Schreiben von IntelliJ IDEA Plugins mit Gradle

1. Einleitung

In den letzten Jahren hat sich IntelliJ von JetBrains schnell zur Top-IDE für Java-Entwickler entwickelt. In unserem jüngsten State of Java-Bericht war IntelliJ für 61% der Befragten die IDE der Wahl, gegenüber 55% im Vorjahr.

Eine Funktion, die IntelliJ für Java-Entwickler so attraktiv macht, ist die Möglichkeit, mithilfe von Plugins neue Funktionen zu erweitern und zu erstellen.

In diesem Tutorial werden wir uns mit dem Schreiben eines IntelliJ-Plugins auf die neue empfohlene Weise mit Gradle befassen, um einige Möglichkeiten zu demonstrieren, wie wir die IDE erweitern können. Dieser Artikel ist eine Neuauflage eines vorherigen Artikels, in dem die Erstellung desselben Plugins mit dem Plugin Devkit beschrieben wird.

2. Haupttypen von Plugins

Die häufigsten Arten von Plugins umfassen Funktionen für:

  • Benutzerdefinierte Sprachunterstützung: Die Fähigkeit, in verschiedenen Sprachen geschriebenen Code zu schreiben, zu interpretieren und zu kompilieren
  • Framework-Integration: Unterstützung für Frameworks von Drittanbietern wie Spring
  • Werkzeugintegration: Integration mit externen Werkzeugen wie Gradle
  • Add-Ons für die Benutzeroberfläche: neue Menüelemente, Werkzeugfenster, Fortschrittsbalken und mehr

Plugins fallen häufig in mehrere Kategorien . Das mit IntelliJ gelieferte Git-Plugin interagiert beispielsweise mit der auf dem System installierten ausführbaren Git- Datei. Das Plugin bietet das Toolfenster und Popup-Menüelemente sowie die Integration in den Workflow für die Projekterstellung, das Einstellungsfenster und vieles mehr.

3. Erstellen Sie ein Plugin

Es gibt zwei unterstützte Möglichkeiten zum Erstellen von Plugins. Wir werden die empfohlene Methode für neue Projekte mit Gradle verwenden, anstatt das Plugin Devkit zu verwenden.

Das Erstellen eines Gradle-basierten Plugins erfolgt über das Menü Neu> Projekt .

Beachten Sie, dass wir Java und das IntelliJ Platform Plugin einschließen müssen, um sicherzustellen, dass die erforderlichen Plugin-Klassen im Klassenpfad verfügbar sind.

Zum jetzigen Zeitpunkt können wir JDK 8 nur zum Schreiben von IntelliJ-Plugins verwenden .

4. Beispiel Plugin

Wir werden ein Plugin erstellen, das aus mehreren Bereichen der IDE einen schnellen Zugriff auf die beliebte Stack Overflow-Website bietet. Es wird enthalten:

  • einen Menüpunkt Extras, um die Seite Frage stellen aufzurufen
  • Ein Popup-Menüelement sowohl im Texteditor als auch in der Konsolenausgabe, um den Stapelüberlauf nach hervorgehobenem Text zu durchsuchen

4.1. Aktionen erstellen

Aktionen sind die häufigste Methode, um auf ein Plugin zuzugreifen . Aktionen werden durch Ereignisse in der IDE ausgelöst, z. B. durch Klicken auf einen Menüpunkt oder eine Symbolleistenschaltfläche.

Der erste Schritt beim Erstellen einer Aktion besteht darin, eine Java-Klasse zu erstellen, die AnAction erweitert . Für unser Stack Overflow-Plugin erstellen wir zwei Aktionen.

Die erste Aktion öffnet die Seite Frage stellen in einem neuen Browserfenster:

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

Wir verwenden die integrierte BrowserUtil- Klasse, um alle Nuancen des Öffnens einer Webseite unter verschiedenen Betriebssystemen und Browsern zu behandeln.

Wir benötigen zwei Parameter, um eine Suche in StackOverflow durchzuführen: das Sprach-Tag und den zu suchenden Text.

Um das Sprach-Tag zu erhalten, verwenden wir das Program Structure Interface (PSI). Diese API analysiert alle Dateien in einem Projekt und bietet eine programmgesteuerte Möglichkeit, sie zu überprüfen.

In diesem Fall verwenden wir das PSI, um die Programmiersprache einer Datei zu bestimmen:

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("");

Um den zu suchenden Text zu erhalten, verwenden wir die Editor- API, um hervorgehobenen Text auf dem Bildschirm abzurufen:

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

Obwohl diese Aktion für Editor- und Konsolenfenster gleich ist, funktioniert der Zugriff auf den ausgewählten Text auf dieselbe Weise.

Jetzt können wir dies alles in einer actionPerformed- Deklaration zusammenfassen:

@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); }

Diese Aktion überschreibt auch eine zweite Methode namens update , mit der wir die Aktion unter verschiedenen Bedingungen aktivieren oder deaktivieren können. In diesem Fall deaktivieren wir die Suchaktion, wenn kein Text ausgewählt ist:

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

4.2. Aktionen registrieren

Sobald wir unsere Aktionen geschrieben haben, müssen wir sie bei der IDE registrieren . Es gibt zwei Möglichkeiten, dies zu tun.

Der erste Weg ist die Verwendung der Datei plugin.xml , die für uns erstellt wird, wenn wir ein neues Projekt starten.

Standardmäßig ist die Datei leer Element, wo wir unsere Aktionen hinzufügen werden:

Durch die Verwendung der XML-Datei zum Registrieren von Aktionen wird sichergestellt, dass diese während des IDE-Starts registriert werden. Dies ist normalerweise vorzuziehen.

Die zweite Möglichkeit zum Registrieren von Aktionen ist die programmgesteuerte Verwendung der ActionManager- Klasse:

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.

Wie immer finden Sie den vollständigen Code für unser Beispiel-Plugin auf GitHub.