Menulis Plugin IntelliJ IDEA Menggunakan Gradle

1. Perkenalan

Selama beberapa tahun terakhir, IntelliJ dari JetBrains dengan cepat menjadi IDE teratas untuk pengembang Java. Dalam laporan State of Java terbaru kami, IntelliJ adalah IDE pilihan bagi 61% responden, naik dari 55% tahun sebelumnya.

Salah satu fitur yang membuat IntelliJ begitu menarik bagi pengembang Java adalah kemampuannya untuk memperluas dan membuat fungsionalitas baru menggunakan plugin.

Dalam tutorial ini, kita akan melihat penulisan plugin IntelliJ menggunakan cara baru yang direkomendasikan dengan Gradle untuk mendemonstrasikan beberapa cara kita dapat memperluas IDE. Artikel ini adalah campuran ulang dari artikel sebelumnya yang menjelaskan tentang pembuatan plugin yang sama menggunakan Plugin Devkit.

2. Jenis Utama Plugin

Jenis plugin yang paling umum mencakup fungsionalitas untuk:

  • Dukungan bahasa kustom: kemampuan untuk menulis, menafsirkan, dan menyusun kode yang ditulis dalam berbagai bahasa
  • Integrasi kerangka kerja: dukungan untuk kerangka kerja pihak ketiga seperti Spring
  • Integrasi alat: integrasi dengan alat eksternal seperti Gradle
  • Add-on antarmuka pengguna: item menu baru, jendela alat, bilah kemajuan, dan banyak lagi

Plugin sering kali termasuk dalam beberapa kategori . Misalnya, plugin Git yang disertakan dengan IntelliJ berinteraksi dengan git yang dapat dieksekusi yang diinstal pada sistem. Plugin menyediakan jendela alat dan item menu popup, sementara juga mengintegrasikannya ke dalam alur kerja pembuatan proyek, jendela preferensi, dan banyak lagi.

3. Buat Plugin

Ada dua cara yang didukung untuk membuat plugin. Kami akan menggunakan cara yang direkomendasikan untuk proyek baru dengan Gradle daripada menggunakan Plugin Devkit mereka.

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

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

Saat tulisan ini dibuat, kita hanya dapat menggunakan JDK 8 untuk menulis plugin IntelliJ .

4. Contoh Plugin

Kami akan membuat plugin yang menyediakan akses cepat ke situs web Stack Overflow populer dari berbagai area di IDE. Ini akan mencakup:

  • item menu Alat untuk mengunjungi halaman Ajukan Pertanyaan
  • item menu popup di editor teks dan output konsol untuk menelusuri Stack Overflow untuk teks yang disorot

4.1. Membuat Tindakan

Tindakan adalah cara paling umum untuk mengakses plugin . Tindakan dipicu oleh peristiwa di IDE, seperti mengklik item menu atau tombol toolbar.

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 Ajukan Pertanyaan di jendela browser 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 halaman web pada sistem operasi dan browser yang berbeda.

Kami membutuhkan dua parameter untuk melakukan pencarian di StackOverflow: tag bahasa dan teks yang akan dicari.

Untuk mendapatkan tag bahasa, kita akan menggunakan Program Structure Interface (PSI). API ini mem-parsing semua file dalam sebuah proyek dan menyediakan cara terprogram untuk memeriksanya.

Dalam hal ini, kami menggunakan PSI untuk menentukan bahasa pemrograman file:

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 akan dicari, kami akan menggunakan API Editor untuk mengambil teks yang disorot di layar:

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

Meskipun tindakan ini sama untuk jendela editor dan konsol, mengakses teks yang dipilih bekerja dengan cara yang sama.

Sekarang, kita bisa menggabungkan semuanya dalam 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 menggantikan metode kedua bernama update , yang memungkinkan kita mengaktifkan atau menonaktifkan tindakan dalam kondisi berbeda. Dalam kasus ini, kami menonaktifkan tindakan pencarian jika tidak ada teks yang dipilih:

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

4.2. Mendaftarkan Tindakan

Setelah tindakan kami ditulis, kami perlu mendaftarkannya dengan IDE . Ada dua cara untuk melakukannya.

Cara pertama adalah menggunakan file plugin.xml , yang dibuat untuk kita saat kita memulai proyek baru.

Secara default, file akan kosong elemen, di mana kita akan menambahkan tindakan kita:

Menggunakan file XML untuk mendaftarkan tindakan akan memastikan tindakan tersebut mendaftar selama pengaktifan IDE, yang biasanya lebih disukai.

Cara kedua untuk mendaftarkan tindakan secara terprogram menggunakan kelas ActionManager :

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, kode lengkap untuk plugin sampel kami dapat ditemukan di GitHub.