Menulis Plugin IntelliJ IDEA Menggunakan Gradle

1. Pengenalan

Sejak beberapa tahun kebelakangan ini, IntelliJ dari JetBrains dengan cepat menjadi IDE teratas untuk pembangun Java. Dalam laporan State of Java kami yang terbaru, IntelliJ adalah IDE pilihan untuk 61% responden, meningkat dari 55% tahun sebelumnya.

Salah satu ciri yang menjadikan IntelliJ begitu menarik bagi pengembang Java adalah kemampuan untuk memperluas dan membuat fungsi baru menggunakan plugin.

Dalam tutorial ini, kita akan melihat penulisan plugin IntelliJ menggunakan cara baru yang disyorkan dengan Gradle untuk menunjukkan beberapa cara untuk memperluas IDE. Artikel ini adalah gabungan semula yang sebelumnya yang menerangkan pembuatan plugin yang sama menggunakan Plugin Devkit.

2. Jenis Plugin Utama

Jenis pemalam yang paling biasa merangkumi fungsi untuk:

  • Sokongan bahasa khusus: keupayaan untuk menulis, mentafsir, dan menyusun kod yang ditulis dalam bahasa yang berbeza
  • Integrasi rangka kerja: sokongan untuk kerangka pihak ketiga seperti Spring
  • Penyatuan alat: penyatuan dengan alat luaran seperti Gradle
  • Alat tambah antara muka pengguna: item menu baru, tetingkap alat, bar kemajuan dan banyak lagi

Pemalam selalunya akan tergolong dalam beberapa kategori . Contohnya, plugin Git yang dihantar dengan IntelliJ berinteraksi dengan git yang boleh dilaksanakan yang dipasang pada sistem. Plugin menyediakan tetingkap alat dan item menu pop timbul, sementara juga mengintegrasikan ke dalam alur kerja pembuatan projek, tetingkap pilihan, dan banyak lagi.

3. Buat Pemalam

Terdapat dua cara yang disokong untuk membuat pemalam. Kami akan menggunakan cara yang disyorkan untuk projek baru dengan Gradle dan bukannya menggunakan Plugin Devkit mereka.

Membuat plugin berasaskan Gradle dilakukan dengan menggunakan menu New> Project .

Perhatikan bahawa kita mesti menyertakan Java dan IntelliJ Platform Plugin untuk memastikan kelas plugin yang diperlukan tersedia di classpath.

Pada penulisan ini, kami hanya dapat menggunakan JDK 8 untuk menulis pemalam IntelliJ .

4. Contoh Pemalam

Kami akan membuat plugin yang menyediakan akses cepat ke laman web Stack Overflow yang popular dari pelbagai kawasan di IDE. Ia merangkumi:

  • item menu Alat untuk melayari halaman Tanya Soalan
  • item menu pop timbul di kedua editor teks dan output konsol untuk mencari Stack Overflow untuk teks yang diserlahkan

4.1. Membuat Tindakan

Tindakan adalah cara yang paling biasa untuk mengakses pemalam . Tindakan dipicu oleh peristiwa di IDE, seperti mengklik item menu atau butang bar alat.

Langkah pertama dalam membuat tindakan adalah membuat kelas Java yang memperluas AnAction . Untuk plugin Stack Overflow kami, kami akan membuat dua tindakan.

Tindakan pertama membuka halaman Tanya Soalan di tetingkap penyemak imbas baru:

public class AskQuestionAction extends AnAction { @Override public void actionPerformed(AnActionEvent e) { BrowserUtil.browse("//stackoverflow.com/questions/ask"); } }

Kami menggunakan kelas BrowserUtil bawaan untuk menangani semua nuansa membuka laman web pada sistem operasi dan penyemak imbas yang berbeza.

Kami memerlukan dua parameter untuk melakukan carian di StackOverflow: tag bahasa dan teks untuk dicari.

Untuk mendapatkan tag bahasa, kami akan menggunakan Program Struktur Interface (PSI). API ini menguraikan semua fail dalam projek dan menyediakan cara terprogram untuk memeriksanya.

Dalam kes ini, kami menggunakan PSI untuk menentukan bahasa pengaturcaraan fail:

