Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Better handling of Lombok configuration for @Nullable annotations #876

Draft
wants to merge 5 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 4 additions & 4 deletions README.md
Expand Up @@ -80,13 +80,13 @@ Unlike other annotation processors above, Lombok modifies the in-memory AST of t

We do not particularly recommend using NullAway with Lombok. However, NullAway encodes some knowledge of common Lombok annotations and we do try for best-effort compatibility. In particular, common usages like `@lombok.Builder` and `@Data` classes should be supported.

In order for NullAway to successfully detect Lombok generated code within the in-memory Java AST, the following configuration option must be passed to Lombok as part of an applicable `lombok.config` file:
For the best compatibility with NullAway, add the following configuration options to an applicable `lombok.config` file:

```
addLombokGeneratedAnnotation
lombok.addLombokGeneratedAnnotation = true
lombok.addNullAnnotations = <flavor>
```

This causes Lombok to add `@lombok.Generated` to the methods/classes it generates. NullAway will ignore (i.e. not check) the implementation of this generated code, treating it as unannotated.
See the [Lombok configuration documentation](https://projectlombok.org/features/configuration) for more details. The `addLombokGeneratedAnnotation` option causes Lombok to add `@lombok.Generated` to the methods/classes it generates. NullAway will ignore (i.e. not check) the implementation of this generated code, treating it as unannotated. The `addNullAnnotations` options causes Lombok to add nullability annotations to its generated code, which can remove certain NullAway false positives. In particular, with this option enabled, Lombok adds a `@Nullable` annotation to the parameter of every generated `equals()` method, and then NullAway will not warn if a `@Nullable` argument is passed to such a method.

## Code Example

Expand Down
2 changes: 1 addition & 1 deletion gradle/dependencies.gradle
Expand Up @@ -109,7 +109,7 @@ 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",
lombok : "org.projectlombok:lombok:1.18.30",
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
Expand Down
Expand Up @@ -86,26 +86,4 @@ public Nullness onOverrideMethodReturnNullability(
}
return returnNullness;
}

/**
* Mark the first argument of Lombok-generated {@code equals} methods as {@code @Nullable}, since
* Lombok does not generate the annotation.
*/
@Override
public Nullness[] onOverrideMethodInvocationParametersNullability(
VisitorState state,
Symbol.MethodSymbol methodSymbol,
boolean isAnnotated,
Nullness[] argumentPositionNullness) {
if (ASTHelpers.hasAnnotation(methodSymbol, LOMBOK_GENERATED_ANNOTATION_NAME, state)) {
// We assume that Lombok-generated equals methods with a single argument override
// Object.equals and are not an overload.
if (methodSymbol.getSimpleName().contentEquals("equals")
&& methodSymbol.params().size() == 1) {
// The parameter is not annotated with @Nullable, but it should be.
argumentPositionNullness[0] = Nullness.NULLABLE;
}
}
return argumentPositionNullness;
}
}
5 changes: 5 additions & 0 deletions test-java-lib-lombok/build.gradle
Expand Up @@ -44,3 +44,8 @@ tasks.withType(JavaCompile) {
"--add-opens=jdk.compiler/com.sun.tools.javac.jvm=ALL-UNNAMED"
]
}

// Needed so that compilation re-runs if the lombok.config is changed
tasks.named('compileJava') {
inputs.file('lombok.config')
}
1 change: 1 addition & 0 deletions test-java-lib-lombok/lombok.config
@@ -1,2 +1,3 @@
config.stopBubbling = true
lombok.addLombokGeneratedAnnotation = true
lombok.addNullAnnotations = javax