de Oliver Nybroe

Cum să creați un plugin IntelliJ – să construim un simplu dicționar

Cum sa creati un plugin IntelliJ haideti sa construim
Fotografie de Echipaj pe Unsplash

Majoritatea dintre noi dezvoltatorii folosim platforme IntelliJ, fie IDEA, PHPStorm, WebStorm, Android Studio, PyCharm, iar lista continuă. Cu toate acestea, uneori, când o folosim, constatăm că lipsește o caracteristică, dar nu avem nicio idee despre cum să adăugăm acea caracteristică și, în cele din urmă, să trăim fără ea.

În acest articol voi prezenta cum putem crea un plugin simplu pentru toate IDE-urile IntelliJ, așa că atunci când adăugați un project.dic fișier, îl va adăuga automat ca unul dintre dicționarele dvs. De asemenea, va căuta fișierul în pachete, astfel încât pachetele să poată adăuga cuvinte personalizate în dicționar. A .dic fișier este un dicționar simplu în care fiecare linie este un cuvânt din dicționar.

Proiectul este doar un eșantion care vă va ajuta să vă dezvoltați propriile pluginuri. Dar este de fapt și o caracteristică care mi-a lipsit, deoarece, atunci când dezvolt un pachet personalizat cu propriile mele cuvinte, urăsc că trebuie să le adaug de fiecare dată în dicționarul la nivel de proiect.

Crearea proiectului

Atunci când creăm pluginuri pentru IntelliJ, trebuie să facem acest lucru fie în Java, fie în Kotlin. O voi face în Java, deoarece majoritatea utilizatorilor sunt familiarizați cu asta. Deoarece acesta este un proiect Java, vom folosi IntelliJ IDEA ca IDE.

In conformitate cu ghid de dezvoltare, modalitatea recomandată de a crea un proiect este folosind Gradle. Începem prin a ne deschide preferences și verificați dacă Gradle și Plugin DevKit sunt instalate pluginuri.

Cum sa creati un plugin IntelliJ haideti sa construim

După instalarea pluginurilor și repornirea IDE, mergem la fluxul de proiecte noi și sub Gradle. Aici există acum o opțiune numită IntelliJ Platform Plugin care este cea de care avem nevoie.

1612006450 524 Cum sa creati un plugin IntelliJ haideti sa construim
Fluxul de creare a proiectului pasul 1

Apoi parcurgeți restul fluxului de creare a proiectului în mod normal – în acest proiect aleg următoarea configurație.

1612006450 332 Cum sa creati un plugin IntelliJ haideti sa construim
Fluxul de creare a proiectului pasul 2
1612006451 526 Cum sa creati un plugin IntelliJ haideti sa construim
Fluxul de creare a proiectului pasul 3
1612006451 258 Cum sa creati un plugin IntelliJ haideti sa construim
Fluxul de creare a proiectului pasul 4

Configurare plugin.xml

Acum că avem un proiect, trebuie să ne configurăm plugin.xml fișier și build.gradle. plugin.xml fișier este un fișier folosit de IntelliJ care definește toate informațiile despre plugin. Aceasta include numele, dependențele, ce acțiuni ar trebui să adauge sau dacă ar trebui să extindă ceva în IntelliJ. Practic, acest fișier definește tot ceea ce ar trebui să facă pluginul dvs. și este rădăcina proiectului dvs. În a noastră build.gradle fișier din care putem defini unele dintre valori plugin.xmlși informații cum ar fi versiunea de IntelliJ pe care dorim să ne testăm pluginul atunci când construim cu gradle.

Să începem prin a ne defini plugin.xml fişier. Puteți găsi fișierul în src/main/resources/META-INF/plugin.xml. Vrem ca pluginul nostru să fie disponibil pe toate IDE-urile IntelliJ, așa că le-am setat dependencies la com.intellij.modules.lang. În acest moment, fișierul nostru arată astfel:

<idea-plugin>    <id>dk.lost_world.Dictionary</id>    <name>Dictionary</name>    <vendor email="olivernybroe@gmail.com" url="https://github.com/olivernybroe/intellij-Dictionary">GitHub</vendor>    <depends>com.intellij.modules.lang</depends></idea-plugin>

Cu toate acestea, în acest moment, acest lucru nu are nicio logică și nu înregistrăm nimic pe platforma IntelliJ.

