Blog

Erstellen von IntelliJ-Plugins von der Kommandozeile aus

Arjan Molenaar

Aktualisiert Oktober 22, 2025
6 Minuten

Schon seit einigen Jahren ist IntelliJ IDEA die IDE meiner Wahl. Vor kurzem bin ich in die Welt der Plugin-Entwicklung für IntelliJ IDEA eingetaucht und war unglücklich überrascht. Die Plugin-Entwicklung hängt ganz von den IDE-Funktionen ab. Es sah schwer aus, ein Build-Skript zu erstellen, um die eigentliche Plugin-Kompilierung und -Paketierung von einem Build-Skript aus durchzuführen. Dafür haben die Leute von JetBrains einfach nicht gesorgt. Wenn Sie nicht TeamCity als CI-Tool verwenden, haben Sie Pech gehabt.

Für mich macht es keinen Sinn, Code zu schreiben, wenn:

  1. es kann nicht von der Kommandozeile aus kompiliert und verpackt werden
  2. der Code kann nicht in einer CI-Umgebung kompiliert und getestet werden
  3. IDE-Konfigurationen können nicht aus dem Build-Skript generiert werden

Google hat mir nicht viel geholfen. Tomasz Dziurko hat mich auf den richtigen Weg gebracht. Um ein Plugin zu erstellen und zu testen, muss Folgendes vorhanden sein:

  1. Zuallererst benötigen Sie IntelliJ IDEA. Das ist ganz offensichtlich. Die Plugin DevKit-Plugins müssen installiert werden. Wenn Sie ein Sprach-Plugin erstellen möchten, sollten Sie vielleicht auch Grammar-Kit installieren.
  2. Es muss ein IDEA SDK registriert werden. Das SDK kann auf Ihre IntelliJ-Installation verweisen.

Die Dateien der Plugin-Module unterscheiden sich nur geringfügig von Ihrem durchschnittlichen Projekt. Update: Ich bin auf einige Probleme bei der Generierung von Formularen und Sprachcode gestoßen und habe am Ende dieses Beitrags einige Updates hinzugefügt.

Kompilieren und Testen des Plugins

Nun zum Build-Skript. Mein Build-Tool der Wahl ist Gradle. Mein Plugin-Code hält sich an die Standard-Gradle-Projektstruktur.Als Erstes müssen Sie sich die IntelliJ IDEA-Bibliotheken auf automatisierte Weise beschaffen. Da die IDEA-Bibliotheken nicht über die Maven-Repos verfügbar sind, ist ein Download der IntelliJ IDEA Community Edition wahrscheinlich die beste Option, um an die Bibliotheken zu gelangen. Der Plan sieht folgendermaßen aus: Laden Sie die Linux-Version von IntelliJ IDEA herunter und entpacken Sie sie an einem vordefinierten Ort. Von dort aus können wir auf die Bibliotheken verweisen und anschließend das Plugin kompilieren und testen. Die Bibliotheken sind in Java geschrieben und daher plattformunabhängig. Ich habe mich für die Linux-Version entschieden, da sie eine schöne, einfache Dateistruktur hat. Der folgende Codeschnipsel ist dafür geeignet: [sourcecode lang="groovy"] Plugin anwenden: 'java' // Wählen Sie die Linux-Version. Da es sich um eine tar.gz-Datei handelt, können wir sie einfach entpacken. def IDEA_SDK_URL = ' https://download.jetbrains.com/idea/ideaIC-14.0.4.tar.gz' def IDEA_SDK_NAME = 'IntelliJ IDEA Community Edition IC-139.1603.1' Konfigurationen { ideaSdk bundle // Abhängigkeiten, die mit dem Plugin gebündelt werden } Abhängigkeiten { ideaSdk fileTree(dir: 'lib/sdk/', include: [' /lib/.jar']) Konfigurationen kompilieren.ideaSdk compile configurations.bundle testCompile 'junit:junit:4.12' testCompile 'org.mockito:mockito-core:1.10.19' } // IntelliJ IDEA kann immer noch auf einer Java 6 JRE laufen, also müssen wir das berücksichtigen. sourceCompatibility = 1.6 targetCompatibility = 1.6 task downloadIdeaSdk(type: Download) { sourceUrl = IDEA_SDK_URL Ziel = Datei('lib/idea-sdk.tar.gz') } task extractIdeaSdk(type: Copy, dependsOn: [downloadIdeaSdk]) { def zipFile = file('lib/idea-sdk.tar.gz') def outputDir = file("lib/sdk") from tarTree(resources.gzip(zipFile)) in outputDir } compileJava.dependsOn extractIdeaSdk class Download extends DefaultTask { @Eingabe String sourceUrl @Ausgabedatei Ziel der Datei @AufgabeAktion void download() { if (!target.parentFile.exists()) { target.parentFile.mkdirs() } ant.get(src: sourceUrl, dest: target, skipexisting: 'true') } } [/sourcecode] Wenn die parallele Testausführung bei Ihrem Plugin nicht funktioniert, sollten Sie sie wie folgt deaktivieren: [sourcecode lang="groovy"] test { // Vermeiden Sie parallele Ausführung, da die IntelliJ-Boilerplate dem nicht gewachsen ist maxParallelForks = 1 } [/sourcecode]

Das Plugin wird geliefert

Natürlich sollte der gesamte Build-Prozess automatisiert werden. Das gilt auch für die Verpackung des Plugins. Ein Plugin ist einfach eine Zip-Datei mit allen Bibliotheken in einem lib-Ordner. [sourcecode lang="groovy"] task dist(type: Zip, dependsOn: [jar, test]) { from configurations.bundle from jar.archivePath rename { f -> "lib/${f}" } into project.name baseName project.name } build.dependsOn dist [/sourcecode]

