Child pages
  • Developing Custom Language Plugins for IntelliJ IDEA

Versions Compared


  • This line was added.
  • This line was removed.
  • Formatting was changed.


Example: NamesValidator for Properties language

Further customization of the Rename refactoring processing is possible on multiple levels. Providing a custom implementation of the RenameHandler interface allows you to entirely replace the UI and workflow of the rename refactoring, and also to support renaming something which is not a PsiElement at all.

Example: RenameHandler for renaming a resource bundle

If you're fine with the standard UI but need to extend the default logic of renaming, you can provide an implementation of the RenamePsiElementProcessor interface. This allows you to:

  • Rename an element different from the one on which the action was invoked (a super method, for example)
  • Rename multiple elements at once (if their names are linked according to the logic of your language)
  • Check for name conflicts (existing names etc.)
  • Customize how search for code references or text references is performed
  • etc.

Example: RenamePsiElementProcesssor for renaming a property

Safe Delete Refactoring

The Safe Delete refactoring also builds on the same Find Usages framework as Rename. In addition to that, in order to support Safe Delete, a plugin needs to implement two things:


Example: delete() implementation for a Property

If needed, it's possible to further customize how Safe Delete is performed for a particular type of element (how references are searched, etc). This is done by implementing the SafeDeleteProcessorDelegate interface.

Example: SafeDeleteProcessorDelegate implementation for a .properties file

Code Formatter

IDEA includes a powerful framework for implementing custom language formatters. In this framework, the plugin specifies the constraints on the spacing between different syntax elements, and the formatting engine, provided by IDEA, calculates the smallest number of whitespace modifications that need to be performed on the file to make it match the constraints.


The starting point for the structure view is the PsiStructureViewFactory interface, which is registered in the com.intellij.lang.psiStructureViewFactory extension point.

Example: PsiStructureViewFactory for .properties files

To reuse the IDEA implementation of the Structure View, the plugin returns a TreeBasedStructureViewBuilder from its PsiStructureViewFactory.getStructureViewBuilder() method. As the model for the builder, the plugin can specify a subclass of TextEditorBasedStructureViewModel, and by overriding methods of this subclass it customizes the structure view for a specific language.

Example: StructureViewModel for .properties files

The main method to override is getRoot(), which returns the instance of a class implementing the StructureViewTreeElement interface. IDEA doesn't provide a standard implementation of this interface, so a plugin will need to implement it completely.


The implementation of StructureViewTreeElement.getChildren() needs to be matched by TextEditorBasedStructureViewModel.getSuitableClasses(). The latter method returns an array of PsiElement-derived classes which can be shown as structure view elements, and is used to select the Structure View item matching the cursor position when the structure view is first opened or when the "Autoscroll from source" option is used.

Example: StructureViewElement for a property

Surround With

In order to support the "Code | Surround With..." action, the plugin needs to register one or more implementations of the SurroundDescriptor interface in the com.intellij.lang.surroundDescriptor extension point. Each of the surround descriptors defines a possible type of code fragment which can be surrounded - for example, one surround descriptor can handle surrounding expressions, and another can handle statements. Each surround descriptor, in turn, contains an array of Surrounder objects, defining specific templates which can be used for surrounding the selected code fragment (for example, "Surround With if", "Surround With for" and so on).