-
Notifications
You must be signed in to change notification settings - Fork 299
Configuration
The NullAway checker takes multiple configuration flags, in the format of Error Prone's Command-Line Flags. Before version 0.12.3, NullAway throws an error immediately upon loading if the -XepOpt:NullAway:AnnotatedPackages
flag is not specified. In versions 0.12.3 and after, NullAway requires exactly one of either the -XepOpt:NullAway:AnnotatedPackages
flag or the -XepOpt:NullAway:OnlyNullMarked
flag (see below).
The following flags are currently supported; each of them can take multiple values as a comma separated list:
-XepOpt:NullAway:AnnotatedPackages=...
The list of packages that should be considered properly annotated according to the NullAway convention (every possibly null parameter / return / field annotated @Nullable
). E.g., -XepOpt:NullAway:AnnotatedPackages=com.foo,org.bar
.
This option supports restricted regexp syntax.
-XepOpt:NullAway:OnlyNullMarked=true
This option indicates that the AnnotatedPackages
flag has been deliberately omitted, and that NullAway can proceed with only treating @NullMarked
code as annotated, in accordance with the JSpecify specification. If this option is passed, the AnnotatedPackages
flag cannot be passed. Note that even if this flag is omitted (and AnnotatedPackages
is passed), any @NullMarked
code will still be treated as annotated.
As JSpecify annotations become more widely adopted, eventually NullAway may remove this flag as it may become unnecessary.
-XepOpt:NullAway:UnannotatedSubPackages=...
A list of subpackages to be excluded from the AnnotatedPackages list. E.g., if all code under com.foo
packages is properly annotated except for code under com.foo.baz
, you could use the options -XepOpt:NullAway:AnnotatedPackages=com.foo -XepOpt:NullAway:UnannotatedSubPackages=com.foo.baz
.
This option supports restricted regexp syntax.
-XepOpt:NullAway:UnannotatedClasses=...
A list of classes within annotated packages that should be treated as unannotated. E.g., if all code under com.foo
should be treated as annotated except for the class com.foo.UnAnnot
, you could use the options -XepOpt:NullAway:AnnotatedPackages=com.foo -XepOpt:NullAway:UnannotatedClasses=com.foo.UnAnnot
.
-XepOpt:NullAway:KnownInitializers=...
The fully qualified name (without argument's, e.g. android.app.Activity.onCreate
) of those methods from third-party libraries that NullAway should treat as initializers (equivalent to being annotated with an @Initializer
annotation).
-XepOpt:NullAway:ExcludedClassAnnotations=...
A list of annotations that cause classes to be excluded from nullability analysis. Note that while NullAway does not analyze the code of these classes, it still assumes the APIs are annotated correctly when analyzing callers into methods of the classes.
-XepOpt:NullAway:ExcludedClasses=...
A list of classes to be excluded from the nullability analysis. Note that while NullAway does not analyze the code of these classes, it still assumes the APIs are annotated correctly when analyzing callers into methods of the classes.
-XepOpt:NullAway:ExcludedFieldAnnotations=...
A list of annotations that cause fields to be excluded from being checked for proper initialization (e.g. javax.inject.Inject
).
This option supports restricted regexp syntax.
[Since 0.9.3]
Please note that NullAway requires no configuration to support any annotations with simple name @Nullable
(such as javax.annotation.Nullable
or androidx.annotation.Nullable
) and natively supports a number of other common nullability annotations. The same is true for common variations of @NonNull
, when relevant. See Supported Annotations.
There is also specific optional support for Android's "Recent" Nullability Annotations, which can be configured separately.
However, if your project uses annotations with non-standard names for nullability, which aren't part of a library NullAway is aware of, you can still specify them by using the following two configuration options:
-XepOpt:NullAway:CustomNullableAnnotations=...
A list of annotations that should be considered equivalent to @Nullable
annotations. Note that any annotation with the simple name @Nullable
, from any package, will be considered a nullable annotation (and thus doesn't need to be explicitly configured), but names passed to this configuration option must be fully-qualified class names.
-XepOpt:NullAway:CustomNonnullAnnotations=...
A list of annotations that should be considered equivalent to @NonNull
annotations, for the cases where NullAway cares about such annotations (see e.g. AcknowledgeRestrictiveAnnotations). Note that any annotation with the simple name @NonNull
, @NotNull
, or @Nonnull
, from any package, will be considered a non-null annotation (and thus doesn't need to be explicitly configured), but names passed to this configuration option must be fully-qualified class names.
-XepOpt:NullAway:CustomInitializerAnnotations=...
A list of annotations that should be considered equivalent to @Initializer
annotations, and thus mark methods as initializers (e.g. org.junit.Before
and org.junit.BeforeClass
, which are automatically added to this list by default). Note that any annotation with the simple name @Initializer
, from any package, will be considered an initializer annotation, but names passed to this configuration option must be fully-qualified class names.
-XepOpt:NullAway:ExternalInitAnnotations=...
A list of annotations for classes that are "externally initialized." Tools like the Cassandra Object Mapper do their own field initialization of objects with a certain annotation (like @Table
), after invoking the zero-argument constructor.
For any class annotated with an external-init annotation, we don't check that the zero-arg constructor initializes all non-null fields.
Additionally, these external-init annotations will also be acknowledged if they annotate a zero-arg constructor directly, rather than the full class, with equivalent semantics to @SuppressWarnings("NullAway.Init")
on that same constructor. Note, however, that external-init annotations will be ignored if they appear in non-zero arg constructors or non-constructor methods (e.g. initializers).
-XepOpt:NullAway:AssertsEnabled=...
By default, NullAway ignores assertions in the analyzed code. The reason for this is that assertions are not guaranteed to be checked at runtime.
Thus, in the following code:
T1 t1 = new T1();
assert t1.obj != null;
t1.obj.toString();
Whether t1.obj
can or can't be null
at the point toString()
is called on it depends on the way the code is run and whether or not assert
statements are being checked by the JVM (usually they are not in production runs). By default, NullAway assumes assert
statements won't always be there at runtime, and thus it doesn't rely on nullness checks within assertions.
Setting AssertsEnabled=true
overrides this behavior and makes NullAway assume that assertions will always be enabled at runtime (e.g. that the code will always be run with -enableassertions
being passed to the JVM).
-XepOpt:NullAway:TreatGeneratedAsUnannotated=...
If set to true
, NullAway treats any class annotated with @Generated
as if its APIs are unannotated when analyzing uses from other classes. It also does not perform analysis on the code inside @Generated
classes. If you can modify the code generator such that at least the APIs of @Generated
classes are annotated correctly, we recommend using the -XepOpt:NullAway:ExcludedClassAnnotations
option instead. Defaults to false
.
-XepOpt:NullAway:CustomGeneratedCodeAnnotations=...
A list of annotations that should be considered as marking code as generated. Note that any annotation with the simple name @Generated
, from any package, will be considered marking code as generated, but names passed to this configuration option must be fully-qualified class names. Useful in conjunction with the TreatGeneratedAsUnannotated
option.
-XepOpt:NullAway:AcknowledgeRestrictiveAnnotations=...
This option adds some extra safety when dealing with third-party code that includes potentially incomplete nullability annotations. If set to true
, NullAway will acknowledge nullability annotations whenever they are available in unannotated code and also more restrictive than it's optimistic defaults.
For example, when this flag is turned on, a method Object foo(Object o)
in an unannotated package will still be assumed to take a nullable argument and return non-null (an optimistic assumption, made for usability reasons). However, a method Object bar(@NonNull Object o)
will be interpreted by NullAway as taking a non-null argument, and a method @Nullable Object baz(Object o)
will be acknowledged as potentially returning null
, even in code otherwise marked as unannotated. If this flag is turned off, which is the default, all three examples are treated as the first and optimistic defaults are assumed to reduce the number of warnings unless the package is marked as fully annotated.
Note that e.g. an @NonNull
annotation in annotated code is meaningless, whether or not this flag is set, as that's NullAway's default for that code. But this affects NullAway's handling of code marked as unannotated.
Also, specific method annotations can always be overridden by explicit Library Models, which take precedence over both the optimistic defaults and any annotations in the code, whether marked as annotated or unannotated.
-XepOpt:Nullaway:AcknowledgeAndroidRecent=...
If this flag is set to true
and -XepOpt:Nullaway:AcknowledgeRestrictiveAnnotations
is set to true
, we treat the Android @RecentlyNullable
annotation as @Nullable
, and similarly for @RecentlyNonNull
.
-XepOpt:NullAway:CastToNonNullMethod=[...]
Specifies the method being used for casting @Nullable
expressions to @NonNull
; see downcasting docs. When this option is passed, NullAway will emit a warning if a downcast is ever performed on an expression that is already @NonNull
.
-XepOpt:NullAway:ExhaustiveOverride=...
By default, NullAway relies on the @Override
annotation to know which methods override a super-type method and thus must be checked for consistency in the nullness of their return value and parameters. This is done for performance reasons.
In codebases where @Override
is not used consistently, this flag should be set to true
. It forces NullAway to check every method to see whether or not it overrides a method of a super-type.
-XepOpt:NullAway:CheckOptionalEmptiness=...
If set to true
, NullAway will check for .get()
accesses to potentially empty Optional
values, analogously to how it handles dereferences to @Nullable
values. Calling .get()
on an Optional
value that hasn't been previously tested with Optional.isPresent(...)
(or otherwise tested for non-emptiness in a way NullAway understands) will result in an error.
This works out of the box for java.util.Optional
. Additionally, the following option can be used to tell NullAway of other Optional
implementations (e.g. Guava's com.google.common.base.Optional
).
-XepOpt:NullAway:CheckOptionalEmptinessCustomClasses=...
Optional handling (for both JDK and custom Optional
classes) is currently disabled by default, but it is under active development. Feel free to try it out and let us know what might still be missing.
-XepOpt:NullAway:HandleTestAssertionLibraries=...
By default, NullAway does not handle assertions from test libraries. If set to true
, NullAway will handle assertions from test libraries, like assertThat(...).isNotNull()
, and use that to reason about the possibility of null dereferences in the code that follows these assertions.
-XepOpt:NullAway:CheckContracts=...
NullAway has support for JetBrains @Contract
annotations. By default, these annotations are trusted but not checked. If this option is set to true
, NullAway will check that @Contract
annotations are valid (for the subset of @Contract
annotations supported by NullAway).
-XepOpt:NullAway:CustomContractAnnotations=...
By default, NullAway recognizes org.jetbrains.annotations.Contract
as a contract annotation. This option allows for specifying an additional list of annotations that should be recognized as providing contracts (with the same contract syntax as org.jetbrains.annotations.Contract
).
-XepOpt:NullAway:ExtraFuturesClasses=...
NullAway currently has temporary special support for reasoning about callbacks passed to Guava's Futures
and FluentFuture
classes; see https://github.com/uber/NullAway/pull/771. This option allows for specifying an additional list of classes that should be recognized as equivalent to those two Guava classes. This special support will likely be removed once NullAway's JSpecify support is more complete.
-XepOpt:NullAway:LegacyAnnotationLocations=...
NullAway 0.12.0 changes the logic for how type-use annotations are interpreted to be consistent with the JSpecify specification. See JSpecify Support for more details. Setting the LegacyAnnotationLocations
flag re-enables NullAway's previous logic for interpreting these annotations, to ease migration. We expect to remove this flag in a future NullAway release.
A few options, marked above, support a restricted regular expression syntax to specify the package names they cover. The main difference between our syntax and standard Java regular expressions, is that the .
character is interpreted as a literal dot, not as "any character", as dots are part of the standard package name syntax and treating them literally favors the common case.
It is still possible to cover patterns of package names, such as:
-XepOpt:NullAway:UnannotatedSubPackages=[a-zA-Z0-9.]*.unannotated
(Will consider any code inside any subpackage named unannotated
, including subpackages thereof, as unannotated. E.g. a.unanoted
, x.y.z.unannotated.z
.)
-XepOpt:NullAway:UnannotatedSubPackages=com.myorg.generated_[a-zA-Z0-9]*
(Matches com.myorg.generated_Foo.subpackage
, but not com.myorg.source_Foo.subpackage
or comxmyorg.generated_Foo
.)
In addition to these options, NullAway will look for any classes implementing the com.uber.nullaway.LibraryModels
interface, in the annotation processor path, and consider those as plug-in models for third-party unannotated libraries. (We search for such classes using the ServiceLoader facility.) Models defined in such classes will be loaded in addition to the default models for common Java and Android libraries included with the checker itself. For documentation on writing such custom models, refer to the javadoc documentation for com.uber.nullaway.LibraryModels
itself. Also see our sample library model for an example; it is pulled in and used by our sample Java module (see the build.gradle
file). Note that if you can edit the source code of the library, you might be able to add @Contract
annotations instead of writing a library model.
Sometimes, it is useful to suppress some library models on a per-compilation target basis, without changing or adding custom library models classes. In these cases, it is possible to skip all Library Models (included with NullAway and custom) for a specific method, simply by passing it to the following option:
-XepOpt:NullAway:IgnoreLibraryModelsFor=com.example.Foo.bar,com.example.Foo.baz
This takes a list of comma-separated methods, given as their fully-qualified class name plus the method simple name.
Note that, for simplicity of dealing with command-line escaped characters and the like, there is currently no way to give the full signature of the method (i.e. the argument types) when using this option. Thus, methods passed to -XepOpt:NullAway:IgnoreLibraryModelsFor
will technically refer to all methods matching the given class and method name.
For configuring Error Prone with Maven, see the docs. It's also good to be familiar with how flags should be passed to Error Prone with Maven; see these docs. Here is an example Maven build configuration (based on the Error Prone example) that pulls in Error Prone and NullAway:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<source>11</source>
<target>11</target>
<encoding>UTF-8</encoding>
<compilerArgs>
<arg>-XDcompilePolicy=simple</arg>
<arg>-Xplugin:ErrorProne -XepOpt:NullAway:AnnotatedPackages=com.uber</arg>
</compilerArgs>
<annotationProcessorPaths>
<path>
<groupId>com.google.errorprone</groupId>
<artifactId>error_prone_core</artifactId>
<version>2.23.0</version>
</path>
<path>
<groupId>com.uber.nullaway</groupId>
<artifactId>nullaway</artifactId>
<version>0.10.15</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
An example (based on this).
WORKSPACE:
maven_jar(
name='jsr305',
artifact='com.google.code.findbugs:jsr305:3.0.2',
)
maven_jar(
name="nullaway",
artifact="com.uber.nullaway:nullaway:0.3.4"
)
BUILD:
java_library(
name='x',
srcs=['X.java'],
deps=['@jsr305//jar'],
plugins=['nullaway'],
javacopts=[
'-Xep:NullAway:ERROR',
'-XepOpt:NullAway:AnnotatedPackages=com.example',
],
)
java_plugin(
name='nullaway',
deps=[
'@nullaway//jar'
],
)
The first step is to get Error Prone running on your build, as documented here. Then, you need to get the NullAway jar on the annotation processor path for the Javac invocations where Error Prone is running. Finally, you need to pass the appropriate compiler arguments to configure NullAway (at the least, the -XepOpt:NullAway:AnnotatedPackages
option).
[Only in version 0.9.9]
-XepOpt:NullAway:AcknowledgeLibraryModelsOfAnnotatedCode=...
This option allows library models to override the annotations on methods within an annotated package. This is useful, e.g., if you want to treat Guava's com.google.common
packages as annotated, but also want the default library models of Guava APIs (e.g., of Strings.isNullOrEmpty()
) to still apply.
In NullAway 0.9.10+, this option is removed, and library models always override annotations on methods within an annotated packaged (i.e., the option is always on).