IntelliJ Platform Plugin SDK Help

Code Inspections

The IntelliJ Platform provides tools designed for static code analysis called code inspections, which help the user maintain and clean up code without actually executing it. Custom code inspections can be implemented as IntelliJ Platform plugins. An example of the plugin approach is the comparing_string_references_inspection code sample.

See the Inspections topic in UI Guidelines on naming, writing description, and message texts for inspections.

Creating an Inspection Plugin

The comparing_string_references_inspection code sample adds a new inspection to the Java | Probable Bugs group in the Inspections list. The inspection reports when the == or != operator is used between String expressions.

It illustrates the components for a custom inspection plugin:

  • Describing an inspection in the plugin configuration file.

  • Implementing a local inspection class to inspect Java code in the editor.

  • Creating a visitor to traverse the PSI tree of the Java file being edited, inspecting for problematic syntax.

  • Implementing a quick fix class to correct syntax problems by altering the PSI tree as needed. Quick fixes are displayed to the user like intentions.

  • Writing an HTML description of the inspection for display in the inspection preferences panel.

  • Creating a test for the implemented inspection and quick fix.

Although the code sample illustrates implementations of these components, it is often useful to see examples of inspections implemented in the IntelliJ Community code base. To identify a given inspection's implementation classes, try to find an inspection by name or by UI texts. Consider also searching for existing implementations in IntelliJ Platform Explorer.

Creating an Inspection

The comparing_string_references_inspection code sample reports when the == or != operators are used between String expressions. The user can apply a quick fix to change a==b to a.equals(b), or a!=b to !a.equals(b).

The details of the comparing_string_references_inspection implementation illustrate the components of an inspection plugin.

Plugin Configuration File

The comparing_string_references_inspection is described as a com.intellij.localInspection extension point in the comparing_string_references_inspection plugin configuration (plugin.xml) file.

There exist two types of inspection extensions:

  • The com.intellij.localInspection extension point is used for inspections that operate on one file at a time, and also operate "on-the-fly" as the user edits the file.

  • The com.intellij.globalInspection extension point is used for inspections that operate across multiple files, and the associated fix might, for example, refactor code between files.

The minimum inspection setup must declare the implementationClass and language attribute (unless the inspection works on any supported language). As shown in the comparing_string_references_inspection plugin configuration file, other attributes can be defined in the localInspection element, either with or without localization. In most cases, it is simplest to define the attributes in the plugin configuration file because the underlying parent classes handle most of the class responsibilities based on the configuration file description.

If required, inspections can define all the attribute information (except implementationClass) by overriding methods in the inspection implementation class (not recommended in general).

Inspection Implementation Java Class

Inspection implementations for Java files, like ComparingStringReferencesInspection, are often based on the Java class AbstractBaseJavaLocalInspectionTool. The AbstractBaseJavaLocalInspectionTool base class offers methods to inspect Java classes, fields, and methods.

More generally, localInspection types are based on the class LocalInspectionTool. Examining the class hierarchy for LocalInspectionTool shows that the IntelliJ Platform provides many child inspection classes for a variety of languages and frameworks. One of these classes is a good basis for a new inspection implementation, but a bespoke implementation can also be based directly on LocalInspectionTool.

The primary responsibilities of the inspection implementation class are to provide:

  • A PsiElementVisitor object to traverse the PSI tree of the file being inspected.

  • A LocalQuickFix class to fix an identified problem (optional).

  • An options panel to be displayed in the Inspections settings dialog (optional). See Inspection Options for more details.

The overridden ComparingStringReferencesInspection methods are discussed in the sections below.

Visitor Implementation Class

The visitor class evaluates whether elements of the file's PSI tree are of interest to an inspection.

The ComparingStringReferencesInspection.buildVisitor() method creates an anonymous visitor class based on JavaElementVisitor to traverse the PSI tree of the Java file being edited, inspecting for suspect syntax. The anonymous class overrides visitBinaryExpression(), which checks if a PsiBinaryExpression's operator is == or !=, and if both operand types are String.

Quick Fix Implementation

The quick fix class acts much like an intention, allowing the user to invoke it on the PsiElement (or TextRange) highlighted by the inspection.

The ComparingStringReferencesInspection implementation uses the nested class ReplaceWithEqualsQuickFix to implement a quick fix based on LocalQuickFix. The ReplaceWithEqualsQuickFix class allows the user to change the use of a == b and a != b expression to a.equals(b) and !a.equals(b) respectively.

The heavy lifting is done in ReplaceWithEqualsQuickFix.applyFix(), which manipulates the PSI tree to convert the expressions. The change to the PSI tree is accomplished by the usual approach to modification:

  • Getting a PsiElementFactory.

  • Creating a new PsiMethodCallExpression.

  • Substituting the original left and right operands into the new PsiMethodCallExpression.

  • Replacing the original binary expression with the PsiMethodCallExpression.

Inspection Description

The inspection description is an HTML file. The description is displayed in the upper right panel of the Inspections settings dialog when an inspection is selected from the list.

See the Inspections topic in UI Guidelines on important guidelines for writing the description.

Implicit in using LocalInspectionTool in the class hierarchy of the inspection implementation means following some conventions.

  • The inspection description file is expected to be located under $RESOURCES_ROOT_DIRECTORY$/inspectionDescriptions/. If the inspection description file is to be located elsewhere, override getDescriptionUrl() in the inspection implementation class.

  • The name of the description file is expected to be the inspection $SHORT_NAME$.html as provided by the inspection description, or the inspection implementation class. If a short name is not provided, the IntelliJ Platform computes one by removing Inspection suffix from the implementation class name.

Code Snippets

Using the following HTML structure, the description can embed code snippets that will be displayed with syntax highlighting:

<p> The following code will be shown with syntax highlighting: </p> <pre> <code> // code snippet </code> </pre>

The language will be set according to the inspection's registration language attribute. If required (e.g., when targeting UAST), it can be specified explicitly via <code lang="LanguageID">...</code>.

To open related settings directly from the inspection description, add a link with settings://$CONFIGURABLE_ID$, optionally followed by ?$SEARCH_STRING$ to pre-select UI element:

See <em>Includes</em> tab in <a href="settings://fileTemplates">Settings | Editor | File and Code Templates</a> to configure.

Inspection Test

The comparing_string_references_inspection code sample provides a test for the inspection. See the Testing Overview section for general information about plugin testing.

The comparing_string_references_inspection test is based on the UsefulTestCase class, part of the JUnit framework APIs. This class handles much of the underlying boilerplate for tests.

By convention, the folder test/testData/ contains the test files. The folder contains pairs of files for each test using the name convention ∗.java and ∗.after.java, e.g., Eq.java/Eq.after.java.

The comparing_string_references_inspection tests run the inspection on the ∗.java files, apply the quick fix, and compare the results with the respective ∗.after.java files containing expected results.

Running the Comparing String References Inspection Code Sample

The comparing_string_references_inspection code sample adds a new inspection to the Java | Probable Bugs group in the Inspections configuration.

See Code Samples on how to set up and run the plugin.

How does it work?

The plugin inspects your code opened in the IntelliJ IDEA editor. The plugin highlights the code fragments where two String expressions are compared by == or != and proposes to replace this code fragment with .equals():

Comparing String References inspection highlighting and quick fix

In this example, the str1 and str2 are variables of the String type. Invoking SDK: Use equals() will result in transforming expression to the form visible in the preview popup (code fragment on the right).

Last modified: 07 October 2024