aboutsummaryrefslogtreecommitdiff
path: root/src/core/lombok/javac/handlers
diff options
context:
space:
mode:
authorReinier Zwitserloot <r.zwitserloot@projectlombok.org>2020-01-20 15:25:08 +0100
committerReinier Zwitserloot <r.zwitserloot@projectlombok.org>2020-01-28 16:21:39 +0100
commite95680a76733c22ee5937a586ee50c703d5ba621 (patch)
tree3eaefce07c41760468c3c2a17c86297e2304a730 /src/core/lombok/javac/handlers
parentfa70b194aa7db62bdbc4cc759a606f97fe50fc92 (diff)
downloadlombok-e95680a76733c22ee5937a586ee50c703d5ba621.tar.gz
lombok-e95680a76733c22ee5937a586ee50c703d5ba621.tar.bz2
lombok-e95680a76733c22ee5937a586ee50c703d5ba621.zip
[issue #2221] [issue #788] Lombok now adds nullity annotations.
Which 'flavour' is defined in lombok.config; applied to toString, equals, canEqual, and plural-form of `@Singular`.
Diffstat (limited to 'src/core/lombok/javac/handlers')
-rw-r--r--src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java21
-rw-r--r--src/core/lombok/javac/handlers/HandleToString.java8
-rw-r--r--src/core/lombok/javac/handlers/HandleWith.java3
-rw-r--r--src/core/lombok/javac/handlers/JavacHandlerUtil.java99
-rw-r--r--src/core/lombok/javac/handlers/JavacSingularsRecipes.java22
-rw-r--r--src/core/lombok/javac/handlers/singulars/JavacGuavaSingularizer.java11
6 files changed, 130 insertions, 34 deletions
diff --git a/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java b/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java
index 0d0369b9..c4cf28da 100644
--- a/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java
+++ b/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java
@@ -383,18 +383,6 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas
List<JCAnnotation> annsOnParamOnMethod = List.nil();
- String nearest = scanForNearestAnnotation(typeNode, "org.eclipse.jdt.annotation.NonNullByDefault");
- if (nearest != null) {
- JCAnnotation m = maker.Annotation(genTypeRef(typeNode, "org.eclipse.jdt.annotation.Nullable"), List.<JCExpression>nil());
- annsOnParamOnMethod = annsOnParamOnMethod.prepend(m);
- }
-
- nearest = scanForNearestAnnotation(typeNode, "javax.annotation.ParametersAreNullableByDefault", "javax.annotation.ParametersAreNonnullByDefault");
- if ("javax.annotation.ParametersAreNonnullByDefault".equals(nearest)) {
- JCAnnotation m = maker.Annotation(genTypeRef(typeNode, "javax.annotation.Nullable"), List.<JCExpression>nil());
- annsOnParamOnMethod = annsOnParamOnMethod.prepend(m);
- }
-
JCAnnotation overrideAnnotation = maker.Annotation(genJavaLangTypeRef(typeNode, "Override"), List.<JCExpression>nil());
List<JCAnnotation> annsOnMethod = List.of(overrideAnnotation);
CheckerFrameworkVersion checkerFramework = getCheckerFrameworkVersion(typeNode);
@@ -415,7 +403,10 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas
long finalFlag = JavacHandlerUtil.addFinalIfNeeded(0L, typeNode.getContext());
ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>();
- final List<JCVariableDecl> params = List.of(maker.VarDef(maker.Modifiers(finalFlag | Flags.PARAMETER, onParam), oName, objectType, null));
+ JCVariableDecl param = maker.VarDef(maker.Modifiers(finalFlag | Flags.PARAMETER, onParam), oName, objectType, null);
+ JavacHandlerUtil.createRelevantNullableAnnotation(typeNode, param);
+
+ final List<JCVariableDecl> params = List.of(param);
/* if (o == this) return true; */ {
statements.append(maker.If(maker.Binary(CTC_EQUAL, maker.Ident(oName),
@@ -538,7 +529,9 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas
JCExpression objectType = genJavaLangTypeRef(typeNode, "Object");
Name otherName = typeNode.toName("other");
long flags = JavacHandlerUtil.addFinalIfNeeded(Flags.PARAMETER, typeNode.getContext());
- List<JCVariableDecl> params = List.of(maker.VarDef(maker.Modifiers(flags, onParam), otherName, objectType, null));
+ JCVariableDecl param = maker.VarDef(maker.Modifiers(flags, onParam), otherName, objectType, null);
+ createRelevantNullableAnnotation(typeNode, param);
+ List<JCVariableDecl> params = List.of(param);
JCBlock body = maker.Block(0, List.<JCStatement>of(
maker.Return(maker.TypeTest(maker.Ident(otherName), createTypeReference(typeNode, false)))));
diff --git a/src/core/lombok/javac/handlers/HandleToString.java b/src/core/lombok/javac/handlers/HandleToString.java
index d0d36e06..0a950f7c 100644
--- a/src/core/lombok/javac/handlers/HandleToString.java
+++ b/src/core/lombok/javac/handlers/HandleToString.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2019 The Project Lombok Authors.
+ * Copyright (C) 2009-2020 The Project Lombok Authors.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -253,8 +253,10 @@ public class HandleToString extends JavacAnnotationHandler<ToString> {
JCBlock body = maker.Block(0, List.of(returnStatement));
- return recursiveSetGeneratedBy(maker.MethodDef(mods, typeNode.toName("toString"), returnType,
- List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null), source, typeNode.getContext());
+ JCMethodDecl methodDef = maker.MethodDef(mods, typeNode.toName("toString"), returnType,
+ List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null);
+ createRelevantNonNullAnnotation(typeNode, methodDef);
+ return recursiveSetGeneratedBy(methodDef, source, typeNode.getContext());
}
public static String getTypeName(JavacNode typeNode) {
diff --git a/src/core/lombok/javac/handlers/HandleWith.java b/src/core/lombok/javac/handlers/HandleWith.java
index 7b2417da..6977b10e 100644
--- a/src/core/lombok/javac/handlers/HandleWith.java
+++ b/src/core/lombok/javac/handlers/HandleWith.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2019 The Project Lombok Authors.
+ * Copyright (C) 2012-2020 The Project Lombok Authors.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -211,6 +211,7 @@ public class HandleWith extends JavacAnnotationHandler<With> {
long access = toJavacModifier(level);
JCMethodDecl createdWith = createWith(access, fieldNode, fieldNode.getTreeMaker(), source, onMethod, onParam, makeAbstract);
+ createRelevantNonNullAnnotation(fieldNode, createdWith);
ClassSymbol sym = ((JCClassDecl) fieldNode.up().get()).sym;
Type returnType = sym == null ? null : sym.type;
diff --git a/src/core/lombok/javac/handlers/JavacHandlerUtil.java b/src/core/lombok/javac/handlers/JavacHandlerUtil.java
index 9359b1ae..0ef8c359 100644
--- a/src/core/lombok/javac/handlers/JavacHandlerUtil.java
+++ b/src/core/lombok/javac/handlers/JavacHandlerUtil.java
@@ -94,6 +94,7 @@ import lombok.core.CleanupTask;
import lombok.core.LombokImmutableList;
import lombok.core.TypeResolver;
import lombok.core.configuration.CheckerFrameworkVersion;
+import lombok.core.configuration.NullAnnotationLibrary;
import lombok.core.configuration.NullCheckExceptionType;
import lombok.core.configuration.TypeName;
import lombok.core.handlers.HandlerUtil;
@@ -1085,6 +1086,13 @@ public class JavacHandlerUtil {
}
}
+ static void setAnnotations(JCTree obj, List<JCAnnotation> anns) {
+ init(obj.getClass());
+ try {
+ ANNOTATIONS.set(obj, anns);
+ } catch (Exception e) {}
+ }
+
static JCExpression getUnderlyingType(JCTree obj) {
init(obj.getClass());
try {
@@ -2054,4 +2062,95 @@ public class JavacHandlerUtil {
String p = extending.toString();
return p.equals("Object") || p.equals("java.lang.Object");
}
+
+ public static void createRelevantNullableAnnotation(JavacNode typeNode, JCMethodDecl mth) {
+ NullAnnotationLibrary lib = typeNode.getAst().readConfiguration(ConfigurationKeys.ADD_NULL_ANNOTATIONS);
+ if (lib == null) return;
+ applyAnnotationToMethodDecl(typeNode, mth, lib.getNullableAnnotation(), lib.isTypeUse());
+ }
+
+ public static void createRelevantNonNullAnnotation(JavacNode typeNode, JCMethodDecl mth) {
+ NullAnnotationLibrary lib = typeNode.getAst().readConfiguration(ConfigurationKeys.ADD_NULL_ANNOTATIONS);
+ if (lib == null) return;
+ applyAnnotationToMethodDecl(typeNode, mth, lib.getNonNullAnnotation(), lib.isTypeUse());
+ }
+
+ public static void createRelevantNonNullAnnotation(JavacNode typeNode, JCVariableDecl arg) {
+ NullAnnotationLibrary lib = typeNode.getAst().readConfiguration(ConfigurationKeys.ADD_NULL_ANNOTATIONS);
+ if (lib == null) return;
+
+ applyAnnotationToVarDecl(typeNode, arg, lib.getNonNullAnnotation(), lib.isTypeUse());
+ }
+
+ public static void createRelevantNullableAnnotation(JavacNode typeNode, JCVariableDecl arg) {
+ NullAnnotationLibrary lib = typeNode.getAst().readConfiguration(ConfigurationKeys.ADD_NULL_ANNOTATIONS);
+ if (lib == null) return;
+
+ applyAnnotationToVarDecl(typeNode, arg, lib.getNullableAnnotation(), lib.isTypeUse());
+ }
+
+ private static void applyAnnotationToMethodDecl(JavacNode typeNode, JCMethodDecl mth, String annType, boolean typeUse) {
+ if (annType == null) return;
+ JavacTreeMaker maker = typeNode.getTreeMaker();
+
+ JCAnnotation m = maker.Annotation(genTypeRef(typeNode, annType), List.<JCExpression>nil());
+ if (typeUse) {
+ JCExpression resType = mth.restype;
+ if (resType instanceof JCTypeApply) {
+ JCTypeApply ta = (JCTypeApply) resType;
+ resType = ta.clazz;
+ }
+
+ if (resType instanceof JCFieldAccess || resType instanceof JCArrayTypeTree) {
+ mth.restype = maker.AnnotatedType(List.of(m), resType);
+ return;
+ }
+
+ if (JCAnnotatedTypeReflect.is(resType)) {
+ List<JCAnnotation> annotations = JCAnnotatedTypeReflect.getAnnotations(resType);
+ JCAnnotatedTypeReflect.setAnnotations(resType, annotations.prepend(m));
+ return;
+ }
+
+ if (resType instanceof JCPrimitiveTypeTree || resType instanceof JCIdent) {
+ mth.mods.annotations = mth.mods.annotations == null ? List.of(m) : mth.mods.annotations.prepend(m);
+ }
+ } else {
+ mth.mods.annotations = mth.mods.annotations == null ? List.of(m) : mth.mods.annotations.prepend(m);
+ }
+ }
+
+ private static void applyAnnotationToVarDecl(JavacNode typeNode, JCVariableDecl arg, String annType, boolean typeUse) {
+ if (annType == null) return;
+ JavacTreeMaker maker = typeNode.getTreeMaker();
+
+ JCAnnotation m = maker.Annotation(genTypeRef(typeNode, annType), List.<JCExpression>nil());
+ if (typeUse) {
+ JCExpression varType = arg.vartype;
+ JCTypeApply ta = null;
+ if (varType instanceof JCTypeApply) {
+ ta = (JCTypeApply) varType;
+ varType = ta.clazz;
+ }
+
+ if (varType instanceof JCFieldAccess || varType instanceof JCArrayTypeTree) {
+ varType = maker.AnnotatedType(List.of(m), varType);
+ if (ta != null) ta.clazz = varType;
+ else arg.vartype = varType;
+ return;
+ }
+
+ if (JCAnnotatedTypeReflect.is(varType)) {
+ List<JCAnnotation> annotations = JCAnnotatedTypeReflect.getAnnotations(varType);
+ JCAnnotatedTypeReflect.setAnnotations(varType, annotations.prepend(m));
+ return;
+ }
+
+ if (varType instanceof JCPrimitiveTypeTree || varType instanceof JCIdent) {
+ arg.mods.annotations = arg.mods.annotations == null ? List.of(m) : arg.mods.annotations.prepend(m);
+ }
+ } else {
+ arg.mods.annotations = arg.mods.annotations == null ? List.of(m) : arg.mods.annotations.prepend(m);
+ }
+ }
}
diff --git a/src/core/lombok/javac/handlers/JavacSingularsRecipes.java b/src/core/lombok/javac/handlers/JavacSingularsRecipes.java
index a5d4a295..9dab3da5 100644
--- a/src/core/lombok/javac/handlers/JavacSingularsRecipes.java
+++ b/src/core/lombok/javac/handlers/JavacSingularsRecipes.java
@@ -273,12 +273,19 @@ public class JavacSingularsRecipes {
generateClearMethod(cfv, deprecate, maker, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, source, access);
}
- private void finishAndInjectMethod(CheckerFrameworkVersion cfv, JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source, boolean deprecate, ListBuffer<JCStatement> statements, Name methodName, List<JCVariableDecl> jcVariableDecls, AccessLevel access) {
+ private void finishAndInjectMethod(CheckerFrameworkVersion cfv, JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source, boolean deprecate, ListBuffer<JCStatement> statements, Name methodName, List<JCVariableDecl> jcVariableDecls, AccessLevel access, NullCollectionBehavior nullBehavior) {
if (returnStatement != null) statements.append(returnStatement);
JCBlock body = maker.Block(0, statements.toList());
JCModifiers mods = makeMods(maker, cfv, builderType, deprecate, access);
List<JCTypeParameter> typeParams = List.nil();
List<JCExpression> thrown = List.nil();
+
+ if (nullBehavior == NullCollectionBehavior.IGNORE) {
+ for (JCVariableDecl d : jcVariableDecls) createRelevantNullableAnnotation(builderType, d);
+ } else if (nullBehavior != null) {
+ for (JCVariableDecl d : jcVariableDecls) createRelevantNonNullAnnotation(builderType, d);
+ }
+
JCMethodDecl method = maker.MethodDef(mods, methodName, returnType, typeParams, jcVariableDecls, thrown, body, null);
recursiveSetGeneratedBy(method, source, builderType.getContext());
injectMethod(builderType, method);
@@ -290,7 +297,7 @@ public class JavacSingularsRecipes {
statements.add(clearStatement);
Name methodName = builderType.toName(HandlerUtil.buildAccessorName("clear", data.getPluralName().toString()));
- finishAndInjectMethod(cfv, maker, returnType, returnStatement, data, builderType, source, deprecate, statements, methodName, List.<JCVariableDecl>nil(), access);
+ finishAndInjectMethod(cfv, maker, returnType, returnStatement, data, builderType, source, deprecate, statements, methodName, List.<JCVariableDecl>nil(), access, null);
}
protected abstract JCStatement generateClearStatements(JavacTreeMaker maker, SingularData data, JavacNode builderType);
@@ -304,7 +311,7 @@ public class JavacSingularsRecipes {
if (!setterPrefix.isEmpty()) name = builderType.toName(HandlerUtil.buildAccessorName(setterPrefix, name.toString()));
statements.prepend(createConstructBuilderVarIfNeeded(maker, data, builderType, source));
- finishAndInjectMethod(cfv, maker, returnType, returnStatement, data, builderType, source, deprecate, statements, name, params, access);
+ finishAndInjectMethod(cfv, maker, returnType, returnStatement, data, builderType, source, deprecate, statements, name, params, access, null);
}
protected JCVariableDecl generateSingularMethodParameter(int typeIndex, JavacTreeMaker maker, SingularData data, JavacNode builderType, JCTree source, Name name) {
@@ -336,10 +343,11 @@ public class JavacSingularsRecipes {
JCExpression paramType = getPluralMethodParamType(builderType);
paramType = addTypeArgs(getTypeArgumentsCount(), true, builderType, paramType, data.getTypeArgs(), source);
long paramFlags = JavacHandlerUtil.addFinalIfNeeded(Flags.PARAMETER, builderType.getContext());
- JCVariableDecl param = maker.VarDef(maker.Modifiers(paramFlags), data.getPluralName(), paramType, null);
- statements.prepend(createConstructBuilderVarIfNeeded(maker, data, builderType, source));
-
NullCollectionBehavior behavior = data.getNullCollectionBehavior();
+ if (behavior == null) behavior = NullCollectionBehavior.IGNORE;
+ JCModifiers paramMods = maker.Modifiers(paramFlags);
+ JCVariableDecl param = maker.VarDef(paramMods, data.getPluralName(), paramType, null);
+ statements.prepend(createConstructBuilderVarIfNeeded(maker, data, builderType, source));
if (behavior == NullCollectionBehavior.IGNORE) {
JCExpression incomingIsNotNull = maker.Binary(CTC_NOT_EQUAL, maker.Ident(data.getPluralName()), maker.Literal(CTC_BOT, null));
@@ -361,7 +369,7 @@ public class JavacSingularsRecipes {
}
}
- finishAndInjectMethod(cfv, maker, returnType, returnStatement, data, builderType, source, deprecate, statements, name, List.of(param), access);
+ finishAndInjectMethod(cfv, maker, returnType, returnStatement, data, builderType, source, deprecate, statements, name, List.of(param), access, behavior);
}
protected ListBuffer<JCStatement> generatePluralMethodStatements(JavacTreeMaker maker, SingularData data, JavacNode builderType, JCTree source) {
diff --git a/src/core/lombok/javac/handlers/singulars/JavacGuavaSingularizer.java b/src/core/lombok/javac/handlers/singulars/JavacGuavaSingularizer.java
index 546dc66e..7cd676c0 100644
--- a/src/core/lombok/javac/handlers/singulars/JavacGuavaSingularizer.java
+++ b/src/core/lombok/javac/handlers/singulars/JavacGuavaSingularizer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015-2018 The Project Lombok Authors.
+ * Copyright (C) 2015-2020 The Project Lombok Authors.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -121,14 +121,7 @@ abstract class JavacGuavaSingularizer extends JavacSingularizer {
@Override
protected JCExpression getPluralMethodParamType(JavacNode builderType) {
- JCExpression paramType;
- String aaTypeName = getAddAllTypeName();
- if (aaTypeName.startsWith("java.lang.") && aaTypeName.indexOf('.', 11) == -1) {
- paramType = genJavaLangTypeRef(builderType, aaTypeName.substring(10));
- } else {
- paramType = chainDotsString(builderType, aaTypeName);
- }
- return paramType;
+ return genTypeRef(builderType, getAddAllTypeName());
}
@Override public void appendBuildCode(SingularData data, JavacNode builderType, JCTree source, ListBuffer<JCStatement> statements, Name targetVariableName, String builderVariable) {