Kako stvoriti dodatak IntelliJ - napravimo jednostavan pretraživač rječnika

Većina nas programera koristi IntelliJ platforme, bilo IDEA, PHPStorm, WebStorm, Android Studio, PyCharm i popis se nastavlja i nastavlja. No ponekad kad je koristimo, ustanovimo da neka značajka nedostaje, ali nemamo pojma kako je zapravo dodati i na kraju jednostavno živjeti bez nje.

U ovom ću članku opisati kako možemo stvoriti jednostavan dodatak za sve IntelliJ IDE-ove, pa će ga, kad dodate project.dicdatoteku, automatski dodati kao jedan od vaših rječnika. Također će tražiti datoteku u paketima, tako da paketi mogu dodavati prilagođene riječi u rječnik. .dicDatoteka je jednostavan rječniku kojoj svaki redak je riječ u rječniku.

Projekt je samo primjer za početak rada na razvoju vlastitih dodataka. Ali to je zapravo i značajka koja mi je nedostajala, jer kada razvijam prilagođeni paket s vlastitim riječima, mrzim što ih moram dodavati svaki put u rječnik na razini projekta.

Izrada projekta

Kada stvaramo dodatke za IntelliJ, moramo to učiniti na Javi ili Kotlinu. Učinit ću to na Javi jer je većina korisnika to upoznata. Kako je ovo Java projekt, koristit ćemo IntelliJ IDEA kao svoj IDE.

Prema razvojnom vodiču, preporučeni način izrade projekta je upotreba Gradlea. Mi smo započeli otvaranjem preferencesi provjeriti da li Gradlete Plugin DevKitsu dodaci instalirani.

Nakon instalacije dodataka i ponovnog pokretanja IDE-a, idemo na tijek novih projekata i ispod Gradle. Ovdje se sada zove opcija IntelliJ Platform Pluginkoja nam je potrebna.

Zatim prođite kroz ostatak tijeka stvaranja projekta kao i obično - u ovom projektu odabirem sljedeću konfiguraciju.

Postavljanje plugin.xml

Sad kad imamo projekt, moramo postaviti plugin.xmldatoteku i build.gradle. plugin.xmlDatoteka je datoteka koristi IntelliJ koji definira sve informacije o dodatku. To uključuje ime, ovisnosti, radnje koje bi trebao dodati ili ako bi trebalo proširiti nešto u IntelliJ-u. U osnovi ova datoteka definira sve što bi vaš dodatak trebao raditi i korijen je vašeg projekta. U našoj build.gradledatoteci možemo definirati neke vrijednosti plugin.xmli informacije poput koje verzije IntelliJ-a želimo testirati svoj dodatak prilikom gradnje s gradleom.

Počnimo s definiranjem naše plugin.xmldatoteke. Datoteku možete pronaći u src/main/resources/META-INF/plugin.xml. Želimo da naš dodatak bude dostupan na svim IntelliJ IDE-ima pa smo ga postavili dependenciesna com.intellij.modules.lang. Trenutno naša datoteka izgleda ovako:

 dk.lost_world.Dictionary Dictionary GitHub com.intellij.modules.lang

Međutim, trenutno to nema nikakve logike i ne registriramo ništa na platformi IntelliJ.

Kako će ovaj projekt pronaći project.dicdatoteke unutar projekta i registrirati ih kao rječnike u tom projektu, morat ćemo registrirati komponentu na razini projekta. Ova će se komponenta pozvati kada se projekt otvori i zatvori. Stvorimo klasu i implementiramo ProjectComponentsučelje. Kad zadržimo pokazivač iznad naziva klase, govori nam da komponenta nije registrirana.

Tada akciju možemo nazvati pozvanom Register Project Componenti ona će nam je registrirati u plugin.xmldatoteci.

Ako otvorimo plugin.xml, treba dodati sljedeći kod. Ako nije dodan prilikom poziva akcije, samo ga dodajte ručno.

  dk.lost_world.dictionary.DictionaryProjectComponent 

Datotečni sustav IntelliJ

Kada se radi s datoteka IntelliJ, koristimo V irtual F ile S ystem (VFS). VFS nam daje univerzalni API za razgovor s datotekama, a da ne moramo razmišljati jesu li s FTP-a, HTTP poslužitelja ili samo na lokalnom disku.