Optional psiFile = Optional.ofNullable(e.getData(LangDataKeys.PSI_FILE)); String languageTag = psiFile.map(PsiFile::getLanguage) .map(Language::getDisplayName) .map(String::toLowerCase) .map(lang -> "[" + lang + "]") .orElse("");

Untuk mendapatkan teks yang dicari, kami akan menggunakan Editor API untuk mengambil teks yang disorot di skrin:

Editor editor = e.getRequiredData(CommonDataKeys.EDITOR); CaretModel caretModel = editor.getCaretModel(); String selectedText = caretModel.getCurrentCaret().getSelectedText();

Walaupun tindakan ini sama untuk tetingkap editor dan konsol, mengakses teks yang dipilih berfungsi dengan cara yang sama.

Sekarang, kita boleh menyatukan ini dalam satu deklarasi actionPerformed :

@Override public void actionPerformed(@NotNull AnActionEvent e) { Optional psiFile = Optional.ofNullable(e.getData(LangDataKeys.PSI_FILE)); String languageTag = psiFile.map(PsiFile::getLanguage) .map(Language::getDisplayName) .map(String::toLowerCase) .map(lang -> "[" + lang + "]") .orElse(""); Editor editor = e.getRequiredData(CommonDataKeys.EDITOR); CaretModel caretModel = editor.getCaretModel(); String selectedText = caretModel.getCurrentCaret().getSelectedText(); BrowserUtil.browse("//stackoverflow.com/search?q=" + languageTag + selectedText); }

Tindakan ini juga mengatasi kaedah kedua bernama kemas kini , yang membolehkan kita mengaktifkan atau menonaktifkan tindakan dalam keadaan yang berbeza. Dalam kes ini, kami mematikan tindakan carian jika tidak ada teks yang dipilih:

Editor editor = e.getRequiredData(CommonDataKeys.EDITOR); CaretModel caretModel = editor.getCaretModel(); e.getPresentation().setEnabledAndVisible(caretModel.getCurrentCaret().hasSelection());

4.2. Mendaftar Tindakan

Setelah tindakan kami ditulis, kami perlu mendaftarkannya dengan IDE . Terdapat dua cara untuk melakukan ini.

Cara pertama adalah menggunakan fail plugin.xml , yang dibuat untuk kita semasa kita memulakan projek baru.

Secara lalai, fail tersebut akan kosong elemen, di mana kita akan menambahkan tindakan kita:

Menggunakan fail XML untuk mendaftarkan tindakan akan memastikan mereka mendaftar semasa permulaan IDE, yang biasanya lebih disukai.

Cara kedua untuk mendaftarkan tindakan adalah menggunakan kelas ActionManager secara program :

ActionManager.getInstance().registerAction("StackOverflow.SearchAction", new SearchAction());

This has the advantage of letting us dynamically register actions. For example, if we write a plugin to integrate with a remote API, we might want to register a different set of actions based on the version of the API that we call.

The disadvantage of this approach is that actions do not register at startup. We have to create an instance of ApplicationComponent to manage actions, which requires more coding and XML configuration.

5. Testing the Plugin

As with any program, writing an IntelliJ plugin requires testing. For a small plugin like the one we've written, it's sufficient to ensure the plugin compiles and that the actions we created work as expected when we click them.

We can manually test (and debug) our plugin by opening the Gradle tool window and executing the runIde task:

This will launch a new instance of IntelliJ with our plugin activated. Doing so allows us to click the different menu items we created and ensure the proper Stack Overflow pages open up.

If we wish to do more traditional unit testing, IntelliJ provides a headless environment to run unit tests. We can write tests using any test framework we want, and the tests run using real, unmocked components from the IDE.

6. Deploying the Plugin

The Gradle Plugin provides a simple way to package plugins so we can install and distribute them. Simply open the Gradle tool window and execute the buildPlugin task. This will generate a ZIP file inside the build/distributions directory.

The generated ZIP file contains the code and configuration files needed to load into IntelliJ. We can install it locally, or publish it to a plugin repository for use by others.

The screenshot below shows one of the new Stack Overflow menu items in action:

7. Conclusion

In this article, we developed a simple plugin that highlights how we can enhance the IntelliJ IDE.

While we primarily work with actions, the IntelliJ plugin SDK offers several ways to add new functionality to the IDE. For further reading, check out their official getting started guide.

Seperti biasa, kod lengkap untuk plugin sampel kami boleh didapati di GitHub.