Schreiben von IntelliJ IDEA Plugins

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 55% der Befragten die IDE der Wahl, gegenüber 48% 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 befassen, um einige Möglichkeiten zur Erweiterung der IDE zu demonstrieren.

Beachten Sie, dass sich dieser Artikel zwar auf IntelliJ-Plugins konzentriert, alle JetBrains-IDEs jedoch gemeinsamen Code verwenden. Daher können viele der hier verwendeten Techniken auf andere JetBrain-IDEs wie PyCharm, RubyMine und mehr angewendet werden.

2. Plugin-Funktionalität

Die Plugin-Funktionalität für IntelliJ fällt normalerweise in eine von vier Kategorien:

  • Benutzerdefinierte Sprachen : Die Fähigkeit, in verschiedenen Sprachen geschriebenen Code zu schreiben, zu interpretieren und zu kompilieren
  • Frameworks : Unterstützung für Frameworks von Drittanbietern wie Spring
  • Tools : Integration mit externen Tools wie Gradle
  • Add-Ons für die Benutzeroberfläche : neue Menüelemente, Werkzeugfenster und Schaltflächen 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 eines Plugins

Der einfachste Weg, um mit IntelliJ-Plugins zu beginnen, ist die Verwendung des Plugins DevKit. Sie können über das Menü Neu > Projekt darauf zugreifen:

Beachten Sie, dass wir ein JetBrains-JDK verwenden müssen, um sicherzustellen, dass die erforderlichen Plugin-Klassen im Klassenpfad verfügbar sind. IntelliJ sollte standardmäßig mit einem geeigneten JDK geliefert werden. Andernfalls können wir eines von hier herunterladen.

Zum jetzigen Zeitpunkt können wir Java 8 nur zum Schreiben von IntelliJ-Plugins verwenden . Dies liegt daran, dass JetBrains derzeit kein offizielles JDK für Java 9 oder höher bereitstellt.

4. Beispiel Plugin

Um das Schreiben eines IntelliJ-Plugins zu demonstrieren, erstellen wir ein Plugin, das aus mehreren Bereichen der IDE einen schnellen Zugriff auf die beliebte Stack Overflow-Website bietet. Wir werden hinzufügen:

  • Ein Menüpunkt Extras zum Aufrufen der Seite Frage stellen
  • 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 Kernkomponente zum Schreiben von IntelliJ-Plugins . 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 2 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, da sie alle Nuancen des Öffnens einer Webseite unter verschiedenen Betriebssystemen und Browsern behandelt.

Die zweite Aktion öffnet die Suchseite "Stapelüberlauf" und übergibt den Suchtext als Abfragezeichenfolge. Dieses Mal werden wir zwei Methoden implementieren.

Die erste Methode, die wir implementieren, ist genau wie unsere erste Aktion und behandelt das Öffnen eines Webbrowsers.

Zunächst müssen wir jedoch zwei Werte für StackOverflow erfassen. Eines ist das Sprach-Tag und das andere ist der zu suchende Text.

Um das Sprach-Tag zu erhalten, verwenden wir die Programmstrukturschnittstelle. 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:

PsiFile file = e.getData(CommonDataKeys.PSI_FILE); Language lang = e.getData(CommonDataKeys.PSI_FILE).getLanguage(); String languageTag = "+[" + lang.getDisplayName().toLowerCase() + "]";

Beachten Sie, dass das PSI auch sprachspezifische Details zu einer Datei bereitstellt. Zum Beispiel könnten wir das PSI verwenden, um alle öffentlichen Methoden in einer Java-Klasse zu finden.

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

final 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(AnActionEvent e) { PsiFile file = e.getData(CommonDataKeys.PSI_FILE); Language lang = e.getData(CommonDataKeys.PSI_FILE).getLanguage(); String languageTag = "+[" + lang.getDisplayName().toLowerCase() + "]"; Editor editor = e.getRequiredData(CommonDataKeys.EDITOR); CaretModel caretModel = editor.getCaretModel(); String selectedText = caretModel.getCurrentCaret().getSelectedText() String query = selectedText.replace(' ', '+') + languageTag; BrowserUtil.browse("//stackoverflow.com/search?q=" + query); } 

Diese Aktion überschreibt auch eine zweite Methode namens update . Dies ermöglicht es uns, die Aktion unter verschiedenen Bedingungen zu aktivieren oder zu deaktivieren.

In diesem Fall deaktivieren wir die Suchaktion, wenn kein Text ausgewählt ist:

@Override public void update(AnActionEvent e) { 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.

The first way is using the plugin.xml file, which is created for us when we start a new project.

By default the file will have an empty element, which is where we will add our actions:

Using the XML file to register actions will ensure they register during IDE startup, which is usually preferable.

The second way to register actions is programmatically using the ActionManager class:

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 to 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 have 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 using a Plugin run configuration:

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

If you 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 plugin DevKit provides a simple way to package plugins so we can install and distribute them. Simply right-click the plugin project and select “Prepare plugin module for Deployment”. This will generate a JAR file inside the project directory.

The generated JAR file contains the code and configuration files needed to load into IntelliJ. You 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 diesem Artikel haben wir ein einfaches Plugin entwickelt, das nur einige Beispiele für die Verbesserung der IntelliJ IDE zeigt.

Während wir hauptsächlich mit Aktionen gearbeitet haben, bietet das IntelliJ-Plugin SDK verschiedene Möglichkeiten, um der IDE neue Funktionen hinzuzufügen. Weitere Informationen finden Sie im offiziellen Leitfaden für die ersten Schritte.

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