diff options
Diffstat (limited to 'src/core/lombok/javac/handlers/HandleSuperBuilder.java')
-rw-r--r-- | src/core/lombok/javac/handlers/HandleSuperBuilder.java | 312 |
1 files changed, 132 insertions, 180 deletions
diff --git a/src/core/lombok/javac/handlers/HandleSuperBuilder.java b/src/core/lombok/javac/handlers/HandleSuperBuilder.java index 1835bd48..1707fb0e 100644 --- a/src/core/lombok/javac/handlers/HandleSuperBuilder.java +++ b/src/core/lombok/javac/handlers/HandleSuperBuilder.java @@ -26,7 +26,6 @@ import static lombok.javac.Javac.*; import static lombok.javac.handlers.JavacHandlerUtil.*; import java.util.ArrayList; -import java.util.function.Supplier; import org.mangosdk.spi.ProviderFor; @@ -43,7 +42,6 @@ import com.sun.tools.javac.tree.JCTree.JCIf; import com.sun.tools.javac.tree.JCTree.JCMethodDecl; import com.sun.tools.javac.tree.JCTree.JCMethodInvocation; import com.sun.tools.javac.tree.JCTree.JCModifiers; -import com.sun.tools.javac.tree.JCTree.JCReturn; import com.sun.tools.javac.tree.JCTree.JCStatement; import com.sun.tools.javac.tree.JCTree.JCTypeApply; import com.sun.tools.javac.tree.JCTree.JCTypeParameter; @@ -70,15 +68,16 @@ import lombok.javac.JavacNode; import lombok.javac.JavacTreeMaker; import lombok.javac.handlers.JavacHandlerUtil.FieldAccess; import lombok.javac.handlers.JavacHandlerUtil.MemberExistsResult; +import lombok.javac.handlers.JavacSingularsRecipes.ExpressionMaker; +import lombok.javac.handlers.JavacSingularsRecipes.StatementMaker; import lombok.javac.handlers.JavacSingularsRecipes.JavacSingularizer; import lombok.javac.handlers.JavacSingularsRecipes.SingularData; @ProviderFor(JavacAnnotationHandler.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 JavacAnnotationHandler<SuperBuilder> { - private static final String SELF_METHOD = "self"; - + private static class BuilderFieldData { JCExpression type; Name rawName; @@ -88,49 +87,41 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { ObtainVia obtainVia; JavacNode obtainViaNode; JavacNode originalFieldNode; - + java.util.List<JavacNode> createdFields = new ArrayList<JavacNode>(); } - + @Override public void handle(AnnotationValues<SuperBuilder> annotation, JCAnnotation ast, JavacNode annotationNode) { handleExperimentalFlagUsage(annotationNode, ConfigurationKeys.SUPERBUILDER_FLAG_USAGE, "@SuperBuilder"); SuperBuilder superbuilderAnnotation = annotation.getInstance(); deleteAnnotationIfNeccessary(annotationNode, SuperBuilder.class); - + String builderMethodName = superbuilderAnnotation.builderMethodName(); String buildMethodName = superbuilderAnnotation.buildMethodName(); - - if (builderMethodName == null) { - builderMethodName = "builder"; - } - if (buildMethodName == null) { - buildMethodName = "build"; - } - - if (!checkName("builderMethodName", builderMethodName, annotationNode)) { - return; - } - if (!checkName("buildMethodName", buildMethodName, annotationNode)) { - return; - } - + + if (builderMethodName == null) builderMethodName = "builder"; + if (buildMethodName == null) buildMethodName = "build"; + + if (!checkName("builderMethodName", builderMethodName, annotationNode)) return; + if (!checkName("buildMethodName", buildMethodName, annotationNode)) return; + JavacNode tdParent = annotationNode.up(); - + java.util.List<BuilderFieldData> builderFields = new ArrayList<BuilderFieldData>(); JCExpression returnType; List<JCTypeParameter> typeParams = List.nil(); List<JCExpression> thrownExceptions = List.nil(); List<JCExpression> superclassTypeParams = List.nil(); - + boolean addCleaning = false; - + if (!(tdParent.get() instanceof JCClassDecl)) { annotationNode.addError("@SuperBuilder is only supported on types."); return; } - + // Gather all fields of the class that should be set by the builder. JCClassDecl td = (JCClassDecl) tdParent.get(); ListBuffer<JavacNode> allFields = new ListBuffer<JavacNode>(); @@ -145,24 +136,22 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { bfd.type = fd.vartype; bfd.singularData = getSingularData(fieldNode); bfd.originalFieldNode = fieldNode; - + if (bfd.singularData != null && isDefault != null) { isDefault.addError("@Builder.Default and @Singular cannot be mixed."); isDefault = null; } - + if (fd.init == null && isDefault != null) { isDefault.addWarning("@Builder.Default requires an initializing expression (' = something;')."); isDefault = null; } - + if (fd.init != null && isDefault == null) { - if (isFinal) { - continue; - } + if (isFinal) continue; fieldNode.addWarning("@SuperBuilder will ignore the initializing expression entirely. If you want the initializing expression to serve as default, add @Builder.Default. If it is not supposed to be settable during building, make the field final."); } - + if (isDefault != null) { bfd.nameOfSetFlag = tdParent.toName(bfd.name + "$set"); // The @Builder annotation removes the initializing expression on the field and moves @@ -179,7 +168,7 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { builderFields.add(bfd); allFields.append(fieldNode); } - + // Set the names of the builder classes. String builderClassName = td.name.toString() + "Builder"; String builderImplClassName = builderClassName + "Impl"; @@ -187,14 +176,14 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { JCExpression superclassBuilderClassExpression = null; if (extendsClause instanceof JCTypeApply) { // Remember the type arguments, because we need them for the extends clause of our abstract builder class. - superclassTypeParams = ((JCTypeApply)extendsClause).getTypeArguments(); + superclassTypeParams = ((JCTypeApply) extendsClause).getTypeArguments(); // A class name with a generics type, e.g., "Superclass<A>". - extendsClause = ((JCTypeApply)extendsClause).getType(); + extendsClause = ((JCTypeApply) extendsClause).getType(); } if (extendsClause instanceof JCFieldAccess) { Name superclassClassName = ((JCFieldAccess)extendsClause).getIdentifier(); String superclassBuilderClassName = superclassClassName + "Builder"; - superclassBuilderClassExpression = tdParent.getTreeMaker().Select((JCFieldAccess)extendsClause, + superclassBuilderClassExpression = tdParent.getTreeMaker().Select((JCFieldAccess) extendsClause, tdParent.toName(superclassBuilderClassName)); } else if (extendsClause != null) { String superclassBuilderClassName = extendsClause.toString() + "Builder"; @@ -202,24 +191,22 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { } // If there is no superclass, superclassBuilderClassExpression is still == null at this point. // You can use it to check whether to inherit or not. - + returnType = namePlusTypeParamsToTypeReference(tdParent.getTreeMaker(), td.name, td.typarams); typeParams = td.typarams; - + // <C, B> are the generics for our builder. String classGenericName = "C"; String builderGenericName = "B"; // If these generics' names collide with any generics on the annotated class, modify them. // For instance, if there are generics <B, B2, C> on the annotated class, use "C2" and "B3" for our builder. java.util.List<String> typeParamStrings = new ArrayList<String>(); - for (JCTypeParameter typeParam : typeParams) { - typeParamStrings.add(typeParam.getName().toString()); - } + for (JCTypeParameter typeParam : typeParams) typeParamStrings.add(typeParam.getName().toString()); classGenericName = generateNonclashingNameFor(classGenericName, typeParamStrings); builderGenericName = generateNonclashingNameFor(builderGenericName, typeParamStrings); - + thrownExceptions = List.nil(); - + // Check validity of @ObtainVia fields, and add check if adding cleaning for @Singular is necessary. for (BuilderFieldData bfd : builderFields) { if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) { @@ -239,7 +226,7 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { } } } - + // Create the abstract builder class. JavacNode builderType = findInnerClass(tdParent, builderClassName); if (builderType == null) { @@ -249,7 +236,7 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { annotationNode.addError("@SuperBuilder does not support customized builders. Use @Builder instead."); return; } - + // Generate the fields in the abstract builder class that hold the values for the instance. generateBuilderFields(builderType, builderFields, ast); if (addCleaning) { @@ -257,37 +244,32 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { JCVariableDecl uncleanField = maker.VarDef(maker.Modifiers(Flags.PRIVATE), builderType.toName("$lombokUnclean"), maker.TypeIdent(CTC_BOOLEAN), null); injectFieldAndMarkGenerated(builderType, uncleanField); } - + // Generate abstract self() and build() methods in the abstract builder. injectMethod(builderType, generateAbstractSelfMethod(tdParent, superclassBuilderClassExpression != null, builderGenericName)); injectMethod(builderType, generateAbstractBuildMethod(tdParent, buildMethodName, superclassBuilderClassExpression != null, classGenericName)); - + // Create the setter methods in the abstract builder. for (BuilderFieldData bfd : builderFields) { generateSetterMethodsForBuilder(builderType, bfd, annotationNode, builderGenericName); } - + // Create the toString() method for the abstract builder. java.util.List<JavacNode> fieldNodes = new ArrayList<JavacNode>(); - for (BuilderFieldData bfd : builderFields) { - fieldNodes.addAll(bfd.createdFields); - } + for (BuilderFieldData bfd : builderFields) fieldNodes.addAll(bfd.createdFields); + // Let toString() call super.toString() if there is a superclass, so that it also shows fields from the superclass' builder. JCMethodDecl toStringMethod = HandleToString.createToString(builderType, fieldNodes, true, superclassBuilderClassExpression != null, FieldAccess.ALWAYS_FIELD, ast); - if (toStringMethod != null) { - injectMethod(builderType, toStringMethod); - } - + if (toStringMethod != null) injectMethod(builderType, toStringMethod); + // If clean methods are requested, add them now. - if (addCleaning) { - injectMethod(builderType, generateCleanMethod(builderFields, builderType, ast)); - } + if (addCleaning) injectMethod(builderType, generateCleanMethod(builderFields, builderType, ast)); recursiveSetGeneratedBy(builderType.get(), ast, annotationNode.getContext()); - + if ((td.mods.flags & Flags.ABSTRACT) == 0) { // Only non-abstract classes get the Builder implementation. - + // Create the builder implementation class. JavacNode builderImplType = findInnerClass(tdParent, builderImplClassName); if (builderImplType == null) { @@ -296,48 +278,45 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { annotationNode.addError("@SuperBuilder does not support customized builders. Use @Builder instead."); return; } - + // Create a simple constructor for the BuilderImpl class. JCMethodDecl cd = HandleConstructor.createConstructor(AccessLevel.PRIVATE, List.<JCAnnotation>nil(), builderImplType, List.<JavacNode>nil(), false, annotationNode); - if (cd != null) { - injectMethod(builderImplType, cd); - } - + if (cd != null) injectMethod(builderImplType, cd); + // Create the self() and build() methods in the BuilderImpl. injectMethod(builderImplType, generateSelfMethod(builderImplType)); injectMethod(builderImplType, generateBuildMethod(buildMethodName, returnType, builderImplType, thrownExceptions)); - + recursiveSetGeneratedBy(builderImplType.get(), ast, annotationNode.getContext()); } - + // Generate a constructor in the annotated class that takes a builder as argument. generateBuilderBasedConstructor(tdParent, typeParams, builderFields, annotationNode, builderClassName, superclassBuilderClassExpression != null); - + if ((td.mods.flags & Flags.ABSTRACT) == 0) { // Only non-abstract classes get the Builder implementation and the builder() method. - + // Add the builder() method to the annotated class. // Allow users to specify their own builder() methods, e.g., to provide default values. if (methodExists(builderMethodName, tdParent, -1) == MemberExistsResult.NOT_EXISTS) { JCMethodDecl builderMethod = generateBuilderMethod(builderMethodName, builderClassName, builderImplClassName, annotationNode, tdParent, typeParams); recursiveSetGeneratedBy(builderMethod, ast, annotationNode.getContext()); - if (builderMethod != null) { - injectMethod(tdParent, builderMethod); - } + if (builderMethod != null) injectMethod(tdParent, builderMethod); } } } - + /** * Creates and returns the abstract builder class and injects it into the annotated class. */ private JavacNode generateBuilderAbstractClass(JavacNode source, JavacNode tdParent, String builderClass, JCExpression superclassBuilderClassExpression, List<JCTypeParameter> typeParams, List<JCExpression> superclassTypeParams, JCAnnotation ast, String classGenericName, String builderGenericName) { + JavacTreeMaker maker = tdParent.getTreeMaker(); JCModifiers mods = maker.Modifiers(Flags.STATIC | Flags.ABSTRACT | Flags.PUBLIC); - + // Keep any type params of the annotated class. ListBuffer<JCTypeParameter> allTypeParams = new ListBuffer<JCTypeParameter>(); allTypeParams.addAll(copyTypeParams(source, typeParams)); @@ -356,7 +335,7 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { typeParamsForBuilder.add(maker.Ident(tdParent.toName(builderGenericName))); JCTypeApply typeApply = maker.TypeApply(maker.Ident(builderClassName), typeParamsForBuilder.toList()); allTypeParams.add(maker.TypeParameter(tdParent.toName(builderGenericName), List.<JCExpression>of(typeApply))); - + JCExpression extending = null; if (superclassBuilderClassExpression != null) { // If the annotated class extends another class, we want this builder to extend the builder of the superclass. @@ -367,18 +346,18 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { typeParamsForBuilder.add(maker.Ident(tdParent.toName(builderGenericName))); extending = maker.TypeApply(superclassBuilderClassExpression, typeParamsForBuilder.toList()); } - + JCClassDecl builder = maker.ClassDef(mods, builderClassName, allTypeParams.toList(), extending, List.<JCExpression>nil(), List.<JCTree>nil()); return injectType(tdParent, builder); } - + /** * Creates and returns the concrete builder implementation class and injects it into the annotated class. */ private JavacNode generateBuilderImplClass(JavacNode source, JavacNode tdParent, String builderImplClass, String builderAbstractClass, List<JCTypeParameter> typeParams, JCAnnotation ast) { JavacTreeMaker maker = tdParent.getTreeMaker(); JCModifiers mods = maker.Modifiers(Flags.STATIC | Flags.PRIVATE | Flags.FINAL); - + // Extend the abstract builder. JCExpression extending = maker.Ident(tdParent.toName(builderAbstractClass)); // Add any type params of the annotated class. @@ -400,7 +379,7 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { typeParamsForBuilder.add(annotatedClass); typeParamsForBuilder.add(builderImplClassExpression); extending = maker.TypeApply(extending, typeParamsForBuilder.toList()); - + JCClassDecl builder = maker.ClassDef(mods, tdParent.toName(builderImplClass), copyTypeParams(source, typeParams), extending, List.<JCExpression>nil(), List.<JCTree>nil()); return injectType(tdParent, builder); } @@ -422,22 +401,20 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { */ private void generateBuilderBasedConstructor(JavacNode typeNode, List<JCTypeParameter> typeParams, java.util.List<BuilderFieldData> builderFields, JavacNode source, String builderClassName, boolean callBuilderBasedSuperConstructor) { JavacTreeMaker maker = typeNode.getTreeMaker(); - + AccessLevel level = AccessLevel.PROTECTED; - + ListBuffer<JCStatement> nullChecks = new ListBuffer<JCStatement>(); ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>(); - + Name builderVariableName = typeNode.toName("b"); for (BuilderFieldData bfd : builderFields) { List<JCAnnotation> nonNulls = findAnnotations(bfd.originalFieldNode, NON_NULL_PATTERN); if (!nonNulls.isEmpty()) { JCStatement nullCheck = generateNullCheck(maker, bfd.originalFieldNode, source); - if (nullCheck != null) { - nullChecks.append(nullCheck); - } + if (nullCheck != null) nullChecks.append(nullCheck); } - + JCExpression rhs; if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) { bfd.singularData.getSingularizer().appendBuildCode(bfd.singularData, bfd.originalFieldNode, bfd.type, statements, bfd.name, "b"); @@ -446,7 +423,7 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { rhs = maker.Select(maker.Ident(builderVariableName), bfd.rawName); } JCFieldAccess thisX = maker.Select(maker.Ident(typeNode.toName("this")), bfd.rawName); - + JCStatement assign = maker.Exec(maker.Assign(thisX, rhs)); // In case of @Builder.Default, only set the value if it really was set in the builder. @@ -458,9 +435,9 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { statements.append(assign); } } - + JCModifiers mods = maker.Modifiers(toJavacModifier(level), List.<JCAnnotation>nil()); - + // Create a constructor that has just the builder as parameter. ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>(); long flags = JavacHandlerUtil.addFinalIfNeeded(Flags.PARAMETER, typeNode.getContext()); @@ -475,7 +452,7 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { JCTypeApply paramType = maker.TypeApply(maker.Ident(builderClassname), typeParamsForBuilderParameter.toList()); JCVariableDecl param = maker.VarDef(maker.Modifiers(flags), builderVariableName, paramType, null); params.append(param); - + if (callBuilderBasedSuperConstructor) { // The first statement must be the call to the super constructor. JCMethodInvocation callToSuperConstructor = maker.Apply(List.<JCExpression>nil(), @@ -483,29 +460,27 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { List.<JCExpression>of(maker.Ident(builderVariableName))); statements.prepend(maker.Exec(callToSuperConstructor)); } - + JCMethodDecl constr = recursiveSetGeneratedBy(maker.MethodDef(mods, typeNode.toName("<init>"), null, List.<JCTypeParameter>nil(), params.toList(), List.<JCExpression>nil(), maker.Block(0L, nullChecks.appendList(statements).toList()), null), source.get(), typeNode.getContext()); - + injectMethod(typeNode, constr, null, Javac.createVoidType(typeNode.getSymbolTable(), CTC_VOID)); } - + private JCMethodDecl generateBuilderMethod(String builderMethodName, String builderClassName, String builderImplClassName, JavacNode source, JavacNode type, List<JCTypeParameter> typeParams) { JavacTreeMaker maker = type.getTreeMaker(); - + ListBuffer<JCExpression> typeArgs = new ListBuffer<JCExpression>(); - for (JCTypeParameter typeParam : typeParams) { - typeArgs.append(maker.Ident(typeParam.name)); - } - + for (JCTypeParameter typeParam : typeParams) typeArgs.append(maker.Ident(typeParam.name)); + JCExpression call = maker.NewClass(null, List.<JCExpression>nil(), namePlusTypeParamsToTypeReference(maker, type.toName(builderImplClassName), typeParams), List.<JCExpression>nil(), null); JCStatement statement = maker.Return(call); - + JCBlock body = maker.Block(0, List.<JCStatement>of(statement)); int modifiers = Flags.PUBLIC; modifiers |= Flags.STATIC; - + // Add any type params of the annotated class to the return type. ListBuffer<JCExpression> typeParameterNames = new ListBuffer<JCExpression>(); typeParameterNames.addAll(typeParameterNames(maker, typeParams)); @@ -514,10 +489,10 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { typeParameterNames.add(wildcard); typeParameterNames.add(wildcard); JCTypeApply returnType = maker.TypeApply(maker.Ident(type.toName(builderClassName)), typeParameterNames.toList()); - + return maker.MethodDef(maker.Modifiers(modifiers), type.toName(builderMethodName), returnType, copyTypeParams(source, typeParams), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null); } - + private JCMethodDecl generateAbstractSelfMethod(JavacNode type, boolean override, String builderGenericName) { JavacTreeMaker maker = type.getTreeMaker(); List<JCAnnotation> annotations = List.nil(); @@ -528,24 +503,24 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { JCModifiers modifiers = maker.Modifiers(Flags.PROTECTED | Flags.ABSTRACT, annotations); Name name = type.toName(SELF_METHOD); JCExpression returnType = maker.Ident(type.toName(builderGenericName)); - + return maker.MethodDef(modifiers, name, returnType, List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), null, null); } - + private JCMethodDecl generateSelfMethod(JavacNode builderImplType) { JavacTreeMaker maker = builderImplType.getTreeMaker(); - + JCAnnotation overrideAnnotation = maker.Annotation(genJavaLangTypeRef(builderImplType, "Override"), List.<JCExpression>nil()); JCModifiers modifiers = maker.Modifiers(Flags.PROTECTED, List.of(overrideAnnotation)); Name name = builderImplType.toName(SELF_METHOD); JCExpression returnType = maker.Ident(builderImplType.toName(builderImplType.getName())); - + JCStatement statement = maker.Return(maker.Ident(builderImplType.toName("this"))); JCBlock body = maker.Block(0, List.<JCStatement>of(statement)); - + return maker.MethodDef(modifiers, name, returnType, List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null); } - + private JCMethodDecl generateAbstractBuildMethod(JavacNode type, String methodName, boolean override, String classGenericName) { JavacTreeMaker maker = type.getTreeMaker(); List<JCAnnotation> annotations = List.nil(); @@ -556,53 +531,51 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { JCModifiers modifiers = maker.Modifiers(Flags.PUBLIC | Flags.ABSTRACT, annotations); Name name = type.toName(methodName); JCExpression returnType = maker.Ident(type.toName(classGenericName)); - + return maker.MethodDef(modifiers, name, returnType, List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), null, null); } private JCMethodDecl generateBuildMethod(String buildName, JCExpression returnType, JavacNode type, List<JCExpression> thrownExceptions) { JavacTreeMaker maker = type.getTreeMaker(); - + JCExpression call; ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>(); - + // Use a constructor that only has this builder as parameter. List<JCExpression> builderArg = List.<JCExpression>of(maker.Ident(type.toName("this"))); call = maker.NewClass(null, List.<JCExpression>nil(), returnType, builderArg, null); statements.append(maker.Return(call)); - + JCBlock body = maker.Block(0, statements.toList()); - + JCAnnotation overrideAnnotation = maker.Annotation(genJavaLangTypeRef(type, "Override"), List.<JCExpression>nil()); JCModifiers modifiers = maker.Modifiers(Flags.PUBLIC, List.of(overrideAnnotation)); - + return maker.MethodDef(modifiers, type.toName(buildName), returnType, List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), thrownExceptions, body, null); } - + private JCMethodDecl generateCleanMethod(java.util.List<BuilderFieldData> builderFields, JavacNode type, JCTree source) { JavacTreeMaker maker = type.getTreeMaker(); ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>(); - + for (BuilderFieldData bfd : builderFields) { if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) { bfd.singularData.getSingularizer().appendCleaningCode(bfd.singularData, type, source, statements); } } - + statements.append(maker.Exec(maker.Assign(maker.Select(maker.Ident(type.toName("this")), type.toName("$lombokUnclean")), maker.Literal(CTC_BOOLEAN, 0)))); JCBlock body = maker.Block(0, statements.toList()); return maker.MethodDef(maker.Modifiers(Flags.PUBLIC), type.toName("$lombokClean"), maker.Type(Javac.createVoidType(type.getSymbolTable(), CTC_VOID)), List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null); } - + private void generateBuilderFields(JavacNode builderType, java.util.List<BuilderFieldData> builderFields, JCTree source) { int len = builderFields.size(); java.util.List<JavacNode> existing = new ArrayList<JavacNode>(); for (JavacNode child : builderType.down()) { - if (child.getKind() == Kind.FIELD) { - existing.add(child); - } + if (child.getKind() == Kind.FIELD) existing.add(child); } - + for (int i = len - 1; i >= 0; i--) { BuilderFieldData bfd = builderFields.get(i); if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) { @@ -611,12 +584,8 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { JavacNode field = null, setFlag = null; for (JavacNode exists : existing) { Name n = ((JCVariableDecl) exists.get()).name; - if (n.equals(bfd.name)) { - field = exists; - } - if (n.equals(bfd.nameOfSetFlag)) { - setFlag = exists; - } + if (n.equals(bfd.name)) field = exists; + if (n.equals(bfd.nameOfSetFlag)) setFlag = exists; } JavacTreeMaker maker = builderType.getTreeMaker(); if (field == null) { @@ -633,52 +602,47 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { } } } - + private void generateSetterMethodsForBuilder(final JavacNode builderType, BuilderFieldData fieldNode, JavacNode source, final String builderGenericName) { boolean deprecate = isFieldDeprecated(fieldNode.originalFieldNode); final JavacTreeMaker maker = builderType.getTreeMaker(); - // TODO: Make these lambdas when switching to a source level >= 1.8. - Supplier<JCExpression> returnType = new Supplier<JCExpression>() { @Override public JCExpression get() { + ExpressionMaker returnTypeMaker = new ExpressionMaker() { @Override public JCExpression make() { return maker.Ident(builderType.toName(builderGenericName)); }}; - Supplier<? extends JCReturn> returnStatement = new Supplier<JCReturn>() { @Override public JCReturn get() { + + StatementMaker returnStatementMaker = new StatementMaker() { @Override public JCStatement make() { return maker.Return(maker.Apply(List.<JCExpression>nil(), maker.Ident(builderType.toName(SELF_METHOD)), List.<JCExpression>nil())); }}; + if (fieldNode.singularData == null || fieldNode.singularData.getSingularizer() == null) { - generateSimpleSetterMethodForBuilder(builderType, deprecate, fieldNode.createdFields.get(0), fieldNode.nameOfSetFlag, source, true, true, returnType.get(), returnStatement.get()); + generateSimpleSetterMethodForBuilder(builderType, deprecate, fieldNode.createdFields.get(0), fieldNode.nameOfSetFlag, source, true, true, returnTypeMaker.make(), returnStatementMaker.make()); } else { - fieldNode.singularData.getSingularizer().generateMethods(fieldNode.singularData, deprecate, builderType, source.get(), true, returnType, returnStatement); + fieldNode.singularData.getSingularizer().generateMethods(fieldNode.singularData, deprecate, builderType, source.get(), true, returnTypeMaker, returnStatementMaker); } } - - private void generateSimpleSetterMethodForBuilder(JavacNode builderType, boolean deprecate, JavacNode fieldNode, Name nameOfSetFlag, JavacNode source, boolean fluent, boolean chain, JCExpression returnType, JCReturn returnStatement) { + + private void generateSimpleSetterMethodForBuilder(JavacNode builderType, boolean deprecate, JavacNode fieldNode, Name nameOfSetFlag, JavacNode source, boolean fluent, boolean chain, JCExpression returnType, JCStatement returnStatement) { Name fieldName = ((JCVariableDecl) fieldNode.get()).name; - + for (JavacNode child : builderType.down()) { - if (child.getKind() != Kind.METHOD) { - continue; - } + if (child.getKind() != Kind.METHOD) continue; JCMethodDecl methodDecl = (JCMethodDecl) child.get(); Name existingName = methodDecl.name; - if (existingName.equals(fieldName) && !isTolerate(fieldNode, methodDecl)) { - return; - } + if (existingName.equals(fieldName) && !isTolerate(fieldNode, methodDecl)) return; } - + String setterName = fluent ? fieldNode.getName() : HandlerUtil.buildAccessorName("set", fieldNode.getName()); - + JavacTreeMaker maker = fieldNode.getTreeMaker(); - + JCMethodDecl newMethod = HandleSetter.createSetter(Flags.PUBLIC, deprecate, fieldNode, maker, setterName, nameOfSetFlag, returnType, returnStatement, source, List.<JCAnnotation>nil(), List.<JCAnnotation>nil()); - + injectMethod(builderType, newMethod); } - + private void addObtainVia(BuilderFieldData bfd, JavacNode node) { for (JavacNode child : node.down()) { - if (!annotationTypeMatches(ObtainVia.class, child)) { - continue; - } + if (!annotationTypeMatches(ObtainVia.class, child)) continue; AnnotationValues<ObtainVia> ann = createAnnotation(ObtainVia.class, child); bfd.obtainVia = ann.getInstance(); bfd.obtainViaNode = child; @@ -686,7 +650,7 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { return; } } - + /** * Returns the explicitly requested singular annotation on this node (field * or parameter), or null if there's no {@code @Singular} annotation on it. @@ -695,9 +659,7 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { */ private SingularData getSingularData(JavacNode node) { for (JavacNode child : node.down()) { - if (!annotationTypeMatches(Singular.class, child)) { - continue; - } + if (!annotationTypeMatches(Singular.class, child)) continue; Name pluralName = node.getKind() == Kind.FIELD ? removePrefixFromField(node) : ((JCVariableDecl) node.get()).name; AnnotationValues<Singular> ann = createAnnotation(Singular.class, child); deleteAnnotationIfNeccessary(child, Singular.class); @@ -715,58 +677,48 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { } } Name singularName = node.toName(explicitSingular); - + JCExpression type = null; - if (node.get() instanceof JCVariableDecl) { - type = ((JCVariableDecl) node.get()).vartype; - } - + if (node.get() instanceof JCVariableDecl) type = ((JCVariableDecl) node.get()).vartype; + String name = null; List<JCExpression> typeArgs = List.nil(); if (type instanceof JCTypeApply) { typeArgs = ((JCTypeApply) type).arguments; type = ((JCTypeApply) type).clazz; } - + name = type.toString(); - + String targetFqn = JavacSingularsRecipes.get().toQualified(name); JavacSingularizer singularizer = JavacSingularsRecipes.get().getSingularizer(targetFqn); if (singularizer == null) { node.addError("Lombok does not know how to create the singular-form builder methods for type '" + name + "'; they won't be generated."); return null; } - + return new SingularData(child, singularName, pluralName, typeArgs, targetFqn, singularizer); } - + return null; } - + private String generateNonclashingNameFor(String classGenericName, java.util.List<String> typeParamStrings) { - if (!typeParamStrings.contains(classGenericName)) { - return classGenericName; - } + if (!typeParamStrings.contains(classGenericName)) return classGenericName; int counter = 2; - while (typeParamStrings.contains(classGenericName + counter)) { - counter++; - } + while (typeParamStrings.contains(classGenericName + counter)) counter++; return classGenericName + counter; } - + private JavacNode findInnerClass(JavacNode parent, String name) { for (JavacNode child : parent.down()) { - if (child.getKind() != Kind.TYPE) { - continue; - } + if (child.getKind() != Kind.TYPE) continue; JCClassDecl td = (JCClassDecl) child.get(); - if (td.name.contentEquals(name)) { - return child; - } + if (td.name.contentEquals(name)) return child; } return null; } - + private ListBuffer<JCExpression> getTypeParamExpressions(List<? extends JCTree> typeParams, JavacTreeMaker maker) { ListBuffer<JCExpression> typeParamsForBuilderParameter = new ListBuffer<JCExpression>(); for (JCTree typeParam : typeParams) { |