Kao što je dodatak izgleda za datoteke zove project.dicto će potreba naravno da razgovor s V irtual F ile S ystem. Sve datoteke u VFS-u su virtualne datoteke. To može zvučati pomalo zastrašujuće, ali u stvarnosti to je samo API za datotečni sustav i za datoteku. Način razmišljati o tome je samo da je V irtual F ile S ystem je vaš datotečni sustav sučelje i virtualne datoteke su datoteke.

Postavke provjere pravopisa

Kako IntelliJ već ima podršku za .dicdatoteke i provjeru pravopisa općenito, jedino što moramo učiniti je registrirati naše project.dicdatoteke u postavkama provjere pravopisa.

Sve postavke za provjeru pravopisa spremaju se u klasu pod nazivom com.intellij.spellchecker.settings.SpellCheckerSettings. Da biste ga dobili, jednostavno pozovite getInstancemetodu (većina klasa IntelliJ ima getInstancemetodu koja koristi IntelliJ-ove ServiceManagerispod).

Klasa postavki dobila je metodu getCustomDictionariesPathskoja vraća sve staze do rječnika koje je instalirao korisnik.

Kada promatramo potpis metode, također vidimo anotaciju koja se naziva AvailableSince. Kasnije ćemo upotrijebiti vrijednost u ovoj bilješci da odredimo minimalnu potrebnu verziju za rad našeg dodatka.

Kako metoda vraća popis, možemo je jednostavno pozvati addda je doda u novi put do rječnika.

Pokretanje našeg dodatka (build.gradle)

Kako sada znamo dodati rječnik u provjeru pravopisa, dodajmo mali primjer koda u našu DictionaryProjectComponentklasu za to.

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

Ovaj će kôd registrirati project.dicdatoteku iz korijena našeg projekta kad god se projekt otvori.

Da bismo testirali naš mali primjer, moramo ažurirati našu build.gradledatoteku. U intellijodjeljak datoteke gradle dodajemo u kojoj verziji IntelliJ-a želimo koristiti. Ovaj je broj verzije onaj iz AvailableSincenapomene na SpellCheckerSettingspredavanju.

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 //github.com/JetBrains/gradle-intellij-plugin/intellij { pluginName 'Dictionary' version '181.2784.17' type 'IC' downloadSources true}

Pokretanjem runIdenaredbe iz gradle pokrenut će se instanca IntelliJ određene verzije. Nakon pokretanja testnog IDE-a trebao bi se pokrenuti naš dodatak. Ako otvorimo preferences > Editor > Spelling > Dictionare, pod prilagođenim rječnicima možemo vidjeti da je sada dodan put koji smo naveli u našem primjeru.

Sada smo u mogućnosti testirati svoj dodatak, pa je sada vrijeme da ga pravilno napravimo kako bi pronašao project.dicdatoteke i registrirao ih za nas.

U DictionaryProjectComponent::projectOpenedmetodi moramo prvo pronaći sve pozvane datoteke project.dici registrirati ih, a također dodati i preslušač datoteka, pa se, kad project.dicse dodaju nove datoteke, automatski registriraju.

Rječnik rječnika

Imat ćemo klasu pod nazivom Dictionary, ona će sadržavati logiku za registraciju i uklanjanje datoteka iz rječnika. Predaja će imati sljedeće javne metode:

void registerAndNotify(Collection files)

void registerAndNotify(VirtualFile file)

void removeAndNotify(VirtualFile file)

void moveAndNotify(VirtualFile oldFile, VirtualFile newDatoteka)

Ove će metode također stvoriti obavijest o tome što se dogodilo, tako da krajnji korisnik zna što se promijenilo s prilagođenim rječnicima. Krajnja datoteka za ovo izgledat će na sljedeći način:

Pronalaženje svih datoteka rječnika

Za pronalaženje svih datoteka rječnika u nazvanom projektu project.dickoristimo klasu FilenameIndex. Datoteka se nalazi u prostoru imena com.intellij.psi.search.FilenameIndex, ima metodu pomoću getVirtualFilesByNamekoje možemo pronaći svoje project.dicdatoteke.

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

