diff options
author | Reinier Zwitserloot <r.zwitserloot@projectlombok.org> | 2020-01-20 15:25:08 +0100 |
---|---|---|
committer | Reinier Zwitserloot <r.zwitserloot@projectlombok.org> | 2020-01-28 16:21:39 +0100 |
commit | e95680a76733c22ee5937a586ee50c703d5ba621 (patch) | |
tree | 3eaefce07c41760468c3c2a17c86297e2304a730 /src/core/lombok/eclipse | |
parent | fa70b194aa7db62bdbc4cc759a606f97fe50fc92 (diff) | |
download | lombok-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/eclipse')
8 files changed, 126 insertions, 16 deletions
diff --git a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java index aa48e000..bd0ad23b 100644 --- a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java +++ b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java @@ -43,6 +43,7 @@ import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration; import org.eclipse.jdt.internal.compiler.ast.AllocationExpression; import org.eclipse.jdt.internal.compiler.ast.Annotation; +import org.eclipse.jdt.internal.compiler.ast.Argument; import org.eclipse.jdt.internal.compiler.ast.ArrayInitializer; import org.eclipse.jdt.internal.compiler.ast.ArrayQualifiedTypeReference; import org.eclipse.jdt.internal.compiler.ast.ArrayTypeReference; @@ -112,6 +113,7 @@ import lombok.core.AnnotationValues.AnnotationValue; 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.debug.ProblemReporter; @@ -2381,6 +2383,101 @@ public class EclipseHandlerUtil { return p.equals("Object") || p.equals("java.lang.Object"); } + public static void createRelevantNullableAnnotation(EclipseNode typeNode, MethodDeclaration 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(EclipseNode typeNode, MethodDeclaration mth) { + NullAnnotationLibrary lib = typeNode.getAst().readConfiguration(ConfigurationKeys.ADD_NULL_ANNOTATIONS); + if (lib == null) return; + + applyAnnotationToMethodDecl(typeNode, mth, lib.getNonNullAnnotation(), lib.isTypeUse()); + } + + public static void createRelevantNullableAnnotation(EclipseNode typeNode, Argument arg) { + NullAnnotationLibrary lib = typeNode.getAst().readConfiguration(ConfigurationKeys.ADD_NULL_ANNOTATIONS); + if (lib == null) return; + + applyAnnotationToVarDecl(typeNode, arg, lib.getNullableAnnotation(), lib.isTypeUse()); + } + + public static void createRelevantNonNullAnnotation(EclipseNode typeNode, Argument arg) { + NullAnnotationLibrary lib = typeNode.getAst().readConfiguration(ConfigurationKeys.ADD_NULL_ANNOTATIONS); + if (lib == null) return; + + applyAnnotationToVarDecl(typeNode, arg, lib.getNonNullAnnotation(), lib.isTypeUse()); + } + + private static void applyAnnotationToMethodDecl(EclipseNode typeNode, MethodDeclaration mth, String annType, boolean typeUse) { + if (annType == null) return; + + int partCount = 1; + for (int i = 0; i < annType.length(); i++) if (annType.charAt(i) == '.') partCount++; + long[] ps = new long[partCount]; + Arrays.fill(ps, 0L); + Annotation ann = new MarkerAnnotation(new QualifiedTypeReference(Eclipse.fromQualifiedName(annType), ps), 0); + + if (!typeUse || mth.returnType == null || mth.returnType.getTypeName().length < 2) { + Annotation[] a = mth.annotations; + if (a == null) a = new Annotation[1]; + else { + Annotation[] b = new Annotation[a.length + 1]; + System.arraycopy(a, 0, b, 0, a.length); + a = b; + } + a[a.length - 1] = ann; + mth.annotations = a; + } else { + int len = mth.returnType.getTypeName().length; + if (mth.returnType.annotations == null) mth.returnType.annotations = new Annotation[len][]; + Annotation[] a = mth.returnType.annotations[len - 1]; + if (a == null) a = new Annotation[1]; + else { + Annotation[] b = new Annotation[a.length + 1]; + System.arraycopy(a, 0, b, 1, a.length); + a = b; + } + a[0] = ann; + mth.returnType.annotations[len - 1] = a; + } + } + private static void applyAnnotationToVarDecl(EclipseNode typeNode, Argument arg, String annType, boolean typeUse) { + if (annType == null) return; + + int partCount = 1; + for (int i = 0; i < annType.length(); i++) if (annType.charAt(i) == '.') partCount++; + long[] ps = new long[partCount]; + Arrays.fill(ps, 0L); + Annotation ann = new MarkerAnnotation(new QualifiedTypeReference(Eclipse.fromQualifiedName(annType), ps), 0); + + if (!typeUse || arg.type.getTypeName().length < 2) { + Annotation[] a = arg.annotations; + if (a == null) a = new Annotation[1]; + else { + Annotation[] b = new Annotation[a.length + 1]; + System.arraycopy(a, 0, b, 0, a.length); + a = b; + } + a[a.length - 1] = ann; + arg.annotations = a; + } else { + int len = arg.type.getTypeName().length; + if (arg.type.annotations == null) arg.type.annotations = new Annotation[len][]; + Annotation[] a = arg.type.annotations[len - 1]; + if (a == null) a = new Annotation[1]; + else { + Annotation[] b = new Annotation[a.length + 1]; + System.arraycopy(a, 0, b, 1, a.length); + a = b; + } + a[0] = ann; + arg.type.annotations[len - 1] = a; + } + } + public static NameReference generateQualifiedNameRef(ASTNode source, char[]... varNames) { int pS = source.sourceStart, pE = source.sourceEnd; long p = (long)pS << 32 | pE; diff --git a/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java b/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java index 5fe4b958..cbbd4cc8 100755 --- a/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java +++ b/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java @@ -35,6 +35,7 @@ import org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; import org.eclipse.jdt.internal.compiler.ast.AllocationExpression; import org.eclipse.jdt.internal.compiler.ast.Annotation; +import org.eclipse.jdt.internal.compiler.ast.Argument; import org.eclipse.jdt.internal.compiler.ast.Block; import org.eclipse.jdt.internal.compiler.ast.ConditionalExpression; import org.eclipse.jdt.internal.compiler.ast.EqualExpression; @@ -437,7 +438,7 @@ public class EclipseSingularsRecipes { } } - protected void nullBehaviorize(SingularData data, List<Statement> statements) { + protected void nullBehaviorize(EclipseNode typeNode, SingularData data, List<Statement> statements, Argument arg) { NullCollectionBehavior behavior = data.getNullCollectionBehavior(); if (behavior == NullCollectionBehavior.IGNORE) { @@ -446,9 +447,12 @@ public class EclipseSingularsRecipes { b.statements = statements.toArray(new Statement[statements.size()]); statements.clear(); statements.add(new IfStatement(isNotNull, b, 0, 0)); + EclipseHandlerUtil.createRelevantNullableAnnotation(typeNode, arg); return; } + EclipseHandlerUtil.createRelevantNonNullAnnotation(typeNode, arg); + String exceptionTypeStr = behavior.getExceptionType(); StringLiteral message = new StringLiteral(behavior.toExceptionMessage(new String(data.getPluralName())).toCharArray(), 0, 0, 0); if (exceptionTypeStr != null) { diff --git a/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java b/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java index 46474b07..959b2cae 100755 --- a/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java +++ b/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java @@ -557,6 +557,7 @@ public class HandleEqualsAndHashCode extends EclipseAnnotationHandler<EqualsAndH method.arguments = new Argument[] {new Argument(new char[] { 'o' }, 0, objectRef, Modifier.FINAL)}; method.arguments[0].sourceStart = pS; method.arguments[0].sourceEnd = pE; if (!onParam.isEmpty()) method.arguments[0].annotations = onParam.toArray(new Annotation[0]); + EclipseHandlerUtil.createRelevantNullableAnnotation(type, method.arguments[0]); setGeneratedBy(method.arguments[0], source); List<Statement> statements = new ArrayList<Statement>(); @@ -806,6 +807,7 @@ public class HandleEqualsAndHashCode extends EclipseAnnotationHandler<EqualsAndH method.arguments = new Argument[] {new Argument(otherName, 0, objectRef, Modifier.FINAL)}; method.arguments[0].sourceStart = pS; method.arguments[0].sourceEnd = pE; if (!onParam.isEmpty()) method.arguments[0].annotations = onParam.toArray(new Annotation[0]); + EclipseHandlerUtil.createRelevantNullableAnnotation(type, method.arguments[0]); setGeneratedBy(method.arguments[0], source); SingleNameReference otherRef = new SingleNameReference(otherName, p); diff --git a/src/core/lombok/eclipse/handlers/HandleToString.java b/src/core/lombok/eclipse/handlers/HandleToString.java index 39fd5937..a6bcb24f 100644 --- a/src/core/lombok/eclipse/handlers/HandleToString.java +++ b/src/core/lombok/eclipse/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 @@ -315,6 +315,7 @@ public class HandleToString extends EclipseAnnotationHandler<ToString> { method.bodyStart = method.declarationSourceStart = method.sourceStart = source.sourceStart; method.bodyEnd = method.declarationSourceEnd = method.sourceEnd = source.sourceEnd; method.statements = new Statement[] { returnStatement }; + EclipseHandlerUtil.createRelevantNonNullAnnotation(type, method); return method; } diff --git a/src/core/lombok/eclipse/handlers/HandleWith.java b/src/core/lombok/eclipse/handlers/HandleWith.java index 8c8c3712..4771818d 100644 --- a/src/core/lombok/eclipse/handlers/HandleWith.java +++ b/src/core/lombok/eclipse/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 @@ -287,6 +287,8 @@ public class HandleWith extends EclipseAnnotationHandler<With> { } param.annotations = copyAnnotations(source, copyableAnnotations, onParam.toArray(new Annotation[0])); + EclipseHandlerUtil.createRelevantNonNullAnnotation(fieldNode, method); + method.traverse(new SetGeneratedByVisitor(source), parent.scope); return method; } diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java index b067ad80..5d656c91 100755 --- a/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java +++ b/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java @@ -196,16 +196,18 @@ abstract class EclipseGuavaSingularizer extends EclipseSingularizer { thisDotFieldDotAddAll.selector = (getAddMethodName() + "All").toCharArray(); statements.add(thisDotFieldDotAddAll); - nullBehaviorize(data, statements); + TypeReference paramType; + paramType = new QualifiedTypeReference(fromQualifiedName(getAddAllTypeName()), NULL_POSS); + paramType = addTypeArgs(getTypeArgumentsCount(), true, builderType, paramType, data.getTypeArgs()); + Argument param = new Argument(data.getPluralName(), 0, paramType, ClassFileConstants.AccFinal); + + nullBehaviorize(builderType, data, statements, param); if (returnStatement != null) statements.add(returnStatement); md.statements = statements.toArray(new Statement[0]); - TypeReference paramType; - paramType = new QualifiedTypeReference(fromQualifiedName(getAddAllTypeName()), NULL_POSS); - paramType = addTypeArgs(getTypeArgumentsCount(), true, builderType, paramType, data.getTypeArgs()); - Argument param = new Argument(data.getPluralName(), 0, paramType, ClassFileConstants.AccFinal); + md.arguments = new Argument[] {param}; md.returnType = returnType; char[] prefixedSelector = data.getSetterPrefix().length == 0 ? data.getPluralName() : HandlerUtil.buildAccessorName(new String(data.getSetterPrefix()), new String(data.getPluralName())).toCharArray(); diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java index ba447397..024f5880 100755 --- a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java +++ b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java @@ -174,14 +174,15 @@ abstract class EclipseJavaUtilListSetSingularizer extends EclipseJavaUtilSingula thisDotFieldDotAddAll.selector = "addAll".toCharArray(); statements.add(thisDotFieldDotAddAll); - nullBehaviorize(data, statements); + TypeReference paramType = new QualifiedTypeReference(TypeConstants.JAVA_UTIL_COLLECTION, NULL_POSS); + paramType = addTypeArgs(1, true, builderType, paramType, data.getTypeArgs()); + Argument param = new Argument(data.getPluralName(), 0, paramType, ClassFileConstants.AccFinal); + + nullBehaviorize(builderType, data, statements, param); if (returnStatement != null) statements.add(returnStatement); md.statements = statements.toArray(new Statement[0]); - TypeReference paramType = new QualifiedTypeReference(TypeConstants.JAVA_UTIL_COLLECTION, NULL_POSS); - paramType = addTypeArgs(1, true, builderType, paramType, data.getTypeArgs()); - Argument param = new Argument(data.getPluralName(), 0, paramType, ClassFileConstants.AccFinal); md.arguments = new Argument[] {param}; md.returnType = returnType; char[] prefixedSelector = data.getSetterPrefix().length == 0 ? data.getPluralName() : HandlerUtil.buildAccessorName(new String(data.getSetterPrefix()), new String(data.getPluralName())).toCharArray(); diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java index e91c6616..843fd073 100755 --- a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java +++ b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java @@ -306,15 +306,16 @@ public class EclipseJavaUtilMapSingularizer extends EclipseJavaUtilSingularizer forEach.action = forEachContent; statements.add(forEach); - nullBehaviorize(data, statements); + TypeReference paramType = new QualifiedTypeReference(JAVA_UTIL_MAP, NULL_POSS); + paramType = addTypeArgs(2, true, builderType, paramType, data.getTypeArgs()); + Argument param = new Argument(data.getPluralName(), 0, paramType, ClassFileConstants.AccFinal); + + nullBehaviorize(builderType, data, statements, param); if (returnStatement != null) statements.add(returnStatement); md.statements = statements.toArray(new Statement[0]); - TypeReference paramType = new QualifiedTypeReference(JAVA_UTIL_MAP, NULL_POSS); - paramType = addTypeArgs(2, true, builderType, paramType, data.getTypeArgs()); - Argument param = new Argument(data.getPluralName(), 0, paramType, ClassFileConstants.AccFinal); md.arguments = new Argument[] {param}; md.returnType = returnType; |