Loading...

Use Sonarqube for Code Inspection

Sonarqube is a starting point to find flaws in your source code. This post gives an introduction and demonstrates how to exclude false positives.

Maven Configuration

Add in the Apache Maven settings.xml a sonar profile. Replace the sonarqube-server address.

<profile>
    <id>sonar</id>
    <activation>
        <activeByDefault>true</activeByDefault>
    </activation>
    <properties>
        <!-- Optional URL to server. Default value is http://localhost:9000 -->
        <sonar.host.url>
          http://sonarqube-server:9000
        </sonar.host.url>
    </properties>
</profile>

Project Configuration

Setup your maven project (pom.xml) with a sonar profile. Most developers prefer to put it into a parent pom.

<profiles>
    <profile>
        <id>sonar-verbose</id>
        <properties>
            <!--<sonar.exclusions></sonar.exclusions>-->
            <sonar.language>java</sonar.language>
            <sonar.verbose>true</sonar.verbose>
        </properties>

        <build>
            <pluginManagement>
                <plugins>
                    <plugin>
                        <groupId>org.sonarsource.scanner.maven</groupId>
                        <artifactId>sonar-maven-plugin</artifactId>
                        <version>3.2</version>
                    </plugin>
                </plugins>
            </pluginManagement>
        </build>
    </profile>
</profiles>

Run the maven goal for sonar with the profiles: sonar, sonar-verbose.

mvn sonar:sonar -p sonar -p sonar-verbose

Following verbose output