După cum va găsi acest proiect project.dic fișierele din interiorul unui proiect și le înregistrăm ca dicționare în acel proiect, va trebui să înregistrăm o componentă la nivel de proiect. Această componentă va fi apelată când un proiect este deschis și închis. Să creăm o clasă și să implementăm ProjectComponent interfață. Când trecem cu mouse-ul peste numele clasei, ne spune că componenta nu este înregistrată.

1612006451 678 Cum sa creati un plugin IntelliJ haideti sa construim
Sugestii despre clasă

Putem apoi numi acțiunea numită Register Project Component și o va înregistra pentru noi în plugin.xml fişier.

1612006451 174 Cum sa creati un plugin IntelliJ haideti sa construim
Acțiuni asupra clasei

Dacă deschidem plugin.xml ar trebui adăugat următorul cod. Dacă nu a fost adăugat la apelarea acțiunii, atunci adăugați-o manual.

<project-components>    <component>        <implementation-class>dk.lost_world.dictionary.DictionaryProjectComponent</implementation-class>    </component></project-components>

Sistemul de fișiere IntelliJ

Când lucrăm cu fișiere în IntelliJ, folosim un Virtual File System (VFS). VFS ne oferă un API universal pentru a vorbi cu fișiere, fără ca noi să ne gândim dacă sunt de pe FTP, un server HTTP sau doar pe discul local.

Pe măsură ce pluginul nostru caută fișiere numite project.dic va trebui, desigur, să discute cu Virtual File System. Toate fișierele din VFS sunt Fișiere virtuale. Acest lucru poate suna puțin intimidant, dar în realitate este doar un API pentru un sistem de fișiere și pentru un fișier. Modul de gândire la asta este doar că Virtual File System este interfața sistemului dvs. de fișiere, iar fișierele virtuale sunt fișierele dvs.

Setări verificator ortografic

Deoarece IntelliJ are deja sprijin pentru .dic fișierele și verificarea ortografică în general, singurul lucru pe care trebuie să-l facem este să-l înregistrăm pe project.dic fișierele din setările verificatorilor ortografici.

Toate setările pentru verificatorul ortografic sunt salvate într-o clasă numită com.intellij.spellchecker.settings.SpellCheckerSettings. Pentru a obține o instanță, sunați pur și simplu la getInstance (majoritatea claselor IntelliJ au primit un getInstance metoda care folosește IntelliJ’s ServiceManager dedesubt).
Clasa de setări a primit o metodă numită getCustomDictionariesPaths care returnează toate căile către dicționarele instalate de utilizator.

1612006452 932 Cum sa creati un plugin IntelliJ haideti sa construim
API-ul getCustomDictionariesPaths

Când ne uităm la semnătura metodei, vedem și o adnotare numită AvailableSince. Ulterior vom folosi valoarea din această adnotare pentru a specifica versiunea minimă necesară pentru ca pluginul nostru să funcționeze.

Pe măsură ce metoda returnează o listă, putem apela pur și simplu add despre metoda de a adăuga într-o nouă cale către un dicționar.

Rularea pluginului nostru (build.gradle)

După cum știm acum cum să adăugăm un dicționar la verificatorul ortografic, să adăugăm un mic exemplu de cod în DictionaryProjectComponent clasa pentru a face acest lucru.

public class DictionaryProjectComponent implements ProjectComponent {    private Project project;    public DictionaryProjectComponent(Project project) {        this.project = project;    }    @Override    public void projectOpened() {        SpellCheckerSettings            .getInstance(project)            .getCustomDictionariesPaths()            .add("./project.dic");    }}

Acest cod va înregistra un project.dic fișier din rădăcina proiectului nostru ori de câte ori proiectul este deschis.

Pentru a testa micul nostru exemplu, trebuie să îl actualizăm build.gradle fişier. În intellij secțiunea din fișierul gradle adăugăm în ce versiune de IntelliJ dorim să folosim. Acest număr de versiune este cel din AvailableSince adnotare pe SpellCheckerSettings clasă.

plugins {    id 'java'    id 'org.jetbrains.intellij' version '0.4.4'}group 'dk.lost_world'version '1.0-SNAPSHOT'sourceCompatibility = 1.8repositories {    mavenCentral()}dependencies {    testCompile group: 'junit', name: 'junit', version: '4.12'}// See https://github.com/JetBrains/gradle-intellij-plugin/intellij {    pluginName 'Dictionary'    version '181.2784.17'    type 'IC'    downloadSources true}

Rularea runIde comanda de la gradle va porni o instanță a IntelliJ a versiunii specifice. După pornirea IDE-ului de testare pluginul nostru ar fi trebuit să fie rulat. Dacă ne deschidem preferences > Editor > Spelling > Dicîn dicționarele personalizate că calea pe care am specificat-o în exemplul nostru este acum adăugată.

