Skrivning af IntelliJ IDEA-plugins ved hjælp af Gradle
1. Introduktion
I løbet af de sidste par år er IntelliJ fra JetBrains hurtigt blevet den bedste IDE for Java-udviklere. I vores seneste State of Java-rapport var IntelliJ den valgte IDE for 61% af respondenterne, op fra 55% året før.
En funktion, der gør IntelliJ så tiltalende for Java-udviklere, er evnen til at udvide og oprette ny funktionalitet ved hjælp af plugins.
I denne vejledning ser vi på at skrive et IntelliJ-plugin ved hjælp af den nye anbefalede måde med Gradle for at demonstrere et par måder, vi kan udvide IDE på. Denne artikel er en genblanding af en tidligere, der beskriver oprettelsen af det samme plugin ved hjælp af Plugin Devkit.
2. Hovedtyper af plugins
De mest almindelige typer plugins inkluderer funktionalitet til:
- Support til brugerdefineret sprog: evnen til at skrive, fortolke og kompilere kode skrevet på forskellige sprog
- Integration af rammer: support til tredjepartsrammer som Spring
- Værktøjsintegration: integration med eksterne værktøjer som Gradle
- Tilføjelser til brugergrænseflade: nye menupunkter, værktøjsvinduer, statuslinjer og meget mere
Plugins falder ofte i flere kategorier. For eksempel interagerer Git-pluginet, der leveres med IntelliJ, med git eksekverbar installeret på systemet. Pluginet giver sit værktøjsvindue og pop op-menupunkter, mens det også integreres i projektoprettelsesarbejdsprocessen, præferencevinduet og mere.
3. Opret et plugin
Der er to understøttede måder at oprette plugins på. Vi bruger den anbefalede måde til nye projekter med Gradle i stedet for at bruge deres Plugin Devkit.
Oprettelse af et Gradle-baseret plugin sker ved hjælp af Nyt> Projekt menu.
Bemærk, at vi skal inkludere Java og IntelliJ Platform Plugin for at sikre, at de krævede plugin-klasser er tilgængelige på klassestien.
I skrivende stund vi kan kun bruge JDK 8 til at skrive IntelliJ-plugins.
4. Eksempel på plugin
Vi opretter et plugin, der giver hurtig adgang til det populære Stack Overflow-websted fra flere områder i IDE. Det inkluderer:
- et værktøjsmenupunkt for at besøge siden Stil et spørgsmål
- et popup-menupunkt i både teksteditor og konsoloutput for at søge i Stack Overflow efter fremhævet tekst
4.1. Oprettelse af handlinger
Handlinger er den mest almindelige måde at få adgang til et plugin på. Handlinger udløses af begivenheder i IDE, såsom at klikke på et menupunkt eller en knap til værktøjslinjen.
Det første trin i oprettelse af en handling er at oprette en Java-klasse, der udvides En handling. For vores Stack Overflow-plugin opretter vi to handlinger.
Den første handling åbner siden Stil et spørgsmål i et nyt browservindue:
offentlig klasse AskQuestionAction udvider AnAction {@Override public void actionPerformed (AnActionEvent e) {BrowserUtil.browse ("// stackoverflow.com/questions/ask"); }}
Vi bruger den indbyggede BrowserUtil klasse til at håndtere alle nuancerne ved at åbne en webside på forskellige operativsystemer og browsere.
Vi har brug for to parametre for at udføre en søgning på StackOverflow: sprogkoden og teksten, der skal søges efter.
For at få sprogmærket bruger vi PSI (Program Structure Interface). Denne API analyserer alle filerne i et projekt og giver en programmatisk måde at inspicere dem på.
I dette tilfælde bruger vi PSI til at bestemme programmeringssproget for en fil:
Valgfri psiFile = Optional.ofNullable (e.getData (LangDataKeys.PSI_FILE)); String languageTag = psiFile.map (PsiFile :: getLanguage) .map (Language :: getDisplayName) .map (String :: toLowerCase) .map (lang -> "[" + lang + "]") .orElse ("") ;
For at få teksten til at søge efter bruger vi Redaktør API til at hente fremhævet tekst på skærmen:
Editor editor = e.getRequiredData (CommonDataKeys.EDITOR); CaretModel caretModel = editor.getCaretModel (); Streng valgtText = caretModel.getCurrentCaret (). GetSelectedText ();
Selvom denne handling er den samme for både editor- og konsolvinduer, fungerer adgang til den valgte tekst på samme måde.
Nu kan vi sætte det hele sammen i en handling udført erklæring:
@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 (); Streng valgtText = caretModel.getCurrentCaret (). GetSelectedText (); BrowserUtil.browse ("// stackoverflow.com/search?q=" + sprogTag + valgt tekst); }
Denne handling tilsidesætter også en anden navngivet metode opdatering, som giver os mulighed for at aktivere eller deaktivere handlingen under forskellige forhold. I dette tilfælde deaktiverer vi søgefunktionen, hvis der ikke er nogen valgt tekst:
Editor editor = e.getRequiredData (CommonDataKeys.EDITOR); CaretModel caretModel = editor.getCaretModel (); e.getPresentation (). setEnabledAndVisible (caretModel.getCurrentCaret (). hasSelection ());
4.2. Registrering af handlinger
Når vi har skrevet vores handlinger, vi er nødt til at registrere dem med IDE. Der er to måder at gøre dette på.
Den første måde er at bruge plugin.xml fil, som oprettes for os, når vi starter et nyt projekt.
Som standard har filen en tom element, hvor vi tilføjer vores handlinger:
Brug af XML-filen til at registrere handlinger vil sikre, at de registreres under IDE-opstart, hvilket normalt er at foretrække.
Den anden måde at registrere handlinger på er programmatisk at bruge ActionManager klasse:
ActionManager.getInstance (). RegisterAction ("StackOverflow.SearchAction", ny SearchAction ());
Dette har fordelen ved at lade os dynamisk registrere handlinger. For eksempel, hvis vi skriver et plugin, der skal integreres med en ekstern API, vil vi måske registrere et andet sæt handlinger baseret på den version af API'en, som vi kalder.
Ulempen ved denne tilgang er, at handlinger ikke registreres ved opstart. Vi er nødt til at oprette en forekomst af ApplicationComponent til at styre handlinger, hvilket kræver mere kodning og XML-konfiguration.
5. Test af pluginet
Som med ethvert program kræver skrivning af et IntelliJ-plugin test. For et lille plugin som det, vi har skrevet, er det tilstrækkeligt at sikre, at pluginet kompileres, og at de handlinger, vi oprettede, fungerer som forventet, når vi klikker på dem.
Vi kan manuelt teste (og fejle) vores plugin ved at åbne Gradle-værktøjsvinduet og udføre runIde opgave:
Dette starter en ny forekomst af IntelliJ med vores plugin aktiveret. Dette gør det muligt for os at klikke på de forskellige menupunkter, vi oprettede, og sikre, at de rette Stack Overflow-sider åbnes.
Hvis vi ønsker at udføre mere traditionel enhedstest, giver IntelliJ et hovedløst miljø til at køre enhedstest. Vi kan skrive tests ved hjælp af de testrammer, vi ønsker, og testene kører ved hjælp af ægte, ikke-mockede komponenter fra IDE.
6. Implementering af pluginet
Gradle Plugin giver en enkel måde at pakke plugins på, så vi kan installere og distribuere dem. Du skal blot åbne Gradle-værktøjsvinduet og udføre buildPlugin opgave. Dette genererer en ZIP-fil inde i build / distributioner vejviser.
Den genererede ZIP-fil indeholder de kode- og konfigurationsfiler, der er nødvendige for at indlæse i IntelliJ. Vi kan installere det lokalt eller offentliggøre det til et plugin-lager til brug for andre.
Skærmbilledet nedenfor viser et af de nye Stack Overflow-menupunkter i aktion:
7. Konklusion
I denne artikel udviklede vi et simpelt plugin, der fremhæver, hvordan vi kan forbedre IntelliJ IDE.
Mens vi primært arbejder med handlinger, tilbyder IntelliJ plugin SDK flere måder at tilføje ny funktionalitet til IDE. For yderligere læsning, se deres officielle startvejledning.
Som altid kan den fulde kode til vores eksempel-plugin findes på GitHub.