[INFO] --- sonar-maven-plugin:3.2:sonar (default-cli) @ dcc-italy ---
[INFO] User cache: C:\Users\tan\.sonar\cache
[INFO] Load global repositories
[INFO] Load global repositories (done) | time=301ms
[INFO] User cache: C:\Users\tan\.sonar\cache
[INFO] Load plugins index
[INFO] Load plugins index (done) | time=13ms
[INFO] SonarQube version: 6.1
[INFO] Default locale: "en_US", source code encoding: "UTF-8"
[INFO] Process project properties
[INFO] Load project repositories
[INFO] Load project repositories (done) | time=169ms
[INFO] Execute project builders
[INFO] Execute project builders (done) | time=0ms
[INFO] Load quality profiles
[INFO] Load quality profiles (done) | time=20ms
[INFO] Load active rules
[INFO] Load active rules (done) | time=201ms
[INFO] Publish mode
[INFO] -------------  Scan DCC Italy
[INFO] Language is forced to java
[INFO] Load server rules
[INFO] Load server rules (done) | time=252ms
[INFO] Excluded sources for coverage:
[INFO]   **/generated/*.java,**/ddl/*.java, **/jaxb/*.java, **/generated-sources/**/*.java
[INFO]   **/simulator/**/*.java
[INFO] Base dir: C:\dev\src\dcc-italy
[INFO] Working dir: C:\dev\src\dcc-italy\target\sonar
[INFO] Source paths: pom.xml, src/main/java
[INFO] Test paths: src/test/java
[INFO] Source encoding: UTF-8, default locale: en_US
[INFO] Index files
[INFO] Excluded sources:
[INFO]   com/sca/**/ddl/**
[INFO]   com/tandem/**
[INFO]   **/wsdl/**
[INFO]   com/six_group/ao/**/*Dummy.java
[INFO]   com/telekurs/**/ddl/**
[INFO]   **/generated/*.java
[INFO]   **/ddl/*.java
[INFO] 12 files indexed
[INFO] 0 files ignored because of inclusion/exclusion patterns
[INFO] Quality profile for java: Frontoffice Default
[INFO] Sensor Lines Sensor
[INFO] Sensor Lines Sensor (done) | time=16ms
[INFO] Sensor JavaSquidSensor
[INFO] Configured Java source version (sonar.java.source): 7
[INFO] JavaClasspath initialization
[INFO] JavaClasspath initialization (done) | time=22ms
[INFO] JavaTestClasspath initialization
[INFO] JavaTestClasspath initialization (done) | time=4ms
[INFO] Java Main Files AST scan
[INFO] 8 source files to be analyzed
[WARNING] Class not found: javax.annotation.Nullable
[INFO] Java Main Files AST scan (done) | time=1869ms
[INFO] Java Test Files AST scan
[INFO] 4 source files to be analyzed
[INFO] 8/8 source files have been analyzed
[WARNING] Class not found: javax.annotation.Nullable
[INFO] Java Test Files AST scan (done) | time=420ms
[INFO] 4/4 source files have been analyzed
[INFO] Sensor JavaSquidSensor (done) | time=2845ms
[INFO] Sensor SCM Sensor
[INFO] SCM Publisher is disabled
[INFO] Sensor SCM Sensor (done) | time=1ms
[INFO] Sensor FindBugs Sensor
[INFO] Sensor FindBugs Sensor (done) | time=0ms
[INFO] Sensor SurefireSensor
[INFO] parsing C:\dev\src\dcc-italy\target\surefire-reports
[INFO] Sensor SurefireSensor (done) | time=159ms
[INFO] Sensor JaCoCoSensor
[INFO] JaCoCoSensor: JaCoCo report not found : C:\dev\src\dcc-italy\target\jacoco.exec
[INFO] Sensor JaCoCoSensor (done) | time=1ms
[INFO] Sensor JaCoCoItSensor
[INFO] JaCoCoItSensor: JaCoCo IT report not found: C:\dev\src\dcc-italy\target\jacoco-it.exec
[INFO] Sensor JaCoCoItSensor (done) | time=0ms
[INFO] Sensor JaCoCoOverallSensor
[INFO] Sensor JaCoCoOverallSensor (done) | time=1ms
[INFO] Sensor XmlFileSensor
[INFO] Sensor XmlFileSensor (done) | time=0ms
[INFO] Sensor Zero Coverage Sensor
[INFO] Sensor Zero Coverage Sensor (done) | time=19ms
[INFO] Sensor Code Colorizer Sensor
[INFO] Sensor Code Colorizer Sensor (done) | time=4ms
[INFO] Sensor CPD Block Indexer
[INFO] JavaCpdBlockIndexer is used for java
[INFO] Sensor CPD Block Indexer (done) | time=74ms
[INFO] Calculating CPD for 8 files
[INFO] CPD calculation finished
[INFO] Analysis report generated in 549ms, dir size=94 KB
[INFO] Analysis reports compressed in 124ms, zip size=46 KB
[INFO] Analysis report generated in C:\dev\src\dcc-italy\target\sonar\batch-report
[INFO] Analysis report uploaded in 63ms
[INFO] ANALYSIS SUCCESSFUL, you can browse http://sonarqube-server:9000/dashboard/index/com.sca.fo:dcc-italy
[INFO] Note that you will be able to access the updated dashboard once the server has processed the submitted analysis report
[INFO] More about the report processing at http://sonarqube-server:9000/api/ce/task?id=AVrMB1PS65C4nw4QRHMg
[INFO] Executing post-job org.sonar.plugins.buildbreaker.ForbiddenConfigurationBreaker
[INFO] Executing post-job org.sonar.plugins.buildbreaker.QualityGateBreaker
[INFO] Executing post-job org.sonar.plugins.stash.StashIssueReportingPostJob

Suppress Warnings

Most trivial methods are auto-generated and thus in the eyes of sonar for the human unreadable or a violation against clean readable code. To exclude or to suppress the warnings from sonar, just add the sonarqube rule into the SuppressWarnings tag.

// Methods should not have too many parameters
@SuppressWarnings("squid:S00107")
private Line(String alphaIsoCurrencyCode, String numericIsoCurrencyCode, String eurobandIndicator,
  String exchangeRate, String merchantFxRate, String validFromDate, String validFromTime, String validToDate,
  String validToTime, String markupPercentage, String markupDecimalPlacesPrecision) {
    this.alphaIsoCurrencyCode = alphaIsoCurrencyCode;
    this.numericIsoCurrencyCode = numericIsoCurrencyCode;
    this.eurobandIndicator = eurobandIndicator;
    this.exchangeRate = exchangeRate;
    this.merchantFxRate = merchantFxRate;
    this.validFromDate = validFromDate;
    this.validFromTime = validFromTime;
    this.validToDate = validToDate;
    this.validToTime = validToTime;
    this.markupPercentage = markupPercentage;
    this.markupDecimalPlacesPrecision = markupDecimalPlacesPrecision;
}

Another example how to exclude multiple rules

// ignore generated method for sonar
// Control structures should use curly braces, Statements should be on separate lines
@SuppressWarnings({"squid:S00121", "squid:S00122"})
@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    Line line = (Line) o;
    return Objects.equals(getAlphaIsoCurrencyCode(), line.getAlphaIsoCurrencyCode()) &&
            Objects.equals(getNumericIsoCurrencyCode(), line.getNumericIsoCurrencyCode()) &&
            Objects.equals(getEurobandIndicator(), line.getEurobandIndicator()) &&
            Objects.equals(getExchangeRate(), line.getExchangeRate()) &&
            Objects.equals(getMerchantFxRate(), line.getMerchantFxRate()) &&
            Objects.equals(getValidFromDate(), line.getValidFromDate()) &&
            Objects.equals(getValidFromTime(), line.getValidFromTime()) &&
            Objects.equals(getValidToDate(), line.getValidToDate()) &&
            Objects.equals(getValidToTime(), line.getValidToTime()) &&
            Objects.equals(getMarkupPercentage(), line.getMarkupPercentage()) &&
            Objects.equals(getMarkupDecimalPlacesPrecision(), line.getMarkupDecimalPlacesPrecision());
}