1612006452 297 Cum sa creati un plugin IntelliJ haideti sa construim
Se afișează preferințele dicționarelor de la IntelliJ IDE

Acum suntem capabili să testăm pluginul, așa că acum este timpul să îl construim corect, astfel încât să găsească project.dic fișierele și le înregistrează pentru noi.

În DictionaryProjectComponent::projectOpened metoda, trebuie mai întâi să găsim toate fișierele numite project.dic și înregistrați-le și adăugați, de asemenea, un ascultător de fișiere, atunci când este nou project.dic fișierele sunt adăugate, sunt înregistrate automat.

Dicționar Class

Vom avea o clasă numită Dictionary, această clasă va conține logica pentru ca noi să înregistrăm și să eliminăm fișiere din dicționar. Clasa va avea următoarele metode publice:
void registerAndNotify(Collection<VirtualFile> files)
void registerAndNotify(VirtualFile file)
void removeAndNotify(VirtualFile file)
void moveAndNotify(VirtualFile oldFile, VirtualFile newFile)

Aceste metode vor crea, de asemenea, o notificare despre ceea ce s-a întâmplat, astfel încât utilizatorul final să știe ce s-a schimbat cu dicționarele personalizate. Fișierul final pentru aceasta va arăta în felul următor:

Găsirea tuturor fișierelor de dicționar

Pentru a găsi toate fișierele de dicționar din proiectul numit project.dic folosim clasa FilenameIndex. Fișierul se află în spațiul de nume com.intellij.psi.search.FilenameIndex, are o metodă getVirtualFilesByName pe care le putem folosi pentru a ne găsi project.dic fișiere.

FilenameIndex.getVirtualFilesByName(    project,    "project.dic",    false,    GlobalSearchScope.allScope(project))

Acest apel va returna toate fișierele virtuale care corespund criteriilor de căutare. Apoi punem rezultatul returnat în metoda clasei Dicționar registerAndNotify.

@Overridepublic void projectOpened() {    Dictionary dictionary = new Dictionary(project);    dictionary.registerAndNotify(        FilenameIndex.getVirtualFilesByName(            project,            "project.dic",            false,            GlobalSearchScope.allScope(project)        )    );}

Codul nostru poate fi găsit acum project.dic fișiere la pornire și înregistrați-le, dacă nu sunt deja înregistrate. De asemenea, va notifica despre fișierele nou înregistrate.

Adăugarea unui ascultător de fișiere virtuale

Următoarea parte este pentru noi să ascultăm modificările fișierelor virtuale. Pentru a face acest lucru, avem nevoie de un ascultător. Pentru aceasta avem nevoie de com.intellij.openapi.vfs.VirtualFileListener.

În blocul de documente pentru clasa ascultător putem vedea că pentru a-l înregistra putem folosi VirtualFilemanager#addVirtualFileListener.
Să creăm o clasă numită DictionaryFileListener și implementăm metodele de care avem nevoie pentru proiectul nostru.

Apoi ne actualizăm projectOpened clasa pentru a adăuga, de asemenea VirtualFileListener.

@Overridepublic void projectOpened() {    Dictionary dictionary = new Dictionary(project);    dictionary.registerAndNotify(        FilenameIndex.getVirtualFilesByName(            project,            "project.dic",            false,            GlobalSearchScope.allScope(project)        )    );    VirtualFileManager.getInstance().addVirtualFileListener(        new DictionaryFileListener(dictionary)    );}

Pluginul nostru este acum capabil să găsească fișierele noastre de dicționar la pornire, dar poate asculta și dacă un fișier de dicționar este adăugat mai târziu. Următorul lucru de care avem nevoie este să adăugăm informații pentru lista noastră de pluginuri.

Adăugarea informațiilor despre plugin

Pentru a adăuga informații despre plugin, deschidem fișierul build.gradle fișier și editați obiectul patchPluginXml. Aici trebuie să specificăm ce versiune de construcție este necesară pentru plugin, versiunea pluginului, descriere și note de modificare.

patchPluginXml {    sinceBuild intellij.version    untilBuild null    version project.version    pluginDescription """Plugin for having a shared dictionary for all members of your project. <br><br>It will automatically find any <code>project.dic</code> files and add themto the list of dictionaries. <br><br>It will also search packages for dictionary files and add them to our list of dictionaries.    """    changeNotes """<p>0.2</p><ul>    <li>Added support for listening for when a <code>project.dic</code> file is added, moved, deleted, copied.</li></ul><p>0.1</p><ul>    <li>First edition of the plugin.</li></ul>    """}

