IntelliJ Plugin Development – Drowning in Documentation

Introduction

Documentation is important. Okay, let’s be slightly more precise – good documentation is important. Take as an example the IntelliJ plugin documentation – at the time of writing, it’s hopefully out of date.

Trying to find any useful sources elsewhere on the ‘net isn’t any easier – you’re urged to “check out the community source code.” Totally as easy as it sounds.

But, you know, it’s not always easy writing documentation. Especially when you have corporate commenting standards that are somewhat ruthless – ever spent a day converting “getTheThing” into

Well, I for one, was over that. And I wanted to learn how IntelliJ plugins work. And I couldn’t read up on it, which leads me back to the beginning of this article.

Which leads us neatly onto the point of this article – let’s see how to create a basic IntelliJ plugin that will look at the currently opened source file, find methods that don’t have JavaDocs yet and document them. Of course documentation like this is next to useless, but sometimes documentation just isn’t appropriate. Accordingly, let’s called the plugin noDoc.

If, somehow or other, you’re just here after the source code, or the compiled JAR, it can be found here.

Setup

Setting up a project like this is fairly easy – create a new plugin project. The only thing you’ll need to do is setup an IntelliJ SDK – the official guides do have this bit documented.

The example project has a space action already configured – in my case, I modified it to give us a “noDoc” menu item and a “Add no documentation” option. For anyone unfamiliar with the _  syntax in the name, that indicates button keyboard shortcut can be used when navigating menus using the Alt key.

Getting to it

Working with IntelliJ plugins is fairly easy – far more straightforward than Eclipse plugins, or at least as far as my experience with it has gone. Most everything you’ll want to modify will exist as an object with Psi  prefixed to it – PsiFile , PsiClass , PsiMethod .

This makes searching for more information easier as well – much easier than Google-ing “how do i make the method pls”, which hopefully would bring up articles pitched at a different level of developer (but if not, good on you. Don’t forget to click the green tick to accept answers!).

Actions in menus should extend the OnAction  class – this provides one method to implement, onAction , which supplies an event object. From this event object we can extract information about the current setup. To start with, let’s check that when the event ran the user was editing a Java file. All JavaDoc is provided courtesy of the final product, before any hate rains down on me.

Here we ask the event for the project and the file. We check that the file is an instance of PsiJavaFile , and if so hand it and our project down to the processFile  method.

One thing to remember when modifying the file is that IntelliJ requires that you be in a “write” mode – this is so that it can support undo-ing the actions. In our case, we can’t just modify the methods as we find them because this would force the user to undo every method one-by-one – we need to write them as one large write.

Reading

First we loop through the classes in the current file (which we handed down), then we loop through each method in the class. We check to see that the method does not already have JavaDoc, and we add it to our list if so. Finally, we perform all of our writes.

The details of how the comments String s themselves are produced are fairly length and uninteresting, this being a guide on creating the actual plugin, but the source is available on the linked GitHub.

For each CommentItem, we store its class, the method and the produced comment. We need to keep track of the class and method as we’ll be using them to insert in a moment.

Writing

Once we’ve gotten a list of all the methods, their locations and their new, shiny JavaDocs, we must insert them into the code. This is done by creating an anonymous Runnable , and having it executed under a WriteCommandAction . An ElementFactory  handles the creation of the appropriate PsiComment  from our String.

For each comment, we create a PsiComment, then we grab our reference to the class that it’s contained in and tell it to insert the new comment directly before the method we’re commenting. Finally, we reformat the class, just to keep it nice and neat.

Easy enough!

Running

You can have IntelliJ launch a test run, which also lets you Debug, or if you’re supremely confident yo can just click Build and have it generate the plugin JAR that can be installed in your IntelliJ via the Plugins menu.

Let me know if you have any questions, or (as is fairly likely) know more about IntelliJ plugins than I do and can point out where I’ve made any errors (no matter how major.minor).

The full source (and compiled JAR) is available on GitHub.

Tagged with: , , , ,
Posted in Java

Leave a Reply