Skip to content

grounds 0.0.6

Choose a tag to compare

@mihaidaniel34 mihaidaniel34 released this 11 Oct 09:42
· 49 commits to master since this release

Parser and null-check release. Still experimental. The binary is for Apple Silicon, macOS 11+; on other platforms, build from source or use the Nix flake.

curl -fsSL https://github.com/mihaidaniel34/grounds/releases/download/v0.0.6/grounds-0.0.6-aarch64-apple-darwin.tar.gz | tar -xz
sudo mv grounds-0.0.6-aarch64-apple-darwin/grounds /usr/local/bin/

Not notarized: after a browser download, xattr -d com.apple.quarantine grounds.

New parser: tree-sitter-java-orchard
Upstream tree-sitter-java is no longer maintained. grounds now uses tree-sitter-java-orchard, the fork its contributors maintain.

  • Java 22–25 syntax parses: statements before super(...)/this(...), and import module java.base;.
  • Qualified record patterns (case Shape.Circle(var r)), final and _ in patterns, and annotated varargs parse natively. About 240 lines of source-rewriting workarounds are gone.
  • Module imports resolve: names come from the module's exported packages and those it re-exports (requires transitive), using a table of all JDK 25 modules. A name exported by two of those packages stays ambiguous, as javac treats it, and the file's own imports take precedence. unused-import no longer reports, or offers to delete, a module import.
  • Tested on the 21-project corpus (identical findings except one false positive fixed), all 15,356 files of the JDK 25 standard library (no parse errors), and a Java 8–25 syntax suite. Three review rounds by gpt-6-astra.
  • Baselines keep working. For methods with qualified-type varargs parameters, fingerprints now include the type. The previous fingerprint is still accepted, so existing baselines continue to suppress those findings.

Test code
Style rules and null-dereference no longer run on test sources: tests are there to run, and a null pointer in a test just fails it. About 6,700 fewer findings on the corpus.

Null checks

  • Helpers that always throw end the path. Examples: Asserts.fail(...), methods whose body ends in a throw (static, private or final ones), @Contract("-> fail"), and JUnit/TestNG/AssertJ fail(...).
  • Throw-on-false checks act as guards:
    • Spring Assert.state/isTrue, Guava checkArgument/checkState, commons Validate.isTrue, JUnit assertTrue;
    • @Contract("false -> fail");
    • project helpers that start with if (!ok) throw.
  • assertThat(x).as("...").isNotNull() counts as a guard.
  • Copies taken before a check share its result: ref = (T) node; if (node == null) return;.

Other fixes

  • inner-class-could-be-static skips JUnit @Nested classes (940 false positives on the corpus).
  • A static equals(Object) no longer counts as overriding equals.

The on-disk cache format changed, so the first run rebuilds it.