
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.dic
datoteku, 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. .dic
Datoteka 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 preferences
i provjeriti da li Gradle
te Plugin DevKit
su 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 Plugin
koja 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.xml
datoteku i build.gradle
. plugin.xml
Datoteka 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.gradle
datoteci možemo definirati neke vrijednosti plugin.xml
i informacije poput koje verzije IntelliJ-a želimo testirati svoj dodatak prilikom gradnje s gradleom.
Počnimo s definiranjem naše plugin.xml
datoteke. 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 dependencies
na 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.dic
datoteke 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 ProjectComponent
sučelje. Kad zadržimo pokazivač iznad naziva klase, govori nam da komponenta nije registrirana.

Tada akciju možemo nazvati pozvanom Register Project Component
i ona će nam je registrirati u plugin.xml
datoteci.

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.dic
to ć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 .dic
datoteke i provjeru pravopisa općenito, jedino što moramo učiniti je registrirati naše project.dic
datoteke 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 getInstance
metodu (većina klasa IntelliJ ima getInstance
metodu koja koristi IntelliJ-ove ServiceManager
ispod).
Klasa postavki dobila je metodu getCustomDictionariesPaths
koja 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 add
da 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 DictionaryProjectComponent
klasu 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.dic
datoteku iz korijena našeg projekta kad god se projekt otvori.
Da bismo testirali naš mali primjer, moramo ažurirati našu build.gradle
datoteku. U intellij
odjeljak datoteke gradle dodajemo u kojoj verziji IntelliJ-a želimo koristiti. Ovaj je broj verzije onaj iz AvailableSince
napomene na SpellCheckerSettings
predavanju.
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 runIde
naredbe 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 > Dic
tionare, 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.dic
datoteke i registrirao ih za nas.
U DictionaryProjectComponent::projectOpened
metodi moramo prvo pronaći sve pozvane datoteke project.dic
i registrirati ih, a također dodati i preslušač datoteka, pa se, kad project.dic
se 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 ne
wDatoteka)
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.dic
koristimo klasu FilenameIndex
. Datoteka se nalazi u prostoru imena com.intellij.psi.search.FilenameIndex
, ima metodu pomoću getVirtualFilesByName
koje možemo pronaći svoje project.dic
datoteke.
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.dic
datoteke 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 DictionaryFileListener
i provedimo metode koje su nam potrebne za naš projekt.
Zatim ažuriramo našu projectOpened
klasu 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.