Argus Codewatch Code check and Quick fix Internals

Code checks

All code checks can be found in arguscodewatch > net.sourceforge.arguscodewatch.builders. The convention is that the class name of every code check should end with "Check". Its class should extend CodewatchVisitor. CodewatchVisitor provides 2 important methods:

getProperty() can be used to get information from the plugin.xml file and allows you to depend the behaviour of your code check on options defined in plugin.xml.

How does Eclipse create its code checks?

Eclipse calls its code checks Bindings. More information can be found in org.eclipse.jdt.core > compiler > org.eclipse.jdt.internal.compiler.lookup. How exactly Eclipse knows about its code checks, and how it executes them, is not known.

Problem markers

To create problem markers, call createMarker(). Use NLS.bind(String message, Object binding) to bind your error message (a String property in CodewatchPlugin.Resources) to one or more variables. This way you can put information in the descriptions of your code checks and it makes your descriptions more dynamic and code specific. You must define a String property in CodewatchPlugin.Resources and define the description in resources.properties.

Note: you can also bind 2 objects or an array of objects. Look in the NLS class for more information.

Argus calls IResource.createMarker() to create a marker. The method returns an IMarker and the returned object is used to set a map containing the attributes.

How does Eclipse create its markers?

Eclipse seems to use IProblemFactory interface to create problem markers. Look in ProblemReporter, ProblemHandler in org.eclipse.jdt.core > compiler > org.eclipse.jdt.internal.compiler.problem for more information.

Enabling @SuppressWarnings

You can let your code check use @SuppressWarnings by defining a String property SUPPRESS_WARNINGS_TOKEN in you code check class. In any visit() method in your class, you can use another important method of CodewatchVisitor:

You should call this method when checking whether the parents of the visited AST node contains the token. In other words: your code check should do the following steps:

  1. Check if parents of the given AST node contains your @SuppressWarnings token and check for other conditions (for example: the visited AST node is a child of some type of another AST node)
  2. Try to find the AST node you want your problem marker to apply to
  3. Create your problem marker.

Make sure you define suppressWarningsToken attribute in plugin.xml, to allow the user to apply your token as a quick fix.

When resolving bindings...

When you resolve bindings in your code check. Make sure you check that the result is not equal to null. The resolved binding may be null if the source code is malformed because of parse errors.

Quick fixes

All quick fixes can be found in arguscodewatch > net.sourceforge.arguscodewatch.quickfixes. The name of the class should end with "Fix". Quick fixes extend CodewatchCompletionProposal. In a quick fix you create AST copies of the nodes you want, modify them, and tell the ASTRewrite object which AST nodes to replace with which copies.

If you want to replace one node by several nodes which have no parent-child relationship, but are in sequential order, you can create a ListRewrite object by calling ASTRewrite.getListRewrite(ASTNode node, ChildListPropertyDescriptor property). Make sure the node you use as the first parameter, is a node that contains the list of nodes: a list you will use to insert nodes before, or after the node you want to replace.

Example:

blockNode contains a list of child nodes. One of these child nodes is the statementNode. In the example, the replacementStatement is inserted before the statementNode.

How does Eclipse create its quick fixes?

Eclipse seems to have its fixes in org.eclipse.jdt.uit > core extension > org.eclipse.jdt.internal.corext.fix. Fixes extend AbstractFix. Examples of manipulation of the AST tree, can be found in org.eclipse.jdt.uit > core extension > org.eclipse.jdt.internal.corext.codemanipulation. The interface IFix is used to describe the the fix.