Umgang mit IntelliJ-Projektdateien

Außerdem müssen wir IntelliJ IDEA Projekt- und Moduldateien erzeugen, damit das Plugin in der IDE verwendet werden kann. Der IDE mitzuteilen, dass es sich um ein Plugin handelt, eröffnet einige nette Funktionen, vor allem die Möglichkeit, das Plugin von der IDE aus auszuführen. Der Blogbeitrag von Anton Arhipov hat mich auf die richtige Spur gebracht. Die Gradle Idee Plugin hilft Ihnen bei der Erstellung dieser Dateien. Für Ihr durchschnittliches Projekt funktioniert das sofort, aber bei Plugins erwartet IntelliJ einige Dinge anders. Die Projektdateien sollten erwähnen, dass es sich um ein Plugin-Projekt handelt, und die Moduldatei sollte auf die für jedes Plugin erforderliche Datei plugin.xml verweisen. Außerdem dürfen die SDK-Bibliotheken nicht in die Moduldatei aufgenommen werden; daher habe ich sie aus der Konfiguration ausgeschlossen. Der folgende Codeschnipsel sorgt für Abhilfe: [sourcecode lang="groovy"]plugin anwenden: 'idea' idea { project { languageLevel = '1.6' jdkName = IDEA_SDK_NAME ipr { withXml { it.node.find { node -> node.@name == 'ProjectRootManager' }.'@project-jdk-type' = 'IDEA JDK' logger.warn "=" 71 logger.warn " Konfiguriertes IDEA JDK '${jdkName}'." logger.warn " Stellen Sie sicher, dass Sie IntelliJ konfiguriert haben, bevor Sie das Projekt öffnen!" logger.warn "=" 71 } } } module { scopes.COMPILE.minus = [ configurations.ideaSdk ] iml { beforeMerged { module -> module.dependencies.clear() } withXml { it.node.@type = 'PLUGIN_MODULE' // <component name="DevKit.ModuleBuildProperties" url="file://$MODULE_DIR$/src/main/resources/META-INF/plugin.xml" /> def cmp = it.node.appendNode('component') cmp.@name = 'DevKit.ModuleBuildProperties' cmp.@url = 'file://$MODULE_DIR$/src/main/resources/META-INF/plugin.xml' } } } } [/sourcecode]

Machen Sie sich an die Arbeit!

Wenn Sie die oben genannten Codeschnipsel kombinieren, erhalten Sie ein Build-Skript, das in jeder Umgebung ausgeführt werden kann. Werfen Sie einen Blick auf mein idea-clock Plugin für ein funktionierendes Beispiel.

Update 1: Formulare

Damit ein IntelliJ-Plugin Formulare verwenden kann, muss anscheinend etwas zusätzliche Arbeit geleistet werden. Dieser Unterschied wird erst deutlich, wenn Sie das von IntelliJ erstellte Plugin mit dem von Gradle erstellten vergleichen:

  1. Fügen Sie eine Reihe von Hilfsklassen ein
  2. Instrumentieren Sie die Formularklassen

Es war einfach, weitere Dateien in das Plugin aufzunehmen. Sehen Sie sich diesen Commit an, um zu sehen, was noch hinzugefügt werden muss. Diese Klassen werden als "Helfer" für das Formular nach der Instrumentierung verwendet. Für die Instrumentierung ist eine Ant-Aufgabe verfügbar. Dieser Task kann in Gradle geladen und als letzter Schritt der Kompilierung verwendet werden. Nachdem ich wusste, wonach ich suchen musste, half mir dieser Beitrag weiter: Wie man den Entwicklungslebenszyklus von IntelliJ-Plugins mit Maven verwaltet, zusammen mit einem Build-Skript.

Update 2: Generierung von Sprachcode

Die Leute von Jetbrains empfehlen die Verwendung von JFlex, um den Lexer für Ihre eigene Sprache zu erstellen. Um dies von Gradle aus nutzen zu können, muss eine eigene Version von JFlex verwendet werden. Dies wurde in einer frühen Version des FitNesse-Plugins verwendet.

Update 3: Verwendung eines Gradle-Plugins

Darren Reid wies mich auf ein von Jetbrains entwickeltes Gradle-Plugin hin, das im Grunde dasselbe tut wie das, was ich oben beschrieben habe. Ich habe das Plugin ausprobiert und es funktioniert wirklich gut. Das Plugin ist einfach zu konfigurieren: [sourcecode lang="groovy"] plugins { id "org.jetbrains.intellij" version "0.0.26" } apply plugin: 'org.jetbrains.intellij' intellij { version '14.1.4' pluginName 'idea-clock' publish { username jetbrainsUsername ?: "" password jetbrainsPassword ?: "" pluginId '7754' } } [/sourcecode] Ihr jetbrainsUsername und jetbrainsPassword können in $HOME/.gradle/gradle.properties konfiguriert werden . Die Unterschiede zu meinem Ansatz sind:

  • Das Projekt wird wie ein normales IntelliJ Java-Projekt geladen. Es handelt sich nicht um ein "spezielles" Plugin-Projekt. Das bedeutet, dass das Plugin nicht über das Menü Run Configuration ausgeführt werden kann. Stattdessen kann es über einen Gradle-Befehl(runIdea) gestartet werden.
  • Ich war nicht in der Lage, IntelliJ im Debug-Modus auszuführen.

Verfasst von

Arjan Molenaar

Contact

Let’s discuss how we can support your journey.