
La mayoría de los desarrolladores usamos plataformas IntelliJ, ya sea IDEA, PHPStorm, WebStorm, Android Studio, PyCharm y la lista sigue y sigue. Sin embargo, a veces, cuando lo usamos, descubrimos que falta una función, pero no tenemos idea de cómo agregar esa función y, finalmente, vivir sin ella.
En este artículo, cubriré cómo podemos crear un complemento simple para todos los IDE de IntelliJ, de modo que cuando agregue un project.dic
archivo, lo agregará automáticamente como uno de sus diccionarios. También buscará el archivo en paquetes, por lo que los paquetes pueden agregar palabras personalizadas al diccionario. Un .dic
archivo es un diccionario simple donde cada línea es una palabra en el diccionario.
El proyecto es solo una muestra para comenzar a desarrollar sus propios complementos. Pero en realidad también es una característica que me faltaba, ya que cuando desarrollo un paquete personalizado con mis propias palabras, odio tener que agregarlas cada vez en el diccionario de nivel de proyecto.
Creando el proyecto
Al crear complementos para IntelliJ, tenemos la opción de hacerlo en Java o Kotlin. Lo haré en Java, ya que la mayoría de los usuarios están familiarizados con eso. Como este es un proyecto Java, usaremos IntelliJ IDEA como nuestro IDE.
Según la guía de desarrollo, la forma recomendada de crear un proyecto es mediante Gradle. Empezamos abriendo preferences
y compruebe si Gradle
y Plugin DevKit
están instalados los plugins.

Después de instalar los complementos y reiniciar el IDE, vamos al flujo de nuevos proyectos y debajo Gradle
. Aquí ahora hay una opción llamada IntelliJ Platform Plugin
que es la que necesitamos.

Luego, realice el resto del flujo de creación del proyecto como de costumbre; en este proyecto, elijo la siguiente configuración.



Configurar plugin.xml
Ahora que tenemos un proyecto, tenemos que configurar nuestro plugin.xml
archivo y build.gradle
. El plugin.xml
archivo es un archivo utilizado por IntelliJ que define toda la información sobre el complemento. Esto incluye el nombre, las dependencias, las acciones que debe agregar o si debe extender algo en IntelliJ. Básicamente, este archivo define todo lo que debe hacer su complemento y es la raíz de su proyecto. En nuestro build.gradle
archivo, podemos definir algunos de los valores plugin.xml
e información como en qué versión de IntelliJ queremos probar nuestro complemento al compilar con gradle.
Comencemos por definir nuestro plugin.xml
archivo. Puede encontrar el archivo en formato src/main/resources/META-INF/plugin.xml
. Queremos que nuestro plugin para estar disponible en todos IntelliJ IDE de lo que establecer nuestra dependencies
a com.intellij.modules.lang
. En este momento, nuestro archivo se ve así:
dk.lost_world.Dictionary Dictionary GitHub com.intellij.modules.lang
Sin embargo, en este momento esto no tiene ninguna lógica y no registramos nada en la plataforma IntelliJ.
Como este proyecto encontrará project.dic
archivos dentro de un proyecto y los registrará como diccionarios en ese proyecto, tendremos que registrar un componente de nivel de proyecto. Este componente se llamará cuando se abra y se cierre un proyecto. Creemos una clase e implementemos la ProjectComponent
interfaz. Cuando pasamos el cursor sobre el nombre de la clase, nos dice que el componente no está registrado.

Entonces podemos llamar a la acción llamada Register Project Component
y la registrará por nosotros en el plugin.xml
archivo.

Si abrimos se plugin.xml
debe agregar el siguiente código. Si no se agregó al llamar a la acción, simplemente agréguelo manualmente.
dk.lost_world.dictionary.DictionaryProjectComponent
Sistema de archivos IntelliJ
Cuando se trabaja con archivos en IntelliJ, utilizamos una V irtual F ile S istema (VFS). El VFS nos brinda una API universal para hablar con archivos, sin que tengamos que pensar si son de FTP, un servidor HTTP o simplemente en el disco local.
A medida que nuestra apariencia del plugin para los archivos de llamada project.dic
que lo hará de la necesidad supuesto para hablar con el V irtual F ile S istema. Todos los archivos del VFS son archivos virtuales. Esto puede sonar un poco intimidante, pero en realidad es solo una API para un sistema de archivos y para un archivo. La manera de pensar en ello es sólo que el V irtual F ile S istema es su interfaz de sistema de archivos y los archivos virtuales son sus archivos.
Configuración del corrector ortográfico
Como IntelliJ ya tiene soporte para .dic
archivos y corrector ortográfico en general, lo único que tenemos que hacer es registrar nuestros project.dic
archivos en la configuración del corrector ortográfico.
Todos los ajustes del corrector ortográfico se guardan en una clase llamada com.intellij.spellchecker.settings.SpellCheckerSettings
. Para obtener una instancia de él, simplemente llame al getInstance
método (la mayoría de las clases de IntelliJ tienen un getInstance
método que usa IntelliJ ServiceManager
debajo).
La clase de configuración obtuvo un método llamado getCustomDictionariesPaths
que devuelve todas las rutas a los diccionarios instalados por el usuario.