Actualizăm și fișierul version proprietate pentru '0.2'a proiectului gradle în sine. Pluginul poate rula acum pe toate versiunile de când a fost adăugată metoda de înregistrare a dicționarelor personalizate.

Pentru a testa dacă generează ieșirea dorită, putem rula sarcina gradle patchPluginXml și sub build/patchedPluginXmlFiles generat de noi plugin.xml fișierul va fi acolo.

De la versiunea IntelliJ 2019.1, toate pluginurile acceptă pictograme. Deoarece acest lucru este destul de nou, o mulțime de pluginuri nu au o pictogramă, iar pluginul dvs. se poate remarca foarte mult prin faptul că are unul. Convenția de numire este pluginIcon.svg ca pictogramă implicită și pluginIcon_dark.svg pentru tema darcula.

Pictogramele plugin-ului ar trebui să fie listate împreună cu fișierul plugin.xml fișier în cale resources/META-INF.

Clădire pentru distribuție

Pluginul este acum gata să fie construit și livrat. Pentru a face acest lucru, executăm sarcina gradle buildPlugin. Sub build/distributions va apărea un fișier zip pe care îl puteți distribui și instala manual în IDE. Adăugați acest fișier zip ca fișier eliberați sub repozitia dvs. github, astfel încât utilizatorii au opțiunea de a-l descărca manual din repo.

Publicarea unui plugin

Pentru a publica pluginul nostru, astfel încât să poată fi descărcat direct din depozitul de pluginuri al IntelliJ, trebuie să ne conectăm la contul nostru JetBrains de pe Site-ul web al depozitului de pluginuri. Când vă aflați aici, o listă derulantă din numele profilului dvs. arată o opțiune de încărcare a unui plugin.

1612006452 74 Cum sa creati un plugin IntelliJ haideti sa construim

Introduceți toate informațiile din fereastră (trebuie să adăugați o licență, dar este destul direct cu Github). Aici adăugăm fișierul zip de distribuție.

1612006452 434 Cum sa creati un plugin IntelliJ haideti sa construim

Când trimiteți formularul, puteți vedea acum pluginul în depozitul de pluginuri. Cu toate acestea, ceilalți utilizatori nu au acces la acesta înainte ca IntelliJ să-l aprobe. Aprobarea pluginului dvs. durează în mod normal 2-3 zile.

1612006453 141 Cum sa creati un plugin IntelliJ haideti sa construim

Actualizarea pluginului dvs. prin Gradle

După ce pluginul a fost creat, îl putem actualiza programatic. Pentru a face acest lucru, cea mai bună practică este să creați un simbol. Deschideți hub-ul cu jetbrains și mergeți la fila autentificare. De aici apăsați New token... și adăugați domeniul de aplicare Plugin Repository.

1612006453 808 Cum sa creati un plugin IntelliJ haideti sa construim

Când apăsați creați, veți obține un simbol. Creați un fișier numit gradle.properties și adăugați simbolul sub cheie intellijPublishToken (nu uitați să ignorați acest fișier).

În a noastră build.gradle fișier, adăugăm pur și simplu următoarele:

publishPlugin {    token intellijPublishToken}

Și acum putem rula sarcina gradle publishPlugin pentru publicarea noii noastre versiuni. Toate numerele versiunilor trebuie să fie unice sau altfel nu se va actualiza. Când se creează o actualizare, trebuie să așteptați din nou 2-3 zile pentru ca aceștia să aprobe actualizarea.

După ce ați așteptat câteva zile, pluginul nostru a fost aprobat și poate fi găsit acum pe piața pluginurilor, căutând un dicționar!

1612006453 373 Cum sa creati un plugin IntelliJ haideti sa construim

Concluzie

Sper că acest articol v-a dat mai mult curaj pentru a începe să vă dezvoltați propriile pluginuri. Una dintre cele mai mari probleme pe care am avut-o în timp ce o dezvoltam a fost să aflu ce clase să folosesc. IntelliJ are un ghid extins pe care ți l-aș recomanda să citești de la început până la sfârșit, totuși o mulțime de clase nu sunt menționate acolo. În cazurile în care vă blocați, acestea au Chat Gitter ceea ce este foarte util și există oameni de la IntelliJ acolo pentru a ajuta, de asemenea.

Codul sursă pentru acest proiect poate fi găsit pe Github iar pluginul pe care l-am creat este în Piața JetBrains.