Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Info
iconfalse
titleTable of Contents

Table of Contents
maxLevel2

There are three ways to extend coding rules:

  1. Adding XPath rules directly in the Sonar web interface.
  2. Extending an existing Sonar plugin. For example Checkstyle and PMD plugins accept definition of custom checks.
  3. Embedding and executing a code analyzer. For example the Checkstyle plugin configures and executes the library Checkstyle.

To implement a new coding rule, we recommend to start with XPath at it is the most simple way. If it cannot be achieved with XPath rules (either because the language plugin does not support XPath yet or because the rule is highly complex and cannot be defined with an XPath expression), then write your own Sonar plugin.

Anchor
extendingRulesXPath
extendingRulesXPath

Adding New Rules Using XPath Expressions

Sonar provides a quick and easy way to add new coding rules directly via the web interface for certain languages (C/C++, C#, Cobol, Flex, JavaScript, PL/I, PL/SQL, Python and VB.NET).

The rules have to be written in XPath to navigate the Abstract Syntax Tree (AST). For each language, an SSLR Toolkit is provided to navigate the AST. This SSLR Toolkit is a standalone application that displays the AST for a provided piece of code source. So that you quickly get the nodes names and attributes to write your XPath expression from your code sample. The proper SSLR Toolkit can be downloaded from the language plugin page. So, finally, knowing the XPath language is the only prerequisite. A lot of tutorials on XPath can be found online (see http://www.w3schools.com/xpath/ for example).

Detailed tutorial

Let's take the following JavaScript source code sample:

Code Block
titleHelloWorld.js
linenumberstrue
languagejavascript
function HelloWorld(hour) {
  if (hour) {
    this.hour = hour;
  } else {
    var date = new Date();
    this.hour = date.getHours();
  }
  this.displayGreeting = function() {
    if (this.hour >= 22 || this.hour <= 5)
      document.write("Good night, World!");
    else
      document.write("Hello, World!");
  }  
}

While parsing the source code, Sonar builds an Abstract Syntax Tree (AST).

An SSLR Toolkit is provided by each language supporting XPath to get a representation of this AST. Here's the AST for our JavaScript sample:

The XPath language provides a way to write coding rules by navigating this AST.

To create a new rule:

  1. Login as an administrator
  2. Go to Configuration > Quality Profile
  3. Select one of the quality profiles whose language you want to add a new rule
  4. Look for the XPath rule template:
  5. Copy this template to create a new rule:
  6. Write your XPath rule (it should comply to XPath 1.0):


    Here are two examples of JavaScript XPath rules:

    Do not use document.write

    Code Block
    languagenone
    //callExpression/memberExpression[count(*) = 3 and primaryExpression[@tokenValue = "document"] and identifierName[@tokenValue = "write"]]


    Always use curly braces for if/else statements:

    Code Block
    languagenone
    //ifStatement/statement[not(block)] 

     

     

  7. Once written, activate those rules and run a Sonar analysis.
     
  8. Issues on those XPath rules are now logged:

Extending Sonar Plugins

The following languages can be extended with new rules:

Executing a Code Analyzer

A code analyzer plugin executes the following steps:

  1. Register definitions of coding rules, when the server is started.
  2. Optionally define some templates of quality profiles, when the server is started.
  3. Analyze source code and inject results in database 

1. Registering Coding Rules

This step relates to the extension point org.sonar.api.rules.RuleRepository. A RuleRepository defines a set of coding rules. It usually loads data from a XML file:

Code Block
java
java
public class CheckstyleRuleRepository extends RuleRepository { 
  // this sonar component is injected in constructor
  private XMLRuleParser xmlRuleParser; 

  public CheckstyleRuleRepository(XMLRuleParser xmlRuleParser) {   
    super("checkstyle", Java.KEY);
    setName("Checkstyle");   
    this.xmlRuleParser = xmlRuleParser; 
  } 

  @Override public List<Rule> createRules() {
    // the InputStream is closed in xmlRuleParser
    return xmlRuleParser.parse(getClass().getResourceAsStream("/org/sonar/plugins/checkstyle/rules.xml"))); 
  }
}

The XML file is available in the plugin classloader and looks like :

Code Block
xml
xml
 <rules> 
  <!-- the format used before sonar 2.3 is still supported : attributes key and priority on the node <rule> -->
  <rule>
    <!-- unique key within this repository -->
    <key>com.puppycrawl.tools.checkstyle.checks.header.HeaderCheck</key>
    <name>Header</name>
    <!-- default priority when the rule is activated (optional, default value is MAJOR). Values are INFO, MINOR,
         MAJOR, CRITICAL, BLOCKER -->
    <priority>MAJOR</priority>

    <!-- this key is used later by the sensor to configure the code analyzer --> 
    <configKey>Checker/Header</configKey>
   
    <!-- available ISO categories : Reliability, Portability, Maintainability, Efficiency, Usability -->
    <category name="Usability"/>

    <!--
    This node is optional: default value is SINGLE.
    MULTIPLE: the rule can be activated many times with different parameters and priority.
    SINGLE: the rule can be activated once
    --> 
    <cardinality>SINGLE</cardinality>

    <description><![CDATA[Checks that ...]]></description>
    <param>
      <key>header</key>
      <description><![CDATA[the required header specified inline. Individual header lines must be separated by the string "\n" (even on platforms with a different line separator)]]></description>
    </param>
    <param>
      <key>ignore</key>
      <description>...</description>
      <defaultValue>false</defaultValue>
    </param>
  </rule>
</rules>

2. Defining Quality Profiles

This step relates to the extension point org.sonar.api.profiles.ProfileDefinition. Quality profiles provided by plugins are registered at server startup.

3. Analyzing Source Code

This step relates to the extension point org.sonar.api.batch.Sensor.