Introduction to developing a plugin for IntelliJ IDEA


This article originally published on my personal website, protsenko.dev.
TL; DR: This article describes how to set up a development environment to create an IDE plugin and begin writing code inspections.
I recently wrote my first article about my experience developing a plugin for JetBrains IDEs, especially IntelliJ IDEA. I want to share a small guide on how you could develop a plugin quickly with less struggle than I had. To develop plugins for JetBrains IDE, you should have skills in Kotlin or Java, but solutions will mainly be made in Kotlin.
Preparing to develop
Developing a plugin for IDEs could be tricky, but the IntelliJ platform provides several ways to build your plugin from scratch.
One of the obvious steps in developing your first plugin is downloading and installing the right IDE. For my pet project, I used IntelliJ Community because I don’t have a personal license for the Ultimate edition. You can easily download it from the official site.
After installing the IDE, you have two choices to start developing the plugin:
Install the Plugin DevKit plugin and create a project with it. Install this plugin not only because of the integrated plugin generator but also for highlighting problems in your plugin.
Clone IntelliJ platform plugin template and adjust it according to your needs.
Plugin DevKit new project generator.
Both ways provide you with a pre-configured project for easier development. After opening it, you must wait while all necessary dependencies are downloaded.
After importing the whole project, Gradle will have new internal tasks, but one of the most important tasks for you is to Run the plugin. It helps you to run a new window IDE with the pre-installed developing plugin.
Running the Run plugin
task is a way to test and debug your plugin, and you will run it a lot.
Developing a plugin
The IntelliJ Platform is well documented, and on their site, you can find useful information their site. In this guide, I will tell you about the parts I constantly use in development.
As a developer you definitely saw how IDE highlights some problems and offers quick fixes for easily resolving them. This mechanism is called Code Inspection
and provides a tool for static code analysis.
For implementing your first code inspection, you should:
Define your idea for code inspection.
Create inspection class by implementing
LocalInspectionTool
. That class will be entry point for developing inspection logic.Inspection and analyzing targeted files performed with special
Visitor
classes. Those classes provide a way to analyze the whole file or specific parts of the analyzed file. So, you should create one for your inspection.If you want to provide a user with a way to fix the highlighted problem, you should implement
LocalQuickFix
.Write inspection description in HTML format, and here Plugin DevKit helps you. When you implement your inspection class, it will suggest creating HTML documentation. It is better to write inspection descriptions following UI guidelines for inspections.
In case if you want to struggle less — make a tests, the platform provides already implemented solution to make tests easy. Just look at this testing documentation. Also read my previous article with testing chapter, automated tests saved a lot of time and nervous.
In general, some of the points are additional, but the base logic for your whole code inspection is to create a class by implementing LocalInspectionTool
and overriding method build visitor that should return you Visitor
with logic.
class SomeCodeInspection: LocalInspectionTool() {
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor {
return object : PsiElementVisitor() {
override fun visitElement(element: PsiElement) {
// there is could be your logic
super.visitElement(element)
println("element: ${element.text}")
}
}
}
}
Look at this small example: an implemented PsiElementVisitor
with override method visitElement
accepts argument PsiElement
. This is a time to speak a bit more about what PsiElement
is and generally what PSI means.
PSI is the Program Structure Interface, the syntactic and semantic code model that powers many of the platform’s features, especially our review code inspections.
The PsiElement
is a primitive in a PSI world; PsiElement
is an interface for any other PSI classes, such as PsiFile
or PsiComment
, from the PsiElementVisitor
interface. There are a lot of different already implemented PSI elements, and you should find what you need.
For me, it implemented PSI classes from the Docker plugin to analyze docker files and commands in it. I knew where I could find those classes but if you are struggling with locating elements that you need, you could use an internal PSI viewer. It is worth mentioning that if you are relying on some plugin — you should declare this plugin as a dependency to use. There is a guide that could help you.
Defining your targeted PSI elements is crucial for further creating inspection. With retrieved PSI elements, you could describe the whole logic for your inspection and analyze elements.
That’s all for now. If you’re interested in software development and want to learn more, follow me for upcoming posts.
Subscribe to my newsletter
Read articles from Dmitry Protsenko directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
