Checkstyle at Wealthfront

At Wealthfront we use Checkstyle to enforce some coding standards, also to detect bad practice at the early stage. In this blog post, we will describe how to configure Checkstyle and how to customize that for our needs.

How to configure Checkstyle?

There are three components working together to automate all these checks:

Few things to note in that plugin configuration:

  • It is bound to the “validate” phase and will check the code prior to compiling the code.
  • We put cacheFile in ${basedir} instead of in target which can save some time when running check over and over.

How does checkstyle work?

There are two types of checks that Checkstyle supports.

com.puppycrawl.tools.checkstyle.api.FileSetCheck

It reads the file and builds a list of String, then passes the File itself with the list of String to FileSetCheck#process(). Also, we have a meta test, BadSnippetsFileSetCheck, which extends FileSetCheck and does regular expression matching against file content.

com.puppycrawl.tools.checkstyle.api.Check

It parses the file and builds an abstract syntax tree, then runs the depth-first traversal starting from the root, and calls Check#visitToken() for each token.

How to add new checks?

RegexpSinglelineJava

The fastest and simplest way? We can add a new module for what should not be used in the code.

BadSnippetsFileSetCheck

If we need some advanced matching or multiline matching, we can add a new snippet in JavaBadCodeSnippetsTest.java. The “value” is the regular expression that should not appear in the code, and “rationale” will be shown to the users if checkstyle detects such violations.

AbstractFileSetCheck

Want to do something more based on the content? We can extend AbstractFileSetCheck and implement processFiltered(). It iterates through the file content, and if there are multiple empty lines, it shows error messages.

AbstractCheck

Want even more advanced syntax check? We can extend AbstractCheck and implement getDefaultTokens() and visitToken(). It shows error messages if it finds any LABELED_STAT token.

By using Checkstyle we can check the code at the earliest possible time and detect some patterns that may cause bigger troubles later. It can do more than just coding style check, for example, it can detect the classes with external operations which should not appear in the database transactions, or remind us to call mockery.assertIsSatisfied() if we use mockery in test cases. Welcome to add more customized checks and find the potential issues as early as possible.