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!).