aboutsummaryrefslogtreecommitdiff
path: root/src/core/lombok/eclipse
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/lombok/eclipse')
-rw-r--r--src/core/lombok/eclipse/EcjAugments.java (renamed from src/core/lombok/eclipse/EclipseAugments.java)15
-rw-r--r--src/core/lombok/eclipse/HandlerLibrary.java2
-rw-r--r--src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java46
-rwxr-xr-xsrc/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java9
-rwxr-xr-xsrc/core/lombok/eclipse/handlers/HandleBuilder.java582
-rwxr-xr-xsrc/core/lombok/eclipse/handlers/HandleConstructor.java15
-rw-r--r--src/core/lombok/eclipse/handlers/HandleSuperBuilder.java517
7 files changed, 651 insertions, 535 deletions
diff --git a/src/core/lombok/eclipse/EclipseAugments.java b/src/core/lombok/eclipse/EcjAugments.java
index 783e25c9..965c4fb6 100644
--- a/src/core/lombok/eclipse/EclipseAugments.java
+++ b/src/core/lombok/eclipse/EcjAugments.java
@@ -33,8 +33,8 @@ import org.eclipse.jdt.internal.core.SourceMethod;
import lombok.core.FieldAugment;
-public final class EclipseAugments {
- private EclipseAugments() {
+public final class EcjAugments {
+ private EcjAugments() {
// Prevent instantiation
}
@@ -42,6 +42,13 @@ public final class EclipseAugments {
public static final FieldAugment<ASTNode, Boolean> ASTNode_handled = FieldAugment.augment(ASTNode.class, boolean.class, "lombok$handled");
public static final FieldAugment<ASTNode, ASTNode> ASTNode_generatedBy = FieldAugment.augment(ASTNode.class, ASTNode.class, "$generatedBy");
public static final FieldAugment<Annotation, Boolean> Annotation_applied = FieldAugment.augment(Annotation.class, boolean.class, "lombok$applied");
- public static final FieldAugment<CompilationUnit, Map<String, String>> CompilationUnit_javadoc = FieldAugment.augment(CompilationUnit.class, Map.class, "$javadoc");
- public static final FieldAugment<CompilationUnit, ConcurrentMap<String, List<SourceMethod>>> CompilationUnit_delegateMethods = FieldAugment.augment(CompilationUnit.class, ConcurrentMap.class, "$delegateMethods");
+
+ public static final class EclipseAugments {
+ private EclipseAugments() {
+ // Prevent instantiation
+ }
+
+ public static final FieldAugment<CompilationUnit, Map<String, String>> CompilationUnit_javadoc = FieldAugment.augment(CompilationUnit.class, Map.class, "$javadoc");
+ public static final FieldAugment<CompilationUnit, ConcurrentMap<String, List<SourceMethod>>> CompilationUnit_delegateMethods = FieldAugment.augment(CompilationUnit.class, ConcurrentMap.class, "$delegateMethods");
+ }
}
diff --git a/src/core/lombok/eclipse/HandlerLibrary.java b/src/core/lombok/eclipse/HandlerLibrary.java
index 0e72fb38..8d69325e 100644
--- a/src/core/lombok/eclipse/HandlerLibrary.java
+++ b/src/core/lombok/eclipse/HandlerLibrary.java
@@ -23,7 +23,7 @@ package lombok.eclipse;
import static lombok.eclipse.Eclipse.*;
import static lombok.eclipse.handlers.EclipseHandlerUtil.*;
-import static lombok.eclipse.EclipseAugments.ASTNode_handled;
+import static lombok.eclipse.EcjAugments.ASTNode_handled;
import java.io.IOException;
import java.lang.annotation.Annotation;
diff --git a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java
index d85c2ee8..03f26341 100644
--- a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java
+++ b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java
@@ -23,7 +23,7 @@ package lombok.eclipse.handlers;
import static lombok.core.handlers.HandlerUtil.*;
import static lombok.eclipse.Eclipse.*;
-import static lombok.eclipse.EclipseAugments.*;
+import static lombok.eclipse.EcjAugments.*;
import static lombok.eclipse.handlers.EclipseHandlerUtil.EclipseReflectiveMembers.*;
import java.lang.reflect.Array;
@@ -2649,22 +2649,42 @@ public class EclipseHandlerUtil {
return null;
}
+ private static class EclipseOnlyUtil {
+ public static void setDocComment(CompilationUnitDeclaration cud, TypeDeclaration type, ASTNode node, String doc) {
+ if (cud.compilationResult.compilationUnit instanceof CompilationUnit) {
+ CompilationUnit compilationUnit = (CompilationUnit) cud.compilationResult.compilationUnit;
+ Map<String, String> docs = EclipseAugments.CompilationUnit_javadoc.setIfAbsent(compilationUnit, new HashMap<String, String>());
+
+ if (node instanceof AbstractMethodDeclaration) {
+ AbstractMethodDeclaration methodDeclaration = (AbstractMethodDeclaration) node;
+ String signature = getSignature(type, methodDeclaration);
+ /* Add javadoc start marker, add leading asterisks to each line, add javadoc end marker */
+ docs.put(signature, String.format("/**%n%s%n */", doc.replaceAll("(?m)^", " * ")));
+ }
+ }
+ }
+ }
+
+ private static Boolean eclipseMode;
+ private static boolean eclipseMode() {
+ if (eclipseMode != null) return eclipseMode.booleanValue();
+ try {
+ Class.forName("org.eclipse.jdt.internal.core.CompilationUnit");
+ eclipseMode = true;
+ } catch (Exception e) {
+ eclipseMode = false;
+ }
+ return eclipseMode;
+ }
+
public static void setDocComment(CompilationUnitDeclaration cud, EclipseNode eclipseNode, String doc) {
+ if (!eclipseMode()) return;
setDocComment(cud, (TypeDeclaration) upToTypeNode(eclipseNode).get(), eclipseNode.get(), doc);
}
-
+
public static void setDocComment(CompilationUnitDeclaration cud, TypeDeclaration type, ASTNode node, String doc) {
- if (cud.compilationResult.compilationUnit instanceof CompilationUnit) {
- CompilationUnit compilationUnit = (CompilationUnit) cud.compilationResult.compilationUnit;
- Map<String, String> docs = CompilationUnit_javadoc.setIfAbsent(compilationUnit, new HashMap<String, String>());
-
- if (node instanceof AbstractMethodDeclaration) {
- AbstractMethodDeclaration methodDeclaration = (AbstractMethodDeclaration) node;
- String signature = getSignature(type, methodDeclaration);
- /* Add javadoc start marker, add leading asterisks to each line, add javadoc end marker */
- docs.put(signature, String.format("/**%n%s%n */", doc.replaceAll("(?m)^", " * ")));
- }
- }
+ if (!eclipseMode()) return;
+ EclipseOnlyUtil.setDocComment(cud, type, node, doc);
}
public static String getSignature(TypeDeclaration type, AbstractMethodDeclaration methodDeclaration) {
diff --git a/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java b/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java
index 85243ec1..760f5282 100755
--- a/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java
+++ b/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java
@@ -68,6 +68,7 @@ import lombok.core.SpiLoadUtil;
import lombok.core.TypeLibrary;
import lombok.core.configuration.CheckerFrameworkVersion;
import lombok.eclipse.EclipseNode;
+import lombok.eclipse.handlers.HandleBuilder.BuilderJob;
public class EclipseSingularsRecipes {
public interface TypeReferenceMaker {
@@ -258,20 +259,20 @@ public class EclipseSingularsRecipes {
* If you need more control over the return type and value, use
* {@link #generateMethods(SingularData, boolean, EclipseNode, boolean, TypeReferenceMaker, StatementMaker)}.
*/
- public void generateMethods(CheckerFrameworkVersion cfv, SingularData data, boolean deprecate, final EclipseNode builderType, boolean fluent, final boolean chain, AccessLevel access) {
+ public void generateMethods(final BuilderJob job, SingularData data, boolean deprecate) {
TypeReferenceMaker returnTypeMaker = new TypeReferenceMaker() {
@Override public TypeReference make() {
- return chain ? cloneSelfType(builderType) : TypeReference.baseTypeReference(TypeIds.T_void, 0);
+ return job.oldChain ? cloneSelfType(job.builderType) : TypeReference.baseTypeReference(TypeIds.T_void, 0);
}
};
StatementMaker returnStatementMaker = new StatementMaker() {
@Override public ReturnStatement make() {
- return chain ? new ReturnStatement(new ThisReference(0, 0), 0, 0) : null;
+ return job.oldChain ? new ReturnStatement(new ThisReference(0, 0), 0, 0) : null;
}
};
- generateMethods(cfv, data, deprecate, builderType, fluent, returnTypeMaker, returnStatementMaker, access);
+ generateMethods(job.checkerFramework, data, deprecate, job.builderType, job.oldFluent, returnTypeMaker, returnStatementMaker, job.accessInners);
}
/**
diff --git a/src/core/lombok/eclipse/handlers/HandleBuilder.java b/src/core/lombok/eclipse/handlers/HandleBuilder.java
index 9e6c28e8..f8eb9ed0 100755
--- a/src/core/lombok/eclipse/handlers/HandleBuilder.java
+++ b/src/core/lombok/eclipse/handlers/HandleBuilder.java
@@ -25,7 +25,6 @@ import static lombok.core.handlers.HandlerUtil.*;
import static lombok.eclipse.Eclipse.*;
import static lombok.eclipse.handlers.EclipseHandlerUtil.*;
-import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -107,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;
@@ -117,6 +124,95 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
return ((Boolean) expr).booleanValue();
}
+ static class BuilderJob {
+ CheckerFrameworkVersion checkerFramework;
+ 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;
+
+ EclipseNode builderType;
+ String builderClassName;
+ char[] builderClassNameArr;
+
+ void setBuilderClassName(String builderClassName) {
+ this.builderClassName = builderClassName;
+ this.builderClassNameArr = builderClassName.toCharArray();
+ }
+
+ TypeParameter[] copyTypeParams() {
+ return EclipseHandlerUtil.copyTypeParams(typeParams, source);
+ }
+
+ long getPos() {
+ return ((long) source.sourceStart) << 32 | source.sourceEnd;
+ }
+
+ public TypeReference createBuilderTypeReference() {
+ return namePlusTypeParamsToTypeReference(parentType, builderClassNameArr, !isStatic, builderTypeParams, getPos());
+ }
+
+ public TypeReference createBuilderTypeReferenceForceStatic() {
+ return namePlusTypeParamsToTypeReference(parentType, builderClassNameArr, false, builderTypeParams, getPos());
+ }
+
+ public TypeReference createBuilderParentTypeReference() {
+ return namePlusTypeParamsToTypeReference(parentType, typeParams, getPos());
+ }
+
+ public EclipseNode getTopNode() {
+ return parentType.top();
+ }
+
+ void init(AnnotationValues<Builder> annValues, Builder ann, EclipseNode 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;
+
+ // These exist just to support the 'old' lombok.experimental.Builder, which had these properties. lombok.Builder no longer has them.
+ oldFluent = toBoolean(annValues.getActualExpression("fluent"), true);
+ oldChain = toBoolean(annValues.getActualExpression("chain"), true);
+
+ builderMethodName = ann.builderMethodName();
+ buildMethodName = ann.buildMethodName();
+ setBuilderClassName(fixBuilderClassName(node, ann.builderClassName()));
+ toBuilder = ann.toBuilder();
+
+ if (builderMethodName == null) builderMethodName = "builder";
+ if (buildMethodName == null) buildMethodName = "build";
+ }
+
+ 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 {
Annotation[] annotations;
TypeReference type;
@@ -151,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);
@@ -164,87 +256,57 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
@Override public void handle(AnnotationValues<Builder> annotation, Annotation ast, EclipseNode annotationNode) {
handleFlagUsage(annotationNode, ConfigurationKeys.BUILDER_FLAG_USAGE, "@Builder");
- CheckerFrameworkVersion cfv = getCheckerFrameworkVersion(annotationNode);
+ BuilderJob job = new BuilderJob();
+ job.sourceNode = annotationNode;
+ job.source = ast;
+ job.checkerFramework = getCheckerFrameworkVersion(annotationNode);
+ job.isStatic = true;
- long p = (long) ast.sourceStart << 32 | ast.sourceEnd;
-
- Builder builderInstance = annotation.getInstance();
- AccessLevel accessForOuters = builderInstance.access();
- if (accessForOuters == null) accessForOuters = AccessLevel.PUBLIC;
- if (builderInstance.access() == 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();
+ Builder annInstance = annotation.getInstance();
+ job.init(annotation, annInstance, annotationNode);
List<char[]> 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;
EclipseNode parent = annotationNode.up();
- List<BuilderFieldData> builderFields = new ArrayList<BuilderFieldData>();
- TypeReference returnType;
- TypeParameter[] typeParams;
- TypeReference[] thrownExceptions;
- char[] nameOfStaticBuilderMethod;
- EclipseNode tdParent;
+ job.builderFields = new ArrayList<BuilderFieldData>();
+ TypeReference buildMethodReturnType;
+ TypeReference[] buildMethodThrownExceptions;
+ char[] nameOfBuilderMethod;
EclipseNode fillParametersFrom = parent.get() instanceof AbstractMethodDeclaration ? parent : null;
boolean addCleaning = false;
- boolean isStatic = true;
List<EclipseNode> 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 TypeDeclaration) {
- tdParent = parent;
- TypeDeclaration td = (TypeDeclaration) tdParent.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(tdParent, 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, builderInstance.setterPrefix());
+ bfd.singularData = getSingularData(fieldNode, ast, annInstance.setterPrefix());
bfd.originalFieldNode = fieldNode;
if (bfd.singularData != null && isDefault != null) {
@@ -269,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(tdParent, md);
+ if (md != null) injectMethod(parent, md);
}
addObtainVia(bfd, fieldNode);
- builderFields.add(bfd);
+ job.builderFields.add(bfd);
allFields.add(fieldNode);
}
- handleConstructor.generateConstructor(tdParent, 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);
- returnType = namePlusTypeParamsToTypeReference(tdParent, td.typeParameters, p);
- typeParams = td.typeParameters;
- thrownExceptions = null;
- nameOfStaticBuilderMethod = null;
- if (replaceNameInBuilderClassName) builderClassName = builderClassName.replace("*", new String(td.name));
- replaceNameInBuilderClassName = false;
+ job.typeParams = job.builderTypeParams = td.typeParameters;
+ buildMethodReturnType = job.createBuilderParentTypeReference();
+ buildMethodThrownExceptions = null;
+ 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) {
@@ -292,21 +354,20 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
return;
}
- tdParent = parent.up();
- TypeDeclaration td = (TypeDeclaration) tdParent.get();
- returnType = namePlusTypeParamsToTypeReference(tdParent, td.typeParameters, p);
- typeParams = td.typeParameters;
- thrownExceptions = cd.thrownExceptions;
- nameOfStaticBuilderMethod = null;
- if (replaceNameInBuilderClassName) builderClassName = builderClassName.replace("*", new String(cd.selector));
- replaceNameInBuilderClassName = false;
+ job.parentType = parent.up();
+ TypeDeclaration td = (TypeDeclaration) job.parentType.get();
+ job.typeParams = job.builderTypeParams = td.typeParameters;
+ buildMethodReturnType = job.createBuilderParentTypeReference();
+ buildMethodThrownExceptions = cd.thrownExceptions;
+ 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();
- tdParent = parent.up();
- isStatic = md.isStatic();
+ job.parentType = parent.up();
+ job.isStatic = md.isStatic();
- if (toBuilder) {
- final String TO_BUILDER_NOT_SUPPORTED = "@Builder(toBuilder=true) is only supported if you return your own type.";
+ if (job.toBuilder) {
char[] token;
char[][] pkg = null;
if (md.returnType.dimensions() > 0) {
@@ -332,12 +393,12 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
return;
}
- if (tdParent == null || !equals(tdParent.getName(), token)) {
+ if (job.parentType == null || !equals(job.parentType.getName(), token)) {
annotationNode.addError(TO_BUILDER_NOT_SUPPORTED);
return;
}
- TypeParameter[] tpOnType = ((TypeDeclaration) tdParent.get()).typeParameters;
+ TypeParameter[] tpOnType = ((TypeDeclaration) job.parentType.get()).typeParameters;
TypeParameter[] tpOnMethod = md.typeParameters;
TypeReference[][] tpOnRet_ = null;
if (md.returnType instanceof ParameterizedSingleTypeReference) {
@@ -376,15 +437,15 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
}
}
- returnType = copyType(md.returnType, ast);
- typeParams = md.typeParameters;
- thrownExceptions = md.thrownExceptions;
- nameOfStaticBuilderMethod = md.selector;
- if (replaceNameInBuilderClassName) {
- char[] token = returnTypeToBuilderClassName(annotationNode, md, typeParams);
- if (token == null)
- return;
- builderClassName = builderClassName.replace("*", new String(token));
+ job.typeParams = job.builderTypeParams = md.typeParameters;
+ buildMethodReturnType = copyType(md.returnType, ast);
+ buildMethodThrownExceptions = md.thrownExceptions;
+ nameOfBuilderMethod = md.selector;
+ if (job.builderClassName.indexOf('*') > -1) {
+ char[] token = returnTypeToBuilderClassName(annotationNode, md, job.typeParams);
+ 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.");
@@ -404,40 +465,39 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
bfd.builderFieldName = bfd.name;
bfd.annotations = copyAnnotations(arg, copyableAnnotations);
bfd.type = arg.type;
- bfd.singularData = getSingularData(param, ast, builderInstance.setterPrefix());
+ bfd.singularData = getSingularData(param, ast, annInstance.setterPrefix());
bfd.originalFieldNode = param;
addObtainVia(bfd, param);
- builderFields.add(bfd);
+ job.builderFields.add(bfd);
}
}
- EclipseNode builderType = findInnerClass(tdParent, builderClassName);
- if (builderType == null) {
- builderType = makeBuilderClass(isStatic, tdParent, builderClassName, typeParams, ast, accessForOuters);
- } else {
- TypeDeclaration builderTypeDeclaration = (TypeDeclaration) builderType.get();
- if (isStatic && (builderTypeDeclaration.modifiers & ClassFileConstants.AccStatic) == 0) {
+ job.builderType = findInnerClass(job.parentType, job.builderClassName);
+ if (job.builderType == null) makeBuilderClass(job);
+ else {
+ TypeDeclaration builderTypeDeclaration = (TypeDeclaration) job.builderType.get();
+ if (job.isStatic && (builderTypeDeclaration.modifiers & ClassFileConstants.AccStatic) == 0) {
annotationNode.addError("Existing Builder must be a static inner class.");
return;
- } else if (!isStatic && (builderTypeDeclaration.modifiers & ClassFileConstants.AccStatic) != 0) {
+ } else if (!job.isStatic && (builderTypeDeclaration.modifiers & ClassFileConstants.AccStatic) != 0) {
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;
EclipseSingularizer 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;
@@ -456,64 +516,64 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
}
}
- generateBuilderFields(builderType, builderFields, ast);
+ 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);
cleanDecl.traverse(new SetGeneratedByVisitor(ast), (MethodScope) null);
- injectFieldAndMarkGenerated(builderType, cleanDecl);
+ injectFieldAndMarkGenerated(job.builderType, cleanDecl);
}
- if (constructorExists(builderType) == MemberExistsResult.NOT_EXISTS) {
+ if (constructorExists(job.builderType) == MemberExistsResult.NOT_EXISTS) {
ConstructorDeclaration cd = HandleConstructor.createConstructor(
- AccessLevel.PACKAGE, builderType, Collections.<EclipseNode>emptyList(), false,
+ AccessLevel.PACKAGE, job.builderType, Collections.<EclipseNode>emptyList(), false,
annotationNode, Collections.<Annotation>emptyList());
- if (cd != null) injectMethod(builderType, cd);
+ if (cd != null) injectMethod(job.builderType, cd);
}
- for (BuilderFieldData bfd : builderFields) {
- makePrefixedSetterMethodsForBuilder(cfv, builderType, bfd, annotationNode, fluent, chain, accessForInners, bfd.originalFieldNode, 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) {
- MethodDeclaration md = generateBuildMethod(cfv, tdParent, isStatic, buildMethodName, nameOfStaticBuilderMethod, returnType, builderFields, builderType, thrownExceptions, addCleaning, ast, accessForInners);
- if (md != null) injectMethod(builderType, md);
+ MethodDeclaration md = generateBuildMethod(job, nameOfBuilderMethod, buildMethodReturnType, buildMethodThrownExceptions, addCleaning);
+ if (md != null) injectMethod(job.builderType, md);
}
}
- 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));
}
}
- MethodDeclaration md = HandleToString.createToString(builderType, fieldNodes, true, false, ast, FieldAccess.ALWAYS_FIELD);
- if (md != null) injectMethod(builderType, md);
+ MethodDeclaration md = HandleToString.createToString(job.builderType, fieldNodes, true, false, ast, FieldAccess.ALWAYS_FIELD);
+ if (md != null) injectMethod(job.builderType, md);
}
if (addCleaning) {
- MethodDeclaration cleanMethod = generateCleanMethod(builderFields, builderType, ast);
- if (cleanMethod != null) injectMethod(builderType, cleanMethod);
+ MethodDeclaration cleanMethod = generateCleanMethod(job);
+ if (cleanMethod != null) injectMethod(job.builderType, cleanMethod);
}
- 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) {
- MethodDeclaration md = generateBuilderMethod(cfv, isStatic, builderMethodName, builderClassName, tdParent, typeParams, ast, accessForOuters);
- if (md != null) injectMethod(tdParent, md);
+ MethodDeclaration md = generateBuilderMethod(job);
+ if (md != null) injectMethod(job.parentType, md);
}
- if (toBuilder) switch (methodExists(toBuilderMethodName, tdParent, 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;
case NOT_EXISTS:
- TypeParameter[] tps = typeParams;
+ TypeParameter[] tps = job.typeParams;
if (typeArgsForToBuilder != null) {
tps = new TypeParameter[typeArgsForToBuilder.size()];
for (int i = 0; i < tps.length; i++) {
@@ -521,9 +581,9 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
tps[i].name = typeArgsForToBuilder.get(i);
}
}
- MethodDeclaration md = generateToBuilderMethod(cfv, isStatic, toBuilderMethodName, builderClassName, tdParent, tps, builderFields, fluent, ast, accessForOuters, builderInstance.setterPrefix());
+ MethodDeclaration md = generateToBuilderMethod(job, tps, annInstance.setterPrefix());
- if (md != null) injectMethod(tdParent, md);
+ if (md != null) injectMethod(job.parentType, md);
}
if (nonFinalNonDefaultedFields != null && generateBuilderMethod) {
@@ -532,7 +592,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
}
}
}
-
+
static char[] returnTypeToBuilderClassName(EclipseNode annotationNode, MethodDeclaration md, TypeParameter[] typeParams) {
char[] token;
if (md.returnType instanceof QualifiedTypeReference) {
@@ -562,26 +622,31 @@ 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(CheckerFrameworkVersion cfv, boolean isStatic, String methodName, String builderClassName, EclipseNode type, TypeParameter[] typeParams, List<BuilderFieldData> builderFields, boolean fluent, ASTNode source, AccessLevel access, String prefix) {
- int pS = source.sourceStart, pE = source.sourceEnd;
- long p = (long) pS << 32 | pE;
+ private MethodDeclaration generateToBuilderMethod(BuilderJob job, TypeParameter[] typeParameters, String prefix) {
+ int pS = job.source.sourceStart, pE = job.source.sourceEnd;
+ long p = job.getPos();
- MethodDeclaration out = new MethodDeclaration(((CompilationUnitDeclaration) type.top().get()).compilationResult);
- out.selector = methodName.toCharArray();
- out.modifiers = toEclipseModifier(access);
+ MethodDeclaration out = job.createNewMethodDeclaration();
+ out.selector = TO_BUILDER_METHOD_NAME;
+ out.modifiers = toEclipseModifier(job.accessOuters);
out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
- out.returnType = namePlusTypeParamsToTypeReference(type, builderClassName.toCharArray(), !isStatic, typeParams, p);
+
+ out.returnType = job.createBuilderTypeReference();
+ 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, builderClassName.toCharArray(), !isStatic, typeParams, p);
+ invoke.type = job.createBuilderTypeReference();
Expression receiver = invoke;
List<Statement> preStatements = null;
List<Statement> postStatements = null;
- for (BuilderFieldData bfd : builderFields) {
+ for (BuilderFieldData bfd : job.builderFields) {
String setterName = new String(bfd.name);
- String setterPrefix = !prefix.isEmpty() ? prefix : fluent ? "" : "set";
+ String setterPrefix = !prefix.isEmpty() ? prefix : job.oldFluent ? "" : "set";
if (!setterPrefix.isEmpty()) setterName = HandlerUtil.buildAccessorName(setterPrefix, setterName);
MessageSend ms = new MessageSend();
@@ -599,13 +664,13 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
boolean obtainIsStatic = bfd.obtainVia.isStatic();
MessageSend obtainExpr = new MessageSend();
if (obtainIsStatic) {
- if (typeParams != null && typeParams.length > 0) {
- obtainExpr.typeArguments = new TypeReference[typeParams.length];
- for (int j = 0; j<typeParams.length; j++) {
- obtainExpr.typeArguments[j] = new SingleTypeReference(typeParams[j].name, 0);
+ if (typeParameters != null && typeParameters.length > 0) {
+ obtainExpr.typeArguments = new TypeReference[typeParameters.length];
+ for (int j = 0; j < typeParameters.length; j++) {
+ obtainExpr.typeArguments[j] = new SingleTypeReference(typeParameters[j].name, 0);
}
}
- obtainExpr.receiver = generateNameReference(type, 0);
+ obtainExpr.receiver = generateNameReference(job.parentType, 0);
} else {
obtainExpr.receiver = new ThisReference(0, 0);
}
@@ -618,7 +683,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
// for ecj so we match what javac's handler does.
LocalDeclaration ld = new LocalDeclaration(bfd.name, 0, 0);
ld.modifiers = ClassFileConstants.AccFinal;
- ld.type = EclipseHandlerUtil.copyType(bfd.type, source);
+ ld.type = EclipseHandlerUtil.copyType(bfd.type, job.source);
ld.initialization = obtainExpr;
if (preStatements == null) preStatements = new ArrayList<Statement>();
preStatements.add(ld);
@@ -647,7 +712,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
LocalDeclaration b = new LocalDeclaration(BUILDER_TEMP_VAR, pS, pE);
out.statements[preSs] = b;
b.modifiers |= ClassFileConstants.AccFinal;
- b.type = namePlusTypeParamsToTypeReference(type, builderClassName.toCharArray(), !isStatic, typeParams, p);
+ b.type = job.createBuilderTypeReference();
b.type.sourceStart = pS; b.type.sourceEnd = pE;
b.initialization = receiver;
out.statements[preSs + postSs + 1] = new ReturnStatement(new SingleNameReference(BUILDER_TEMP_VAR, p), pS, pE);
@@ -657,69 +722,81 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
out.statements[preSs] = new ReturnStatement(receiver, 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;
}
- 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();
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;
}
- static Receiver generateBuildReceiver(CheckerFrameworkVersion cfv, EclipseNode type, List<BuilderFieldData> builderFields, ASTNode source) {
- if (!cfv.generateCalledMethods()) return null;
+ 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;
List<char[]> mandatories = new ArrayList<char[]>();
- for (BuilderFieldData bfd : builderFields) {
+ for (BuilderFieldData bfd : job.builderFields) {
if (bfd.singularData == null && bfd.nameOfSetFlag == null) mandatories.add(bfd.name);
}
if (mandatories.size() == 0) return null;
+
+ int pS = job.source.sourceStart, pE = job.source.sourceEnd;
+
char[][] nameCalled = fromQualifiedName(CheckerFrameworkVersion.NAME__CALLED);
- SingleMemberAnnotation ann = new SingleMemberAnnotation(new QualifiedTypeReference(nameCalled, poss(source, nameCalled.length)), source.sourceStart);
+ SingleMemberAnnotation ann = new SingleMemberAnnotation(new QualifiedTypeReference(nameCalled, poss(job.source, nameCalled.length)), pS);
if (mandatories.size() == 1) {
ann.memberValue = new StringLiteral(mandatories.get(0), 0, 0, 0);
} else {
ArrayInitializer arr = new ArrayInitializer();
- arr.sourceStart = source.sourceStart;
- arr.sourceEnd = source.sourceEnd;
+ arr.sourceStart = pS;
+ arr.sourceEnd = pE;
arr.expressions = new Expression[mandatories.size()];
for (int i = 0; i < arr.expressions.length; i++) {
- arr.expressions[i] = new StringLiteral(mandatories.get(i), source.sourceStart, source.sourceEnd, 0);
+ arr.expressions[i] = new StringLiteral(mandatories.get(i), pS, pE, 0);
}
ann.memberValue = arr;
}
-
- QualifiedTypeReference typeReference = (QualifiedTypeReference) generateTypeReference(type, source.sourceStart);
- typeReference.annotations = new Annotation[typeReference.tokens.length][];
- typeReference.annotations[0] = new Annotation[] {ann};
- return new Receiver(new char[] { 't', 'h', 'i', 's' }, 0, typeReference, null, Modifier.FINAL);
+
+ TypeReference typeReference = job.createBuilderTypeReference();
+ int len = typeReference.getTypeName().length;
+ typeReference.annotations = new Annotation[len][];
+ typeReference.annotations[len - 1] = new Annotation[] {ann};
+ return new Receiver(new char[] { 't', 'h', 'i', 's' }, 0, typeReference, null, 0);
}
- public MethodDeclaration generateBuildMethod(CheckerFrameworkVersion cfv, EclipseNode tdParent, boolean isStatic, String name, char[] staticName, TypeReference returnType, List<BuilderFieldData> builderFields, EclipseNode type, TypeReference[] thrownExceptions, boolean addCleaning, ASTNode source, AccessLevel access) {
- MethodDeclaration out = new MethodDeclaration(((CompilationUnitDeclaration) type.top().get()).compilationResult);
+ public MethodDeclaration generateBuildMethod(BuilderJob job, char[] staticName, TypeReference returnType, TypeReference[] thrownExceptions, boolean addCleaning) {
+ MethodDeclaration out = job.createNewMethodDeclaration();
out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
List<Statement> statements = new ArrayList<Statement>();
@@ -732,14 +809,14 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
statements.add(new IfStatement(notClean, invokeClean, 0, 0));
}
- for (BuilderFieldData bfd : builderFields) {
+ for (BuilderFieldData bfd : job.builderFields) {
if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) {
- bfd.singularData.getSingularizer().appendBuildCode(bfd.singularData, type, statements, bfd.builderFieldName, "this");
+ bfd.singularData.getSingularizer().appendBuildCode(bfd.singularData, job.builderType, statements, bfd.builderFieldName, "this");
}
}
List<Expression> args = new ArrayList<Expression>();
- for (BuilderFieldData bfd : builderFields) {
+ for (BuilderFieldData bfd : job.builderFields) {
if (bfd.nameOfSetFlag != null) {
LocalDeclaration ld = new LocalDeclaration(bfd.builderFieldName, 0, 0);
ld.type = copyType(bfd.type);
@@ -749,11 +826,11 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
statements.add(ld);
MessageSend inv = new MessageSend();
- inv.sourceStart = source.sourceStart;
- inv.sourceEnd = source.sourceEnd;
- inv.receiver = new SingleNameReference(((TypeDeclaration) tdParent.get()).name, 0L);
+ inv.sourceStart = job.source.sourceStart;
+ inv.sourceEnd = job.source.sourceEnd;
+ inv.receiver = new SingleNameReference(((TypeDeclaration) job.parentType.get()).name, 0L);
inv.selector = bfd.nameOfDefaultProvider;
- inv.typeArguments = typeParameterNames(((TypeDeclaration) type.get()).typeParameters);
+ inv.typeArguments = typeParameterNames(((TypeDeclaration) job.builderType.get()).typeParameters);
Assignment defaultAssign = new Assignment(new SingleNameReference(bfd.builderFieldName, 0L), inv, 0);
FieldReference thisSet = new FieldReference(bfd.nameOfSetFlag, 0L);
@@ -777,8 +854,8 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
statements.add(new Assignment(thisUnclean, new TrueLiteral(0, 0), 0));
}
- out.modifiers = toEclipseModifier(access);
- out.selector = name.toCharArray();
+ out.modifiers = toEclipseModifier(job.accessInners);
+ out.selector = job.buildMethodName.toCharArray();
out.thrownExceptions = copyTypes(thrownExceptions);
out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
out.returnType = returnType;
@@ -791,13 +868,13 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
} else {
MessageSend invoke = new MessageSend();
invoke.selector = staticName;
- if (isStatic) {
- invoke.receiver = new SingleNameReference(type.up().getName().toCharArray(), 0);
+ if (job.isStatic) {
+ invoke.receiver = new SingleNameReference(job.builderType.up().getName().toCharArray(), 0);
} else {
- invoke.receiver = new QualifiedThisReference(generateTypeReference(type.up(), 0) , 0, 0);
+ invoke.receiver = new QualifiedThisReference(generateTypeReference(job.builderType.up(), 0) , 0, 0);
}
- invoke.typeArguments = typeParameterNames(((TypeDeclaration) type.get()).typeParameters);
+ invoke.typeArguments = typeParameterNames(((TypeDeclaration) job.builderType.get()).typeParameters);
invoke.arguments = args.isEmpty() ? null : args.toArray(new Expression[0]);
if (returnType instanceof SingleTypeReference && Arrays.equals(TypeConstants.VOID, ((SingleTypeReference) returnType).token)) {
statements.add(invoke);
@@ -806,12 +883,12 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
}
}
out.statements = statements.isEmpty() ? null : statements.toArray(new Statement[0]);
- if (cfv.generateSideEffectFree()) {
- out.annotations = new Annotation[] {generateNamedAnnotation(source, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE)};
+ if (job.checkerFramework.generateSideEffectFree()) {
+ out.annotations = new Annotation[] {generateNamedAnnotation(job.source, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE)};
}
- out.receiver = generateBuildReceiver(cfv, type, builderFields, source);
- if (staticName == null) createRelevantNonNullAnnotation(type, out);
- out.traverse(new SetGeneratedByVisitor(source), (ClassScope) null);
+ out.receiver = generateBuildReceiver(job);
+ if (staticName == null) createRelevantNonNullAnnotation(job.builderType, out);
+ out.traverse(new SetGeneratedByVisitor(job.source), (ClassScope) null);
return out;
}
@@ -842,57 +919,55 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
return out;
}
- public MethodDeclaration generateBuilderMethod(CheckerFrameworkVersion cfv, boolean isStatic, String builderMethodName, String builderClassName, EclipseNode type, TypeParameter[] typeParams, ASTNode source, AccessLevel access) {
- int pS = source.sourceStart, pE = source.sourceEnd;
- long p = (long) pS << 32 | pE;
- char[] builderClassName_ = builderClassName.toCharArray();
+ public MethodDeclaration generateBuilderMethod(BuilderJob job) {
+ int pS = job.source.sourceStart, pE = job.source.sourceEnd;
+ long p = job.getPos();
- MethodDeclaration out = new MethodDeclaration(((CompilationUnitDeclaration) type.top().get()).compilationResult);
- out.selector = builderMethodName.toCharArray();
- out.modifiers = toEclipseModifier(access);
- if (isStatic) out.modifiers |= ClassFileConstants.AccStatic;
+ MethodDeclaration out = job.createNewMethodDeclaration();
+ out.selector = job.builderMethodName.toCharArray();
+ out.modifiers = toEclipseModifier(job.accessOuters);
+ if (job.isStatic) out.modifiers |= ClassFileConstants.AccStatic;
out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
- out.returnType = namePlusTypeParamsToTypeReference(type, builderClassName_, !isStatic, typeParams, p);
- out.typeParameters = copyTypeParams(typeParams, source);
+ out.returnType = job.createBuilderTypeReference();
+ 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)};
+ }
+ out.typeParameters = job.copyTypeParams();
AllocationExpression invoke = new AllocationExpression();
- if (isStatic) {
- invoke.type = namePlusTypeParamsToTypeReference(type, builderClassName_, false, typeParams, p);
+ if (job.isStatic) {
+ invoke.type = job.createBuilderTypeReferenceForceStatic();
out.statements = new Statement[] {new ReturnStatement(invoke, pS, pE)};
} else {
// return this.new Builder();
QualifiedAllocationExpression qualifiedInvoke = new QualifiedAllocationExpression();
qualifiedInvoke.enclosingInstance = new ThisReference(pS, pE);
- if (typeParams == null || typeParams.length == 0) {
- qualifiedInvoke.type = new SingleTypeReference(builderClassName_, p);
+ if (job.typeParams == null || job.typeParams.length == 0) {
+ qualifiedInvoke.type = new SingleTypeReference(job.builderClassNameArr, p);
} else {
- qualifiedInvoke.type = namePlusTypeParamsToTypeReference(null, builderClassName_, false, typeParams, p);
+ qualifiedInvoke.type = namePlusTypeParamsToTypeReference(null, job.builderClassNameArr, false, job.typeParams, p);
}
out.statements = new Statement[] {new ReturnStatement(qualifiedInvoke, pS, pE)};
}
- Annotation uniqueAnn = cfv.generateUnique() ? generateNamedAnnotation(source, CheckerFrameworkVersion.NAME__UNIQUE) : null;
- Annotation sefAnn = cfv.generateSideEffectFree() ? generateNamedAnnotation(source, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE) : null;
- if (uniqueAnn != null && sefAnn != null) {
- out.annotations = new Annotation[] {uniqueAnn, sefAnn};
- } else if (uniqueAnn != null) {
- out.annotations = new Annotation[] {uniqueAnn};
- } else if (sefAnn != null) {
- out.annotations = new Annotation[] {sefAnn};
+ if (job.checkerFramework.generateSideEffectFree()) {
+ out.annotations = new Annotation[] {generateNamedAnnotation(job.source, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE)};
}
- createRelevantNonNullAnnotation(type, out);
- out.traverse(new SetGeneratedByVisitor(source), ((TypeDeclaration) type.get()).scope);
+ createRelevantNonNullAnnotation(job.builderType, out);
+ out.traverse(new SetGeneratedByVisitor(job.source), ((TypeDeclaration) job.builderType.get()).scope);
return out;
}
- public void generateBuilderFields(EclipseNode builderType, List<BuilderFieldData> builderFields, ASTNode source) {
+ public 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) {
@@ -906,45 +981,43 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
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 static final AbstractMethodDeclaration[] EMPTY = {};
-
- public void makePrefixedSetterMethodsForBuilder(CheckerFrameworkVersion cfv, EclipseNode builderType, BuilderFieldData bfd, EclipseNode sourceNode, boolean fluent, boolean chain, AccessLevel access, EclipseNode originalFieldNode, String prefix) {
+ public void makePrefixedSetterMethodsForBuilder(BuilderJob job, BuilderFieldData bfd, String prefix) {
boolean deprecate = isFieldDeprecated(bfd.originalFieldNode);
if (bfd.singularData == null || bfd.singularData.getSingularizer() == null) {
- makePrefixedSetterMethodForBuilder(cfv, builderType, deprecate, bfd.createdFields.get(0), bfd.name, bfd.nameOfSetFlag, sourceNode, fluent, chain, bfd.annotations, access, originalFieldNode, prefix);
+ makePrefixedSetterMethodForBuilder(job, bfd, deprecate, prefix);
} else {
- bfd.singularData.getSingularizer().generateMethods(cfv, bfd.singularData, deprecate, builderType, fluent, chain, access);
+ bfd.singularData.getSingularizer().generateMethods(job, bfd.singularData, deprecate);
}
}
- private void makePrefixedSetterMethodForBuilder(CheckerFrameworkVersion cfv, EclipseNode builderType, boolean deprecate, EclipseNode fieldNode, char[] paramName, char[] nameOfSetFlag, EclipseNode sourceNode, boolean fluent, boolean chain, Annotation[] annotations, AccessLevel access, EclipseNode originalFieldNode, String prefix) {
- TypeDeclaration td = (TypeDeclaration) builderType.get();
+ 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(fluent) {
- setterName = prefix.isEmpty() ? new String(paramName) : HandlerUtil.buildAccessorName(setterPrefix, new String(paramName));
+ if (job.oldFluent) {
+ 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++) {
@@ -954,27 +1027,18 @@ 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 = sourceNode.get();
- MethodDeclaration setter = HandleSetter.createSetter(td, deprecate, fieldNode, setterName, paramName, nameOfSetFlag, chain, toEclipseModifier(access),
- sourceNode, methodAnnsList, annotations != null ? Arrays.asList(copyAnnotations(source, annotations)) : 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);
- }
- if (sourceNode.up().getKind() == Kind.METHOD) {
- copyJavadocFromParam(originalFieldNode.up(), setter, td, paramName.toString());
+ ASTNode source = job.sourceNode.get();
+ 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(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(builderType, setter);
+ injectMethod(job.builderType, setter);
}
private void copyJavadocFromParam(EclipseNode from, MethodDeclaration to, TypeDeclaration type, String param) {
@@ -991,17 +1055,17 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
}
} catch (Exception ignore) {}
}
-
- public EclipseNode makeBuilderClass(boolean isStatic, EclipseNode tdParent, String builderClassName, TypeParameter[] typeParams, ASTNode source, AccessLevel access) {
- TypeDeclaration parent = (TypeDeclaration) tdParent.get();
+
+ public void makeBuilderClass(BuilderJob job) {
+ TypeDeclaration parent = (TypeDeclaration) job.parentType.get();
TypeDeclaration builder = new TypeDeclaration(parent.compilationResult);
builder.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG;
- builder.modifiers |= toEclipseModifier(access);
- if (isStatic) builder.modifiers |= ClassFileConstants.AccStatic;
- builder.typeParameters = copyTypeParams(typeParams, source);
- builder.name = builderClassName.toCharArray();
- builder.traverse(new SetGeneratedByVisitor(source), (ClassScope) null);
- return injectType(tdParent, builder);
+ builder.modifiers |= toEclipseModifier(job.accessOuters);
+ if (job.isStatic) builder.modifiers |= ClassFileConstants.AccStatic;
+ builder.typeParameters = job.copyTypeParams();
+ builder.name = job.builderClassNameArr;
+ builder.traverse(new SetGeneratedByVisitor(job.source), (ClassScope) null);
+ 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) {