aboutsummaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
authorReinier Zwitserloot <r.zwitserloot@projectlombok.org>2019-08-22 23:26:55 +0200
committerGitHub <noreply@github.com>2019-08-22 23:26:55 +0200
commitdb19a9fd8320a0abf7a530e9e35639089ce77050 (patch)
treebfd83d64061f1606470e91ae24dc4c8693b10015 /src/core
parent819d1956761f6077fdf897e77c4f6ac47e92104e (diff)
parentba8fd3782819682b3f4081cb410b6d43055989b9 (diff)
downloadlombok-db19a9fd8320a0abf7a530e9e35639089ce77050.tar.gz
lombok-db19a9fd8320a0abf7a530e9e35639089ce77050.tar.bz2
lombok-db19a9fd8320a0abf7a530e9e35639089ce77050.zip
Merge branch 'master' into clone-type
Diffstat (limited to 'src/core')
-rw-r--r--src/core/lombok/ConfigurationKeys.java10
-rw-r--r--src/core/lombok/core/configuration/CheckerFrameworkVersion.java86
-rw-r--r--src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java33
-rwxr-xr-xsrc/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java17
-rwxr-xr-xsrc/core/lombok/eclipse/handlers/HandleBuilder.java93
-rwxr-xr-xsrc/core/lombok/eclipse/handlers/HandleConstructor.java17
-rwxr-xr-xsrc/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java18
-rw-r--r--src/core/lombok/eclipse/handlers/HandleGetter.java13
-rw-r--r--src/core/lombok/eclipse/handlers/HandleSetter.java7
-rwxr-xr-xsrc/core/lombok/eclipse/handlers/HandleSuperBuilder.java106
-rw-r--r--src/core/lombok/eclipse/handlers/HandleToString.java10
-rw-r--r--src/core/lombok/eclipse/handlers/HandleWither.java13
-rwxr-xr-xsrc/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java21
-rwxr-xr-xsrc/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java23
-rwxr-xr-xsrc/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java23
-rw-r--r--src/core/lombok/javac/handlers/HandleBuilder.java69
-rw-r--r--src/core/lombok/javac/handlers/HandleConstructor.java9
-rw-r--r--src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java22
-rw-r--r--src/core/lombok/javac/handlers/HandleGetter.java9
-rw-r--r--src/core/lombok/javac/handlers/HandleSetter.java11
-rw-r--r--src/core/lombok/javac/handlers/HandleSuperBuilder.java95
-rw-r--r--src/core/lombok/javac/handlers/HandleToString.java9
-rw-r--r--src/core/lombok/javac/handlers/HandleWither.java10
-rw-r--r--src/core/lombok/javac/handlers/JavacHandlerUtil.java8
-rw-r--r--src/core/lombok/javac/handlers/JavacSingularsRecipes.java40
-rw-r--r--src/core/lombok/javac/handlers/singulars/JavacGuavaSingularizer.java5
-rw-r--r--src/core/lombok/javac/handlers/singulars/JavacJavaUtilListSetSingularizer.java5
-rw-r--r--src/core/lombok/javac/handlers/singulars/JavacJavaUtilMapSingularizer.java5
28 files changed, 586 insertions, 201 deletions
diff --git a/src/core/lombok/ConfigurationKeys.java b/src/core/lombok/ConfigurationKeys.java
index dda0b54b..d46889d6 100644
--- a/src/core/lombok/ConfigurationKeys.java
+++ b/src/core/lombok/ConfigurationKeys.java
@@ -24,6 +24,7 @@ package lombok;
import java.util.List;
import lombok.core.configuration.CallSuperType;
+import lombok.core.configuration.CheckerFrameworkVersion;
import lombok.core.configuration.ConfigurationKey;
import lombok.core.configuration.LogDeclaration;
import lombok.core.configuration.FlagUsageType;
@@ -627,5 +628,14 @@ public class ConfigurationKeys {
* Copy these annotations to getters, setters, withers, builder-setters, etc.
*/
public static final ConfigurationKey<List<TypeName>> COPYABLE_ANNOTATIONS = new ConfigurationKey<List<TypeName>>("lombok.copyableAnnotations", "Copy these annotations to getters, setters, withers, builder-setters, etc.") {};
+
+ /**
+ * lombok configuration: {@code checkerframework} = {@code true} | {@code false} | &lt;String: MajorVer.MinorVer&gt; (Default: false).
+ *
+ * If set, lombok will generate appropriate annotations from checkerframework.org on generated code. If set to {@code true}, all relevant annotations from the most recent version of
+ * checkerframework.org that lombok supports will be generated. If set to a specific major/minor version number, only checkerframework annotations introduced on or before the stated
+ * checkerframework.org version will be generated.
+ */
+ public static final ConfigurationKey<CheckerFrameworkVersion> CHECKER_FRAMEWORK = new ConfigurationKey<CheckerFrameworkVersion>("checkerframework", "If set with the version of checkerframework.org (in major.minor, or just 'true' for the latest supported version), create relevant checkerframework.org annotations for code lombok generates (default: false).") {};
}
diff --git a/src/core/lombok/core/configuration/CheckerFrameworkVersion.java b/src/core/lombok/core/configuration/CheckerFrameworkVersion.java
new file mode 100644
index 00000000..68fc05a7
--- /dev/null
+++ b/src/core/lombok/core/configuration/CheckerFrameworkVersion.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2019 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
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package lombok.core.configuration;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public final class CheckerFrameworkVersion implements ConfigurationValueType {
+ private final int version;
+ private static final int MAX_SUPPORTED = 3000;
+
+ public static final String NAME__SIDE_EFFECT_FREE = "org.checkerframework.dataflow.qual.SideEffectFree";
+ public static final String NAME__UNIQUE = "org.checkerframework.common.aliasing.qual.Unique";
+ public static final String NAME__RETURNS_RECEIVER = "org.checkerframework.checker.builder.qual.ReturnsReceiver";
+ public static final String NAME__NOT_CALLED = "org.checkerframework.checker.builder.qual.NotCalledMethods";
+ public static final String NAME__CALLED = "org.checkerframework.checker.builder.qual.CalledMethods";
+
+ public static final CheckerFrameworkVersion NONE = new CheckerFrameworkVersion(0);
+
+ private CheckerFrameworkVersion(int v) {
+ this.version = v;
+ }
+
+ private static final Pattern VERSION = Pattern.compile("^(\\d+)(?:\\.(\\d+))?(?:\\.\\d+)*$");
+
+ public boolean generateSideEffectFree() {
+ return version > 0;
+ }
+
+ public boolean generateUnique() {
+ return version > 0;
+ }
+
+ public boolean generateReturnsReceiver() {
+ return version > 2999;
+ }
+
+ public boolean generateCalledMethods() {
+ return version > 2999;
+ }
+
+ public static CheckerFrameworkVersion valueOf(String versionString) {
+ if (versionString != null) versionString = versionString.trim();
+ if (versionString == null || versionString.equalsIgnoreCase("false") || versionString.equals("0")) return new CheckerFrameworkVersion(0);
+ if (versionString.equalsIgnoreCase("true")) return new CheckerFrameworkVersion(MAX_SUPPORTED);
+ Matcher m = VERSION.matcher(versionString);
+ if (!m.matches()) throw new IllegalArgumentException("Expected 'true' or 'false' or a major/minor version, such as '2.9'");
+ int major = Integer.parseInt(m.group(1));
+ int minor = (m.group(2) != null && !m.group(2).isEmpty()) ? Integer.parseInt(m.group(2)) : 0;
+ if (minor > 999) throw new IllegalArgumentException("Minor version must be between 0 and 999");
+ int v = major * 1000 + minor;
+ if (v > MAX_SUPPORTED) {
+ String s = (v / 1000) + "." + (v % 1000);
+ throw new IllegalArgumentException("Lombok supports at most v" + s + "; reduce the value of key 'checkerframework' to " + s);
+ }
+ return new CheckerFrameworkVersion(v);
+ }
+
+ public static String description() {
+ return "checkerframework-version";
+ }
+
+ public static String exampleValue() {
+ String s = (MAX_SUPPORTED / 1000) + "." + (MAX_SUPPORTED % 1000);
+ return "major.minor (example: 2.9 - and no higher than " + s + ") or true or false";
+ }
+}
diff --git a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java
index 11a2b9bd..782c6a29 100644
--- a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java
+++ b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java
@@ -111,6 +111,7 @@ import lombok.core.AnnotationValues;
import lombok.core.AnnotationValues.AnnotationValue;
import lombok.core.LombokImmutableList;
import lombok.core.TypeResolver;
+import lombok.core.configuration.CheckerFrameworkVersion;
import lombok.core.configuration.NullCheckExceptionType;
import lombok.core.configuration.TypeName;
import lombok.core.debug.ProblemReporter;
@@ -184,6 +185,23 @@ public class EclipseHandlerUtil {
return ma;
}
+ public static MarkerAnnotation generateNamedAnnotation(ASTNode source, String typeName) {
+ char[][] cc = fromQualifiedName(typeName);
+ QualifiedTypeReference qtr = new QualifiedTypeReference(cc, poss(source, cc.length));
+ setGeneratedBy(qtr, source);
+ MarkerAnnotation ma = new MarkerAnnotation(qtr, source.sourceStart);
+ // No matter what value you input for sourceEnd, the AST->DOM converter of eclipse will reparse to find the end, and will fail as
+ // it can't find code that isn't really there. This results in the end position being set to 2 or 0 or some weird magic value, and thus,
+ // length, as calculated by end-start, is all screwed up, resulting in IllegalArgumentException during a setSourceRange call MUCH later in the process.
+ // We solve it by going with a voodoo magic source start value such that the calculated length so happens to exactly be 0. 0 lengths are accepted
+ // by eclipse. For some reason.
+ // TL;DR: Don't change 1. 1 is sacred. Trust the 1.
+ // issue: #408.
+ ma.sourceStart = 1;
+ setGeneratedBy(ma, source);
+ return ma;
+ }
+
public static boolean isFieldDeprecated(EclipseNode fieldNode) {
if (!(fieldNode.get() instanceof FieldDeclaration)) return false;
FieldDeclaration field = (FieldDeclaration) fieldNode.get();
@@ -199,6 +217,11 @@ public class EclipseHandlerUtil {
return false;
}
+ public static CheckerFrameworkVersion getCheckerFrameworkVersion(EclipseNode node) {
+ CheckerFrameworkVersion cfv = node.getAst().readConfiguration(ConfigurationKeys.CHECKER_FRAMEWORK);
+ return cfv != null ? cfv : CheckerFrameworkVersion.NONE;
+ }
+
/**
* Checks if the given TypeReference node is likely to be a reference to the provided class.
*
@@ -1908,11 +1931,13 @@ public class EclipseHandlerUtil {
* Create an annotation of the given name, and is marked as being generated by the given source.
*/
public static MarkerAnnotation makeMarkerAnnotation(char[][] name, ASTNode source) {
- long pos = (long)source.sourceStart << 32 | source.sourceEnd;
- TypeReference typeRef = new QualifiedTypeReference(name, new long[] {pos, pos, pos});
+ long pos = (long) source.sourceStart << 32 | source.sourceEnd;
+ long[] poss = new long[name.length];
+ Arrays.fill(poss, pos);
+ TypeReference typeRef = new QualifiedTypeReference(name, poss);
setGeneratedBy(typeRef, source);
- MarkerAnnotation ann = new MarkerAnnotation(typeRef, (int)(pos >> 32));
- ann.declarationSourceEnd = ann.sourceEnd = ann.statementEnd = (int)pos;
+ MarkerAnnotation ann = new MarkerAnnotation(typeRef, (int) (pos >> 32));
+ ann.declarationSourceEnd = ann.sourceEnd = ann.statementEnd = (int) pos;
setGeneratedBy(ann, source);
return ann;
}
diff --git a/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java b/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java
index a8a780d6..da0bf471 100755
--- a/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java
+++ b/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java
@@ -33,6 +33,7 @@ import java.util.Map;
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.Annotation;
import org.eclipse.jdt.internal.compiler.ast.ConditionalExpression;
import org.eclipse.jdt.internal.compiler.ast.EqualExpression;
import org.eclipse.jdt.internal.compiler.ast.Expression;
@@ -62,6 +63,7 @@ import lombok.AccessLevel;
import lombok.core.LombokImmutableList;
import lombok.core.SpiLoadUtil;
import lombok.core.TypeLibrary;
+import lombok.core.configuration.CheckerFrameworkVersion;
import lombok.eclipse.EclipseNode;
public class EclipseSingularsRecipes {
@@ -235,7 +237,7 @@ public class EclipseSingularsRecipes {
* If you need more control over the return type and value, use
* {@link #generateMethods(SingularData, boolean, EclipseNode, boolean, TypeReferenceMaker, StatementMaker)}.
*/
- public void generateMethods(SingularData data, boolean deprecate, final EclipseNode builderType, boolean fluent, final boolean chain, AccessLevel access) {
+ public void generateMethods(CheckerFrameworkVersion cfv, SingularData data, boolean deprecate, final EclipseNode builderType, boolean fluent, final boolean chain, AccessLevel access) {
TypeReferenceMaker returnTypeMaker = new TypeReferenceMaker() {
@Override public TypeReference make() {
return chain ? cloneSelfType(builderType) : TypeReference.baseTypeReference(TypeIds.T_void, 0);
@@ -248,14 +250,14 @@ public class EclipseSingularsRecipes {
}
};
- generateMethods(data, deprecate, builderType, fluent, returnTypeMaker, returnStatementMaker, access);
+ generateMethods(cfv, data, deprecate, builderType, fluent, returnTypeMaker, returnStatementMaker, access);
}
/**
* Generates the singular, plural, and clear methods for the given {@link SingularData}.
* Uses the given {@code returnTypeMaker} and {@code returnStatementMaker} for the generated methods.
*/
- public abstract void generateMethods(SingularData data, boolean deprecate, EclipseNode builderType, boolean fluent, TypeReferenceMaker returnTypeMaker, StatementMaker returnStatementMaker, AccessLevel access);
+ public abstract void generateMethods(CheckerFrameworkVersion cfv, SingularData data, boolean deprecate, EclipseNode builderType, boolean fluent, TypeReferenceMaker returnTypeMaker, StatementMaker returnStatementMaker, AccessLevel access);
public abstract void appendBuildCode(SingularData data, EclipseNode builderType, List<Statement> statements, char[] targetVariableName, String builderVariable);
@@ -272,6 +274,15 @@ public class EclipseSingularsRecipes {
// -- Utility methods --
+ protected Annotation[] generateSelfReturnAnnotations(boolean deprecate, CheckerFrameworkVersion cfv, ASTNode source) {
+ Annotation deprecated = deprecate ? generateDeprecatedAnnotation(source) : null;
+ Annotation returnsReceiver = cfv.generateReturnsReceiver() ? generateNamedAnnotation(source, CheckerFrameworkVersion.NAME__RETURNS_RECEIVER) : null;
+ if (deprecated == null && returnsReceiver == null) return null;
+ if (deprecated == null) return new Annotation[] {returnsReceiver};
+ if (returnsReceiver == null) return new Annotation[] {deprecated};
+ return new Annotation[] {deprecated, returnsReceiver};
+ }
+
/**
* Adds the requested number of type arguments to the provided type, copying each argument in {@code typeArgs}. If typeArgs is too long, the extra elements are ignored.
* If {@code typeArgs} is null or too short, {@code java.lang.Object} will be substituted for each missing type argument.
diff --git a/src/core/lombok/eclipse/handlers/HandleBuilder.java b/src/core/lombok/eclipse/handlers/HandleBuilder.java
index d2b1b823..8bfdeb65 100755
--- a/src/core/lombok/eclipse/handlers/HandleBuilder.java
+++ b/src/core/lombok/eclipse/handlers/HandleBuilder.java
@@ -37,6 +37,7 @@ 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.Assignment;
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
import org.eclipse.jdt.internal.compiler.ast.ConditionalExpression;
@@ -57,9 +58,11 @@ import org.eclipse.jdt.internal.compiler.ast.ParameterizedSingleTypeReference;
import org.eclipse.jdt.internal.compiler.ast.QualifiedThisReference;
import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference;
import org.eclipse.jdt.internal.compiler.ast.ReturnStatement;
+import org.eclipse.jdt.internal.compiler.ast.SingleMemberAnnotation;
import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
import org.eclipse.jdt.internal.compiler.ast.SingleTypeReference;
import org.eclipse.jdt.internal.compiler.ast.Statement;
+import org.eclipse.jdt.internal.compiler.ast.StringLiteral;
import org.eclipse.jdt.internal.compiler.ast.ThisReference;
import org.eclipse.jdt.internal.compiler.ast.TrueLiteral;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
@@ -84,6 +87,7 @@ import lombok.core.handlers.HandlerUtil;
import lombok.core.handlers.InclusionExclusionUtils.Included;
import lombok.core.AnnotationValues;
import lombok.core.HandlerPriority;
+import lombok.core.configuration.CheckerFrameworkVersion;
import lombok.eclipse.Eclipse;
import lombok.eclipse.EclipseAnnotationHandler;
import lombok.eclipse.EclipseNode;
@@ -155,7 +159,8 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
@Override public void handle(AnnotationValues<Builder> annotation, Annotation ast, EclipseNode annotationNode) {
handleFlagUsage(annotationNode, ConfigurationKeys.BUILDER_FLAG_USAGE, "@Builder");
-
+ CheckerFrameworkVersion cfv = getCheckerFrameworkVersion(annotationNode);
+
long p = (long) ast.sourceStart << 32 | ast.sourceEnd;
Builder builderInstance = annotation.getInstance();
@@ -487,14 +492,14 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
}
for (BuilderFieldData bfd : builderFields) {
- makeSetterMethodsForBuilder(builderType, bfd, annotationNode, fluent, chain, accessForInners, bfd.originalFieldNode);
+ makeSetterMethodsForBuilder(cfv, builderType, bfd, annotationNode, fluent, chain, accessForInners, bfd.originalFieldNode);
}
{
MemberExistsResult methodExists = methodExists(buildMethodName, builderType, -1);
if (methodExists == MemberExistsResult.EXISTS_BY_LOMBOK) methodExists = methodExists(buildMethodName, builderType, 0);
if (methodExists == MemberExistsResult.NOT_EXISTS) {
- MethodDeclaration md = generateBuildMethod(tdParent, isStatic, buildMethodName, nameOfStaticBuilderMethod, returnType, builderFields, builderType, thrownExceptions, addCleaning, ast, accessForInners);
+ MethodDeclaration md = generateBuildMethod(cfv, tdParent, isStatic, buildMethodName, nameOfStaticBuilderMethod, returnType, builderFields, builderType, thrownExceptions, addCleaning, ast, accessForInners);
if (md != null) injectMethod(builderType, md);
}
}
@@ -517,7 +522,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
if (generateBuilderMethod && methodExists(builderMethodName, tdParent, -1) != MemberExistsResult.NOT_EXISTS) generateBuilderMethod = false;
if (generateBuilderMethod) {
- MethodDeclaration md = generateBuilderMethod(isStatic, builderMethodName, builderClassName, tdParent, typeParams, ast, accessForOuters);
+ MethodDeclaration md = generateBuilderMethod(cfv, isStatic, builderMethodName, builderClassName, tdParent, typeParams, ast, accessForOuters);
if (md != null) injectMethod(tdParent, md);
}
@@ -534,7 +539,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
tps[i].name = typeArgsForToBuilder.get(i);
}
}
- MethodDeclaration md = generateToBuilderMethod(toBuilderMethodName, builderClassName, tdParent, tps, builderFields, fluent, ast, accessForOuters);
+ MethodDeclaration md = generateToBuilderMethod(cfv, toBuilderMethodName, builderClassName, tdParent, tps, builderFields, fluent, ast, accessForOuters);
if (md != null) injectMethod(tdParent, md);
}
@@ -547,7 +552,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
}
private static final char[] BUILDER_TEMP_VAR = {'b', 'u', 'i', 'l', 'd', 'e', 'r'};
- private MethodDeclaration generateToBuilderMethod(String methodName, String builderClassName, EclipseNode type, TypeParameter[] typeParams, List<BuilderFieldData> builderFields, boolean fluent, ASTNode source, AccessLevel access) {
+ private MethodDeclaration generateToBuilderMethod(CheckerFrameworkVersion cfv, String methodName, String builderClassName, EclipseNode type, TypeParameter[] typeParams, List<BuilderFieldData> builderFields, boolean fluent, ASTNode source, AccessLevel access) {
int pS = source.sourceStart, pE = source.sourceEnd;
long p = (long) pS << 32 | pE;
@@ -623,6 +628,10 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
out.statements = new Statement[] {new ReturnStatement(receiver, pS, pE)};
}
+ if (cfv.generateUnique()) {
+ out.annotations = new Annotation[] {generateNamedAnnotation(source, CheckerFrameworkVersion.NAME__UNIQUE)};
+ }
+
out.traverse(new SetGeneratedByVisitor(source), ((TypeDeclaration) type.get()).scope);
return out;
@@ -650,7 +659,35 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
return decl;
}
- public MethodDeclaration generateBuildMethod(EclipseNode tdParent, boolean isStatic, String name, char[] staticName, TypeReference returnType, List<BuilderFieldData> builderFields, EclipseNode type, TypeReference[] thrownExceptions, boolean addCleaning, ASTNode source, AccessLevel access) {
+ static Argument[] generateBuildArgs(CheckerFrameworkVersion cfv, EclipseNode type, List<BuilderFieldData> builderFields, ASTNode source) {
+ if (!cfv.generateCalledMethods()) return null;
+
+ List<char[]> mandatories = new ArrayList<char[]>();
+ for (BuilderFieldData bfd : builderFields) {
+ if (bfd.singularData == null && bfd.nameOfSetFlag == null) mandatories.add(bfd.name);
+ }
+
+ if (mandatories.size() == 0) return null;
+ char[][] nameCalled = fromQualifiedName(CheckerFrameworkVersion.NAME__CALLED);
+ SingleMemberAnnotation ann = new SingleMemberAnnotation(new QualifiedTypeReference(nameCalled, poss(source, nameCalled.length)), source.sourceStart);
+ if (mandatories.size() == 1) {
+ ann.memberValue = new StringLiteral(mandatories.get(0), 0, 0, 0);
+ } else {
+ ArrayInitializer arr = new ArrayInitializer();
+ arr.sourceStart = source.sourceStart;
+ arr.sourceEnd = source.sourceEnd;
+ arr.expressions = new Expression[mandatories.size()];
+ for (int i = 0; i < arr.expressions.length; i++) {
+ arr.expressions[i] = new StringLiteral(mandatories.get(i), source.sourceStart, source.sourceEnd, 0);
+ }
+ ann.memberValue = arr;
+ }
+ Argument arg = new Argument(new char[] { 't', 'h', 'i', 's' }, 0, new SingleTypeReference(type.getName().toCharArray(), source.sourceStart), Modifier.FINAL);
+ arg.annotations = new Annotation[] {ann};
+ return new Argument[] {arg};
+ }
+
+ public MethodDeclaration generateBuildMethod(CheckerFrameworkVersion cfv, EclipseNode tdParent, boolean isStatic, String name, char[] staticName, TypeReference returnType, List<BuilderFieldData> builderFields, EclipseNode type, TypeReference[] thrownExceptions, boolean addCleaning, ASTNode source, AccessLevel access) {
MethodDeclaration out = new MethodDeclaration(((CompilationUnitDeclaration) type.top().get()).compilationResult);
out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
List<Statement> statements = new ArrayList<Statement>();
@@ -723,6 +760,10 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
}
}
out.statements = statements.isEmpty() ? null : statements.toArray(new Statement[0]);
+ if (cfv.generateSideEffectFree()) {
+ out.annotations = new Annotation[] {generateNamedAnnotation(source, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE)};
+ }
+ out.arguments = generateBuildArgs(cfv, type, builderFields, source);
out.traverse(new SetGeneratedByVisitor(source), (ClassScope) null);
return out;
}
@@ -754,7 +795,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
return out;
}
- public MethodDeclaration generateBuilderMethod(boolean isStatic, String builderMethodName, String builderClassName, EclipseNode type, TypeParameter[] typeParams, ASTNode source, AccessLevel access) {
+ public MethodDeclaration generateBuilderMethod(CheckerFrameworkVersion cfv, boolean isStatic, String builderMethodName, String builderClassName, EclipseNode type, TypeParameter[] typeParams, ASTNode source, AccessLevel access) {
int pS = source.sourceStart, pE = source.sourceEnd;
long p = (long) pS << 32 | pE;
@@ -768,7 +809,15 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
AllocationExpression invoke = new AllocationExpression();
invoke.type = namePlusTypeParamsToTypeReference(builderClassName.toCharArray(), typeParams, p);
out.statements = new Statement[] {new ReturnStatement(invoke, pS, pE)};
-
+ Annotation uniqueAnn = cfv.generateUnique() ? generateNamedAnnotation(source, CheckerFrameworkVersion.NAME__UNIQUE) : null;
+ Annotation sefAnn = cfv.generateSideEffectFree() ? generateNamedAnnotation(source, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE) : null;
+ if (uniqueAnn != null && sefAnn != null) {
+ out.annotations = new Annotation[] {uniqueAnn, sefAnn};
+ } else if (uniqueAnn != null) {
+ out.annotations = new Annotation[] {uniqueAnn};
+ } else if (sefAnn != null) {
+ out.annotations = new Annotation[] {sefAnn};
+ }
out.traverse(new SetGeneratedByVisitor(source), ((TypeDeclaration) type.get()).scope);
return out;
}
@@ -813,18 +862,19 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
private static final AbstractMethodDeclaration[] EMPTY = {};
- public void makeSetterMethodsForBuilder(EclipseNode builderType, BuilderFieldData bfd, EclipseNode sourceNode, boolean fluent, boolean chain, AccessLevel access, EclipseNode originalFieldNode) {
+ public void makeSetterMethodsForBuilder(CheckerFrameworkVersion cfv, EclipseNode builderType, BuilderFieldData bfd, EclipseNode sourceNode, boolean fluent, boolean chain, AccessLevel access, EclipseNode originalFieldNode) {
boolean deprecate = isFieldDeprecated(bfd.originalFieldNode);
if (bfd.singularData == null || bfd.singularData.getSingularizer() == null) {
- makeSimpleSetterMethodForBuilder(builderType, deprecate, bfd.createdFields.get(0), bfd.name, bfd.nameOfSetFlag, sourceNode, fluent, chain, bfd.annotations, access, originalFieldNode);
+ makeSimpleSetterMethodForBuilder(cfv, builderType, deprecate, bfd.createdFields.get(0), bfd.name, bfd.nameOfSetFlag, sourceNode, fluent, chain, bfd.annotations, access, originalFieldNode);
} else {
- bfd.singularData.getSingularizer().generateMethods(bfd.singularData, deprecate, builderType, fluent, chain, access);
+ bfd.singularData.getSingularizer().generateMethods(cfv, bfd.singularData, deprecate, builderType, fluent, chain, access);
}
}
- private void makeSimpleSetterMethodForBuilder(EclipseNode builderType, boolean deprecate, EclipseNode fieldNode, char[] paramName, char[] nameOfSetFlag, EclipseNode sourceNode, boolean fluent, boolean chain, Annotation[] annotations, AccessLevel access, EclipseNode originalFieldNode) {
+ private void makeSimpleSetterMethodForBuilder(CheckerFrameworkVersion cfv, EclipseNode builderType, boolean deprecate, EclipseNode fieldNode, char[] paramName, char[] nameOfSetFlag, EclipseNode sourceNode, boolean fluent, boolean chain, Annotation[] annotations, AccessLevel access, EclipseNode originalFieldNode) {
TypeDeclaration td = (TypeDeclaration) builderType.get();
AbstractMethodDeclaration[] existing = td.methods;
+ ASTNode source = sourceNode.get();
if (existing == null) existing = EMPTY;
int len = existing.length;
FieldDeclaration fd = (FieldDeclaration) fieldNode.get();
@@ -838,11 +888,20 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
String setterName = fluent ? new String(paramName) : HandlerUtil.buildAccessorName("set", new String(paramName));
- List<Annotation> methodAnnsList = Collections.<Annotation>emptyList();
- Annotation[] methodAnns = EclipseHandlerUtil.findCopyableToSetterAnnotations(originalFieldNode);
- if (methodAnns != null && methodAnns.length > 0) methodAnnsList = Arrays.asList(methodAnns);
+ List<Annotation> methodAnnsList = Arrays.asList(EclipseHandlerUtil.findCopyableToSetterAnnotations(originalFieldNode));
MethodDeclaration setter = HandleSetter.createSetter(td, deprecate, fieldNode, setterName, paramName, nameOfSetFlag, chain, toEclipseModifier(access),
- sourceNode, methodAnnsList, annotations != null ? Arrays.asList(copyAnnotations(sourceNode.get(), annotations)) : Collections.<Annotation>emptyList());
+ sourceNode, methodAnnsList, annotations != null ? Arrays.asList(copyAnnotations(source, annotations)) : Collections.<Annotation>emptyList());
+ if (cfv.generateCalledMethods()) {
+ Argument[] arr = setter.arguments == null ? new Argument[0] : setter.arguments;
+ Argument[] newArr = new Argument[arr.length + 1];
+ System.arraycopy(arr, 0, newArr, 1, arr.length);
+ newArr[0] = new Argument(new char[] { 't', 'h', 'i', 's' }, 0, new SingleTypeReference(builderType.getName().toCharArray(), 0), Modifier.FINAL);
+ char[][] nameNotCalled = fromQualifiedName(CheckerFrameworkVersion.NAME__NOT_CALLED);
+ SingleMemberAnnotation ann = new SingleMemberAnnotation(new QualifiedTypeReference(nameNotCalled, poss(source, nameNotCalled.length)), source.sourceStart);
+ ann.memberValue = new StringLiteral(setterName.toCharArray(), 0, 0, 0);
+ newArr[0].annotations = new Annotation[] {ann};
+ setter.arguments = newArr;
+ }
injectMethod(builderType, setter);
}
diff --git a/src/core/lombok/eclipse/handlers/HandleConstructor.java b/src/core/lombok/eclipse/handlers/HandleConstructor.java
index c6b51042..8f981c1a 100755
--- a/src/core/lombok/eclipse/handlers/HandleConstructor.java
+++ b/src/core/lombok/eclipse/handlers/HandleConstructor.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2018 The Project Lombok Authors.
+ * Copyright (C) 2010-2019 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
@@ -39,6 +39,7 @@ import lombok.ConfigurationKeys;
import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor;
import lombok.core.AST.Kind;
+import lombok.core.configuration.CheckerFrameworkVersion;
import lombok.core.AnnotationValues;
import lombok.eclipse.EclipseAnnotationHandler;
import lombok.eclipse.EclipseNode;
@@ -456,14 +457,14 @@ public class HandleConstructor {
constructor.arguments = params.isEmpty() ? null : params.toArray(new Argument[0]);
/* Generate annotations that must be put on the generated method, and attach them. */ {
- Annotation[] constructorProperties = null;
- if (addConstructorProperties && !isLocalType(type)) {
- constructorProperties = createConstructorProperties(source, fieldsToParam);
- }
+ Annotation[] constructorProperties = null, checkerFramework = null;
+ if (addConstructorProperties && !isLocalType(type)) constructorProperties = createConstructorProperties(source, fieldsToParam);
+ if (getCheckerFrameworkVersion(type).generateUnique()) checkerFramework = new Annotation[] { generateNamedAnnotation(source, CheckerFrameworkVersion.NAME__UNIQUE) };
constructor.annotations = copyAnnotations(source,
onConstructor.toArray(new Annotation[0]),
- constructorProperties);
+ constructorProperties,
+ checkerFramework);
}
constructor.traverse(new SetGeneratedByVisitor(source), typeDeclaration.scope);
@@ -551,7 +552,9 @@ public class HandleConstructor {
assigns.add(nameRef);
Argument parameter = new Argument(field.name, fieldPos, copyType(field.type, source), Modifier.FINAL);
- parameter.annotations = copyAnnotations(source, findCopyableAnnotations(fieldNode));
+ Annotation[] checkerFramework = null;
+ if (getCheckerFrameworkVersion(fieldNode).generateUnique()) checkerFramework = new Annotation[] { generateNamedAnnotation(source, CheckerFrameworkVersion.NAME__UNIQUE) };
+ parameter.annotations = copyAnnotations(source, findCopyableAnnotations(fieldNode), checkerFramework);
params.add(parameter);
}
diff --git a/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java b/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java
index 046b197f..1bca4767 100755
--- a/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java
+++ b/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2018 The Project Lombok Authors.
+ * Copyright (C) 2009-2019 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
@@ -42,6 +42,7 @@ import lombok.core.handlers.InclusionExclusionUtils;
import lombok.core.handlers.InclusionExclusionUtils.Included;
import lombok.core.AnnotationValues;
import lombok.core.configuration.CallSuperType;
+import lombok.core.configuration.CheckerFrameworkVersion;
import lombok.eclipse.Eclipse;
import lombok.eclipse.EclipseAnnotationHandler;
import lombok.eclipse.EclipseNode;
@@ -235,7 +236,12 @@ public class HandleEqualsAndHashCode extends EclipseAnnotationHandler<EqualsAndH
method.modifiers = toEclipseModifier(AccessLevel.PUBLIC);
method.returnType = TypeReference.baseTypeReference(TypeIds.T_int, 0);
setGeneratedBy(method.returnType, source);
- method.annotations = new Annotation[] {makeMarkerAnnotation(TypeConstants.JAVA_LANG_OVERRIDE, source)};
+ Annotation overrideAnnotation = makeMarkerAnnotation(TypeConstants.JAVA_LANG_OVERRIDE, source);
+ if (getCheckerFrameworkVersion(type).generateSideEffectFree()) {
+ method.annotations = new Annotation[] { overrideAnnotation, generateNamedAnnotation(source, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE) };
+ } else {
+ method.annotations = new Annotation[] { overrideAnnotation };
+ }
method.selector = "hashCode".toCharArray();
method.thrownExceptions = null;
method.typeParameters = null;
@@ -508,7 +514,12 @@ public class HandleEqualsAndHashCode extends EclipseAnnotationHandler<EqualsAndH
method.returnType = TypeReference.baseTypeReference(TypeIds.T_boolean, 0);
method.returnType.sourceStart = pS; method.returnType.sourceEnd = pE;
setGeneratedBy(method.returnType, source);
- method.annotations = new Annotation[] {makeMarkerAnnotation(TypeConstants.JAVA_LANG_OVERRIDE, source)};
+ Annotation overrideAnnotation = makeMarkerAnnotation(TypeConstants.JAVA_LANG_OVERRIDE, source);
+ if (getCheckerFrameworkVersion(type).generateSideEffectFree()) {
+ method.annotations = new Annotation[] { overrideAnnotation, generateNamedAnnotation(source, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE) };
+ } else {
+ method.annotations = new Annotation[] { overrideAnnotation };
+ }
method.selector = "equals".toCharArray();
method.thrownExceptions = null;
method.typeParameters = null;
@@ -785,6 +796,7 @@ public class HandleEqualsAndHashCode extends EclipseAnnotationHandler<EqualsAndH
setGeneratedBy(returnStatement, source);
method.statements = new Statement[] {returnStatement};
+ if (getCheckerFrameworkVersion(type).generateSideEffectFree()) method.annotations = new Annotation[] { generateNamedAnnotation(source, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE) };
return method;
}
diff --git a/src/core/lombok/eclipse/handlers/HandleGetter.java b/src/core/lombok/eclipse/handlers/HandleGetter.java
index 7d3fe62f..7ba84cdc 100644
--- a/src/core/lombok/eclipse/handlers/HandleGetter.java
+++ b/src/core/lombok/eclipse/handlers/HandleGetter.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2016 The Project Lombok Authors.
+ * Copyright (C) 2009-2019 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
@@ -38,6 +38,7 @@ import lombok.experimental.Delegate;
import lombok.Getter;
import lombok.core.AST.Kind;
import lombok.core.AnnotationValues;
+import lombok.core.configuration.CheckerFrameworkVersion;
import lombok.eclipse.EclipseAnnotationHandler;
import lombok.eclipse.EclipseNode;
import lombok.eclipse.agent.PatchDelegate;
@@ -262,16 +263,16 @@ public class HandleGetter extends EclipseAnnotationHandler<Getter> {
EclipseHandlerUtil.registerCreatedLazyGetter((FieldDeclaration) fieldNode.get(), method.selector, returnType);
- /* Generate annotations that must be put on the generated method, and attach them. */ {
- Annotation[] deprecated = null;
- if (isFieldDeprecated(fieldNode)) {
- deprecated = new Annotation[] { generateDeprecatedAnnotation(source) };
- }
+ /* Generate annotations that must be put on the generated method, and attach them. */ {
+ Annotation[] deprecated = null, checkerFramework = null;
+ if (isFieldDeprecated(fieldNode)) deprecated = new Annotation[] { generateDeprecatedAnnotation(source) };
+ if (getCheckerFrameworkVersion(fieldNode).generateSideEffectFree()) checkerFramework = new Annotation[] { generateNamedAnnotation(source, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE) };
method.annotations = copyAnnotations(source,
onMethod.toArray(new Annotation[0]),
findCopyableAnnotations(fieldNode),
findDelegatesAndMarkAsHandled(fieldNode),
+ checkerFramework,
deprecated);
}
diff --git a/src/core/lombok/eclipse/handlers/HandleSetter.java b/src/core/lombok/eclipse/handlers/HandleSetter.java
index bb704ead..bfa60db0 100644
--- a/src/core/lombok/eclipse/handlers/HandleSetter.java
+++ b/src/core/lombok/eclipse/handlers/HandleSetter.java
@@ -36,6 +36,7 @@ import lombok.AccessLevel;
import lombok.ConfigurationKeys;
import lombok.Setter;
import lombok.core.AST.Kind;
+import lombok.core.configuration.CheckerFrameworkVersion;
import lombok.core.AnnotationValues;
import lombok.eclipse.EclipseAnnotationHandler;
import lombok.eclipse.EclipseNode;
@@ -200,7 +201,11 @@ public class HandleSetter extends EclipseAnnotationHandler<Setter> {
returnThis = new ReturnStatement(thisRef, pS, pE);
}
- return createSetter(parent, deprecate, fieldNode, name, paramName, booleanFieldToSet, returnType, returnThis, modifier, sourceNode, onMethod, onParam);
+ MethodDeclaration d = createSetter(parent, deprecate, fieldNode, name, paramName, booleanFieldToSet, returnType, returnThis, modifier, sourceNode, onMethod, onParam);
+ if (shouldReturnThis && getCheckerFrameworkVersion(sourceNode).generateReturnsReceiver()) {
+ d.annotations = copyAnnotations(source, d.annotations, new Annotation[] { generateNamedAnnotation(source, CheckerFrameworkVersion.NAME__RETURNS_RECEIVER) });
+ }
+ return d;
}
static MethodDeclaration createSetter(TypeDeclaration parent, boolean deprecate, EclipseNode fieldNode, String name, char[] paramName, char[] booleanFieldToSet, TypeReference returnType, Statement returnStatement, int modifier, EclipseNode sourceNode, List<Annotation> onMethod, List<Annotation> onParam) {
diff --git a/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java b/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java
index 88479911..8f0ef338 100755
--- a/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java
+++ b/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java
@@ -57,9 +57,11 @@ import org.eclipse.jdt.internal.compiler.ast.ParameterizedSingleTypeReference;
import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference;
import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference;
import org.eclipse.jdt.internal.compiler.ast.ReturnStatement;
+import org.eclipse.jdt.internal.compiler.ast.SingleMemberAnnotation;
import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
import org.eclipse.jdt.internal.compiler.ast.SingleTypeReference;
import org.eclipse.jdt.internal.compiler.ast.Statement;
+import org.eclipse.jdt.internal.compiler.ast.StringLiteral;
import org.eclipse.jdt.internal.compiler.ast.SuperReference;
import org.eclipse.jdt.internal.compiler.ast.ThisReference;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
@@ -81,6 +83,7 @@ import lombok.ConfigurationKeys;
import lombok.Singular;
import lombok.ToString;
import lombok.core.AST.Kind;
+import lombok.core.configuration.CheckerFrameworkVersion;
import lombok.core.handlers.HandlerUtil;
import lombok.core.handlers.InclusionExclusionUtils.Included;
import lombok.core.AnnotationValues;
@@ -119,6 +122,7 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
@Override
public void handle(AnnotationValues<SuperBuilder> annotation, Annotation ast, EclipseNode annotationNode) {
handleExperimentalFlagUsage(annotationNode, ConfigurationKeys.SUPERBUILDER_FLAG_USAGE, "@SuperBuilder");
+ CheckerFrameworkVersion cfv = getCheckerFrameworkVersion(annotationNode);
long p = (long) ast.sourceStart << 32 | ast.sourceEnd;
@@ -269,7 +273,7 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
// If there is no superclass, superclassBuilderClassExpression is still == null at this point.
// You can use it to check whether to inherit or not.
- generateBuilderBasedConstructor(tdParent, typeParams, builderFields, annotationNode, builderClassName,
+ generateBuilderBasedConstructor(cfv, tdParent, typeParams, builderFields, annotationNode, builderClassName,
superclassBuilderClass != null);
// Create the abstract builder class, or reuse an existing one.
@@ -334,12 +338,12 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
}
// Generate abstract self() and build() methods in the abstract builder.
- injectMethod(builderType, generateAbstractSelfMethod(tdParent, superclassBuilderClass != null, builderGenericName));
- injectMethod(builderType, generateAbstractBuildMethod(tdParent, buildMethodName, superclassBuilderClass != null, classGenericName, ast));
+ injectMethod(builderType, generateAbstractSelfMethod(cfv, tdParent, superclassBuilderClass != null, builderGenericName));
+ injectMethod(builderType, generateAbstractBuildMethod(cfv, builderType, buildMethodName, builderFields, superclassBuilderClass != null, classGenericName, ast));
// Create the setter methods in the abstract builder.
for (BuilderFieldData bfd : builderFields) {
- generateSetterMethodsForBuilder(builderType, bfd, annotationNode, builderGenericName);
+ generateSetterMethodsForBuilder(cfv, builderType, bfd, annotationNode, builderGenericName);
}
// Create the toString() method for the abstract builder.
@@ -386,22 +390,22 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
annotationNode.addWarning("Not generating toBuilder() as it already exists.");
break;
case NOT_EXISTS:
- injectMethod(tdParent, generateToBuilderMethod(builderClassName, builderImplClassName, tdParent, typeParams, ast));
+ injectMethod(tdParent, generateToBuilderMethod(cfv, builderClassName, builderImplClassName, tdParent, typeParams, ast));
default:
// Should not happen.
}
}
// Create the self() and build() methods in the BuilderImpl.
- injectMethod(builderImplType, generateSelfMethod(builderImplType, typeParams, p));
+ injectMethod(builderImplType, generateSelfMethod(cfv, builderImplType, typeParams, p));
if (methodExists(buildMethodName, builderImplType, -1) == MemberExistsResult.NOT_EXISTS) {
- injectMethod(builderImplType, generateBuildMethod(tdParent, buildMethodName, returnType, ast));
+ injectMethod(builderImplType, generateBuildMethod(cfv, builderImplType, buildMethodName, returnType, builderFields, ast));
}
// Add the builder() method to the annotated class.
if (generateBuilderMethod && methodExists(builderMethodName, tdParent, -1) != MemberExistsResult.NOT_EXISTS) generateBuilderMethod = false;
if (generateBuilderMethod) {
- MethodDeclaration md = generateBuilderMethod(builderMethodName, builderClassName, builderImplClassName, tdParent, typeParams, ast);
+ MethodDeclaration md = generateBuilderMethod(cfv, builderMethodName, builderClassName, builderImplClassName, tdParent, typeParams, ast);
if (md != null) injectMethod(tdParent, md);
}
@@ -483,6 +487,7 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
* the type (with the {@code @Builder} annotation) for which a
* constructor should be generated.
* @param typeParams
+ * @param cfv Settings for generating checker framework annotations
* @param builderFields a list of fields in the builder which should be assigned to new instances.
* @param source the annotation (used for setting source code locations for the generated code).
* @param callBuilderBasedSuperConstructor
@@ -490,7 +495,7 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
* constructor with the builder as argument. Requires
* {@code builderClassAsParameter != null}.
*/
- private void generateBuilderBasedConstructor(EclipseNode typeNode, TypeParameter[] typeParams, List<BuilderFieldData> builderFields,
+ private void generateBuilderBasedConstructor(CheckerFrameworkVersion cfv, EclipseNode typeNode, TypeParameter[] typeParams, List<BuilderFieldData> builderFields,
EclipseNode sourceNode, String builderClassName, boolean callBuilderBasedSuperConstructor) {
ASTNode source = sourceNode.get();
@@ -501,6 +506,7 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
ConstructorDeclaration constructor = new ConstructorDeclaration(((CompilationUnitDeclaration) typeNode.top().get()).compilationResult);
constructor.modifiers = toEclipseModifier(AccessLevel.PROTECTED);
+ if (cfv.generateUnique()) constructor.annotations = new Annotation[] {generateNamedAnnotation(source, CheckerFrameworkVersion.NAME__UNIQUE)};
constructor.selector = typeDeclaration.name;
if (callBuilderBasedSuperConstructor) {
constructor.constructorCall = new ExplicitConstructorCall(ExplicitConstructorCall.Super);
@@ -572,7 +578,7 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
injectMethod(typeNode, constructor);
}
- private MethodDeclaration generateBuilderMethod(String builderMethodName, String builderClassName, String builderImplClassName, EclipseNode type, TypeParameter[] typeParams, ASTNode source) {
+ private MethodDeclaration generateBuilderMethod(CheckerFrameworkVersion cfv, String builderMethodName, String builderClassName, String builderImplClassName, EclipseNode type, TypeParameter[] typeParams, ASTNode source) {
int pS = source.sourceStart, pE = source.sourceEnd;
long p = (long) pS << 32 | pE;
@@ -591,6 +597,8 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
invoke.type = namePlusTypeParamsToTypeReference(builderImplClassName.toCharArray(), typeParams, p);
out.statements = new Statement[] {new ReturnStatement(invoke, pS, pE)};
+ if (cfv.generateUnique()) out.annotations = new Annotation[] {generateNamedAnnotation(source, CheckerFrameworkVersion.NAME__UNIQUE)};
+
out.traverse(new SetGeneratedByVisitor(source), ((TypeDeclaration) type.get()).scope);
return out;
}
@@ -603,7 +611,7 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
* }
* </pre>
*/
- private MethodDeclaration generateToBuilderMethod(String builderClassName, String builderImplClassName, EclipseNode type, TypeParameter[] typeParams, ASTNode source) {
+ private MethodDeclaration generateToBuilderMethod(CheckerFrameworkVersion cfv, String builderClassName, String builderImplClassName, EclipseNode type, TypeParameter[] typeParams, ASTNode source) {
int pS = source.sourceStart, pE = source.sourceEnd;
long p = (long) pS << 32 | pE;
@@ -623,6 +631,8 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
invokeFillMethod.arguments = new Expression[] {new ThisReference(0, 0)};
out.statements = new Statement[] {new ReturnStatement(invokeFillMethod, pS, pE)};
+ if (cfv.generateUnique()) out.annotations = new Annotation[] {generateNamedAnnotation(source, CheckerFrameworkVersion.NAME__UNIQUE)};
+
out.traverse(new SetGeneratedByVisitor(source), ((TypeDeclaration) type.get()).scope);
return out;
}
@@ -755,44 +765,64 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
return ms;
}
- private MethodDeclaration generateAbstractSelfMethod(EclipseNode tdParent, boolean override, String builderGenericName) {
+ private MethodDeclaration generateAbstractSelfMethod(CheckerFrameworkVersion cfv, EclipseNode tdParent, boolean override, String builderGenericName) {
MethodDeclaration out = new MethodDeclaration(((CompilationUnitDeclaration) tdParent.top().get()).compilationResult);
out.selector = SELF_METHOD_NAME;
out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
out.modifiers = ClassFileConstants.AccAbstract | ClassFileConstants.AccProtected | ExtraCompilerModifiers.AccSemicolonBody;
- if (override) out.annotations = new Annotation[] {makeMarkerAnnotation(TypeConstants.JAVA_LANG_OVERRIDE, tdParent.get())};
+ Annotation overrideAnn = override ? makeMarkerAnnotation(TypeConstants.JAVA_LANG_OVERRIDE, tdParent.get()) : null;
+ Annotation rrAnn = cfv.generateReturnsReceiver() ? generateNamedAnnotation(tdParent.get(), CheckerFrameworkVersion.NAME__RETURNS_RECEIVER): null;
+ Annotation sefAnn = cfv.generateSideEffectFree() ? generateNamedAnnotation(tdParent.get(), CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE): null;
+ if (overrideAnn != null && rrAnn != null && sefAnn != null) out.annotations = new Annotation[] {overrideAnn, rrAnn, sefAnn};
+ else if (overrideAnn != null && rrAnn != null) out.annotations = new Annotation[] {overrideAnn, rrAnn};
+ else if (overrideAnn != null && sefAnn != null) out.annotations = new Annotation[] {overrideAnn, sefAnn};
+ else if (overrideAnn != null) out.annotations = new Annotation[] {overrideAnn};
+ else if (rrAnn != null && sefAnn != null) out.annotations = new Annotation[] {rrAnn, sefAnn};
+ else if (rrAnn != null) out.annotations = new Annotation[] {rrAnn};
+ else if (sefAnn != null) out.annotations = new Annotation[] {sefAnn};
out.returnType = new SingleTypeReference(builderGenericName.toCharArray(), 0);
return out;
}
- private MethodDeclaration generateSelfMethod(EclipseNode builderImplType, TypeParameter[] typeParams, long p) {
+ private MethodDeclaration generateSelfMethod(CheckerFrameworkVersion cfv, EclipseNode builderImplType, TypeParameter[] typeParams, long p) {
MethodDeclaration out = new MethodDeclaration(((CompilationUnitDeclaration) builderImplType.top().get()).compilationResult);
out.selector = SELF_METHOD_NAME;
out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
out.modifiers = ClassFileConstants.AccProtected;
- out.annotations = new Annotation[] {makeMarkerAnnotation(TypeConstants.JAVA_LANG_OVERRIDE, builderImplType.get())};
+ Annotation overrideAnn = makeMarkerAnnotation(TypeConstants.JAVA_LANG_OVERRIDE, builderImplType.get());
+ Annotation rrAnn = cfv.generateReturnsReceiver() ? generateNamedAnnotation(builderImplType.get(), CheckerFrameworkVersion.NAME__RETURNS_RECEIVER): null;
+ Annotation sefAnn = cfv.generateSideEffectFree() ? generateNamedAnnotation(builderImplType.get(), CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE): null;
+ if (rrAnn != null && sefAnn != null) out.annotations = new Annotation[] {overrideAnn, rrAnn, sefAnn};
+ else if (rrAnn != null) out.annotations = new Annotation[] {overrideAnn, rrAnn};
+ else if (sefAnn != null) out.annotations = new Annotation[] {overrideAnn, sefAnn};
+ else out.annotations = new Annotation[] {overrideAnn};
out.returnType = namePlusTypeParamsToTypeReference(builderImplType.getName().toCharArray(), typeParams, p);
out.statements = new Statement[] {new ReturnStatement(new ThisReference(0, 0), 0, 0)};
return out;
}
- private MethodDeclaration generateAbstractBuildMethod(EclipseNode tdParent, String methodName, boolean override,
+ private MethodDeclaration generateAbstractBuildMethod(CheckerFrameworkVersion cfv, EclipseNode builderType, String methodName, List<BuilderFieldData> builderFields, boolean override,
String classGenericName, ASTNode source) {
- MethodDeclaration out = new MethodDeclaration(((CompilationUnitDeclaration) tdParent.top().get()).compilationResult);
+ MethodDeclaration out = new MethodDeclaration(((CompilationUnitDeclaration) builderType.top().get()).compilationResult);
out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
out.modifiers = ClassFileConstants.AccPublic | ClassFileConstants.AccAbstract | ExtraCompilerModifiers.AccSemicolonBody;
out.selector = methodName.toCharArray();
out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
out.returnType = new SingleTypeReference(classGenericName.toCharArray(), 0);
- if (override) out.annotations = new Annotation[] {makeMarkerAnnotation(TypeConstants.JAVA_LANG_OVERRIDE, source)};
+ Annotation overrideAnn = override ? makeMarkerAnnotation(TypeConstants.JAVA_LANG_OVERRIDE, source) : null;
+ Annotation sefAnn = cfv.generateSideEffectFree() ? generateNamedAnnotation(source, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE): null;
+ if (overrideAnn != null && sefAnn != null) out.annotations = new Annotation[] {overrideAnn, sefAnn};
+ else if (overrideAnn != null) out.annotations = new Annotation[] {overrideAnn};
+ else if (sefAnn != null) out.annotations = new Annotation[] {sefAnn};
+ out.arguments = HandleBuilder.generateBuildArgs(cfv, builderType, builderFields, source);
out.traverse(new SetGeneratedByVisitor(source), (ClassScope) null);
return out;
}
- private MethodDeclaration generateBuildMethod(EclipseNode tdParent, String name, TypeReference returnType, ASTNode source) {
- MethodDeclaration out = new MethodDeclaration(((CompilationUnitDeclaration) tdParent.top().get()).compilationResult);
+ private MethodDeclaration generateBuildMethod(CheckerFrameworkVersion cfv, EclipseNode builderType, String name, TypeReference returnType, List<BuilderFieldData> builderFields, ASTNode source) {
+ MethodDeclaration out = new MethodDeclaration(((CompilationUnitDeclaration) builderType.top().get()).compilationResult);
out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
List<Statement> statements = new ArrayList<Statement>();
@@ -800,7 +830,10 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
out.selector = name.toCharArray();
out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
out.returnType = returnType;
- out.annotations = new Annotation[] {makeMarkerAnnotation(TypeConstants.JAVA_LANG_OVERRIDE, source)};
+ Annotation overrideAnn = makeMarkerAnnotation(TypeConstants.JAVA_LANG_OVERRIDE, source);
+ Annotation sefAnn = cfv.generateSideEffectFree() ? generateNamedAnnotation(source, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE): null;
+ if (sefAnn != null) out.annotations = new Annotation[] {overrideAnn, sefAnn};
+ else out.annotations = new Annotation[] {overrideAnn};
AllocationExpression allocationStatement = new AllocationExpression();
allocationStatement.type = copyType(out.returnType);
@@ -809,6 +842,7 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
statements.add(new ReturnStatement(allocationStatement, 0, 0));
out.statements = statements.isEmpty() ? null : statements.toArray(new Statement[0]);
out.traverse(new SetGeneratedByVisitor(source), (ClassScope) null);
+ out.arguments = HandleBuilder.generateBuildArgs(cfv, builderType, builderFields, source);
return out;
}
@@ -872,7 +906,7 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
}
}
- private void generateSetterMethodsForBuilder(EclipseNode builderType, BuilderFieldData bfd, EclipseNode sourceNode, final String builderGenericName) {
+ private void generateSetterMethodsForBuilder(CheckerFrameworkVersion cfv, EclipseNode builderType, BuilderFieldData bfd, EclipseNode sourceNode, final String builderGenericName) {
boolean deprecate = isFieldDeprecated(bfd.originalFieldNode);
TypeReferenceMaker returnTypeMaker = new TypeReferenceMaker() {
@@ -891,14 +925,15 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
};
if (bfd.singularData == null || bfd.singularData.getSingularizer() == null) {
- generateSimpleSetterMethodForBuilder(builderType, deprecate, bfd.createdFields.get(0), bfd.name, bfd.nameOfSetFlag, true, returnTypeMaker.make(), returnStatementMaker.make(), sourceNode, bfd.annotations, bfd.originalFieldNode);
+ generateSimpleSetterMethodForBuilder(cfv, builderType, deprecate, bfd.createdFields.get(0), bfd.name, bfd.nameOfSetFlag, true, returnTypeMaker.make(), returnStatementMaker.make(), sourceNode, bfd.annotations, bfd.originalFieldNode);
} else {
- bfd.singularData.getSingularizer().generateMethods(bfd.singularData, deprecate, builderType, true, returnTypeMaker, returnStatementMaker, AccessLevel.PUBLIC);
+ bfd.singularData.getSingularizer().generateMethods(cfv, bfd.singularData, deprecate, builderType, true, returnTypeMaker, returnStatementMaker, AccessLevel.PUBLIC);
}
}
- private void generateSimpleSetterMethodForBuilder(EclipseNode builderType, boolean deprecate, EclipseNode fieldNode, char[] paramName, char[] nameOfSetFlag, boolean fluent, TypeReference returnType, Statement returnStatement, EclipseNode sourceNode, Annotation[] annosOnParam, EclipseNode originalFieldNode) {
+ private void generateSimpleSetterMethodForBuilder(CheckerFrameworkVersion cfv, EclipseNode builderType, boolean deprecate, EclipseNode fieldNode, char[] paramName, char[] nameOfSetFlag, boolean fluent, TypeReference returnType, Statement returnStatement, EclipseNode sourceNode, Annotation[] annosOnParam, EclipseNode originalFieldNode) {
TypeDeclaration td = (TypeDeclaration) builderType.get();
+ ASTNode source = sourceNode.get();
AbstractMethodDeclaration[] existing = td.methods;
if (existing == null) existing = EMPTY_METHODS;
int len = existing.length;
@@ -913,11 +948,24 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
String setterName = fluent ? new String(paramName) : HandlerUtil.buildAccessorName("set", new String(paramName));
- List<Annotation> methodAnnsList = Collections.<Annotation>emptyList();
- Annotation[] methodAnns = EclipseHandlerUtil.findCopyableToSetterAnnotations(originalFieldNode);
- if (methodAnns != null && methodAnns.length > 0) methodAnnsList = Arrays.asList(methodAnns);
+ List<Annotation> methodAnnsList = Arrays.asList(EclipseHandlerUtil.findCopyableToSetterAnnotations(originalFieldNode));
+ if (cfv.generateReturnsReceiver()) {
+ methodAnnsList = new ArrayList<Annotation>(methodAnnsList);
+ methodAnnsList.add(generateNamedAnnotation(source, CheckerFrameworkVersion.NAME__RETURNS_RECEIVER));
+ }
MethodDeclaration setter = HandleSetter.createSetter(td, deprecate, fieldNode, setterName, paramName, nameOfSetFlag, returnType, returnStatement, ClassFileConstants.AccPublic,
- sourceNode, methodAnnsList, annosOnParam != null ? Arrays.asList(copyAnnotations(sourceNode.get(), annosOnParam)) : Collections.<Annotation>emptyList());
+ sourceNode, methodAnnsList, annosOnParam != null ? Arrays.asList(copyAnnotations(source, annosOnParam)) : Collections.<Annotation>emptyList());
+ if (cfv.generateCalledMethods()) {
+ Argument[] arr = setter.arguments == null ? new Argument[0] : setter.arguments;
+ Argument[] newArr = new Argument[arr.length + 1];
+ System.arraycopy(arr, 0, newArr, 1, arr.length);
+ newArr[0] = new Argument(new char[] { 't', 'h', 'i', 's' }, 0, new SingleTypeReference(builderType.getName().toCharArray(), 0), Modifier.FINAL);
+ char[][] nameNotCalled = fromQualifiedName(CheckerFrameworkVersion.NAME__NOT_CALLED);
+ SingleMemberAnnotation ann = new SingleMemberAnnotation(new QualifiedTypeReference(nameNotCalled, poss(source, nameNotCalled.length)), source.sourceStart);
+ ann.memberValue = new StringLiteral(setterName.toCharArray(), 0, 0, 0);
+ newArr[0].annotations = new Annotation[] {ann};
+ setter.arguments = newArr;
+ }
injectMethod(builderType, setter);
}
diff --git a/src/core/lombok/eclipse/handlers/HandleToString.java b/src/core/lombok/eclipse/handlers/HandleToString.java
index bb52feb5..39fd5937 100644
--- a/src/core/lombok/eclipse/handlers/HandleToString.java
+++ b/src/core/lombok/eclipse/handlers/HandleToString.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2018 The Project Lombok Authors.
+ * Copyright (C) 2009-2019 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
@@ -60,6 +60,7 @@ import lombok.ToString;
import lombok.core.AST.Kind;
import lombok.core.AnnotationValues;
import lombok.core.configuration.CallSuperType;
+import lombok.core.configuration.CheckerFrameworkVersion;
import lombok.core.handlers.HandlerUtil.FieldAccess;
import lombok.core.handlers.InclusionExclusionUtils;
import lombok.core.handlers.InclusionExclusionUtils.Included;
@@ -300,7 +301,12 @@ public class HandleToString extends EclipseAnnotationHandler<ToString> {
method.modifiers = toEclipseModifier(AccessLevel.PUBLIC);
method.returnType = new QualifiedTypeReference(TypeConstants.JAVA_LANG_STRING, new long[] {p, p, p});
setGeneratedBy(method.returnType, source);
- method.annotations = new Annotation[] {makeMarkerAnnotation(TypeConstants.JAVA_LANG_OVERRIDE, source)};
+ Annotation overrideAnnotation = makeMarkerAnnotation(TypeConstants.JAVA_LANG_OVERRIDE, source);
+ if (getCheckerFrameworkVersion(type).generateSideEffectFree()) {
+ method.annotations = new Annotation[] { overrideAnnotation, generateNamedAnnotation(source, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE) };
+ } else {
+ method.annotations = new Annotation[] { overrideAnnotation };
+ }
method.arguments = null;
method.selector = "toString".toCharArray();
method.thrownExceptions = null;
diff --git a/src/core/lombok/eclipse/handlers/HandleWither.java b/src/core/lombok/eclipse/handlers/HandleWither.java
index a99789a6..8be08cfe 100644
--- a/src/core/lombok/eclipse/handlers/HandleWither.java
+++ b/src/core/lombok/eclipse/handlers/HandleWither.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2014 The Project Lombok Authors.
+ * Copyright (C) 2012-2019 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
@@ -33,6 +33,7 @@ import java.util.List;
import lombok.AccessLevel;
import lombok.ConfigurationKeys;
import lombok.core.AST.Kind;
+import lombok.core.configuration.CheckerFrameworkVersion;
import lombok.core.AnnotationValues;
import lombok.eclipse.EclipseAnnotationHandler;
import lombok.eclipse.EclipseNode;
@@ -226,11 +227,11 @@ public class HandleWither extends EclipseAnnotationHandler<Wither> {
method.returnType = cloneSelfType(fieldNode, source);
if (method.returnType == null) return null;
- Annotation[] deprecated = null;
- if (isFieldDeprecated(fieldNode)) {
- deprecated = new Annotation[] { generateDeprecatedAnnotation(source) };
- }
- method.annotations = copyAnnotations(source, onMethod.toArray(new Annotation[0]), deprecated);
+ Annotation[] deprecated = null, checkerFramework = null;
+ if (isFieldDeprecated(fieldNode)) deprecated = new Annotation[] { generateDeprecatedAnnotation(source) };
+ if (getCheckerFrameworkVersion(fieldNode).generateSideEffectFree()) checkerFramework = new Annotation[] { generateNamedAnnotation(source, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE) };
+
+ method.annotations = copyAnnotations(source, onMethod.toArray(new Annotation[0]), checkerFramework, deprecated);
Argument param = new Argument(field.name, p, copyType(field.type, source), ClassFileConstants.AccFinal);
param.sourceStart = pS; param.sourceEnd = pE;
method.arguments = new Argument[] { param };
diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java
index 642ba9b7..338f5eab 100755
--- a/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java
+++ b/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java
@@ -31,6 +31,7 @@ import java.util.List;
import lombok.AccessLevel;
import lombok.core.GuavaTypeMap;
import lombok.core.LombokImmutableList;
+import lombok.core.configuration.CheckerFrameworkVersion;
import lombok.core.handlers.HandlerUtil;
import lombok.eclipse.EclipseNode;
import lombok.eclipse.handlers.HandleNonNull;
@@ -111,13 +112,13 @@ abstract class EclipseGuavaSingularizer extends EclipseSingularizer {
return Collections.singletonList(injectFieldAndMarkGenerated(builderType, buildField));
}
- @Override public void generateMethods(SingularData data, boolean deprecate, EclipseNode builderType, boolean fluent, TypeReferenceMaker returnTypeMaker, StatementMaker returnStatementMaker, AccessLevel access) {
- generateSingularMethod(deprecate, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, fluent, access);
- generatePluralMethod(deprecate, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, fluent, access);
- generateClearMethod(deprecate, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, access);
+ @Override public void generateMethods(CheckerFrameworkVersion cfv, SingularData data, boolean deprecate, EclipseNode builderType, boolean fluent, TypeReferenceMaker returnTypeMaker, StatementMaker returnStatementMaker, AccessLevel access) {
+ generateSingularMethod(cfv, deprecate, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, fluent, access);
+ generatePluralMethod(cfv, deprecate, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, fluent, access);
+ generateClearMethod(cfv, deprecate, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, access);
}
- void generateClearMethod(boolean deprecate, TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType, AccessLevel access) {
+ void generateClearMethod(CheckerFrameworkVersion cfv, boolean deprecate, TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType, AccessLevel access) {
MethodDeclaration md = new MethodDeclaration(((CompilationUnitDeclaration) builderType.top().get()).compilationResult);
md.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
md.modifiers = toEclipseModifier(access);
@@ -128,13 +129,13 @@ abstract class EclipseGuavaSingularizer extends EclipseSingularizer {
md.selector = HandlerUtil.buildAccessorName("clear", new String(data.getPluralName())).toCharArray();
md.statements = returnStatement != null ? new Statement[] {a, returnStatement} : new Statement[] {a};
md.returnType = returnType;
- md.annotations = deprecate ? new Annotation[] { generateDeprecatedAnnotation(data.getSource()) } : null;
+ md.annotations = generateSelfReturnAnnotations(deprecate, cfv, data.getSource());
data.setGeneratedByRecursive(md);
injectMethod(builderType, md);
}
- void generateSingularMethod(boolean deprecate, TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType, boolean fluent, AccessLevel access) {
+ void generateSingularMethod(CheckerFrameworkVersion cfv, boolean deprecate, TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType, boolean fluent, AccessLevel access) {
LombokImmutableList<String> suffixes = getArgumentSuffixes();
char[][] names = new char[suffixes.size()][];
for (int i = 0; i < suffixes.size(); i++) {
@@ -172,13 +173,13 @@ abstract class EclipseGuavaSingularizer extends EclipseSingularizer {
}
md.returnType = returnType;
md.selector = fluent ? data.getSingularName() : HandlerUtil.buildAccessorName(getAddMethodName(), new String(data.getSingularName())).toCharArray();
- md.annotations = deprecate ? new Annotation[] { generateDeprecatedAnnotation(data.getSource()) } : null;
+ md.annotations = generateSelfReturnAnnotations(deprecate, cfv, data.getSource());
data.setGeneratedByRecursive(md);
HandleNonNull.INSTANCE.fix(injectMethod(builderType, md));
}
- void generatePluralMethod(boolean deprecate, TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType, boolean fluent, AccessLevel access) {
+ void generatePluralMethod(CheckerFrameworkVersion cfv, boolean deprecate, TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType, boolean fluent, AccessLevel access) {
MethodDeclaration md = new MethodDeclaration(((CompilationUnitDeclaration) builderType.top().get()).compilationResult);
md.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
md.modifiers = toEclipseModifier(access);
@@ -204,7 +205,7 @@ abstract class EclipseGuavaSingularizer extends EclipseSingularizer {
md.arguments = new Argument[] {param};
md.returnType = returnType;
md.selector = fluent ? data.getPluralName() : HandlerUtil.buildAccessorName(getAddMethodName() + "All", new String(data.getPluralName())).toCharArray();
- md.annotations = deprecate ? new Annotation[] { generateDeprecatedAnnotation(data.getSource()) } : null;
+ md.annotations = generateSelfReturnAnnotations(deprecate, cfv, data.getSource());
data.setGeneratedByRecursive(md);
injectMethod(builderType, md);
diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java
index 73d6fe9b..53ea15a6 100755
--- a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java
+++ b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java
@@ -29,6 +29,7 @@ import java.util.Collections;
import java.util.List;
import lombok.AccessLevel;
+import lombok.core.configuration.CheckerFrameworkVersion;
import lombok.core.handlers.HandlerUtil;
import lombok.eclipse.EclipseNode;
import lombok.eclipse.handlers.HandleNonNull;
@@ -91,18 +92,18 @@ abstract class EclipseJavaUtilListSetSingularizer extends EclipseJavaUtilSingula
return Collections.singletonList(injectFieldAndMarkGenerated(builderType, buildField));
}
- @Override public void generateMethods(SingularData data, boolean deprecate, EclipseNode builderType, boolean fluent, TypeReferenceMaker returnTypeMaker, StatementMaker returnStatementMaker, AccessLevel access) {
+ @Override public void generateMethods(CheckerFrameworkVersion cfv, SingularData data, boolean deprecate, EclipseNode builderType, boolean fluent, TypeReferenceMaker returnTypeMaker, StatementMaker returnStatementMaker, AccessLevel access) {
if (useGuavaInstead(builderType)) {
- guavaListSetSingularizer.generateMethods(data, deprecate, builderType, fluent, returnTypeMaker, returnStatementMaker, access);
+ guavaListSetSingularizer.generateMethods(cfv, data, deprecate, builderType, fluent, returnTypeMaker, returnStatementMaker, access);
return;
}
- generateSingularMethod(deprecate, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, fluent, access);
- generatePluralMethod(deprecate, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, fluent, access);
- generateClearMethod(deprecate, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, access);
+ generateSingularMethod(cfv, deprecate, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, fluent, access);
+ generatePluralMethod(cfv, deprecate, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, fluent, access);
+ generateClearMethod(cfv, deprecate, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, access);
}
- private void generateClearMethod(boolean deprecate, TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType, AccessLevel access) {
+ private void generateClearMethod(CheckerFrameworkVersion cfv, boolean deprecate, TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType, AccessLevel access) {
MethodDeclaration md = new MethodDeclaration(((CompilationUnitDeclaration) builderType.top().get()).compilationResult);
md.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
md.modifiers = toEclipseModifier(access);
@@ -118,13 +119,13 @@ abstract class EclipseJavaUtilListSetSingularizer extends EclipseJavaUtilSingula
Statement clearStatement = new IfStatement(new EqualExpression(thisDotField, new NullLiteral(0, 0), OperatorIds.NOT_EQUAL), clearMsg, 0, 0);
md.statements = returnStatement != null ? new Statement[] {clearStatement, returnStatement} : new Statement[] {clearStatement};
md.returnType = returnType;
- md.annotations = deprecate ? new Annotation[] { generateDeprecatedAnnotation(data.getSource()) } : null;
+ md.annotations = generateSelfReturnAnnotations(deprecate, cfv, data.getSource());
data.setGeneratedByRecursive(md);
injectMethod(builderType, md);
}
- void generateSingularMethod(boolean deprecate, TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType, boolean fluent, AccessLevel access) {
+ void generateSingularMethod(CheckerFrameworkVersion cfv, boolean deprecate, TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType, boolean fluent, AccessLevel access) {
MethodDeclaration md = new MethodDeclaration(((CompilationUnitDeclaration) builderType.top().get()).compilationResult);
md.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
md.modifiers = toEclipseModifier(access);
@@ -150,13 +151,13 @@ abstract class EclipseJavaUtilListSetSingularizer extends EclipseJavaUtilSingula
md.arguments = new Argument[] {param};
md.returnType = returnType;
md.selector = fluent ? data.getSingularName() : HandlerUtil.buildAccessorName("add", new String(data.getSingularName())).toCharArray();
- md.annotations = deprecate ? new Annotation[] { generateDeprecatedAnnotation(data.getSource()) } : null;
+ md.annotations = generateSelfReturnAnnotations(deprecate, cfv, data.getSource());
data.setGeneratedByRecursive(md);
HandleNonNull.INSTANCE.fix(injectMethod(builderType, md));
}
- void generatePluralMethod(boolean deprecate, TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType, boolean fluent, AccessLevel access) {
+ void generatePluralMethod(CheckerFrameworkVersion cfv, boolean deprecate, TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType, boolean fluent, AccessLevel access) {
MethodDeclaration md = new MethodDeclaration(((CompilationUnitDeclaration) builderType.top().get()).compilationResult);
md.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
md.modifiers = toEclipseModifier(access);
@@ -181,7 +182,7 @@ abstract class EclipseJavaUtilListSetSingularizer extends EclipseJavaUtilSingula
md.arguments = new Argument[] {param};
md.returnType = returnType;
md.selector = fluent ? data.getPluralName() : HandlerUtil.buildAccessorName("addAll", new String(data.getPluralName())).toCharArray();
- md.annotations = deprecate ? new Annotation[] { generateDeprecatedAnnotation(data.getSource()) } : null;
+ md.annotations = generateSelfReturnAnnotations(deprecate, cfv, data.getSource());
data.setGeneratedByRecursive(md);
injectMethod(builderType, md);
diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java
index b642522f..8684987f 100755
--- a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java
+++ b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java
@@ -54,6 +54,7 @@ import org.mangosdk.spi.ProviderFor;
import lombok.AccessLevel;
import lombok.core.LombokImmutableList;
+import lombok.core.configuration.CheckerFrameworkVersion;
import lombok.core.handlers.HandlerUtil;
import lombok.eclipse.EclipseNode;
import lombok.eclipse.handlers.EclipseSingularsRecipes.EclipseSingularizer;
@@ -150,18 +151,18 @@ public class EclipseJavaUtilMapSingularizer extends EclipseJavaUtilSingularizer
return Arrays.asList(keyFieldNode, valueFieldNode);
}
- @Override public void generateMethods(SingularData data, boolean deprecate, EclipseNode builderType, boolean fluent, TypeReferenceMaker returnTypeMaker, StatementMaker returnStatementMaker, AccessLevel access) {
+ @Override public void generateMethods(CheckerFrameworkVersion cfv, SingularData data, boolean deprecate, EclipseNode builderType, boolean fluent, TypeReferenceMaker returnTypeMaker, StatementMaker returnStatementMaker, AccessLevel access) {
if (useGuavaInstead(builderType)) {
- guavaMapSingularizer.generateMethods(data, deprecate, builderType, fluent, returnTypeMaker, returnStatementMaker, access);
+ guavaMapSingularizer.generateMethods(cfv, data, deprecate, builderType, fluent, returnTypeMaker, returnStatementMaker, access);
return;
}
- generateSingularMethod(deprecate, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, fluent, access);
- generatePluralMethod(deprecate, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, fluent, access);
- generateClearMethod(deprecate, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, access);
+ generateSingularMethod(cfv, deprecate, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, fluent, access);
+ generatePluralMethod(cfv, deprecate, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, fluent, access);
+ generateClearMethod(cfv, deprecate, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, access);
}
- private void generateClearMethod(boolean deprecate, TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType, AccessLevel access) {
+ private void generateClearMethod(CheckerFrameworkVersion cfv, boolean deprecate, TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType, AccessLevel access) {
MethodDeclaration md = new MethodDeclaration(((CompilationUnitDeclaration) builderType.top().get()).compilationResult);
md.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
md.modifiers = toEclipseModifier(access);
@@ -188,13 +189,13 @@ public class EclipseJavaUtilMapSingularizer extends EclipseJavaUtilSingularizer
Statement clearStatement = new IfStatement(new EqualExpression(thisDotField, new NullLiteral(0, 0), OperatorIds.NOT_EQUAL), clearMsgs, 0, 0);
md.statements = returnStatement != null ? new Statement[] {clearStatement, returnStatement} : new Statement[] {clearStatement};
md.returnType = returnType;
- md.annotations = deprecate ? new Annotation[] { generateDeprecatedAnnotation(data.getSource()) } : null;
+ md.annotations = generateSelfReturnAnnotations(deprecate, cfv, data.getSource());
data.setGeneratedByRecursive(md);
injectMethod(builderType, md);
}
- private void generateSingularMethod(boolean deprecate, TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType, boolean fluent, AccessLevel access) {
+ private void generateSingularMethod(CheckerFrameworkVersion cfv, boolean deprecate, TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType, boolean fluent, AccessLevel access) {
MethodDeclaration md = new MethodDeclaration(((CompilationUnitDeclaration) builderType.top().get()).compilationResult);
md.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
md.modifiers = toEclipseModifier(access);
@@ -245,13 +246,13 @@ public class EclipseJavaUtilMapSingularizer extends EclipseJavaUtilSingularizer
md.arguments = new Argument[] {keyParam, valueParam};
md.returnType = returnType;
md.selector = fluent ? data.getSingularName() : HandlerUtil.buildAccessorName("put", new String(data.getSingularName())).toCharArray();
- md.annotations = deprecate ? new Annotation[] { generateDeprecatedAnnotation(data.getSource()) } : null;
+ md.annotations = generateSelfReturnAnnotations(deprecate, cfv, data.getSource());
data.setGeneratedByRecursive(md);
HandleNonNull.INSTANCE.fix(injectMethod(builderType, md));
}
- private void generatePluralMethod(boolean deprecate, TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType, boolean fluent, AccessLevel access) {
+ private void generatePluralMethod(CheckerFrameworkVersion cfv, boolean deprecate, TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType, boolean fluent, AccessLevel access) {
MethodDeclaration md = new MethodDeclaration(((CompilationUnitDeclaration) builderType.top().get()).compilationResult);
md.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
md.modifiers = toEclipseModifier(access);
@@ -309,7 +310,7 @@ public class EclipseJavaUtilMapSingularizer extends EclipseJavaUtilSingularizer
md.arguments = new Argument[] {param};
md.returnType = returnType;
md.selector = fluent ? data.getPluralName() : HandlerUtil.buildAccessorName("putAll", new String(data.getPluralName())).toCharArray();
- md.annotations = deprecate ? new Annotation[] { generateDeprecatedAnnotation(data.getSource()) } : null;
+ md.annotations = generateSelfReturnAnnotations(deprecate, cfv, data.getSource());
data.setGeneratedByRecursive(md);
injectMethod(builderType, md);
diff --git a/src/core/lombok/javac/handlers/HandleBuilder.java b/src/core/lombok/javac/handlers/HandleBuilder.java
index 35a6dc26..de2bdde1 100644
--- a/src/core/lombok/javac/handlers/HandleBuilder.java
+++ b/src/core/lombok/javac/handlers/HandleBuilder.java
@@ -58,6 +58,7 @@ import lombok.ToString;
import lombok.core.AST.Kind;
import lombok.core.AnnotationValues;
import lombok.core.HandlerPriority;
+import lombok.core.configuration.CheckerFrameworkVersion;
import lombok.core.handlers.HandlerUtil;
import lombok.core.handlers.InclusionExclusionUtils.Included;
import lombok.experimental.NonFinal;
@@ -102,6 +103,7 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
@Override public void handle(AnnotationValues<Builder> annotation, JCAnnotation ast, JavacNode annotationNode) {
handleFlagUsage(annotationNode, ConfigurationKeys.BUILDER_FLAG_USAGE, "@Builder");
+ CheckerFrameworkVersion cfv = getCheckerFrameworkVersion(annotationNode);
Builder builderInstance = annotation.getInstance();
AccessLevel accessForOuters = builderInstance.access();
@@ -434,14 +436,14 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
}
for (BuilderFieldData bfd : builderFields) {
- makeSetterMethodsForBuilder(builderType, bfd, annotationNode, fluent, chain, accessForInners);
+ makeSetterMethodsForBuilder(cfv, builderType, bfd, annotationNode, fluent, chain, accessForInners);
}
{
MemberExistsResult methodExists = methodExists(buildMethodName, builderType, -1);
if (methodExists == MemberExistsResult.EXISTS_BY_LOMBOK) methodExists = methodExists(buildMethodName, builderType, 0);
if (methodExists == MemberExistsResult.NOT_EXISTS) {
- JCMethodDecl md = generateBuildMethod(tdParent, isStatic, buildMethodName, nameOfBuilderMethod, returnType, builderFields, builderType, thrownExceptions, ast, addCleaning, accessForInners);
+ JCMethodDecl md = generateBuildMethod(cfv, tdParent, isStatic, buildMethodName, nameOfBuilderMethod, returnType, builderFields, builderType, thrownExceptions, ast, addCleaning, accessForInners);
if (md != null) {
injectMethod(builderType, md);
recursiveSetGeneratedBy(md, ast, annotationNode.getContext());
@@ -465,7 +467,7 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
if (generateBuilderMethod && methodExists(builderMethodName, tdParent, -1) != MemberExistsResult.NOT_EXISTS) generateBuilderMethod = false;
if (generateBuilderMethod) {
- JCMethodDecl md = generateBuilderMethod(isStatic, builderMethodName, builderClassName, annotationNode, tdParent, typeParams, accessForOuters);
+ JCMethodDecl md = generateBuilderMethod(cfv, isStatic, builderMethodName, builderClassName, annotationNode, tdParent, typeParams, accessForOuters);
recursiveSetGeneratedBy(md, ast, annotationNode.getContext());
if (md != null) injectMethod(tdParent, md);
}
@@ -485,7 +487,7 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
}
tps = lb.toList();
}
- JCMethodDecl md = generateToBuilderMethod(toBuilderMethodName, builderClassName, tdParent, tps, builderFields, fluent, ast, accessForOuters);
+ JCMethodDecl md = generateToBuilderMethod(cfv, toBuilderMethodName, builderClassName, tdParent, tps, builderFields, fluent, ast, accessForOuters);
if (md != null) {
recursiveSetGeneratedBy(md, ast, annotationNode.getContext());
injectMethod(tdParent, md);
@@ -534,7 +536,7 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
}
private static final String BUILDER_TEMP_VAR = "builder";
- private JCMethodDecl generateToBuilderMethod(String toBuilderMethodName, String builderClassName, JavacNode type, List<JCTypeParameter> typeParams, java.util.List<BuilderFieldData> builderFields, boolean fluent, JCAnnotation ast, AccessLevel access) {
+ private JCMethodDecl generateToBuilderMethod(CheckerFrameworkVersion cfv, String toBuilderMethodName, String builderClassName, JavacNode type, List<JCTypeParameter> typeParams, java.util.List<BuilderFieldData> builderFields, boolean fluent, JCAnnotation ast, AccessLevel access) {
// return new ThingieBuilder<A, B>().setA(this.a).setB(this.b);
JavacTreeMaker maker = type.getTreeMaker();
@@ -585,7 +587,8 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
statements.append(maker.Return(invoke));
}
JCBlock body = maker.Block(0, statements.toList());
- return maker.MethodDef(maker.Modifiers(toJavacModifier(access)), type.toName(toBuilderMethodName), namePlusTypeParamsToTypeReference(maker, type.toName(builderClassName), typeParams), List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null);
+ List<JCAnnotation> annsOnMethod = cfv.generateUnique() ? List.of(maker.Annotation(genTypeRef(type, CheckerFrameworkVersion.NAME__UNIQUE), List.<JCExpression>nil())) : List.<JCAnnotation>nil();
+ return maker.MethodDef(maker.Modifiers(toJavacModifier(access), annsOnMethod), type.toName(toBuilderMethodName), namePlusTypeParamsToTypeReference(maker, type.toName(builderClassName), typeParams), List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null);
}
private JCMethodDecl generateCleanMethod(java.util.List<BuilderFieldData> builderFields, JavacNode type, JCTree source) {
@@ -617,7 +620,30 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
*/
}
- private JCMethodDecl generateBuildMethod(JavacNode tdParent, boolean isStatic, String buildName, Name builderName, JCExpression returnType, java.util.List<BuilderFieldData> builderFields, JavacNode type, List<JCExpression> thrownExceptions, JCTree source, boolean addCleaning, AccessLevel access) {
+ static List<JCVariableDecl> generateBuildArgs(CheckerFrameworkVersion cfv, JavacNode type, java.util.List<BuilderFieldData> builderFields) {
+ if (!cfv.generateCalledMethods()) return List.<JCVariableDecl>nil();
+
+ ArrayList<String> mandatories = new ArrayList<String>();
+ for (BuilderFieldData bfd : builderFields) {
+ if (bfd.singularData == null && bfd.nameOfSetFlag == null) mandatories.add(bfd.name.toString());
+ }
+
+ JCExpression arg;
+ JavacTreeMaker maker = type.getTreeMaker();
+ if (mandatories.size() == 0) return List.<JCVariableDecl>nil();
+ if (mandatories.size() == 1) arg = maker.Literal(mandatories.get(0));
+ else {
+ List<JCExpression> elems = List.nil();
+ for (int i = mandatories.size() - 1; i >= 0; i--) elems = elems.prepend(maker.Literal(mandatories.get(i)));
+ arg = maker.NewArray(null, List.<JCExpression>nil(), elems);
+ }
+ JCAnnotation recvAnno = maker.Annotation(genTypeRef(type, CheckerFrameworkVersion.NAME__CALLED), List.of(arg));
+ JCClassDecl builderTypeNode = (JCClassDecl) type.get();
+ JCVariableDecl recv = maker.VarDef(maker.Modifiers(0L, List.<JCAnnotation>of(recvAnno)), type.toName("this"), maker.Ident(builderTypeNode.name), null);
+ return List.of(recv);
+ }
+
+ private JCMethodDecl generateBuildMethod(CheckerFrameworkVersion cfv, JavacNode tdParent, boolean isStatic, String buildName, Name builderName, JCExpression returnType, java.util.List<BuilderFieldData> builderFields, JavacNode type, List<JCExpression> thrownExceptions, JCTree source, boolean addCleaning, AccessLevel access) {
JavacTreeMaker maker = type.getTreeMaker();
JCExpression call;
@@ -670,7 +696,9 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
JCBlock body = maker.Block(0, statements.toList());
- return maker.MethodDef(maker.Modifiers(toJavacModifier(access)), type.toName(buildName), returnType, List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), thrownExceptions, body, null);
+ List<JCAnnotation> annsOnMethod = cfv.generateSideEffectFree() ? List.of(maker.Annotation(genTypeRef(type, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE), List.<JCExpression>nil())) : List.<JCAnnotation>nil();
+ List<JCVariableDecl> params = generateBuildArgs(cfv, type, builderFields);
+ return maker.MethodDef(maker.Modifiers(toJavacModifier(access), annsOnMethod), type.toName(buildName), returnType, List.<JCTypeParameter>nil(), params, thrownExceptions, body, null);
}
public static JCMethodDecl generateDefaultProvider(Name methodName, JavacNode fieldNode, List<JCTypeParameter> params) {
@@ -685,7 +713,7 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
return maker.MethodDef(maker.Modifiers(modifiers), methodName, cloneType(maker, field.vartype, field, fieldNode.getContext()), copyTypeParams(fieldNode, params), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null);
}
- public JCMethodDecl generateBuilderMethod(boolean isStatic, String builderMethodName, String builderClassName, JavacNode source, JavacNode type, List<JCTypeParameter> typeParams, AccessLevel access) {
+ public JCMethodDecl generateBuilderMethod(CheckerFrameworkVersion cfv, boolean isStatic, String builderMethodName, String builderClassName, JavacNode source, JavacNode type, List<JCTypeParameter> typeParams, AccessLevel access) {
JavacTreeMaker maker = type.getTreeMaker();
ListBuffer<JCExpression> typeArgs = new ListBuffer<JCExpression>();
@@ -699,7 +727,14 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
JCBlock body = maker.Block(0, List.<JCStatement>of(statement));
int modifiers = toJavacModifier(access);
if (isStatic) modifiers |= Flags.STATIC;
- return maker.MethodDef(maker.Modifiers(modifiers), type.toName(builderMethodName), namePlusTypeParamsToTypeReference(maker, type.toName(builderClassName), typeParams), copyTypeParams(source, typeParams), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null);
+ JCAnnotation annUnique = cfv.generateUnique() ? maker.Annotation(genTypeRef(type, CheckerFrameworkVersion.NAME__UNIQUE), List.<JCExpression>nil()) : null;
+ JCAnnotation annSef = cfv.generateSideEffectFree() ? maker.Annotation(genTypeRef(type, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE), List.<JCExpression>nil()) : null;
+ List<JCAnnotation> annsOnMethod;
+ if (annUnique != null && annSef != null) annsOnMethod = List.of(annUnique, annSef);
+ else if (annUnique != null) annsOnMethod = List.of(annUnique);
+ else if (annSef != null) annsOnMethod = List.of(annSef);
+ else annsOnMethod = List.nil();
+ return maker.MethodDef(maker.Modifiers(modifiers, annsOnMethod), type.toName(builderMethodName), namePlusTypeParamsToTypeReference(maker, type.toName(builderClassName), typeParams), copyTypeParams(source, typeParams), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null);
}
public void generateBuilderFields(JavacNode builderType, java.util.List<BuilderFieldData> builderFields, JCTree source) {
@@ -741,16 +776,16 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
for (JCVariableDecl gen : generated) recursiveSetGeneratedBy(gen, source, builderType.getContext());
}
- public void makeSetterMethodsForBuilder(JavacNode builderType, BuilderFieldData fieldNode, JavacNode source, boolean fluent, boolean chain, AccessLevel access) {
+ public void makeSetterMethodsForBuilder(CheckerFrameworkVersion cfv, JavacNode builderType, BuilderFieldData fieldNode, JavacNode source, boolean fluent, boolean chain, AccessLevel access) {
boolean deprecate = isFieldDeprecated(fieldNode.originalFieldNode);
if (fieldNode.singularData == null || fieldNode.singularData.getSingularizer() == null) {
- makeSimpleSetterMethodForBuilder(builderType, deprecate, fieldNode.createdFields.get(0), fieldNode.name, fieldNode.nameOfSetFlag, source, fluent, chain, fieldNode.annotations, fieldNode.originalFieldNode, access);
+ makeSimpleSetterMethodForBuilder(cfv, builderType, deprecate, fieldNode.createdFields.get(0), fieldNode.name, fieldNode.nameOfSetFlag, source, fluent, chain, fieldNode.annotations, fieldNode.originalFieldNode, access);
} else {
- fieldNode.singularData.getSingularizer().generateMethods(fieldNode.singularData, deprecate, builderType, source.get(), fluent, chain, access);
+ fieldNode.singularData.getSingularizer().generateMethods(cfv, fieldNode.singularData, deprecate, builderType, source.get(), fluent, chain, access);
}
}
- private void makeSimpleSetterMethodForBuilder(JavacNode builderType, boolean deprecate, JavacNode fieldNode, Name paramName, Name nameOfSetFlag, JavacNode source, boolean fluent, boolean chain, List<JCAnnotation> annosOnParam, JavacNode originalFieldNode, AccessLevel access) {
+ private void makeSimpleSetterMethodForBuilder(CheckerFrameworkVersion cfv, JavacNode builderType, boolean deprecate, JavacNode fieldNode, Name paramName, Name nameOfSetFlag, JavacNode source, boolean fluent, boolean chain, List<JCAnnotation> annosOnParam, JavacNode originalFieldNode, AccessLevel access) {
Name fieldName = ((JCVariableDecl) fieldNode.get()).name;
for (JavacNode child : builderType.down()) {
@@ -766,6 +801,12 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
List<JCAnnotation> methodAnns = JavacHandlerUtil.findCopyableToSetterAnnotations(originalFieldNode);
JCMethodDecl newMethod = HandleSetter.createSetter(toJavacModifier(access), deprecate, fieldNode, maker, setterName, paramName, nameOfSetFlag, chain, source, methodAnns, annosOnParam);
+ if (cfv.generateCalledMethods()) {
+ JCAnnotation ncAnno = maker.Annotation(genTypeRef(source, CheckerFrameworkVersion.NAME__NOT_CALLED), List.<JCExpression>of(maker.Literal(newMethod.getName().toString())));
+ JCClassDecl builderTypeNode = (JCClassDecl) builderType.get();
+ JCVariableDecl recv = maker.VarDef(maker.Modifiers(0L, List.<JCAnnotation>of(ncAnno)), builderType.toName("this"), maker.Ident(builderTypeNode.name), null);
+ newMethod.params = List.of(recv, newMethod.params.get(0));
+ }
recursiveSetGeneratedBy(newMethod, source.get(), builderType.getContext());
copyJavadoc(originalFieldNode, newMethod, CopyJavadoc.SETTER);
diff --git a/src/core/lombok/javac/handlers/HandleConstructor.java b/src/core/lombok/javac/handlers/HandleConstructor.java
index 34d2cbfe..4d7c61ad 100644
--- a/src/core/lombok/javac/handlers/HandleConstructor.java
+++ b/src/core/lombok/javac/handlers/HandleConstructor.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2018 The Project Lombok Authors.
+ * Copyright (C) 2010-2019 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
@@ -56,6 +56,7 @@ import lombok.RequiredArgsConstructor;
import lombok.core.AST.Kind;
import lombok.core.AnnotationValues;
import lombok.core.LombokNode;
+import lombok.core.configuration.CheckerFrameworkVersion;
import lombok.delombok.LombokOptionsFactory;
import lombok.javac.Javac;
import lombok.javac.JavacAST;
@@ -222,7 +223,6 @@ public class HandleConstructor {
boolean staticConstrRequired = staticName != null && !staticName.equals("");
if (skipIfConstructorExists != SkipIfConstructorExists.NO) {
-
for (JavacNode child : typeNode.down()) {
if (child.getKind() == Kind.ANNOTATION) {
boolean skipGeneration = annotationTypeMatches(NoArgsConstructor.class, child) ||
@@ -247,7 +247,7 @@ public class HandleConstructor {
}
if (noArgs && noArgsConstructorExists(typeNode)) return;
-
+
ListBuffer<Type> argTypes = new ListBuffer<Type>();
for (JavacNode fieldNode : fields) {
Type mirror = getMirrorForFieldType(fieldNode);
@@ -374,7 +374,7 @@ public class HandleConstructor {
addConstructorProperties(mods, typeNode, fieldsToParam);
}
if (onConstructor != null) mods.annotations = mods.annotations.appendList(copyAnnotations(onConstructor));
-
+ if (getCheckerFrameworkVersion(source).generateUnique()) mods.annotations = mods.annotations.prepend(maker.Annotation(genTypeRef(source, CheckerFrameworkVersion.NAME__UNIQUE), List.<JCExpression>nil()));
return recursiveSetGeneratedBy(maker.MethodDef(mods, typeNode.toName("<init>"),
null, List.<JCTypeParameter>nil(), params.toList(), List.<JCExpression>nil(),
maker.Block(0L, nullChecks.appendList(assigns).toList()), null), source.get(), typeNode.getContext());
@@ -453,6 +453,7 @@ public class HandleConstructor {
JCClassDecl type = (JCClassDecl) typeNode.get();
JCModifiers mods = maker.Modifiers(Flags.STATIC | toJavacModifier(level));
+ if (getCheckerFrameworkVersion(typeNode).generateUnique()) mods.annotations = mods.annotations.prepend(maker.Annotation(genTypeRef(typeNode, CheckerFrameworkVersion.NAME__UNIQUE), List.<JCExpression>nil()));
JCExpression returnType, constructorType;
diff --git a/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java b/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java
index e4d7fa7f..2981bfa7 100644
--- a/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java
+++ b/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2018 The Project Lombok Authors.
+ * Copyright (C) 2009-2019 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
@@ -59,6 +59,7 @@ import lombok.EqualsAndHashCode;
import lombok.core.AST.Kind;
import lombok.core.AnnotationValues;
import lombok.core.configuration.CallSuperType;
+import lombok.core.configuration.CheckerFrameworkVersion;
import lombok.core.handlers.HandlerUtil;
import lombok.core.handlers.HandlerUtil.FieldAccess;
import lombok.core.handlers.InclusionExclusionUtils;
@@ -203,7 +204,10 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas
JavacTreeMaker maker = typeNode.getTreeMaker();
JCAnnotation overrideAnnotation = maker.Annotation(genJavaLangTypeRef(typeNode, "Override"), List.<JCExpression>nil());
- JCModifiers mods = maker.Modifiers(Flags.PUBLIC, List.of(overrideAnnotation));
+ List<JCAnnotation> annsOnMethod = List.of(overrideAnnotation);
+ CheckerFrameworkVersion checkerFramework = getCheckerFrameworkVersion(typeNode);
+ if (checkerFramework.generateSideEffectFree()) annsOnMethod = annsOnMethod.prepend(maker.Annotation(genTypeRef(typeNode, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE), List.<JCExpression>nil()));
+ JCModifiers mods = maker.Modifiers(Flags.PUBLIC, annsOnMethod);
JCExpression returnType = maker.TypeIdent(CTC_INT);
ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>();
@@ -378,7 +382,12 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas
Name thisName = typeNode.toName("this");
JCAnnotation overrideAnnotation = maker.Annotation(genJavaLangTypeRef(typeNode, "Override"), List.<JCExpression>nil());
- JCModifiers mods = maker.Modifiers(Flags.PUBLIC, List.of(overrideAnnotation));
+ List<JCAnnotation> annsOnMethod = List.of(overrideAnnotation);
+ CheckerFrameworkVersion checkerFramework = getCheckerFrameworkVersion(typeNode);
+ if (checkerFramework.generateSideEffectFree()) {
+ annsOnMethod = annsOnMethod.prepend(maker.Annotation(genTypeRef(typeNode, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE), List.<JCExpression>nil()));
+ }
+ JCModifiers mods = maker.Modifiers(Flags.PUBLIC, annsOnMethod);
JCExpression objectType = genJavaLangTypeRef(typeNode, "Object");
JCExpression returnType = maker.TypeIdent(CTC_BOOLEAN);
@@ -497,7 +506,12 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas
*/
JavacTreeMaker maker = typeNode.getTreeMaker();
- JCModifiers mods = maker.Modifiers(Flags.PROTECTED, List.<JCAnnotation>nil());
+ List<JCAnnotation> annsOnMethod = List.nil();
+ CheckerFrameworkVersion checkerFramework = getCheckerFrameworkVersion(typeNode);
+ if (checkerFramework.generateSideEffectFree()) {
+ annsOnMethod = annsOnMethod.prepend(maker.Annotation(genTypeRef(typeNode, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE), List.<JCExpression>nil()));
+ }
+ JCModifiers mods = maker.Modifiers(Flags.PROTECTED, annsOnMethod);
JCExpression returnType = maker.TypeIdent(CTC_BOOLEAN);
Name canEqualName = typeNode.toName("canEqual");
JCExpression objectType = genJavaLangTypeRef(typeNode, "Object");
diff --git a/src/core/lombok/javac/handlers/HandleGetter.java b/src/core/lombok/javac/handlers/HandleGetter.java
index f17936eb..681865df 100644
--- a/src/core/lombok/javac/handlers/HandleGetter.java
+++ b/src/core/lombok/javac/handlers/HandleGetter.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2017 The Project Lombok Authors.
+ * Copyright (C) 2009-2019 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
@@ -37,6 +37,7 @@ import lombok.experimental.Delegate;
import lombok.Getter;
import lombok.core.AST.Kind;
import lombok.core.AnnotationValues;
+import lombok.core.configuration.CheckerFrameworkVersion;
import lombok.javac.JavacAnnotationHandler;
import lombok.javac.JavacNode;
import lombok.javac.JavacTreeMaker;
@@ -167,6 +168,7 @@ public class HandleGetter extends JavacAnnotationHandler<Getter> {
public void createGetterForField(AccessLevel level,
JavacNode fieldNode, JavacNode source, boolean whineIfExists, boolean lazy, List<JCAnnotation> onMethod) {
+
if (fieldNode.getKind() != Kind.FIELD) {
source.addError("@Getter is only supported on a class or a field.");
return;
@@ -246,9 +248,8 @@ public class HandleGetter extends JavacAnnotationHandler<Getter> {
List<JCAnnotation> copyableAnnotations = findCopyableAnnotations(field);
List<JCAnnotation> delegates = findDelegatesAndRemoveFromField(field);
List<JCAnnotation> annsOnMethod = copyAnnotations(onMethod).appendList(copyableAnnotations);
- if (isFieldDeprecated(field)) {
- annsOnMethod = annsOnMethod.prepend(treeMaker.Annotation(genJavaLangTypeRef(field, "Deprecated"), List.<JCExpression>nil()));
- }
+ if (getCheckerFrameworkVersion(field).generateSideEffectFree()) annsOnMethod = annsOnMethod.prepend(treeMaker.Annotation(genTypeRef(field, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE), List.<JCExpression>nil()));
+ if (isFieldDeprecated(field)) annsOnMethod = annsOnMethod.prepend(treeMaker.Annotation(genJavaLangTypeRef(field, "Deprecated"), List.<JCExpression>nil()));
JCMethodDecl decl = recursiveSetGeneratedBy(treeMaker.MethodDef(treeMaker.Modifiers(access, annsOnMethod), methodName, methodType,
methodGenericParams, parameters, throwsClauses, methodBody, annotationMethodDefaultValue), source, field.getContext());
diff --git a/src/core/lombok/javac/handlers/HandleSetter.java b/src/core/lombok/javac/handlers/HandleSetter.java
index 560069ff..926e94d9 100644
--- a/src/core/lombok/javac/handlers/HandleSetter.java
+++ b/src/core/lombok/javac/handlers/HandleSetter.java
@@ -32,6 +32,7 @@ import lombok.ConfigurationKeys;
import lombok.Setter;
import lombok.core.AST.Kind;
import lombok.core.AnnotationValues;
+import lombok.core.configuration.CheckerFrameworkVersion;
import lombok.javac.Javac;
import lombok.javac.JavacAnnotationHandler;
import lombok.javac.JavacNode;
@@ -214,7 +215,15 @@ public class HandleSetter extends JavacAnnotationHandler<Setter> {
returnStatement = treeMaker.Return(treeMaker.Ident(field.toName("this")));
}
- return createSetter(access, deprecate, field, treeMaker, setterName, paramName, booleanFieldToSet, returnType, returnStatement, source, onMethod, onParam);
+ JCMethodDecl d = createSetter(access, deprecate, field, treeMaker, setterName, paramName, booleanFieldToSet, returnType, returnStatement, source, onMethod, onParam);
+ if (shouldReturnThis && getCheckerFrameworkVersion(source).generateReturnsReceiver()) {
+ List<JCAnnotation> annotations = d.mods.annotations;
+ if (annotations == null) annotations = List.nil();
+ JCAnnotation anno = treeMaker.Annotation(genTypeRef(source, CheckerFrameworkVersion.NAME__RETURNS_RECEIVER), List.<JCExpression>nil());
+ recursiveSetGeneratedBy(anno, source.get(), field.getContext());
+ d.mods.annotations = annotations.prepend(anno);
+ }
+ return d;
}
public static JCMethodDecl createSetter(long access, boolean deprecate, JavacNode field, JavacTreeMaker treeMaker, String setterName, Name paramName, Name booleanFieldToSet, JCExpression methodType, JCStatement returnStatement, JavacNode source, List<JCAnnotation> onMethod, List<JCAnnotation> onParam) {
diff --git a/src/core/lombok/javac/handlers/HandleSuperBuilder.java b/src/core/lombok/javac/handlers/HandleSuperBuilder.java
index a5c492a1..0f809571 100644
--- a/src/core/lombok/javac/handlers/HandleSuperBuilder.java
+++ b/src/core/lombok/javac/handlers/HandleSuperBuilder.java
@@ -62,6 +62,7 @@ import lombok.ConfigurationKeys;
import lombok.Singular;
import lombok.ToString;
import lombok.core.AST.Kind;
+import lombok.core.configuration.CheckerFrameworkVersion;
import lombok.core.AnnotationValues;
import lombok.core.HandlerPriority;
import lombok.core.handlers.HandlerUtil;
@@ -93,7 +94,7 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
@Override
public void handle(AnnotationValues<SuperBuilder> annotation, JCAnnotation ast, JavacNode annotationNode) {
handleExperimentalFlagUsage(annotationNode, ConfigurationKeys.SUPERBUILDER_FLAG_USAGE, "@SuperBuilder");
-
+ CheckerFrameworkVersion cfv = getCheckerFrameworkVersion(annotationNode);
SuperBuilder superbuilderAnnotation = annotation.getInstance();
deleteAnnotationIfNeccessary(annotationNode, SuperBuilder.class);
@@ -284,16 +285,16 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
}
// Generate abstract self() and build() methods in the abstract builder.
- JCMethodDecl asm = generateAbstractSelfMethod(tdParent, superclassBuilderClassExpression != null, builderGenericName);
+ JCMethodDecl asm = generateAbstractSelfMethod(cfv, tdParent, superclassBuilderClassExpression != null, builderGenericName);
recursiveSetGeneratedBy(asm, ast, annotationNode.getContext());
injectMethod(builderType, asm);
- JCMethodDecl abm = generateAbstractBuildMethod(tdParent, buildMethodName, superclassBuilderClassExpression != null, classGenericName);
+ JCMethodDecl abm = generateAbstractBuildMethod(cfv, tdParent, buildMethodName, builderFields, superclassBuilderClassExpression != null, classGenericName);
recursiveSetGeneratedBy(abm, ast, annotationNode.getContext());
injectMethod(builderType, abm);
// Create the setter methods in the abstract builder.
for (BuilderFieldData bfd : builderFields) {
- generateSetterMethodsForBuilder(builderType, bfd, annotationNode, builderGenericName);
+ generateSetterMethodsForBuilder(cfv, builderType, bfd, annotationNode, builderGenericName);
}
// Create the toString() method for the abstract builder.
@@ -339,18 +340,18 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
if (cd != null) injectMethod(builderImplType, cd);
// Create the self() and build() methods in the BuilderImpl.
- JCMethodDecl selfMethod = generateSelfMethod(builderImplType, typeParams);
+ JCMethodDecl selfMethod = generateSelfMethod(cfv, builderImplType, typeParams);
recursiveSetGeneratedBy(selfMethod, ast, annotationNode.getContext());
injectMethod(builderImplType, selfMethod);
if (methodExists(buildMethodName, builderImplType, -1) == MemberExistsResult.NOT_EXISTS) {
- JCMethodDecl buildMethod = generateBuildMethod(buildMethodName, tdParent, builderImplType, thrownExceptions);
+ JCMethodDecl buildMethod = generateBuildMethod(cfv, buildMethodName, tdParent, builderImplType, builderFields, thrownExceptions);
recursiveSetGeneratedBy(buildMethod, ast, annotationNode.getContext());
injectMethod(builderImplType, buildMethod);
}
}
// Generate a constructor in the annotated class that takes a builder as argument.
- generateBuilderBasedConstructor(tdParent, typeParams, builderFields, annotationNode, builderClassName,
+ generateBuilderBasedConstructor(cfv, tdParent, typeParams, builderFields, annotationNode, builderClassName,
superclassBuilderClassExpression != null);
if (isAbstract) {
@@ -362,7 +363,7 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
// Allow users to specify their own builder() methods, e.g., to provide default values.
if (generateBuilderMethod && methodExists(builderMethodName, tdParent, -1) != MemberExistsResult.NOT_EXISTS) generateBuilderMethod = false;
if (generateBuilderMethod) {
- JCMethodDecl builderMethod = generateBuilderMethod(builderMethodName, builderClassName, builderImplClassName, annotationNode, tdParent, typeParams);
+ JCMethodDecl builderMethod = generateBuilderMethod(cfv, builderMethodName, builderClassName, builderImplClassName, annotationNode, tdParent, typeParams);
recursiveSetGeneratedBy(builderMethod, ast, annotationNode.getContext());
if (builderMethod != null) injectMethod(tdParent, builderMethod);
}
@@ -374,7 +375,7 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
annotationNode.addWarning("Not generating toBuilder() as it already exists.");
return;
case NOT_EXISTS:
- JCMethodDecl md = generateToBuilderMethod(builderClassName, builderImplClassName, annotationNode, tdParent, typeParams);
+ JCMethodDecl md = generateToBuilderMethod(cfv, builderClassName, builderImplClassName, annotationNode, tdParent, typeParams);
if (md != null) {
recursiveSetGeneratedBy(md, ast, annotationNode.getContext());
injectMethod(tdParent, md);
@@ -483,7 +484,7 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
* constructor with the builder as argument. Requires
* {@code builderClassAsParameter != null}.
*/
- private void generateBuilderBasedConstructor(JavacNode typeNode, List<JCTypeParameter> typeParams, java.util.List<BuilderFieldData> builderFields, JavacNode source, String builderClassName, boolean callBuilderBasedSuperConstructor) {
+ private void generateBuilderBasedConstructor(CheckerFrameworkVersion cfv, JavacNode typeNode, List<JCTypeParameter> typeParams, java.util.List<BuilderFieldData> builderFields, JavacNode source, String builderClassName, boolean callBuilderBasedSuperConstructor) {
JavacTreeMaker maker = typeNode.getTreeMaker();
AccessLevel level = AccessLevel.PROTECTED;
@@ -519,7 +520,8 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
}
}
- JCModifiers mods = maker.Modifiers(toJavacModifier(level), List.<JCAnnotation>nil());
+ List<JCAnnotation> annsOnMethod = cfv.generateUnique() ? List.of(maker.Annotation(genTypeRef(typeNode, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE), List.<JCExpression>nil())) : List.<JCAnnotation>nil();
+ JCModifiers mods = maker.Modifiers(toJavacModifier(level), annsOnMethod);
// Create a constructor that has just the builder as parameter.
ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>();
@@ -551,7 +553,7 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
injectMethod(typeNode, constr, null, Javac.createVoidType(typeNode.getSymbolTable(), CTC_VOID));
}
- private JCMethodDecl generateBuilderMethod(String builderMethodName, String builderClassName, String builderImplClassName, JavacNode source, JavacNode type, List<JCTypeParameter> typeParams) {
+ private JCMethodDecl generateBuilderMethod(CheckerFrameworkVersion cfv, String builderMethodName, String builderClassName, String builderImplClassName, JavacNode source, JavacNode type, List<JCTypeParameter> typeParams) {
JavacTreeMaker maker = type.getTreeMaker();
ListBuffer<JCExpression> typeArgs = new ListBuffer<JCExpression>();
@@ -573,7 +575,8 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
typeParameterNames.add(wildcard);
JCTypeApply returnType = maker.TypeApply(maker.Ident(type.toName(builderClassName)), typeParameterNames.toList());
- return maker.MethodDef(maker.Modifiers(modifiers), type.toName(builderMethodName), returnType, copyTypeParams(source, typeParams), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null);
+ List<JCAnnotation> annsOnMethod = cfv.generateUnique() ? List.of(maker.Annotation(genTypeRef(type, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE), List.<JCExpression>nil())) : List.<JCAnnotation>nil();
+ return maker.MethodDef(maker.Modifiers(modifiers, annsOnMethod), type.toName(builderMethodName), returnType, copyTypeParams(source, typeParams), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null);
}
/**
@@ -584,7 +587,7 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
* }
* </pre>
*/
- private JCMethodDecl generateToBuilderMethod(String builderClassName, String builderImplClassName, JavacNode source, JavacNode type, List<JCTypeParameter> typeParams) {
+ private JCMethodDecl generateToBuilderMethod(CheckerFrameworkVersion cfv, String builderClassName, String builderImplClassName, JavacNode source, JavacNode type, List<JCTypeParameter> typeParams) {
JavacTreeMaker maker = type.getTreeMaker();
ListBuffer<JCExpression> typeArgs = new ListBuffer<JCExpression>();
@@ -607,7 +610,8 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
typeParameterNames.add(wildcard);
JCTypeApply returnType = maker.TypeApply(maker.Ident(type.toName(builderClassName)), typeParameterNames.toList());
- return maker.MethodDef(maker.Modifiers(modifiers), type.toName(TO_BUILDER_METHOD_NAME), returnType, List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null);
+ List<JCAnnotation> annsOnMethod = cfv.generateUnique() ? List.of(maker.Annotation(genTypeRef(type, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE), List.<JCExpression>nil())) : List.<JCAnnotation>nil();
+ return maker.MethodDef(maker.Modifiers(modifiers, annsOnMethod), type.toName(TO_BUILDER_METHOD_NAME), returnType, List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null);
}
/**
@@ -737,25 +741,34 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
return exec;
}
- private JCMethodDecl generateAbstractSelfMethod(JavacNode type, boolean override, String builderGenericName) {
+ private JCMethodDecl generateAbstractSelfMethod(CheckerFrameworkVersion cfv, JavacNode type, boolean override, String builderGenericName) {
JavacTreeMaker maker = type.getTreeMaker();
List<JCAnnotation> annotations = List.nil();
- if (override) {
- JCAnnotation overrideAnnotation = maker.Annotation(genJavaLangTypeRef(type, "Override"), List.<JCExpression>nil());
- annotations = List.of(overrideAnnotation);
- }
+ JCAnnotation overrideAnnotation = override ? maker.Annotation(genJavaLangTypeRef(type, "Override"), List.<JCExpression>nil()) : null;
+ JCAnnotation rrAnnotation = cfv.generateReturnsReceiver() ? maker.Annotation(genTypeRef(type, CheckerFrameworkVersion.NAME__RETURNS_RECEIVER), List.<JCExpression>nil()) : null;
+ JCAnnotation sefAnnotation = cfv.generateSideEffectFree() ? maker.Annotation(genTypeRef(type, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE), List.<JCExpression>nil()) : null;
+ if (sefAnnotation != null) annotations = annotations.prepend(sefAnnotation);
+ if (rrAnnotation != null) annotations = annotations.prepend(rrAnnotation);
+ if (overrideAnnotation != null) annotations = annotations.prepend(overrideAnnotation);
JCModifiers modifiers = maker.Modifiers(Flags.PROTECTED | Flags.ABSTRACT, annotations);
Name name = type.toName(SELF_METHOD);
JCExpression returnType = maker.Ident(type.toName(builderGenericName));
-
+
return maker.MethodDef(modifiers, name, returnType, List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), null, null);
}
- private JCMethodDecl generateSelfMethod(JavacNode builderImplType, List<JCTypeParameter> typeParams) {
+ private JCMethodDecl generateSelfMethod(CheckerFrameworkVersion cfv, JavacNode builderImplType, List<JCTypeParameter> typeParams) {
JavacTreeMaker maker = builderImplType.getTreeMaker();
JCAnnotation overrideAnnotation = maker.Annotation(genJavaLangTypeRef(builderImplType, "Override"), List.<JCExpression>nil());
- JCModifiers modifiers = maker.Modifiers(Flags.PROTECTED, List.of(overrideAnnotation));
+ JCAnnotation rrAnnotation = cfv.generateReturnsReceiver() ? maker.Annotation(genTypeRef(builderImplType, CheckerFrameworkVersion.NAME__RETURNS_RECEIVER), List.<JCExpression>nil()) : null;
+ JCAnnotation sefAnnotation = cfv.generateSideEffectFree() ? maker.Annotation(genTypeRef(builderImplType, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE), List.<JCExpression>nil()) : null;
+ List<JCAnnotation> annsOnMethod = List.nil();
+ if (sefAnnotation != null) annsOnMethod = annsOnMethod.prepend(sefAnnotation);
+ if (rrAnnotation != null) annsOnMethod = annsOnMethod.prepend(rrAnnotation);
+ annsOnMethod = annsOnMethod.prepend(overrideAnnotation);
+
+ JCModifiers modifiers = maker.Modifiers(Flags.PROTECTED, annsOnMethod);
Name name = builderImplType.toName(SELF_METHOD);
JCExpression returnType = namePlusTypeParamsToTypeReference(maker, builderImplType.toName(builderImplType.getName()), typeParams);
@@ -765,21 +778,23 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
return maker.MethodDef(modifiers, name, returnType, List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null);
}
- private JCMethodDecl generateAbstractBuildMethod(JavacNode type, String methodName, boolean override, String classGenericName) {
+ private JCMethodDecl generateAbstractBuildMethod(CheckerFrameworkVersion cfv, JavacNode type, String methodName, java.util.List<BuilderFieldData> builderFields, boolean override, String classGenericName) {
JavacTreeMaker maker = type.getTreeMaker();
List<JCAnnotation> annotations = List.nil();
if (override) {
JCAnnotation overrideAnnotation = maker.Annotation(genJavaLangTypeRef(type, "Override"), List.<JCExpression>nil());
annotations = List.of(overrideAnnotation);
}
+ if (cfv.generateSideEffectFree()) annotations = annotations.prepend(maker.Annotation(genTypeRef(type, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE), List.<JCExpression>nil()));
JCModifiers modifiers = maker.Modifiers(Flags.PUBLIC | Flags.ABSTRACT, annotations);
Name name = type.toName(methodName);
JCExpression returnType = maker.Ident(type.toName(classGenericName));
- return maker.MethodDef(modifiers, name, returnType, List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), null, null);
+ List<JCVariableDecl> params = HandleBuilder.generateBuildArgs(cfv, type, builderFields);
+ return maker.MethodDef(modifiers, name, returnType, List.<JCTypeParameter>nil(), params, List.<JCExpression>nil(), null, null);
}
- private JCMethodDecl generateBuildMethod(String buildName, JavacNode returnType, JavacNode type, List<JCExpression> thrownExceptions) {
+ private JCMethodDecl generateBuildMethod(CheckerFrameworkVersion cfv, String buildName, JavacNode returnType, JavacNode type, java.util.List<BuilderFieldData> builderFields, List<JCExpression> thrownExceptions) {
JavacTreeMaker maker = type.getTreeMaker();
JCExpression call;
@@ -793,9 +808,12 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
JCBlock body = maker.Block(0, statements.toList());
JCAnnotation overrideAnnotation = maker.Annotation(genJavaLangTypeRef(type, "Override"), List.<JCExpression>nil());
- JCModifiers modifiers = maker.Modifiers(Flags.PUBLIC, List.of(overrideAnnotation));
+ List<JCAnnotation> annsOnMethod = List.of(overrideAnnotation);
+ if (cfv.generateSideEffectFree()) annsOnMethod = annsOnMethod.prepend(maker.Annotation(genTypeRef(type, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE), List.<JCExpression>nil()));
+ JCModifiers modifiers = maker.Modifiers(Flags.PUBLIC, annsOnMethod);
- return maker.MethodDef(modifiers, type.toName(buildName), cloneSelfType(returnType), List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), thrownExceptions, body, null);
+ List<JCVariableDecl> params = HandleBuilder.generateBuildArgs(cfv, type, builderFields);
+ return maker.MethodDef(modifiers, type.toName(buildName), cloneSelfType(returnType), List.<JCTypeParameter>nil(), params, thrownExceptions, body, null);
}
private JCMethodDecl generateCleanMethod(java.util.List<BuilderFieldData> builderFields, JavacNode type, JCTree source) {
@@ -852,7 +870,7 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
for (JCVariableDecl gen : generated) recursiveSetGeneratedBy(gen, source, builderType.getContext());
}
- private void generateSetterMethodsForBuilder(final JavacNode builderType, BuilderFieldData fieldNode, JavacNode source, final String builderGenericName) {
+ private void generateSetterMethodsForBuilder(CheckerFrameworkVersion cfv, final JavacNode builderType, BuilderFieldData fieldNode, JavacNode source, final String builderGenericName) {
boolean deprecate = isFieldDeprecated(fieldNode.originalFieldNode);
final JavacTreeMaker maker = builderType.getTreeMaker();
ExpressionMaker returnTypeMaker = new ExpressionMaker() { @Override public JCExpression make() {
@@ -864,13 +882,13 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
}};
if (fieldNode.singularData == null || fieldNode.singularData.getSingularizer() == null) {
- generateSimpleSetterMethodForBuilder(builderType, deprecate, fieldNode.createdFields.get(0), fieldNode.name, fieldNode.nameOfSetFlag, source, true, returnTypeMaker.make(), returnStatementMaker.make(), fieldNode.annotations, fieldNode.originalFieldNode);
+ generateSimpleSetterMethodForBuilder(cfv, builderType, deprecate, fieldNode.createdFields.get(0), fieldNode.name, fieldNode.nameOfSetFlag, source, true, returnTypeMaker.make(), returnStatementMaker.make(), fieldNode.annotations, fieldNode.originalFieldNode);
} else {
- fieldNode.singularData.getSingularizer().generateMethods(fieldNode.singularData, deprecate, builderType, source.get(), true, returnTypeMaker, returnStatementMaker, AccessLevel.PUBLIC);
+ fieldNode.singularData.getSingularizer().generateMethods(cfv, fieldNode.singularData, deprecate, builderType, source.get(), true, returnTypeMaker, returnStatementMaker, AccessLevel.PUBLIC);
}
}
- private void generateSimpleSetterMethodForBuilder(JavacNode builderType, boolean deprecate, JavacNode fieldNode, Name paramName, Name nameOfSetFlag, JavacNode source, boolean fluent, JCExpression returnType, JCStatement returnStatement, List<JCAnnotation> annosOnParam, JavacNode originalFieldNode) {
+ private void generateSimpleSetterMethodForBuilder(CheckerFrameworkVersion cfv, JavacNode builderType, boolean deprecate, JavacNode fieldNode, Name paramName, Name nameOfSetFlag, JavacNode source, boolean fluent, JCExpression returnType, JCStatement returnStatement, List<JCAnnotation> annosOnParam, JavacNode originalFieldNode) {
Name fieldName = ((JCVariableDecl) fieldNode.get()).name;
for (JavacNode child : builderType.down()) {
@@ -886,6 +904,19 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
List<JCAnnotation> methodAnns = JavacHandlerUtil.findCopyableToSetterAnnotations(originalFieldNode);
JCMethodDecl newMethod = HandleSetter.createSetter(Flags.PUBLIC, deprecate, fieldNode, maker, setterName, paramName, nameOfSetFlag, returnType, returnStatement, source, methodAnns, annosOnParam);
+ if (cfv.generateCalledMethods()) {
+ JCAnnotation ncAnno = maker.Annotation(genTypeRef(source, CheckerFrameworkVersion.NAME__NOT_CALLED), List.<JCExpression>of(maker.Literal(newMethod.getName().toString())));
+ JCClassDecl builderTypeNode = (JCClassDecl) builderType.get();
+ JCVariableDecl recv = maker.VarDef(maker.Modifiers(0L, List.<JCAnnotation>of(ncAnno)), builderType.toName("this"), maker.Ident(builderTypeNode.name), null);
+ newMethod.params = List.of(recv, newMethod.params.get(0));
+ }
+ if (cfv.generateReturnsReceiver()) {
+ List<JCAnnotation> annotations = newMethod.mods.annotations;
+ if (annotations == null) annotations = List.nil();
+ JCAnnotation anno = maker.Annotation(genTypeRef(source, CheckerFrameworkVersion.NAME__RETURNS_RECEIVER), List.<JCExpression>nil());
+ recursiveSetGeneratedBy(anno, source.get(), builderType.getContext());
+ newMethod.mods.annotations = annotations.prepend(anno);
+ }
injectMethod(builderType, newMethod);
}
diff --git a/src/core/lombok/javac/handlers/HandleToString.java b/src/core/lombok/javac/handlers/HandleToString.java
index 3780da79..d0d36e06 100644
--- a/src/core/lombok/javac/handlers/HandleToString.java
+++ b/src/core/lombok/javac/handlers/HandleToString.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2018 The Project Lombok Authors.
+ * Copyright (C) 2009-2019 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
@@ -31,6 +31,7 @@ import lombok.ConfigurationKeys;
import lombok.ToString;
import lombok.core.AnnotationValues;
import lombok.core.configuration.CallSuperType;
+import lombok.core.configuration.CheckerFrameworkVersion;
import lombok.core.AST.Kind;
import lombok.core.handlers.InclusionExclusionUtils;
import lombok.core.handlers.InclusionExclusionUtils.Included;
@@ -93,7 +94,7 @@ public class HandleToString extends JavacAnnotationHandler<ToString> {
boolean includeFieldNames = true;
try {
Boolean configuration = typeNode.getAst().readConfiguration(ConfigurationKeys.TO_STRING_INCLUDE_FIELD_NAMES);
- includeFieldNames = configuration != null ? configuration : ((Boolean)ToString.class.getMethod("includeFieldNames").getDefaultValue()).booleanValue();
+ includeFieldNames = configuration != null ? configuration : ((Boolean) ToString.class.getMethod("includeFieldNames").getDefaultValue()).booleanValue();
} catch (Exception ignore) {}
Boolean doNotUseGettersConfiguration = typeNode.getAst().readConfiguration(ConfigurationKeys.TO_STRING_DO_NOT_USE_GETTERS);
@@ -160,7 +161,9 @@ public class HandleToString extends JavacAnnotationHandler<ToString> {
JavacTreeMaker maker = typeNode.getTreeMaker();
JCAnnotation overrideAnnotation = maker.Annotation(genJavaLangTypeRef(typeNode, "Override"), List.<JCExpression>nil());
- JCModifiers mods = maker.Modifiers(Flags.PUBLIC, List.of(overrideAnnotation));
+ List<JCAnnotation> annsOnMethod = List.of(overrideAnnotation);
+ if (getCheckerFrameworkVersion(typeNode).generateSideEffectFree()) annsOnMethod = annsOnMethod.prepend(maker.Annotation(genTypeRef(typeNode, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE), List.<JCExpression>nil()));
+ JCModifiers mods = maker.Modifiers(Flags.PUBLIC, annsOnMethod);
JCExpression returnType = genJavaLangTypeRef(typeNode, "String");
boolean first = true;
diff --git a/src/core/lombok/javac/handlers/HandleWither.java b/src/core/lombok/javac/handlers/HandleWither.java
index 33c4dec2..9c95cb78 100644
--- a/src/core/lombok/javac/handlers/HandleWither.java
+++ b/src/core/lombok/javac/handlers/HandleWither.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2014 The Project Lombok Authors.
+ * Copyright (C) 2012-2019 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
@@ -31,6 +31,7 @@ import lombok.AccessLevel;
import lombok.ConfigurationKeys;
import lombok.core.AST.Kind;
import lombok.core.AnnotationValues;
+import lombok.core.configuration.CheckerFrameworkVersion;
import lombok.experimental.Wither;
import lombok.javac.JavacAnnotationHandler;
import lombok.javac.JavacNode;
@@ -279,10 +280,11 @@ public class HandleWither extends JavacAnnotationHandler<Wither> {
JCExpression annotationMethodDefaultValue = null;
List<JCAnnotation> annsOnMethod = copyAnnotations(onMethod);
+ CheckerFrameworkVersion checkerFramework = getCheckerFrameworkVersion(source);
+ if (checkerFramework.generateSideEffectFree()) annsOnMethod = annsOnMethod.prepend(maker.Annotation(genTypeRef(source, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE), List.<JCExpression>nil()));
+
+ if (isFieldDeprecated(field)) annsOnMethod = annsOnMethod.prepend(maker.Annotation(genJavaLangTypeRef(field, "Deprecated"), List.<JCExpression>nil()));
- if (isFieldDeprecated(field)) {
- annsOnMethod = annsOnMethod.prepend(maker.Annotation(genJavaLangTypeRef(field, "Deprecated"), List.<JCExpression>nil()));
- }
if (makeAbstract) access = access | Flags.ABSTRACT;
JCMethodDecl decl = recursiveSetGeneratedBy(maker.MethodDef(maker.Modifiers(access, annsOnMethod), methodName, returnType,
methodGenericParams, parameters, throwsClauses, methodBody, annotationMethodDefaultValue), source.get(), field.getContext());
diff --git a/src/core/lombok/javac/handlers/JavacHandlerUtil.java b/src/core/lombok/javac/handlers/JavacHandlerUtil.java
index 5f0f39b0..f23a894a 100644
--- a/src/core/lombok/javac/handlers/JavacHandlerUtil.java
+++ b/src/core/lombok/javac/handlers/JavacHandlerUtil.java
@@ -93,6 +93,7 @@ import lombok.core.AnnotationValues.AnnotationValue;
import lombok.core.CleanupTask;
import lombok.core.LombokImmutableList;
import lombok.core.TypeResolver;
+import lombok.core.configuration.CheckerFrameworkVersion;
import lombok.core.configuration.NullCheckExceptionType;
import lombok.core.configuration.TypeName;
import lombok.core.handlers.HandlerUtil;
@@ -330,6 +331,11 @@ public class JavacHandlerUtil {
return false;
}
+ public static CheckerFrameworkVersion getCheckerFrameworkVersion(JavacNode node) {
+ CheckerFrameworkVersion cfv = node.getAst().readConfiguration(ConfigurationKeys.CHECKER_FRAMEWORK);
+ return cfv == null ? CheckerFrameworkVersion.NONE : cfv;
+ }
+
/**
* Returns if a node is marked deprecated (as picked up on by the parser).
* @param node the node to check (type, method, or field decl).
@@ -1266,7 +1272,7 @@ public class JavacHandlerUtil {
}
}
- private static void addAnnotation(JCModifiers mods, JavacNode node, int pos, JCTree source, Context context, String annotationTypeFqn, JCExpression arg) {
+ public static void addAnnotation(JCModifiers mods, JavacNode node, int pos, JCTree source, Context context, String annotationTypeFqn, JCExpression arg) {
boolean isJavaLangBased;
String simpleName; {
int idx = annotationTypeFqn.lastIndexOf('.');
diff --git a/src/core/lombok/javac/handlers/JavacSingularsRecipes.java b/src/core/lombok/javac/handlers/JavacSingularsRecipes.java
index a5895951..341d44df 100644
--- a/src/core/lombok/javac/handlers/JavacSingularsRecipes.java
+++ b/src/core/lombok/javac/handlers/JavacSingularsRecipes.java
@@ -37,6 +37,7 @@ import lombok.ConfigurationKeys;
import lombok.core.LombokImmutableList;
import lombok.core.SpiLoadUtil;
import lombok.core.TypeLibrary;
+import lombok.core.configuration.CheckerFrameworkVersion;
import lombok.core.handlers.HandlerUtil;
import lombok.javac.JavacNode;
import lombok.javac.JavacTreeMaker;
@@ -163,9 +164,12 @@ public class JavacSingularsRecipes {
return this;
}
- protected JCModifiers makeMods(JavacTreeMaker maker, JavacNode node, boolean deprecate, AccessLevel access) {
- if (deprecate) return maker.Modifiers(toJavacModifier(access), List.<JCAnnotation>of(maker.Annotation(genJavaLangTypeRef(node, "Deprecated"), List.<JCExpression>nil())));
- return maker.Modifiers(toJavacModifier(access));
+ protected JCModifiers makeMods(JavacTreeMaker maker, CheckerFrameworkVersion cfv, JavacNode node, boolean deprecate, AccessLevel access) {
+ JCAnnotation deprecateAnn = deprecate ? maker.Annotation(genJavaLangTypeRef(node, "Deprecated"), List.<JCExpression>nil()) : null;
+ JCAnnotation rrAnn = cfv.generateReturnsReceiver() ? maker.Annotation(genTypeRef(node, CheckerFrameworkVersion.NAME__RETURNS_RECEIVER), List.<JCExpression>nil()) : null;
+
+ List<JCAnnotation> annsOnMethod = (deprecateAnn != null && rrAnn != null) ? List.of(deprecateAnn, rrAnn) : deprecateAnn != null ? List.of(deprecateAnn) : rrAnn != null ? List.of(rrAnn) : List.<JCAnnotation>nil();
+ return maker.Modifiers(toJavacModifier(access), annsOnMethod);
}
/** Checks if any of the to-be-generated nodes (fields, methods) already exist. If so, errors on these (singulars don't support manually writing some of it, and returns true). */
@@ -220,7 +224,7 @@ public class JavacSingularsRecipes {
* If you need more control over the return type and value, use
* {@link #generateMethods(SingularData, boolean, JavacNode, JCTree, boolean, ExpressionMaker, StatementMaker)}.
*/
- public void generateMethods(SingularData data, boolean deprecate, final JavacNode builderType, JCTree source, boolean fluent, final boolean chain, AccessLevel access) {
+ public void generateMethods(CheckerFrameworkVersion cfv, SingularData data, boolean deprecate, final JavacNode builderType, JCTree source, boolean fluent, final boolean chain, AccessLevel access) {
final JavacTreeMaker maker = builderType.getTreeMaker();
ExpressionMaker returnTypeMaker = new ExpressionMaker() { @Override public JCExpression make() {
@@ -233,26 +237,26 @@ public class JavacSingularsRecipes {
return chain ? maker.Return(maker.Ident(builderType.toName("this"))) : null;
}};
- generateMethods(data, deprecate, builderType, source, fluent, returnTypeMaker, returnStatementMaker, access);
+ generateMethods(cfv, data, deprecate, builderType, source, fluent, returnTypeMaker, returnStatementMaker, access);
}
/**
* Generates the singular, plural, and clear methods for the given {@link SingularData}.
* Uses the given {@code returnTypeMaker} and {@code returnStatementMaker} for the generated methods.
*/
- public abstract void generateMethods(SingularData data, boolean deprecate, JavacNode builderType, JCTree source, boolean fluent, ExpressionMaker returnTypeMaker, StatementMaker returnStatementMaker, AccessLevel access);
+ public abstract void generateMethods(CheckerFrameworkVersion cfv, SingularData data, boolean deprecate, JavacNode builderType, JCTree source, boolean fluent, ExpressionMaker returnTypeMaker, StatementMaker returnStatementMaker, AccessLevel access);
- protected void doGenerateMethods(SingularData data, boolean deprecate, JavacNode builderType, JCTree source, boolean fluent, ExpressionMaker returnTypeMaker, StatementMaker returnStatementMaker, AccessLevel access) {
+ protected void doGenerateMethods(CheckerFrameworkVersion cfv, SingularData data, boolean deprecate, JavacNode builderType, JCTree source, boolean fluent, ExpressionMaker returnTypeMaker, StatementMaker returnStatementMaker, AccessLevel access) {
JavacTreeMaker maker = builderType.getTreeMaker();
- generateSingularMethod(deprecate, maker, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, source, fluent, access);
- generatePluralMethod(deprecate, maker, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, source, fluent, access);
- generateClearMethod(deprecate, maker, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, source, access);
+ generateSingularMethod(cfv, deprecate, maker, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, source, fluent, access);
+ generatePluralMethod(cfv, deprecate, maker, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, source, fluent, access);
+ generateClearMethod(cfv, deprecate, maker, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, source, access);
}
- private void finishAndInjectMethod(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) {
if (returnStatement != null) statements.append(returnStatement);
JCBlock body = maker.Block(0, statements.toList());
- JCModifiers mods = makeMods(maker, builderType, deprecate, access);
+ JCModifiers mods = makeMods(maker, cfv, builderType, deprecate, access);
List<JCTypeParameter> typeParams = List.nil();
List<JCExpression> thrown = List.nil();
JCMethodDecl method = maker.MethodDef(mods, methodName, returnType, typeParams, jcVariableDecls, thrown, body, null);
@@ -260,25 +264,25 @@ public class JavacSingularsRecipes {
injectMethod(builderType, method);
}
- private void generateClearMethod(boolean deprecate, JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source, AccessLevel access) {
+ private void generateClearMethod(CheckerFrameworkVersion cfv, boolean deprecate, JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source, AccessLevel access) {
JCStatement clearStatement = generateClearStatements(maker, data, builderType);
ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>();
statements.add(clearStatement);
Name methodName = builderType.toName(HandlerUtil.buildAccessorName("clear", data.getPluralName().toString()));
- finishAndInjectMethod(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);
}
protected abstract JCStatement generateClearStatements(JavacTreeMaker maker, SingularData data, JavacNode builderType);
- private void generateSingularMethod(boolean deprecate, JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source, boolean fluent, AccessLevel access) {
+ private void generateSingularMethod(CheckerFrameworkVersion cfv, boolean deprecate, JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source, boolean fluent, AccessLevel access) {
ListBuffer<JCStatement> statements = generateSingularMethodStatements(maker, data, builderType, source);
List<JCVariableDecl> params = generateSingularMethodParameters(maker, data, builderType, source);
Name name = data.getSingularName();
if (!fluent) name = builderType.toName(HandlerUtil.buildAccessorName(getAddMethodName(), name.toString()));
statements.prepend(createConstructBuilderVarIfNeeded(maker, data, builderType, source));
- finishAndInjectMethod(maker, returnType, returnStatement, data, builderType, source, deprecate, statements, name, params, access);
+ finishAndInjectMethod(cfv, maker, returnType, returnStatement, data, builderType, source, deprecate, statements, name, params, access);
}
protected JCVariableDecl generateSingularMethodParameter(int typeIndex, JavacTreeMaker maker, SingularData data, JavacNode builderType, JCTree source, Name name) {
@@ -300,7 +304,7 @@ public class JavacSingularsRecipes {
protected abstract List<JCVariableDecl> generateSingularMethodParameters(JavacTreeMaker maker, SingularData data, JavacNode builderType, JCTree source);
- private void generatePluralMethod(boolean deprecate, JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source, boolean fluent, AccessLevel access) {
+ private void generatePluralMethod(CheckerFrameworkVersion cfv, boolean deprecate, JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source, boolean fluent, AccessLevel access) {
ListBuffer<JCStatement> statements = generatePluralMethodStatements(maker, data, builderType, source);
Name name = data.getPluralName();
if (!fluent) name = builderType.toName(HandlerUtil.buildAccessorName(getAddMethodName() + "All", name.toString()));
@@ -309,7 +313,7 @@ public class JavacSingularsRecipes {
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));
- finishAndInjectMethod(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);
}
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 5b022206..546dc66e 100644
--- a/src/core/lombok/javac/handlers/singulars/JavacGuavaSingularizer.java
+++ b/src/core/lombok/javac/handlers/singulars/JavacGuavaSingularizer.java
@@ -29,6 +29,7 @@ import java.util.Collections;
import lombok.AccessLevel;
import lombok.core.GuavaTypeMap;
import lombok.core.LombokImmutableList;
+import lombok.core.configuration.CheckerFrameworkVersion;
import lombok.javac.JavacNode;
import lombok.javac.JavacTreeMaker;
import lombok.javac.handlers.JavacHandlerUtil;
@@ -71,8 +72,8 @@ abstract class JavacGuavaSingularizer extends JavacSingularizer {
return Collections.singletonList(injectFieldAndMarkGenerated(builderType, buildField));
}
- @Override public void generateMethods(SingularData data, boolean deprecate, JavacNode builderType, JCTree source, boolean fluent, ExpressionMaker returnTypeMaker, StatementMaker returnStatementMaker, AccessLevel access) {
- doGenerateMethods(data, deprecate, builderType, source, fluent, returnTypeMaker, returnStatementMaker, access);
+ @Override public void generateMethods(CheckerFrameworkVersion cfv, SingularData data, boolean deprecate, JavacNode builderType, JCTree source, boolean fluent, ExpressionMaker returnTypeMaker, StatementMaker returnStatementMaker, AccessLevel access) {
+ doGenerateMethods(cfv, data, deprecate, builderType, source, fluent, returnTypeMaker, returnStatementMaker, access);
}
@Override
diff --git a/src/core/lombok/javac/handlers/singulars/JavacJavaUtilListSetSingularizer.java b/src/core/lombok/javac/handlers/singulars/JavacJavaUtilListSetSingularizer.java
index 9d24f5d5..634a086d 100644
--- a/src/core/lombok/javac/handlers/singulars/JavacJavaUtilListSetSingularizer.java
+++ b/src/core/lombok/javac/handlers/singulars/JavacJavaUtilListSetSingularizer.java
@@ -27,6 +27,7 @@ import static lombok.javac.handlers.JavacHandlerUtil.*;
import java.util.Collections;
import lombok.AccessLevel;
+import lombok.core.configuration.CheckerFrameworkVersion;
import lombok.javac.JavacNode;
import lombok.javac.JavacTreeMaker;
import lombok.javac.handlers.JavacHandlerUtil;
@@ -66,8 +67,8 @@ abstract class JavacJavaUtilListSetSingularizer extends JavacJavaUtilSingularize
return Collections.singletonList(injectFieldAndMarkGenerated(builderType, buildField));
}
- @Override public void generateMethods(SingularData data, boolean deprecate, JavacNode builderType, JCTree source, boolean fluent, ExpressionMaker returnTypeMaker, StatementMaker returnStatementMaker, AccessLevel access) {
- doGenerateMethods(data, deprecate, builderType, source, fluent, returnTypeMaker, returnStatementMaker, access);
+ @Override public void generateMethods(CheckerFrameworkVersion cfv, SingularData data, boolean deprecate, JavacNode builderType, JCTree source, boolean fluent, ExpressionMaker returnTypeMaker, StatementMaker returnStatementMaker, AccessLevel access) {
+ doGenerateMethods(cfv, data, deprecate, builderType, source, fluent, returnTypeMaker, returnStatementMaker, access);
}
@Override
diff --git a/src/core/lombok/javac/handlers/singulars/JavacJavaUtilMapSingularizer.java b/src/core/lombok/javac/handlers/singulars/JavacJavaUtilMapSingularizer.java
index 3e498cac..8dc7ecff 100644
--- a/src/core/lombok/javac/handlers/singulars/JavacJavaUtilMapSingularizer.java
+++ b/src/core/lombok/javac/handlers/singulars/JavacJavaUtilMapSingularizer.java
@@ -28,6 +28,7 @@ import java.util.Arrays;
import lombok.AccessLevel;
import lombok.core.LombokImmutableList;
+import lombok.core.configuration.CheckerFrameworkVersion;
import lombok.javac.JavacNode;
import lombok.javac.JavacTreeMaker;
import lombok.javac.handlers.JavacHandlerUtil;
@@ -97,8 +98,8 @@ public class JavacJavaUtilMapSingularizer extends JavacJavaUtilSingularizer {
return Arrays.asList(keyFieldNode, valueFieldNode);
}
- @Override public void generateMethods(SingularData data, boolean deprecate, JavacNode builderType, JCTree source, boolean fluent, ExpressionMaker returnTypeMaker, StatementMaker returnStatementMaker, AccessLevel access) {
- doGenerateMethods(data, deprecate, builderType, source, fluent, returnTypeMaker, returnStatementMaker, access);
+ @Override public void generateMethods(CheckerFrameworkVersion cfv, SingularData data, boolean deprecate, JavacNode builderType, JCTree source, boolean fluent, ExpressionMaker returnTypeMaker, StatementMaker returnStatementMaker, AccessLevel access) {
+ doGenerateMethods(cfv, data, deprecate, builderType, source, fluent, returnTypeMaker, returnStatementMaker, access);
}
@Override