From ed9c096e372a41e8cfa19e25fa09dadac878b021 Mon Sep 17 00:00:00 2001 From: Arnaud Lacurie Date: Fri, 28 Aug 2026 17:47:39 +0200 Subject: [PATCH] Adopt jspecify + NullAway null-checking on fdb-java-annotations Adds jspecify + NullAway (via net.ltgt.errorprone), scoped to this module only; com.apple.foundationdb.annotation is marked @NullMarked. This worktree's checkout predates the grpc/jdbc precedent branches, so the jspecify/errorprone/nullaway catalog entries in gradle/libs.versions.toml (assumed already present) had to be added here instead, mirroring exactly what the grpc branch added. Only real @Nonnull usages (annotating this module's own method params/ return types) were swapped away, relying on the @NullMarked default. GenerateVisitorAnnotationHelper.java also uses javax.annotation.Nonnull.class as a JavaPoet Class literal to annotate *generated* visitor interfaces consumed by other modules (e.g. fdb-record-layer-core, via @GenerateVisitor); that import/usage is intentionally left untouched, since swapping it would inject an org.jspecify import into generated code compiled in modules that don't have jspecify on their classpath, breaking their builds. No @Nullable annotations were needed: nothing in this module's 2 files returns or accepts null. compileJava, compileTestJava (no test sources), test (no test sources), and check (with SpotBugs HTML report) all pass clean with no NullAway suppressions required. --- .../fdb-java-annotations.gradle | 20 ++++++++ .../GenerateVisitorAnnotationHelper.java | 50 +++++++++---------- .../GenerateVisitorAnnotationProcessor.java | 4 +- .../foundationdb/annotation/package-info.java | 3 ++ 4 files changed, 49 insertions(+), 28 deletions(-) diff --git a/fdb-java-annotations/fdb-java-annotations.gradle b/fdb-java-annotations/fdb-java-annotations.gradle index 5b8bd85debb..84dd03074de 100644 --- a/fdb-java-annotations/fdb-java-annotations.gradle +++ b/fdb-java-annotations/fdb-java-annotations.gradle @@ -18,6 +18,10 @@ * limitations under the License. */ +plugins { + alias(libs.plugins.errorprone) +} + apply from: rootProject.file('gradle/publishing.gradle') dependencies { @@ -28,7 +32,23 @@ dependencies { // barring that, we can exclude it as a transitive dependency when importing implementation(libs.javaPoet) compileOnly(libs.autoService) + compileOnly(libs.jspecify) annotationProcessor(libs.autoService) + + errorprone(libs.errorprone.core) + errorprone(libs.nullaway) +} + +// jspecify + NullAway, scoped to this module only. See @NullMarked package-info.java in +// com.apple.foundationdb.annotation. +tasks.withType(JavaCompile).configureEach { + options.errorprone { + disableAllChecks = true + error("NullAway") + option("NullAway:AnnotatedPackages", "com.apple.foundationdb.annotation") + option("NullAway:JSpecifyMode", "true") + option("NullAway:AcknowledgeRestrictiveAnnotations", "true") + } } publishing { diff --git a/fdb-java-annotations/src/main/java/com/apple/foundationdb/annotation/GenerateVisitorAnnotationHelper.java b/fdb-java-annotations/src/main/java/com/apple/foundationdb/annotation/GenerateVisitorAnnotationHelper.java index 956fbfce873..65c3a9f6c9d 100644 --- a/fdb-java-annotations/src/main/java/com/apple/foundationdb/annotation/GenerateVisitorAnnotationHelper.java +++ b/fdb-java-annotations/src/main/java/com/apple/foundationdb/annotation/GenerateVisitorAnnotationHelper.java @@ -121,12 +121,12 @@ static boolean process(final ProcessingEnvironment processingEnv, Set subClassTypeMirrors) throws IOException { + private static void generateCode(final Types typeUtils, + final Filer filer, + GenerateVisitor generateVisitor, + final PackageElement packageElement, + final TypeElement rootTypeElement, + final List subClassTypeMirrors) throws IOException { final var rootTypeMirror = rootTypeElement.asType(); final var interfaceName = rootTypeElement.getSimpleName() + generateVisitor.classSuffix(); final var typeVariableName = TypeVariableName.get("T"); @@ -138,15 +138,15 @@ private static void generateCode(@Nonnull final Types typeUtils, generateImplementationWithDefaults(typeUtils, filer, generateVisitor, packageElement, subClassTypeMirrors, className, interfaceName, typeVariableName, defaultMethodName); } - private static void generateInterface(@Nonnull final Types typeUtils, - @Nonnull final Filer filer, - @Nonnull final GenerateVisitor generateVisitor, - @Nonnull final PackageElement packageElement, - @Nonnull final List subClassTypeMirrors, - @Nonnull final TypeMirror rootTypeMirror, - @Nonnull final String interfaceName, - @Nonnull final TypeVariableName typeVariableName, - @Nonnull final String defaultMethodName) throws IOException { + private static void generateInterface(final Types typeUtils, + final Filer filer, + final GenerateVisitor generateVisitor, + final PackageElement packageElement, + final List subClassTypeMirrors, + final TypeMirror rootTypeMirror, + final String interfaceName, + final TypeVariableName typeVariableName, + final String defaultMethodName) throws IOException { final TypeSpec.Builder typeBuilder = TypeSpec.interfaceBuilder(interfaceName) .addModifiers(Modifier.PUBLIC) @@ -216,15 +216,15 @@ private static void generateInterface(@Nonnull final Types typeUtils, .writeTo(Objects.requireNonNull(filer)); } - private static void generateImplementationWithDefaults(@Nonnull final Types typeUtils, - @Nonnull final Filer filer, - @Nonnull final GenerateVisitor generateVisitor, - @Nonnull final PackageElement packageElement, - @Nonnull final List subClassTypeMirrors, - @Nonnull final String className, - @Nonnull final String interfaceName, - @Nonnull final TypeVariableName typeVariableName, - @Nonnull final String defaultMethodName) throws IOException { + private static void generateImplementationWithDefaults(final Types typeUtils, + final Filer filer, + final GenerateVisitor generateVisitor, + final PackageElement packageElement, + final List subClassTypeMirrors, + final String className, + final String interfaceName, + final TypeVariableName typeVariableName, + final String defaultMethodName) throws IOException { final TypeSpec.Builder typeBuilder = TypeSpec.interfaceBuilder(className) .addModifiers(Modifier.PUBLIC) @@ -254,7 +254,7 @@ private static void generateImplementationWithDefaults(@Nonnull final Types type .writeTo(Objects.requireNonNull(filer)); } - private static String methodNameOfVisitMethod(@Nonnull final GenerateVisitor generateVisitor, @Nonnull TypeElement typeElement) { + private static String methodNameOfVisitMethod(final GenerateVisitor generateVisitor, TypeElement typeElement) { return generateVisitor.methodPrefix() + typeElement.getSimpleName().toString().replace(generateVisitor.stripPrefix(), ""); } diff --git a/fdb-java-annotations/src/main/java/com/apple/foundationdb/annotation/GenerateVisitorAnnotationProcessor.java b/fdb-java-annotations/src/main/java/com/apple/foundationdb/annotation/GenerateVisitorAnnotationProcessor.java index 991ece2db9e..d87b242f1c0 100644 --- a/fdb-java-annotations/src/main/java/com/apple/foundationdb/annotation/GenerateVisitorAnnotationProcessor.java +++ b/fdb-java-annotations/src/main/java/com/apple/foundationdb/annotation/GenerateVisitorAnnotationProcessor.java @@ -22,7 +22,6 @@ import com.google.auto.service.AutoService; -import javax.annotation.Nonnull; import javax.annotation.processing.AbstractProcessor; import javax.annotation.processing.ProcessingEnvironment; import javax.annotation.processing.Processor; @@ -78,11 +77,10 @@ @AutoService(Processor.class) public class GenerateVisitorAnnotationProcessor extends AbstractProcessor { @Override - public synchronized void init(@Nonnull final ProcessingEnvironment processingEnv) { + public synchronized void init(final ProcessingEnvironment processingEnv) { super.init(processingEnv); } - @Nonnull @Override public SourceVersion getSupportedSourceVersion() { return SourceVersion.latestSupported(); diff --git a/fdb-java-annotations/src/main/java/com/apple/foundationdb/annotation/package-info.java b/fdb-java-annotations/src/main/java/com/apple/foundationdb/annotation/package-info.java index 0e3828ffcc0..ed4d9ba4ae3 100644 --- a/fdb-java-annotations/src/main/java/com/apple/foundationdb/annotation/package-info.java +++ b/fdb-java-annotations/src/main/java/com/apple/foundationdb/annotation/package-info.java @@ -33,4 +33,7 @@ * None of the annotations have dependencies on *

*/ +@NullMarked package com.apple.foundationdb.annotation; + +import org.jspecify.annotations.NullMarked;