Skip to content

build: wire Error Prone + NullAway with JSpecify#28

Open
dfa1 wants to merge 2 commits into
mainfrom
nullaway
Open

build: wire Error Prone + NullAway with JSpecify#28
dfa1 wants to merge 2 commits into
mainfrom
nullaway

Conversation

@dfa1

@dfa1 dfa1 commented Jun 10, 2026

Copy link
Copy Markdown
Owner

Summary

  • Adds compile-time null-safety analysis via Error Prone + NullAway, keyed on JSpecify @NullMarked / @Nullable.
  • Proof-of-concept scope: annotates io.github.dfa1.vortex.extension only. Other packages stay unmarked (NullAway skips them when OnlyNullMarked=true).
  • Validates the tooling end-to-end: full ./mvnw verify green on JDK 25 (920+ unit + 243 integration tests pass).
  • Fixes three real nullness contracts found by NullAway in the annotated package:
    • ExtensionId.tryFrom return → @Nullable
    • Extension.findKnown return → @Nullable
    • TimestampExtension.dtype(unit, zone, nullable) zone param → @Nullable

How it works

  • pom.xml: errorprone 2.36.0, nullaway 0.12.3, jspecify 1.0.0. Error Prone + NullAway run as annotationProcessorPaths on maven-compiler-plugin. Flags: -XDcompilePolicy=simple --should-stop=ifError=FLOW -Xplugin:ErrorProne -XepDisableAllChecks -Xep:NullAway:ERROR -XepOpt:NullAway:OnlyNullMarked=true -XepOpt:NullAway:JSpecifyMode=true.
  • .mvn/jvm.config: --add-exports/--add-opens for jdk.compiler internals — required by Error Prone on JDK 25; the -J… compilerArgs are no-ops because maven-compiler-plugin runs javac in the Maven JVM.
  • performance/pom.xml: jmh-generator-annprocess pinned + combine.children="append" so JMH merges with the inherited Error Prone + NullAway processors.
  • XepExcludedPaths skips generated fbs/proto packages and the CLI TUI/server packages (workaround for upstream NullAway crashes on certain lambda + try/finally shapes).

Follow-ups (separate commits)

  • Extend @NullMarked to encoding, core, core.array, io, scan, writer, reader. Triage and annotate as NullAway flags real bugs (the PostscriptParser extension-nullable hardcode would have been caught here).
  • File upstream NullAway issues for the IoWorker lambda crash + DType pattern-match crash; remove exclusions once fixed.

Test plan

  • ./mvnw verify green on JDK 25.
  • CI runs the new compiler config on Linux + macOS + Windows.
  • Reviewer confirms the @NullMarked boundary scope is acceptable as a starting point.

🤖 Generated with Claude Code

dfa1 and others added 2 commits June 10, 2026 22:10
Adds compile-time null-safety analysis via Error Prone + NullAway,
keyed on JSpecify @NullMarked / @nullable.

- Root pom: errorprone 2.36.0, nullaway 0.12.3, jspecify 1.0.0 in
  versions block; jspecify in dependencyManagement; Error Prone +
  NullAway annotation processors on maven-compiler-plugin with
  Xep:NullAway:ERROR, OnlyNullMarked=true, JSpecifyMode=true.
- .mvn/jvm.config: add jdk.compiler add-exports/add-opens flags so
  Error Prone can reflect into javac internals on JDK 25.
- performance/pom.xml: pin jmh-generator-annprocess version explicitly
  + combine.children=append so the JMH processor merges with the
  inherited Error Prone + NullAway processors.
- Exclude generated (fbs/proto) and TUI/server packages via
  XepExcludedPaths to dodge upstream NullAway crashes on certain
  lambda + try/finally shapes.

Annotated boundary (proof-of-concept scope):
- io.github.dfa1.vortex.extension via package-info @NullMarked.
- ExtensionId.tryFrom return @nullable.
- Extension.findKnown return @nullable.
- TimestampExtension.dtype(unit, zone, nullable): zone @nullable.

Follow-ups: extend @NullMarked to io.github.dfa1.vortex.encoding,
core, core.array, io, scan, writer, reader as separate commits.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@nullable return types let callers silently dereference; Optional
forces the caller to handle the empty case at the type level and
reads as idiomatic modern Java per CLAUDE.md.

- ExtensionId.tryFrom: Optional<ExtensionId>
- Extension.findKnown: Optional<Extension>
- Callers updated: Chunk.as, VortexWriter.writeChunk, JdbcImporter.fillExtensionCell, VortexInspectorTui.formatValue.
- ExtensionIdTest assertions: isSameAs -> contains / isNull -> isEmpty.
- ExtensionTestSupport.tzMeta tz arg stays @nullable (string, not a result).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant