Static Code Analysis

Integrating ErrorProne and NullAway with an Android project

2017-09-15 Android, Gradle, Java, Static Code Analysis No comments

Recently, with the remote help of guys from Uber in California, I integrated NullAway and ErrorProne with the one of my open-source Android projects.

What is NullAway?

Basically, it’s a tool to help eliminate NullPointerExceptions (NPEs) in your Java code. It detects situations where NPE could occur at the compile time.

Let’s have a look at the following code:

static void log(Object x) {
    System.out.println(x.toString());
}
static void foo() {
    log(null);
}

NullAway will find out that we’re passing null and we’ll get appropriate error message:

warning: [NullAway] passing @Nullable parameter 'null' where @NonNull is required
    log(null);
        ^

It’s good to have checks like that because they eliminate possible bugs in advance and follows Clean Code principles.

A few words about ErrorProne

NullAway is built as a plugin to ErrorProne and can run on every single build of our code. Moreover, ErrorProne can perform other checks on our code, which can find out commonly people mistakes. E.g. it can detect a situation, where programmer forgot to add @Test annotation in the unit test method in a test suite and other things. It has built-in bug patterns, which are used during code analysis.

Integration with the Android project

I’ve integrated ErrorProne and NullAway with ReactiveNetwork Android library.

First, in the main build.gradle file, I’ve added the following lines:

ext.deps = [
            ...
            nullaway          : 'com.uber.nullaway:nullaway:0.1.2',
            errorprone        : 'com.google.errorprone:error_prone_core:2.1.1',
            ...
            ]

buildscript {
  repositories {
    jcenter()
    maven {
      url 'https://plugins.gradle.org/m2/'
    }
  }
  dependencies {
    ...
    classpath 'net.ltgt.gradle:gradle-errorprone-plugin:0.0.11'
    classpath 'net.ltgt.gradle:gradle-apt-plugin:0.11'
    // NOTE: Do not place your application dependencies here; they belong
    // in the individual module build.gradle files
  }
}

Next, in the library/build.gradle file, I’ve added appropriate plugins in the top:

apply plugin: 'net.ltgt.errorprone'
apply plugin: 'net.ltgt.apt'

Afterwards, I could add dependencies:

dependencies {
  ...

  annotationProcessor deps.nullaway
  errorprone deps.errorprone
}

The last thing to do, is the task responsible for running analysis during project compilation:

tasks.withType(JavaCompile) {
  if (!name.toLowerCase().contains("test")) {
    options.compilerArgs += ["-Xep:NullAway:ERROR", "-XepOpt:NullAway:AnnotatedPackages=com.github.pwittchen.reactivenetwork"]
  }
}

That’s it! Now, I could run analysis by typing:

./gradlew check

and fix the issues.

I think, a quite similar approach and configuration could be applied to a regular, pure Java project built with Gradle.

If you’re interested in the complete configurations, check it out in my project at: https://github.com/pwittchen/ReactiveNetwork.
You can also view Pull Request #226 made by @msridhar (kudos for him!).

Static Code Analysis in Android project

2015-03-26 Android, Continuous Integration, Static Code Analysis, Unit Tests No comments

Overview

I’ve recently read great article telling how to improve quality and syntax of your Android code by Vincent Brison. It presents how to use tools like Checkstyle, Findbugs, PMD, and Android Lint for Static Code Analysis in Android project. Static Code Analysis allows us to keep consistency of the source code style and helps us to find errors, warnings, possible bugs, bottlenecks and ways to improve the projects. I highly recommend to use tools like those mentioned.

Example

Visit repository at: https://github.com/vincentbrison/vb-android-app-quality.
The most important files are:

We can run analysis by executing the following command:

./gradlew check

Besides that, we can run each command like checkstyle, findbugs, pmd or lint separately if we want to.
In addition, when we build the project with command:

./gradlew build

check command will be executed as well, because of the following line in quality.gradle file:

check.dependsOn 'checkstyle', 'findbugs', 'pmd', 'lint'

After that, we can find output with our reports in directory: app/build/reports/. Of course, we can customize output directory and names of the report files. In default configuration, check command with generate reports in HTML format. Only output from the checkstyle operation will be generated in XML format. We can customize findbugs, pmd and lint, to generate XML reports instead of HTML reports in quality.gradle file.

Sensitivity of the build

We can customize rules of the Static Code Analysis tools in restrictive and non-restrictive way.
In findbugs and pmd task, we can set ignoreFailures attribute as follows:

ignoreFailures = false

When it’s set to false, tasks will only generate reports, but when we set it to true, build will fail, when at least one error will be found.
In lint task, we can customize attribute abortOnError as follows:

abortOnError true

It will literally abort the build, when any lint error occur. Warnings will be ignored. When we want to ignore errors, we can set this attribute to false.

Static Code Analysis on CI server

When we want to perform Static Code Analysis on CI server, we can do it easily from the command line interface. If we want to automatically collect and analyze reports generated by mentioned tools, we should generate them in XML format instead of HTML, so they can be parsed by appropriate plugins. Mentioned tools can be easily integrated with Jenkins CI server.
We need the following plugins:

After installing those plugins, we can define post-build actions in our Jenkins Job, provide paths to the appropriate XML reports and then we can view results of the reports and trend graphs directly from web panel of our Jenkins server.

Exemplary trend graphs looks as follows:

lint_checkstyle_findbugs_pmd_trends

If we have unit tests in our project, we can also generate test reports and monitor test trend.
In the chart below, failed build don’t have generated test reports that’s why chart may look strange. In addition, number of tests was decreased, because they were migrated from JUnit3 to JUnit4. In JUnit3 for some reason each test case is treated as an additional unit test. JUnit4 report shows real number of tests.

test_trend

In every build, we can browse generated reports and their details.

android_build_report

I really recommend to use Static Code Analysis tools and reporting plugins on CI in the projects, because they will increase quality of the code really fast and will allow to eliminate many errors before shipping the application.