Skip to content

Use static analysis

B. K. Oxley (binkley) edited this page Aug 15, 2024 · 19 revisions

Use static analysis

TODO page changes

  • Update with more options for plugins. See epic #462.
  • Edit "Going further" list at bottom, and decide what should be discussed in this page, and what should be links for folks to follow.

There are different stages or phases to static code analysis depending on (1) what is analyzed (source, compiled code, etc), and (2) the purpose of the analysis (bugs, code style, etc).

Analysis subject Analysis type Example
Source Build tool version Enforcer
Source Security (dependencies) DependencyCheck
Source Security (vulnerabilities) CodeQL
Source Bugs PMD
Source Style Checkstyle
Source Legacy code Modernizer
Compiling Bugs The compiler
Compiling Bugs error_prone compiler
Bytecode Security FindSecurityBugs extension to SpotBugs
Bytecode Bugs SpotBugs
Bytecode Bugs PIT mutation testing

"Linting" is static code analysis with an eye towards style and dodgy source code constructs. The term derives from early UNIX.

Some languages and their compilers do this for you; this is the case, for example, in Golang. See Leverage the compiler for more in depth on this.

On the style and formatting side, having common team agreements is a boon for avoiding bikeshedding, and aids in:

  • Reading a code base, relying on a similar style throughout
  • Code reviews, focusing on substantive over superficial changes
  • Merging code, avoiding trivial or irrelevant conflicts

Code style and formatting are entirely a matter of team discussion and agreement. In Java, there is no recommended style, and javac is good at parsing almost anything thrown at it. However, humans reading code are not as well-equipped.

Pick a team style, stick to it, and enforce it with tooling. See Choose your code style for more in depth.

See the section Checkstyle for more details on enforcement and Choose your code style for alternatives to Checkstyle. There is a lot of overlap bewteen "code style" and "static analysis".

Enforcing versions

Ultimately you want to have consistent build tools for all environments; that is, every build is the same in local and in CI so that you trust outcomes. This means keeping versions the same not just for dependencies but for the tools themselves.

From this need comes the "enforcer" plugins which let you require specific versions of Gradle or Maven and of the JVM.

Gradle

Gradle will complain at you when there is a newer Gradle version to use, but this is not quite what you want. So, it complains at you when you are using an older (or newer) Gradle version. For you, there is Enforcer Gradle Plugin. You are looking at settings.gradle in this project.

Maven

The Maven Enforcer Plugin lets you put hard restrictions in your pom.xml for an exact version of Maven. You are looking at the maven-enforcer-plugin plugin configuration in pom.xml.

Modernizer

Another static code analysis tool is Modernizer to check of use of obsolete APIs and types; this is related to but not identical to deprecated APIs. An example is moving to the JDK's Objects.equals from Guava's Objects.equal.

Note that Modernizer works at the bytecode level (not source code), so is suitable for any JVM language, not just Java.

PMD

PMD checks for common problems in the source code such as unused variables, empty catch blocks, or unneeded object creation. While SpotBugs focuses on your compiled code, PMD focuses on your source code. See the PMD Best Practices page for more on what problems PMD focuses on.

Both Gradle and Maven support PMD out of the box if enabled in your build (this project enables them).

Gradle

Documentation is in Gradle plugin.

To open the report for PMD, build locally, then open <project root>/build/reports/pmd/. The reports are:

  • main.html (production code)
  • test.html (test code)
  • integrationTest.html (integration test code)

Presently the PMD plugin for Gradle does not support CPD (copy-paste detector). An option is to use and external CPD plugin for Gradle.

Maven

Documentation is in Maven plugin.

To open the report for PMD, build locally, then open <project root/target/site/. The reports are:

  • PMD: pmd.html (potential issues)
  • CPD: cpd.html (source code duplicates)

Out of the box, the Maven PMD plugin supports CPD (copy-paste detection).

SpotBugs

SpotBugs checks for common problems in the compiled code such as anti-patterns, insecure code, or outdated code patterns. While PMD focuses on your source code, SpotBugs focuses on your compiled code. See the SpotBugs Bug descriptions page for more on what problems SpotBugs focuses on.

Security

Use the Find Security Bugs extension for SpotBugs. See Shift security left for more details.

CodeQL

CodeQL is also provided by GitHub for helping you analyze and search your codebase for vulnerabilities. The way it works is it builds a database of your codebase that can be scanned for potential problems using its own query language. It can easily be setup in github to scan your codebase using query suites. There is a default one, which focuses on finding high risk issues, an extended one which broadens to include ones with lower severity or you can create your own custom suite. These can either be configured to run either on your pipeline or using their CLI tool.

For further reading, you can start here or there is also a built in tutorial which can be found here.

Tips

  • Edit config/pmd/custom-rules.xml to adjust how PMD reviews your code (the sample in this project is from the PMD website.)
  • To open the report for SpotBugs, build locally and use the <project root>/build/reports/spotbugs/ (Gradle) or <project root>/target/site/ (Maven) path. Run ./mvnw site for the latter. The path shown in a Docker build is relative to the interior of the container
  • If you use Google Java coding conventions, consider Spotless which can autoformat your code.
  • Consider use of EditorConfig for teams when editor choice is up to each developer. EditorConfig is a cross-IDE standard means of specifying code formatting respected by common code editors (either directly, or through popular plugins)
  • To open the report for Checkstyle, build locally and use the <project root>/build/reports/checkstyle/ path. The path shown in a Docker build is relative to the interior of the container
  • If you use CodeQL, you can add a badge to your project README.md like this project does. You can navigate to actions/workflows/github-code-scanning/codeql for your project, and use the top-right "Show workflow options" dot-dot-dot for a drop list that includes "Create status badge".

Going further

Depending on your choices, you may be interested in other code quality plugins such as:

Clone this wiki locally