aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rwxr-xr-xsrc/core/lombok/eclipse/handlers/HandleBuilder.java218
-rwxr-xr-xsrc/core/lombok/eclipse/handlers/HandleConstructor.java15
-rw-r--r--src/core/lombok/eclipse/handlers/HandleSuperBuilder.java517
-rw-r--r--src/core/lombok/javac/handlers/HandleBuilder.java554
-rw-r--r--src/core/lombok/javac/handlers/HandleConstructor.java6
-rw-r--r--src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java2
-rw-r--r--src/core/lombok/javac/handlers/HandleGetter.java2
-rw-r--r--src/core/lombok/javac/handlers/HandleSetter.java33
-rw-r--r--src/core/lombok/javac/handlers/HandleSuperBuilder.java610
-rw-r--r--src/core/lombok/javac/handlers/JavacSingularsRecipes.java17
-rw-r--r--src/core/lombok/javac/handlers/singulars/JavacGuavaSingularizer.java2
-rw-r--r--src/core/lombok/javac/handlers/singulars/JavacJavaUtilListSingularizer.java2
-rw-r--r--src/core/lombok/javac/handlers/singulars/JavacJavaUtilSingularizer.java6
13 files changed, 1085 insertions, 899 deletions
diff --git a/src/core/lombok/eclipse/handlers/HandleBuilder.java b/src/core/lombok/eclipse/handlers/HandleBuilder.java
index 5bda6e1a..f8eb9ed0 100755
--- a/src/core/lombok/eclipse/handlers/HandleBuilder.java
+++ b/src/core/lombok/eclipse/handlers/HandleBuilder.java
@@ -106,8 +106,16 @@ import lombok.experimental.NonFinal;
public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
private HandleConstructor handleConstructor = new HandleConstructor();
- private static final char[] CLEAN_FIELD_NAME = "$lombokUnclean".toCharArray();
- private static final char[] CLEAN_METHOD_NAME = "$lombokClean".toCharArray();
+ static final char[] CLEAN_FIELD_NAME = "$lombokUnclean".toCharArray();
+ static final char[] CLEAN_METHOD_NAME = "$lombokClean".toCharArray();
+ static final String TO_BUILDER_METHOD_NAME_STRING = "toBuilder";
+ static final char[] TO_BUILDER_METHOD_NAME = TO_BUILDER_METHOD_NAME_STRING.toCharArray();
+ static final char[] DEFAULT_PREFIX = {'$', 'd', 'e', 'f', 'a', 'u', 'l', 't', '$'};
+ static final char[] SET_PREFIX = {'$', 's', 'e', 't'};
+ static final char[] VALUE_PREFIX = {'$', 'v', 'a', 'l', 'u', 'e'};
+ static final char[] BUILDER_TEMP_VAR = {'b', 'u', 'i', 'l', 'd', 'e', 'r'};
+ static final AbstractMethodDeclaration[] EMPTY_METHODS = {};
+ static final String TO_BUILDER_NOT_SUPPORTED = "@Builder(toBuilder=true) is only supported if you return your own type.";
private static final boolean toBoolean(Object expr, boolean defaultValue) {
if (expr == null) return defaultValue;
@@ -118,22 +126,28 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
static class BuilderJob {
CheckerFrameworkVersion checkerFramework;
- EclipseNode builderTypeParent, builderType;
- String builderClassName, builderMethodName, buildMethodName, toBuilderMethodName;
+ EclipseNode parentType;
+ String builderMethodName, buildMethodName;
boolean isStatic;
TypeParameter[] typeParams;
+ TypeParameter[] builderTypeParams;
ASTNode source;
EclipseNode sourceNode;
List<BuilderFieldData> builderFields;
AccessLevel accessInners, accessOuters;
boolean oldFluent, oldChain, toBuilder;
- TypeParameter[] copyTypeParams() {
- return EclipseHandlerUtil.copyTypeParams(typeParams, source);
+ EclipseNode builderType;
+ String builderClassName;
+ char[] builderClassNameArr;
+
+ void setBuilderClassName(String builderClassName) {
+ this.builderClassName = builderClassName;
+ this.builderClassNameArr = builderClassName.toCharArray();
}
- char[] getBuilderClassName() {
- return builderClassName.toCharArray();
+ TypeParameter[] copyTypeParams() {
+ return EclipseHandlerUtil.copyTypeParams(typeParams, source);
}
long getPos() {
@@ -141,22 +155,22 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
}
public TypeReference createBuilderTypeReference() {
- return namePlusTypeParamsToTypeReference(builderTypeParent, getBuilderClassName(), !isStatic, typeParams, getPos());
+ return namePlusTypeParamsToTypeReference(parentType, builderClassNameArr, !isStatic, builderTypeParams, getPos());
}
public TypeReference createBuilderTypeReferenceForceStatic() {
- return namePlusTypeParamsToTypeReference(builderTypeParent, getBuilderClassName(), false, typeParams, getPos());
+ return namePlusTypeParamsToTypeReference(parentType, builderClassNameArr, false, builderTypeParams, getPos());
}
public TypeReference createBuilderParentTypeReference() {
- return namePlusTypeParamsToTypeReference(builderTypeParent, typeParams, getPos());
+ return namePlusTypeParamsToTypeReference(parentType, typeParams, getPos());
}
public EclipseNode getTopNode() {
- return builderTypeParent.top();
+ return parentType.top();
}
- public void init(AnnotationValues<Builder> node, Builder ann) {
+ void init(AnnotationValues<Builder> annValues, Builder ann, EclipseNode node) {
accessOuters = ann.access();
if (accessOuters == null) accessOuters = AccessLevel.PUBLIC;
if (accessOuters == AccessLevel.NONE) {
@@ -166,23 +180,37 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
accessInners = accessOuters == AccessLevel.PROTECTED ? AccessLevel.PUBLIC : accessOuters;
// These exist just to support the 'old' lombok.experimental.Builder, which had these properties. lombok.Builder no longer has them.
- oldFluent = toBoolean(node.getActualExpression("fluent"), true);
- oldChain = toBoolean(node.getActualExpression("chain"), true);
+ oldFluent = toBoolean(annValues.getActualExpression("fluent"), true);
+ oldChain = toBoolean(annValues.getActualExpression("chain"), true);
builderMethodName = ann.builderMethodName();
buildMethodName = ann.buildMethodName();
- builderClassName = ann.builderClassName();
- toBuilderMethodName = "toBuilder";
+ setBuilderClassName(fixBuilderClassName(node, ann.builderClassName()));
toBuilder = ann.toBuilder();
if (builderMethodName == null) builderMethodName = "builder";
if (buildMethodName == null) buildMethodName = "build";
- if (builderClassName == null) builderClassName = "";
}
- public MethodDeclaration createNewMethodDeclaration() {
+ static String fixBuilderClassName(EclipseNode node, String override) {
+ if (override != null && !override.isEmpty()) return override;
+ override = node.getAst().readConfiguration(ConfigurationKeys.BUILDER_CLASS_NAME);
+ if (override != null && !override.isEmpty()) return override;
+ return "*Builder";
+ }
+
+ MethodDeclaration createNewMethodDeclaration() {
return new MethodDeclaration(((CompilationUnitDeclaration) getTopNode().get()).compilationResult);
}
+
+ String replaceBuilderClassName(char[] name) {
+ if (builderClassName.indexOf('*') == -1) return builderClassName;
+ return builderClassName.replace("*", new String(name));
+ }
+
+ String replaceBuilderClassName(String name) {
+ return builderClassName.replace("*", name);
+ }
}
static class BuilderFieldData {
@@ -219,10 +247,6 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
return true;
}
- private static final char[] DEFAULT_PREFIX = {'$', 'd', 'e', 'f', 'a', 'u', 'l', 't', '$'};
- private static final char[] SET_PREFIX = {'$', 's', 'e', 't'};
- private static final char[] VALUE_PREFIX = {'$', 'v', 'a', 'l', 'u', 'e'};
-
private static final char[] prefixWith(char[] prefix, char[] name) {
char[] out = new char[prefix.length + name.length];
System.arraycopy(prefix, 0, out, 0, prefix.length);
@@ -236,9 +260,10 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
job.sourceNode = annotationNode;
job.source = ast;
job.checkerFramework = getCheckerFrameworkVersion(annotationNode);
+ job.isStatic = true;
Builder annInstance = annotation.getInstance();
- job.init(annotation, annInstance);
+ job.init(annotation, annInstance, annotationNode);
List<char[]> typeArgsForToBuilder = null;
boolean generateBuilderMethod;
@@ -251,45 +276,35 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
}
if (!checkName("buildMethodName", job.buildMethodName, annotationNode)) return;
- if (!job.builderClassName.isEmpty()) {
- if (!checkName("builderClassName", job.builderClassName, annotationNode)) return;
- }
EclipseNode parent = annotationNode.up();
job.builderFields = new ArrayList<BuilderFieldData>();
TypeReference buildMethodReturnType;
TypeReference[] buildMethodThrownExceptions;
- char[] nameOfStaticBuilderMethod;
+ char[] nameOfBuilderMethod;
EclipseNode fillParametersFrom = parent.get() instanceof AbstractMethodDeclaration ? parent : null;
boolean addCleaning = false;
- job.isStatic = true;
List<EclipseNode> nonFinalNonDefaultedFields = null;
- if (job.builderClassName.isEmpty()) job.builderClassName = annotationNode.getAst().readConfiguration(ConfigurationKeys.BUILDER_CLASS_NAME);
- if (job.builderClassName == null || job.builderClassName.isEmpty()) job.builderClassName = "*Builder";
- boolean replaceNameInBuilderClassName = job.builderClassName.contains("*");
-
if (parent.get() instanceof TypeDeclaration) {
- job.builderTypeParent = parent;
- TypeDeclaration td = (TypeDeclaration) job.builderTypeParent.get();
+ job.parentType = parent;
+ TypeDeclaration td = (TypeDeclaration) parent.get();
List<EclipseNode> allFields = new ArrayList<EclipseNode>();
boolean valuePresent = (hasAnnotation(lombok.Value.class, parent) || hasAnnotation("lombok.experimental.Value", parent));
- for (EclipseNode fieldNode : HandleConstructor.findAllFields(job.builderTypeParent, true)) {
+ for (EclipseNode fieldNode : HandleConstructor.findAllFields(parent, true)) {
FieldDeclaration fd = (FieldDeclaration) fieldNode.get();
EclipseNode isDefault = findAnnotation(Builder.Default.class, fieldNode);
boolean isFinal = ((fd.modifiers & ClassFileConstants.AccFinal) != 0) || (valuePresent && !hasAnnotation(NonFinal.class, fieldNode));
- Annotation[] copyableAnnotations = findCopyableAnnotations(fieldNode);
-
BuilderFieldData bfd = new BuilderFieldData();
bfd.rawName = fieldNode.getName().toCharArray();
bfd.name = removePrefixFromField(fieldNode);
bfd.builderFieldName = bfd.name;
- bfd.annotations = copyAnnotations(fd, copyableAnnotations);
+ bfd.annotations = copyAnnotations(fd, findCopyableAnnotations(fieldNode));
bfd.type = fd.type;
bfd.singularData = getSingularData(fieldNode, ast, annInstance.setterPrefix());
bfd.originalFieldNode = fieldNode;
@@ -316,22 +331,22 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
bfd.builderFieldName = prefixWith(bfd.name, VALUE_PREFIX);
MethodDeclaration md = generateDefaultProvider(bfd.nameOfDefaultProvider, td.typeParameters, fieldNode, ast);
- if (md != null) injectMethod(job.builderTypeParent, md);
+ if (md != null) injectMethod(parent, md);
}
addObtainVia(bfd, fieldNode);
job.builderFields.add(bfd);
allFields.add(fieldNode);
}
- handleConstructor.generateConstructor(job.builderTypeParent, AccessLevel.PACKAGE, allFields, false, null, SkipIfConstructorExists.I_AM_BUILDER,
+ handleConstructor.generateConstructor(parent, AccessLevel.PACKAGE, allFields, false, null, SkipIfConstructorExists.I_AM_BUILDER,
Collections.<Annotation>emptyList(), annotationNode);
- job.typeParams = td.typeParameters;
+ job.typeParams = job.builderTypeParams = td.typeParameters;
buildMethodReturnType = job.createBuilderParentTypeReference();
buildMethodThrownExceptions = null;
- nameOfStaticBuilderMethod = null;
- if (replaceNameInBuilderClassName) job.builderClassName = job.builderClassName.replace("*", new String(td.name));
- replaceNameInBuilderClassName = false;
+ nameOfBuilderMethod = null;
+ job.setBuilderClassName(job.replaceBuilderClassName(td.name));
+ if (!checkName("builderClassName", job.builderClassName, annotationNode)) return;
} else if (parent.get() instanceof ConstructorDeclaration) {
ConstructorDeclaration cd = (ConstructorDeclaration) parent.get();
if (cd.typeParameters != null && cd.typeParameters.length > 0) {
@@ -339,21 +354,20 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
return;
}
- job.builderTypeParent = parent.up();
- TypeDeclaration td = (TypeDeclaration) job.builderTypeParent.get();
- job.typeParams = td.typeParameters;
+ job.parentType = parent.up();
+ TypeDeclaration td = (TypeDeclaration) job.parentType.get();
+ job.typeParams = job.builderTypeParams = td.typeParameters;
buildMethodReturnType = job.createBuilderParentTypeReference();
buildMethodThrownExceptions = cd.thrownExceptions;
- nameOfStaticBuilderMethod = null;
- if (replaceNameInBuilderClassName) job.builderClassName = job.builderClassName.replace("*", new String(cd.selector));
- replaceNameInBuilderClassName = false;
+ nameOfBuilderMethod = null;
+ job.setBuilderClassName(job.replaceBuilderClassName(cd.selector));
+ if (!checkName("builderClassName", job.builderClassName, annotationNode)) return;
} else if (parent.get() instanceof MethodDeclaration) {
MethodDeclaration md = (MethodDeclaration) parent.get();
- job.builderTypeParent = parent.up();
+ job.parentType = parent.up();
job.isStatic = md.isStatic();
if (job.toBuilder) {
- final String TO_BUILDER_NOT_SUPPORTED = "@Builder(toBuilder=true) is only supported if you return your own type.";
char[] token;
char[][] pkg = null;
if (md.returnType.dimensions() > 0) {
@@ -379,12 +393,12 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
return;
}
- if (job.builderTypeParent == null || !equals(job.builderTypeParent.getName(), token)) {
+ if (job.parentType == null || !equals(job.parentType.getName(), token)) {
annotationNode.addError(TO_BUILDER_NOT_SUPPORTED);
return;
}
- TypeParameter[] tpOnType = ((TypeDeclaration) job.builderTypeParent.get()).typeParameters;
+ TypeParameter[] tpOnType = ((TypeDeclaration) job.parentType.get()).typeParameters;
TypeParameter[] tpOnMethod = md.typeParameters;
TypeReference[][] tpOnRet_ = null;
if (md.returnType instanceof ParameterizedSingleTypeReference) {
@@ -423,15 +437,15 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
}
}
- job.typeParams = md.typeParameters;
+ job.typeParams = job.builderTypeParams = md.typeParameters;
buildMethodReturnType = copyType(md.returnType, ast);
buildMethodThrownExceptions = md.thrownExceptions;
- nameOfStaticBuilderMethod = md.selector;
- if (replaceNameInBuilderClassName) {
+ nameOfBuilderMethod = md.selector;
+ if (job.builderClassName.indexOf('*') > -1) {
char[] token = returnTypeToBuilderClassName(annotationNode, md, job.typeParams);
- if (token == null)
- return;
- job.builderClassName = job.builderClassName.replace("*", new String(token));
+ if (token == null) return; // should not happen.
+ job.setBuilderClassName(job.replaceBuilderClassName(token));
+ if (!checkName("builderClassName", job.builderClassName, annotationNode)) return;
}
} else {
annotationNode.addError("@Builder is only supported on types, constructors, and methods.");
@@ -458,7 +472,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
}
}
- job.builderType = findInnerClass(job.builderTypeParent, job.builderClassName);
+ job.builderType = findInnerClass(job.parentType, job.builderClassName);
if (job.builderType == null) makeBuilderClass(job);
else {
TypeDeclaration builderTypeDeclaration = (TypeDeclaration) job.builderType.get();
@@ -527,7 +541,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
MemberExistsResult methodExists = methodExists(job.buildMethodName, job.builderType, -1);
if (methodExists == MemberExistsResult.EXISTS_BY_LOMBOK) methodExists = methodExists(job.buildMethodName, job.builderType, 0);
if (methodExists == MemberExistsResult.NOT_EXISTS) {
- MethodDeclaration md = generateBuildMethod(job, nameOfStaticBuilderMethod, buildMethodReturnType, buildMethodThrownExceptions, addCleaning);
+ MethodDeclaration md = generateBuildMethod(job, nameOfBuilderMethod, buildMethodReturnType, buildMethodThrownExceptions, addCleaning);
if (md != null) injectMethod(job.builderType, md);
}
}
@@ -548,13 +562,13 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
if (cleanMethod != null) injectMethod(job.builderType, cleanMethod);
}
- if (generateBuilderMethod && methodExists(job.builderMethodName, job.builderTypeParent, -1) != MemberExistsResult.NOT_EXISTS) generateBuilderMethod = false;
+ if (generateBuilderMethod && methodExists(job.builderMethodName, job.parentType, -1) != MemberExistsResult.NOT_EXISTS) generateBuilderMethod = false;
if (generateBuilderMethod) {
MethodDeclaration md = generateBuilderMethod(job);
- if (md != null) injectMethod(job.builderTypeParent, md);
+ if (md != null) injectMethod(job.parentType, md);
}
- if (job.toBuilder) switch (methodExists(job.toBuilderMethodName, job.builderTypeParent, 0)) {
+ if (job.toBuilder) switch (methodExists(TO_BUILDER_METHOD_NAME_STRING, job.parentType, 0)) {
case EXISTS_BY_USER:
annotationNode.addWarning("Not generating toBuilder() as it already exists.");
break;
@@ -569,7 +583,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
}
MethodDeclaration md = generateToBuilderMethod(job, tps, annInstance.setterPrefix());
- if (md != null) injectMethod(job.builderTypeParent, md);
+ if (md != null) injectMethod(job.parentType, md);
}
if (nonFinalNonDefaultedFields != null && generateBuilderMethod) {
@@ -608,13 +622,12 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
return token;
}
- private static final char[] BUILDER_TEMP_VAR = {'b', 'u', 'i', 'l', 'd', 'e', 'r'};
private MethodDeclaration generateToBuilderMethod(BuilderJob job, TypeParameter[] typeParameters, String prefix) {
int pS = job.source.sourceStart, pE = job.source.sourceEnd;
long p = job.getPos();
MethodDeclaration out = job.createNewMethodDeclaration();
- out.selector = job.toBuilderMethodName.toCharArray();
+ out.selector = TO_BUILDER_METHOD_NAME;
out.modifiers = toEclipseModifier(job.accessOuters);
out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
@@ -657,7 +670,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
obtainExpr.typeArguments[j] = new SingleTypeReference(typeParameters[j].name, 0);
}
}
- obtainExpr.receiver = generateNameReference(job.builderTypeParent, 0);
+ obtainExpr.receiver = generateNameReference(job.parentType, 0);
} else {
obtainExpr.receiver = new ThisReference(0, 0);
}
@@ -709,8 +722,8 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
out.statements[preSs] = new ReturnStatement(receiver, pS, pE);
}
- createRelevantNonNullAnnotation(job.builderTypeParent, out);
- out.traverse(new SetGeneratedByVisitor(job.source), ((TypeDeclaration) job.builderTypeParent.get()).scope);
+ createRelevantNonNullAnnotation(job.parentType, out);
+ out.traverse(new SetGeneratedByVisitor(job.source), ((TypeDeclaration) job.parentType.get()).scope);
return out;
}
@@ -736,6 +749,18 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
return decl;
}
+ static Receiver generateNotCalledReceiver(BuilderJob job, String setterName) {
+ char[][] nameNotCalled = fromQualifiedName(CheckerFrameworkVersion.NAME__NOT_CALLED);
+ SingleMemberAnnotation ann = new SingleMemberAnnotation(new QualifiedTypeReference(nameNotCalled, poss(job.source, nameNotCalled.length)), job.source.sourceStart);
+ ann.memberValue = new StringLiteral(setterName.toCharArray(), 0, 0, 0);
+
+ TypeReference typeReference = job.createBuilderTypeReference();
+ int trLen = typeReference.getTypeName().length;
+ typeReference.annotations = new Annotation[trLen][];
+ typeReference.annotations[trLen - 1] = new Annotation[] {ann};
+ return new Receiver(new char[] { 't', 'h', 'i', 's' }, 0, typeReference, null, 0);
+ }
+
static Receiver generateBuildReceiver(BuilderJob job) {
if (!job.checkerFramework.generateCalledMethods()) return null;
@@ -803,7 +828,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
MessageSend inv = new MessageSend();
inv.sourceStart = job.source.sourceStart;
inv.sourceEnd = job.source.sourceEnd;
- inv.receiver = new SingleNameReference(((TypeDeclaration) job.builderTypeParent.get()).name, 0L);
+ inv.receiver = new SingleNameReference(((TypeDeclaration) job.parentType.get()).name, 0L);
inv.selector = bfd.nameOfDefaultProvider;
inv.typeArguments = typeParameterNames(((TypeDeclaration) job.builderType.get()).typeParameters);
@@ -897,7 +922,6 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
public MethodDeclaration generateBuilderMethod(BuilderJob job) {
int pS = job.source.sourceStart, pE = job.source.sourceEnd;
long p = job.getPos();
- char[] builderClassName = job.getBuilderClassName();
MethodDeclaration out = job.createNewMethodDeclaration();
out.selector = job.builderMethodName.toCharArray();
@@ -920,9 +944,9 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
QualifiedAllocationExpression qualifiedInvoke = new QualifiedAllocationExpression();
qualifiedInvoke.enclosingInstance = new ThisReference(pS, pE);
if (job.typeParams == null || job.typeParams.length == 0) {
- qualifiedInvoke.type = new SingleTypeReference(builderClassName, p);
+ qualifiedInvoke.type = new SingleTypeReference(job.builderClassNameArr, p);
} else {
- qualifiedInvoke.type = namePlusTypeParamsToTypeReference(null, builderClassName, false, job.typeParams, p);
+ qualifiedInvoke.type = namePlusTypeParamsToTypeReference(null, job.builderClassNameArr, false, job.typeParams, p);
}
out.statements = new Statement[] {new ReturnStatement(qualifiedInvoke, pS, pE)};
@@ -973,29 +997,27 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
}
}
- private static final AbstractMethodDeclaration[] EMPTY = {};
-
public void makePrefixedSetterMethodsForBuilder(BuilderJob job, BuilderFieldData bfd, String prefix) {
boolean deprecate = isFieldDeprecated(bfd.originalFieldNode);
if (bfd.singularData == null || bfd.singularData.getSingularizer() == null) {
- makePrefixedSetterMethodForBuilder(job, deprecate, bfd.createdFields.get(0), bfd.name, bfd.nameOfSetFlag, bfd.annotations, bfd.originalFieldNode, prefix);
+ makePrefixedSetterMethodForBuilder(job, bfd, deprecate, prefix);
} else {
bfd.singularData.getSingularizer().generateMethods(job, bfd.singularData, deprecate);
}
}
- private void makePrefixedSetterMethodForBuilder(BuilderJob job, boolean deprecate, EclipseNode fieldNode, char[] paramName, char[] nameOfSetFlag, Annotation[] annotations, EclipseNode originalFieldNode, String prefix) {
+ private void makePrefixedSetterMethodForBuilder(BuilderJob job, BuilderFieldData bfd, boolean deprecate, String prefix) {
TypeDeclaration td = (TypeDeclaration) job.builderType.get();
+ EclipseNode fieldNode = bfd.createdFields.get(0);
AbstractMethodDeclaration[] existing = td.methods;
- if (existing == null) existing = EMPTY;
+ if (existing == null) existing = EMPTY_METHODS;
int len = existing.length;
-
String setterPrefix = prefix.isEmpty() ? "set" : prefix;
String setterName;
if (job.oldFluent) {
- setterName = prefix.isEmpty() ? new String(paramName) : HandlerUtil.buildAccessorName(setterPrefix, new String(paramName));
+ setterName = prefix.isEmpty() ? new String(bfd.name) : HandlerUtil.buildAccessorName(setterPrefix, new String(bfd.name));
} else {
- setterName = HandlerUtil.buildAccessorName(setterPrefix, new String(paramName));
+ setterName = HandlerUtil.buildAccessorName(setterPrefix, new String(bfd.name));
}
for (int i = 0; i < len; i++) {
@@ -1005,26 +1027,16 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
}
List<Annotation> methodAnnsList = Collections.<Annotation>emptyList();
- Annotation[] methodAnns = EclipseHandlerUtil.findCopyableToSetterAnnotations(originalFieldNode);
+ Annotation[] methodAnns = EclipseHandlerUtil.findCopyableToSetterAnnotations(bfd.originalFieldNode);
if (methodAnns != null && methodAnns.length > 0) methodAnnsList = Arrays.asList(methodAnns);
ASTNode source = job.sourceNode.get();
- MethodDeclaration setter = HandleSetter.createSetter(td, deprecate, fieldNode, setterName, paramName, nameOfSetFlag, job.oldChain, toEclipseModifier(job.accessInners),
- job.sourceNode, methodAnnsList, annotations != null ? Arrays.asList(copyAnnotations(source, annotations)) : Collections.<Annotation>emptyList());
- if (job.checkerFramework.generateCalledMethods()) {
- 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);
-
- TypeReference typeReference = job.createBuilderTypeReference();
- int trLen = typeReference.getTypeName().length;
- typeReference.annotations = new Annotation[trLen][];
- typeReference.annotations[trLen - 1] = new Annotation[] {ann};
- setter.receiver = new Receiver(new char[] { 't', 'h', 'i', 's' }, 0, typeReference, null, 0);
- }
+ MethodDeclaration setter = HandleSetter.createSetter(td, deprecate, fieldNode, setterName, bfd.name, bfd.nameOfSetFlag, job.oldChain, toEclipseModifier(job.accessInners),
+ job.sourceNode, methodAnnsList, bfd.annotations != null ? Arrays.asList(copyAnnotations(source, bfd.annotations)) : Collections.<Annotation>emptyList());
+ if (job.checkerFramework.generateCalledMethods()) setter.receiver = generateNotCalledReceiver(job, setterName);
if (job.sourceNode.up().getKind() == Kind.METHOD) {
- copyJavadocFromParam(originalFieldNode.up(), setter, td, paramName.toString());
+ copyJavadocFromParam(bfd.originalFieldNode.up(), setter, td, bfd.name.toString());
} else {
- copyJavadoc(originalFieldNode, setter, td, CopyJavadoc.SETTER, true);
+ copyJavadoc(bfd.originalFieldNode, setter, td, CopyJavadoc.SETTER, true);
}
injectMethod(job.builderType, setter);
}
@@ -1045,15 +1057,15 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
}
public void makeBuilderClass(BuilderJob job) {
- TypeDeclaration parent = (TypeDeclaration) job.builderTypeParent.get();
+ TypeDeclaration parent = (TypeDeclaration) job.parentType.get();
TypeDeclaration builder = new TypeDeclaration(parent.compilationResult);
builder.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG;
builder.modifiers |= toEclipseModifier(job.accessOuters);
if (job.isStatic) builder.modifiers |= ClassFileConstants.AccStatic;
builder.typeParameters = job.copyTypeParams();
- builder.name = job.getBuilderClassName();
+ builder.name = job.builderClassNameArr;
builder.traverse(new SetGeneratedByVisitor(job.source), (ClassScope) null);
- job.builderType = injectType(job.builderTypeParent, builder);
+ job.builderType = injectType(job.parentType, builder);
}
private void addObtainVia(BuilderFieldData bfd, EclipseNode node) {
diff --git a/src/core/lombok/eclipse/handlers/HandleConstructor.java b/src/core/lombok/eclipse/handlers/HandleConstructor.java
index 06c9ecd9..3233a8c6 100755
--- a/src/core/lombok/eclipse/handlers/HandleConstructor.java
+++ b/src/core/lombok/eclipse/handlers/HandleConstructor.java
@@ -461,14 +461,12 @@ 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, checkerFramework = null;
+ Annotation[] constructorProperties = 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,
- checkerFramework);
+ constructorProperties);
}
constructor.traverse(new SetGeneratedByVisitor(source), typeDeclaration.scope);
@@ -536,6 +534,11 @@ public class HandleConstructor {
TypeDeclaration typeDecl = (TypeDeclaration) type.get();
constructor.returnType = EclipseHandlerUtil.namePlusTypeParamsToTypeReference(type, typeDecl.typeParameters, p);
constructor.annotations = null;
+ if (getCheckerFrameworkVersion(type).generateUnique()) {
+ int len = constructor.returnType.getTypeName().length;
+ constructor.returnType.annotations = new Annotation[len][];
+ constructor.returnType.annotations[len - 1] = new Annotation[] {generateNamedAnnotation(source, CheckerFrameworkVersion.NAME__UNIQUE)};
+ }
constructor.selector = name.toCharArray();
constructor.thrownExceptions = null;
constructor.typeParameters = copyTypeParams(((TypeDeclaration) type.get()).typeParameters, source);
@@ -556,9 +559,7 @@ public class HandleConstructor {
assigns.add(nameRef);
Argument parameter = new Argument(field.name, fieldPos, copyType(field.type, source), Modifier.FINAL);
- Annotation[] checkerFramework = null;
- if (getCheckerFrameworkVersion(fieldNode).generateUnique()) checkerFramework = new Annotation[] { generateNamedAnnotation(source, CheckerFrameworkVersion.NAME__UNIQUE) };
- parameter.annotations = copyAnnotations(source, findCopyableAnnotations(fieldNode), checkerFramework);
+ parameter.annotations = copyAnnotations(source, findCopyableAnnotations(fieldNode));
params.add(parameter);
}
diff --git a/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java b/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java
index 79b7e816..8fdfd315 100644
--- a/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java
+++ b/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java
@@ -21,6 +21,7 @@
*/
package lombok.eclipse.handlers;
+import static lombok.eclipse.handlers.HandleBuilder.*;
import static lombok.core.handlers.HandlerUtil.*;
import static lombok.eclipse.Eclipse.*;
import static lombok.eclipse.handlers.EclipseHandlerUtil.*;
@@ -57,13 +58,10 @@ import org.eclipse.jdt.internal.compiler.ast.ParameterizedQualifiedTypeReference
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.Receiver;
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;
@@ -99,75 +97,100 @@ import lombok.eclipse.handlers.EclipseSingularsRecipes.SingularData;
import lombok.eclipse.handlers.EclipseSingularsRecipes.StatementMaker;
import lombok.eclipse.handlers.EclipseSingularsRecipes.TypeReferenceMaker;
import lombok.eclipse.handlers.HandleBuilder.BuilderFieldData;
+import lombok.eclipse.handlers.HandleBuilder.BuilderJob;
import lombok.experimental.NonFinal;
import lombok.experimental.SuperBuilder;
@ProviderFor(EclipseAnnotationHandler.class)
@HandlerPriority(-1024) //-2^10; to ensure we've picked up @FieldDefault's changes (-2048) but @Value hasn't removed itself yet (-512), so that we can error on presence of it on the builder classes.
public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
- private static final char[] CLEAN_FIELD_NAME = "$lombokUnclean".toCharArray();
- private static final char[] CLEAN_METHOD_NAME = "$lombokClean".toCharArray();
- private static final char[] DEFAULT_PREFIX = "$default$".toCharArray();
- private static final char[] SET_PREFIX = "$set".toCharArray();
- private static final char[] VALUE_PREFIX = "$value".toCharArray();
private static final char[] SELF_METHOD_NAME = "self".toCharArray();
- private static final String TO_BUILDER_METHOD_NAME_STRING = "toBuilder";
- private static final char[] TO_BUILDER_METHOD_NAME = TO_BUILDER_METHOD_NAME_STRING.toCharArray();
private static final char[] FILL_VALUES_METHOD_NAME = "$fillValuesFrom".toCharArray();
private static final char[] FILL_VALUES_STATIC_METHOD_NAME = "$fillValuesFromInstanceIntoBuilder".toCharArray();
private static final char[] INSTANCE_VARIABLE_NAME = "instance".toCharArray();
private static final String BUILDER_VARIABLE_NAME_STRING = "b";
private static final char[] BUILDER_VARIABLE_NAME = BUILDER_VARIABLE_NAME_STRING.toCharArray();
- private static final AbstractMethodDeclaration[] EMPTY_METHODS = {};
-
- @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;
+ class SuperBuilderJob extends BuilderJob {
+ void init(AnnotationValues<SuperBuilder> annValues, SuperBuilder ann, EclipseNode node) {
+ accessOuters = accessInners = AccessLevel.PUBLIC;
+ oldFluent = true;
+ oldChain = true;
+
+ builderMethodName = ann.builderMethodName();
+ buildMethodName = ann.buildMethodName();
+ toBuilder = ann.toBuilder();
+
+ if (builderMethodName == null) builderMethodName = "builder";
+ if (buildMethodName == null) buildMethodName = "build";
+ builderClassName = fixBuilderClassName(node, "");
+ }
- SuperBuilder superbuilderAnnotation = annotation.getInstance();
+ EclipseNode builderAbstractType;
+ String builderAbstractClassName;
+ char[] builderAbstractClassNameArr;
+ EclipseNode builderImplType;
+ String builderImplClassName;
+ char[] builderImplClassNameArr;
+ private TypeParameter[] builderTypeParams_;
+ void setBuilderToImpl() {
+ builderType = builderImplType;
+ builderClassName = builderImplClassName;
+ builderClassNameArr = builderImplClassNameArr;
+ builderTypeParams = typeParams;
+ }
- String builderMethodName = superbuilderAnnotation.builderMethodName();
- String buildMethodName = superbuilderAnnotation.buildMethodName();
+ void setBuilderToAbstract() {
+ builderType = builderAbstractType;
+ builderClassName = builderAbstractClassName;
+ builderClassNameArr = builderAbstractClassNameArr;
+ builderTypeParams = builderTypeParams_;
+ }
+ }
+
+ @Override public void handle(AnnotationValues<SuperBuilder> annotation, Annotation ast, EclipseNode annotationNode) {
+ handleExperimentalFlagUsage(annotationNode, ConfigurationKeys.SUPERBUILDER_FLAG_USAGE, "@SuperBuilder");
+ SuperBuilderJob job = new SuperBuilderJob();
+ job.sourceNode = annotationNode;
+ job.source = ast;
+ job.checkerFramework = getCheckerFrameworkVersion(annotationNode);
+ job.isStatic = true;
- if (builderMethodName == null) builderMethodName = "builder";
- if (buildMethodName == null) buildMethodName = "build";
+ SuperBuilder annInstance = annotation.getInstance();
+ job.init(annotation, annInstance, annotationNode);
boolean generateBuilderMethod;
- if (builderMethodName.isEmpty()) {
+ if (job.builderMethodName.isEmpty()) {
generateBuilderMethod = false;
- } else if (!checkName("builderMethodName", builderMethodName, annotationNode)) {
+ } else if (!checkName("builderMethodName", job.builderMethodName, annotationNode)) {
return;
} else {
generateBuilderMethod = true;
}
- if (!checkName("buildMethodName", buildMethodName, annotationNode)) return;
- boolean toBuilder = superbuilderAnnotation.toBuilder();
+ if (!checkName("buildMethodName", job.buildMethodName, annotationNode)) return;
- EclipseNode tdParent = annotationNode.up();
+ EclipseNode parent = annotationNode.up();
- java.util.List<BuilderFieldData> builderFields = new ArrayList<BuilderFieldData>();
- TypeReference returnType;
- TypeParameter[] typeParams;
+ job.builderFields = new ArrayList<BuilderFieldData>();
+ TypeReference buildMethodReturnType;
boolean addCleaning = false;
- if (!(tdParent.get() instanceof TypeDeclaration)) {
+ List<EclipseNode> nonFinalNonDefaultedFields = null;
+
+ if (!(parent.get() instanceof TypeDeclaration)) {
annotationNode.addError("@SuperBuilder is only supported on types.");
return;
}
- TypeDeclaration td = (TypeDeclaration) tdParent.get();
+ job.parentType = parent;
+ TypeDeclaration td = (TypeDeclaration) parent.get();
// Gather all fields of the class that should be set by the builder.
List<EclipseNode> allFields = new ArrayList<EclipseNode>();
- List<EclipseNode> nonFinalNonDefaultedFields = null;
- boolean valuePresent = (hasAnnotation(lombok.Value.class, tdParent) || hasAnnotation("lombok.experimental.Value", tdParent));
- for (EclipseNode fieldNode : HandleConstructor.findAllFields(tdParent, true)) {
+ boolean valuePresent = (hasAnnotation(lombok.Value.class, parent) || hasAnnotation("lombok.experimental.Value", parent));
+ for (EclipseNode fieldNode : HandleConstructor.findAllFields(parent, true)) {
FieldDeclaration fd = (FieldDeclaration) fieldNode.get();
EclipseNode isDefault = findAnnotation(Builder.Default.class, fieldNode);
boolean isFinal = ((fd.modifiers & ClassFileConstants.AccFinal) != 0) || (valuePresent && !hasAnnotation(NonFinal.class, fieldNode));
@@ -180,7 +203,7 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
bfd.builderFieldName = bfd.name;
bfd.annotations = copyAnnotations(fd, copyableAnnotations);
bfd.type = fd.type;
- bfd.singularData = getSingularData(fieldNode, ast, superbuilderAnnotation.setterPrefix());
+ bfd.singularData = getSingularData(fieldNode, ast, annInstance.setterPrefix());
bfd.originalFieldNode = fieldNode;
if (bfd.singularData != null && isDefault != null) {
@@ -205,21 +228,15 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
bfd.builderFieldName = prefixWith(bfd.name, VALUE_PREFIX);
MethodDeclaration md = HandleBuilder.generateDefaultProvider(bfd.nameOfDefaultProvider, td.typeParameters, fieldNode, ast);
- if (md != null) injectMethod(tdParent, md);
+ if (md != null) injectMethod(parent, md);
}
addObtainVia(bfd, fieldNode);
- builderFields.add(bfd);
+ job.builderFields.add(bfd);
allFields.add(fieldNode);
}
- // Set the names of the builder classes.
- String builderClassNameTemplate = annotationNode.getAst().readConfiguration(ConfigurationKeys.BUILDER_CLASS_NAME);
- if (builderClassNameTemplate == null || builderClassNameTemplate.isEmpty()) builderClassNameTemplate = "*Builder";
- String builderClassName = builderClassNameTemplate.replace("*", String.valueOf(td.name));
- String builderImplClassName = builderClassName + "Impl";
-
- typeParams = td.typeParameters != null ? td.typeParameters : new TypeParameter[0];
- returnType = namePlusTypeParamsToTypeReference(tdParent, typeParams, p);
+ job.typeParams = td.typeParameters != null ? td.typeParameters : new TypeParameter[0];
+ buildMethodReturnType = job.createBuilderParentTypeReference();
// <C, B> are the generics for our builder.
String classGenericName = "C";
@@ -227,25 +244,41 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
// We have to make sure that the generics' names do not collide with any generics on the annotated class,
// the classname itself, or any member type name of the annotated class.
// For instance, if there are generics <B, B2, C> on the annotated class, use "C2" and "B3" for our builder.
- java.util.Set<String> usedNames = gatherUsedTypeNames(typeParams, td);
+ java.util.Set<String> usedNames = gatherUsedTypeNames(job.typeParams, td);
classGenericName = generateNonclashingNameFor(classGenericName, usedNames);
builderGenericName = generateNonclashingNameFor(builderGenericName, usedNames);
+ TypeParameter[] paddedTypeParameters; {
+ paddedTypeParameters = new TypeParameter[job.typeParams.length + 2];
+ System.arraycopy(job.typeParams, 0, paddedTypeParameters, 0, job.typeParams.length);
+
+ TypeParameter c = new TypeParameter();
+ c.name = classGenericName.toCharArray();
+ c.type = cloneSelfType(job.parentType, job.source);
+ paddedTypeParameters[paddedTypeParameters.length - 2] = c;
+
+ TypeParameter b = new TypeParameter();
+ b.name = builderGenericName.toCharArray();
+ b.type = cloneSelfType(job.parentType, job.source);
+ paddedTypeParameters[paddedTypeParameters.length - 1] = b;
+ }
+ job.builderTypeParams = job.builderTypeParams_ = paddedTypeParameters;
+
TypeReference extendsClause = td.superclass;
TypeReference superclassBuilderClass = null;
TypeReference[] typeArguments = new TypeReference[] {
new SingleTypeReference(classGenericName.toCharArray(), 0),
- new SingleTypeReference(builderGenericName.toCharArray(), 0)
+ new SingleTypeReference(builderGenericName.toCharArray(), 0),
};
if (extendsClause instanceof QualifiedTypeReference) {
QualifiedTypeReference qualifiedTypeReference = (QualifiedTypeReference)extendsClause;
String superclassClassName = String.valueOf(qualifiedTypeReference.getLastToken());
- String superclassBuilderClassName = builderClassNameTemplate.replace("*", superclassClassName);
+ String superclassBuilderClassName = job.replaceBuilderClassName(superclassClassName);
char[][] tokens = Arrays.copyOf(qualifiedTypeReference.tokens, qualifiedTypeReference.tokens.length + 1);
tokens[tokens.length-1] = superclassBuilderClassName.toCharArray();
long[] poss = new long[tokens.length];
- Arrays.fill(poss, p);
+ Arrays.fill(poss, job.getPos());
TypeReference[] superclassTypeArgs = getTypeParametersFrom(extendsClause);
@@ -261,7 +294,7 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
char[][] tokens = new char[][] {superClass.toCharArray(), superclassBuilderClassName.toCharArray()};
long[] poss = new long[tokens.length];
- Arrays.fill(poss, p);
+ Arrays.fill(poss, job.getPos());
TypeReference[] superclassTypeArgs = getTypeParametersFrom(extendsClause);
@@ -272,40 +305,43 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
superclassBuilderClass = new ParameterizedQualifiedTypeReference(tokens, typeArgsForTokens, 0, poss);
}
+ job.builderAbstractClassName = job.builderClassName = job.replaceBuilderClassName(td.name);
+ job.builderAbstractClassNameArr = job.builderClassNameArr = job.builderAbstractClassName.toCharArray();
+ job.builderImplClassName = job.builderAbstractClassName + "Impl";
+ job.builderImplClassNameArr = job.builderImplClassName.toCharArray();
+
// If there is no superclass, superclassBuilderClassExpression is still == null at this point.
// You can use it to check whether to inherit or not.
- if (!constructorExists(tdParent, builderClassName)) {
- generateBuilderBasedConstructor(cfv, tdParent, typeParams, builderFields, annotationNode, builderClassName,
- superclassBuilderClass != null);
+ if (!constructorExists(parent, job.builderClassName)) {
+ generateBuilderBasedConstructor(job, superclassBuilderClass != null);
}
// Create the abstract builder class, or reuse an existing one.
- EclipseNode builderType = findInnerClass(tdParent, builderClassName);
- if (builderType == null) {
- builderType = generateBuilderAbstractClass(tdParent, builderClassName, superclassBuilderClass,
- typeParams, ast, classGenericName, builderGenericName);
+ job.builderAbstractType = findInnerClass(parent, job.builderClassName);
+ if (job.builderAbstractType == null) {
+ job.builderAbstractType = generateBuilderAbstractClass(job, superclassBuilderClass, classGenericName, builderGenericName);
} else {
- TypeDeclaration builderTypeDeclaration = (TypeDeclaration) builderType.get();
+ TypeDeclaration builderTypeDeclaration = (TypeDeclaration) job.builderAbstractType.get();
if ((builderTypeDeclaration.modifiers & (ClassFileConstants.AccStatic | ClassFileConstants.AccAbstract)) == 0) {
annotationNode.addError("Existing Builder must be an abstract static inner class.");
return;
}
- sanityCheckForMethodGeneratingAnnotationsOnBuilderClass(builderType, annotationNode);
+ sanityCheckForMethodGeneratingAnnotationsOnBuilderClass(job.builderAbstractType, annotationNode);
// Generate errors for @Singular BFDs that have one already defined node.
- for (BuilderFieldData bfd : builderFields) {
+ for (BuilderFieldData bfd : job.builderFields) {
SingularData sd = bfd.singularData;
if (sd == null) continue;
EclipseSingularizer singularizer = sd.getSingularizer();
if (singularizer == null) continue;
- if (singularizer.checkForAlreadyExistingNodesAndGenerateError(builderType, sd)) {
+ if (singularizer.checkForAlreadyExistingNodesAndGenerateError(job.builderAbstractType, sd)) {
bfd.singularData = null;
}
}
}
// Check validity of @ObtainVia fields, and add check if adding cleaning for @Singular is necessary.
- for (BuilderFieldData bfd : builderFields) {
+ for (BuilderFieldData bfd : job.builderFields) {
if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) {
if (bfd.singularData.getSingularizer().requiresCleaning()) {
addCleaning = true;
@@ -325,47 +361,52 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
}
// Generate the fields in the abstract builder class that hold the values for the instance.
- generateBuilderFields(builderType, builderFields, ast);
+ job.setBuilderToAbstract();
+ generateBuilderFields(job);
if (addCleaning) {
FieldDeclaration cleanDecl = new FieldDeclaration(CLEAN_FIELD_NAME, 0, -1);
cleanDecl.declarationSourceEnd = -1;
cleanDecl.modifiers = ClassFileConstants.AccPrivate;
cleanDecl.type = TypeReference.baseTypeReference(TypeIds.T_boolean, 0);
- injectFieldAndMarkGenerated(builderType, cleanDecl);
+ injectFieldAndMarkGenerated(job.builderType, cleanDecl);
}
- if (toBuilder) {
+ if (job.toBuilder) {
// Generate $fillValuesFrom() method in the abstract builder.
- injectMethod(builderType, generateFillValuesMethod(tdParent, superclassBuilderClass != null, builderGenericName, classGenericName, builderClassName, typeParams));
+ injectMethod(job.builderType, generateFillValuesMethod(job, superclassBuilderClass != null, builderGenericName, classGenericName));
// Generate $fillValuesFromInstanceIntoBuilder() method in the builder implementation class.
- injectMethod(builderType, generateStaticFillValuesMethod(tdParent, builderClassName, typeParams, builderFields, ast, superbuilderAnnotation.setterPrefix()));
+ injectMethod(job.builderType, generateStaticFillValuesMethod(job, annInstance.setterPrefix()));
}
// Generate abstract self() and build() methods in the abstract builder.
- injectMethod(builderType, generateAbstractSelfMethod(cfv, tdParent, superclassBuilderClass != null, builderGenericName));
- injectMethod(builderType, generateAbstractBuildMethod(cfv, builderType, buildMethodName, builderFields, superclassBuilderClass != null, classGenericName, ast));
+ injectMethod(job.builderType, generateAbstractSelfMethod(job, superclassBuilderClass != null, builderGenericName));
+ job.setBuilderToAbstract();
+ injectMethod(job.builderType, generateAbstractBuildMethod(job, superclassBuilderClass != null, classGenericName));
// Create the setter methods in the abstract builder.
- for (BuilderFieldData bfd : builderFields) {
- generateSetterMethodsForBuilder(cfv, builderType, bfd, annotationNode, builderGenericName, superbuilderAnnotation.setterPrefix());
+ for (BuilderFieldData bfd : job.builderFields) {
+ generateSetterMethodsForBuilder(job, bfd, builderGenericName, annInstance.setterPrefix());
}
// Create the toString() method for the abstract builder.
- if (methodExists("toString", builderType, 0) == MemberExistsResult.NOT_EXISTS) {
+ if (methodExists("toString", job.builderType, 0) == MemberExistsResult.NOT_EXISTS) {
List<Included<EclipseNode, ToString.Include>> fieldNodes = new ArrayList<Included<EclipseNode, ToString.Include>>();
- for (BuilderFieldData bfd : builderFields) {
+ for (BuilderFieldData bfd : job.builderFields) {
for (EclipseNode f : bfd.createdFields) {
fieldNodes.add(new Included<EclipseNode, ToString.Include>(f, null, true, false));
}
}
// Let toString() call super.toString() if there is a superclass, so that it also shows fields from the superclass' builder.
- MethodDeclaration md = HandleToString.createToString(builderType, fieldNodes, true, superclassBuilderClass != null, ast, FieldAccess.ALWAYS_FIELD);
+ MethodDeclaration md = HandleToString.createToString(job.builderType, fieldNodes, true, superclassBuilderClass != null, ast, FieldAccess.ALWAYS_FIELD);
if (md != null) {
- injectMethod(builderType, md);
+ injectMethod(job.builderType, md);
}
}
- if (addCleaning) injectMethod(builderType, generateCleanMethod(builderFields, builderType, ast));
+ if (addCleaning) {
+ job.setBuilderToAbstract();
+ injectMethod(job.builderType, generateCleanMethod(job));
+ }
boolean isAbstract = (td.modifiers & ClassFileConstants.AccAbstract) != 0;
if (isAbstract) {
@@ -374,26 +415,27 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
}
// Create the builder implementation class, or reuse an existing one.
- EclipseNode builderImplType = findInnerClass(tdParent, builderImplClassName);
- if (builderImplType == null) {
- builderImplType = generateBuilderImplClass(tdParent, builderImplClassName, builderClassName, typeParams, ast);
+ job.builderImplType = findInnerClass(parent, job.builderImplClassName);
+ if (job.builderImplType == null) {
+ job.builderImplType = generateBuilderImplClass(job, job.builderImplClassName);
} else {
- TypeDeclaration builderImplTypeDeclaration = (TypeDeclaration) builderImplType.get();
+ TypeDeclaration builderImplTypeDeclaration = (TypeDeclaration) job.builderImplType.get();
if ((builderImplTypeDeclaration.modifiers & ClassFileConstants.AccAbstract) != 0 ||
(builderImplTypeDeclaration.modifiers & ClassFileConstants.AccStatic) == 0) {
annotationNode.addError("Existing BuilderImpl must be a non-abstract static inner class.");
return;
}
- sanityCheckForMethodGeneratingAnnotationsOnBuilderClass(builderImplType, annotationNode);
+ sanityCheckForMethodGeneratingAnnotationsOnBuilderClass(job.builderImplType, annotationNode);
}
- if (toBuilder) {
+ job.setBuilderToImpl();
+ if (job.toBuilder) {
// Add the toBuilder() method to the annotated class.
- switch (methodExists(TO_BUILDER_METHOD_NAME_STRING, tdParent, 0)) {
+ switch (methodExists(TO_BUILDER_METHOD_NAME_STRING, job.parentType, 0)) {
case EXISTS_BY_USER:
break;
case NOT_EXISTS:
- injectMethod(tdParent, generateToBuilderMethod(cfv, builderClassName, builderImplClassName, tdParent, typeParams, ast));
+ injectMethod(parent, generateToBuilderMethod(job));
break;
default:
// Should not happen.
@@ -401,17 +443,19 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
}
// Create the self() and build() methods in the BuilderImpl.
- injectMethod(builderImplType, generateSelfMethod(cfv, builderImplType, typeParams, p));
+ job.setBuilderToImpl();
+ injectMethod(job.builderImplType, generateSelfMethod(job));
- if (methodExists(buildMethodName, builderImplType, -1) == MemberExistsResult.NOT_EXISTS) {
- injectMethod(builderImplType, generateBuildMethod(cfv, builderImplType, buildMethodName, returnType, builderFields, ast));
+ if (methodExists(job.buildMethodName, job.builderImplType, -1) == MemberExistsResult.NOT_EXISTS) {
+ job.setBuilderToImpl();
+ injectMethod(job.builderImplType, generateBuildMethod(job, buildMethodReturnType));
}
// Add the builder() method to the annotated class.
- if (generateBuilderMethod && methodExists(builderMethodName, tdParent, -1) != MemberExistsResult.NOT_EXISTS) generateBuilderMethod = false;
+ if (generateBuilderMethod && methodExists(job.builderMethodName, parent, -1) != MemberExistsResult.NOT_EXISTS) generateBuilderMethod = false;
if (generateBuilderMethod) {
- MethodDeclaration md = generateBuilderMethod(cfv, builderMethodName, builderClassName, builderImplClassName, tdParent, typeParams, ast);
- if (md != null) injectMethod(tdParent, md);
+ MethodDeclaration md = generateBuilderMethod(job);
+ if (md != null) injectMethod(parent, md);
}
if (nonFinalNonDefaultedFields != null && generateBuilderMethod) {
@@ -421,97 +465,82 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
}
}
- private EclipseNode generateBuilderAbstractClass(EclipseNode tdParent, String builderClass,
- TypeReference superclassBuilderClass, TypeParameter[] typeParams,
- ASTNode source, String classGenericName, String builderGenericName) {
-
- TypeDeclaration parent = (TypeDeclaration) tdParent.get();
+ private EclipseNode generateBuilderAbstractClass(BuilderJob job, TypeReference superclassBuilderClass, String classGenericName, String builderGenericName) {
+ TypeDeclaration parent = (TypeDeclaration) job.parentType.get();
TypeDeclaration builder = new TypeDeclaration(parent.compilationResult);
builder.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG;
builder.modifiers |= ClassFileConstants.AccPublic | ClassFileConstants.AccStatic | ClassFileConstants.AccAbstract;
- builder.name = builderClass.toCharArray();
+ builder.name = job.builderClassNameArr;
// Keep any type params of the annotated class.
- builder.typeParameters = Arrays.copyOf(copyTypeParams(typeParams, source), typeParams.length + 2);
+ builder.typeParameters = Arrays.copyOf(copyTypeParams(job.typeParams, job.source), job.typeParams.length + 2);
// Add builder-specific type params required for inheritable builders.
// 1. The return type for the build() method, named "C", which extends the annotated class.
TypeParameter o = new TypeParameter();
o.name = classGenericName.toCharArray();
- o.type = cloneSelfType(tdParent, source);
+ o.type = cloneSelfType(job.parentType, job.source);
builder.typeParameters[builder.typeParameters.length - 2] = o;
// 2. The return type for all setter methods, named "B", which extends this builder class.
o = new TypeParameter();
o.name = builderGenericName.toCharArray();
- TypeReference[] typerefs = appendBuilderTypeReferences(typeParams, classGenericName, builderGenericName);
- o.type = generateParameterizedTypeReference(tdParent, builderClass.toCharArray(), false, typerefs, 0);
+ TypeReference[] typerefs = appendBuilderTypeReferences(job.typeParams, classGenericName, builderGenericName);
+ o.type = generateParameterizedTypeReference(job.parentType, job.builderClassNameArr, false, typerefs, 0);
builder.typeParameters[builder.typeParameters.length - 1] = o;
- builder.superclass = copyType(superclassBuilderClass, source);
+ if (superclassBuilderClass != null) builder.superclass = copyType(superclassBuilderClass, job.source);
builder.createDefaultConstructor(false, true);
- builder.traverse(new SetGeneratedByVisitor(source), (ClassScope) null);
- return injectType(tdParent, builder);
+ builder.traverse(new SetGeneratedByVisitor(job.source), (ClassScope) null);
+ return injectType(job.parentType, builder);
}
- private EclipseNode generateBuilderImplClass(EclipseNode tdParent, String builderImplClass, String builderAbstractClass, TypeParameter[] typeParams, ASTNode source) {
- TypeDeclaration parent = (TypeDeclaration) tdParent.get();
+ private EclipseNode generateBuilderImplClass(BuilderJob job, String builderImplClass) {
+ TypeDeclaration parent = (TypeDeclaration) job.parentType.get();
TypeDeclaration builder = new TypeDeclaration(parent.compilationResult);
builder.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG;
builder.modifiers |= ClassFileConstants.AccPrivate | ClassFileConstants.AccStatic | ClassFileConstants.AccFinal;
builder.name = builderImplClass.toCharArray();
// Add type params if there are any.
- if (typeParams != null && typeParams.length > 0) builder.typeParameters = copyTypeParams(typeParams, source);
+ if (job.typeParams != null && job.typeParams.length > 0) builder.typeParameters = copyTypeParams(job.typeParams, job.source);
- if (builderAbstractClass != null) {
+ if (job.builderClassName != null) {
// Extend the abstract builder.
// 1. Add any type params of the annotated class.
- TypeReference[] typeArgs = new TypeReference[typeParams.length + 2];
- for (int i = 0; i < typeParams.length; i++) {
- typeArgs[i] = new SingleTypeReference(typeParams[i].name, 0);
+ TypeReference[] typeArgs = new TypeReference[job.typeParams.length + 2];
+ for (int i = 0; i < job.typeParams.length; i++) {
+ typeArgs[i] = new SingleTypeReference(job.typeParams[i].name, 0);
}
// 2. The return type for the build() method (named "C" in the abstract builder), which is the annotated class.
// 3. The return type for all setter methods (named "B" in the abstract builder), which is this builder class.
- typeArgs[typeArgs.length - 2] = cloneSelfType(tdParent, source);
- typeArgs[typeArgs.length - 1] = createTypeReferenceWithTypeParameters(tdParent, builderImplClass, typeParams);
- builder.superclass = generateParameterizedTypeReference(tdParent, builderAbstractClass.toCharArray(), false, typeArgs, 0);
+ typeArgs[typeArgs.length - 2] = cloneSelfType(job.parentType, job.source);
+ typeArgs[typeArgs.length - 1] = createTypeReferenceWithTypeParameters(job.parentType, builderImplClass, job.typeParams);
+ builder.superclass = generateParameterizedTypeReference(job.parentType, job.builderClassNameArr, false, typeArgs, 0);
}
builder.createDefaultConstructor(false, true);
- builder.traverse(new SetGeneratedByVisitor(source), (ClassScope) null);
- return injectType(tdParent, builder);
+ builder.traverse(new SetGeneratedByVisitor(job.source), (ClassScope) null);
+ return injectType(job.parentType, builder);
}
/**
* Generates a constructor that has a builder as the only parameter.
* The values from the builder are used to initialize the fields of new instances.
*
- * @param typeNode
- * 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
* If {@code true}, the constructor will explicitly call a super
* constructor with the builder as argument. Requires
* {@code builderClassAsParameter != null}.
*/
- private void generateBuilderBasedConstructor(CheckerFrameworkVersion cfv, EclipseNode typeNode, TypeParameter[] typeParams, List<BuilderFieldData> builderFields,
- EclipseNode sourceNode, String builderClassName, boolean callBuilderBasedSuperConstructor) {
-
- ASTNode source = sourceNode.get();
+ private void generateBuilderBasedConstructor(BuilderJob job, boolean callBuilderBasedSuperConstructor) {
+ TypeDeclaration typeDeclaration = ((TypeDeclaration) job.parentType.get());
+ long p = job.getPos();
- TypeDeclaration typeDeclaration = ((TypeDeclaration) typeNode.get());
- long p = (long) source.sourceStart << 32 | source.sourceEnd;
-
- ConstructorDeclaration constructor = new ConstructorDeclaration(((CompilationUnitDeclaration) typeNode.top().get()).compilationResult);
+ ConstructorDeclaration constructor = new ConstructorDeclaration(((CompilationUnitDeclaration) job.parentType.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);
@@ -519,21 +548,21 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
} else {
constructor.constructorCall = new ExplicitConstructorCall(ExplicitConstructorCall.ImplicitSuper);
}
- constructor.constructorCall.sourceStart = source.sourceStart;
- constructor.constructorCall.sourceEnd = source.sourceEnd;
+ constructor.constructorCall.sourceStart = job.source.sourceStart;
+ constructor.constructorCall.sourceEnd = job.source.sourceEnd;
constructor.thrownExceptions = null;
constructor.typeParameters = null;
constructor.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
- constructor.bodyStart = constructor.declarationSourceStart = constructor.sourceStart = source.sourceStart;
- constructor.bodyEnd = constructor.declarationSourceEnd = constructor.sourceEnd = source.sourceEnd;
+ constructor.bodyStart = constructor.declarationSourceStart = constructor.sourceStart = job.source.sourceStart;
+ constructor.bodyEnd = constructor.declarationSourceEnd = constructor.sourceEnd = job.source.sourceEnd;
TypeReference[] wildcards = new TypeReference[] {new Wildcard(Wildcard.UNBOUND), new Wildcard(Wildcard.UNBOUND)};
- TypeReference builderType = generateParameterizedTypeReference(typeNode, builderClassName.toCharArray(), false, mergeToTypeReferences(typeParams, wildcards), p);
+ TypeReference builderType = generateParameterizedTypeReference(job.parentType, job.builderClassNameArr, false, mergeToTypeReferences(job.typeParams, wildcards), p);
constructor.arguments = new Argument[] {new Argument(BUILDER_VARIABLE_NAME, p, builderType, Modifier.FINAL)};
List<Statement> statements = new ArrayList<Statement>();
- for (BuilderFieldData fieldNode : builderFields) {
+ for (BuilderFieldData fieldNode : job.builderFields) {
FieldReference fieldInThis = new FieldReference(fieldNode.rawName, p);
int s = (int) (p >> 32);
int e = (int) p;
@@ -541,7 +570,7 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
Expression assignmentExpr;
if (fieldNode.singularData != null && fieldNode.singularData.getSingularizer() != null) {
- fieldNode.singularData.getSingularizer().appendBuildCode(fieldNode.singularData, typeNode, statements, fieldNode.builderFieldName, BUILDER_VARIABLE_NAME_STRING);
+ fieldNode.singularData.getSingularizer().appendBuildCode(fieldNode.singularData, job.parentType, statements, fieldNode.builderFieldName, BUILDER_VARIABLE_NAME_STRING);
assignmentExpr = new SingleNameReference(fieldNode.builderFieldName, p);
} else {
char[][] variableInBuilder = new char[][] {BUILDER_VARIABLE_NAME, fieldNode.builderFieldName};
@@ -557,11 +586,11 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
QualifiedNameReference setVariableInBuilderRef = new QualifiedNameReference(setVariableInBuilder, positions, s, e);
MessageSend defaultMethodCall = new MessageSend();
- defaultMethodCall.sourceStart = source.sourceStart;
- defaultMethodCall.sourceEnd = source.sourceEnd;
- defaultMethodCall.receiver = generateNameReference(typeNode, 0L);
+ defaultMethodCall.sourceStart = job.source.sourceStart;
+ defaultMethodCall.sourceEnd = job.source.sourceEnd;
+ defaultMethodCall.receiver = generateNameReference(job.parentType, 0L);
defaultMethodCall.selector = fieldNode.nameOfDefaultProvider;
- defaultMethodCall.typeArguments = typeParameterNames(((TypeDeclaration) typeNode.get()).typeParameters);
+ defaultMethodCall.typeArguments = typeParameterNames(((TypeDeclaration) job.parentType.get()).typeParameters);
Statement defaultAssignment = new Assignment(fieldInThis, defaultMethodCall, (int) p);
IfStatement ifBlockForDefault = new IfStatement(setVariableInBuilderRef, assignment, defaultAssignment, s, e);
@@ -571,41 +600,44 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
}
if (hasNonNullAnnotations(fieldNode.originalFieldNode)) {
- Statement nullCheck = generateNullCheck((FieldDeclaration) fieldNode.originalFieldNode.get(), sourceNode, null);
+ Statement nullCheck = generateNullCheck((FieldDeclaration) fieldNode.originalFieldNode.get(), job.sourceNode, null);
if (nullCheck != null) statements.add(nullCheck);
}
}
constructor.statements = statements.isEmpty() ? null : statements.toArray(new Statement[0]);
- constructor.traverse(new SetGeneratedByVisitor(source), typeDeclaration.scope);
+ constructor.traverse(new SetGeneratedByVisitor(job.source), typeDeclaration.scope);
- injectMethod(typeNode, constructor);
+ injectMethod(job.parentType, constructor);
}
- private MethodDeclaration generateBuilderMethod(CheckerFrameworkVersion cfv, String builderMethodName, String builderClassName, String builderImplClassName, EclipseNode type, TypeParameter[] typeParams, ASTNode source) {
- int pS = source.sourceStart, pE = source.sourceEnd;
+ private MethodDeclaration generateBuilderMethod(SuperBuilderJob job) {
+ int pS = job.source.sourceStart, pE = job.source.sourceEnd;
long p = (long) pS << 32 | pE;
- MethodDeclaration out = new MethodDeclaration(((CompilationUnitDeclaration) type.top().get()).compilationResult);
- out.selector = builderMethodName.toCharArray();
+ MethodDeclaration out = job.createNewMethodDeclaration();
+ out.selector = job.builderMethodName.toCharArray();
out.modifiers = ClassFileConstants.AccPublic | ClassFileConstants.AccStatic;
out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
// Add type params if there are any.
- if (typeParams != null && typeParams.length > 0) out.typeParameters = copyTypeParams(typeParams, source);
+ if (job.typeParams != null && job.typeParams.length > 0) out.typeParameters = copyTypeParams(job.typeParams, job.source);
TypeReference[] wildcards = new TypeReference[] {new Wildcard(Wildcard.UNBOUND), new Wildcard(Wildcard.UNBOUND) };
- out.returnType = generateParameterizedTypeReference(type, builderClassName.toCharArray(), false, mergeToTypeReferences(typeParams, wildcards), p);
+ out.returnType = generateParameterizedTypeReference(job.parentType, job.builderAbstractClassNameArr, false, mergeToTypeReferences(job.typeParams, wildcards), p);
+ if (job.checkerFramework.generateUnique()) {
+ int len = out.returnType.getTypeName().length;
+ out.returnType.annotations = new Annotation[len][];
+ out.returnType.annotations[len - 1] = new Annotation[] {generateNamedAnnotation(job.source, CheckerFrameworkVersion.NAME__UNIQUE)};
+ }
AllocationExpression invoke = new AllocationExpression();
- invoke.type = namePlusTypeParamsToTypeReference(type, builderImplClassName.toCharArray(), false, typeParams, p);
+ invoke.type = namePlusTypeParamsToTypeReference(job.parentType, job.builderImplClassNameArr, false, job.typeParams, p);
out.statements = new Statement[] {new ReturnStatement(invoke, pS, pE)};
- if (cfv.generateUnique()) out.annotations = new Annotation[] {generateNamedAnnotation(source, CheckerFrameworkVersion.NAME__UNIQUE)};
-
- createRelevantNonNullAnnotation(type, out);
- out.traverse(new SetGeneratedByVisitor(source), ((TypeDeclaration) type.get()).scope);
+ createRelevantNonNullAnnotation(job.parentType, out);
+ out.traverse(new SetGeneratedByVisitor(job.source), ((TypeDeclaration) job.parentType.get()).scope);
return out;
}
@@ -617,30 +649,33 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
* }
* </pre>
*/
- private MethodDeclaration generateToBuilderMethod(CheckerFrameworkVersion cfv, String builderClassName, String builderImplClassName, EclipseNode type, TypeParameter[] typeParams, ASTNode source) {
- int pS = source.sourceStart, pE = source.sourceEnd;
+ private MethodDeclaration generateToBuilderMethod(SuperBuilderJob job) {
+ int pS = job.source.sourceStart, pE = job.source.sourceEnd;
long p = (long) pS << 32 | pE;
- MethodDeclaration out = new MethodDeclaration(((CompilationUnitDeclaration) type.top().get()).compilationResult);
+ MethodDeclaration out = job.createNewMethodDeclaration();
out.selector = TO_BUILDER_METHOD_NAME;
out.modifiers = ClassFileConstants.AccPublic;
out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
TypeReference[] wildcards = new TypeReference[] {new Wildcard(Wildcard.UNBOUND), new Wildcard(Wildcard.UNBOUND) };
- out.returnType = generateParameterizedTypeReference(type, builderClassName.toCharArray(), false, mergeToTypeReferences(typeParams, wildcards), p);
+ out.returnType = generateParameterizedTypeReference(job.parentType, job.builderAbstractClassNameArr, false, mergeToTypeReferences(job.typeParams, wildcards), p);
+ if (job.checkerFramework.generateUnique()) {
+ int len = out.returnType.getTypeName().length;
+ out.returnType.annotations = new Annotation[len][];
+ out.returnType.annotations[len - 1] = new Annotation[] {generateNamedAnnotation(job.source, CheckerFrameworkVersion.NAME__UNIQUE)};
+ }
AllocationExpression newClass = new AllocationExpression();
- newClass.type = namePlusTypeParamsToTypeReference(type, builderImplClassName.toCharArray(), false, typeParams, p);
+ newClass.type = namePlusTypeParamsToTypeReference(job.parentType, job.builderImplClassNameArr, false, job.typeParams, p);
MessageSend invokeFillMethod = new MessageSend();
invokeFillMethod.receiver = newClass;
invokeFillMethod.selector = FILL_VALUES_METHOD_NAME;
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)};
-
- createRelevantNonNullAnnotation(type, out);
- out.traverse(new SetGeneratedByVisitor(source), ((TypeDeclaration) type.get()).scope);
+ createRelevantNonNullAnnotation(job.parentType, out);
+ out.traverse(new SetGeneratedByVisitor(job.source), ((TypeDeclaration) job.parentType.get()).scope);
return out;
}
@@ -650,17 +685,17 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
* <pre>
* protected B $fillValuesFrom(final C instance) {
* super.$fillValuesFrom(instance);
- * Foobar.FoobarBuilderImpl.$fillValuesFromInstanceIntoBuilder(instance, this);
+ * Foobar.FoobarBuilder.$fillValuesFromInstanceIntoBuilder(instance, this);
* return self();
* }
* </pre>
*/
- private MethodDeclaration generateFillValuesMethod(EclipseNode tdParent, boolean inherited, String builderGenericName, String classGenericName, String builderClassName, TypeParameter[] typeParams) {
- MethodDeclaration out = new MethodDeclaration(((CompilationUnitDeclaration) tdParent.top().get()).compilationResult);
+ private MethodDeclaration generateFillValuesMethod(SuperBuilderJob job, boolean inherited, String builderGenericName, String classGenericName) {
+ MethodDeclaration out = job.createNewMethodDeclaration();
out.selector = FILL_VALUES_METHOD_NAME;
out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
out.modifiers = ClassFileConstants.AccProtected;
- if (inherited) out.annotations = new Annotation[] {makeMarkerAnnotation(TypeConstants.JAVA_LANG_OVERRIDE, tdParent.get())};
+ if (inherited) out.annotations = new Annotation[] {makeMarkerAnnotation(TypeConstants.JAVA_LANG_OVERRIDE, job.parentType.get())};
out.returnType = new SingleTypeReference(builderGenericName.toCharArray(), 0);
TypeReference builderType = new SingleTypeReference(classGenericName.toCharArray(), 0);
@@ -679,7 +714,7 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
// Call the builder implemention's helper method that actually fills the values from the instance.
MessageSend callStaticFillValuesMethod = new MessageSend();
- callStaticFillValuesMethod.receiver = generateNameReference(tdParent, builderClassName.toCharArray(), 0);
+ callStaticFillValuesMethod.receiver = generateNameReference(job.parentType, job.builderAbstractClassNameArr, 0);
callStaticFillValuesMethod.selector = FILL_VALUES_STATIC_METHOD_NAME;
callStaticFillValuesMethod.arguments = new Expression[] {new SingleNameReference(INSTANCE_VARIABLE_NAME, 0), new ThisReference(0, 0)};
body.add(callStaticFillValuesMethod);
@@ -707,41 +742,40 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
* </pre>
* @param setterPrefix the prefix for setter methods
*/
- private MethodDeclaration generateStaticFillValuesMethod(EclipseNode tdParent, String builderClassName, TypeParameter[] typeParams, java.util.List<BuilderFieldData> builderFields, ASTNode source, String setterPrefix) {
- MethodDeclaration out = new MethodDeclaration(((CompilationUnitDeclaration) tdParent.top().get()).compilationResult);
+ private MethodDeclaration generateStaticFillValuesMethod(BuilderJob job, String setterPrefix) {
+ MethodDeclaration out = job.createNewMethodDeclaration();
out.selector = FILL_VALUES_STATIC_METHOD_NAME;
out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
out.modifiers = ClassFileConstants.AccPrivate | ClassFileConstants.AccStatic;
out.returnType = TypeReference.baseTypeReference(TypeIds.T_void, 0);
TypeReference[] wildcards = new TypeReference[] {new Wildcard(Wildcard.UNBOUND), new Wildcard(Wildcard.UNBOUND)};
- TypeReference builderType = generateParameterizedTypeReference(tdParent, builderClassName.toCharArray(), false, mergeToTypeReferences(typeParams, wildcards), 0);
+ TypeReference builderType = generateParameterizedTypeReference(job.parentType, job.builderClassNameArr, false, mergeToTypeReferences(job.typeParams, wildcards), 0);
Argument builderArgument = new Argument(BUILDER_VARIABLE_NAME, 0, builderType, Modifier.FINAL);
TypeReference[] typerefs = null;
- if (typeParams.length > 0) {
- typerefs = new TypeReference[typeParams.length];
- for (int i = 0; i < typeParams.length; i++) typerefs[i] = new SingleTypeReference(typeParams[i].name, 0);
+ if (job.typeParams.length > 0) {
+ typerefs = new TypeReference[job.typeParams.length];
+ for (int i = 0; i < job.typeParams.length; i++) typerefs[i] = new SingleTypeReference(job.typeParams[i].name, 0);
}
- long p = source.sourceStart;
- p = (p << 32) | source.sourceEnd;
+ long p = job.getPos();
- TypeReference parentArgument = typerefs == null ? generateTypeReference(tdParent, p) : generateParameterizedTypeReference(tdParent, typerefs, p);
+ TypeReference parentArgument = typerefs == null ? generateTypeReference(job.parentType, p) : generateParameterizedTypeReference(job.parentType, typerefs, p);
out.arguments = new Argument[] {new Argument(INSTANCE_VARIABLE_NAME, 0, parentArgument, Modifier.FINAL), builderArgument};
// Add type params if there are any.
- if (typeParams.length > 0) out.typeParameters = copyTypeParams(typeParams, source);
+ if (job.typeParams.length > 0) out.typeParameters = copyTypeParams(job.typeParams, job.source);
List<Statement> body = new ArrayList<Statement>();
// Call the builder's setter methods to fill the values from the instance.
- for (BuilderFieldData bfd : builderFields) {
- MessageSend exec = createSetterCallWithInstanceValue(bfd, tdParent, source, setterPrefix);
+ for (BuilderFieldData bfd : job.builderFields) {
+ MessageSend exec = createSetterCallWithInstanceValue(bfd, job.parentType, job.source, setterPrefix);
body.add(exec);
}
out.statements = body.isEmpty() ? null : body.toArray(new Statement[0]);
- out.traverse(new SetGeneratedByVisitor(source), (ClassScope) null);
+ out.traverse(new SetGeneratedByVisitor(job.source), (ClassScope) null);
return out;
}
@@ -783,14 +817,14 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
return ms;
}
- private MethodDeclaration generateAbstractSelfMethod(CheckerFrameworkVersion cfv, EclipseNode tdParent, boolean override, String builderGenericName) {
- MethodDeclaration out = new MethodDeclaration(((CompilationUnitDeclaration) tdParent.top().get()).compilationResult);
+ private MethodDeclaration generateAbstractSelfMethod(BuilderJob job, boolean override, String builderGenericName) {
+ MethodDeclaration out = job.createNewMethodDeclaration();
out.selector = SELF_METHOD_NAME;
out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
out.modifiers = ClassFileConstants.AccAbstract | ClassFileConstants.AccProtected | ExtraCompilerModifiers.AccSemicolonBody;
- 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.generatePure() ? generateNamedAnnotation(tdParent.get(), CheckerFrameworkVersion.NAME__PURE): null;
+ Annotation overrideAnn = override ? makeMarkerAnnotation(TypeConstants.JAVA_LANG_OVERRIDE, job.parentType.get()) : null;
+ Annotation rrAnn = job.checkerFramework.generateReturnsReceiver() ? generateNamedAnnotation(job.parentType.get(), CheckerFrameworkVersion.NAME__RETURNS_RECEIVER): null;
+ Annotation sefAnn = job.checkerFramework.generatePure() ? generateNamedAnnotation(job.parentType.get(), CheckerFrameworkVersion.NAME__PURE): 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};
@@ -802,54 +836,52 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
return out;
}
- private MethodDeclaration generateSelfMethod(CheckerFrameworkVersion cfv, EclipseNode builderImplType, TypeParameter[] typeParams, long p) {
- MethodDeclaration out = new MethodDeclaration(((CompilationUnitDeclaration) builderImplType.top().get()).compilationResult);
+ private MethodDeclaration generateSelfMethod(BuilderJob job) {
+ MethodDeclaration out = job.createNewMethodDeclaration();
out.selector = SELF_METHOD_NAME;
out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
out.modifiers = ClassFileConstants.AccProtected;
- Annotation overrideAnn = makeMarkerAnnotation(TypeConstants.JAVA_LANG_OVERRIDE, builderImplType.get());
- Annotation rrAnn = cfv.generateReturnsReceiver() ? generateNamedAnnotation(builderImplType.get(), CheckerFrameworkVersion.NAME__RETURNS_RECEIVER) : null;
- Annotation sefAnn = cfv.generatePure() ? generateNamedAnnotation(builderImplType.get(), CheckerFrameworkVersion.NAME__PURE) : null;
+ Annotation overrideAnn = makeMarkerAnnotation(TypeConstants.JAVA_LANG_OVERRIDE, job.builderType.get());
+ Annotation rrAnn = job.checkerFramework.generateReturnsReceiver() ? generateNamedAnnotation(job.builderType.get(), CheckerFrameworkVersion.NAME__RETURNS_RECEIVER) : null;
+ Annotation sefAnn = job.checkerFramework.generatePure() ? generateNamedAnnotation(job.builderType.get(), CheckerFrameworkVersion.NAME__PURE) : 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, typeParams, p);
+ out.returnType = namePlusTypeParamsToTypeReference(job.builderType, job.typeParams, job.getPos());
out.statements = new Statement[] {new ReturnStatement(new ThisReference(0, 0), 0, 0)};
return out;
}
- private MethodDeclaration generateAbstractBuildMethod(CheckerFrameworkVersion cfv, EclipseNode builderType, String methodName, List<BuilderFieldData> builderFields, boolean override,
- String classGenericName, ASTNode source) {
-
- MethodDeclaration out = new MethodDeclaration(((CompilationUnitDeclaration) builderType.top().get()).compilationResult);
+ private MethodDeclaration generateAbstractBuildMethod(BuilderJob job, boolean override, String classGenericName) {
+ MethodDeclaration out = job.createNewMethodDeclaration();
out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
out.modifiers = ClassFileConstants.AccPublic | ClassFileConstants.AccAbstract | ExtraCompilerModifiers.AccSemicolonBody;
- out.selector = methodName.toCharArray();
+ out.selector = job.buildMethodName.toCharArray();
out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
out.returnType = new SingleTypeReference(classGenericName.toCharArray(), 0);
- Annotation overrideAnn = override ? makeMarkerAnnotation(TypeConstants.JAVA_LANG_OVERRIDE, source) : null;
- Annotation sefAnn = cfv.generateSideEffectFree() ? generateNamedAnnotation(source, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE): null;
+ Annotation overrideAnn = override ? makeMarkerAnnotation(TypeConstants.JAVA_LANG_OVERRIDE, job.source) : null;
+ Annotation sefAnn = job.checkerFramework.generateSideEffectFree() ? generateNamedAnnotation(job.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.receiver = HandleBuilder.generateBuildReceiver(cfv, builderType, builderFields, source);
- out.traverse(new SetGeneratedByVisitor(source), (ClassScope) null);
+ out.receiver = HandleBuilder.generateBuildReceiver(job);
+ out.traverse(new SetGeneratedByVisitor(job.source), (ClassScope) null);
return out;
}
- 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);
+ private MethodDeclaration generateBuildMethod(BuilderJob job, TypeReference returnType) {
+ MethodDeclaration out = job.createNewMethodDeclaration();
out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
List<Statement> statements = new ArrayList<Statement>();
out.modifiers = ClassFileConstants.AccPublic;
- out.selector = name.toCharArray();
+ out.selector = job.buildMethodName.toCharArray();
out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
out.returnType = returnType;
- Annotation overrideAnn = makeMarkerAnnotation(TypeConstants.JAVA_LANG_OVERRIDE, source);
- Annotation sefAnn = cfv.generateSideEffectFree() ? generateNamedAnnotation(source, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE): null;
+ Annotation overrideAnn = makeMarkerAnnotation(TypeConstants.JAVA_LANG_OVERRIDE, job.source);
+ Annotation sefAnn = job.checkerFramework.generateSideEffectFree() ? generateNamedAnnotation(job.source, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE): null;
if (sefAnn != null) out.annotations = new Annotation[] {overrideAnn, sefAnn};
else out.annotations = new Annotation[] {overrideAnn};
@@ -859,43 +891,44 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
allocationStatement.arguments = new Expression[] {new ThisReference(0, 0)};
statements.add(new ReturnStatement(allocationStatement, 0, 0));
out.statements = statements.isEmpty() ? null : statements.toArray(new Statement[0]);
- out.receiver = HandleBuilder.generateBuildReceiver(cfv, builderType, builderFields, source);
- createRelevantNonNullAnnotation(builderType, out);
- out.traverse(new SetGeneratedByVisitor(source), (ClassScope) null);
+ out.receiver = HandleBuilder.generateBuildReceiver(job);
+ createRelevantNonNullAnnotation(job.builderType, out);
+ out.traverse(new SetGeneratedByVisitor(job.source), (ClassScope) null);
return out;
}
- private MethodDeclaration generateCleanMethod(List<BuilderFieldData> builderFields, EclipseNode builderType, ASTNode source) {
+ private MethodDeclaration generateCleanMethod(BuilderJob job) {
List<Statement> statements = new ArrayList<Statement>();
- for (BuilderFieldData bfd : builderFields) {
+ for (BuilderFieldData bfd : job.builderFields) {
if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) {
- bfd.singularData.getSingularizer().appendCleaningCode(bfd.singularData, builderType, statements);
+ bfd.singularData.getSingularizer().appendCleaningCode(bfd.singularData, job.builderType, statements);
}
}
FieldReference thisUnclean = new FieldReference(CLEAN_FIELD_NAME, 0);
thisUnclean.receiver = new ThisReference(0, 0);
statements.add(new Assignment(thisUnclean, new FalseLiteral(0, 0), 0));
- MethodDeclaration decl = new MethodDeclaration(((CompilationUnitDeclaration) builderType.top().get()).compilationResult);
+ MethodDeclaration decl = job.createNewMethodDeclaration();
+ //new MethodDeclaration(((CompilationUnitDeclaration) builderType.top().get()).compilationResult);
decl.selector = CLEAN_METHOD_NAME;
decl.modifiers = ClassFileConstants.AccPrivate;
decl.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
decl.returnType = TypeReference.baseTypeReference(TypeIds.T_void, 0);
decl.statements = statements.toArray(new Statement[0]);
- decl.traverse(new SetGeneratedByVisitor(source), (ClassScope) null);
+ decl.traverse(new SetGeneratedByVisitor(job.source), (ClassScope) null);
return decl;
}
- private void generateBuilderFields(EclipseNode builderType, List<BuilderFieldData> builderFields, ASTNode source) {
+ private void generateBuilderFields(BuilderJob job) {
List<EclipseNode> existing = new ArrayList<EclipseNode>();
- for (EclipseNode child : builderType.down()) {
+ for (EclipseNode child : job.builderType.down()) {
if (child.getKind() == Kind.FIELD) existing.add(child);
}
- for (BuilderFieldData bfd : builderFields) {
+ for (BuilderFieldData bfd : job.builderFields) {
if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) {
- bfd.createdFields.addAll(bfd.singularData.getSingularizer().generateFields(bfd.singularData, builderType));
+ bfd.createdFields.addAll(bfd.singularData.getSingularizer().generateFields(bfd.singularData, job.builderType));
} else {
EclipseNode field = null, setFlag = null;
for (EclipseNode exists : existing) {
@@ -909,23 +942,23 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
fd.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG;
fd.modifiers = ClassFileConstants.AccPrivate;
fd.type = copyType(bfd.type);
- fd.traverse(new SetGeneratedByVisitor(source), (MethodScope) null);
- field = injectFieldAndMarkGenerated(builderType, fd);
+ fd.traverse(new SetGeneratedByVisitor(job.source), (MethodScope) null);
+ field = injectFieldAndMarkGenerated(job.builderType, fd);
}
if (setFlag == null && bfd.nameOfSetFlag != null) {
FieldDeclaration fd = new FieldDeclaration(bfd.nameOfSetFlag, 0, 0);
fd.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG;
fd.modifiers = ClassFileConstants.AccPrivate;
fd.type = TypeReference.baseTypeReference(TypeIds.T_boolean, 0);
- fd.traverse(new SetGeneratedByVisitor(source), (MethodScope) null);
- injectFieldAndMarkGenerated(builderType, fd);
+ fd.traverse(new SetGeneratedByVisitor(job.source), (MethodScope) null);
+ injectFieldAndMarkGenerated(job.builderType, fd);
}
bfd.createdFields.add(field);
}
}
}
- private void generateSetterMethodsForBuilder(CheckerFrameworkVersion cfv, EclipseNode builderType, BuilderFieldData bfd, EclipseNode sourceNode, final String builderGenericName, String setterPrefix) {
+ private void generateSetterMethodsForBuilder(BuilderJob job, BuilderFieldData bfd, final String builderGenericName, String setterPrefix) {
boolean deprecate = isFieldDeprecated(bfd.originalFieldNode);
TypeReferenceMaker returnTypeMaker = new TypeReferenceMaker() {
@@ -944,15 +977,14 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
};
if (bfd.singularData == null || bfd.singularData.getSingularizer() == null) {
- generateSimpleSetterMethodForBuilder(cfv, builderType, deprecate, bfd.createdFields.get(0), bfd.name, bfd.nameOfSetFlag, returnTypeMaker.make(), returnStatementMaker.make(), sourceNode, bfd.annotations, bfd.originalFieldNode, setterPrefix);
+ generateSimpleSetterMethodForBuilder(job, deprecate, bfd.createdFields.get(0), bfd.name, bfd.nameOfSetFlag, returnTypeMaker.make(), returnStatementMaker.make(), bfd.annotations, bfd.originalFieldNode, setterPrefix);
} else {
- bfd.singularData.getSingularizer().generateMethods(cfv, bfd.singularData, deprecate, builderType, true, returnTypeMaker, returnStatementMaker, AccessLevel.PUBLIC);
+ bfd.singularData.getSingularizer().generateMethods(job.checkerFramework, bfd.singularData, deprecate, job.builderType, true, returnTypeMaker, returnStatementMaker, AccessLevel.PUBLIC);
}
}
-
- private void generateSimpleSetterMethodForBuilder(CheckerFrameworkVersion cfv, EclipseNode builderType, boolean deprecate, EclipseNode fieldNode, char[] paramName, char[] nameOfSetFlag, TypeReference returnType, Statement returnStatement, EclipseNode sourceNode, Annotation[] annosOnParam, EclipseNode originalFieldNode, String setterPrefix) {
- TypeDeclaration td = (TypeDeclaration) builderType.get();
- ASTNode source = sourceNode.get();
+
+ private void generateSimpleSetterMethodForBuilder(BuilderJob job, boolean deprecate, EclipseNode fieldNode, char[] paramName, char[] nameOfSetFlag, TypeReference returnType, Statement returnStatement, Annotation[] annosOnParam, EclipseNode originalFieldNode, String setterPrefix) {
+ TypeDeclaration td = (TypeDeclaration) job.builderType.get();
AbstractMethodDeclaration[] existing = td.methods;
if (existing == null) existing = EMPTY_METHODS;
int len = existing.length;
@@ -966,23 +998,14 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
}
List<Annotation> methodAnnsList = Arrays.asList(EclipseHandlerUtil.findCopyableToSetterAnnotations(originalFieldNode));
- if (cfv.generateReturnsReceiver()) {
+ if (job.checkerFramework.generateReturnsReceiver()) {
methodAnnsList = new ArrayList<Annotation>(methodAnnsList);
- methodAnnsList.add(generateNamedAnnotation(source, CheckerFrameworkVersion.NAME__RETURNS_RECEIVER));
+ methodAnnsList.add(generateNamedAnnotation(job.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(source, annosOnParam)) : Collections.<Annotation>emptyList());
- if (cfv.generateCalledMethods()) {
- 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);
-
- QualifiedTypeReference typeReference = (QualifiedTypeReference) generateTypeReference(builderType, 0);
- typeReference.annotations = new Annotation[typeReference.tokens.length][];
- typeReference.annotations[0] = new Annotation[] {ann};
- setter.receiver = new Receiver(new char[] { 't', 'h', 'i', 's' }, 0, typeReference, null, Modifier.FINAL);
- }
- injectMethod(builderType, setter);
+ job.sourceNode, methodAnnsList, annosOnParam != null ? Arrays.asList(copyAnnotations(job.source, annosOnParam)) : Collections.<Annotation>emptyList());
+ if (job.checkerFramework.generateCalledMethods()) setter.receiver = generateNotCalledReceiver(job, setterName);
+ injectMethod(job.builderType, setter);
}
private void addObtainVia(BuilderFieldData bfd, EclipseNode node) {
diff --git a/src/core/lombok/javac/handlers/HandleBuilder.java b/src/core/lombok/javac/handlers/HandleBuilder.java
index 7e87ce11..1c74ce37 100644
--- a/src/core/lombok/javac/handlers/HandleBuilder.java
+++ b/src/core/lombok/javac/handlers/HandleBuilder.java
@@ -55,6 +55,7 @@ import com.sun.tools.javac.tree.JCTree.JCStatement;
import com.sun.tools.javac.tree.JCTree.JCTypeApply;
import com.sun.tools.javac.tree.JCTree.JCTypeParameter;
import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
+import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.ListBuffer;
import com.sun.tools.javac.util.Name;
@@ -88,12 +89,96 @@ import lombok.javac.handlers.JavacSingularsRecipes.SingularData;
public class HandleBuilder extends JavacAnnotationHandler<Builder> {
private HandleConstructor handleConstructor = new HandleConstructor();
+ static final String CLEAN_FIELD_NAME = "$lombokUnclean";
+ static final String CLEAN_METHOD_NAME = "$lombokClean";
+ static final String TO_BUILDER_METHOD_NAME = "toBuilder";
+ static final String DEFAULT_PREFIX = "$default$";
+ static final String SET_PREFIX = "$set";
+ static final String VALUE_PREFIX = "$value";
+ static final String BUILDER_TEMP_VAR = "builder";
+ static final String TO_BUILDER_NOT_SUPPORTED = "@Builder(toBuilder=true) is only supported if you return your own type.";
+
private static final boolean toBoolean(Object expr, boolean defaultValue) {
if (expr == null) return defaultValue;
if (expr instanceof JCLiteral) return ((Integer) ((JCLiteral) expr).value) != 0;
return ((Boolean) expr).booleanValue();
}
+ static class BuilderJob {
+ CheckerFrameworkVersion checkerFramework;
+ JavacNode parentType;
+ String builderMethodName, buildMethodName;
+ boolean isStatic;
+ List<JCTypeParameter> typeParams;
+ List<JCTypeParameter> builderTypeParams;
+ JCTree source;
+ JavacNode sourceNode;
+ java.util.List<BuilderFieldData> builderFields;
+ AccessLevel accessInners, accessOuters;
+ boolean oldFluent, oldChain, toBuilder;
+
+ JavacNode builderType;
+ String builderClassName;
+
+ void init(AnnotationValues<Builder> annValues, Builder ann, JavacNode node) {
+ accessOuters = ann.access();
+ if (accessOuters == null) accessOuters = AccessLevel.PUBLIC;
+ if (accessOuters == AccessLevel.NONE) {
+ sourceNode.addError("AccessLevel.NONE is not valid here");
+ accessOuters = AccessLevel.PUBLIC;
+ }
+ accessInners = accessOuters == AccessLevel.PROTECTED ? AccessLevel.PUBLIC : accessOuters;
+
+ oldFluent = toBoolean(annValues.getActualExpression("fluent"), true);
+ oldChain = toBoolean(annValues.getActualExpression("chain"), true);
+
+ builderMethodName = ann.builderMethodName();
+ buildMethodName = ann.buildMethodName();
+ builderClassName = fixBuilderClassName(node, ann.builderClassName());
+ toBuilder = ann.toBuilder();
+
+ if (builderMethodName == null) builderMethodName = "builder";
+ if (buildMethodName == null) buildMethodName = "build";
+ if (builderClassName == null) builderClassName = "";
+ }
+
+ static String fixBuilderClassName(JavacNode node, String override) {
+ if (override != null && !override.isEmpty()) return override;
+ override = node.getAst().readConfiguration(ConfigurationKeys.BUILDER_CLASS_NAME);
+ if (override != null && !override.isEmpty()) return override;
+ return "*Builder";
+ }
+
+ String replaceBuilderClassName(Name name) {
+ if (builderClassName.indexOf('*') == -1) return builderClassName;
+ return builderClassName.replace("*", name.toString());
+ }
+
+ JCExpression createBuilderParentTypeReference() {
+ return namePlusTypeParamsToTypeReference(parentType.getTreeMaker(), parentType, typeParams);
+ }
+
+ Name getBuilderClassName() {
+ return parentType.toName(builderClassName);
+ }
+
+ List<JCTypeParameter> copyTypeParams() {
+ return JavacHandlerUtil.copyTypeParams(sourceNode, typeParams);
+ }
+
+ Name toName(String name) {
+ return parentType.toName(name);
+ }
+
+ Context getContext() {
+ return parentType.getContext();
+ }
+
+ JavacTreeMaker getTreeMaker() {
+ return parentType.getTreeMaker();
+ }
+ }
+
static class BuilderFieldData {
List<JCAnnotation> annotations;
JCExpression type;
@@ -112,73 +197,49 @@ 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();
- if (accessForOuters == null) accessForOuters = AccessLevel.PUBLIC;
- if (accessForOuters == AccessLevel.NONE) {
- annotationNode.addError("AccessLevel.NONE is not valid here");
- accessForOuters = AccessLevel.PUBLIC;
- }
- AccessLevel accessForInners = accessForOuters == AccessLevel.PROTECTED ? AccessLevel.PUBLIC : accessForOuters;
-
- // These exist just to support the 'old' lombok.experimental.Builder, which had these properties. lombok.Builder no longer has them.
- boolean fluent = toBoolean(annotation.getActualExpression("fluent"), true);
- boolean chain = toBoolean(annotation.getActualExpression("chain"), true);
-
- String builderMethodName = builderInstance.builderMethodName();
- String buildMethodName = builderInstance.buildMethodName();
- String builderClassName = builderInstance.builderClassName();
- String toBuilderMethodName = "toBuilder";
- boolean toBuilder = builderInstance.toBuilder();
+ BuilderJob job = new BuilderJob();
+ job.sourceNode = annotationNode;
+ job.source = ast;
+ job.checkerFramework = getCheckerFrameworkVersion(annotationNode);
+ job.isStatic = true;
+
+ Builder annInstance = annotation.getInstance();
+ job.init(annotation, annInstance, annotationNode);
java.util.List<Name> typeArgsForToBuilder = null;
- if (builderMethodName == null) builderMethodName = "builder";
- if (buildMethodName == null) buildMethodName = "build";
- if (builderClassName == null) builderClassName = "";
-
boolean generateBuilderMethod;
- if (builderMethodName.isEmpty()) {
+ if (job.builderMethodName.isEmpty()) {
generateBuilderMethod = false;
- } else if (!checkName("builderMethodName", builderMethodName, annotationNode)) {
+ } else if (!checkName("builderMethodName", job.builderMethodName, annotationNode)) {
return;
} else {
generateBuilderMethod = true;
}
- if (!checkName("buildMethodName", buildMethodName, annotationNode)) return;
- if (!builderClassName.isEmpty()) {
- if (!checkName("builderClassName", builderClassName, annotationNode)) return;
- }
+ if (!checkName("buildMethodName", job.buildMethodName, annotationNode)) return;
- // Do not delete the Builder annotation here, we need it for @Jacksonized.
+ // Do not delete the Builder annotation yet, we need it for @Jacksonized.
JavacNode parent = annotationNode.up();
- java.util.List<BuilderFieldData> builderFields = new ArrayList<BuilderFieldData>();
- JCExpression returnType;
- List<JCTypeParameter> typeParams = List.nil();
- List<JCExpression> thrownExceptions = List.nil();
+ job.builderFields = new ArrayList<BuilderFieldData>();
+ JCExpression buildMethodReturnType;
+ job.typeParams = List.nil();
+ List<JCExpression> buildMethodThrownExceptions;
Name nameOfBuilderMethod;
- JavacNode tdParent;
JavacNode fillParametersFrom = parent.get() instanceof JCMethodDecl ? parent : null;
boolean addCleaning = false;
- boolean isStatic = true;
ArrayList<JavacNode> nonFinalNonDefaultedFields = null;
- if (builderClassName.isEmpty()) builderClassName = annotationNode.getAst().readConfiguration(ConfigurationKeys.BUILDER_CLASS_NAME);
- if (builderClassName == null || builderClassName.isEmpty()) builderClassName = "*Builder";
- boolean replaceNameInBuilderClassName = builderClassName.contains("*");
-
if (parent.get() instanceof JCClassDecl) {
- tdParent = parent;
- JCClassDecl td = (JCClassDecl) tdParent.get();
+ job.parentType = parent;
+ JCClassDecl td = (JCClassDecl) parent.get();
+
ListBuffer<JavacNode> allFields = new ListBuffer<JavacNode>();
boolean valuePresent = (hasAnnotation(lombok.Value.class, parent) || hasAnnotation("lombok.experimental.Value", parent));
- for (JavacNode fieldNode : HandleConstructor.findAllFields(tdParent, true)) {
+ for (JavacNode fieldNode : HandleConstructor.findAllFields(parent, true)) {
JCVariableDecl fd = (JCVariableDecl) fieldNode.get();
JavacNode isDefault = findAnnotation(Builder.Default.class, fieldNode, false);
boolean isFinal = (fd.mods.flags & Flags.FINAL) != 0 || (valuePresent && !hasAnnotation(NonFinal.class, fieldNode));
@@ -189,7 +250,7 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
bfd.builderFieldName = bfd.name;
bfd.annotations = findCopyableAnnotations(fieldNode);
bfd.type = fd.vartype;
- bfd.singularData = getSingularData(fieldNode, builderInstance.setterPrefix());
+ bfd.singularData = getSingularData(fieldNode, annInstance.setterPrefix());
bfd.originalFieldNode = fieldNode;
if (bfd.singularData != null && isDefault != null) {
@@ -211,26 +272,26 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
}
if (isDefault != null) {
- bfd.nameOfDefaultProvider = parent.toName("$default$" + bfd.name);
- bfd.nameOfSetFlag = parent.toName(bfd.name + "$set");
- bfd.builderFieldName = parent.toName(bfd.name + "$value");
+ bfd.nameOfDefaultProvider = parent.toName(DEFAULT_PREFIX + bfd.name);
+ bfd.nameOfSetFlag = parent.toName(bfd.name + SET_PREFIX);
+ bfd.builderFieldName = parent.toName(bfd.name + VALUE_PREFIX);
JCMethodDecl md = generateDefaultProvider(bfd.nameOfDefaultProvider, fieldNode, td.typarams);
recursiveSetGeneratedBy(md, ast, annotationNode.getContext());
- if (md != null) injectMethod(tdParent, md);
+ if (md != null) injectMethod(parent, md);
}
addObtainVia(bfd, fieldNode);
- builderFields.add(bfd);
+ job.builderFields.add(bfd);
allFields.append(fieldNode);
}
- handleConstructor.generateConstructor(tdParent, AccessLevel.PACKAGE, List.<JCAnnotation>nil(), allFields.toList(), false, null, SkipIfConstructorExists.I_AM_BUILDER, annotationNode);
+ handleConstructor.generateConstructor(parent, AccessLevel.PACKAGE, List.<JCAnnotation>nil(), allFields.toList(), false, null, SkipIfConstructorExists.I_AM_BUILDER, annotationNode);
- returnType = namePlusTypeParamsToTypeReference(tdParent.getTreeMaker(), tdParent, td.typarams);
- typeParams = td.typarams;
- thrownExceptions = List.nil();
+ buildMethodReturnType = namePlusTypeParamsToTypeReference(parent.getTreeMaker(), parent, td.typarams);
+ job.typeParams = job.builderTypeParams = td.typarams;
+ buildMethodThrownExceptions = List.nil();
nameOfBuilderMethod = null;
- if (replaceNameInBuilderClassName) builderClassName = builderClassName.replace("*", td.name.toString());
- replaceNameInBuilderClassName = false;
+ job.builderClassName = job.replaceBuilderClassName(td.name);
+ if (!checkName("builderClassName", job.builderClassName, annotationNode)) return;
} else if (fillParametersFrom != null && fillParametersFrom.getName().toString().equals("<init>")) {
JCMethodDecl jmd = (JCMethodDecl) fillParametersFrom.get();
if (!jmd.typarams.isEmpty()) {
@@ -238,38 +299,35 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
return;
}
- tdParent = parent.up();
- JCClassDecl td = (JCClassDecl) tdParent.get();
- returnType = namePlusTypeParamsToTypeReference(tdParent.getTreeMaker(), tdParent, td.typarams);
- typeParams = td.typarams;
- thrownExceptions = jmd.thrown;
+ job.parentType = parent.up();
+ JCClassDecl td = (JCClassDecl) job.parentType.get();
+ job.typeParams = job.builderTypeParams = td.typarams;
+ buildMethodReturnType = job.createBuilderParentTypeReference();
+ buildMethodThrownExceptions = jmd.thrown;
nameOfBuilderMethod = null;
- if (replaceNameInBuilderClassName) builderClassName = builderClassName.replace("*", td.name.toString());
- replaceNameInBuilderClassName = false;
+ job.builderClassName = job.replaceBuilderClassName(td.name);
+ if (!checkName("builderClassName", job.builderClassName, annotationNode)) return;
} else if (fillParametersFrom != null) {
- tdParent = parent.up();
- JCClassDecl td = (JCClassDecl) tdParent.get();
+ job.parentType = parent.up();
+ JCClassDecl td = (JCClassDecl) job.parentType.get();
JCMethodDecl jmd = (JCMethodDecl) fillParametersFrom.get();
- isStatic = (jmd.mods.flags & Flags.STATIC) != 0;
+ job.isStatic = (jmd.mods.flags & Flags.STATIC) != 0;
+
JCExpression fullReturnType = jmd.restype;
- returnType = fullReturnType;
- typeParams = jmd.typarams;
- thrownExceptions = jmd.thrown;
+ buildMethodReturnType = fullReturnType;
+ job.typeParams = job.builderTypeParams = jmd.typarams;
+ buildMethodThrownExceptions = jmd.thrown;
nameOfBuilderMethod = jmd.name;
- if (returnType instanceof JCTypeApply) {
- returnType = cloneType(tdParent.getTreeMaker(), returnType, ast, annotationNode.getContext());
+ if (buildMethodReturnType instanceof JCTypeApply) {
+ buildMethodReturnType = cloneType(job.getTreeMaker(), buildMethodReturnType, ast, annotationNode.getContext());
}
- if (replaceNameInBuilderClassName) {
- String replStr = returnTypeToBuilderClassName(annotationNode, td, returnType, typeParams);
- if (replStr == null)
- return;
- builderClassName = builderClassName.replace("*", replStr);
- replaceNameInBuilderClassName = false;
+ if (job.builderClassName.indexOf('*') > -1) {
+ String replStr = returnTypeToBuilderClassName(annotationNode, td, buildMethodReturnType, job.typeParams);
+ if (replStr == null) return; // shuold not happen
+ job.builderClassName = job.builderClassName.replace("*", replStr);
}
- if (replaceNameInBuilderClassName) builderClassName = builderClassName.replace("*", td.name.toString());
- if (toBuilder) {
- final String TO_BUILDER_NOT_SUPPORTED = "@Builder(toBuilder=true) is only supported if you return your own type.";
- if (returnType instanceof JCArrayTypeTree) {
+ if (job.toBuilder) {
+ if (fullReturnType instanceof JCArrayTypeTree) {
annotationNode.addError(TO_BUILDER_NOT_SUPPORTED);
return;
}
@@ -282,8 +340,8 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
tpOnRet = ((JCTypeApply) fullReturnType).arguments;
}
- JCExpression namingType = returnType;
- if (returnType instanceof JCTypeApply) namingType = ((JCTypeApply) returnType).clazz;
+ JCExpression namingType = fullReturnType;
+ if (buildMethodReturnType instanceof JCTypeApply) namingType = ((JCTypeApply) buildMethodReturnType).clazz;
if (namingType instanceof JCIdent) {
simpleName = ((JCIdent) namingType).name;
@@ -307,13 +365,13 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
return;
}
- if (!tdParent.getName().contentEquals(simpleName)) {
+ if (!job.parentType.getName().contentEquals(simpleName)) {
annotationNode.addError(TO_BUILDER_NOT_SUPPORTED);
return;
}
List<JCTypeParameter> tpOnMethod = jmd.typarams;
- List<JCTypeParameter> tpOnType = ((JCClassDecl) tdParent.get()).typarams;
+ List<JCTypeParameter> tpOnType = ((JCClassDecl) job.builderType.get()).typarams;
typeArgsForToBuilder = new ArrayList<Name>();
for (JCTypeParameter tp : tpOnMethod) {
@@ -349,41 +407,41 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
bfd.rawName = raw.name;
bfd.annotations = findCopyableAnnotations(param);
bfd.type = raw.vartype;
- bfd.singularData = getSingularData(param, builderInstance.setterPrefix());
+ bfd.singularData = getSingularData(param, annInstance.setterPrefix());
bfd.originalFieldNode = param;
addObtainVia(bfd, param);
- builderFields.add(bfd);
+ job.builderFields.add(bfd);
}
}
- JavacNode builderType = findInnerClass(tdParent, builderClassName);
- if (builderType == null) {
- builderType = makeBuilderClass(isStatic, annotationNode, tdParent, builderClassName, typeParams, ast, accessForOuters);
- recursiveSetGeneratedBy(builderType.get(), ast, annotationNode.getContext());
+ job.builderType = findInnerClass(job.parentType, job.builderClassName);
+ if (job.builderType == null) {
+ job.builderType = makeBuilderClass(job);
+ recursiveSetGeneratedBy(job.builderType.get(), ast, annotationNode.getContext());
} else {
- JCClassDecl builderTypeDeclaration = (JCClassDecl) builderType.get();
- if (isStatic && !builderTypeDeclaration.getModifiers().getFlags().contains(Modifier.STATIC)) {
+ JCClassDecl builderTypeDeclaration = (JCClassDecl) job.builderType.get();
+ if (job.isStatic && !builderTypeDeclaration.getModifiers().getFlags().contains(Modifier.STATIC)) {
annotationNode.addError("Existing Builder must be a static inner class.");
return;
- } else if (!isStatic && builderTypeDeclaration.getModifiers().getFlags().contains(Modifier.STATIC)) {
+ } else if (!job.isStatic && builderTypeDeclaration.getModifiers().getFlags().contains(Modifier.STATIC)) {
annotationNode.addError("Existing Builder must be a non-static inner class.");
return;
}
- sanityCheckForMethodGeneratingAnnotationsOnBuilderClass(builderType, annotationNode);
+ sanityCheckForMethodGeneratingAnnotationsOnBuilderClass(job.builderType, annotationNode);
/* generate errors for @Singular BFDs that have one already defined node. */ {
- for (BuilderFieldData bfd : builderFields) {
+ for (BuilderFieldData bfd : job.builderFields) {
SingularData sd = bfd.singularData;
if (sd == null) continue;
JavacSingularizer singularizer = sd.getSingularizer();
if (singularizer == null) continue;
- if (singularizer.checkForAlreadyExistingNodesAndGenerateError(builderType, sd)) {
+ if (singularizer.checkForAlreadyExistingNodesAndGenerateError(job.builderType, sd)) {
bfd.singularData = null;
}
}
}
}
- for (BuilderFieldData bfd : builderFields) {
+ for (BuilderFieldData bfd : job.builderFields) {
if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) {
if (bfd.singularData.getSingularizer().requiresCleaning()) {
addCleaning = true;
@@ -402,75 +460,75 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
}
}
- generateBuilderFields(builderType, builderFields, ast);
+ generateBuilderFields(job);
if (addCleaning) {
- JavacTreeMaker maker = builderType.getTreeMaker();
- JCVariableDecl uncleanField = maker.VarDef(maker.Modifiers(Flags.PRIVATE), builderType.toName("$lombokUnclean"), maker.TypeIdent(CTC_BOOLEAN), null);
- injectFieldAndMarkGenerated(builderType, uncleanField);
+ JavacTreeMaker maker = job.getTreeMaker();
+ JCVariableDecl uncleanField = maker.VarDef(maker.Modifiers(Flags.PRIVATE), job.builderType.toName(CLEAN_FIELD_NAME), maker.TypeIdent(CTC_BOOLEAN), null);
+ injectFieldAndMarkGenerated(job.builderType, uncleanField);
recursiveSetGeneratedBy(uncleanField, ast, annotationNode.getContext());
}
- if (constructorExists(builderType) == MemberExistsResult.NOT_EXISTS) {
- JCMethodDecl cd = HandleConstructor.createConstructor(AccessLevel.PACKAGE, List.<JCAnnotation>nil(), builderType, List.<JavacNode>nil(), false, annotationNode);
- if (cd != null) injectMethod(builderType, cd);
+ if (constructorExists(job.builderType) == MemberExistsResult.NOT_EXISTS) {
+ JCMethodDecl cd = HandleConstructor.createConstructor(AccessLevel.PACKAGE, List.<JCAnnotation>nil(), job.builderType, List.<JavacNode>nil(), false, annotationNode);
+ if (cd != null) injectMethod(job.builderType, cd);
}
- for (BuilderFieldData bfd : builderFields) {
- makePrefixedSetterMethodsForBuilder(cfv, builderType, bfd, annotationNode, fluent, chain, accessForInners, builderInstance.setterPrefix());
+ for (BuilderFieldData bfd : job.builderFields) {
+ makePrefixedSetterMethodsForBuilder(job, bfd, annInstance.setterPrefix());
}
{
- MemberExistsResult methodExists = methodExists(buildMethodName, builderType, -1);
- if (methodExists == MemberExistsResult.EXISTS_BY_LOMBOK) methodExists = methodExists(buildMethodName, builderType, 0);
+ MemberExistsResult methodExists = methodExists(job.buildMethodName, job.builderType, -1);
+ if (methodExists == MemberExistsResult.EXISTS_BY_LOMBOK) methodExists = methodExists(job.buildMethodName, job.builderType, 0);
if (methodExists == MemberExistsResult.NOT_EXISTS) {
- JCMethodDecl md = generateBuildMethod(cfv, tdParent, isStatic, buildMethodName, nameOfBuilderMethod, returnType, builderFields, builderType, thrownExceptions, ast, addCleaning, accessForInners);
+ JCMethodDecl md = generateBuildMethod(job, nameOfBuilderMethod, buildMethodReturnType, buildMethodThrownExceptions, addCleaning);
if (md != null) {
- injectMethod(builderType, md);
+ injectMethod(job.builderType, md);
recursiveSetGeneratedBy(md, ast, annotationNode.getContext());
}
}
}
- if (methodExists("toString", builderType, 0) == MemberExistsResult.NOT_EXISTS) {
+ if (methodExists("toString", job.builderType, 0) == MemberExistsResult.NOT_EXISTS) {
java.util.List<Included<JavacNode, ToString.Include>> fieldNodes = new ArrayList<Included<JavacNode, ToString.Include>>();
- for (BuilderFieldData bfd : builderFields) {
+ for (BuilderFieldData bfd : job.builderFields) {
for (JavacNode f : bfd.createdFields) {
fieldNodes.add(new Included<JavacNode, ToString.Include>(f, null, true, false));
}
}
- JCMethodDecl md = HandleToString.createToString(builderType, fieldNodes, true, false, FieldAccess.ALWAYS_FIELD, ast);
- if (md != null) injectMethod(builderType, md);
+ JCMethodDecl md = HandleToString.createToString(job.builderType, fieldNodes, true, false, FieldAccess.ALWAYS_FIELD, ast);
+ if (md != null) injectMethod(job.builderType, md);
}
- if (addCleaning) injectMethod(builderType, generateCleanMethod(builderFields, builderType, ast));
+ if (addCleaning) injectMethod(job.builderType, generateCleanMethod(job));
- if (generateBuilderMethod && methodExists(builderMethodName, tdParent, -1) != MemberExistsResult.NOT_EXISTS) generateBuilderMethod = false;
+ if (generateBuilderMethod && methodExists(job.builderMethodName, job.parentType, -1) != MemberExistsResult.NOT_EXISTS) generateBuilderMethod = false;
if (generateBuilderMethod) {
- JCMethodDecl md = generateBuilderMethod(cfv, isStatic, builderMethodName, builderClassName, annotationNode, tdParent, typeParams, accessForOuters);
+ JCMethodDecl md = generateBuilderMethod(job);
recursiveSetGeneratedBy(md, ast, annotationNode.getContext());
- if (md != null) injectMethod(tdParent, md);
+ if (md != null) injectMethod(job.parentType, md);
}
- if (toBuilder) {
- switch (methodExists(toBuilderMethodName, tdParent, 0)) {
+ if (job.toBuilder) {
+ switch (methodExists(TO_BUILDER_METHOD_NAME, job.parentType, 0)) {
case EXISTS_BY_USER:
annotationNode.addWarning("Not generating toBuilder() as it already exists.");
return;
case NOT_EXISTS:
- List<JCTypeParameter> tps = typeParams;
+ List<JCTypeParameter> tps = job.typeParams;
if (typeArgsForToBuilder != null) {
ListBuffer<JCTypeParameter> lb = new ListBuffer<JCTypeParameter>();
- JavacTreeMaker maker = tdParent.getTreeMaker();
+ JavacTreeMaker maker = job.getTreeMaker();
for (Name n : typeArgsForToBuilder) {
lb.append(maker.TypeParameter(n, List.<JCExpression>nil()));
}
tps = lb.toList();
}
- JCMethodDecl md = generateToBuilderMethod(cfv, toBuilderMethodName, builderClassName, tdParent, isStatic, tps, builderFields, fluent, ast, accessForOuters, builderInstance.setterPrefix());
+ JCMethodDecl md = generateToBuilderMethod(job, tps, annInstance.setterPrefix());
if (md != null) {
recursiveSetGeneratedBy(md, ast, annotationNode.getContext());
- injectMethod(tdParent, md);
+ injectMethod(job.parentType, md);
}
}
}
@@ -551,47 +609,45 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
sb.append("__ERR__");
}
- private static final String BUILDER_TEMP_VAR = "builder";
- private JCMethodDecl generateToBuilderMethod(CheckerFrameworkVersion cfv, String toBuilderMethodName, String builderClassName, JavacNode type, boolean isStatic, List<JCTypeParameter> typeParams, java.util.List<BuilderFieldData> builderFields, boolean fluent, JCAnnotation ast, AccessLevel access, String prefix) {
+ private JCMethodDecl generateToBuilderMethod(BuilderJob job, List<JCTypeParameter> typeParameters, String prefix) {
// return new ThingieBuilder<A, B>().setA(this.a).setB(this.b);
- JavacTreeMaker maker = type.getTreeMaker();
-
+ JavacTreeMaker maker = job.getTreeMaker();
ListBuffer<JCExpression> typeArgs = new ListBuffer<JCExpression>();
- for (JCTypeParameter typeParam : typeParams) {
+ for (JCTypeParameter typeParam : typeParameters) {
typeArgs.append(maker.Ident(typeParam.name));
}
- JCExpression call = maker.NewClass(null, List.<JCExpression>nil(), namePlusTypeParamsToTypeReference(maker, type, type.toName(builderClassName), !isStatic, typeParams), List.<JCExpression>nil(), null);
+ JCExpression call = maker.NewClass(null, List.<JCExpression>nil(), namePlusTypeParamsToTypeReference(maker, job.parentType, job.toName(job.builderClassName), !job.isStatic, job.builderTypeParams), List.<JCExpression>nil(), null);
JCExpression invoke = call;
ListBuffer<JCStatement> preStatements = null;
ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>();
- for (BuilderFieldData bfd : builderFields) {
- String setterPrefix = !prefix.isEmpty() ? prefix : fluent ? "" : "set";
+ for (BuilderFieldData bfd : job.builderFields) {
+ String setterPrefix = !prefix.isEmpty() ? prefix : job.oldFluent ? "" : "set";
String prefixedSetterName = bfd.name.toString();
if (!setterPrefix.isEmpty()) prefixedSetterName = HandlerUtil.buildAccessorName(setterPrefix, prefixedSetterName);
- Name setterName = type.toName(prefixedSetterName);
+ Name setterName = job.toName(prefixedSetterName);
JCExpression[] tgt = new JCExpression[bfd.singularData == null ? 1 : 2];
if (bfd.obtainVia == null || !bfd.obtainVia.field().isEmpty()) {
for (int i = 0; i < tgt.length; i++) {
- tgt[i] = maker.Select(maker.Ident(type.toName("this")), bfd.obtainVia == null ? bfd.rawName : type.toName(bfd.obtainVia.field()));
+ tgt[i] = maker.Select(maker.Ident(job.toName("this")), bfd.obtainVia == null ? bfd.rawName : job.toName(bfd.obtainVia.field()));
}
} else {
String name = bfd.obtainVia.method();
JCMethodInvocation inv;
if (bfd.obtainVia.isStatic()) {
- JCExpression c = maker.Select(maker.Ident(type.toName(type.getName())), type.toName(name));
- inv = maker.Apply(typeParameterNames(maker, typeParams), c, List.<JCExpression>of(maker.Ident(type.toName("this"))));
+ JCExpression c = maker.Select(maker.Ident(job.toName(job.parentType.getName())), job.toName(name));
+ inv = maker.Apply(typeParameterNames(maker, typeParameters), c, List.<JCExpression>of(maker.Ident(job.toName("this"))));
} else {
- JCExpression c = maker.Select(maker.Ident(type.toName("this")), type.toName(name));
+ JCExpression c = maker.Select(maker.Ident(job.toName("this")), job.toName(name));
inv = maker.Apply(List.<JCExpression>nil(), c, List.<JCExpression>nil());
}
for (int i = 0; i < tgt.length; i++) tgt[i] = maker.Ident(bfd.name);
// javac appears to cache the type of JCMethodInvocation expressions based on position, meaning, if you have 2 ObtainVia-based method invokes on different types, you get bizarre type mismatch errors.
// going via a local variable declaration solves the problem.
- JCExpression varType = JavacHandlerUtil.cloneType(maker, bfd.type, ast, type.getContext());
+ JCExpression varType = JavacHandlerUtil.cloneType(maker, bfd.type, job.source, job.getContext());
if (preStatements == null) preStatements = new ListBuffer<JCStatement>();
preStatements.append(maker.VarDef(maker.Modifiers(Flags.FINAL), bfd.name, varType, inv));
}
@@ -602,15 +658,15 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
invoke = maker.Apply(List.<JCExpression>nil(), maker.Select(invoke, setterName), List.of(arg));
} else {
JCExpression isNotNull = maker.Binary(CTC_NOT_EQUAL, tgt[0], maker.Literal(CTC_BOT, null));
- JCExpression invokeBuilder = maker.Apply(List.<JCExpression>nil(), maker.Select(maker.Ident(type.toName(BUILDER_TEMP_VAR)), setterName), List.<JCExpression>of(tgt[1]));
+ JCExpression invokeBuilder = maker.Apply(List.<JCExpression>nil(), maker.Select(maker.Ident(job.toName(BUILDER_TEMP_VAR)), setterName), List.<JCExpression>of(tgt[1]));
statements.append(maker.If(isNotNull, maker.Exec(invokeBuilder), null));
}
}
if (!statements.isEmpty()) {
- JCExpression tempVarType = namePlusTypeParamsToTypeReference(maker, type, type.toName(builderClassName), !isStatic, typeParams);
- statements.prepend(maker.VarDef(maker.Modifiers(Flags.FINAL), type.toName(BUILDER_TEMP_VAR), tempVarType, invoke));
- statements.append(maker.Return(maker.Ident(type.toName(BUILDER_TEMP_VAR))));
+ JCExpression tempVarType = namePlusTypeParamsToTypeReference(maker, job.parentType, job.getBuilderClassName(), !job.isStatic, typeParameters);
+ statements.prepend(maker.VarDef(maker.Modifiers(Flags.FINAL), job.toName(BUILDER_TEMP_VAR), tempVarType, invoke));
+ statements.append(maker.Return(maker.Ident(job.toName(BUILDER_TEMP_VAR))));
} else {
statements.append(maker.Return(invoke));
}
@@ -620,77 +676,78 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
statements = preStatements;
}
JCBlock body = maker.Block(0, statements.toList());
- List<JCAnnotation> annsOnMethod = cfv.generateUnique() ? List.of(maker.Annotation(genTypeRef(type, CheckerFrameworkVersion.NAME__UNIQUE), List.<JCExpression>nil())) : List.<JCAnnotation>nil();
- JCMethodDecl methodDef = maker.MethodDef(maker.Modifiers(toJavacModifier(access), annsOnMethod), type.toName(toBuilderMethodName), namePlusTypeParamsToTypeReference(maker, type, type.toName(builderClassName), !isStatic, typeParams), List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null);
- createRelevantNonNullAnnotation(type, methodDef);
+ List<JCAnnotation> annsOnParamType = List.nil();
+ if (job.checkerFramework.generateUnique()) annsOnParamType = List.of(maker.Annotation(genTypeRef(job.parentType, CheckerFrameworkVersion.NAME__UNIQUE), List.<JCExpression>nil()));
+ JCMethodDecl methodDef = maker.MethodDef(maker.Modifiers(toJavacModifier(job.accessOuters)), job.toName(TO_BUILDER_METHOD_NAME), namePlusTypeParamsToTypeReference(maker, job.parentType, job.getBuilderClassName(), !job.isStatic, typeParameters, annsOnParamType), List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null);
+ createRelevantNonNullAnnotation(job.parentType, methodDef);
return methodDef;
}
- private JCMethodDecl generateCleanMethod(java.util.List<BuilderFieldData> builderFields, JavacNode type, JCTree source) {
- JavacTreeMaker maker = type.getTreeMaker();
+ private JCMethodDecl generateCleanMethod(BuilderJob job) {
+ JavacTreeMaker maker = job.getTreeMaker();
ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>();
- for (BuilderFieldData bfd : builderFields) {
+ for (BuilderFieldData bfd : job.builderFields) {
if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) {
- bfd.singularData.getSingularizer().appendCleaningCode(bfd.singularData, type, source, statements);
+ bfd.singularData.getSingularizer().appendCleaningCode(bfd.singularData, job.builderType, job.source, statements);
}
}
- statements.append(maker.Exec(maker.Assign(maker.Select(maker.Ident(type.toName("this")), type.toName("$lombokUnclean")), maker.Literal(CTC_BOOLEAN, 0))));
+ statements.append(maker.Exec(maker.Assign(maker.Select(maker.Ident(job.toName("this")), job.toName(CLEAN_FIELD_NAME)), maker.Literal(CTC_BOOLEAN, 0))));
JCBlock body = maker.Block(0, statements.toList());
- JCMethodDecl method = maker.MethodDef(maker.Modifiers(toJavacModifier(AccessLevel.PRIVATE)), type.toName("$lombokClean"), maker.Type(Javac.createVoidType(type.getSymbolTable(), CTC_VOID)), List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null);
- recursiveSetGeneratedBy(method, source, type.getContext());
+ JCMethodDecl method = maker.MethodDef(maker.Modifiers(toJavacModifier(AccessLevel.PRIVATE)), job.toName(CLEAN_METHOD_NAME), maker.Type(Javac.createVoidType(job.builderType.getSymbolTable(), CTC_VOID)), List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null);
+ recursiveSetGeneratedBy(method, job.source, job.getContext());
return method;
}
- static List<JCVariableDecl> generateBuildArgs(CheckerFrameworkVersion cfv, JavacNode type, java.util.List<BuilderFieldData> builderFields) {
- if (!cfv.generateCalledMethods()) return List.<JCVariableDecl>nil();
-
+ static JCVariableDecl generateReceiver(BuilderJob job) {
+ if (!job.checkerFramework.generateCalledMethods()) return null;
+
ArrayList<String> mandatories = new ArrayList<String>();
- for (BuilderFieldData bfd : builderFields) {
+ for (BuilderFieldData bfd : job.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();
+ JavacTreeMaker maker = job.getTreeMaker();
+ if (mandatories.size() == 0) return null;
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"), namePlusTypeParamsToTypeReference(maker, type, builderTypeNode.typarams), null);
- return List.of(recv);
+ JCAnnotation recvAnno = maker.Annotation(genTypeRef(job.builderType, CheckerFrameworkVersion.NAME__CALLED), List.of(arg));
+ JCClassDecl builderTypeNode = (JCClassDecl) job.builderType.get();
+ JCVariableDecl recv = maker.VarDef(maker.Modifiers(Flags.PARAMETER, List.<JCAnnotation>nil()), job.toName("this"), namePlusTypeParamsToTypeReference(maker, job.builderType, builderTypeNode.typarams, List.<JCAnnotation>of(recvAnno)), null);
+ return 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();
+ private JCMethodDecl generateBuildMethod(BuilderJob job, Name staticName, JCExpression returnType, List<JCExpression> thrownExceptions, boolean addCleaning) {
+ JavacTreeMaker maker = job.getTreeMaker();
JCExpression call;
ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>();
if (addCleaning) {
- JCExpression notClean = maker.Unary(CTC_NOT, maker.Select(maker.Ident(type.toName("this")), type.toName("$lombokUnclean")));
- JCStatement invokeClean = maker.Exec(maker.Apply(List.<JCExpression>nil(), maker.Ident(type.toName("$lombokClean")), List.<JCExpression>nil()));
+ JCExpression notClean = maker.Unary(CTC_NOT, maker.Select(maker.Ident(job.toName("this")), job.toName(CLEAN_FIELD_NAME)));
+ JCStatement invokeClean = maker.Exec(maker.Apply(List.<JCExpression>nil(), maker.Ident(job.toName(CLEAN_METHOD_NAME)), List.<JCExpression>nil()));
JCIf ifUnclean = maker.If(notClean, invokeClean, null);
statements.append(ifUnclean);
}
- for (BuilderFieldData bfd : builderFields) {
+ for (BuilderFieldData bfd : job.builderFields) {
if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) {
- bfd.singularData.getSingularizer().appendBuildCode(bfd.singularData, type, source, statements, bfd.builderFieldName, "this");
+ bfd.singularData.getSingularizer().appendBuildCode(bfd.singularData, job.builderType, job.source, statements, bfd.builderFieldName, "this");
}
}
ListBuffer<JCExpression> args = new ListBuffer<JCExpression>();
- Name thisName = type.toName("this");
- for (BuilderFieldData bfd : builderFields) {
+ Name thisName = job.toName("this");
+ for (BuilderFieldData bfd : job.builderFields) {
if (bfd.nameOfSetFlag != null) {
- statements.append(maker.VarDef(maker.Modifiers(0L), bfd.builderFieldName, cloneType(maker, bfd.type, source, tdParent.getContext()), maker.Select(maker.Ident(thisName), bfd.builderFieldName)));
- statements.append(maker.If(maker.Unary(CTC_NOT, maker.Select(maker.Ident(thisName), bfd.nameOfSetFlag)), maker.Exec(maker.Assign(maker.Ident(bfd.builderFieldName), maker.Apply(typeParameterNames(maker, ((JCClassDecl) tdParent.get()).typarams), maker.Select(maker.Ident(((JCClassDecl) tdParent.get()).name), bfd.nameOfDefaultProvider), List.<JCExpression>nil()))), null));
+ statements.append(maker.VarDef(maker.Modifiers(0L), bfd.builderFieldName, cloneType(maker, bfd.type, job.source, job.getContext()), maker.Select(maker.Ident(thisName), bfd.builderFieldName)));
+ statements.append(maker.If(maker.Unary(CTC_NOT, maker.Select(maker.Ident(thisName), bfd.nameOfSetFlag)), maker.Exec(maker.Assign(maker.Ident(bfd.builderFieldName), maker.Apply(typeParameterNames(maker, ((JCClassDecl) job.parentType.get()).typarams), maker.Select(maker.Ident(((JCClassDecl) job.parentType.get()).name), bfd.nameOfDefaultProvider), List.<JCExpression>nil()))), null));
}
if (bfd.nameOfSetFlag != null || (bfd.singularData != null && bfd.singularData.getSingularizer().shadowedDuringBuild())) {
args.append(maker.Ident(bfd.builderFieldName));
@@ -700,20 +757,20 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
}
if (addCleaning) {
- statements.append(maker.Exec(maker.Assign(maker.Select(maker.Ident(type.toName("this")), type.toName("$lombokUnclean")), maker.Literal(CTC_BOOLEAN, 1))));
+ statements.append(maker.Exec(maker.Assign(maker.Select(maker.Ident(job.toName("this")), job.toName(CLEAN_FIELD_NAME)), maker.Literal(CTC_BOOLEAN, 1))));
}
- if (builderName == null) {
+ if (staticName == null) {
call = maker.NewClass(null, List.<JCExpression>nil(), returnType, args.toList(), null);
statements.append(maker.Return(call));
} else {
ListBuffer<JCExpression> typeParams = new ListBuffer<JCExpression>();
- for (JCTypeParameter tp : ((JCClassDecl) type.get()).typarams) {
+ for (JCTypeParameter tp : ((JCClassDecl) job.builderType.get()).typarams) {
typeParams.append(maker.Ident(tp.name));
}
- JCExpression callee = maker.Ident(((JCClassDecl) type.up().get()).name);
- if (!isStatic) callee = maker.Select(callee, type.up().toName("this"));
- JCExpression fn = maker.Select(callee, builderName);
+ JCExpression callee = maker.Ident(((JCClassDecl) job.parentType.get()).name);
+ if (!job.isStatic) callee = maker.Select(callee, job.toName("this"));
+ JCExpression fn = maker.Select(callee, staticName);
call = maker.Apply(typeParams.toList(), fn, args.toList());
if (returnType instanceof JCPrimitiveTypeTree && CTC_VOID.equals(typeTag(returnType))) {
statements.append(maker.Exec(call));
@@ -724,10 +781,15 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
JCBlock body = maker.Block(0, statements.toList());
- 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);
- JCMethodDecl methodDef = maker.MethodDef(maker.Modifiers(toJavacModifier(access), annsOnMethod), type.toName(buildName), returnType, List.<JCTypeParameter>nil(), params, thrownExceptions, body, null);
- if (builderName == null) createRelevantNonNullAnnotation(type, methodDef);
+ List<JCAnnotation> annsOnMethod = job.checkerFramework.generateSideEffectFree() ? List.of(maker.Annotation(genTypeRef(job.builderType, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE), List.<JCExpression>nil())) : List.<JCAnnotation>nil();
+ JCVariableDecl recv = generateReceiver(job);
+ JCMethodDecl methodDef;
+ if (recv != null && maker.hasMethodDefWithRecvParam()) {
+ methodDef = maker.MethodDefWithRecvParam(maker.Modifiers(toJavacModifier(job.accessInners), annsOnMethod), job.toName(job.buildMethodName), returnType, List.<JCTypeParameter>nil(), recv, List.<JCVariableDecl>nil(), thrownExceptions, body, null);
+ } else {
+ methodDef = maker.MethodDef(maker.Modifiers(toJavacModifier(job.accessInners), annsOnMethod), job.toName(job.buildMethodName), returnType, List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), thrownExceptions, body, null);
+ }
+ if (staticName == null) createRelevantNonNullAnnotation(job.builderType, methodDef);
return methodDef;
}
@@ -743,52 +805,54 @@ 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(CheckerFrameworkVersion cfv, boolean isStatic, String builderMethodName, String builderClassName, JavacNode source, JavacNode type, List<JCTypeParameter> typeParams, AccessLevel access) {
- JavacTreeMaker maker = type.getTreeMaker();
+ public JCMethodDecl generateBuilderMethod(BuilderJob job) {
+ //String builderClassName, JavacNode source, JavacNode type, List<JCTypeParameter> typeParams, AccessLevel access) {
+ //builderClassName, annotationNode, tdParent, typeParams, accessForOuters);
+
+ JavacTreeMaker maker = job.getTreeMaker();
ListBuffer<JCExpression> typeArgs = new ListBuffer<JCExpression>();
- for (JCTypeParameter typeParam : typeParams) {
+ for (JCTypeParameter typeParam : job.typeParams) {
typeArgs.append(maker.Ident(typeParam.name));
}
JCExpression call;
- if (isStatic) {
- call = maker.NewClass(null, List.<JCExpression>nil(), namePlusTypeParamsToTypeReference(maker, type, type.toName(builderClassName), false, typeParams), List.<JCExpression>nil(), null);
+ if (job.isStatic) {
+ call = maker.NewClass(null, List.<JCExpression>nil(), namePlusTypeParamsToTypeReference(maker, job.parentType, job.toName(job.builderClassName), false, job.typeParams), List.<JCExpression>nil(), null);
} else {
- call = maker.NewClass(null, List.<JCExpression>nil(), namePlusTypeParamsToTypeReference(maker, null, type.toName(builderClassName), false, typeParams), List.<JCExpression>nil(), null);
- ((JCNewClass) call).encl = maker.Ident(type.toName("this"));
+ call = maker.NewClass(null, List.<JCExpression>nil(), namePlusTypeParamsToTypeReference(maker, null, job.toName(job.builderClassName), false, job.typeParams), List.<JCExpression>nil(), null);
+ ((JCNewClass) call).encl = maker.Ident(job.toName("this"));
}
JCStatement statement = maker.Return(call);
JCBlock body = maker.Block(0, List.<JCStatement>of(statement));
- int modifiers = toJavacModifier(access);
- if (isStatic) modifiers |= Flags.STATIC;
- 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();
- JCMethodDecl methodDef = maker.MethodDef(maker.Modifiers(modifiers, annsOnMethod), type.toName(builderMethodName), namePlusTypeParamsToTypeReference(maker, type, type.toName(builderClassName), !isStatic, typeParams), copyTypeParams(source, typeParams), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null);
- createRelevantNonNullAnnotation(type, methodDef);
+ int modifiers = toJavacModifier(job.accessOuters);
+ if (job.isStatic) modifiers |= Flags.STATIC;
+ List<JCAnnotation> annsOnMethod = List.nil();
+ if (job.checkerFramework.generateSideEffectFree()) annsOnMethod = List.of(maker.Annotation(genTypeRef(job.parentType, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE), List.<JCExpression>nil()));
+ List<JCAnnotation> annsOnParamType = List.nil();
+ if (job.checkerFramework.generateUnique()) annsOnParamType = List.of(maker.Annotation(genTypeRef(job.parentType, CheckerFrameworkVersion.NAME__UNIQUE), List.<JCExpression>nil()));
+
+ JCExpression returnType = namePlusTypeParamsToTypeReference(maker, job.parentType, job.getBuilderClassName(), !job.isStatic, job.builderTypeParams, annsOnParamType);
+ JCMethodDecl methodDef = maker.MethodDef(maker.Modifiers(modifiers, annsOnMethod), job.toName(job.builderMethodName), returnType, job.copyTypeParams(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null);
+ createRelevantNonNullAnnotation(job.parentType, methodDef);
return methodDef;
}
- public void generateBuilderFields(JavacNode builderType, java.util.List<BuilderFieldData> builderFields, JCTree source) {
- int len = builderFields.size();
+ public void generateBuilderFields(BuilderJob job) {
+ int len = job.builderFields.size();
java.util.List<JavacNode> existing = new ArrayList<JavacNode>();
- for (JavacNode child : builderType.down()) {
+ for (JavacNode child : job.builderType.down()) {
if (child.getKind() == Kind.FIELD) existing.add(child);
}
java.util.List<JCVariableDecl> generated = new ArrayList<JCVariableDecl>();
for (int i = len - 1; i >= 0; i--) {
- BuilderFieldData bfd = builderFields.get(i);
+ BuilderFieldData bfd = job.builderFields.get(i);
if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) {
- bfd.createdFields.addAll(bfd.singularData.getSingularizer().generateFields(bfd.singularData, builderType, source));
+ bfd.createdFields.addAll(bfd.singularData.getSingularizer().generateFields(bfd.singularData, job.builderType, job.source));
} else {
JavacNode field = null, setFlag = null;
for (JavacNode exists : existing) {
@@ -796,40 +860,41 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
if (n.equals(bfd.builderFieldName)) field = exists;
if (n.equals(bfd.nameOfSetFlag)) setFlag = exists;
}
- JavacTreeMaker maker = builderType.getTreeMaker();
+ JavacTreeMaker maker = job.getTreeMaker();
if (field == null) {
JCModifiers mods = maker.Modifiers(Flags.PRIVATE);
- JCVariableDecl newField = maker.VarDef(mods, bfd.builderFieldName, cloneType(maker, bfd.type, source, builderType.getContext()), null);
- field = injectFieldAndMarkGenerated(builderType, newField);
+ JCVariableDecl newField = maker.VarDef(mods, bfd.builderFieldName, cloneType(maker, bfd.type, job.source, job.getContext()), null);
+ field = injectFieldAndMarkGenerated(job.builderType, newField);
generated.add(newField);
}
if (setFlag == null && bfd.nameOfSetFlag != null) {
JCModifiers mods = maker.Modifiers(Flags.PRIVATE);
JCVariableDecl newField = maker.VarDef(mods, bfd.nameOfSetFlag, maker.TypeIdent(CTC_BOOLEAN), null);
- injectFieldAndMarkGenerated(builderType, newField);
+ injectFieldAndMarkGenerated(job.builderType, newField);
generated.add(newField);
}
bfd.createdFields.add(field);
}
}
- for (JCVariableDecl gen : generated) recursiveSetGeneratedBy(gen, source, builderType.getContext());
+ for (JCVariableDecl gen : generated) recursiveSetGeneratedBy(gen, job.source, job.getContext());
}
- public void makePrefixedSetterMethodsForBuilder(CheckerFrameworkVersion cfv, JavacNode builderType, BuilderFieldData fieldNode, JavacNode source, boolean fluent, boolean chain, AccessLevel access, String prefix) {
- boolean deprecate = isFieldDeprecated(fieldNode.originalFieldNode);
- if (fieldNode.singularData == null || fieldNode.singularData.getSingularizer() == null) {
- makePrefixedSetterMethodForBuilder(cfv, builderType, deprecate, fieldNode.createdFields.get(0), fieldNode.name, fieldNode.nameOfSetFlag, source, fluent, chain, fieldNode.annotations, fieldNode.originalFieldNode, access, prefix);
+ public void makePrefixedSetterMethodsForBuilder(BuilderJob job, BuilderFieldData bfd, String prefix) {
+ boolean deprecate = isFieldDeprecated(bfd.originalFieldNode);
+ if (bfd.singularData == null || bfd.singularData.getSingularizer() == null) {
+ makePrefixedSetterMethodForBuilder(job, bfd, deprecate, prefix);
} else {
- fieldNode.singularData.getSingularizer().generateMethods(cfv, fieldNode.singularData, deprecate, builderType, source.get(), fluent, chain, access);
+ bfd.singularData.getSingularizer().generateMethods(job, bfd.singularData, deprecate);
}
}
- private void makePrefixedSetterMethodForBuilder(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, String prefix) {
- String setterPrefix = !prefix.isEmpty() ? prefix : fluent ? "" : "set";
- String setterName = HandlerUtil.buildAccessorName(setterPrefix, paramName.toString());
- Name setterName_ = builderType.toName(setterName);
+ private void makePrefixedSetterMethodForBuilder(BuilderJob job, BuilderFieldData bfd, boolean deprecate, String prefix) {
+ JavacNode fieldNode = bfd.createdFields.get(0);
+ String setterPrefix = !prefix.isEmpty() ? prefix : job.oldFluent ? "" : "set";
+ String setterName = HandlerUtil.buildAccessorName(setterPrefix, bfd.name.toString());
+ Name setterName_ = job.builderType.toName(setterName);
- for (JavacNode child : builderType.down()) {
+ for (JavacNode child : job.builderType.down()) {
if (child.getKind() != Kind.METHOD) continue;
JCMethodDecl methodDecl = (JCMethodDecl) child.get();
Name existingName = methodDecl.name;
@@ -838,23 +903,24 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
JavacTreeMaker maker = fieldNode.getTreeMaker();
- 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();
- JCExpression selfType = namePlusTypeParamsToTypeReference(maker, builderType, builderTypeNode.typarams);
- JCVariableDecl recv = maker.VarDef(maker.Modifiers(0L, List.<JCAnnotation>of(ncAnno)), builderType.toName("this"), selfType, null);
- newMethod.params = List.of(recv, newMethod.params.get(0));
- }
- recursiveSetGeneratedBy(newMethod, source.get(), builderType.getContext());
- if (source.up().getKind() == Kind.METHOD) {
- copyJavadocFromParam(originalFieldNode.up(), newMethod, paramName.toString());
+ List<JCAnnotation> methodAnns = JavacHandlerUtil.findCopyableToSetterAnnotations(bfd.originalFieldNode);
+ JCMethodDecl newMethod = null;
+ if (job.checkerFramework.generateCalledMethods() && maker.hasMethodDefWithRecvParam()) {
+ JCAnnotation ncAnno = maker.Annotation(genTypeRef(job.sourceNode, CheckerFrameworkVersion.NAME__NOT_CALLED), List.<JCExpression>of(maker.Literal(setterName.toString())));
+ JCClassDecl builderTypeNode = (JCClassDecl) job.builderType.get();
+ JCExpression selfType = namePlusTypeParamsToTypeReference(maker, job.builderType, builderTypeNode.typarams, List.<JCAnnotation>of(ncAnno));
+ JCVariableDecl recv = maker.VarDef(maker.Modifiers(Flags.PARAMETER, List.<JCAnnotation>nil()), job.builderType.toName("this"), selfType, null);
+ newMethod = HandleSetter.createSetterWithRecv(toJavacModifier(job.accessInners), deprecate, fieldNode, maker, setterName, bfd.name, bfd.nameOfSetFlag, job.oldChain, job.sourceNode, methodAnns, bfd.annotations, recv);
+ }
+ if (newMethod == null) newMethod = HandleSetter.createSetter(toJavacModifier(job.accessInners), deprecate, fieldNode, maker, setterName, bfd.name, bfd.nameOfSetFlag, job.oldChain, job.sourceNode, methodAnns, bfd.annotations);
+ recursiveSetGeneratedBy(newMethod, job.source, job.getContext());
+ if (job.sourceNode.up().getKind() == Kind.METHOD) {
+ copyJavadocFromParam(bfd.originalFieldNode.up(), newMethod, bfd.name.toString());
} else {
- copyJavadoc(originalFieldNode, newMethod, CopyJavadoc.SETTER, true);
+ copyJavadoc(bfd.originalFieldNode, newMethod, CopyJavadoc.SETTER, true);
}
- injectMethod(builderType, newMethod);
+ injectMethod(job.builderType, newMethod);
}
private void copyJavadocFromParam(JavacNode from, JCMethodDecl to, String param) {
@@ -871,14 +937,16 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
}
} catch (Exception ignore) {}
}
-
- public JavacNode makeBuilderClass(boolean isStatic, JavacNode source, JavacNode tdParent, String builderClassName, List<JCTypeParameter> typeParams, JCAnnotation ast, AccessLevel access) {
- JavacTreeMaker maker = tdParent.getTreeMaker();
- int modifiers = toJavacModifier(access);
- if (isStatic) modifiers |= Flags.STATIC;
+
+ public JavacNode makeBuilderClass(BuilderJob job) {
+ //boolean isStatic, JavacNode source, JavacNode tdParent, String builderClassName, List<JCTypeParameter> typeParams, JCAnnotation ast, AccessLevel access) {
+ //isStatic, annotationNode, tdParent, builderClassName, typeParams, ast, accessForOuters
+ JavacTreeMaker maker = job.getTreeMaker();
+ int modifiers = toJavacModifier(job.accessOuters);
+ if (job.isStatic) modifiers |= Flags.STATIC;
JCModifiers mods = maker.Modifiers(modifiers);
- JCClassDecl builder = maker.ClassDef(mods, tdParent.toName(builderClassName), copyTypeParams(source, typeParams), null, List.<JCExpression>nil(), List.<JCTree>nil());
- return injectType(tdParent, builder);
+ JCClassDecl builder = maker.ClassDef(mods, job.getBuilderClassName(), job.copyTypeParams(), null, List.<JCExpression>nil(), List.<JCTree>nil());
+ return injectType(job.parentType, builder);
}
private void addObtainVia(BuilderFieldData bfd, JavacNode node) {
diff --git a/src/core/lombok/javac/handlers/HandleConstructor.java b/src/core/lombok/javac/handlers/HandleConstructor.java
index 2a683767..f30320dc 100644
--- a/src/core/lombok/javac/handlers/HandleConstructor.java
+++ b/src/core/lombok/javac/handlers/HandleConstructor.java
@@ -377,7 +377,6 @@ 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());
@@ -456,7 +455,6 @@ 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;
@@ -469,7 +467,9 @@ public class HandleConstructor {
typeParams.append(maker.TypeParameter(param.name, param.bounds));
}
}
- returnType = namePlusTypeParamsToTypeReference(maker, typeNode, type.typarams);
+ List<JCAnnotation> annsOnReturnType = List.nil();
+ if (getCheckerFrameworkVersion(typeNode).generateUnique()) annsOnReturnType = List.of(maker.Annotation(genTypeRef(typeNode, CheckerFrameworkVersion.NAME__UNIQUE), List.<JCExpression>nil()));
+ returnType = namePlusTypeParamsToTypeReference(maker, typeNode, type.typarams, annsOnReturnType);
constructorType = namePlusTypeParamsToTypeReference(maker, typeNode, type.typarams);
for (JavacNode fieldNode : fields) {
diff --git a/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java b/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java
index d490738e..3935ab4e 100644
--- a/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java
+++ b/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java
@@ -234,7 +234,7 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas
/* ... 1; */
init = maker.Literal(1);
}
- statements.append(maker.VarDef(maker.Modifiers(isEmpty ? finalFlag : 0), resultName, maker.TypeIdent(CTC_INT), init));
+ statements.append(maker.VarDef(maker.Modifiers(isEmpty ? finalFlag : 0L), resultName, maker.TypeIdent(CTC_INT), init));
}
for (Included<JavacNode, EqualsAndHashCode.Include> member : members) {
diff --git a/src/core/lombok/javac/handlers/HandleGetter.java b/src/core/lombok/javac/handlers/HandleGetter.java
index 110941d6..afe2c1b6 100644
--- a/src/core/lombok/javac/handlers/HandleGetter.java
+++ b/src/core/lombok/javac/handlers/HandleGetter.java
@@ -380,7 +380,7 @@ public class HandleGetter extends JavacAnnotationHandler<Getter> {
/* java.lang.Object value = this.fieldName.get();*/ {
JCExpression valueVarType = genJavaLangTypeRef(fieldNode, "Object");
- statements.append(maker.VarDef(maker.Modifiers(0), valueName, valueVarType, callGet(fieldNode, createFieldAccessor(maker, fieldNode, FieldAccess.ALWAYS_FIELD))));
+ statements.append(maker.VarDef(maker.Modifiers(0L), valueName, valueVarType, callGet(fieldNode, createFieldAccessor(maker, fieldNode, FieldAccess.ALWAYS_FIELD))));
}
/* if (value == null) { */ {
diff --git a/src/core/lombok/javac/handlers/HandleSetter.java b/src/core/lombok/javac/handlers/HandleSetter.java
index 82c95719..5c4c7681 100644
--- a/src/core/lombok/javac/handlers/HandleSetter.java
+++ b/src/core/lombok/javac/handlers/HandleSetter.java
@@ -226,7 +226,30 @@ public class HandleSetter extends JavacAnnotationHandler<Setter> {
return d;
}
+ public static JCMethodDecl createSetterWithRecv(long access, boolean deprecate, JavacNode field, JavacTreeMaker treeMaker, String setterName, Name paramName, Name booleanFieldToSet, boolean shouldReturnThis, JavacNode source, List<JCAnnotation> onMethod, List<JCAnnotation> onParam, JCVariableDecl recv) {
+ JCExpression returnType = null;
+ JCReturn returnStatement = null;
+ if (shouldReturnThis) {
+ returnType = cloneSelfType(field);
+ returnStatement = treeMaker.Return(treeMaker.Ident(field.toName("this")));
+ }
+
+ JCMethodDecl d = createSetterWithRecv(access, deprecate, field, treeMaker, setterName, paramName, booleanFieldToSet, returnType, returnStatement, source, onMethod, onParam, recv);
+ 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) {
+ return createSetterWithRecv(access, deprecate, field, treeMaker, setterName, paramName, booleanFieldToSet, methodType, returnStatement, source, onMethod, onParam, null);
+ }
+
+ public static JCMethodDecl createSetterWithRecv(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, JCVariableDecl recv) {
if (setterName == null) return null;
JCVariableDecl fieldDecl = (JCVariableDecl) field.get();
@@ -277,8 +300,14 @@ public class HandleSetter extends JavacAnnotationHandler<Setter> {
annsOnMethod = annsOnMethod.prepend(treeMaker.Annotation(genJavaLangTypeRef(field, "Deprecated"), List.<JCExpression>nil()));
}
- JCMethodDecl methodDef = treeMaker.MethodDef(treeMaker.Modifiers(access, annsOnMethod), methodName, methodType,
- methodGenericParams, parameters, throwsClauses, methodBody, annotationMethodDefaultValue);
+ JCMethodDecl methodDef;
+ if (recv != null && treeMaker.hasMethodDefWithRecvParam()) {
+ methodDef = treeMaker.MethodDefWithRecvParam(treeMaker.Modifiers(access, annsOnMethod), methodName, methodType,
+ methodGenericParams, recv, parameters, throwsClauses, methodBody, annotationMethodDefaultValue);
+ } else {
+ methodDef = treeMaker.MethodDef(treeMaker.Modifiers(access, annsOnMethod), methodName, methodType,
+ methodGenericParams, parameters, throwsClauses, methodBody, annotationMethodDefaultValue);
+ }
if (returnStatement != null) createRelevantNonNullAnnotation(source, methodDef);
JCMethodDecl decl = recursiveSetGeneratedBy(methodDef, source.get(), field.getContext());
copyJavadoc(field, decl, CopyJavadoc.SETTER, returnStatement != null);
diff --git a/src/core/lombok/javac/handlers/HandleSuperBuilder.java b/src/core/lombok/javac/handlers/HandleSuperBuilder.java
index f6bf9e1f..99f0ea6a 100644
--- a/src/core/lombok/javac/handlers/HandleSuperBuilder.java
+++ b/src/core/lombok/javac/handlers/HandleSuperBuilder.java
@@ -21,6 +21,7 @@
*/
package lombok.javac.handlers;
+import static lombok.javac.handlers.HandleBuilder.*;
import static lombok.core.handlers.HandlerUtil.*;
import static lombok.javac.Javac.*;
import static lombok.javac.handlers.JavacHandlerUtil.*;
@@ -78,6 +79,7 @@ import lombok.javac.JavacAnnotationHandler;
import lombok.javac.JavacNode;
import lombok.javac.JavacTreeMaker;
import lombok.javac.handlers.HandleBuilder.BuilderFieldData;
+import lombok.javac.handlers.HandleBuilder.BuilderJob;
import lombok.javac.handlers.JavacHandlerUtil.MemberExistsResult;
import lombok.javac.handlers.JavacSingularsRecipes.ExpressionMaker;
import lombok.javac.handlers.JavacSingularsRecipes.JavacSingularizer;
@@ -88,58 +90,91 @@ import lombok.javac.handlers.JavacSingularsRecipes.StatementMaker;
@HandlerPriority(-1024) //-2^10; to ensure we've picked up @FieldDefault's changes (-2048) but @Value hasn't removed itself yet (-512), so that we can error on presence of it on the builder classes.
public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
private static final String SELF_METHOD = "self";
- private static final String TO_BUILDER_METHOD_NAME = "toBuilder";
private static final String FILL_VALUES_METHOD_NAME = "$fillValuesFrom";
private static final String STATIC_FILL_VALUES_METHOD_NAME = "$fillValuesFromInstanceIntoBuilder";
private static final String INSTANCE_VARIABLE_NAME = "instance";
private static final String BUILDER_VARIABLE_NAME = "b";
-
+
+ class SuperBuilderJob extends BuilderJob {
+ JavacNode builderAbstractType;
+ String builderAbstractClassName;
+ JavacNode builderImplType;
+ String builderImplClassName;
+ List<JCTypeParameter> builderTypeParams_;
+
+ void init(AnnotationValues<SuperBuilder> annValues, SuperBuilder ann, JavacNode node) {
+ accessOuters = accessInners = AccessLevel.PUBLIC;
+ oldFluent = true;
+ oldChain = true;
+
+ builderMethodName = ann.builderMethodName();
+ buildMethodName = ann.buildMethodName();
+ toBuilder = ann.toBuilder();
+
+ if (builderMethodName == null) builderMethodName = "builder";
+ if (buildMethodName == null) buildMethodName = "build";
+ builderClassName = fixBuilderClassName(node, "");
+ }
+
+ void setBuilderToImpl() {
+ builderType = builderImplType;
+ builderClassName = builderImplClassName;
+ builderTypeParams = typeParams;
+ }
+
+ void setBuilderToAbstract() {
+ builderType = builderAbstractType;
+ builderClassName = builderAbstractClassName;
+ builderTypeParams = builderTypeParams_;
+ }
+ }
+
@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();
- // Do not delete the SuperBuilder annotation here, we need it for @Jacksonized.
+ SuperBuilderJob job = new SuperBuilderJob();
+ job.sourceNode = annotationNode;
+ job.source = ast;
+ job.checkerFramework = getCheckerFrameworkVersion(annotationNode);
+ job.isStatic = true;
- String builderMethodName = superbuilderAnnotation.builderMethodName();
- String buildMethodName = superbuilderAnnotation.buildMethodName();
+ SuperBuilder annInstance = annotation.getInstance();
- if (builderMethodName == null) builderMethodName = "builder";
- if (buildMethodName == null) buildMethodName = "build";
+ job.init(annotation, annInstance, annotationNode);
boolean generateBuilderMethod;
- if (builderMethodName.isEmpty()) {
+ if (job.builderMethodName.isEmpty()) {
generateBuilderMethod = false;
- } else if (!checkName("builderMethodName", builderMethodName, annotationNode)) {
+ } else if (!checkName("builderMethodName", job.builderMethodName, annotationNode)) {
return;
} else {
generateBuilderMethod = true;
}
- if (!checkName("buildMethodName", buildMethodName, annotationNode)) return;
+ if (!checkName("buildMethodName", job.buildMethodName, annotationNode)) return;
- boolean toBuilder = superbuilderAnnotation.toBuilder();
+ // Do not delete the SuperBuilder annotation here, we need it for @Jacksonized.
- JavacNode tdParent = annotationNode.up();
+ JavacNode parent = annotationNode.up();
- java.util.List<BuilderFieldData> builderFields = new ArrayList<BuilderFieldData>();
- List<JCTypeParameter> typeParams = List.nil();
- List<JCExpression> thrownExceptions = List.nil();
+ job.builderFields = new ArrayList<BuilderFieldData>();
+ job.typeParams = List.nil();
+ List<JCExpression> buildMethodThrownExceptions = List.nil();
List<JCExpression> superclassTypeParams = List.nil();
-
boolean addCleaning = false;
- if (!(tdParent.get() instanceof JCClassDecl)) {
+ if (!(parent.get() instanceof JCClassDecl)) {
annotationNode.addError("@SuperBuilder is only supported on types.");
return;
}
// Gather all fields of the class that should be set by the builder.
- JCClassDecl td = (JCClassDecl) tdParent.get();
+ job.parentType = parent;
+ JCClassDecl td = (JCClassDecl) parent.get();
ListBuffer<JavacNode> allFields = new ListBuffer<JavacNode>();
ArrayList<JavacNode> nonFinalNonDefaultedFields = null;
- boolean valuePresent = (hasAnnotation(lombok.Value.class, tdParent) || hasAnnotation("lombok.experimental.Value", tdParent));
- for (JavacNode fieldNode : HandleConstructor.findAllFields(tdParent, true)) {
+ boolean valuePresent = (hasAnnotation(lombok.Value.class, parent) || hasAnnotation("lombok.experimental.Value", parent));
+ for (JavacNode fieldNode : HandleConstructor.findAllFields(parent, true)) {
JCVariableDecl fd = (JCVariableDecl) fieldNode.get();
JavacNode isDefault = findAnnotation(Builder.Default.class, fieldNode, true);
boolean isFinal = (fd.mods.flags & Flags.FINAL) != 0 || (valuePresent && !hasAnnotation(NonFinal.class, fieldNode));
@@ -149,7 +184,7 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
bfd.builderFieldName = bfd.name;
bfd.annotations = findCopyableAnnotations(fieldNode);
bfd.type = fd.vartype;
- bfd.singularData = getSingularData(fieldNode, superbuilderAnnotation.setterPrefix());
+ bfd.singularData = getSingularData(fieldNode, annInstance.setterPrefix());
bfd.originalFieldNode = fieldNode;
if (bfd.singularData != null && isDefault != null) {
@@ -169,44 +204,21 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
}
if (isDefault != null) {
- bfd.nameOfDefaultProvider = tdParent.toName("$default$" + bfd.name);
- bfd.nameOfSetFlag = tdParent.toName(bfd.name + "$set");
- bfd.builderFieldName = tdParent.toName(bfd.name + "$value");
+ bfd.nameOfDefaultProvider = parent.toName(DEFAULT_PREFIX + bfd.name);
+ bfd.nameOfSetFlag = parent.toName(bfd.name + SET_PREFIX);
+ bfd.builderFieldName = parent.toName(bfd.name + VALUE_PREFIX);
JCMethodDecl md = HandleBuilder.generateDefaultProvider(bfd.nameOfDefaultProvider, fieldNode, td.typarams);
recursiveSetGeneratedBy(md, ast, annotationNode.getContext());
- if (md != null) injectMethod(tdParent, md);
+ if (md != null) injectMethod(parent, md);
}
addObtainVia(bfd, fieldNode);
- builderFields.add(bfd);
+ job.builderFields.add(bfd);
allFields.append(fieldNode);
}
- // Set the names of the builder classes.
- String builderClassNameTemplate = annotationNode.getAst().readConfiguration(ConfigurationKeys.BUILDER_CLASS_NAME);
- if (builderClassNameTemplate == null || builderClassNameTemplate.isEmpty()) builderClassNameTemplate = "*Builder";
- String builderClassName = builderClassNameTemplate.replace("*", td.name.toString());
- String builderImplClassName = builderClassName + "Impl";
- JCTree extendsClause = Javac.getExtendsClause(td);
- JCExpression superclassBuilderClassExpression = null;
- if (extendsClause instanceof JCTypeApply) {
- // Remember the type arguments, because we need them for the extends clause of our abstract builder class.
- superclassTypeParams = ((JCTypeApply) extendsClause).getTypeArguments();
- // A class name with a generics type, e.g., "Superclass<A>".
- extendsClause = ((JCTypeApply) extendsClause).getType();
- }
- if (extendsClause instanceof JCFieldAccess) {
- Name superclassClassName = ((JCFieldAccess)extendsClause).getIdentifier();
- String superclassBuilderClassName = builderClassNameTemplate.replace("*", superclassClassName);
- superclassBuilderClassExpression = tdParent.getTreeMaker().Select((JCFieldAccess) extendsClause,
- tdParent.toName(superclassBuilderClassName));
- } else if (extendsClause != null) {
- String superclassBuilderClassName = builderClassNameTemplate.replace("*", extendsClause.toString());
- superclassBuilderClassExpression = chainDots(tdParent, extendsClause.toString(), superclassBuilderClassName);
- }
- // If there is no superclass, superclassBuilderClassExpression is still == null at this point.
- // You can use it to check whether to inherit or not.
-
- typeParams = td.typarams;
+ job.typeParams = job.builderTypeParams = td.typarams;
+ job.builderClassName = job.replaceBuilderClassName(td.name);
+ if (!checkName("builderClassName", job.builderClassName, annotationNode)) return;
// <C, B> are the generics for our builder.
String classGenericName = "C";
@@ -214,14 +226,46 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
// We have to make sure that the generics' names do not collide with any generics on the annotated class,
// the classname itself, or any member type name of the annotated class.
// For instance, if there are generics <B, B2, C> on the annotated class, use "C2" and "B3" for our builder.
- java.util.HashSet<String> usedNames = gatherUsedTypeNames(typeParams, td);
+ java.util.HashSet<String> usedNames = gatherUsedTypeNames(job.typeParams, td);
classGenericName = generateNonclashingNameFor(classGenericName, usedNames);
builderGenericName = generateNonclashingNameFor(builderGenericName, usedNames);
- thrownExceptions = List.nil();
+ JavacTreeMaker maker = annotationNode.getTreeMaker();
+
+ {
+ JCExpression annotatedClass = namePlusTypeParamsToTypeReference(maker, parent, job.typeParams);
+ JCTypeParameter c = maker.TypeParameter(parent.toName(classGenericName), List.<JCExpression>of(annotatedClass));
+ ListBuffer<JCExpression> typeParamsForBuilder = getTypeParamExpressions(job.typeParams, maker, job.sourceNode.getContext());
+ typeParamsForBuilder.add(maker.Ident(parent.toName(classGenericName)));
+ typeParamsForBuilder.add(maker.Ident(parent.toName(builderGenericName)));
+ JCTypeApply typeApply = maker.TypeApply(namePlusTypeParamsToTypeReference(maker, parent, job.getBuilderClassName(), false, List.<JCTypeParameter>nil()), typeParamsForBuilder.toList());
+ JCTypeParameter d = maker.TypeParameter(parent.toName(builderGenericName), List.<JCExpression>of(typeApply));
+ if (job.typeParams == null || job.typeParams.isEmpty()) {
+ job.builderTypeParams_ = List.of(c, d);
+ } else {
+ job.builderTypeParams_ = job.typeParams.append(c).append(d);
+ }
+ }
+
+ JCTree extendsClause = Javac.getExtendsClause(td);
+ JCExpression superclassBuilderClass = null;
+ if (extendsClause instanceof JCTypeApply) {
+ // Remember the type arguments, because we need them for the extends clause of our abstract builder class.
+ superclassTypeParams = ((JCTypeApply) extendsClause).getTypeArguments();
+ // A class name with a generics type, e.g., "Superclass<A>".
+ extendsClause = ((JCTypeApply) extendsClause).getType();
+ }
+ if (extendsClause instanceof JCFieldAccess) {
+ Name superclassName = ((JCFieldAccess) extendsClause).getIdentifier();
+ String superclassBuilderClassName = superclassName.toString() + "Builder";
+ superclassBuilderClass = parent.getTreeMaker().Select((JCFieldAccess) extendsClause, parent.toName(superclassBuilderClassName));
+ } else if (extendsClause != null) {
+ String superclassBuilderClassName = extendsClause.toString() + "Builder";
+ superclassBuilderClass = chainDots(parent, extendsClause.toString(), superclassBuilderClassName);
+ }
// Check validity of @ObtainVia fields, and add check if adding cleaning for @Singular is necessary.
- for (BuilderFieldData bfd : builderFields) {
+ for (BuilderFieldData bfd : job.builderFields) {
if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) {
if (bfd.singularData.getSingularizer().requiresCleaning()) {
addCleaning = true;
@@ -240,83 +284,85 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
}
}
+ job.builderAbstractClassName = job.builderClassName = job.replaceBuilderClassName(td.name);
+ job.builderImplClassName = job.builderAbstractClassName + "Impl";
+
// Create the abstract builder class.
- JavacNode builderType = findInnerClass(tdParent, builderClassName);
- if (builderType == null) {
- builderType = generateBuilderAbstractClass(annotationNode, tdParent, builderClassName, superclassBuilderClassExpression,
- typeParams, superclassTypeParams, classGenericName, builderGenericName);
- recursiveSetGeneratedBy(builderType.get(), ast, annotationNode.getContext());
+ job.builderAbstractType = findInnerClass(parent, job.builderClassName);
+ if (job.builderAbstractType == null) {
+ job.builderAbstractType = generateBuilderAbstractClass(job, superclassBuilderClass, superclassTypeParams, classGenericName, builderGenericName);
+ recursiveSetGeneratedBy(job.builderAbstractType.get(), ast, annotationNode.getContext());
} else {
- JCClassDecl builderTypeDeclaration = (JCClassDecl) builderType.get();
+ JCClassDecl builderTypeDeclaration = (JCClassDecl) job.builderAbstractType.get();
if (!builderTypeDeclaration.getModifiers().getFlags().contains(Modifier.STATIC)
|| !builderTypeDeclaration.getModifiers().getFlags().contains(Modifier.ABSTRACT)) {
annotationNode.addError("Existing Builder must be an abstract static inner class.");
return;
}
- sanityCheckForMethodGeneratingAnnotationsOnBuilderClass(builderType, annotationNode);
+ sanityCheckForMethodGeneratingAnnotationsOnBuilderClass(job.builderAbstractType, annotationNode);
// Generate errors for @Singular BFDs that have one already defined node.
- for (BuilderFieldData bfd : builderFields) {
+ for (BuilderFieldData bfd : job.builderFields) {
SingularData sd = bfd.singularData;
if (sd == null) continue;
JavacSingularizer singularizer = sd.getSingularizer();
if (singularizer == null) continue;
- if (singularizer.checkForAlreadyExistingNodesAndGenerateError(builderType, sd)) {
+ if (singularizer.checkForAlreadyExistingNodesAndGenerateError(job.builderType, sd)) {
bfd.singularData = null;
}
}
}
// Generate the fields in the abstract builder class that hold the values for the instance.
- generateBuilderFields(builderType, builderFields, ast);
+ job.setBuilderToAbstract();
+ generateBuilderFields(job.builderType, job.builderFields, ast);
if (addCleaning) {
- JavacTreeMaker maker = builderType.getTreeMaker();
- JCVariableDecl uncleanField = maker.VarDef(maker.Modifiers(Flags.PRIVATE), builderType.toName("$lombokUnclean"), maker.TypeIdent(CTC_BOOLEAN), null);
+ JCVariableDecl uncleanField = maker.VarDef(maker.Modifiers(Flags.PRIVATE), job.toName("$lombokUnclean"), maker.TypeIdent(CTC_BOOLEAN), null);
recursiveSetGeneratedBy(uncleanField, ast, annotationNode.getContext());
- injectFieldAndMarkGenerated(builderType, uncleanField);
+ injectFieldAndMarkGenerated(job.builderType, uncleanField);
}
- if (toBuilder) {
+ if (job.toBuilder) {
// Generate $fillValuesFrom() method in the abstract builder.
- JCMethodDecl fvm = generateFillValuesMethod(tdParent, superclassBuilderClassExpression != null, builderGenericName, classGenericName, builderClassName);
+ JCMethodDecl fvm = generateFillValuesMethod(job, superclassBuilderClass != null, builderGenericName, classGenericName);
recursiveSetGeneratedBy(fvm, ast, annotationNode.getContext());
- injectMethod(builderType, fvm);
+ injectMethod(job.builderType, fvm);
// Generate $fillValuesFromInstanceIntoBuilder() method in the builder implementation class.
- JCMethodDecl sfvm = generateStaticFillValuesMethod(tdParent, builderClassName, typeParams, builderFields, superbuilderAnnotation.setterPrefix());
+ JCMethodDecl sfvm = generateStaticFillValuesMethod(job, annInstance.setterPrefix());
recursiveSetGeneratedBy(sfvm, ast, annotationNode.getContext());
- injectMethod(builderType, sfvm);
+ injectMethod(job.builderType, sfvm);
}
// Generate abstract self() and build() methods in the abstract builder.
- JCMethodDecl asm = generateAbstractSelfMethod(cfv, tdParent, superclassBuilderClassExpression != null, builderGenericName);
+ JCMethodDecl asm = generateAbstractSelfMethod(job, superclassBuilderClass != null, builderGenericName);
recursiveSetGeneratedBy(asm, ast, annotationNode.getContext());
- injectMethod(builderType, asm);
- JCMethodDecl abm = generateAbstractBuildMethod(cfv, tdParent, buildMethodName, builderFields, superclassBuilderClassExpression != null, classGenericName);
+ injectMethod(job.builderType, asm);
+ JCMethodDecl abm = generateAbstractBuildMethod(job, superclassBuilderClass != null, classGenericName);
recursiveSetGeneratedBy(abm, ast, annotationNode.getContext());
- injectMethod(builderType, abm);
+ injectMethod(job.builderType, abm);
// Create the setter methods in the abstract builder.
- for (BuilderFieldData bfd : builderFields) {
- generateSetterMethodsForBuilder(cfv, builderType, bfd, annotationNode, builderGenericName, superbuilderAnnotation.setterPrefix());
+ for (BuilderFieldData bfd : job.builderFields) {
+ generateSetterMethodsForBuilder(job, bfd, builderGenericName, annInstance.setterPrefix());
}
// Create the toString() method for the abstract builder.
java.util.List<Included<JavacNode, ToString.Include>> fieldNodes = new ArrayList<Included<JavacNode, ToString.Include>>();
- for (BuilderFieldData bfd : builderFields) {
+ for (BuilderFieldData bfd : job.builderFields) {
for (JavacNode f : bfd.createdFields) {
fieldNodes.add(new Included<JavacNode, ToString.Include>(f, null, true, false));
}
}
// Let toString() call super.toString() if there is a superclass, so that it also shows fields from the superclass' builder.
- JCMethodDecl toStringMethod = HandleToString.createToString(builderType, fieldNodes, true, superclassBuilderClassExpression != null, FieldAccess.ALWAYS_FIELD, ast);
- if (toStringMethod != null) injectMethod(builderType, toStringMethod);
+ JCMethodDecl toStringMethod = HandleToString.createToString(job.builderType, fieldNodes, true, superclassBuilderClass != null, FieldAccess.ALWAYS_FIELD, ast);
+ if (toStringMethod != null) injectMethod(job.builderType, toStringMethod);
// If clean methods are requested, add them now.
if (addCleaning) {
- JCMethodDecl md = generateCleanMethod(builderFields, builderType, ast);
+ JCMethodDecl md = generateCleanMethod(job.builderFields, job.builderType, ast);
recursiveSetGeneratedBy(md, ast, annotationNode.getContext());
- injectMethod(builderType, md);
+ injectMethod(job.builderType, md);
}
boolean isAbstract = (td.mods.flags & Flags.ABSTRACT) != 0;
@@ -324,69 +370,71 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
// Only non-abstract classes get the Builder implementation.
// Create the builder implementation class.
- JavacNode builderImplType = findInnerClass(tdParent, builderImplClassName);
- if (builderImplType == null) {
- builderImplType = generateBuilderImplClass(annotationNode, tdParent, builderImplClassName, builderClassName, typeParams);
- recursiveSetGeneratedBy(builderImplType.get(), ast, annotationNode.getContext());
+ job.builderImplType = findInnerClass(parent, job.builderImplClassName);
+ if (job.builderImplType == null) {
+ job.builderImplType = generateBuilderImplClass(job);
+ recursiveSetGeneratedBy(job.builderImplType.get(), ast, annotationNode.getContext());
} else {
- JCClassDecl builderImplTypeDeclaration = (JCClassDecl) builderImplType.get();
+ JCClassDecl builderImplTypeDeclaration = (JCClassDecl) job.builderImplType.get();
if (!builderImplTypeDeclaration.getModifiers().getFlags().contains(Modifier.STATIC)
|| builderImplTypeDeclaration.getModifiers().getFlags().contains(Modifier.ABSTRACT)) {
annotationNode.addError("Existing BuilderImpl must be a non-abstract static inner class.");
return;
}
- sanityCheckForMethodGeneratingAnnotationsOnBuilderClass(builderImplType, annotationNode);
+ sanityCheckForMethodGeneratingAnnotationsOnBuilderClass(job.builderImplType, annotationNode);
}
// Create a simple constructor for the BuilderImpl class.
- JCMethodDecl cd = HandleConstructor.createConstructor(AccessLevel.PRIVATE, List.<JCAnnotation>nil(), builderImplType, List.<JavacNode>nil(), false, annotationNode);
- if (cd != null) injectMethod(builderImplType, cd);
+ JCMethodDecl cd = HandleConstructor.createConstructor(AccessLevel.PRIVATE, List.<JCAnnotation>nil(), job.builderImplType, List.<JavacNode>nil(), false, annotationNode);
+ if (cd != null) injectMethod(job.builderImplType, cd);
+ job.setBuilderToImpl();
// Create the self() and build() methods in the BuilderImpl.
- JCMethodDecl selfMethod = generateSelfMethod(cfv, builderImplType, typeParams);
+ JCMethodDecl selfMethod = generateSelfMethod(job);
recursiveSetGeneratedBy(selfMethod, ast, annotationNode.getContext());
- injectMethod(builderImplType, selfMethod);
- if (methodExists(buildMethodName, builderImplType, -1) == MemberExistsResult.NOT_EXISTS) {
- JCMethodDecl buildMethod = generateBuildMethod(cfv, buildMethodName, tdParent, builderImplType, builderFields, thrownExceptions);
+ injectMethod(job.builderType, selfMethod);
+ if (methodExists(job.buildMethodName, job.builderType, -1) == MemberExistsResult.NOT_EXISTS) {
+ JCMethodDecl buildMethod = generateBuildMethod(job, buildMethodThrownExceptions);
recursiveSetGeneratedBy(buildMethod, ast, annotationNode.getContext());
- injectMethod(builderImplType, buildMethod);
+ injectMethod(job.builderType, buildMethod);
}
}
// Generate a constructor in the annotated class that takes a builder as argument.
- if (!constructorExists(tdParent, builderClassName)) {
- generateBuilderBasedConstructor(cfv, tdParent, typeParams, builderFields, annotationNode, builderClassName,
- superclassBuilderClassExpression != null);
+ if (!constructorExists(job.parentType, job.builderAbstractClassName)) {
+ job.setBuilderToAbstract();
+ generateBuilderBasedConstructor(job, superclassBuilderClass != null);
}
- if (isAbstract) {
+ if (!isAbstract) {
// Only non-abstract classes get the builder() and toBuilder() methods.
- return;
- }
- // Add the builder() method to the annotated class.
- // 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(cfv, builderMethodName, builderClassName, builderImplClassName, annotationNode, tdParent, typeParams);
- recursiveSetGeneratedBy(builderMethod, ast, annotationNode.getContext());
- if (builderMethod != null) injectMethod(tdParent, builderMethod);
- }
-
- // Add the toBuilder() method to the annotated class.
- if (toBuilder) {
- switch (methodExists(TO_BUILDER_METHOD_NAME, tdParent, 0)) {
- case EXISTS_BY_USER:
- break;
- case NOT_EXISTS:
- JCMethodDecl md = generateToBuilderMethod(cfv, builderClassName, builderImplClassName, annotationNode, tdParent, typeParams);
- if (md != null) {
- recursiveSetGeneratedBy(md, ast, annotationNode.getContext());
- injectMethod(tdParent, md);
+ // Add the builder() method to the annotated class.
+ // Allow users to specify their own builder() methods, e.g., to provide default values.
+ if (generateBuilderMethod && methodExists(job.builderMethodName, job.parentType, -1) != MemberExistsResult.NOT_EXISTS) generateBuilderMethod = false;
+ if (generateBuilderMethod) {
+ JCMethodDecl builderMethod = generateBuilderMethod(job);
+ if (builderMethod != null) {
+ recursiveSetGeneratedBy(builderMethod, ast, annotationNode.getContext());
+ injectMethod(job.parentType, builderMethod);
+ }
+ }
+
+ // Add the toBuilder() method to the annotated class.
+ if (job.toBuilder) {
+ switch (methodExists(TO_BUILDER_METHOD_NAME, job.parentType, 0)) {
+ case EXISTS_BY_USER:
+ break;
+ case NOT_EXISTS:
+ JCMethodDecl md = generateToBuilderMethod(job);
+ if (md != null) {
+ recursiveSetGeneratedBy(md, ast, annotationNode.getContext());
+ injectMethod(job.parentType, md);
+ }
+ break;
+ default:
+ // Should not happen.
}
- break;
- default:
- // Should not happen.
}
}
@@ -400,95 +448,86 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
/**
* Creates and returns the abstract builder class and injects it into the annotated class.
*/
- private JavacNode generateBuilderAbstractClass(JavacNode source, JavacNode tdParent, String builderClass,
- JCExpression superclassBuilderClassExpression, List<JCTypeParameter> typeParams,
- List<JCExpression> superclassTypeParams, String classGenericName, String builderGenericName) {
-
- JavacTreeMaker maker = tdParent.getTreeMaker();
+ private JavacNode generateBuilderAbstractClass(SuperBuilderJob job, JCExpression superclassBuilderClass, List<JCExpression> superclassTypeParams, String classGenericName, String builderGenericName) {
+ JavacTreeMaker maker = job.parentType.getTreeMaker();
JCModifiers mods = maker.Modifiers(Flags.STATIC | Flags.ABSTRACT | Flags.PUBLIC);
// Keep any type params of the annotated class.
ListBuffer<JCTypeParameter> allTypeParams = new ListBuffer<JCTypeParameter>();
- allTypeParams.addAll(copyTypeParams(source, typeParams));
+ allTypeParams.addAll(copyTypeParams(job.sourceNode, job.typeParams));
// Add builder-specific type params required for inheritable builders.
// 1. The return type for the build() method, named "C", which extends the annotated class.
- JCExpression annotatedClass = namePlusTypeParamsToTypeReference(maker, tdParent, typeParams);
+ JCExpression annotatedClass = namePlusTypeParamsToTypeReference(maker, job.parentType, job.typeParams);
- allTypeParams.add(maker.TypeParameter(tdParent.toName(classGenericName), List.<JCExpression>of(annotatedClass)));
+ allTypeParams.add(maker.TypeParameter(job.toName(classGenericName), List.<JCExpression>of(annotatedClass)));
// 2. The return type for all setter methods, named "B", which extends this builder class.
- Name builderClassName = tdParent.toName(builderClass);
- ListBuffer<JCExpression> typeParamsForBuilder = getTypeParamExpressions(typeParams, maker, source.getContext());
- typeParamsForBuilder.add(maker.Ident(tdParent.toName(classGenericName)));
- typeParamsForBuilder.add(maker.Ident(tdParent.toName(builderGenericName)));
- JCTypeApply typeApply = maker.TypeApply(namePlusTypeParamsToTypeReference(maker, tdParent, builderClassName, false, List.<JCTypeParameter>nil()), typeParamsForBuilder.toList());
- allTypeParams.add(maker.TypeParameter(tdParent.toName(builderGenericName), List.<JCExpression>of(typeApply)));
+ Name builderClassName = job.toName(job.builderClassName);
+ ListBuffer<JCExpression> typeParamsForBuilder = getTypeParamExpressions(job.typeParams, maker, job.sourceNode.getContext());
+ typeParamsForBuilder.add(maker.Ident(job.toName(classGenericName)));
+ typeParamsForBuilder.add(maker.Ident(job.toName(builderGenericName)));
+ JCTypeApply typeApply = maker.TypeApply(namePlusTypeParamsToTypeReference(maker, job.parentType, builderClassName, false, List.<JCTypeParameter>nil()), typeParamsForBuilder.toList());
+ allTypeParams.add(maker.TypeParameter(job.toName(builderGenericName), List.<JCExpression>of(typeApply)));
JCExpression extending = null;
- if (superclassBuilderClassExpression != null) {
+ if (superclassBuilderClass != null) {
// If the annotated class extends another class, we want this builder to extend the builder of the superclass.
// 1. Add the type parameters of the superclass.
- typeParamsForBuilder = getTypeParamExpressions(superclassTypeParams, maker, source.getContext());
+ typeParamsForBuilder = getTypeParamExpressions(superclassTypeParams, maker, job.sourceNode.getContext());
// 2. Add the builder type params <C, B>.
- typeParamsForBuilder.add(maker.Ident(tdParent.toName(classGenericName)));
- typeParamsForBuilder.add(maker.Ident(tdParent.toName(builderGenericName)));
- extending = maker.TypeApply(superclassBuilderClassExpression, typeParamsForBuilder.toList());
+ typeParamsForBuilder.add(maker.Ident(job.toName(classGenericName)));
+ typeParamsForBuilder.add(maker.Ident(job.toName(builderGenericName)));
+ extending = maker.TypeApply(superclassBuilderClass, typeParamsForBuilder.toList());
}
JCClassDecl builder = maker.ClassDef(mods, builderClassName, allTypeParams.toList(), extending, List.<JCExpression>nil(), List.<JCTree>nil());
- return injectType(tdParent, builder);
+ return injectType(job.parentType, builder);
}
/**
* Creates and returns the concrete builder implementation class and injects it into the annotated class.
*/
- private JavacNode generateBuilderImplClass(JavacNode source, JavacNode tdParent, String builderImplClass, String builderAbstractClass, List<JCTypeParameter> typeParams) {
- JavacTreeMaker maker = tdParent.getTreeMaker();
+ private JavacNode generateBuilderImplClass(SuperBuilderJob job) {
+ JavacTreeMaker maker = job.getTreeMaker();
JCModifiers mods = maker.Modifiers(Flags.STATIC | Flags.PRIVATE | Flags.FINAL);
// Extend the abstract builder.
- JCExpression extending = namePlusTypeParamsToTypeReference(maker, tdParent, tdParent.toName(builderAbstractClass), false, List.<JCTypeParameter>nil());
+ JCExpression extending = namePlusTypeParamsToTypeReference(maker, job.parentType, job.toName(job.builderAbstractClassName), false, List.<JCTypeParameter>nil());
// Add any type params of the annotated class.
ListBuffer<JCTypeParameter> allTypeParams = new ListBuffer<JCTypeParameter>();
- allTypeParams.addAll(copyTypeParams(source, typeParams));
+ allTypeParams.addAll(copyTypeParams(job.sourceNode, job.typeParams));
// Add builder-specific type params required for inheritable builders.
// 1. The return type for the build() method (named "C" in the abstract builder), which is the annotated class.
- JCExpression annotatedClass = namePlusTypeParamsToTypeReference(maker, tdParent, typeParams);
+ JCExpression annotatedClass = namePlusTypeParamsToTypeReference(maker, job.parentType, job.typeParams);
// 2. The return type for all setter methods (named "B" in the abstract builder), which is this builder class.
- JCExpression builderImplClassExpression = namePlusTypeParamsToTypeReference(maker, tdParent, tdParent.toName(builderImplClass), false, typeParams);
+ JCExpression builderImplClassExpression = namePlusTypeParamsToTypeReference(maker, job.parentType, job.toName(job.builderImplClassName), false, job.typeParams);
- ListBuffer<JCExpression> typeParamsForBuilder = getTypeParamExpressions(typeParams, maker, source.getContext());
+ ListBuffer<JCExpression> typeParamsForBuilder = getTypeParamExpressions(job.typeParams, maker, job.getContext());
typeParamsForBuilder.add(annotatedClass);
typeParamsForBuilder.add(builderImplClassExpression);
extending = maker.TypeApply(extending, typeParamsForBuilder.toList());
- JCClassDecl builder = maker.ClassDef(mods, tdParent.toName(builderImplClass), copyTypeParams(source, typeParams), extending, List.<JCExpression>nil(), List.<JCTree>nil());
- return injectType(tdParent, builder);
+ JCClassDecl builder = maker.ClassDef(mods, job.toName(job.builderImplClassName), copyTypeParams(job.parentType, job.typeParams), extending, List.<JCExpression>nil(), List.<JCTree>nil());
+ return injectType(job.parentType, builder);
}
/**
* Generates a constructor that has a builder as the only parameter.
* The values from the builder are used to initialize the fields of new instances.
*
- * @param typeNode
- * the type (with the {@code @Builder} annotation) for which a
- * constructor should be generated.
- * @param typeParams
- * @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
* If {@code true}, the constructor will explicitly call a super
* constructor with the builder as argument. Requires
* {@code builderClassAsParameter != null}.
*/
- 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();
+ private void generateBuilderBasedConstructor(SuperBuilderJob job, boolean callBuilderBasedSuperConstructor) {
+ JavacTreeMaker maker = job.getTreeMaker();
AccessLevel level = AccessLevel.PROTECTED;
ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>();
- Name builderVariableName = typeNode.toName(BUILDER_VARIABLE_NAME);
- for (BuilderFieldData bfd : builderFields) {
+ Name builderVariableName = job.toName(BUILDER_VARIABLE_NAME);
+ for (BuilderFieldData bfd : job.builderFields) {
JCExpression rhs;
if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) {
bfd.singularData.getSingularizer().appendBuildCode(bfd.singularData, bfd.originalFieldNode, bfd.type, statements, bfd.builderFieldName, "b");
@@ -496,67 +535,66 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
} else {
rhs = maker.Select(maker.Ident(builderVariableName), bfd.builderFieldName);
}
- JCFieldAccess fieldInThis = maker.Select(maker.Ident(typeNode.toName("this")), bfd.rawName);
+ JCFieldAccess fieldInThis = maker.Select(maker.Ident(job.toName("this")), bfd.rawName);
JCStatement assign = maker.Exec(maker.Assign(fieldInThis, rhs));
// In case of @Builder.Default, set the value to the default if it was not set in the builder.
if (bfd.nameOfSetFlag != null) {
JCFieldAccess setField = maker.Select(maker.Ident(builderVariableName), bfd.nameOfSetFlag);
- fieldInThis = maker.Select(maker.Ident(typeNode.toName("this")), bfd.rawName);
- JCExpression parentTypeRef = namePlusTypeParamsToTypeReference(maker, typeNode, List.<JCTypeParameter>nil());
- JCAssign assignDefault = maker.Assign(fieldInThis, maker.Apply(typeParameterNames(maker, ((JCClassDecl) typeNode.get()).typarams), maker.Select(parentTypeRef, bfd.nameOfDefaultProvider), List.<JCExpression>nil()));
+ fieldInThis = maker.Select(maker.Ident(job.toName("this")), bfd.rawName);
+ JCExpression parentTypeRef = namePlusTypeParamsToTypeReference(maker, job.parentType, List.<JCTypeParameter>nil());
+ JCAssign assignDefault = maker.Assign(fieldInThis, maker.Apply(typeParameterNames(maker, ((JCClassDecl) job.parentType.get()).typarams), maker.Select(parentTypeRef, bfd.nameOfDefaultProvider), List.<JCExpression>nil()));
statements.append(maker.If(setField, assign, maker.Exec(assignDefault)));
} else {
statements.append(assign);
}
if (hasNonNullAnnotations(bfd.originalFieldNode)) {
- JCStatement nullCheck = generateNullCheck(maker, bfd.originalFieldNode, source);
+ JCStatement nullCheck = generateNullCheck(maker, bfd.originalFieldNode, job.sourceNode);
if (nullCheck != null) statements.append(nullCheck);
}
}
- List<JCAnnotation> annsOnMethod = cfv.generateUnique() ? List.of(maker.Annotation(genTypeRef(typeNode, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE), List.<JCExpression>nil())) : List.<JCAnnotation>nil();
+ List<JCAnnotation> annsOnMethod = job.checkerFramework.generateUnique() ? List.of(maker.Annotation(genTypeRef(job.parentType, 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>();
- long flags = JavacHandlerUtil.addFinalIfNeeded(Flags.PARAMETER, typeNode.getContext());
- Name builderClassname = typeNode.toName(builderClassName);
+ long flags = JavacHandlerUtil.addFinalIfNeeded(Flags.PARAMETER, job.getContext());
// First add all generics that are present on the parent type.
- ListBuffer<JCExpression> typeParamsForBuilderParameter = getTypeParamExpressions(typeParams, maker, typeNode.getContext());
+ ListBuffer<JCExpression> typeParamsForBuilderParameter = getTypeParamExpressions(job.typeParams, maker, job.getContext());
// Now add the <?, ?>.
JCWildcard wildcard = maker.Wildcard(maker.TypeBoundKind(BoundKind.UNBOUND), null);
typeParamsForBuilderParameter.add(wildcard);
wildcard = maker.Wildcard(maker.TypeBoundKind(BoundKind.UNBOUND), null);
typeParamsForBuilderParameter.add(wildcard);
- JCTypeApply paramType = maker.TypeApply(namePlusTypeParamsToTypeReference(maker, typeNode, builderClassname, false, List.<JCTypeParameter>nil()), typeParamsForBuilderParameter.toList());
+ JCTypeApply paramType = maker.TypeApply(namePlusTypeParamsToTypeReference(maker, job.parentType, job.getBuilderClassName(), false, List.<JCTypeParameter>nil()), typeParamsForBuilderParameter.toList());
JCVariableDecl param = maker.VarDef(maker.Modifiers(flags), builderVariableName, paramType, null);
params.append(param);
if (callBuilderBasedSuperConstructor) {
// The first statement must be the call to the super constructor.
JCMethodInvocation callToSuperConstructor = maker.Apply(List.<JCExpression>nil(),
- maker.Ident(typeNode.toName("super")),
+ maker.Ident(job.toName("super")),
List.<JCExpression>of(maker.Ident(builderVariableName)));
statements.prepend(maker.Exec(callToSuperConstructor));
}
- JCMethodDecl constr = recursiveSetGeneratedBy(maker.MethodDef(mods, typeNode.toName("<init>"),
+ JCMethodDecl constr = recursiveSetGeneratedBy(maker.MethodDef(mods, job.toName("<init>"),
null, List.<JCTypeParameter>nil(), params.toList(), List.<JCExpression>nil(),
- maker.Block(0L, statements.toList()), null), source.get(), typeNode.getContext());
+ maker.Block(0L, statements.toList()), null), job.source, job.getContext());
- injectMethod(typeNode, constr, null, Javac.createVoidType(typeNode.getSymbolTable(), CTC_VOID));
+ injectMethod(job.parentType, constr, null, Javac.createVoidType(job.builderType.getSymbolTable(), CTC_VOID));
}
- private JCMethodDecl generateBuilderMethod(CheckerFrameworkVersion cfv, String builderMethodName, String builderClassName, String builderImplClassName, JavacNode source, JavacNode type, List<JCTypeParameter> typeParams) {
- JavacTreeMaker maker = type.getTreeMaker();
+ private JCMethodDecl generateBuilderMethod(SuperBuilderJob job) {
+ JavacTreeMaker maker = job.getTreeMaker();
ListBuffer<JCExpression> typeArgs = new ListBuffer<JCExpression>();
- for (JCTypeParameter typeParam : typeParams) typeArgs.append(maker.Ident(typeParam.name));
+ for (JCTypeParameter typeParam : job.typeParams) typeArgs.append(maker.Ident(typeParam.name));
- JCExpression call = maker.NewClass(null, List.<JCExpression>nil(), namePlusTypeParamsToTypeReference(maker, type, type.toName(builderImplClassName), false, typeParams), List.<JCExpression>nil(), null);
+ JCExpression call = maker.NewClass(null, List.<JCExpression>nil(), namePlusTypeParamsToTypeReference(maker, job.parentType, job.toName(job.builderImplClassName), false, job.typeParams), List.<JCExpression>nil(), null);
JCStatement statement = maker.Return(call);
JCBlock body = maker.Block(0, List.<JCStatement>of(statement));
@@ -565,16 +603,16 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
// Add any type params of the annotated class to the return type.
ListBuffer<JCExpression> typeParameterNames = new ListBuffer<JCExpression>();
- typeParameterNames.addAll(typeParameterNames(maker, typeParams));
+ typeParameterNames.addAll(typeParameterNames(maker, job.typeParams));
// Now add the <?, ?>.
JCWildcard wildcard = maker.Wildcard(maker.TypeBoundKind(BoundKind.UNBOUND), null);
typeParameterNames.add(wildcard);
typeParameterNames.add(wildcard);
- JCTypeApply returnType = maker.TypeApply(namePlusTypeParamsToTypeReference(maker, type, type.toName(builderClassName), false, List.<JCTypeParameter>nil()), typeParameterNames.toList());
+ JCTypeApply returnType = maker.TypeApply(namePlusTypeParamsToTypeReference(maker, job.parentType, job.toName(job.builderAbstractClassName), false, List.<JCTypeParameter>nil()), typeParameterNames.toList());
- List<JCAnnotation> annsOnMethod = cfv.generateUnique() ? List.of(maker.Annotation(genTypeRef(type, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE), List.<JCExpression>nil())) : List.<JCAnnotation>nil();
- JCMethodDecl methodDef = maker.MethodDef(maker.Modifiers(modifiers, annsOnMethod), type.toName(builderMethodName), returnType, copyTypeParams(source, typeParams), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null);
- createRelevantNonNullAnnotation(type, methodDef);
+ List<JCAnnotation> annsOnMethod = job.checkerFramework.generateUnique() ? List.of(maker.Annotation(genTypeRef(job.parentType, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE), List.<JCExpression>nil())) : List.<JCAnnotation>nil();
+ JCMethodDecl methodDef = maker.MethodDef(maker.Modifiers(modifiers, annsOnMethod), job.toName(job.builderMethodName), returnType, copyTypeParams(job.sourceNode, job.typeParams), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null);
+ createRelevantNonNullAnnotation(job.parentType, methodDef);
return methodDef;
}
@@ -586,15 +624,15 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
* }
* </pre>
*/
- private JCMethodDecl generateToBuilderMethod(CheckerFrameworkVersion cfv, String builderClassName, String builderImplClassName, JavacNode source, JavacNode type, List<JCTypeParameter> typeParams) {
- JavacTreeMaker maker = type.getTreeMaker();
+ private JCMethodDecl generateToBuilderMethod(SuperBuilderJob job) {
+ JavacTreeMaker maker = job.getTreeMaker();
ListBuffer<JCExpression> typeArgs = new ListBuffer<JCExpression>();
- for (JCTypeParameter typeParam : typeParams) typeArgs.append(maker.Ident(typeParam.name));
+ for (JCTypeParameter typeParam : job.typeParams) typeArgs.append(maker.Ident(typeParam.name));
- JCExpression newClass = maker.NewClass(null, List.<JCExpression>nil(), namePlusTypeParamsToTypeReference(maker, type, type.toName(builderImplClassName), false, typeParams), List.<JCExpression>nil(), null);
- List<JCExpression> methodArgs = List.<JCExpression>of(maker.Ident(type.toName("this")));
- JCMethodInvocation invokeFillMethod = maker.Apply(List.<JCExpression>nil(), maker.Select(newClass, type.toName(FILL_VALUES_METHOD_NAME)), methodArgs);
+ JCExpression newClass = maker.NewClass(null, List.<JCExpression>nil(), namePlusTypeParamsToTypeReference(maker, job.parentType, job.toName(job.builderImplClassName), false, job.typeParams), List.<JCExpression>nil(), null);
+ List<JCExpression> methodArgs = List.<JCExpression>of(maker.Ident(job.toName("this")));
+ JCMethodInvocation invokeFillMethod = maker.Apply(List.<JCExpression>nil(), maker.Select(newClass, job.toName(FILL_VALUES_METHOD_NAME)), methodArgs);
JCStatement statement = maker.Return(invokeFillMethod);
JCBlock body = maker.Block(0, List.<JCStatement>of(statement));
@@ -602,16 +640,16 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
// Add any type params of the annotated class to the return type.
ListBuffer<JCExpression> typeParameterNames = new ListBuffer<JCExpression>();
- typeParameterNames.addAll(typeParameterNames(maker, typeParams));
+ typeParameterNames.addAll(typeParameterNames(maker, job.typeParams));
// Now add the <?, ?>.
JCWildcard wildcard = maker.Wildcard(maker.TypeBoundKind(BoundKind.UNBOUND), null);
typeParameterNames.add(wildcard);
typeParameterNames.add(wildcard);
- JCTypeApply returnType = maker.TypeApply(namePlusTypeParamsToTypeReference(maker, type, type.toName(builderClassName), false, List.<JCTypeParameter>nil()), typeParameterNames.toList());
+ JCTypeApply returnType = maker.TypeApply(namePlusTypeParamsToTypeReference(maker, job.parentType, job.toName(job.builderAbstractClassName), false, List.<JCTypeParameter>nil()), typeParameterNames.toList());
- List<JCAnnotation> annsOnMethod = cfv.generateUnique() ? List.of(maker.Annotation(genTypeRef(type, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE), List.<JCExpression>nil())) : List.<JCAnnotation>nil();
- JCMethodDecl methodDef = maker.MethodDef(maker.Modifiers(modifiers, annsOnMethod), type.toName(TO_BUILDER_METHOD_NAME), returnType, List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null);
- createRelevantNonNullAnnotation(type, methodDef);
+ List<JCAnnotation> annsOnMethod = job.checkerFramework.generateUnique() ? List.of(maker.Annotation(genTypeRef(job.parentType, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE), List.<JCExpression>nil())) : List.<JCAnnotation>nil();
+ JCMethodDecl methodDef = maker.MethodDef(maker.Modifiers(modifiers, annsOnMethod), job.toName(TO_BUILDER_METHOD_NAME), returnType, List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null);
+ createRelevantNonNullAnnotation(job.parentType, methodDef);
return methodDef;
}
@@ -621,43 +659,43 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
* <pre>
* protected B $fillValuesFrom(final C instance) {
* super.$fillValuesFrom(instance);
- * FoobarBuilderImpl.$fillValuesFromInstanceIntoBuilder(instance, this);
+ * FoobarBuilder.$fillValuesFromInstanceIntoBuilder(instance, this);
* return self();
* }
* </pre>
*/
- private JCMethodDecl generateFillValuesMethod(JavacNode type, boolean inherited, String builderGenericName, String classGenericName, String builderImplClassName) {
- JavacTreeMaker maker = type.getTreeMaker();
+ private JCMethodDecl generateFillValuesMethod(SuperBuilderJob job, boolean inherited, String builderGenericName, String classGenericName) {
+ JavacTreeMaker maker = job.getTreeMaker();
List<JCAnnotation> annotations = List.nil();
if (inherited) {
- JCAnnotation overrideAnnotation = maker.Annotation(genJavaLangTypeRef(type, "Override"), List.<JCExpression>nil());
+ JCAnnotation overrideAnnotation = maker.Annotation(genJavaLangTypeRef(job.builderType, "Override"), List.<JCExpression>nil());
annotations = List.of(overrideAnnotation);
}
JCModifiers modifiers = maker.Modifiers(Flags.PROTECTED, annotations);
- Name name = type.toName(FILL_VALUES_METHOD_NAME);
- JCExpression returnType = maker.Ident(type.toName(builderGenericName));
+ Name name = job.toName(FILL_VALUES_METHOD_NAME);
+ JCExpression returnType = maker.Ident(job.toName(builderGenericName));
- JCExpression classGenericNameExpr = maker.Ident(type.toName(classGenericName));
- JCVariableDecl param = maker.VarDef(maker.Modifiers(Flags.LocalVarFlags), type.toName(INSTANCE_VARIABLE_NAME), classGenericNameExpr, null);
+ JCExpression classGenericNameExpr = maker.Ident(job.toName(classGenericName));
+ JCVariableDecl param = maker.VarDef(maker.Modifiers(Flags.PARAMETER | Flags.FINAL), job.toName(INSTANCE_VARIABLE_NAME), classGenericNameExpr, null);
ListBuffer<JCStatement> body = new ListBuffer<JCStatement>();
if (inherited) {
// Call super.
JCMethodInvocation callToSuper = maker.Apply(List.<JCExpression>nil(),
- maker.Select(maker.Ident(type.toName("super")), name),
- List.<JCExpression>of(maker.Ident(type.toName(INSTANCE_VARIABLE_NAME))));
+ maker.Select(maker.Ident(job.toName("super")), name),
+ List.<JCExpression>of(maker.Ident(job.toName(INSTANCE_VARIABLE_NAME))));
body.append(maker.Exec(callToSuper));
}
// Call the builder implemention's helper method that actually fills the values from the instance.
- JCExpression ref = namePlusTypeParamsToTypeReference(maker, type, type.toName(builderImplClassName), false, List.<JCTypeParameter>nil());
+ JCExpression ref = namePlusTypeParamsToTypeReference(maker, job.parentType, job.getBuilderClassName(), false, List.<JCTypeParameter>nil());
JCMethodInvocation callStaticFillValuesMethod = maker.Apply(List.<JCExpression>nil(),
- maker.Select(ref, type.toName(STATIC_FILL_VALUES_METHOD_NAME)),
- List.<JCExpression>of(maker.Ident(type.toName(INSTANCE_VARIABLE_NAME)), maker.Ident(type.toName("this"))));
+ maker.Select(ref, job.toName(STATIC_FILL_VALUES_METHOD_NAME)),
+ List.<JCExpression>of(maker.Ident(job.toName(INSTANCE_VARIABLE_NAME)), maker.Ident(job.toName("this"))));
body.append(maker.Exec(callStaticFillValuesMethod));
- JCReturn returnStatement = maker.Return(maker.Apply(List.<JCExpression>nil(), maker.Ident(type.toName(SELF_METHOD)), List.<JCExpression>nil()));
+ JCReturn returnStatement = maker.Return(maker.Apply(List.<JCExpression>nil(), maker.Ident(job.toName(SELF_METHOD)), List.<JCExpression>nil()));
body.append(returnStatement);
JCBlock bodyBlock = maker.Block(0, body.toList());
@@ -674,40 +712,39 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
* b.field(instance.field);
* }
* </pre>
- * @param setterPrefix the prefix for setter methods
*/
- private JCMethodDecl generateStaticFillValuesMethod(JavacNode type, String builderClassname, List<JCTypeParameter> typeParams, java.util.List<BuilderFieldData> builderFields, String setterPrefix) {
- JavacTreeMaker maker = type.getTreeMaker();
+ private JCMethodDecl generateStaticFillValuesMethod(SuperBuilderJob job, String setterPrefix) {
+ JavacTreeMaker maker = job.getTreeMaker();
List<JCAnnotation> annotations = List.nil();
JCModifiers modifiers = maker.Modifiers(Flags.PRIVATE | Flags.STATIC, annotations);
- Name name = type.toName(STATIC_FILL_VALUES_METHOD_NAME);
+ Name name = job.toName(STATIC_FILL_VALUES_METHOD_NAME);
JCExpression returnType = maker.TypeIdent(CTC_VOID);
// 1st parameter: "Foobar instance"
- JCVariableDecl paramInstance = maker.VarDef(maker.Modifiers(Flags.LocalVarFlags), type.toName(INSTANCE_VARIABLE_NAME), cloneSelfType(type), null);
+ JCVariableDecl paramInstance = maker.VarDef(maker.Modifiers(Flags.PARAMETER | Flags.FINAL), job.toName(INSTANCE_VARIABLE_NAME), cloneSelfType(job.parentType), null);
// 2nd parameter: "FoobarBuilder<?, ?> b" (plus generics on the annotated type)
// First add all generics that are present on the parent type.
- ListBuffer<JCExpression> typeParamsForBuilderParameter = getTypeParamExpressions(typeParams, maker, type.getContext());
+ ListBuffer<JCExpression> typeParamsForBuilderParameter = getTypeParamExpressions(job.typeParams, maker, job.getContext());
// Now add the <?, ?>.
JCWildcard wildcard = maker.Wildcard(maker.TypeBoundKind(BoundKind.UNBOUND), null);
typeParamsForBuilderParameter.add(wildcard);
wildcard = maker.Wildcard(maker.TypeBoundKind(BoundKind.UNBOUND), null);
typeParamsForBuilderParameter.add(wildcard);
- JCTypeApply builderType = maker.TypeApply(namePlusTypeParamsToTypeReference(maker, type, type.toName(builderClassname), false, List.<JCTypeParameter>nil()), typeParamsForBuilderParameter.toList());
- JCVariableDecl paramBuilder = maker.VarDef(maker.Modifiers(Flags.LocalVarFlags), type.toName(BUILDER_VARIABLE_NAME), builderType, null);
-
+ JCTypeApply builderType = maker.TypeApply(namePlusTypeParamsToTypeReference(maker, job.parentType, job.getBuilderClassName(), false, List.<JCTypeParameter>nil()), typeParamsForBuilderParameter.toList());
+ JCVariableDecl paramBuilder = maker.VarDef(maker.Modifiers(Flags.PARAMETER | Flags.FINAL), job.toName(BUILDER_VARIABLE_NAME), builderType, null);
+
ListBuffer<JCStatement> body = new ListBuffer<JCStatement>();
// Call the builder's setter methods to fill the values from the instance.
- for (BuilderFieldData bfd : builderFields) {
- JCExpressionStatement exec = createSetterCallWithInstanceValue(bfd, type, maker, setterPrefix);
+ for (BuilderFieldData bfd : job.builderFields) {
+ JCExpressionStatement exec = createSetterCallWithInstanceValue(bfd, job.parentType, maker, setterPrefix);
body.append(exec);
}
JCBlock bodyBlock = maker.Block(0, body.toList());
-
- return maker.MethodDef(modifiers, name, returnType, copyTypeParams(type, typeParams), List.of(paramInstance, paramBuilder), List.<JCExpression>nil(), bodyBlock, null);
+
+ return maker.MethodDef(modifiers, name, returnType, copyTypeParams(job.builderType, job.typeParams), List.of(paramInstance, paramBuilder), List.<JCExpression>nil(), bodyBlock, null);
}
private JCExpressionStatement createSetterCallWithInstanceValue(BuilderFieldData bfd, JavacNode type, JavacTreeMaker maker, String setterPrefix) {
@@ -747,80 +784,91 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
return exec;
}
- private JCMethodDecl generateAbstractSelfMethod(CheckerFrameworkVersion cfv, JavacNode type, boolean override, String builderGenericName) {
- JavacTreeMaker maker = type.getTreeMaker();
+ private JCMethodDecl generateAbstractSelfMethod(SuperBuilderJob job, boolean override, String builderGenericName) {
+ JavacTreeMaker maker = job.getTreeMaker();
List<JCAnnotation> annotations = List.nil();
- 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.generatePure() ? maker.Annotation(genTypeRef(type, CheckerFrameworkVersion.NAME__PURE), List.<JCExpression>nil()) : null;
+ JCAnnotation overrideAnnotation = override ? maker.Annotation(genJavaLangTypeRef(job.builderType, "Override"), List.<JCExpression>nil()) : null;
+ JCAnnotation rrAnnotation = job.checkerFramework.generateReturnsReceiver() ? maker.Annotation(genTypeRef(job.builderType, CheckerFrameworkVersion.NAME__RETURNS_RECEIVER), List.<JCExpression>nil()) : null;
+ JCAnnotation sefAnnotation = job.checkerFramework.generatePure() ? maker.Annotation(genTypeRef(job.builderType, CheckerFrameworkVersion.NAME__PURE), 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));
+ Name name = job.toName(SELF_METHOD);
+ JCExpression returnType = maker.Ident(job.toName(builderGenericName));
return maker.MethodDef(modifiers, name, returnType, List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), null, null);
}
- private JCMethodDecl generateSelfMethod(CheckerFrameworkVersion cfv, JavacNode builderImplType, List<JCTypeParameter> typeParams) {
- JavacTreeMaker maker = builderImplType.getTreeMaker();
+ private JCMethodDecl generateSelfMethod(SuperBuilderJob job) {
+ JavacTreeMaker maker = job.getTreeMaker();
- JCAnnotation overrideAnnotation = maker.Annotation(genJavaLangTypeRef(builderImplType, "Override"), List.<JCExpression>nil());
- JCAnnotation rrAnnotation = cfv.generateReturnsReceiver() ? maker.Annotation(genTypeRef(builderImplType, CheckerFrameworkVersion.NAME__RETURNS_RECEIVER), List.<JCExpression>nil()) : null;
- JCAnnotation sefAnnotation = cfv.generatePure() ? maker.Annotation(genTypeRef(builderImplType, CheckerFrameworkVersion.NAME__PURE), List.<JCExpression>nil()) : null;
+ JCAnnotation overrideAnnotation = maker.Annotation(genJavaLangTypeRef(job.builderType, "Override"), List.<JCExpression>nil());
+ JCAnnotation rrAnnotation = job.checkerFramework.generateReturnsReceiver() ? maker.Annotation(genTypeRef(job.builderType, CheckerFrameworkVersion.NAME__RETURNS_RECEIVER), List.<JCExpression>nil()) : null;
+ JCAnnotation sefAnnotation = job.checkerFramework.generatePure() ? maker.Annotation(genTypeRef(job.builderType, CheckerFrameworkVersion.NAME__PURE), 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);
+ Name name = job.toName(SELF_METHOD);
- JCExpression returnType = namePlusTypeParamsToTypeReference(maker, builderImplType.up(), builderImplType.toName(builderImplType.getName()), false, typeParams);
- JCStatement statement = maker.Return(maker.Ident(builderImplType.toName("this")));
+ JCExpression returnType = namePlusTypeParamsToTypeReference(maker, job.builderType.up(), job.getBuilderClassName(), false, job.typeParams);
+ JCStatement statement = maker.Return(maker.Ident(job.toName("this")));
JCBlock body = maker.Block(0, List.<JCStatement>of(statement));
return maker.MethodDef(modifiers, name, returnType, List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null);
}
- private JCMethodDecl generateAbstractBuildMethod(CheckerFrameworkVersion cfv, JavacNode type, String methodName, java.util.List<BuilderFieldData> builderFields, boolean override, String classGenericName) {
- JavacTreeMaker maker = type.getTreeMaker();
+ private JCMethodDecl generateAbstractBuildMethod(SuperBuilderJob job, boolean override, String classGenericName) {
+ JavacTreeMaker maker = job.getTreeMaker();
List<JCAnnotation> annotations = List.nil();
if (override) {
- JCAnnotation overrideAnnotation = maker.Annotation(genJavaLangTypeRef(type, "Override"), List.<JCExpression>nil());
+ JCAnnotation overrideAnnotation = maker.Annotation(genJavaLangTypeRef(job.builderType, "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()));
+ if (job.checkerFramework.generateSideEffectFree()) annotations = annotations.prepend(maker.Annotation(genTypeRef(job.builderType, 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));
+ Name name = job.toName(job.buildMethodName);
+ JCExpression returnType = maker.Ident(job.toName(classGenericName));
- List<JCVariableDecl> params = HandleBuilder.generateBuildArgs(cfv, type, builderFields);
- return maker.MethodDef(modifiers, name, returnType, List.<JCTypeParameter>nil(), params, List.<JCExpression>nil(), null, null);
+ JCVariableDecl recv = HandleBuilder.generateReceiver(job);
+ JCMethodDecl methodDef;
+ if (recv != null && maker.hasMethodDefWithRecvParam()) {
+ methodDef = maker.MethodDefWithRecvParam(modifiers, name, returnType, List.<JCTypeParameter>nil(), recv, List.<JCVariableDecl>nil(), List.<JCExpression>nil(), null, null);
+ } else {
+ methodDef = maker.MethodDef(modifiers, name, returnType, List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), null, null);
+ }
+ return methodDef;
}
-
- private JCMethodDecl generateBuildMethod(CheckerFrameworkVersion cfv, String buildName, JavacNode returnType, JavacNode type, java.util.List<BuilderFieldData> builderFields, List<JCExpression> thrownExceptions) {
- JavacTreeMaker maker = type.getTreeMaker();
+
+ private JCMethodDecl generateBuildMethod(SuperBuilderJob job, List<JCExpression> thrownExceptions) {
+ JavacTreeMaker maker = job.getTreeMaker();
JCExpression call;
ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>();
// Use a constructor that only has this builder as parameter.
- List<JCExpression> builderArg = List.<JCExpression>of(maker.Ident(type.toName("this")));
- call = maker.NewClass(null, List.<JCExpression>nil(), cloneSelfType(returnType), builderArg, null);
+ List<JCExpression> builderArg = List.<JCExpression>of(maker.Ident(job.toName("this")));
+ call = maker.NewClass(null, List.<JCExpression>nil(), cloneSelfType(job.parentType), builderArg, null);
statements.append(maker.Return(call));
JCBlock body = maker.Block(0, statements.toList());
- JCAnnotation overrideAnnotation = maker.Annotation(genJavaLangTypeRef(type, "Override"), List.<JCExpression>nil());
+ JCAnnotation overrideAnnotation = maker.Annotation(genJavaLangTypeRef(job.builderType, "Override"), List.<JCExpression>nil());
List<JCAnnotation> annsOnMethod = List.of(overrideAnnotation);
- if (cfv.generateSideEffectFree()) annsOnMethod = annsOnMethod.prepend(maker.Annotation(genTypeRef(type, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE), List.<JCExpression>nil()));
+ if (job.checkerFramework.generateSideEffectFree()) annsOnMethod = annsOnMethod.prepend(maker.Annotation(genTypeRef(job.builderType, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE), List.<JCExpression>nil()));
JCModifiers modifiers = maker.Modifiers(Flags.PUBLIC, annsOnMethod);
- List<JCVariableDecl> params = HandleBuilder.generateBuildArgs(cfv, type, builderFields);
- JCMethodDecl methodDef = maker.MethodDef(modifiers, type.toName(buildName), cloneSelfType(returnType), List.<JCTypeParameter>nil(), params, thrownExceptions, body, null);
- createRelevantNonNullAnnotation(type, methodDef);
+ JCVariableDecl recv = HandleBuilder.generateReceiver(job);
+ JCMethodDecl methodDef;
+ if (recv != null && maker.hasMethodDefWithRecvParam()) {
+ methodDef = maker.MethodDefWithRecvParam(modifiers, job.toName(job.buildMethodName), cloneSelfType(job.parentType), List.<JCTypeParameter>nil(), recv, List.<JCVariableDecl>nil(), thrownExceptions, body, null);
+ } else {
+ methodDef = maker.MethodDef(modifiers, job.toName(job.buildMethodName), cloneSelfType(job.parentType), List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), thrownExceptions, body, null);
+ }
+ createRelevantNonNullAnnotation(job.builderType, methodDef);
return methodDef;
}
@@ -878,29 +926,30 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
for (JCVariableDecl gen : generated) recursiveSetGeneratedBy(gen, source, builderType.getContext());
}
- private void generateSetterMethodsForBuilder(CheckerFrameworkVersion cfv, final JavacNode builderType, BuilderFieldData fieldNode, JavacNode source, final String builderGenericName, String setterPrefix) {
+ private void generateSetterMethodsForBuilder(final SuperBuilderJob job, BuilderFieldData fieldNode, final String builderGenericName, String setterPrefix) {
boolean deprecate = isFieldDeprecated(fieldNode.originalFieldNode);
- final JavacTreeMaker maker = builderType.getTreeMaker();
+ final JavacTreeMaker maker = job.getTreeMaker();
ExpressionMaker returnTypeMaker = new ExpressionMaker() { @Override public JCExpression make() {
- return maker.Ident(builderType.toName(builderGenericName));
+ return maker.Ident(job.toName(builderGenericName));
}};
StatementMaker returnStatementMaker = new StatementMaker() { @Override public JCStatement make() {
- return maker.Return(maker.Apply(List.<JCExpression>nil(), maker.Ident(builderType.toName(SELF_METHOD)), List.<JCExpression>nil()));
+ return maker.Return(maker.Apply(List.<JCExpression>nil(), maker.Ident(job.toName(SELF_METHOD)), List.<JCExpression>nil()));
}};
if (fieldNode.singularData == null || fieldNode.singularData.getSingularizer() == null) {
- generateSimpleSetterMethodForBuilder(cfv, builderType, deprecate, fieldNode.createdFields.get(0), fieldNode.name, fieldNode.nameOfSetFlag, source, returnTypeMaker.make(), returnStatementMaker.make(), fieldNode.annotations, fieldNode.originalFieldNode, setterPrefix);
+ generateSimpleSetterMethodForBuilder(job, deprecate, fieldNode.createdFields.get(0), fieldNode.name, fieldNode.nameOfSetFlag, returnTypeMaker.make(), returnStatementMaker.make(), fieldNode.annotations, fieldNode.originalFieldNode, setterPrefix);
} else {
- fieldNode.singularData.getSingularizer().generateMethods(cfv, fieldNode.singularData, deprecate, builderType, source.get(), true, returnTypeMaker, returnStatementMaker, AccessLevel.PUBLIC);
+ fieldNode.singularData.getSingularizer().generateMethods(job.checkerFramework, fieldNode.singularData, deprecate, job.builderType,
+ job.source, true, returnTypeMaker, returnStatementMaker, AccessLevel.PUBLIC);
}
}
- private void generateSimpleSetterMethodForBuilder(CheckerFrameworkVersion cfv, JavacNode builderType, boolean deprecate, JavacNode fieldNode, Name paramName, Name nameOfSetFlag, JavacNode source, JCExpression returnType, JCStatement returnStatement, List<JCAnnotation> annosOnParam, JavacNode originalFieldNode, String setterPrefix) {
+ private void generateSimpleSetterMethodForBuilder(SuperBuilderJob job, boolean deprecate, JavacNode fieldNode, Name paramName, Name nameOfSetFlag, JCExpression returnType, JCStatement returnStatement, List<JCAnnotation> annosOnParam, JavacNode originalFieldNode, String setterPrefix) {
String setterName = HandlerUtil.buildAccessorName(setterPrefix, paramName.toString());
- Name setterName_ = builderType.toName(setterName);
+ Name setterName_ = job.builderType.toName(setterName);
- for (JavacNode child : builderType.down()) {
+ for (JavacNode child : job.builderType.down()) {
if (child.getKind() != Kind.METHOD) continue;
JCMethodDecl methodDecl = (JCMethodDecl) child.get();
Name existingName = methodDecl.name;
@@ -910,23 +959,24 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
JavacTreeMaker maker = fieldNode.getTreeMaker();
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();
- JCExpression selfType = namePlusTypeParamsToTypeReference(maker, builderType, builderTypeNode.typarams);
- JCVariableDecl recv = maker.VarDef(maker.Modifiers(0L, List.<JCAnnotation>of(ncAnno)), builderType.toName("this"), selfType, null);
- newMethod.params = List.of(recv, newMethod.params.get(0));
+ JCMethodDecl newMethod = null;
+ if (job.checkerFramework.generateCalledMethods() && maker.hasMethodDefWithRecvParam()) {
+ JCAnnotation ncAnno = maker.Annotation(genTypeRef(job.sourceNode, CheckerFrameworkVersion.NAME__NOT_CALLED), List.<JCExpression>of(maker.Literal(setterName.toString())));
+ JCClassDecl builderTypeNode = (JCClassDecl) job.builderType.get();
+ JCExpression selfType = namePlusTypeParamsToTypeReference(maker, job.builderType, builderTypeNode.typarams, List.<JCAnnotation>of(ncAnno));
+ JCVariableDecl recv = maker.VarDef(maker.Modifiers(0L, List.<JCAnnotation>nil()), job.toName("this"), selfType, null);
+ newMethod = HandleSetter.createSetterWithRecv(Flags.PUBLIC, deprecate, fieldNode, maker, setterName, paramName, nameOfSetFlag, returnType, returnStatement, job.sourceNode, methodAnns, annosOnParam, recv);
}
- if (cfv.generateReturnsReceiver()) {
+ if (newMethod == null) newMethod = HandleSetter.createSetter(Flags.PUBLIC, deprecate, fieldNode, maker, setterName, paramName, nameOfSetFlag, returnType, returnStatement, job.sourceNode, methodAnns, annosOnParam);
+ if (job.checkerFramework.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());
+ JCAnnotation anno = maker.Annotation(genTypeRef(job.builderType, CheckerFrameworkVersion.NAME__RETURNS_RECEIVER), List.<JCExpression>nil());
+ recursiveSetGeneratedBy(anno, job.source, job.getContext());
newMethod.mods.annotations = annotations.prepend(anno);
}
- injectMethod(builderType, newMethod);
+ injectMethod(job.builderType, newMethod);
}
private void addObtainVia(BuilderFieldData bfd, JavacNode node) {
diff --git a/src/core/lombok/javac/handlers/JavacSingularsRecipes.java b/src/core/lombok/javac/handlers/JavacSingularsRecipes.java
index 7cd52c8c..2fc9329c 100644
--- a/src/core/lombok/javac/handlers/JavacSingularsRecipes.java
+++ b/src/core/lombok/javac/handlers/JavacSingularsRecipes.java
@@ -57,6 +57,7 @@ import lombok.core.configuration.CheckerFrameworkVersion;
import lombok.core.handlers.HandlerUtil;
import lombok.javac.JavacNode;
import lombok.javac.JavacTreeMaker;
+import lombok.javac.handlers.HandleBuilder.BuilderJob;
public class JavacSingularsRecipes {
public interface ExpressionMaker {
@@ -243,20 +244,22 @@ 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(CheckerFrameworkVersion cfv, SingularData data, boolean deprecate, final JavacNode builderType, JCTree source, boolean fluent, final boolean chain, AccessLevel access) {
- final JavacTreeMaker maker = builderType.getTreeMaker();
+ public void generateMethods(final BuilderJob job, SingularData data, boolean deprecate) {
+ //job.checkerFramework, job.builderType, job.source, job.oldFluent, job.oldChain, job.accessInners
+ //CheckerFrameworkVersion cfv, final JavacNode builderType, JCTree source, boolean fluent, final boolean chain, AccessLevel access) {
+ final JavacTreeMaker maker = job.builderType.getTreeMaker();
ExpressionMaker returnTypeMaker = new ExpressionMaker() { @Override public JCExpression make() {
- return chain ?
- cloneSelfType(builderType) :
- maker.Type(createVoidType(builderType.getSymbolTable(), CTC_VOID));
+ return job.oldChain ?
+ cloneSelfType(job.builderType) :
+ maker.Type(createVoidType(job.builderType.getSymbolTable(), CTC_VOID));
}};
StatementMaker returnStatementMaker = new StatementMaker() { @Override public JCStatement make() {
- return chain ? maker.Return(maker.Ident(builderType.toName("this"))) : null;
+ return job.oldChain ? maker.Return(maker.Ident(job.builderType.toName("this"))) : null;
}};
- generateMethods(cfv, data, deprecate, builderType, source, fluent, returnTypeMaker, returnStatementMaker, access);
+ generateMethods(job.checkerFramework, data, deprecate, job.builderType, job.source, job.oldFluent, returnTypeMaker, returnStatementMaker, job.accessInners);
}
/**
diff --git a/src/core/lombok/javac/handlers/singulars/JavacGuavaSingularizer.java b/src/core/lombok/javac/handlers/singulars/JavacGuavaSingularizer.java
index 7cd676c0..dadf881d 100644
--- a/src/core/lombok/javac/handlers/singulars/JavacGuavaSingularizer.java
+++ b/src/core/lombok/javac/handlers/singulars/JavacGuavaSingularizer.java
@@ -151,7 +151,7 @@ abstract class JavacGuavaSingularizer extends JavacSingularizer {
JCExpression init = maker.Conditional(isNull, empty, invokeBuild); // this.pluralName == null ? ImmutableX.of() : this.pluralName.build()
- JCStatement jcs = maker.VarDef(maker.Modifiers(0), data.getPluralName(), varType, init);
+ JCStatement jcs = maker.VarDef(maker.Modifiers(0L), data.getPluralName(), varType, init);
statements.append(jcs);
}
diff --git a/src/core/lombok/javac/handlers/singulars/JavacJavaUtilListSingularizer.java b/src/core/lombok/javac/handlers/singulars/JavacJavaUtilListSingularizer.java
index b4ad3428..1f8bbbe9 100644
--- a/src/core/lombok/javac/handlers/singulars/JavacJavaUtilListSingularizer.java
+++ b/src/core/lombok/javac/handlers/singulars/JavacJavaUtilListSingularizer.java
@@ -89,7 +89,7 @@ public class JavacJavaUtilListSingularizer extends JavacJavaUtilListSetSingulari
JCStatement switchStat = maker.Switch(getSize(maker, builderType, data.getPluralName(), true, false, builderVariable), cases.toList());
JCExpression localShadowerType = chainDotsString(builderType, data.getTargetFqn());
localShadowerType = addTypeArgs(1, false, builderType, localShadowerType, data.getTypeArgs(), source);
- JCStatement varDefStat = maker.VarDef(maker.Modifiers(0), data.getPluralName(), localShadowerType, null);
+ JCStatement varDefStat = maker.VarDef(maker.Modifiers(0L), data.getPluralName(), localShadowerType, null);
statements.append(varDefStat);
statements.append(switchStat);
}
diff --git a/src/core/lombok/javac/handlers/singulars/JavacJavaUtilSingularizer.java b/src/core/lombok/javac/handlers/singulars/JavacJavaUtilSingularizer.java
index 50950915..5670b5e6 100644
--- a/src/core/lombok/javac/handlers/singulars/JavacJavaUtilSingularizer.java
+++ b/src/core/lombok/javac/handlers/singulars/JavacJavaUtilSingularizer.java
@@ -84,7 +84,7 @@ abstract class JavacJavaUtilSingularizer extends JavacSingularizer {
JCStatement switchStat = maker.Switch(getSize(maker, builderType, mapMode ? builderType.toName(data.getPluralName() + "$key") : data.getPluralName(), true, false, builderVariable), cases.toList());
JCExpression localShadowerType = chainDotsString(builderType, data.getTargetFqn());
localShadowerType = addTypeArgs(mapMode ? 2 : 1, false, builderType, localShadowerType, data.getTypeArgs(), source);
- JCStatement varDefStat = maker.VarDef(maker.Modifiers(0), data.getPluralName(), localShadowerType, null);
+ JCStatement varDefStat = maker.VarDef(maker.Modifiers(0L), data.getPluralName(), localShadowerType, null);
return List.of(varDefStat, switchStat);
}
@@ -143,7 +143,7 @@ abstract class JavacJavaUtilSingularizer extends JavacSingularizer {
if (defineVar) {
JCExpression localShadowerType = chainDotsString(builderType, data.getTargetFqn());
localShadowerType = addTypeArgs(mapMode ? 2 : 1, false, builderType, localShadowerType, data.getTypeArgs(), source);
- createStat = maker.VarDef(maker.Modifiers(0), data.getPluralName(), localShadowerType, constructorCall);
+ createStat = maker.VarDef(maker.Modifiers(0L), data.getPluralName(), localShadowerType, constructorCall);
} else {
createStat = maker.Exec(maker.Assign(maker.Ident(data.getPluralName()), constructorCall));
}
@@ -161,7 +161,7 @@ abstract class JavacJavaUtilSingularizer extends JavacSingularizer {
// error: method put in interface Map<K#2,V#2> cannot be applied to given types;
arg2 = maker.TypeCast(createTypeArgs(2, false, builderType, data.getTypeArgs(), source).get(1), arg2);
JCStatement putStatement = maker.Exec(maker.Apply(jceBlank, pluralnameDotPut, List.of(arg1, arg2)));
- JCStatement forInit = maker.VarDef(maker.Modifiers(0), ivar, maker.TypeIdent(CTC_INT), maker.Literal(CTC_INT, 0));
+ JCStatement forInit = maker.VarDef(maker.Modifiers(0L), ivar, maker.TypeIdent(CTC_INT), maker.Literal(CTC_INT, 0));
JCExpression checkExpr = maker.Binary(CTC_LESS_THAN, maker.Ident(ivar), getSize(maker, builderType, keyVarName, nullGuard, true, builderVariable));
JCExpression incrementExpr = maker.Unary(CTC_POSTINC, maker.Ident(ivar));
fillStat = maker.ForLoop(List.of(forInit), checkExpr, List.of(maker.Exec(incrementExpr)), putStatement);