Al mirar la firma del método, también vemos una anotación llamada AvailableSince
. Luego usaremos el valor en esta anotación para especificar la versión mínima requerida para que funcione nuestro complemento.
Como el método devuelve una lista, simplemente podemos llamar add
al método para agregar una nueva ruta a un diccionario.
Ejecutando nuestro complemento (build.gradle)
Como ahora sabemos cómo agregar un diccionario al corrector ortográfico, agreguemos un pequeño ejemplo de código en nuestra DictionaryProjectComponent
clase para hacer esto.
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"); }}
Este código registrará un project.dic
archivo desde la raíz de nuestro proyecto cada vez que se abra el proyecto.
Para probar nuestro pequeño ejemplo, necesitamos actualizar nuestro build.gradle
archivo. En la intellij
sección del archivo gradle agregamos qué versión de IntelliJ queremos usar. Este número de versión es el de la AvailableSince
anotación en la SpellCheckerSettings
clase.
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}
Al ejecutar el runIde
comando desde gradle, se iniciará una instancia de IntelliJ de la versión específica. Después de iniciar el IDE de prueba, nuestro complemento debería haberse ejecutado. Si abrimos los preferences > Editor > Spelling > Dic
corredores, podemos ver en los diccionarios personalizados que ahora se agrega la ruta que especificamos en nuestro ejemplo.

Ahora podemos probar nuestro complemento, por lo que ahora es el momento de compilarlo correctamente para que encuentre los project.dic
archivos y los registre.
En el DictionaryProjectComponent::projectOpened
método, primero debemos buscar todos los archivos llamados project.dic
y registrarlos y también agregar un detector de archivos para que cuando project.dic
se agreguen nuevos archivos, se registren automáticamente.
Clase de diccionario
Tendremos una clase llamada Dictionary
, esta clase contendrá la lógica para que registremos y eliminemos archivos del diccionario. La clase tendrá los siguientes métodos públicos:
void registerAndNotify(Collection files)
void registerAndNotify(VirtualFile file)
void removeAndNotify(VirtualFile file)
void moveAndNotify(VirtualFile oldFile, VirtualFile ne
wFile)
Estos métodos también crearán una notificación sobre lo sucedido, para que el usuario final sepa qué cambió con los diccionarios personalizados. El archivo final para esto se verá de la siguiente manera:
Encontrar todos los archivos de diccionario
Para encontrar todos los archivos de diccionario en el proyecto llamado project.dic
usamos la clase FilenameIndex
. El archivo está en el espacio de nombres com.intellij.psi.search.FilenameIndex
, tiene un método getVirtualFilesByName
que podemos usar para encontrar nuestros project.dic
archivos.
FilenameIndex.getVirtualFilesByName( project, "project.dic", false, GlobalSearchScope.allScope(project))
Esta llamada devolverá todos los archivos virtuales que coincidan con los criterios de búsqueda. Luego colocamos el resultado devuelto en el método de la clase Diccionario registerAndNotify
.
@Overridepublic void projectOpened() { Dictionary dictionary = new Dictionary(project); dictionary.registerAndNotify( FilenameIndex.getVirtualFilesByName( project, "project.dic", false, GlobalSearchScope.allScope(project) ) );}
Our code is now able to find project.dic
files at start up and register them, if they are not already registered. It will also notify about the newly registered files.
Adding a Virtual File Listener
The next part is for us to listen for changes in virtual files. To do this we need a listener. For this we need the com.intellij.openapi.vfs.VirtualFileListener
.
In the docblock for the listener class we can see that to register it we can use VirtualFilemanager#addVirtualFileListener
.
Let’s create a class named DictionaryFileListener
and implement the methods which we need for our project.
Then we update our projectOpened
class to also add the 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) );}
Our plugin is now able to find our dictionary files at startup, but also listen for if a dictionary file is added later on. The next thing we need is to add information for our plugin listing.
Adding plugin information
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.