Skip to end of metadata
Go to start of metadata

Overview

The COBOL plugin parses the source code, creates an Abstract Syntax Tree (AST) and then walks through the entire tree. A coding rule can subscribe to be notified every time a type of node is visited.

As soon as the coding rule is notified, it can navigate the tree around the node and log issues if necessary.

Writing a Plugin

Writing new COBOL coding rules is a six-step process:

  • Create a standard SonarQube plugin.
  • Attach this plugin to the SonarQube COBOL plugin (see the pom.xml file of the provided sample plugin project).
  • Create as many custom COBOL coding rules as required by extending com.sonarsource.api.ast.CobolCheck and add them to the previous repository.
  • Generate the SonarQube plugin (jar file).
  • Place this jar file in the SONARQUBE_HOME/extensions/plugins directory.
  • Restart the SonarQube server.

Plugin Project Sample

To get started, clone the sample plugin project and follow the steps below:

  • Install Maven
  • Build the plugin by running “mvn install”. This will generate a SonarQube plugin jar file in the target directory.
  • Add your newly created jar into the SONARQUBE_HOME/extensions/plugins directory
  • Restart the SonarQube server

If you now look at the COBOL quality profiles, you will find the new coding rule (“Sample check”). Don’t forget to activate it. Run an analysis of a COBOL project, and you will find that an issue was logged at line 5 on every file.

Subscribing to a NodeType

Very often when writing a coding rule, you will want to subscribe to a NodeType. A NodeType can be either a rule of the grammar or a keyword of the language. As an example, here is the code of the implementation of the “Avoid using Merge statement” coding rule:

public class MergeStatementUsageCheck extends CobolCheck {

  public void init() {
    subscribeTo(getCobolGrammar().mergeStatement);
  }

  public void visitNode(AstNode node) {
    reportIssue("Avoid using MERGE statement.").on(node);
  }
}

Note that CICS and SQL grammars can be accessed using getCicsGrammar() and getSqlGrammar().

Coding Rule Lifecycle

A coding rule can optionally override six methods inherited from the CobolCheck class. Those methods are called sequentially in the following order:

  • public void init() {…}: This method is called only once and should be used to subscribe to one or more NodeType(s).
  • public void visitFile(AstNode astNode) {…}: This method is called on each file before starting the parsing.
  • public void visitNode(AstNode astNode) {…}: This method is called when an AstNode matches a subscribed NodeType (see Subscribing to a NodeType) and before analyzing its content.
  • public void leaveNode(AstNode astNode) {…}: This method is called when an AstNode matches a desired NodeType (see Subscribing to a NodeType) and after analyzing its content.
  • public void leaveFile(AstNode astNode) {…}: This method is called before exiting a file.
  • public void destroy() {…}: This method is called before shutting down the coding rule.

The reportIssue(…) method, used to log an issue, should be called only inside the visitFile(…), visitNode(…), leaveNode(…) and leaveFile(…) methods. Indeed, the file context isn’t known when the init() and destroy() methods are called, so the issue can’t be associated to a file.

More advanced features are documented in the API Javadoc.

Navigating the AST (Abstract Syntax Tree) with the SSLR COBOL Toolkit

When starting to write a new COBOL coding rule, the main difficulty is to understand the COBOL AST in order to know which NodeType(s) need to be visited. This can be achieved by using the SSLR COBOL Toolkit, a Swing application that enables loading a COBOL file and displaying its representation as an Abstract Syntax Tree.

Each node in the AST is a COBOL grammar rule and each leaf in the AST is a COBOL token. Let’s say you want to visit the node ‘ifStatement’. In this case, the init() method of your COBOL coding rule must contain the following statement: subscribeTo(getCOBOLGrammar().ifStatement);

API Changes

Since 4.0

A new API is available to write the rules but also to implement the tests.

  • Custom rules should now extend CobolCheck (CobolAstCheck is now deprecated) and issues should be logged using the reportIssue(...) method.
  • Tests on custom rules should now use CobolCheckVerifier: the assertions about issues should now be added as comments inside COBOL test files.
  • Custom rules should be listed in an implementation of CobolCheckRepository (CobolAstCheckRepository is now deprecated) and metadata should be loaded by implementing RulesDefinitionExtension.
  • You can now store your custom rules into a dedicated rule repository by implementing SonarQube's RulesDefinition: in that case, you don't need to implement RulesDefinitionExtension.
    (warning) For users having already custom rules in production: existing issues will be closed and re-opened because the internal keys of the rules are changing.

If you wrote a custom plugin against SonarCOBOL 3.x, it should still be compatible at runtime with SonarCOBOL 4.0.

To migrate to the new API (full example on github):

  • First, migrate tests without modifying rule classes. That mainly requires moving assertions from java test classes to comments inside test cobol files (see an example on github).
  • Update check classes to replace the calls to deprecated methods by the new methods which create issues (see an example on github).
  • Implement CobolRulesDefinitionExtension and CobolCheckRepository, remove the class extending CobolAstCheckRepository (see an example on github).
  • Update check classes to extend CobolCheck instead of CobolAstCheck to stop using any deprecated API (see an example on github).

 

To move your custom rules to a dedicated rule repository, see an example on github.
  • No labels