diff options
Diffstat (limited to 'src/core/lombok')
13 files changed, 1085 insertions, 899 deletions
diff --git a/src/core/lombok/eclipse/handlers/HandleBuilder.java b/src/core/lombok/eclipse/handlers/HandleBuilder.java index 5bda6e1a..f8eb9ed0 100755 --- a/src/core/lombok/eclipse/handlers/HandleBuilder.java +++ b/src/core/lombok/eclipse/handlers/HandleBuilder.java @@ -106,8 +106,16 @@ import lombok.experimental.NonFinal; public class HandleBuilder extends EclipseAnnotationHandler<Builder> { private HandleConstructor handleConstructor = new HandleConstructor(); - private static final char[] CLEAN_FIELD_NAME = "$lombokUnclean".toCharArray(); - private static final char[] CLEAN_METHOD_NAME = "$lombokClean".toCharArray(); + static final char[] CLEAN_FIELD_NAME = "$lombokUnclean".toCharArray(); + static final char[] CLEAN_METHOD_NAME = "$lombokClean".toCharArray(); + static final String TO_BUILDER_METHOD_NAME_STRING = "toBuilder"; + static final char[] TO_BUILDER_METHOD_NAME = TO_BUILDER_METHOD_NAME_STRING.toCharArray(); + static final char[] DEFAULT_PREFIX = {'$', 'd', 'e', 'f', 'a', 'u', 'l', 't', '$'}; + static final char[] SET_PREFIX = {'$', 's', 'e', 't'}; + static final char[] VALUE_PREFIX = {'$', 'v', 'a', 'l', 'u', 'e'}; + static final char[] BUILDER_TEMP_VAR = {'b', 'u', 'i', 'l', 'd', 'e', 'r'}; + static final AbstractMethodDeclaration[] EMPTY_METHODS = {}; + static final String TO_BUILDER_NOT_SUPPORTED = "@Builder(toBuilder=true) is only supported if you return your own type."; private static final boolean toBoolean(Object expr, boolean defaultValue) { if (expr == null) return defaultValue; @@ -118,22 +126,28 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { static class BuilderJob { CheckerFrameworkVersion checkerFramework; - EclipseNode builderTypeParent, builderType; - String builderClassName, builderMethodName, buildMethodName, toBuilderMethodName; + EclipseNode parentType; + String builderMethodName, buildMethodName; boolean isStatic; TypeParameter[] typeParams; + TypeParameter[] builderTypeParams; ASTNode source; EclipseNode sourceNode; List<BuilderFieldData> builderFields; AccessLevel accessInners, accessOuters; boolean oldFluent, oldChain, toBuilder; - TypeParameter[] copyTypeParams() { - return EclipseHandlerUtil.copyTypeParams(typeParams, source); + EclipseNode builderType; + String builderClassName; + char[] builderClassNameArr; + + void setBuilderClassName(String builderClassName) { + this.builderClassName = builderClassName; + this.builderClassNameArr = builderClassName.toCharArray(); } - char[] getBuilderClassName() { - return builderClassName.toCharArray(); + TypeParameter[] copyTypeParams() { + return EclipseHandlerUtil.copyTypeParams(typeParams, source); } long getPos() { @@ -141,22 +155,22 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { } public TypeReference createBuilderTypeReference() { - return namePlusTypeParamsToTypeReference(builderTypeParent, getBuilderClassName(), !isStatic, typeParams, getPos()); + return namePlusTypeParamsToTypeReference(parentType, builderClassNameArr, !isStatic, builderTypeParams, getPos()); } public TypeReference createBuilderTypeReferenceForceStatic() { - return namePlusTypeParamsToTypeReference(builderTypeParent, getBuilderClassName(), false, typeParams, getPos()); + return namePlusTypeParamsToTypeReference(parentType, builderClassNameArr, false, builderTypeParams, getPos()); } public TypeReference createBuilderParentTypeReference() { - return namePlusTypeParamsToTypeReference(builderTypeParent, typeParams, getPos()); + return namePlusTypeParamsToTypeReference(parentType, typeParams, getPos()); } public EclipseNode getTopNode() { - return builderTypeParent.top(); + return parentType.top(); } - public void init(AnnotationValues<Builder> node, Builder ann) { + void init(AnnotationValues<Builder> annValues, Builder ann, EclipseNode node) { accessOuters = ann.access(); if (accessOuters == null) accessOuters = AccessLevel.PUBLIC; if (accessOuters == AccessLevel.NONE) { @@ -166,23 +180,37 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { accessInners = accessOuters == AccessLevel.PROTECTED ? AccessLevel.PUBLIC : accessOuters; // These exist just to support the 'old' lombok.experimental.Builder, which had these properties. lombok.Builder no longer has them. - oldFluent = toBoolean(node.getActualExpression("fluent"), true); - oldChain = toBoolean(node.getActualExpression("chain"), true); + oldFluent = toBoolean(annValues.getActualExpression("fluent"), true); + oldChain = toBoolean(annValues.getActualExpression("chain"), true); builderMethodName = ann.builderMethodName(); buildMethodName = ann.buildMethodName(); - builderClassName = ann.builderClassName(); - toBuilderMethodName = "toBuilder"; + setBuilderClassName(fixBuilderClassName(node, ann.builderClassName())); toBuilder = ann.toBuilder(); if (builderMethodName == null) builderMethodName = "builder"; if (buildMethodName == null) buildMethodName = "build"; - if (builderClassName == null) builderClassName = ""; } - public MethodDeclaration createNewMethodDeclaration() { + static String fixBuilderClassName(EclipseNode node, String override) { + if (override != null && !override.isEmpty()) return override; + override = node.getAst().readConfiguration(ConfigurationKeys.BUILDER_CLASS_NAME); + if (override != null && !override.isEmpty()) return override; + return "*Builder"; + } + + MethodDeclaration createNewMethodDeclaration() { return new MethodDeclaration(((CompilationUnitDeclaration) getTopNode().get()).compilationResult); } + + String replaceBuilderClassName(char[] name) { + if (builderClassName.indexOf('*') == -1) return builderClassName; + return builderClassName.replace("*", new String(name)); + } + + String replaceBuilderClassName(String name) { + return builderClassName.replace("*", name); + } } static class BuilderFieldData { @@ -219,10 +247,6 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { return true; } - private static final char[] DEFAULT_PREFIX = {'$', 'd', 'e', 'f', 'a', 'u', 'l', 't', '$'}; - private static final char[] SET_PREFIX = {'$', 's', 'e', 't'}; - private static final char[] VALUE_PREFIX = {'$', 'v', 'a', 'l', 'u', 'e'}; - private static final char[] prefixWith(char[] prefix, char[] name) { char[] out = new char[prefix.length + name.length]; System.arraycopy(prefix, 0, out, 0, prefix.length); @@ -236,9 +260,10 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { job.sourceNode = annotationNode; job.source = ast; job.checkerFramework = getCheckerFrameworkVersion(annotationNode); + job.isStatic = true; Builder annInstance = annotation.getInstance(); - job.init(annotation, annInstance); + job.init(annotation, annInstance, annotationNode); List<char[]> typeArgsForToBuilder = null; boolean generateBuilderMethod; @@ -251,45 +276,35 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { } if (!checkName("buildMethodName", job.buildMethodName, annotationNode)) return; - if (!job.builderClassName.isEmpty()) { - if (!checkName("builderClassName", job.builderClassName, annotationNode)) return; - } EclipseNode parent = annotationNode.up(); job.builderFields = new ArrayList<BuilderFieldData>(); TypeReference buildMethodReturnType; TypeReference[] buildMethodThrownExceptions; - char[] nameOfStaticBuilderMethod; + char[] nameOfBuilderMethod; EclipseNode fillParametersFrom = parent.get() instanceof AbstractMethodDeclaration ? parent : null; boolean addCleaning = false; - job.isStatic = true; List<EclipseNode> nonFinalNonDefaultedFields = null; - if (job.builderClassName.isEmpty()) job.builderClassName = annotationNode.getAst().readConfiguration(ConfigurationKeys.BUILDER_CLASS_NAME); - if (job.builderClassName == null || job.builderClassName.isEmpty()) job.builderClassName = "*Builder"; - boolean replaceNameInBuilderClassName = job.builderClassName.contains("*"); - if (parent.get() instanceof TypeDeclaration) { - job.builderTypeParent = parent; - TypeDeclaration td = (TypeDeclaration) job.builderTypeParent.get(); + job.parentType = parent; + TypeDeclaration td = (TypeDeclaration) parent.get(); List<EclipseNode> allFields = new ArrayList<EclipseNode>(); boolean valuePresent = (hasAnnotation(lombok.Value.class, parent) || hasAnnotation("lombok.experimental.Value", parent)); - for (EclipseNode fieldNode : HandleConstructor.findAllFields(job.builderTypeParent, true)) { + for (EclipseNode fieldNode : HandleConstructor.findAllFields(parent, true)) { FieldDeclaration fd = (FieldDeclaration) fieldNode.get(); EclipseNode isDefault = findAnnotation(Builder.Default.class, fieldNode); boolean isFinal = ((fd.modifiers & ClassFileConstants.AccFinal) != 0) || (valuePresent && !hasAnnotation(NonFinal.class, fieldNode)); - Annotation[] copyableAnnotations = findCopyableAnnotations(fieldNode); - BuilderFieldData bfd = new BuilderFieldData(); bfd.rawName = fieldNode.getName().toCharArray(); bfd.name = removePrefixFromField(fieldNode); bfd.builderFieldName = bfd.name; - bfd.annotations = copyAnnotations(fd, copyableAnnotations); + bfd.annotations = copyAnnotations(fd, findCopyableAnnotations(fieldNode)); bfd.type = fd.type; bfd.singularData = getSingularData(fieldNode, ast, annInstance.setterPrefix()); bfd.originalFieldNode = fieldNode; @@ -316,22 +331,22 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { bfd.builderFieldName = prefixWith(bfd.name, VALUE_PREFIX); MethodDeclaration md = generateDefaultProvider(bfd.nameOfDefaultProvider, td.typeParameters, fieldNode, ast); - if (md != null) injectMethod(job.builderTypeParent, md); + if (md != null) injectMethod(parent, md); } addObtainVia(bfd, fieldNode); job.builderFields.add(bfd); allFields.add(fieldNode); } - handleConstructor.generateConstructor(job.builderTypeParent, AccessLevel.PACKAGE, allFields, false, null, SkipIfConstructorExists.I_AM_BUILDER, + handleConstructor.generateConstructor(parent, AccessLevel.PACKAGE, allFields, false, null, SkipIfConstructorExists.I_AM_BUILDER, Collections.<Annotation>emptyList(), annotationNode); - job.typeParams = td.typeParameters; + job.typeParams = job.builderTypeParams = td.typeParameters; buildMethodReturnType = job.createBuilderParentTypeReference(); buildMethodThrownExceptions = null; - nameOfStaticBuilderMethod = null; - if (replaceNameInBuilderClassName) job.builderClassName = job.builderClassName.replace("*", new String(td.name)); - replaceNameInBuilderClassName = false; + nameOfBuilderMethod = null; + job.setBuilderClassName(job.replaceBuilderClassName(td.name)); + if (!checkName("builderClassName", job.builderClassName, annotationNode)) return; } else if (parent.get() instanceof ConstructorDeclaration) { ConstructorDeclaration cd = (ConstructorDeclaration) parent.get(); if (cd.typeParameters != null && cd.typeParameters.length > 0) { @@ -339,21 +354,20 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { return; } - job.builderTypeParent = parent.up(); - TypeDeclaration td = (TypeDeclaration) job.builderTypeParent.get(); - job.typeParams = td.typeParameters; + job.parentType = parent.up(); + TypeDeclaration td = (TypeDeclaration) job.parentType.get(); + job.typeParams = job.builderTypeParams = td.typeParameters; buildMethodReturnType = job.createBuilderParentTypeReference(); buildMethodThrownExceptions = cd.thrownExceptions; - nameOfStaticBuilderMethod = null; - if (replaceNameInBuilderClassName) job.builderClassName = job.builderClassName.replace("*", new String(cd.selector)); - replaceNameInBuilderClassName = false; + nameOfBuilderMethod = null; + job.setBuilderClassName(job.replaceBuilderClassName(cd.selector)); + if (!checkName("builderClassName", job.builderClassName, annotationNode)) return; } else if (parent.get() instanceof MethodDeclaration) { MethodDeclaration md = (MethodDeclaration) parent.get(); - job.builderTypeParent = parent.up(); + job.parentType = parent.up(); job.isStatic = md.isStatic(); if (job.toBuilder) { - final String TO_BUILDER_NOT_SUPPORTED = "@Builder(toBuilder=true) is only supported if you return your own type."; char[] token; char[][] pkg = null; if (md.returnType.dimensions() > 0) { @@ -379,12 +393,12 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { return; } - if (job.builderTypeParent == null || !equals(job.builderTypeParent.getName(), token)) { + if (job.parentType == null || !equals(job.parentType.getName(), token)) { annotationNode.addError(TO_BUILDER_NOT_SUPPORTED); return; } - TypeParameter[] tpOnType = ((TypeDeclaration) job.builderTypeParent.get()).typeParameters; + TypeParameter[] tpOnType = ((TypeDeclaration) job.parentType.get()).typeParameters; TypeParameter[] tpOnMethod = md.typeParameters; TypeReference[][] tpOnRet_ = null; if (md.returnType instanceof ParameterizedSingleTypeReference) { @@ -423,15 +437,15 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { } } - job.typeParams = md.typeParameters; + job.typeParams = job.builderTypeParams = md.typeParameters; buildMethodReturnType = copyType(md.returnType, ast); buildMethodThrownExceptions = md.thrownExceptions; - nameOfStaticBuilderMethod = md.selector; - if (replaceNameInBuilderClassName) { + nameOfBuilderMethod = md.selector; + if (job.builderClassName.indexOf('*') > -1) { char[] token = returnTypeToBuilderClassName(annotationNode, md, job.typeParams); - if (token == null) - return; - job.builderClassName = job.builderClassName.replace("*", new String(token)); + if (token == null) return; // should not happen. + job.setBuilderClassName(job.replaceBuilderClassName(token)); + if (!checkName("builderClassName", job.builderClassName, annotationNode)) return; } } else { annotationNode.addError("@Builder is only supported on types, constructors, and methods."); @@ -458,7 +472,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { } } - job.builderType = findInnerClass(job.builderTypeParent, job.builderClassName); + job.builderType = findInnerClass(job.parentType, job.builderClassName); if (job.builderType == null) makeBuilderClass(job); else { TypeDeclaration builderTypeDeclaration = (TypeDeclaration) job.builderType.get(); @@ -527,7 +541,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { MemberExistsResult methodExists = methodExists(job.buildMethodName, job.builderType, -1); if (methodExists == MemberExistsResult.EXISTS_BY_LOMBOK) methodExists = methodExists(job.buildMethodName, job.builderType, 0); if (methodExists == MemberExistsResult.NOT_EXISTS) { - MethodDeclaration md = generateBuildMethod(job, nameOfStaticBuilderMethod, buildMethodReturnType, buildMethodThrownExceptions, addCleaning); + MethodDeclaration md = generateBuildMethod(job, nameOfBuilderMethod, buildMethodReturnType, buildMethodThrownExceptions, addCleaning); if (md != null) injectMethod(job.builderType, md); } } @@ -548,13 +562,13 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { if (cleanMethod != null) injectMethod(job.builderType, cleanMethod); } - if (generateBuilderMethod && methodExists(job.builderMethodName, job.builderTypeParent, -1) != MemberExistsResult.NOT_EXISTS) generateBuilderMethod = false; + if (generateBuilderMethod && methodExists(job.builderMethodName, job.parentType, -1) != MemberExistsResult.NOT_EXISTS) generateBuilderMethod = false; if (generateBuilderMethod) { MethodDeclaration md = generateBuilderMethod(job); - if (md != null) injectMethod(job.builderTypeParent, md); + if (md != null) injectMethod(job.parentType, md); } - if (job.toBuilder) switch (methodExists(job.toBuilderMethodName, job.builderTypeParent, 0)) { + if (job.toBuilder) switch (methodExists(TO_BUILDER_METHOD_NAME_STRING, job.parentType, 0)) { case EXISTS_BY_USER: annotationNode.addWarning("Not generating toBuilder() as it already exists."); break; @@ -569,7 +583,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { } MethodDeclaration md = generateToBuilderMethod(job, tps, annInstance.setterPrefix()); - if (md != null) injectMethod(job.builderTypeParent, md); + if (md != null) injectMethod(job.parentType, md); } if (nonFinalNonDefaultedFields != null && generateBuilderMethod) { @@ -608,13 +622,12 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { return token; } - private static final char[] BUILDER_TEMP_VAR = {'b', 'u', 'i', 'l', 'd', 'e', 'r'}; private MethodDeclaration generateToBuilderMethod(BuilderJob job, TypeParameter[] typeParameters, String prefix) { int pS = job.source.sourceStart, pE = job.source.sourceEnd; long p = job.getPos(); MethodDeclaration out = job.createNewMethodDeclaration(); - out.selector = job.toBuilderMethodName.toCharArray(); + out.selector = TO_BUILDER_METHOD_NAME; out.modifiers = toEclipseModifier(job.accessOuters); out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG; @@ -657,7 +670,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { obtainExpr.typeArguments[j] = new SingleTypeReference(typeParameters[j].name, 0); } } - obtainExpr.receiver = generateNameReference(job.builderTypeParent, 0); + obtainExpr.receiver = generateNameReference(job.parentType, 0); } else { obtainExpr.receiver = new ThisReference(0, 0); } @@ -709,8 +722,8 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { out.statements[preSs] = new ReturnStatement(receiver, pS, pE); } - createRelevantNonNullAnnotation(job.builderTypeParent, out); - out.traverse(new SetGeneratedByVisitor(job.source), ((TypeDeclaration) job.builderTypeParent.get()).scope); + createRelevantNonNullAnnotation(job.parentType, out); + out.traverse(new SetGeneratedByVisitor(job.source), ((TypeDeclaration) job.parentType.get()).scope); return out; } @@ -736,6 +749,18 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { return decl; } + static Receiver generateNotCalledReceiver(BuilderJob job, String setterName) { + char[][] nameNotCalled = fromQualifiedName(CheckerFrameworkVersion.NAME__NOT_CALLED); + SingleMemberAnnotation ann = new SingleMemberAnnotation(new QualifiedTypeReference(nameNotCalled, poss(job.source, nameNotCalled.length)), job.source.sourceStart); + ann.memberValue = new StringLiteral(setterName.toCharArray(), 0, 0, 0); + + TypeReference typeReference = job.createBuilderTypeReference(); + int trLen = typeReference.getTypeName().length; + typeReference.annotations = new Annotation[trLen][]; + typeReference.annotations[trLen - 1] = new Annotation[] {ann}; + return new Receiver(new char[] { 't', 'h', 'i', 's' }, 0, typeReference, null, 0); + } + static Receiver generateBuildReceiver(BuilderJob job) { if (!job.checkerFramework.generateCalledMethods()) return null; @@ -803,7 +828,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { MessageSend inv = new MessageSend(); inv.sourceStart = job.source.sourceStart; inv.sourceEnd = job.source.sourceEnd; - inv.receiver = new SingleNameReference(((TypeDeclaration) job.builderTypeParent.get()).name, 0L); + inv.receiver = new SingleNameReference(((TypeDeclaration) job.parentType.get()).name, 0L); inv.selector = bfd.nameOfDefaultProvider; inv.typeArguments = typeParameterNames(((TypeDeclaration) job.builderType.get()).typeParameters); @@ -897,7 +922,6 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { public MethodDeclaration generateBuilderMethod(BuilderJob job) { int pS = job.source.sourceStart, pE = job.source.sourceEnd; long p = job.getPos(); - char[] builderClassName = job.getBuilderClassName(); MethodDeclaration out = job.createNewMethodDeclaration(); out.selector = job.builderMethodName.toCharArray(); @@ -920,9 +944,9 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { QualifiedAllocationExpression qualifiedInvoke = new QualifiedAllocationExpression(); qualifiedInvoke.enclosingInstance = new ThisReference(pS, pE); if (job.typeParams == null || job.typeParams.length == 0) { - qualifiedInvoke.type = new SingleTypeReference(builderClassName, p); + qualifiedInvoke.type = new SingleTypeReference(job.builderClassNameArr, p); } else { - qualifiedInvoke.type = namePlusTypeParamsToTypeReference(null, builderClassName, false, job.typeParams, p); + qualifiedInvoke.type = namePlusTypeParamsToTypeReference(null, job.builderClassNameArr, false, job.typeParams, p); } out.statements = new Statement[] {new ReturnStatement(qualifiedInvoke, pS, pE)}; @@ -973,29 +997,27 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { } } - private static final AbstractMethodDeclaration[] EMPTY = {}; - public void makePrefixedSetterMethodsForBuilder(BuilderJob job, BuilderFieldData bfd, String prefix) { boolean deprecate = isFieldDeprecated(bfd.originalFieldNode); if (bfd.singularData == null || bfd.singularData.getSingularizer() == null) { - makePrefixedSetterMethodForBuilder(job, deprecate, bfd.createdFields.get(0), bfd.name, bfd.nameOfSetFlag, bfd.annotations, bfd.originalFieldNode, prefix); + makePrefixedSetterMethodForBuilder(job, bfd, deprecate, prefix); } else { bfd.singularData.getSingularizer().generateMethods(job, bfd.singularData, deprecate); } } - private void makePrefixedSetterMethodForBuilder(BuilderJob job, boolean deprecate, EclipseNode fieldNode, char[] paramName, char[] nameOfSetFlag, Annotation[] annotations, EclipseNode originalFieldNode, String prefix) { + private void makePrefixedSetterMethodForBuilder(BuilderJob job, BuilderFieldData bfd, boolean deprecate, String prefix) { TypeDeclaration td = (TypeDeclaration) job.builderType.get(); + EclipseNode fieldNode = bfd.createdFields.get(0); AbstractMethodDeclaration[] existing = td.methods; - if (existing == null) existing = EMPTY; + if (existing == null) existing = EMPTY_METHODS; int len = existing.length; - String setterPrefix = prefix.isEmpty() ? "set" : prefix; String setterName; if (job.oldFluent) { - setterName = prefix.isEmpty() ? new String(paramName) : HandlerUtil.buildAccessorName(setterPrefix, new String(paramName)); + setterName = prefix.isEmpty() ? new String(bfd.name) : HandlerUtil.buildAccessorName(setterPrefix, new String(bfd.name)); } else { - setterName = HandlerUtil.buildAccessorName(setterPrefix, new String(paramName)); + setterName = HandlerUtil.buildAccessorName(setterPrefix, new String(bfd.name)); } for (int i = 0; i < len; i++) { @@ -1005,26 +1027,16 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { } List<Annotation> methodAnnsList = Collections.<Annotation>emptyList(); - Annotation[] methodAnns = EclipseHandlerUtil.findCopyableToSetterAnnotations(originalFieldNode); + Annotation[] methodAnns = EclipseHandlerUtil.findCopyableToSetterAnnotations(bfd.originalFieldNode); if (methodAnns != null && methodAnns.length > 0) methodAnnsList = Arrays.asList(methodAnns); ASTNode source = job.sourceNode.get(); - MethodDeclaration setter = HandleSetter.createSetter(td, deprecate, fieldNode, setterName, paramName, nameOfSetFlag, job.oldChain, toEclipseModifier(job.accessInners), - job.sourceNode, methodAnnsList, annotations != null ? Arrays.asList(copyAnnotations(source, annotations)) : Collections.<Annotation>emptyList()); - if (job.checkerFramework.generateCalledMethods()) { - char[][] nameNotCalled = fromQualifiedName(CheckerFrameworkVersion.NAME__NOT_CALLED); - SingleMemberAnnotation ann = new SingleMemberAnnotation(new QualifiedTypeReference(nameNotCalled, poss(source, nameNotCalled.length)), source.sourceStart); - ann.memberValue = new StringLiteral(setterName.toCharArray(), 0, 0, 0); - - TypeReference typeReference = job.createBuilderTypeReference(); - int trLen = typeReference.getTypeName().length; - typeReference.annotations = new Annotation[trLen][]; - typeReference.annotations[trLen - 1] = new Annotation[] {ann}; - setter.receiver = new Receiver(new char[] { 't', 'h', 'i', 's' }, 0, typeReference, null, 0); - } + MethodDeclaration setter = HandleSetter.createSetter(td, deprecate, fieldNode, setterName, bfd.name, bfd.nameOfSetFlag, job.oldChain, toEclipseModifier(job.accessInners), + job.sourceNode, methodAnnsList, bfd.annotations != null ? Arrays.asList(copyAnnotations(source, bfd.annotations)) : Collections.<Annotation>emptyList()); + if (job.checkerFramework.generateCalledMethods()) setter.receiver = generateNotCalledReceiver(job, setterName); if (job.sourceNode.up().getKind() == Kind.METHOD) { - copyJavadocFromParam(originalFieldNode.up(), setter, td, paramName.toString()); + copyJavadocFromParam(bfd.originalFieldNode.up(), setter, td, bfd.name.toString()); } else { - copyJavadoc(originalFieldNode, setter, td, CopyJavadoc.SETTER, true); + copyJavadoc(bfd.originalFieldNode, setter, td, CopyJavadoc.SETTER, true); } injectMethod(job.builderType, setter); } @@ -1045,15 +1057,15 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { } public void makeBuilderClass(BuilderJob job) { - TypeDeclaration parent = (TypeDeclaration) job.builderTypeParent.get(); + TypeDeclaration parent = (TypeDeclaration) job.parentType.get(); TypeDeclaration builder = new TypeDeclaration(parent.compilationResult); builder.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG; builder.modifiers |= toEclipseModifier(job.accessOuters); if (job.isStatic) builder.modifiers |= ClassFileConstants.AccStatic; builder.typeParameters = job.copyTypeParams(); - builder.name = job.getBuilderClassName(); + builder.name = job.builderClassNameArr; builder.traverse(new SetGeneratedByVisitor(job.source), (ClassScope) null); - job.builderType = injectType(job.builderTypeParent, builder); + job.builderType = injectType(job.parentType, builder); } private void addObtainVia(BuilderFieldData bfd, EclipseNode node) { diff --git a/src/core/lombok/eclipse/handlers/HandleConstructor.java b/src/core/lombok/eclipse/handlers/HandleConstructor.java index 06c9ecd9..3233a8c6 100755 --- a/src/core/lombok/eclipse/handlers/HandleConstructor.java +++ b/src/core/lombok/eclipse/handlers/HandleConstructor.java @@ -461,14 +461,12 @@ public class HandleConstructor { constructor.arguments = params.isEmpty() ? null : params.toArray(new Argument[0]); /* Generate annotations that must be put on the generated method, and attach them. */ { - Annotation[] constructorProperties = null, checkerFramework = null; + Annotation[] constructorProperties = null; if (addConstructorProperties && !isLocalType(type)) constructorProperties = createConstructorProperties(source, fieldsToParam); - if (getCheckerFrameworkVersion(type).generateUnique()) checkerFramework = new Annotation[] { generateNamedAnnotation(source, CheckerFrameworkVersion.NAME__UNIQUE) }; constructor.annotations = copyAnnotations(source, onConstructor.toArray(new Annotation[0]), - constructorProperties, - checkerFramework); + constructorProperties); } constructor.traverse(new SetGeneratedByVisitor(source), typeDeclaration.scope); @@ -536,6 +534,11 @@ public class HandleConstructor { TypeDeclaration typeDecl = (TypeDeclaration) type.get(); constructor.returnType = EclipseHandlerUtil.namePlusTypeParamsToTypeReference(type, typeDecl.typeParameters, p); constructor.annotations = null; + if (getCheckerFrameworkVersion(type).generateUnique()) { + int len = constructor.returnType.getTypeName().length; + constructor.returnType.annotations = new Annotation[len][]; + constructor.returnType.annotations[len - 1] = new Annotation[] {generateNamedAnnotation(source, CheckerFrameworkVersion.NAME__UNIQUE)}; + } constructor.selector = name.toCharArray(); constructor.thrownExceptions = null; constructor.typeParameters = copyTypeParams(((TypeDeclaration) type.get()).typeParameters, source); @@ -556,9 +559,7 @@ public class HandleConstructor { assigns.add(nameRef); Argument parameter = new Argument(field.name, fieldPos, copyType(field.type, source), Modifier.FINAL); - Annotation[] checkerFramework = null; - if (getCheckerFrameworkVersion(fieldNode).generateUnique()) checkerFramework = new Annotation[] { generateNamedAnnotation(source, CheckerFrameworkVersion.NAME__UNIQUE) }; - parameter.annotations = copyAnnotations(source, findCopyableAnnotations(fieldNode), checkerFramework); + parameter.annotations = copyAnnotations(source, findCopyableAnnotations(fieldNode)); params.add(parameter); } diff --git a/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java b/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java index 79b7e816..8fdfd315 100644 --- a/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java +++ b/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java @@ -21,6 +21,7 @@ */ package lombok.eclipse.handlers; +import static lombok.eclipse.handlers.HandleBuilder.*; import static lombok.core.handlers.HandlerUtil.*; import static lombok.eclipse.Eclipse.*; import static lombok.eclipse.handlers.EclipseHandlerUtil.*; @@ -57,13 +58,10 @@ import org.eclipse.jdt.internal.compiler.ast.ParameterizedQualifiedTypeReference import org.eclipse.jdt.internal.compiler.ast.ParameterizedSingleTypeReference; import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference; import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference; -import org.eclipse.jdt.internal.compiler.ast.Receiver; import org.eclipse.jdt.internal.compiler.ast.ReturnStatement; -import org.eclipse.jdt.internal.compiler.ast.SingleMemberAnnotation; import org.eclipse.jdt.internal.compiler.ast.SingleNameReference; import org.eclipse.jdt.internal.compiler.ast.SingleTypeReference; import org.eclipse.jdt.internal.compiler.ast.Statement; -import org.eclipse.jdt.internal.compiler.ast.StringLiteral; import org.eclipse.jdt.internal.compiler.ast.SuperReference; import org.eclipse.jdt.internal.compiler.ast.ThisReference; import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; @@ -99,75 +97,100 @@ import lombok.eclipse.handlers.EclipseSingularsRecipes.SingularData; import lombok.eclipse.handlers.EclipseSingularsRecipes.StatementMaker; import lombok.eclipse.handlers.EclipseSingularsRecipes.TypeReferenceMaker; import lombok.eclipse.handlers.HandleBuilder.BuilderFieldData; +import lombok.eclipse.handlers.HandleBuilder.BuilderJob; import lombok.experimental.NonFinal; import lombok.experimental.SuperBuilder; @ProviderFor(EclipseAnnotationHandler.class) @HandlerPriority(-1024) //-2^10; to ensure we've picked up @FieldDefault's changes (-2048) but @Value hasn't removed itself yet (-512), so that we can error on presence of it on the builder classes. public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> { - private static final char[] CLEAN_FIELD_NAME = "$lombokUnclean".toCharArray(); - private static final char[] CLEAN_METHOD_NAME = "$lombokClean".toCharArray(); - private static final char[] DEFAULT_PREFIX = "$default$".toCharArray(); - private static final char[] SET_PREFIX = "$set".toCharArray(); - private static final char[] VALUE_PREFIX = "$value".toCharArray(); private static final char[] SELF_METHOD_NAME = "self".toCharArray(); - private static final String TO_BUILDER_METHOD_NAME_STRING = "toBuilder"; - private static final char[] TO_BUILDER_METHOD_NAME = TO_BUILDER_METHOD_NAME_STRING.toCharArray(); private static final char[] FILL_VALUES_METHOD_NAME = "$fillValuesFrom".toCharArray(); private static final char[] FILL_VALUES_STATIC_METHOD_NAME = "$fillValuesFromInstanceIntoBuilder".toCharArray(); private static final char[] INSTANCE_VARIABLE_NAME = "instance".toCharArray(); private static final String BUILDER_VARIABLE_NAME_STRING = "b"; private static final char[] BUILDER_VARIABLE_NAME = BUILDER_VARIABLE_NAME_STRING.toCharArray(); - private static final AbstractMethodDeclaration[] EMPTY_METHODS = {}; - - @Override - public void handle(AnnotationValues<SuperBuilder> annotation, Annotation ast, EclipseNode annotationNode) { - handleExperimentalFlagUsage(annotationNode, ConfigurationKeys.SUPERBUILDER_FLAG_USAGE, "@SuperBuilder"); - CheckerFrameworkVersion cfv = getCheckerFrameworkVersion(annotationNode); - - long p = (long) ast.sourceStart << 32 | ast.sourceEnd; + class SuperBuilderJob extends BuilderJob { + void init(AnnotationValues<SuperBuilder> annValues, SuperBuilder ann, EclipseNode node) { + accessOuters = accessInners = AccessLevel.PUBLIC; + oldFluent = true; + oldChain = true; + + builderMethodName = ann.builderMethodName(); + buildMethodName = ann.buildMethodName(); + toBuilder = ann.toBuilder(); + + if (builderMethodName == null) builderMethodName = "builder"; + if (buildMethodName == null) buildMethodName = "build"; + builderClassName = fixBuilderClassName(node, ""); + } - SuperBuilder superbuilderAnnotation = annotation.getInstance(); + EclipseNode builderAbstractType; + String builderAbstractClassName; + char[] builderAbstractClassNameArr; + EclipseNode builderImplType; + String builderImplClassName; + char[] builderImplClassNameArr; + private TypeParameter[] builderTypeParams_; + void setBuilderToImpl() { + builderType = builderImplType; + builderClassName = builderImplClassName; + builderClassNameArr = builderImplClassNameArr; + builderTypeParams = typeParams; + } - String builderMethodName = superbuilderAnnotation.builderMethodName(); - String buildMethodName = superbuilderAnnotation.buildMethodName(); + void setBuilderToAbstract() { + builderType = builderAbstractType; + builderClassName = builderAbstractClassName; + builderClassNameArr = builderAbstractClassNameArr; + builderTypeParams = builderTypeParams_; + } + } + + @Override public void handle(AnnotationValues<SuperBuilder> annotation, Annotation ast, EclipseNode annotationNode) { + handleExperimentalFlagUsage(annotationNode, ConfigurationKeys.SUPERBUILDER_FLAG_USAGE, "@SuperBuilder"); + SuperBuilderJob job = new SuperBuilderJob(); + job.sourceNode = annotationNode; + job.source = ast; + job.checkerFramework = getCheckerFrameworkVersion(annotationNode); + job.isStatic = true; - if (builderMethodName == null) builderMethodName = "builder"; - if (buildMethodName == null) buildMethodName = "build"; + SuperBuilder annInstance = annotation.getInstance(); + job.init(annotation, annInstance, annotationNode); boolean generateBuilderMethod; - if (builderMethodName.isEmpty()) { + if (job.builderMethodName.isEmpty()) { generateBuilderMethod = false; - } else if (!checkName("builderMethodName", builderMethodName, annotationNode)) { + } else if (!checkName("builderMethodName", job.builderMethodName, annotationNode)) { return; } else { generateBuilderMethod = true; } - if (!checkName("buildMethodName", buildMethodName, annotationNode)) return; - boolean toBuilder = superbuilderAnnotation.toBuilder(); + if (!checkName("buildMethodName", job.buildMethodName, annotationNode)) return; - EclipseNode tdParent = annotationNode.up(); + EclipseNode parent = annotationNode.up(); - java.util.List<BuilderFieldData> builderFields = new ArrayList<BuilderFieldData>(); - TypeReference returnType; - TypeParameter[] typeParams; + job.builderFields = new ArrayList<BuilderFieldData>(); + TypeReference buildMethodReturnType; boolean addCleaning = false; - if (!(tdParent.get() instanceof TypeDeclaration)) { + List<EclipseNode> nonFinalNonDefaultedFields = null; + + if (!(parent.get() instanceof TypeDeclaration)) { annotationNode.addError("@SuperBuilder is only supported on types."); return; } - TypeDeclaration td = (TypeDeclaration) tdPare |