Ovaj poziv vratit će sve virtualne datoteke koje odgovaraju kriterijima pretraživanja. Zatim povratni rezultat stavljamo u metodu klase Dictionary registerAndNotify.

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

Naš je kod sada u mogućnosti pronaći project.dicdatoteke prilikom pokretanja i registrirati ih ako već nisu registrirane. Također će obavijestiti o novo registriranim datotekama.

Dodavanje virtualnog slušatelja datoteka

Sljedeći je dio da osluškujemo promjene u virtualnim datotekama. Da bismo to učinili potreban nam je slušatelj. Za ovo nam treba com.intellij.openapi.vfs.VirtualFileListener.

U bloku doc ​​za klasu slušatelj možemo vidjeti da ga možemo registrirati za registraciju VirtualFilemanager#addVirtualFileListener.

Stvorimo razred s imenom DictionaryFileListeneri provedimo metode koje su nam potrebne za naš projekt.

Zatim ažuriramo našu projectOpenedklasu kako bismo dodali i 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) );}

Naš dodatak sada može pronaći datoteke rječnika pri pokretanju, ali i poslušati ako se datoteka rječnika doda kasnije. Sljedeće što trebamo je dodati podatke za naš popis dodataka.

Dodavanje podataka o dodatku

To add information about the plugin, we open the build.gradle file and edit the object patchPluginXml. In here we need to specify which build version is required for the plugin, version of the plugin, description and change notes.

patchPluginXml { sinceBuild intellij.version untilBuild null version project.version pluginDescription """Plugin for having a shared dictionary for all members of your project.

It will automatically find any project.dic files and add themto the list of dictionaries.

It will also search packages for dictionary files and add them to our list of dictionaries. """ changeNotes """

0.2

  • Added support for listening for when a project.dic file is added, moved, deleted, copied.

0.1

  • First edition of the plugin.
"""}

We also update the version property to '0.2'of the gradle project itself. The plugin can now run on all versions since the method for registering custom dictionaries was added.

To test if it generates the desired output, we can run the gradle task patchPluginXml and under build/patchedPluginXmlFiles our generated plugin.xml file will be there.

Since IntelliJ version 2019.1, all plugins supports icons. As this is fairly new a lot of plugins do not have an icon, and your plugin can stand out a lot by having one. The naming convention is pluginIcon.svg as the default icon and pluginIcon_dark.svg for the darcula theme.

The plugin icons should be listed together with the plugin.xml file in the path resources/META-INF.

Building for distribution

The plugin is now ready to be built and shipped. To do this we run the gradle task buildPlugin. Under build/distributions a zip file will appear which you can distribute and install manually in your IDE. Add this zip file as a release under your github repo, so users have the option to download it manually from you repo.

Publishing a plugin

To publish our plugin so it can be downloaded directly from IntelliJ’s plugin repository, we need to login on our JetBrains account on the Plugin Repository website. When in here, a dropdown from your profile name shows an option to upload a plugin.

Input all the information in the dialog (you have to add a license, but that is pretty straightforward with Github). Here we add the distribution zip file.

When you submit the form, you can now see your plugin in the plugin repository. However other users do not have access to it before IntelliJ has approved it. Approving your plugin normally takes 2–3 days.

Updating your plugin via Gradle

After the plugin has been created, we can update it programmatically. To do this the best practice is to create a token. Open up jetbrains hub and go to the authentification tab. From here press New token... and add the scope Plugin Repository.

When pressing create you get a token. Create a file called gradle.properties and add the token under the key intellijPublishToken (remember to git ignore this file).

In our build.gradle file, we simply add the following:

publishPlugin { token intellijPublishToken}

And we can now run the gradle task publishPlugin for publishing our new version. All versions numbers have to be unique or else it will fail updating. When an update is created, you have to wait 2–3 days again for them to approve the update.

After waiting some days our plugin has now been approved and can now be found in the plugin marketplace by searching for dictionary!

Conclusion

I hope this article has given you more courage to start developing your own plugins. One of the biggest problems I had while developing it was to find out which classes to use. IntelliJ has an extensive guide which I would recommend that you read from start to end, however a lot of classes are not mentioned in there. In cases where you get stuck, they have a Gitter chat which is really helpful and there are people from IntelliJ on there to help also.

The source code for this project can be found on Github and the plugin we created is in the JetBrains marketplace.