From 95478ae6892a0a974ce073fec06b2fcb6811b89f Mon Sep 17 00:00:00 2001 From: Manu Sridharan Date: Fri, 19 Jul 2024 15:55:15 -0700 Subject: [PATCH] Update to JSpecify 1.0 and use JSpecify annotations in NullAway code (#1000) * Update our JSpecify dependence to 1.0 * Change NullAway source code to use JSpecify annotations (test inputs were left alone) * Fix position of type use `@Nullable` annotations to be next to type and enable the `AnnotationPosition` Error Prone check * Update README to encourage use of JSpecify --- README.md | 11 ++-- build.gradle | 1 + gradle/dependencies.gradle | 6 +- guava-recent-unit-tests/build.gradle | 2 +- jar-infer/test-java-lib-jarinfer/build.gradle | 2 +- jdk-recent-unit-tests/build.gradle | 2 +- jmh/build.gradle | 1 + .../com/uber/nullaway/jmh/NullawayJavac.java | 4 +- .../test-library-model-generator/build.gradle | 2 +- nullaway/build.gradle | 3 +- .../com/uber/nullaway/CodeAnnotationInfo.java | 2 +- .../main/java/com/uber/nullaway/Config.java | 5 +- .../com/uber/nullaway/DummyOptionsConfig.java | 5 +- .../java/com/uber/nullaway/ErrorBuilder.java | 5 +- .../nullaway/ErrorProneCLIFlagsConfig.java | 11 ++-- .../main/java/com/uber/nullaway/NullAway.java | 5 +- .../com/uber/nullaway/NullabilityUtil.java | 11 ++-- .../uber/nullaway/dataflow/AccessPath.java | 60 +++++++------------ .../dataflow/AccessPathNullnessAnalysis.java | 13 ++-- .../AccessPathNullnessPropagation.java | 7 +-- .../CoreNullnessStoreInitializer.java | 4 +- .../com/uber/nullaway/dataflow/DataFlow.java | 22 +++---- .../EnclosingEnvironmentNullness.java | 5 +- .../dataflow/FieldOrMethodCallElement.java | 4 +- .../uber/nullaway/dataflow/NullnessStore.java | 5 +- .../dataflow/NullnessStoreInitializer.java | 5 +- .../FixSerializationConfig.java | 11 ++-- .../SerializationService.java | 2 +- .../nullaway/fixserialization/Serializer.java | 5 +- .../nullaway/fixserialization/XMLUtil.java | 7 +-- .../location/AbstractSymbolLocation.java | 4 +- .../out/ClassAndMemberInfo.java | 14 ++--- .../fixserialization/out/ErrorInfo.java | 18 +++--- .../nullaway/generics/GenericsChecks.java | 11 ++-- .../AbstractFieldContractHandler.java | 2 +- .../handlers/ApacheThriftIsSetHandler.java | 6 +- .../nullaway/handlers/AssertionHandler.java | 2 +- .../nullaway/handlers/BaseNoOpHandler.java | 5 +- .../nullaway/handlers/CompositeHandler.java | 5 +- .../uber/nullaway/handlers/GrpcHandler.java | 5 +- .../handlers/GuavaAssertionsHandler.java | 12 ++-- .../com/uber/nullaway/handlers/Handler.java | 5 +- .../handlers/InferredJARModelsHandler.java | 6 +- .../handlers/LibraryModelsHandler.java | 15 ++--- .../uber/nullaway/handlers/LombokHandler.java | 2 +- .../handlers/OptionalEmptinessHandler.java | 13 ++-- .../RestrictiveAnnotationHandler.java | 4 +- .../handlers/contract/ContractHandler.java | 2 +- .../handlers/contract/ContractUtils.java | 5 +- .../handlers/stream/StreamModelBuilder.java | 2 +- sample/build.gradle | 2 +- .../src/main/java/com/uber/mylib/Lambdas.java | 5 +- .../src/main/java/com/uber/mylib/MyClass.java | 2 +- .../java/com/uber/mylib/MyClass.java.buggy | 2 +- .../main/java/org/utilities/StringUtils.java | 2 +- test-java-lib-lombok/build.gradle | 2 +- .../main/java/com/uber/lombok/LombokDTO.java | 6 +- .../main/java/com/uber/lombok/UsesDTO.java | 2 +- test-java-lib/build.gradle | 1 - .../AndroidRecentlyAnnotatedClass.java | 3 +- .../unannotated/RestrictivelyAnnotatedFI.java | 2 +- ...rictivelyAnnotatedFIWithModelOverride.java | 5 +- 62 files changed, 170 insertions(+), 230 deletions(-) diff --git a/README.md b/README.md index 1fa724529f..e3ff1d8c9e 100644 --- a/README.md +++ b/README.md @@ -25,10 +25,9 @@ plugins { dependencies { errorprone "com.uber.nullaway:nullaway:" - // Optional, some source of nullability annotations. - // Not required on Android if you use the support - // library nullability annotations. - compileOnly "com.google.code.findbugs:jsr305:3.0.2" + // Some source of nullability annotations; JSpecify recommended, + // but others supported as well. + api "org.jspecify:jspecify:1.0.0" errorprone "com.google.errorprone:error_prone_core:" } @@ -48,7 +47,7 @@ tasks.withType(JavaCompile) { Let's walk through this script step by step. The `plugins` section pulls in the [Gradle Error Prone plugin](https://github.com/tbroyer/gradle-errorprone-plugin) for Error Prone integration. -In `dependencies`, the first `errorprone` line loads NullAway, and the `compileOnly` line loads a [JSR 305](https://jcp.org/en/jsr/detail?id=305) library which provides a suitable `@Nullable` annotation (`javax.annotation.Nullable`). NullAway allows for any `@Nullable` annotation to be used, so, e.g., `@Nullable` from the Android Support Library or JetBrains annotations is also fine. The second `errorprone` line sets the version of Error Prone is used. +In `dependencies`, the first `errorprone` line loads NullAway, and the `api` line loads the [JSpecify](https://jspecify.dev) library which provides suitable nullability annotations, e.g., `org.jspecify.annotations.Nullable`. NullAway allows for any `@Nullable` annotation to be used, so, e.g., `@Nullable` from the AndroidX annotations Library or JetBrains annotations is also fine. The second `errorprone` line sets the version of Error Prone is used. Finally, in the `tasks.withType(JavaCompile)` section, we pass some configuration options to NullAway. First `check("NullAway", CheckSeverity.ERROR)` sets NullAway issues to the error level (it's equivalent to the `-Xep:NullAway:ERROR` standard Error Prone argument); by default NullAway emits warnings. Then, `option("NullAway:AnnotatedPackages", "com.uber")` (equivalent to the `-XepOpt:NullAway:AnnotatedPackages=com.uber` standard Error Prone argument) tells NullAway that source code in packages under the `com.uber` namespace should be checked for null dereferences and proper usage of `@Nullable` annotations, and that class files in these packages should be assumed to have correct usage of `@Nullable` (see [the docs](https://github.com/uber/NullAway/wiki/Configuration) for more detail). NullAway requires at least the `AnnotatedPackages` configuration argument to run, in order to distinguish between annotated and unannotated code. See [the configuration docs](https://github.com/uber/NullAway/wiki/Configuration) for other useful configuration options. For even simpler configuration of NullAway options, use the [Gradle NullAway plugin](https://github.com/tbroyer/gradle-nullaway-plugin). @@ -58,7 +57,7 @@ We recommend addressing all the issues that Error Prone reports, particularly th Versions 3.0.0 and later of the Gradle Error Prone Plugin [no longer support Android](https://github.com/tbroyer/gradle-errorprone-plugin/releases/tag/v3.0.0). So if you're using a recent version of this plugin, you'll need to add some further configuration to run Error Prone and NullAway. Our [sample app `build.gradle` file](https://github.com/uber/NullAway/blob/master/sample-app/build.gradle) shows one way to do this, but your Android project may require tweaks. Alternately, 2.x versions of the Gradle Error Prone Plugin still support Android and may still work with your project. -Beyond that, compared to the Java configuration, the `com.google.code.findbugs:jsr305:3.0.2` dependency can be removed; you can use the `android.support.annotation.Nullable` annotation from the Android Support library instead. +Beyond that, compared to the Java configuration, the JSpecify dependency can be removed; you can use the `androidx.annotation.Nullable` annotation from the AndroidX annotation library instead. #### Annotation Processors / Generated Code diff --git a/build.gradle b/build.gradle index 845ec01016..450c0f3dd2 100644 --- a/build.gradle +++ b/build.gradle @@ -82,6 +82,7 @@ subprojects { project -> check("UnusedException", CheckSeverity.ERROR) check("UnnecessaryFinal", CheckSeverity.ERROR) check("PreferredInterfaceType", CheckSeverity.ERROR) + check("AnnotationPosition", CheckSeverity.ERROR) // To enable auto-patching, uncomment the line below, replace [CheckerName] with // the checker(s) you want to apply patches for (comma-separated), and above, disable // "-Werror" diff --git a/gradle/dependencies.gradle b/gradle/dependencies.gradle index 72221be7c5..d3203078ef 100755 --- a/gradle/dependencies.gradle +++ b/gradle/dependencies.gradle @@ -77,8 +77,7 @@ def build = [ guava : "com.google.guava:guava:30.1-jre", javaparser : "com.github.javaparser:javaparser-core:3.26.0", javaxValidation : "javax.validation:validation-api:2.0.1.Final", - jspecify : "org.jspecify:jspecify:0.3.0", - jsr305Annotations : "com.google.code.findbugs:jsr305:3.0.2", + jspecify : "org.jspecify:jspecify:1.0.0", commonsIO : "commons-io:commons-io:2.11.0", wala : [ "com.ibm.wala:com.ibm.wala.util:${versions.wala}", @@ -112,7 +111,8 @@ def test = [ rxjava2 : "io.reactivex.rxjava2:rxjava:2.1.2", commonsLang3 : "org.apache.commons:commons-lang3:3.8.1", commonsLang : "commons-lang:commons-lang:2.6", - lombok : "org.projectlombok:lombok:1.18.24", + jsr305Annotations : "com.google.code.findbugs:jsr305:3.0.2", + lombok : "org.projectlombok:lombok:1.18.34", springBeans : "org.springframework:spring-beans:5.3.7", springContext : "org.springframework:spring-context:5.3.7", grpcCore : "io.grpc:grpc-core:1.15.1", // Should upgrade, but this matches our guava version diff --git a/guava-recent-unit-tests/build.gradle b/guava-recent-unit-tests/build.gradle index b8a0662643..ccc5bb00a2 100644 --- a/guava-recent-unit-tests/build.gradle +++ b/guava-recent-unit-tests/build.gradle @@ -32,7 +32,7 @@ dependencies { testImplementation(deps.build.errorProneTestHelpers) { exclude group: "junit", module: "junit" } - testImplementation deps.build.jsr305Annotations + testImplementation deps.test.jsr305Annotations testImplementation "com.google.guava:guava:31.1-jre" errorProneOldest deps.build.errorProneCheckApiOld diff --git a/jar-infer/test-java-lib-jarinfer/build.gradle b/jar-infer/test-java-lib-jarinfer/build.gradle index df1a7a0683..fca6883f07 100644 --- a/jar-infer/test-java-lib-jarinfer/build.gradle +++ b/jar-infer/test-java-lib-jarinfer/build.gradle @@ -53,7 +53,7 @@ dependencies { compileOnly deps.apt.autoService annotationProcessor deps.apt.autoService compileOnly project(":nullaway") - implementation deps.build.jsr305Annotations + api deps.build.jspecify } jar.dependsOn ":jar-infer:jar-infer-cli:assemble" diff --git a/jdk-recent-unit-tests/build.gradle b/jdk-recent-unit-tests/build.gradle index ba7f95ffaa..36c7db2562 100644 --- a/jdk-recent-unit-tests/build.gradle +++ b/jdk-recent-unit-tests/build.gradle @@ -39,7 +39,7 @@ dependencies { testImplementation(deps.build.errorProneTestHelpers) { exclude group: "junit", module: "junit" } - testImplementation deps.build.jsr305Annotations + testImplementation deps.test.jsr305Annotations testModulePath deps.test.cfQual } diff --git a/jmh/build.gradle b/jmh/build.gradle index 3788935517..25e8a6ecb2 100644 --- a/jmh/build.gradle +++ b/jmh/build.gradle @@ -41,6 +41,7 @@ dependencies { // use the same version of Error Prone Core that we are compiling NullAway against, so we can // benchmark against different versions of Error Prone implementation deps.build.errorProneCoreForApi + api deps.build.jspecify // Source jars for our desired benchmarks diff --git a/jmh/src/main/java/com/uber/nullaway/jmh/NullawayJavac.java b/jmh/src/main/java/com/uber/nullaway/jmh/NullawayJavac.java index 1d094d8869..0691af9c62 100644 --- a/jmh/src/main/java/com/uber/nullaway/jmh/NullawayJavac.java +++ b/jmh/src/main/java/com/uber/nullaway/jmh/NullawayJavac.java @@ -33,13 +33,13 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; -import javax.annotation.Nullable; import javax.tools.DiagnosticListener; import javax.tools.JavaCompiler; import javax.tools.JavaFileObject; import javax.tools.SimpleJavaFileObject; import javax.tools.StandardJavaFileManager; import javax.tools.ToolProvider; +import org.jspecify.annotations.Nullable; /** * Code to run Javac with NullAway enabled, designed to aid benchmarking. Construction of {@code @@ -53,7 +53,7 @@ public class NullawayJavac { ////////////////////// private List compilationUnits; private JavaCompiler compiler; - @Nullable private DiagnosticListener diagnosticListener; + private @Nullable DiagnosticListener diagnosticListener; private StandardJavaFileManager fileManager; private List options; diff --git a/library-model/test-library-model-generator/build.gradle b/library-model/test-library-model-generator/build.gradle index 676abca9e7..82289966b2 100644 --- a/library-model/test-library-model-generator/build.gradle +++ b/library-model/test-library-model-generator/build.gradle @@ -49,7 +49,7 @@ dependencies { compileOnly deps.apt.autoService annotationProcessor deps.apt.autoService compileOnly project(":nullaway") - implementation deps.build.jsr305Annotations + api deps.build.jspecify } jar.dependsOn ":library-model:library-model-generator-cli:assemble" diff --git a/nullaway/build.gradle b/nullaway/build.gradle index c2b56fd2d1..17adb65077 100644 --- a/nullaway/build.gradle +++ b/nullaway/build.gradle @@ -31,7 +31,8 @@ dependencies { annotationProcessor deps.apt.autoValue compileOnly deps.apt.autoServiceAnnot annotationProcessor deps.apt.autoService - compileOnly deps.build.jsr305Annotations + // Using api following the guidance at https://jspecify.dev/docs/using#gradle + api deps.build.jspecify compileOnly deps.test.jetbrainsAnnotations compileOnly deps.apt.javaxInject diff --git a/nullaway/src/main/java/com/uber/nullaway/CodeAnnotationInfo.java b/nullaway/src/main/java/com/uber/nullaway/CodeAnnotationInfo.java index 99570daade..4844efc308 100644 --- a/nullaway/src/main/java/com/uber/nullaway/CodeAnnotationInfo.java +++ b/nullaway/src/main/java/com/uber/nullaway/CodeAnnotationInfo.java @@ -35,8 +35,8 @@ import com.uber.nullaway.handlers.Handler; import java.util.HashMap; import java.util.Map; -import javax.annotation.Nullable; import javax.lang.model.element.ElementKind; +import org.jspecify.annotations.Nullable; /** * Provides APIs for querying whether code is annotated for nullness checking, and for related diff --git a/nullaway/src/main/java/com/uber/nullaway/Config.java b/nullaway/src/main/java/com/uber/nullaway/Config.java index 65374dcd95..10f87ea2d6 100644 --- a/nullaway/src/main/java/com/uber/nullaway/Config.java +++ b/nullaway/src/main/java/com/uber/nullaway/Config.java @@ -26,7 +26,7 @@ import com.sun.tools.javac.code.Symbol; import com.uber.nullaway.fixserialization.FixSerializationConfig; import java.util.Set; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; /** Provides configuration parameters for the nullability checker. */ public interface Config { @@ -238,8 +238,7 @@ public interface Config { * return an @NonNull copy (likely through an unsafe downcast, but performing runtime checking * and logging) */ - @Nullable - String getCastToNonNullMethod(); + @Nullable String getCastToNonNullMethod(); /** * Gets an optional comment to add to auto-fix suppressions. diff --git a/nullaway/src/main/java/com/uber/nullaway/DummyOptionsConfig.java b/nullaway/src/main/java/com/uber/nullaway/DummyOptionsConfig.java index a9694fc413..117670d5c4 100644 --- a/nullaway/src/main/java/com/uber/nullaway/DummyOptionsConfig.java +++ b/nullaway/src/main/java/com/uber/nullaway/DummyOptionsConfig.java @@ -29,7 +29,7 @@ import com.sun.tools.javac.code.Symbol; import com.uber.nullaway.fixserialization.FixSerializationConfig; import java.util.Set; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; /** * Dummy Config class required for the {@link NullAway} empty constructor. @@ -175,8 +175,7 @@ public Set getOptionalClassPaths() { } @Override - @Nullable - public String getCastToNonNullMethod() { + public @Nullable String getCastToNonNullMethod() { throw new IllegalStateException(ERROR_MESSAGE); } diff --git a/nullaway/src/main/java/com/uber/nullaway/ErrorBuilder.java b/nullaway/src/main/java/com/uber/nullaway/ErrorBuilder.java index 5206912499..4cdb31d4a5 100755 --- a/nullaway/src/main/java/com/uber/nullaway/ErrorBuilder.java +++ b/nullaway/src/main/java/com/uber/nullaway/ErrorBuilder.java @@ -61,10 +61,10 @@ import java.util.List; import java.util.Set; import java.util.stream.StreamSupport; -import javax.annotation.Nullable; import javax.lang.model.element.Element; import javax.lang.model.element.ElementKind; import javax.tools.JavaFileObject; +import org.jspecify.annotations.Nullable; /** A class to construct error message to be displayed after the analysis finds error. */ public class ErrorBuilder { @@ -318,8 +318,7 @@ Description.Builder addSuppressWarningsFix( *

TODO: actually use {@link * com.google.errorprone.fixes.SuggestedFixes#addSuppressWarnings(VisitorState, String)} instead */ - @Nullable - private Tree suppressibleNode(@Nullable TreePath path) { + private @Nullable Tree suppressibleNode(@Nullable TreePath path) { if (path == null) { return null; } diff --git a/nullaway/src/main/java/com/uber/nullaway/ErrorProneCLIFlagsConfig.java b/nullaway/src/main/java/com/uber/nullaway/ErrorProneCLIFlagsConfig.java index 90110e5ce3..dd7436af16 100644 --- a/nullaway/src/main/java/com/uber/nullaway/ErrorProneCLIFlagsConfig.java +++ b/nullaway/src/main/java/com/uber/nullaway/ErrorProneCLIFlagsConfig.java @@ -37,7 +37,7 @@ import java.util.Optional; import java.util.Set; import java.util.regex.Pattern; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; /** * provides nullability configuration based on additional flags passed to ErrorProne via @@ -189,12 +189,12 @@ final class ErrorProneCLIFlagsConfig implements Config { private final Pattern unannotatedSubPackages; /** Source code in these classes will not be analyzed for nullability issues */ - @Nullable private final ImmutableSet sourceClassesToExclude; + private final @Nullable ImmutableSet sourceClassesToExclude; /** * these classes will be treated as unannotated (don't analyze *and* treat methods as unannotated) */ - @Nullable private final ImmutableSet unannotatedClasses; + private final @Nullable ImmutableSet unannotatedClasses; private final Pattern fieldAnnotPattern; private final boolean isExhaustiveOverride; @@ -214,7 +214,7 @@ final class ErrorProneCLIFlagsConfig implements Config { private final ImmutableSet initializerAnnotations; private final ImmutableSet externalInitAnnotations; private final ImmutableSet contractAnnotations; - @Nullable private final String castToNonNullMethod; + private final @Nullable String castToNonNullMethod; private final String autofixSuppressionComment; private final ImmutableSet skippedLibraryModels; private final ImmutableSet extraFuturesClasses; @@ -515,8 +515,7 @@ public boolean assertsEnabled() { } @Override - @Nullable - public String getCastToNonNullMethod() { + public @Nullable String getCastToNonNullMethod() { return castToNonNullMethod; } diff --git a/nullaway/src/main/java/com/uber/nullaway/NullAway.java b/nullaway/src/main/java/com/uber/nullaway/NullAway.java index db4d0331f8..4cd68978b2 100644 --- a/nullaway/src/main/java/com/uber/nullaway/NullAway.java +++ b/nullaway/src/main/java/com/uber/nullaway/NullAway.java @@ -110,7 +110,6 @@ import java.util.function.Predicate; import java.util.stream.Collectors; import java.util.stream.StreamSupport; -import javax.annotation.Nullable; import javax.inject.Inject; import javax.lang.model.element.AnnotationMirror; import javax.lang.model.element.Element; @@ -122,6 +121,7 @@ import org.checkerframework.nullaway.dataflow.cfg.node.MethodInvocationNode; import org.checkerframework.nullaway.javacutil.ElementUtils; import org.checkerframework.nullaway.javacutil.TreeUtils; +import org.jspecify.annotations.Nullable; /** * Checker for nullability errors. It assumes that any field, method parameter, or return type that @@ -2154,8 +2154,7 @@ private Set getSafeInitMethods( * @param state visitor state * @return element of safe init function if stmt invokes that function; null otherwise */ - @Nullable - private Element getInvokeOfSafeInitMethod( + private @Nullable Element getInvokeOfSafeInitMethod( StatementTree stmt, Symbol.ClassSymbol enclosingClassSymbol, VisitorState state) { Matcher invokeMatcher = (expressionTree, s) -> { diff --git a/nullaway/src/main/java/com/uber/nullaway/NullabilityUtil.java b/nullaway/src/main/java/com/uber/nullaway/NullabilityUtil.java index 6befea7b79..6092d46a55 100644 --- a/nullaway/src/main/java/com/uber/nullaway/NullabilityUtil.java +++ b/nullaway/src/main/java/com/uber/nullaway/NullabilityUtil.java @@ -51,11 +51,11 @@ import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; -import javax.annotation.Nullable; import javax.lang.model.element.AnnotationMirror; import javax.lang.model.element.AnnotationValue; import javax.lang.model.element.ExecutableElement; import org.checkerframework.nullaway.javacutil.AnnotationUtils; +import org.jspecify.annotations.Nullable; /** Helpful utility methods for nullability analysis. */ public class NullabilityUtil { @@ -102,8 +102,7 @@ public static boolean lambdaParamIsImplicitlyTyped(VariableTree lambdaParameter) * @return closest overridden ancestor method, or null if method does not override * anything */ - @Nullable - public static Symbol.MethodSymbol getClosestOverriddenMethod( + public static Symbol.@Nullable MethodSymbol getClosestOverriddenMethod( Symbol.MethodSymbol method, Types types) { // taken from Error Prone MethodOverrides check Symbol.ClassSymbol owner = method.enclClass(); @@ -135,8 +134,7 @@ public static Symbol.MethodSymbol getClosestOverriddenMethod( * @param others also stop and return in case of any of these tree kinds * @return the closest enclosing method / lambda */ - @Nullable - public static TreePath findEnclosingMethodOrLambdaOrInitializer( + public static @Nullable TreePath findEnclosingMethodOrLambdaOrInitializer( TreePath path, ImmutableSet others) { TreePath curPath = path.getParentPath(); while (curPath != null) { @@ -169,8 +167,7 @@ public static TreePath findEnclosingMethodOrLambdaOrInitializer( * @param path the tree path * @return the closest enclosing method / lambda */ - @Nullable - public static TreePath findEnclosingMethodOrLambdaOrInitializer(TreePath path) { + public static @Nullable TreePath findEnclosingMethodOrLambdaOrInitializer(TreePath path) { return findEnclosingMethodOrLambdaOrInitializer(path, ImmutableSet.of()); } diff --git a/nullaway/src/main/java/com/uber/nullaway/dataflow/AccessPath.java b/nullaway/src/main/java/com/uber/nullaway/dataflow/AccessPath.java index 436547b2f2..78fe3d8f61 100644 --- a/nullaway/src/main/java/com/uber/nullaway/dataflow/AccessPath.java +++ b/nullaway/src/main/java/com/uber/nullaway/dataflow/AccessPath.java @@ -41,7 +41,6 @@ import java.util.List; import java.util.Objects; import java.util.Set; -import javax.annotation.Nullable; import javax.lang.model.element.Element; import javax.lang.model.element.ElementKind; import javax.lang.model.element.Modifier; @@ -62,6 +61,7 @@ import org.checkerframework.nullaway.dataflow.cfg.node.VariableDeclarationNode; import org.checkerframework.nullaway.dataflow.cfg.node.WideningConversionNode; import org.checkerframework.nullaway.javacutil.TreeUtils; +import org.jspecify.annotations.Nullable; /** * Represents an extended notion of an access path, which we track for nullness. @@ -103,14 +103,14 @@ public static String immutableFieldNameAsConstantArgument(String fieldFQN) { } /** Root of the access path. If {@code null}, the root is the receiver argument */ - @Nullable private final Element root; + private final @Nullable Element root; private final ImmutableList elements; /** * if present, the argument to the map get() method call that is the final element of this path */ - @Nullable private final MapKey mapGetArg; + private final @Nullable MapKey mapGetArg; private AccessPath(@Nullable Element root, ImmutableList elements) { this(root, elements, null); @@ -154,13 +154,11 @@ static AccessPath fromVarDecl(VariableDeclarationNode node) { * AccessPath.AccessPathContext}). * @return access path for the field access, or null if it cannot be represented */ - @Nullable - static AccessPath fromFieldAccess(FieldAccessNode node, AccessPathContext apContext) { + static @Nullable AccessPath fromFieldAccess(FieldAccessNode node, AccessPathContext apContext) { return fromNodeAndContext(node, apContext); } - @Nullable - private static AccessPath fromNodeAndContext(Node node, AccessPathContext apContext) { + private static @Nullable AccessPath fromNodeAndContext(Node node, AccessPathContext apContext) { return buildAccessPathRecursive(node, new ArrayDeque<>(), apContext, null); } @@ -172,8 +170,7 @@ private static AccessPath fromNodeAndContext(Node node, AccessPathContext apCont * AccessPath.AccessPathContext}). * @return access path for the method call, or null if it cannot be represented */ - @Nullable - static AccessPath fromMethodCall( + static @Nullable AccessPath fromMethodCall( MethodInvocationNode node, VisitorState state, AccessPathContext apContext) { if (isMapGet(ASTHelpers.getSymbol(node.getTree()), state)) { return fromMapGetCall(node, state, apContext); @@ -181,8 +178,7 @@ static AccessPath fromMethodCall( return fromVanillaMethodCall(node, apContext); } - @Nullable - private static AccessPath fromVanillaMethodCall( + private static @Nullable AccessPath fromVanillaMethodCall( MethodInvocationNode node, AccessPathContext apContext) { return fromNodeAndContext(node, apContext); } @@ -204,14 +200,12 @@ static AccessPath switchRoot(AccessPath origAP, Element newRoot) { * AccessPath.AccessPathContext}). * @return the {@link AccessPath} {@code base.element} */ - @Nullable - public static AccessPath fromBaseAndElement( + public static @Nullable AccessPath fromBaseAndElement( Node base, Element element, AccessPathContext apContext) { return fromNodeElementAndContext(base, new FieldOrMethodCallElement(element), apContext); } - @Nullable - private static AccessPath fromNodeElementAndContext( + private static @Nullable AccessPath fromNodeElementAndContext( Node base, AccessPathElement apElement, AccessPathContext apContext) { ArrayDeque elements = new ArrayDeque<>(); elements.push(apElement); @@ -236,8 +230,7 @@ private static AccessPath fromNodeElementAndContext( * AccessPath.AccessPathContext}). * @return the {@link AccessPath} {@code base.method(CONS)} */ - @Nullable - public static AccessPath fromBaseMethodAndConstantArgs( + public static @Nullable AccessPath fromBaseMethodAndConstantArgs( Node base, Element method, List constantArguments, AccessPathContext apContext) { return fromNodeElementAndContext( base, new FieldOrMethodCallElement(method, constantArguments), apContext); @@ -253,8 +246,7 @@ public static AccessPath fromBaseMethodAndConstantArgs( * @return an AccessPath representing invoking get() on the same type of map as from node, passing * the same first argument as is passed in node */ - @Nullable - public static AccessPath getForMapInvocation( + public static @Nullable AccessPath getForMapInvocation( MethodInvocationNode node, VisitorState state, AccessPathContext apContext) { // For the receiver type for get, use the declared type of the receiver of the containsKey() // call. Note that this may differ from the containing class of the resolved containsKey() @@ -270,8 +262,7 @@ private static Node stripCasts(Node node) { return node; } - @Nullable - private static MapKey argumentToMapKeySpecifier( + private static @Nullable MapKey argumentToMapKeySpecifier( Node argument, VisitorState state, AccessPathContext apContext) { // Required to have Node type match Tree type in some instances. if (argument instanceof WideningConversionNode) { @@ -303,8 +294,7 @@ && castToNonNull(receiver.getTree()).getKind().equals(Tree.Kind.IDENTIFIER) } } - @Nullable - private static AccessPath fromMapGetCall( + private static @Nullable AccessPath fromMapGetCall( MethodInvocationNode node, VisitorState state, AccessPathContext apContext) { Node argument = node.getArgument(0); MapKey mapKey = argumentToMapKeySpecifier(argument, state, apContext); @@ -326,8 +316,7 @@ private static AccessPath fromMapGetCall( * AccessPath.AccessPathContext}). * @return corresponding AccessPath if it exists; null otherwise */ - @Nullable - public static AccessPath getAccessPathForNode( + public static @Nullable AccessPath getAccessPathForNode( Node node, VisitorState state, AccessPathContext apContext) { if (node instanceof LocalVariableNode) { return fromLocal((LocalVariableNode) node); @@ -342,13 +331,12 @@ public static AccessPath getAccessPathForNode( } } - @Nullable - private static AccessPath fromArrayAccess(ArrayAccessNode node, AccessPathContext apContext) { + private static @Nullable AccessPath fromArrayAccess( + ArrayAccessNode node, AccessPathContext apContext) { return fromNodeAndContext(node, apContext); } - @Nullable - private static Element getElementFromArrayNode(Node arrayNode) { + private static @Nullable Element getElementFromArrayNode(Node arrayNode) { if (arrayNode instanceof LocalVariableNode) { return ((LocalVariableNode) arrayNode).getElement(); } else if (arrayNode instanceof FieldAccessNode) { @@ -389,8 +377,7 @@ private static boolean isBoxingMethod(Symbol.MethodSymbol methodSymbol) { * @param mapKey map key to be used as the map-get argument, or {@code null} if there is no key * @return the final access path */ - @Nullable - private static AccessPath buildAccessPathRecursive( + private static @Nullable AccessPath buildAccessPathRecursive( Node node, ArrayDeque elements, AccessPathContext apContext, @@ -551,8 +538,7 @@ && isBoxingMethod(ASTHelpers.getSymbol(methodInvocationTree))) { * @return access path representing the get call, or {@code null} if the map node cannot be * represented with an access path */ - @Nullable - public static AccessPath mapWithIteratorContentsKey( + public static @Nullable AccessPath mapWithIteratorContentsKey( Node mapNode, LocalVariableNode iterVar, AccessPathContext apContext) { IteratorContentsKey iterContentsKey = new IteratorContentsKey((VariableElement) iterVar.getElement()); @@ -594,8 +580,7 @@ public int hashCode() { * Returns the root element of the access path. If the root is the receiver argument, returns * {@code null}. */ - @Nullable - public Element getRoot() { + public @Nullable Element getRoot() { return root; } @@ -603,8 +588,7 @@ public ImmutableList getElements() { return elements; } - @Nullable - public MapKey getMapGetArg() { + public @Nullable MapKey getMapGetArg() { return mapGetArg; } @@ -759,7 +743,7 @@ public static Builder builder() { /** class for building up instances of the AccessPathContext. */ public static final class Builder { - @Nullable private ImmutableSet immutableTypes; + private @Nullable ImmutableSet immutableTypes; Builder() {} diff --git a/nullaway/src/main/java/com/uber/nullaway/dataflow/AccessPathNullnessAnalysis.java b/nullaway/src/main/java/com/uber/nullaway/dataflow/AccessPathNullnessAnalysis.java index 2e1054a8e0..8c2dae9151 100644 --- a/nullaway/src/main/java/com/uber/nullaway/dataflow/AccessPathNullnessAnalysis.java +++ b/nullaway/src/main/java/com/uber/nullaway/dataflow/AccessPathNullnessAnalysis.java @@ -34,7 +34,6 @@ import java.util.LinkedHashSet; import java.util.Set; import java.util.function.Predicate; -import javax.annotation.Nullable; import javax.lang.model.element.Element; import javax.lang.model.element.ElementKind; import javax.lang.model.element.Modifier; @@ -43,6 +42,7 @@ import org.checkerframework.nullaway.dataflow.cfg.node.MethodAccessNode; import org.checkerframework.nullaway.dataflow.cfg.node.MethodInvocationNode; import org.checkerframework.nullaway.dataflow.cfg.node.Node; +import org.jspecify.annotations.Nullable; /** * API to our nullness dataflow analysis for access paths. @@ -60,7 +60,7 @@ public final class AccessPathNullnessAnalysis { private final DataFlow dataFlow; - @Nullable private AccessPathNullnessPropagation contractNullnessPropagation; + private @Nullable AccessPathNullnessPropagation contractNullnessPropagation; // Use #instance to instantiate private AccessPathNullnessAnalysis( @@ -126,8 +126,7 @@ public static AccessPathNullnessAnalysis instance( * @param context Javac context * @return nullness info for expression, from dataflow */ - @Nullable - public Nullness getNullness(TreePath exprPath, Context context) { + public @Nullable Nullness getNullness(TreePath exprPath, Context context) { return dataFlow.expressionDataflow(exprPath, context, nullnessPropagation); } @@ -139,8 +138,7 @@ public Nullness getNullness(TreePath exprPath, Context context) { * @param context Javac context * @return nullness info for expression, from dataflow in case contract check */ - @Nullable - public Nullness getNullnessForContractDataflow(TreePath exprPath, Context context) { + public @Nullable Nullness getNullnessForContractDataflow(TreePath exprPath, Context context) { return dataFlow.expressionDataflow( exprPath, context, castToNonNull(contractNullnessPropagation)); } @@ -343,8 +341,7 @@ private Set getNonnullStaticFields(NullnessStore nullnessResult) { * @param context Javac context * @return the final NullnessStore on exit from the method. */ - @Nullable - public NullnessStore forceRunOnMethod(TreePath methodPath, Context context) { + public @Nullable NullnessStore forceRunOnMethod(TreePath methodPath, Context context) { return dataFlow.finalResult(methodPath, context, nullnessPropagation); } diff --git a/nullaway/src/main/java/com/uber/nullaway/dataflow/AccessPathNullnessPropagation.java b/nullaway/src/main/java/com/uber/nullaway/dataflow/AccessPathNullnessPropagation.java index 7e37237a60..49dca06fac 100644 --- a/nullaway/src/main/java/com/uber/nullaway/dataflow/AccessPathNullnessPropagation.java +++ b/nullaway/src/main/java/com/uber/nullaway/dataflow/AccessPathNullnessPropagation.java @@ -47,7 +47,6 @@ import java.util.Map; import java.util.function.Predicate; import javax.annotation.CheckReturnValue; -import javax.annotation.Nullable; import javax.lang.model.element.ElementKind; import javax.lang.model.element.VariableElement; import javax.lang.model.type.TypeKind; @@ -130,6 +129,7 @@ import org.checkerframework.nullaway.dataflow.cfg.node.UnsignedRightShiftNode; import org.checkerframework.nullaway.dataflow.cfg.node.VariableDeclarationNode; import org.checkerframework.nullaway.dataflow.cfg.node.WideningConversionNode; +import org.jspecify.annotations.Nullable; /** * transfer functions for our access path nullness dataflow analysis @@ -613,8 +613,7 @@ && isEnhancedForIteratorVariable((LocalVariableNode) receiver)) { * of the form {@code e'.keySet()}, returns the {@code Node} for {@code e'}. Otherwise, returns * {@code null}. */ - @Nullable - private Node getMapNodeForKeySetIteratorCall(MethodInvocationNode invocationNode) { + private @Nullable Node getMapNodeForKeySetIteratorCall(MethodInvocationNode invocationNode) { Node receiver = invocationNode.getTarget().getReceiver(); if (receiver instanceof MethodInvocationNode) { MethodInvocationNode baseInvocation = (MethodInvocationNode) receiver; @@ -762,7 +761,7 @@ public TransferResult visitFieldAccess( return updateRegularStore(nullness, input, updates); } - @Nullable private CodeAnnotationInfo codeAnnotationInfo; + private @Nullable CodeAnnotationInfo codeAnnotationInfo; private CodeAnnotationInfo getCodeAnnotationInfo(VisitorState state) { if (codeAnnotationInfo == null) { diff --git a/nullaway/src/main/java/com/uber/nullaway/dataflow/CoreNullnessStoreInitializer.java b/nullaway/src/main/java/com/uber/nullaway/dataflow/CoreNullnessStoreInitializer.java index a22e718fb9..0726cd87f5 100644 --- a/nullaway/src/main/java/com/uber/nullaway/dataflow/CoreNullnessStoreInitializer.java +++ b/nullaway/src/main/java/com/uber/nullaway/dataflow/CoreNullnessStoreInitializer.java @@ -18,10 +18,10 @@ import com.uber.nullaway.handlers.Handler; import java.util.List; import java.util.Objects; -import javax.annotation.Nullable; import javax.lang.model.element.Element; import org.checkerframework.nullaway.dataflow.cfg.UnderlyingAST; import org.checkerframework.nullaway.dataflow.cfg.node.LocalVariableNode; +import org.jspecify.annotations.Nullable; class CoreNullnessStoreInitializer extends NullnessStoreInitializer { @@ -144,7 +144,7 @@ private static NullnessStore lambdaInitialStore( return result.build(); } - @Nullable private CodeAnnotationInfo codeAnnotationInfo; + private @Nullable CodeAnnotationInfo codeAnnotationInfo; private CodeAnnotationInfo getCodeAnnotationInfo(Context context) { if (codeAnnotationInfo == null) { diff --git a/nullaway/src/main/java/com/uber/nullaway/dataflow/DataFlow.java b/nullaway/src/main/java/com/uber/nullaway/dataflow/DataFlow.java index 07b6070a81..d7579e114e 100644 --- a/nullaway/src/main/java/com/uber/nullaway/dataflow/DataFlow.java +++ b/nullaway/src/main/java/com/uber/nullaway/dataflow/DataFlow.java @@ -40,7 +40,6 @@ import com.uber.nullaway.NullabilityUtil; import com.uber.nullaway.dataflow.cfg.NullAwayCFGBuilder; import com.uber.nullaway.handlers.Handler; -import javax.annotation.Nullable; import javax.annotation.processing.ProcessingEnvironment; import org.checkerframework.nullaway.dataflow.analysis.AbstractValue; import org.checkerframework.nullaway.dataflow.analysis.Analysis; @@ -51,6 +50,7 @@ import org.checkerframework.nullaway.dataflow.analysis.TransferFunction; import org.checkerframework.nullaway.dataflow.cfg.ControlFlowGraph; import org.checkerframework.nullaway.dataflow.cfg.UnderlyingAST; +import org.jspecify.annotations.Nullable; /** * Provides a wrapper around {@link org.checkerframework.nullaway.dataflow.analysis.Analysis}. @@ -202,9 +202,8 @@ ControlFlowGraph getControlFlowGraph(TreePath path, Context context, T transfer) * @param transfer function type * @return dataflow value for expression */ - @Nullable public , S extends Store, T extends ForwardTransferFunction> - A expressionDataflow(TreePath exprPath, Context context, T transfer) { + @Nullable A expressionDataflow(TreePath exprPath, Context context, T transfer) { AnalysisResult analysisResult = resultForExpr(exprPath, context, transfer); return analysisResult == null ? null : analysisResult.getValue(exprPath.getLeaf()); } @@ -220,9 +219,8 @@ A expressionDataflow(TreePath exprPath, Context context, T transfer) { * @param transfer function type * @return dataflow result at exit of method */ - @Nullable public , S extends Store, T extends ForwardTransferFunction> - S finalResult(TreePath path, Context context, T transfer) { + @Nullable S finalResult(TreePath path, Context context, T transfer) { Tree leaf = path.getLeaf(); Preconditions.checkArgument( leaf instanceof MethodTree @@ -235,9 +233,8 @@ S finalResult(TreePath path, Context context, T transfer) { return dataflow(path, context, transfer).getAnalysis().getRegularExitStore(); } - @Nullable public , S extends Store, T extends ForwardTransferFunction> - S resultBeforeExpr(TreePath exprPath, Context context, T transfer) { + @Nullable S resultBeforeExpr(TreePath exprPath, Context context, T transfer) { AnalysisResult analysisResult = resultForExpr(exprPath, context, transfer); return analysisResult == null ? null : analysisResult.getStoreBefore(exprPath.getLeaf()); } @@ -247,16 +244,14 @@ S resultBeforeExpr(TreePath exprPath, Context context, T transfer) { * Tree in a method. A bit riskier to use since we don't check that there is a corresponding CFG * node to the Tree; use with care. */ - @Nullable public , S extends Store, T extends ForwardTransferFunction> - S resultBefore(TreePath exprPath, Context context, T transfer) { + @Nullable S resultBefore(TreePath exprPath, Context context, T transfer) { AnalysisResult analysisResult = resultFor(exprPath, context, transfer); return analysisResult == null ? null : analysisResult.getStoreBefore(exprPath.getLeaf()); } - @Nullable , S extends Store, T extends ForwardTransferFunction> - AnalysisResult resultForExpr(TreePath exprPath, Context context, T transfer) { + @Nullable AnalysisResult resultForExpr(TreePath exprPath, Context context, T transfer) { Tree leaf = exprPath.getLeaf(); Preconditions.checkArgument( leaf instanceof ExpressionTree, @@ -266,9 +261,8 @@ AnalysisResult resultForExpr(TreePath exprPath, Context context, T transfe return resultFor(exprPath, context, transfer); } - private @Nullable < - A extends AbstractValue, S extends Store, T extends ForwardTransferFunction> - AnalysisResult resultFor(TreePath exprPath, Context context, T transfer) { + private , S extends Store, T extends ForwardTransferFunction> + @Nullable AnalysisResult resultFor(TreePath exprPath, Context context, T transfer) { TreePath enclosingPath = NullabilityUtil.findEnclosingMethodOrLambdaOrInitializer(exprPath); if (enclosingPath == null) { throw new RuntimeException("expression is not inside a method, lambda or initializer block!"); diff --git a/nullaway/src/main/java/com/uber/nullaway/dataflow/EnclosingEnvironmentNullness.java b/nullaway/src/main/java/com/uber/nullaway/dataflow/EnclosingEnvironmentNullness.java index 60669f75de..8f8cfb0931 100644 --- a/nullaway/src/main/java/com/uber/nullaway/dataflow/EnclosingEnvironmentNullness.java +++ b/nullaway/src/main/java/com/uber/nullaway/dataflow/EnclosingEnvironmentNullness.java @@ -8,8 +8,8 @@ import com.sun.tools.javac.util.Context; import java.util.LinkedHashMap; import java.util.Map; -import javax.annotation.Nullable; import javax.lang.model.element.NestingKind; +import org.jspecify.annotations.Nullable; /** * Stores info on nullness of local variables in enclosing environments, used when performing @@ -37,8 +37,7 @@ public void addEnvironmentMapping(Tree t, NullnessStore s) { environmentNullness.put(t, s); } - @Nullable - public NullnessStore getEnvironmentMapping(Tree t) { + public @Nullable NullnessStore getEnvironmentMapping(Tree t) { Preconditions.checkArgument(isValidTreeType(t)); return environmentNullness.get(t); } diff --git a/nullaway/src/main/java/com/uber/nullaway/dataflow/FieldOrMethodCallElement.java b/nullaway/src/main/java/com/uber/nullaway/dataflow/FieldOrMethodCallElement.java index 8b519a0fa5..2ff9ca190d 100644 --- a/nullaway/src/main/java/com/uber/nullaway/dataflow/FieldOrMethodCallElement.java +++ b/nullaway/src/main/java/com/uber/nullaway/dataflow/FieldOrMethodCallElement.java @@ -4,8 +4,8 @@ import java.util.Arrays; import java.util.List; import java.util.Objects; -import javax.annotation.Nullable; import javax.lang.model.element.Element; +import org.jspecify.annotations.Nullable; /** * Represents a (non-root) field or method call element of an AccessPath. @@ -16,7 +16,7 @@ */ public class FieldOrMethodCallElement implements AccessPathElement { private final Element javaElement; - @Nullable private final ImmutableList constantArguments; + private final @Nullable ImmutableList constantArguments; public FieldOrMethodCallElement(Element javaElement, List constantArguments) { this.javaElement = javaElement; diff --git a/nullaway/src/main/java/com/uber/nullaway/dataflow/NullnessStore.java b/nullaway/src/main/java/com/uber/nullaway/dataflow/NullnessStore.java index 732ed01920..8225d5c143 100644 --- a/nullaway/src/main/java/com/uber/nullaway/dataflow/NullnessStore.java +++ b/nullaway/src/main/java/com/uber/nullaway/dataflow/NullnessStore.java @@ -29,7 +29,6 @@ import java.util.Set; import java.util.function.Predicate; import java.util.stream.Collectors; -import javax.annotation.Nullable; import javax.lang.model.element.Element; import org.checkerframework.nullaway.dataflow.analysis.Store; import org.checkerframework.nullaway.dataflow.cfg.node.FieldAccessNode; @@ -37,6 +36,7 @@ import org.checkerframework.nullaway.dataflow.cfg.node.MethodInvocationNode; import org.checkerframework.nullaway.dataflow.cfg.visualize.CFGVisualizer; import org.checkerframework.nullaway.dataflow.expression.JavaExpression; +import org.jspecify.annotations.Nullable; /** * Highly based on {@link com.google.errorprone.dataflow.LocalStore}, but for {@link AccessPath}s. @@ -127,8 +127,7 @@ public Set getAccessPathsWithValue(Nullness value) { * IteratorContentsKey} whose variable is {@code iteratorVar}, returns {@code p}. Otherwise, * returns {@code null}. */ - @Nullable - public AccessPath getMapGetIteratorContentsAccessPath(LocalVariableNode iteratorVar) { + public @Nullable AccessPath getMapGetIteratorContentsAccessPath(LocalVariableNode iteratorVar) { for (AccessPath accessPath : contents.keySet()) { MapKey mapGetArg = accessPath.getMapGetArg(); if (mapGetArg instanceof IteratorContentsKey) { diff --git a/nullaway/src/main/java/com/uber/nullaway/dataflow/NullnessStoreInitializer.java b/nullaway/src/main/java/com/uber/nullaway/dataflow/NullnessStoreInitializer.java index c654621933..68fb8fc246 100644 --- a/nullaway/src/main/java/com/uber/nullaway/dataflow/NullnessStoreInitializer.java +++ b/nullaway/src/main/java/com/uber/nullaway/dataflow/NullnessStoreInitializer.java @@ -11,10 +11,10 @@ import com.uber.nullaway.handlers.Handler; import java.util.List; import java.util.Objects; -import javax.annotation.Nullable; import javax.lang.model.element.NestingKind; import org.checkerframework.nullaway.dataflow.cfg.UnderlyingAST; import org.checkerframework.nullaway.dataflow.cfg.node.LocalVariableNode; +import org.jspecify.annotations.Nullable; /** * An abstract class that allows overriding initialization of nullness store in dataflow. Currently, @@ -60,8 +60,7 @@ protected static NullnessStore getEnvNullnessStoreForClass(ClassTree classTree, return envStore; } - @Nullable - private static ClassTree findEnclosingLocalOrAnonymousClass( + private static @Nullable ClassTree findEnclosingLocalOrAnonymousClass( ClassTree classTree, Context context) { Symbol.ClassSymbol symbol = ASTHelpers.getSymbol(classTree); // we need this while loop since we can have a NestingKind.NESTED class (i.e., a nested diff --git a/nullaway/src/main/java/com/uber/nullaway/fixserialization/FixSerializationConfig.java b/nullaway/src/main/java/com/uber/nullaway/fixserialization/FixSerializationConfig.java index 769c9eac0a..cc5b446324 100644 --- a/nullaway/src/main/java/com/uber/nullaway/fixserialization/FixSerializationConfig.java +++ b/nullaway/src/main/java/com/uber/nullaway/fixserialization/FixSerializationConfig.java @@ -30,10 +30,10 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; -import javax.annotation.Nullable; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; +import org.jspecify.annotations.Nullable; import org.w3c.dom.Document; import org.xml.sax.SAXException; @@ -64,9 +64,9 @@ public class FixSerializationConfig { public final boolean fieldInitInfoEnabled; /** The directory where all files generated/read by Fix Serialization package resides. */ - @Nullable public final String outputDirectory; + public final @Nullable String outputDirectory; - @Nullable private final Serializer serializer; + private final @Nullable Serializer serializer; /** Default Constructor, all features are disabled with this config. */ public FixSerializationConfig() { @@ -152,8 +152,7 @@ private SerializationAdapter initializeAdapter(int version) { } } - @Nullable - public Serializer getSerializer() { + public @Nullable Serializer getSerializer() { return serializer; } @@ -163,7 +162,7 @@ public static class Builder { private boolean suggestEnabled; private boolean suggestEnclosing; private boolean fieldInitInfo; - @Nullable private String outputDir; + private @Nullable String outputDir; public Builder() { suggestEnabled = false; diff --git a/nullaway/src/main/java/com/uber/nullaway/fixserialization/SerializationService.java b/nullaway/src/main/java/com/uber/nullaway/fixserialization/SerializationService.java index eefe7b6f11..e85fa6799f 100644 --- a/nullaway/src/main/java/com/uber/nullaway/fixserialization/SerializationService.java +++ b/nullaway/src/main/java/com/uber/nullaway/fixserialization/SerializationService.java @@ -39,7 +39,7 @@ import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; /** A facade class to interact with fix serialization package. */ public class SerializationService { diff --git a/nullaway/src/main/java/com/uber/nullaway/fixserialization/Serializer.java b/nullaway/src/main/java/com/uber/nullaway/fixserialization/Serializer.java index 3adb94bbb7..055db9065a 100644 --- a/nullaway/src/main/java/com/uber/nullaway/fixserialization/Serializer.java +++ b/nullaway/src/main/java/com/uber/nullaway/fixserialization/Serializer.java @@ -37,7 +37,7 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; /** * Serializer class where all generated files in Fix Serialization package is created through APIs @@ -181,8 +181,7 @@ private void appendToFile(String row, Path path) { * @param uri Given uri. * @return Real path for the give uri. */ - @Nullable - public static Path pathToSourceFileFromURI(@Nullable URI uri) { + public static @Nullable Path pathToSourceFileFromURI(@Nullable URI uri) { if (uri == null) { return null; } diff --git a/nullaway/src/main/java/com/uber/nullaway/fixserialization/XMLUtil.java b/nullaway/src/main/java/com/uber/nullaway/fixserialization/XMLUtil.java index 9c0154a812..c37fa1e76f 100644 --- a/nullaway/src/main/java/com/uber/nullaway/fixserialization/XMLUtil.java +++ b/nullaway/src/main/java/com/uber/nullaway/fixserialization/XMLUtil.java @@ -23,7 +23,6 @@ package com.uber.nullaway.fixserialization; import java.io.File; -import javax.annotation.Nullable; import javax.xml.XMLConstants; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; @@ -38,6 +37,7 @@ import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; import org.jetbrains.annotations.Contract; +import org.jspecify.annotations.Nullable; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; @@ -170,7 +170,7 @@ public static void writeInXMLFormat(FixSerializationConfig config, String path) /** Helper class for setting default values when the key is not found. */ static class DefaultXMLValueProvider { - @Nullable final Object value; + final @Nullable Object value; final Class klass; DefaultXMLValueProvider(@Nullable Object value, Class klass) { @@ -199,8 +199,7 @@ static class DefaultXMLValueProvider { } @Contract("!null -> !null") - @Nullable - T orElse(@Nullable T other) { + @Nullable T orElse(@Nullable T other) { return value == null ? other : klass.cast(this.value); } } diff --git a/nullaway/src/main/java/com/uber/nullaway/fixserialization/location/AbstractSymbolLocation.java b/nullaway/src/main/java/com/uber/nullaway/fixserialization/location/AbstractSymbolLocation.java index 319c636e48..4b2adbdba9 100644 --- a/nullaway/src/main/java/com/uber/nullaway/fixserialization/location/AbstractSymbolLocation.java +++ b/nullaway/src/main/java/com/uber/nullaway/fixserialization/location/AbstractSymbolLocation.java @@ -30,8 +30,8 @@ import com.uber.nullaway.fixserialization.Serializer; import java.net.URI; import java.nio.file.Path; -import javax.annotation.Nullable; import javax.lang.model.element.ElementKind; +import org.jspecify.annotations.Nullable; /** abstract base class for {@link SymbolLocation}. */ public abstract class AbstractSymbolLocation implements SymbolLocation { @@ -40,7 +40,7 @@ public abstract class AbstractSymbolLocation implements SymbolLocation { protected final ElementKind type; /** Path of the file containing the symbol, if available. */ - @Nullable protected final Path path; + protected final @Nullable Path path; /** Enclosing class of the symbol. */ protected final Symbol.ClassSymbol enclosingClass; diff --git a/nullaway/src/main/java/com/uber/nullaway/fixserialization/out/ClassAndMemberInfo.java b/nullaway/src/main/java/com/uber/nullaway/fixserialization/out/ClassAndMemberInfo.java index 258830dad7..727df5b68c 100644 --- a/nullaway/src/main/java/com/uber/nullaway/fixserialization/out/ClassAndMemberInfo.java +++ b/nullaway/src/main/java/com/uber/nullaway/fixserialization/out/ClassAndMemberInfo.java @@ -30,19 +30,19 @@ import com.sun.source.tree.VariableTree; import com.sun.source.util.TreePath; import com.sun.tools.javac.code.Symbol; -import javax.annotation.Nullable; import javax.lang.model.element.ElementKind; +import org.jspecify.annotations.Nullable; /** Class and member corresponding to a program point at which an error / fix was reported. */ public class ClassAndMemberInfo { /** Path to the program point of the reported error / fix */ - @Nullable public TreePath path; + public @Nullable TreePath path; // Finding values for these properties is costly and are not needed by default, hence, they are // not final and are only initialized at request. - @Nullable private Symbol member; + private @Nullable Symbol member; - @Nullable private Symbol.ClassSymbol clazz; + private Symbol.@Nullable ClassSymbol clazz; public ClassAndMemberInfo(TreePath path) { Preconditions.checkNotNull(path); @@ -125,13 +125,11 @@ public void findValues() { } } - @Nullable - public Symbol getMember() { + public @Nullable Symbol getMember() { return member; } - @Nullable - public Symbol.ClassSymbol getClazz() { + public Symbol.@Nullable ClassSymbol getClazz() { return clazz; } } diff --git a/nullaway/src/main/java/com/uber/nullaway/fixserialization/out/ErrorInfo.java b/nullaway/src/main/java/com/uber/nullaway/fixserialization/out/ErrorInfo.java index eb4b21fd57..5dda09d43c 100644 --- a/nullaway/src/main/java/com/uber/nullaway/fixserialization/out/ErrorInfo.java +++ b/nullaway/src/main/java/com/uber/nullaway/fixserialization/out/ErrorInfo.java @@ -32,7 +32,7 @@ import com.uber.nullaway.ErrorMessage; import com.uber.nullaway.fixserialization.Serializer; import java.nio.file.Path; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; /** Stores information regarding an error which will be reported by NullAway. */ public class ErrorInfo { @@ -44,7 +44,7 @@ public class ErrorInfo { * if non-null, this error involved a pseudo-assignment of a @Nullable expression into a @NonNull * target, and this field is the Symbol for that target. */ - @Nullable private final Symbol nonnullTarget; + private final @Nullable Symbol nonnullTarget; /** * In cases where {@link ErrorInfo#nonnullTarget} is {@code null}, we serialize this value at its @@ -57,7 +57,7 @@ public class ErrorInfo { private final int offset; /** Path to the containing source file where this error is reported. */ - @Nullable private final Path path; + private final @Nullable Path path; public ErrorInfo( TreePath path, Tree errorTree, ErrorMessage errorMessage, @Nullable Symbol nonnullTarget) { @@ -88,8 +88,7 @@ public ErrorMessage getErrorMessage() { * * @return Enclosing region member. Returns {@code null} if the values are not computed yet. */ - @Nullable - public Symbol getRegionMember() { + public @Nullable Symbol getRegionMember() { return classAndMemberInfo.getMember(); } @@ -98,8 +97,7 @@ public Symbol getRegionMember() { * * @return Enclosing region class. Returns {@code null} if the values are not computed yet. */ - @Nullable - public Symbol getRegionClass() { + public @Nullable Symbol getRegionClass() { return classAndMemberInfo.getClazz(); } @@ -110,8 +108,7 @@ public Symbol getRegionClass() { * * @return The symbol of the {@code @Nonnull} element if exists, and {@code null} otherwise. */ - @Nullable - public Symbol getNonnullTarget() { + public @Nullable Symbol getNonnullTarget() { return nonnullTarget; } @@ -129,8 +126,7 @@ public int getOffset() { * * @return Path to the containing source file where this error is reported. */ - @Nullable - public Path getPath() { + public @Nullable Path getPath() { return path; } diff --git a/nullaway/src/main/java/com/uber/nullaway/generics/GenericsChecks.java b/nullaway/src/main/java/com/uber/nullaway/generics/GenericsChecks.java index cac2ac7bfc..949e9e517b 100644 --- a/nullaway/src/main/java/com/uber/nullaway/generics/GenericsChecks.java +++ b/nullaway/src/main/java/com/uber/nullaway/generics/GenericsChecks.java @@ -35,10 +35,10 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import javax.annotation.Nullable; import javax.lang.model.type.ExecutableType; import javax.lang.model.type.TypeKind; import javax.lang.model.type.TypeVariable; +import org.jspecify.annotations.Nullable; /** Methods for performing checks related to generic types and nullability. */ public final class GenericsChecks { @@ -255,8 +255,7 @@ private static void reportInvalidOverridingMethodParamTypeError( * @param state the visitor state * @return Type of the tree with preserved annotations. */ - @Nullable - private static Type getTreeType(Tree tree, VisitorState state) { + private static @Nullable Type getTreeType(Tree tree, VisitorState state) { if (tree instanceof NewClassTree && ((NewClassTree) tree).getIdentifier() instanceof ParameterizedTypeTree) { ParameterizedTypeTree paramTypedTree = @@ -476,8 +475,7 @@ public static void checkTypeParameterNullnessForConditionalExpression( } } - @Nullable - private static Type getConditionalExpressionType( + private static @Nullable Type getConditionalExpressionType( ConditionalExpressionTree tree, VisitorState state) { // hack: sometimes array nullability doesn't get computed correctly for a conditional expression // on the RHS of an assignment. So, look at the type of the assignment tree. @@ -616,8 +614,7 @@ public static Nullness getGenericMethodReturnTypeNullness( * @param state the visitor state * @return the type for {@code symbol} */ - @Nullable - private static Type getTypeForSymbol(Symbol symbol, VisitorState state) { + private static @Nullable Type getTypeForSymbol(Symbol symbol, VisitorState state) { if (symbol.isAnonymous()) { // For anonymous classes, symbol.type does not contain annotations on generic type parameters. // So, we get a correct type from the enclosing NewClassTree. diff --git a/nullaway/src/main/java/com/uber/nullaway/handlers/AbstractFieldContractHandler.java b/nullaway/src/main/java/com/uber/nullaway/handlers/AbstractFieldContractHandler.java index 831d633359..3d590f7c61 100644 --- a/nullaway/src/main/java/com/uber/nullaway/handlers/AbstractFieldContractHandler.java +++ b/nullaway/src/main/java/com/uber/nullaway/handlers/AbstractFieldContractHandler.java @@ -36,10 +36,10 @@ import com.uber.nullaway.handlers.contract.ContractUtils; import java.util.Collections; import java.util.Set; -import javax.annotation.Nullable; import javax.lang.model.element.Element; import javax.lang.model.element.Modifier; import javax.lang.model.element.VariableElement; +import org.jspecify.annotations.Nullable; /** * Abstract base class for handlers that process pre- and post-condition annotations for fields. diff --git a/nullaway/src/main/java/com/uber/nullaway/handlers/ApacheThriftIsSetHandler.java b/nullaway/src/main/java/com/uber/nullaway/handlers/ApacheThriftIsSetHandler.java index 802cedd447..ee12abe16a 100644 --- a/nullaway/src/main/java/com/uber/nullaway/handlers/ApacheThriftIsSetHandler.java +++ b/nullaway/src/main/java/com/uber/nullaway/handlers/ApacheThriftIsSetHandler.java @@ -37,11 +37,11 @@ import com.uber.nullaway.dataflow.AccessPathNullnessPropagation; import java.util.Objects; import java.util.Optional; -import javax.annotation.Nullable; import javax.lang.model.element.Element; import javax.lang.model.element.ElementKind; import org.checkerframework.nullaway.dataflow.cfg.node.MethodInvocationNode; import org.checkerframework.nullaway.dataflow.cfg.node.Node; +import org.jspecify.annotations.Nullable; /** * Handler to better handle {@code isSetXXXX()} methods in code generated by Apache Thrift. With @@ -111,9 +111,9 @@ private void updateNonNullAPsForElement( private static final class FieldAndGetterElements { - @Nullable final Element fieldElem; + final @Nullable Element fieldElem; - @Nullable final Element getterElem; + final @Nullable Element getterElem; public FieldAndGetterElements(@Nullable Element fieldElem, @Nullable Element getterElem) { this.fieldElem = fieldElem; diff --git a/nullaway/src/main/java/com/uber/nullaway/handlers/AssertionHandler.java b/nullaway/src/main/java/com/uber/nullaway/handlers/AssertionHandler.java index 676d3b4743..d886a9cab8 100644 --- a/nullaway/src/main/java/com/uber/nullaway/handlers/AssertionHandler.java +++ b/nullaway/src/main/java/com/uber/nullaway/handlers/AssertionHandler.java @@ -30,9 +30,9 @@ import com.uber.nullaway.dataflow.AccessPath; import com.uber.nullaway.dataflow.AccessPathNullnessPropagation; import java.util.List; -import javax.annotation.Nullable; import org.checkerframework.nullaway.dataflow.cfg.node.MethodInvocationNode; import org.checkerframework.nullaway.dataflow.cfg.node.Node; +import org.jspecify.annotations.Nullable; /** This Handler deals with assertions which ensure that their arguments cannot be null. */ public class AssertionHandler extends BaseNoOpHandler { diff --git a/nullaway/src/main/java/com/uber/nullaway/handlers/BaseNoOpHandler.java b/nullaway/src/main/java/com/uber/nullaway/handlers/BaseNoOpHandler.java index 4656031de9..3664529998 100644 --- a/nullaway/src/main/java/com/uber/nullaway/handlers/BaseNoOpHandler.java +++ b/nullaway/src/main/java/com/uber/nullaway/handlers/BaseNoOpHandler.java @@ -46,11 +46,11 @@ import java.util.List; import java.util.Optional; import java.util.function.Predicate; -import javax.annotation.Nullable; import org.checkerframework.nullaway.dataflow.cfg.UnderlyingAST; import org.checkerframework.nullaway.dataflow.cfg.node.FieldAccessNode; import org.checkerframework.nullaway.dataflow.cfg.node.LocalVariableNode; import org.checkerframework.nullaway.dataflow.cfg.node.MethodInvocationNode; +import org.jspecify.annotations.Nullable; /** * Provides a default (No-Op) implementation of every method defined by the Handler interface. @@ -226,8 +226,7 @@ public MethodInvocationNode onCFGBuildPhase1AfterVisitMethodInvocation( } @Override - @Nullable - public Integer castToNonNullArgumentPositionsForMethod( + public @Nullable Integer castToNonNullArgumentPositionsForMethod( List actualParams, @Nullable Integer previousArgumentPosition, MethodAnalysisContext methodAnalysisContext) { diff --git a/nullaway/src/main/java/com/uber/nullaway/handlers/CompositeHandler.java b/nullaway/src/main/java/com/uber/nullaway/handlers/CompositeHandler.java index 3829dc82b4..df5293d690 100644 --- a/nullaway/src/main/java/com/uber/nullaway/handlers/CompositeHandler.java +++ b/nullaway/src/main/java/com/uber/nullaway/handlers/CompositeHandler.java @@ -50,11 +50,11 @@ import java.util.List; import java.util.Optional; import java.util.function.Predicate; -import javax.annotation.Nullable; import org.checkerframework.nullaway.dataflow.cfg.UnderlyingAST; import org.checkerframework.nullaway.dataflow.cfg.node.FieldAccessNode; import org.checkerframework.nullaway.dataflow.cfg.node.LocalVariableNode; import org.checkerframework.nullaway.dataflow.cfg.node.MethodInvocationNode; +import org.jspecify.annotations.Nullable; /** * Registry of all handlers registered on our analysis. @@ -298,8 +298,7 @@ public MethodInvocationNode onCFGBuildPhase1AfterVisitMethodInvocation( } @Override - @Nullable - public Integer castToNonNullArgumentPositionsForMethod( + public @Nullable Integer castToNonNullArgumentPositionsForMethod( List actualParams, @Nullable Integer previousArgumentPosition, MethodAnalysisContext methodAnalysisContext) { diff --git a/nullaway/src/main/java/com/uber/nullaway/handlers/GrpcHandler.java b/nullaway/src/main/java/com/uber/nullaway/handlers/GrpcHandler.java index 82b436fc46..a12613ae17 100644 --- a/nullaway/src/main/java/com/uber/nullaway/handlers/GrpcHandler.java +++ b/nullaway/src/main/java/com/uber/nullaway/handlers/GrpcHandler.java @@ -42,12 +42,12 @@ import java.util.ArrayList; import java.util.List; import java.util.Optional; -import javax.annotation.Nullable; import javax.lang.model.element.Element; import javax.lang.model.element.ElementKind; import javax.lang.model.type.TypeKind; import org.checkerframework.nullaway.dataflow.cfg.node.MethodInvocationNode; import org.checkerframework.nullaway.dataflow.cfg.node.Node; +import org.jspecify.annotations.Nullable; public class GrpcHandler extends BaseNoOpHandler { private static final String GRPC_METADATA_TNAME = "io.grpc.Metadata"; @@ -124,8 +124,7 @@ public ImmutableSet onRegisterImmutableTypes() { return ImmutableSet.of(GRPC_METADATA_KEY_TNAME); } - @Nullable - private Symbol.MethodSymbol getGetterForMetadataSubtype( + private Symbol.@Nullable MethodSymbol getGetterForMetadataSubtype( Symbol.ClassSymbol classSymbol, Types types) { // Is there a better way than iteration? for (Symbol elem : getEnclosedElements(classSymbol)) { diff --git a/nullaway/src/main/java/com/uber/nullaway/handlers/GuavaAssertionsHandler.java b/nullaway/src/main/java/com/uber/nullaway/handlers/GuavaAssertionsHandler.java index 53561715c9..4f923d9fa3 100644 --- a/nullaway/src/main/java/com/uber/nullaway/handlers/GuavaAssertionsHandler.java +++ b/nullaway/src/main/java/com/uber/nullaway/handlers/GuavaAssertionsHandler.java @@ -5,10 +5,10 @@ import com.sun.source.tree.MethodInvocationTree; import com.sun.tools.javac.code.Symbol; import com.uber.nullaway.dataflow.cfg.NullAwayCFGBuilder; -import javax.annotation.Nullable; import javax.lang.model.element.Name; import javax.lang.model.type.TypeMirror; import org.checkerframework.nullaway.dataflow.cfg.node.MethodInvocationNode; +import org.jspecify.annotations.Nullable; /** * Handler to expose semantics of Guava routines like {@code checkState}, {@code checkArgument}, and @@ -22,11 +22,11 @@ public class GuavaAssertionsHandler extends BaseNoOpHandler { private static final String VERIFY_CLASS_NAME = "com.google.common.base.Verify"; private static final String VERIFY_METHOD_NAME = "verify"; - @Nullable private Name preconditionsClass; - @Nullable private Name verifyClass; - @Nullable private Name checkArgumentMethod; - @Nullable private Name checkStateMethod; - @Nullable private Name verifyMethod; + private @Nullable Name preconditionsClass; + private @Nullable Name verifyClass; + private @Nullable Name checkArgumentMethod; + private @Nullable Name checkStateMethod; + private @Nullable Name verifyMethod; @Nullable TypeMirror preconditionCheckArgumentErrorType; @Nullable TypeMirror preconditionCheckStateErrorType; @Nullable TypeMirror verifyErrorType; diff --git a/nullaway/src/main/java/com/uber/nullaway/handlers/Handler.java b/nullaway/src/main/java/com/uber/nullaway/handlers/Handler.java index 538c587e95..f8a11afe85 100644 --- a/nullaway/src/main/java/com/uber/nullaway/handlers/Handler.java +++ b/nullaway/src/main/java/com/uber/nullaway/handlers/Handler.java @@ -47,11 +47,11 @@ import java.util.List; import java.util.Optional; import java.util.function.Predicate; -import javax.annotation.Nullable; import org.checkerframework.nullaway.dataflow.cfg.UnderlyingAST; import org.checkerframework.nullaway.dataflow.cfg.node.FieldAccessNode; import org.checkerframework.nullaway.dataflow.cfg.node.LocalVariableNode; import org.checkerframework.nullaway.dataflow.cfg.node.MethodInvocationNode; +import org.jspecify.annotations.Nullable; /** * The general interface representing a handler. @@ -377,8 +377,7 @@ MethodInvocationNode onCFGBuildPhase1AfterVisitMethodInvocation( * handler in the chain. * @param methodAnalysisContext The MethodAnalysisContext object */ - @Nullable - Integer castToNonNullArgumentPositionsForMethod( + @Nullable Integer castToNonNullArgumentPositionsForMethod( List actualParams, @Nullable Integer previousArgumentPosition, MethodAnalysisContext methodAnalysisContext); diff --git a/nullaway/src/main/java/com/uber/nullaway/handlers/InferredJARModelsHandler.java b/nullaway/src/main/java/com/uber/nullaway/handlers/InferredJARModelsHandler.java index f171c502da..472c69bbcd 100644 --- a/nullaway/src/main/java/com/uber/nullaway/handlers/InferredJARModelsHandler.java +++ b/nullaway/src/main/java/com/uber/nullaway/handlers/InferredJARModelsHandler.java @@ -38,10 +38,10 @@ import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; -import javax.annotation.Nullable; import javax.lang.model.element.Modifier; import javax.lang.model.type.TypeKind; import org.checkerframework.nullaway.dataflow.cfg.node.MethodInvocationNode; +import org.jspecify.annotations.Nullable; /** This handler loads inferred nullability model from stubs for methods in unannotated packages. */ public class InferredJARModelsHandler extends BaseNoOpHandler { @@ -203,8 +203,8 @@ private boolean isReturnAnnotatedNullable(Symbol.MethodSymbol methodSymbol) { return false; } - @Nullable - private Map> lookupMethodInCache(String className, String methodSign) { + private @Nullable Map> lookupMethodInCache( + String className, String methodSign) { if (!argAnnotCache.containsKey(className)) { return null; } diff --git a/nullaway/src/main/java/com/uber/nullaway/handlers/LibraryModelsHandler.java b/nullaway/src/main/java/com/uber/nullaway/handlers/LibraryModelsHandler.java index 10445a9aa5..3862b0704b 100644 --- a/nullaway/src/main/java/com/uber/nullaway/handlers/LibraryModelsHandler.java +++ b/nullaway/src/main/java/com/uber/nullaway/handlers/LibraryModelsHandler.java @@ -57,10 +57,10 @@ import java.util.ServiceLoader; import java.util.Set; import java.util.function.Function; -import javax.annotation.Nullable; import org.checkerframework.nullaway.dataflow.cfg.node.FieldAccessNode; import org.checkerframework.nullaway.dataflow.cfg.node.MethodInvocationNode; import org.checkerframework.nullaway.dataflow.cfg.node.Node; +import org.jspecify.annotations.Nullable; /** * This Handler deals with any methods from unannotated packages for which we need a nullability @@ -74,7 +74,7 @@ public class LibraryModelsHandler extends BaseNoOpHandler { private final Config config; private final LibraryModels libraryModels; - @Nullable private OptimizedLibraryModels optLibraryModels; + private @Nullable OptimizedLibraryModels optLibraryModels; public LibraryModelsHandler(Config config) { super(); @@ -184,8 +184,7 @@ public boolean onOverrideMayBeNullExpr( } @Override - @Nullable - public Integer castToNonNullArgumentPositionsForMethod( + public @Nullable Integer castToNonNullArgumentPositionsForMethod( List actualParams, @Nullable Integer previousArgumentPosition, MethodAnalysisContext methodAnalysisContext) { @@ -206,7 +205,7 @@ public Integer castToNonNullArgumentPositionsForMethod( return newPositions.stream().findAny().orElse(previousArgumentPosition); } - @Nullable private CodeAnnotationInfo codeAnnotationInfo; + private @Nullable CodeAnnotationInfo codeAnnotationInfo; private CodeAnnotationInfo getCodeAnnotationInfo(Context context) { if (codeAnnotationInfo == null) { @@ -1151,8 +1150,7 @@ private static class NameIndexedMap { this.state = state; } - @Nullable - public T get(Symbol.MethodSymbol symbol) { + public @Nullable T get(Symbol.MethodSymbol symbol) { Map methodRefTMap = state.get(symbol.name); if (methodRefTMap == null) { return null; @@ -1259,8 +1257,7 @@ private NameIndexedMap makeOptimizedLookup( * checks if symbol is present in the NameIndexedMap or if it overrides some method in the * NameIndexedMap */ - @Nullable - private static Symbol.MethodSymbol lookupHandlingOverrides( + private static Symbol.@Nullable MethodSymbol lookupHandlingOverrides( Symbol.MethodSymbol symbol, Types types, NameIndexedMap optLookup, diff --git a/nullaway/src/main/java/com/uber/nullaway/handlers/LombokHandler.java b/nullaway/src/main/java/com/uber/nullaway/handlers/LombokHandler.java index 7069497800..5ed8fef2d3 100644 --- a/nullaway/src/main/java/com/uber/nullaway/handlers/LombokHandler.java +++ b/nullaway/src/main/java/com/uber/nullaway/handlers/LombokHandler.java @@ -11,8 +11,8 @@ import com.uber.nullaway.NullAway; import com.uber.nullaway.Nullness; import java.util.stream.StreamSupport; -import javax.annotation.Nullable; import javax.lang.model.element.ElementKind; +import org.jspecify.annotations.Nullable; /** * A general handler for Lombok generated code and its internal semantics. diff --git a/nullaway/src/main/java/com/uber/nullaway/handlers/OptionalEmptinessHandler.java b/nullaway/src/main/java/com/uber/nullaway/handlers/OptionalEmptinessHandler.java index 10f1217083..bc790e0825 100644 --- a/nullaway/src/main/java/com/uber/nullaway/handlers/OptionalEmptinessHandler.java +++ b/nullaway/src/main/java/com/uber/nullaway/handlers/OptionalEmptinessHandler.java @@ -49,7 +49,6 @@ import java.util.Objects; import java.util.Optional; import java.util.function.Consumer; -import javax.annotation.Nullable; import javax.lang.model.element.AnnotationMirror; import javax.lang.model.element.Element; import javax.lang.model.element.ElementKind; @@ -61,6 +60,7 @@ import javax.lang.model.type.TypeMirror; import org.checkerframework.nullaway.dataflow.cfg.node.MethodInvocationNode; import org.checkerframework.nullaway.dataflow.cfg.node.Node; +import org.jspecify.annotations.Nullable; /** * Handler to better handle {@code isPresent()} methods in code generated for Optionals. With this @@ -68,7 +68,7 @@ */ public class OptionalEmptinessHandler extends BaseNoOpHandler { - @Nullable private ImmutableSet optionalTypes; + private @Nullable ImmutableSet optionalTypes; private @Nullable NullAway analysis; private final Config config; @@ -333,8 +333,7 @@ private OptionalContentVariableElement(Name name, TypeMirror asType) { } @Override - @Nullable - public Object getConstantValue() { + public @Nullable Object getConstantValue() { return null; } @@ -344,8 +343,7 @@ public Name getSimpleName() { } @Override - @Nullable - public Element getEnclosingElement() { + public @Nullable Element getEnclosingElement() { // A field would have an enclosing element, however this method isn't guaranteed to // return non-null in all cases. It may be beneficial to implement this in a future // improvement, but that will require tracking an instance per supported optional @@ -364,8 +362,7 @@ public List getAnnotationMirrors() { } @Override - @Nullable - public A getAnnotation(Class aClass) { + public @Nullable A getAnnotation(Class aClass) { return null; } diff --git a/nullaway/src/main/java/com/uber/nullaway/handlers/RestrictiveAnnotationHandler.java b/nullaway/src/main/java/com/uber/nullaway/handlers/RestrictiveAnnotationHandler.java index f1398f237d..ef04e8bf91 100644 --- a/nullaway/src/main/java/com/uber/nullaway/handlers/RestrictiveAnnotationHandler.java +++ b/nullaway/src/main/java/com/uber/nullaway/handlers/RestrictiveAnnotationHandler.java @@ -34,9 +34,9 @@ import com.uber.nullaway.Nullness; import com.uber.nullaway.dataflow.AccessPath; import com.uber.nullaway.dataflow.AccessPathNullnessPropagation; -import javax.annotation.Nullable; import org.checkerframework.nullaway.dataflow.cfg.node.FieldAccessNode; import org.checkerframework.nullaway.dataflow.cfg.node.MethodInvocationNode; +import org.jspecify.annotations.Nullable; public class RestrictiveAnnotationHandler extends BaseNoOpHandler { @@ -88,7 +88,7 @@ && isSymbolRestrictivelyNullable(exprSymbol, state.context)) { return false; } - @Nullable private CodeAnnotationInfo codeAnnotationInfo; + private @Nullable CodeAnnotationInfo codeAnnotationInfo; private CodeAnnotationInfo getCodeAnnotationInfo(Context context) { if (codeAnnotationInfo == null) { diff --git a/nullaway/src/main/java/com/uber/nullaway/handlers/contract/ContractHandler.java b/nullaway/src/main/java/com/uber/nullaway/handlers/contract/ContractHandler.java index 0b61cb0cd4..a1d15c7fc5 100644 --- a/nullaway/src/main/java/com/uber/nullaway/handlers/contract/ContractHandler.java +++ b/nullaway/src/main/java/com/uber/nullaway/handlers/contract/ContractHandler.java @@ -41,7 +41,6 @@ import com.uber.nullaway.dataflow.cfg.NullAwayCFGBuilder; import com.uber.nullaway.handlers.BaseNoOpHandler; import java.util.Optional; -import javax.annotation.Nullable; import javax.lang.model.type.TypeMirror; import org.checkerframework.nullaway.dataflow.cfg.node.AbstractNodeVisitor; import org.checkerframework.nullaway.dataflow.cfg.node.BinaryOperationNode; @@ -49,6 +48,7 @@ import org.checkerframework.nullaway.dataflow.cfg.node.MethodInvocationNode; import org.checkerframework.nullaway.dataflow.cfg.node.Node; import org.checkerframework.nullaway.dataflow.cfg.node.NotEqualNode; +import org.jspecify.annotations.Nullable; /** * This Handler parses the jetbrains @Contract annotation and honors the nullness spec defined there diff --git a/nullaway/src/main/java/com/uber/nullaway/handlers/contract/ContractUtils.java b/nullaway/src/main/java/com/uber/nullaway/handlers/contract/ContractUtils.java index ac54e11326..4d75f08e0f 100644 --- a/nullaway/src/main/java/com/uber/nullaway/handlers/contract/ContractUtils.java +++ b/nullaway/src/main/java/com/uber/nullaway/handlers/contract/ContractUtils.java @@ -10,9 +10,9 @@ import com.uber.nullaway.NullabilityUtil; import java.util.Set; import java.util.stream.Collectors; -import javax.annotation.Nullable; import javax.lang.model.element.AnnotationMirror; import org.checkerframework.nullaway.javacutil.AnnotationUtils; +import org.jspecify.annotations.Nullable; /** An utility class for {@link ContractHandler} and {@link ContractCheckHandler}. */ public class ContractUtils { @@ -120,8 +120,7 @@ static String[] getAntecedent( * @param config the NullAway config * @return the value of a Contract annotation if present, or {@code null} if not present. */ - @Nullable - static String getContractString(Symbol.MethodSymbol methodSymbol, Config config) { + static @Nullable String getContractString(Symbol.MethodSymbol methodSymbol, Config config) { for (AnnotationMirror annotation : methodSymbol.getAnnotationMirrors()) { String name = AnnotationUtils.annotationName(annotation); if (config.isContractAnnotation(name)) { diff --git a/nullaway/src/main/java/com/uber/nullaway/handlers/stream/StreamModelBuilder.java b/nullaway/src/main/java/com/uber/nullaway/handlers/stream/StreamModelBuilder.java index be13dcfec5..41d07819fa 100644 --- a/nullaway/src/main/java/com/uber/nullaway/handlers/stream/StreamModelBuilder.java +++ b/nullaway/src/main/java/com/uber/nullaway/handlers/stream/StreamModelBuilder.java @@ -30,7 +30,7 @@ import com.google.errorprone.suppliers.Suppliers; import java.util.ArrayList; import java.util.List; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; /** * Used to produce a new list of StreamTypeRecord models, where each model represents a class from a diff --git a/sample/build.gradle b/sample/build.gradle index 58ddd90185..3f975ba8e8 100644 --- a/sample/build.gradle +++ b/sample/build.gradle @@ -24,7 +24,7 @@ dependencies { annotationProcessor project(":nullaway") annotationProcessor project(path: ":sample-library-model") - compileOnly deps.build.jsr305Annotations + api deps.build.jspecify testImplementation deps.test.junit4 } diff --git a/sample/src/main/java/com/uber/mylib/Lambdas.java b/sample/src/main/java/com/uber/mylib/Lambdas.java index 10c5d5a952..0a10dd192d 100644 --- a/sample/src/main/java/com/uber/mylib/Lambdas.java +++ b/sample/src/main/java/com/uber/mylib/Lambdas.java @@ -5,7 +5,7 @@ import java.util.List; import java.util.function.BiFunction; import java.util.function.Function; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; /** Code that uses Java 8 lambdas */ @SuppressWarnings("UnusedVariable") // This is sample code @@ -14,8 +14,7 @@ public class Lambdas { @FunctionalInterface interface RetNullableFunction { - @Nullable - Object getVal(); + @Nullable Object getVal(); } public static void testLambda() { diff --git a/sample/src/main/java/com/uber/mylib/MyClass.java b/sample/src/main/java/com/uber/mylib/MyClass.java index d4721d7ddb..5e3fba4a67 100644 --- a/sample/src/main/java/com/uber/mylib/MyClass.java +++ b/sample/src/main/java/com/uber/mylib/MyClass.java @@ -1,6 +1,6 @@ package com.uber.mylib; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import org.utilities.StringUtils; /** A sample class. */ diff --git a/sample/src/main/java/com/uber/mylib/MyClass.java.buggy b/sample/src/main/java/com/uber/mylib/MyClass.java.buggy index 55bebc8d49..7dc7273433 100644 --- a/sample/src/main/java/com/uber/mylib/MyClass.java.buggy +++ b/sample/src/main/java/com/uber/mylib/MyClass.java.buggy @@ -1,6 +1,6 @@ package com.uber.mylib; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; /** * A sample class. diff --git a/sample/src/main/java/org/utilities/StringUtils.java b/sample/src/main/java/org/utilities/StringUtils.java index 104c30be0a..079fed7d91 100644 --- a/sample/src/main/java/org/utilities/StringUtils.java +++ b/sample/src/main/java/org/utilities/StringUtils.java @@ -1,6 +1,6 @@ package org.utilities; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; public class StringUtils { diff --git a/test-java-lib-lombok/build.gradle b/test-java-lib-lombok/build.gradle index c70f54828d..c9c9722beb 100644 --- a/test-java-lib-lombok/build.gradle +++ b/test-java-lib-lombok/build.gradle @@ -24,7 +24,7 @@ dependencies { annotationProcessor project(":nullaway") annotationProcessor deps.test.lombok - compileOnly deps.build.jsr305Annotations + api deps.build.jspecify compileOnly deps.build.javaxValidation compileOnly deps.test.cfQual compileOnly deps.test.lombok diff --git a/test-java-lib-lombok/src/main/java/com/uber/lombok/LombokDTO.java b/test-java-lib-lombok/src/main/java/com/uber/lombok/LombokDTO.java index 44d6b50709..aedfb52285 100644 --- a/test-java-lib-lombok/src/main/java/com/uber/lombok/LombokDTO.java +++ b/test-java-lib-lombok/src/main/java/com/uber/lombok/LombokDTO.java @@ -22,9 +22,9 @@ package com.uber.lombok; -import javax.annotation.Nullable; import lombok.Builder; import lombok.Data; +import org.jspecify.annotations.Nullable; @Builder @Data @@ -35,6 +35,6 @@ public class LombokDTO { // issue an uninitialized field warning. private String field; @Builder.Default private String fieldWithDefault = "Default"; - @Nullable private String nullableField; - @Nullable @Builder.Default private String fieldWithNullDefault = null; + private @Nullable String nullableField; + @Builder.Default private @Nullable String fieldWithNullDefault = null; } diff --git a/test-java-lib-lombok/src/main/java/com/uber/lombok/UsesDTO.java b/test-java-lib-lombok/src/main/java/com/uber/lombok/UsesDTO.java index f236a65056..836c84e78a 100644 --- a/test-java-lib-lombok/src/main/java/com/uber/lombok/UsesDTO.java +++ b/test-java-lib-lombok/src/main/java/com/uber/lombok/UsesDTO.java @@ -22,7 +22,7 @@ package com.uber.lombok; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; class UsesDTO { diff --git a/test-java-lib/build.gradle b/test-java-lib/build.gradle index 79323d6ebf..6be5a65469 100644 --- a/test-java-lib/build.gradle +++ b/test-java-lib/build.gradle @@ -24,7 +24,6 @@ dependencies { annotationProcessor project(":nullaway") implementation deps.build.jspecify - compileOnly deps.build.jsr305Annotations compileOnly deps.build.javaxValidation compileOnly deps.test.cfQual } diff --git a/test-java-lib/src/main/java/com/uber/lib/unannotated/AndroidRecentlyAnnotatedClass.java b/test-java-lib/src/main/java/com/uber/lib/unannotated/AndroidRecentlyAnnotatedClass.java index 2a609501c5..6a9727240d 100644 --- a/test-java-lib/src/main/java/com/uber/lib/unannotated/AndroidRecentlyAnnotatedClass.java +++ b/test-java-lib/src/main/java/com/uber/lib/unannotated/AndroidRecentlyAnnotatedClass.java @@ -5,7 +5,8 @@ public class AndroidRecentlyAnnotatedClass { - public static @RecentlyNullable Object returnsNull() { + @RecentlyNullable + public static Object returnsNull() { return null; } diff --git a/test-java-lib/src/main/java/com/uber/lib/unannotated/RestrictivelyAnnotatedFI.java b/test-java-lib/src/main/java/com/uber/lib/unannotated/RestrictivelyAnnotatedFI.java index a3ee49ccb0..11b7de489c 100644 --- a/test-java-lib/src/main/java/com/uber/lib/unannotated/RestrictivelyAnnotatedFI.java +++ b/test-java-lib/src/main/java/com/uber/lib/unannotated/RestrictivelyAnnotatedFI.java @@ -1,6 +1,6 @@ package com.uber.lib.unannotated; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; public interface RestrictivelyAnnotatedFI { diff --git a/test-java-lib/src/main/java/com/uber/lib/unannotated/RestrictivelyAnnotatedFIWithModelOverride.java b/test-java-lib/src/main/java/com/uber/lib/unannotated/RestrictivelyAnnotatedFIWithModelOverride.java index a2c37f30b1..44cdea0157 100644 --- a/test-java-lib/src/main/java/com/uber/lib/unannotated/RestrictivelyAnnotatedFIWithModelOverride.java +++ b/test-java-lib/src/main/java/com/uber/lib/unannotated/RestrictivelyAnnotatedFIWithModelOverride.java @@ -1,9 +1,8 @@ package com.uber.lib.unannotated; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; public interface RestrictivelyAnnotatedFIWithModelOverride { - @Nullable - Object apply(@Nullable Object o); + @Nullable Object apply(@Nullable Object o); }