Icheckstyle Processor
Purpose
Checks Java code with Checkstyle’s checks, in-process (no checkstyle program, no Java runtime to install). The Rust alternative to the checkstyle processor: a port of checkstyle 8.36.1, so a file gets the same messages, at the same lines and columns, and passes or fails the way checkstyle would exit.
How It Works
Each file goes through what checkstyle does to it: its Java grammar (the ANTLR 2 lexer and parser checkstyle generates from java.g, with the same lookahead decisions, the same tree and the same parse errors), the comments and Javadoc it records on the way, and the checks the configuration names, walked over the tree as checkstyle’s TreeWalker walks it. Messages are printed as checkstyle prints them, in its order, and a message of severity error fails the product:
[ERROR] src/Bad.java:1: File does not end with a newline. [NewlineAtEndOfFile]
[ERROR] src/Bad.java:1:8: Unused import - java.util.List. [UnusedImports]
[ERROR] src/Bad.java:3:14: Should use uppercase 'L'. [UpperEll]
Messages of severity warning and info are printed and the file passes; ignore hides them. A file checkstyle cannot check (a syntax error, or one of the cases where checkstyle itself throws) fails with the exception checkstyle stops on:
src/Broken.java:2:13: unexpected token: {
The checks are configured as checkstyle is, by a checkstyle.xml:
[processor.checker.icheckstyle]
src_dirs = ["src"]
Implemented modules
Checker (with severity, tabWidth, fileExtensions, charset UTF-8), TreeWalker, NewlineAtEndOfFile, ArrayTypeStyle, CovariantEquals, DefaultComesLast, EmptyStatement, EqualsHashCode, FallThrough, ModifiedControlVariable, OneStatementPerLine, RedundantImport, SimplifyBooleanExpression, SimplifyBooleanReturn, StringLiteralEquality, UnusedImports and UpperEll, each with all its properties, severity, id, tabWidth and <message> overrides. These are the checks of the fleet’s shared checkstyle.xml. Any other module, or a property this port does not reproduce, is a configuration error that names it, so a configuration either runs as checkstyle runs it or does not run.
Fidelity
Checked against checkstyle 8.36.1 over 5169 Java files (the fleet’s 2559, checkstyle’s own sources and the 1700 Java inputs of its test suite, many of them deliberately odd syntax) and 6000 mutated copies (broken quotes, comments, braces and literals, deleted, duplicated and swapped lines), under the fleet’s configuration and two configurations that set every other property: the same messages, line for line, and for every file checkstyle stops on, the same exception (about 4400 of them, parse errors and checkstyle’s own exceptions alike).
It is also lighter: those 5169 files take under a second of CPU, against checkstyle’s 25 seconds (and its JVM).
The engine’s unit tests (src/engines/checkstyle/tests.rs) keep it that way: they run checkstyle 8.36.1 itself (a missing or different version fails them) and the engine over the files in src/engines/checkstyle/testdata/ and deterministic mutants of them, under three configurations, and require the same result for every file.
Known differences: checkstyle checks the files of a run in one process, and two checks carry a little state from one file to the next (the line of the last lambda in OneStatementPerLine); each file here is checked on its own. Messages are English only, ${property} references resolve only through a default, and files are read as UTF-8.
Source Files
- Input:
.javafiles undersrc_dirs, or the files insrc_files - Output: none (checker)
The default src_dirs is empty, so a stanza with no src_dirs or src_files checks nothing: name the directories ([""] for the whole project) or files to check.
Configuration
| Key | Type | Default | Description |
|---|---|---|---|
config_file | string | "checkstyle.xml" | The checkstyle configuration, as checkstyle -c; relative to the project root |
dep_auto | string[] | ["checkstyle.xml"] | Config files that are inputs when they exist |
A config_file other than checkstyle.xml should also be listed in dep_inputs, so that changing it rebuilds.
Switching a repo from checkstyle: [processor.checker.checkstyle] → [processor.checker.icheckstyle], and args = ["-c", "checkstyle.xml"] is dropped (or becomes config_file for another file name).
Batch support
Not used: checking in-process has no start-up cost for a batch to share, so files are checked in parallel as separate products.
Clean behavior
This processor is a Checker — rsconstruct clean outputs is a no-op for it (checkers produce no outputs). See Clean behavior and rsconstruct clean.