diff options
Diffstat (limited to 'src/core/lombok')
12 files changed, 374 insertions, 456 deletions
diff --git a/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java b/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java index e24cd5b5..b9b9e07d 100644 --- a/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java +++ b/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015-2017 The Project Lombok Authors. + * Copyright (C) 2015-2018 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -30,7 +30,6 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.function.Supplier; import org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; @@ -65,6 +64,14 @@ import lombok.core.TypeLibrary; import lombok.eclipse.EclipseNode; public class EclipseSingularsRecipes { + public interface TypeReferenceMaker { + TypeReference make(); + } + + public interface StatementMaker { + Statement make(); + } + private static final EclipseSingularsRecipes INSTANCE = new EclipseSingularsRecipes(); private final Map<String, EclipseSingularizer> singularizers = new HashMap<String, EclipseSingularizer>(); private final TypeLibrary singularizableTypes = new TypeLibrary(); @@ -220,37 +227,35 @@ public class EclipseSingularsRecipes { } public abstract List<EclipseNode> generateFields(SingularData data, EclipseNode builderType); - + /** - * Generates the singular, plural, and clear methods for the given - * {@link SingularData}.<br> - * Uses the given <code>builderType</code> as return type if - * <code>chain == true</code>, <code>void</code> otherwise. If you need more - * control over the return type and value, use - * {@link #generateMethods(SingularData, boolean, EclipseNode, boolean, Supplier, Supplier)}. + * Generates the singular, plural, and clear methods for the given {@link SingularData}. + * Uses the given {@code builderType} as return type if {@code chain == true}, {@code void} otherwise. + * If you need more control over the return type and value, use + * {@link #generateMethods(SingularData, boolean, EclipseNode, boolean, TypeReferenceMaker, StatementMaker)}. */ public void generateMethods(SingularData data, boolean deprecate, final EclipseNode builderType, boolean fluent, final boolean chain) { - // TODO: Make these lambdas when switching to a source level >= 1.8. - Supplier<TypeReference> returnType = new Supplier<TypeReference>() { - @Override public TypeReference get() { + TypeReferenceMaker returnTypeMaker = new TypeReferenceMaker() { + @Override public TypeReference make() { return chain ? cloneSelfType(builderType) : TypeReference.baseTypeReference(TypeIds.T_void, 0); } }; - Supplier<ReturnStatement> returnStatement = new Supplier<ReturnStatement>() { - @Override public ReturnStatement get() { + + StatementMaker returnStatementMaker = new StatementMaker() { + @Override public ReturnStatement make() { return chain ? new ReturnStatement(new ThisReference(0, 0), 0, 0) : null; } }; - generateMethods(data, deprecate, builderType, fluent, returnType, returnStatement); + + generateMethods(data, deprecate, builderType, fluent, returnTypeMaker, returnStatementMaker); } /** - * Generates the singular, plural, and clear methods for the given - * {@link SingularData}.<br> - * Uses the given <code>returnType</code> and <code>returnStatement</code> for the generated methods. + * Generates the singular, plural, and clear methods for the given {@link SingularData}. + * Uses the given {@code returnTypeMaker} and {@code returnStatementMaker} for the generated methods. */ - public abstract void generateMethods(SingularData data, boolean deprecate, EclipseNode builderType, boolean fluent, Supplier<TypeReference> returnType, Supplier<ReturnStatement> returnStatement); - + public abstract void generateMethods(SingularData data, boolean deprecate, EclipseNode builderType, boolean fluent, TypeReferenceMaker returnTypeMaker, StatementMaker returnStatementMaker); + public abstract void appendBuildCode(SingularData data, EclipseNode builderType, List<Statement> statements, char[] targetVariableName, String builderVariable); public boolean requiresCleaning() { diff --git a/src/core/lombok/eclipse/handlers/HandleSetter.java b/src/core/lombok/eclipse/handlers/HandleSetter.java index 434939a6..92489c09 100644 --- a/src/core/lombok/eclipse/handlers/HandleSetter.java +++ b/src/core/lombok/eclipse/handlers/HandleSetter.java @@ -212,7 +212,7 @@ public class HandleSetter extends EclipseAnnotationHandler<Setter> { return createSetter(parent, deprecate, fieldNode, name, booleanFieldToSet, returnType, returnThis, modifier, sourceNode, onMethod, onParam); } - static MethodDeclaration createSetter(TypeDeclaration parent, boolean deprecate, EclipseNode fieldNode, String name, char[] booleanFieldToSet, TypeReference returnType, ReturnStatement returnStatement, int modifier, EclipseNode sourceNode, List<Annotation> onMethod, List<Annotation> onParam) { + static MethodDeclaration createSetter(TypeDeclaration parent, boolean deprecate, EclipseNode fieldNode, String name, char[] booleanFieldToSet, TypeReference returnType, Statement returnStatement, int modifier, EclipseNode sourceNode, List<Annotation> onMethod, List<Annotation> onParam) { FieldDeclaration field = (FieldDeclaration) fieldNode.get(); ASTNode source = sourceNode.get(); int pS = source.sourceStart, pE = source.sourceEnd; diff --git a/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java b/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java index 1100cbf0..12fc4761 100644 --- a/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java +++ b/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java @@ -30,7 +30,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; -import java.util.function.Supplier; import org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; @@ -85,20 +84,21 @@ import lombok.eclipse.handlers.EclipseHandlerUtil.FieldAccess; import lombok.eclipse.handlers.EclipseHandlerUtil.MemberExistsResult; import lombok.eclipse.handlers.EclipseSingularsRecipes.EclipseSingularizer; import lombok.eclipse.handlers.EclipseSingularsRecipes.SingularData; +import lombok.eclipse.handlers.EclipseSingularsRecipes.StatementMaker; +import lombok.eclipse.handlers.EclipseSingularsRecipes.TypeReferenceMaker; 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[] SET_PREFIX = "$set".toCharArray(); private static final char[] SELF_METHOD_NAME = "self".toCharArray(); - + private static final AbstractMethodDeclaration[] EMPTY_METHODS = {}; - + private static class BuilderFieldData { TypeReference type; char[] rawName; @@ -108,49 +108,41 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> { ObtainVia obtainVia; EclipseNode obtainViaNode; EclipseNode originalFieldNode; - + List<EclipseNode> createdFields = new ArrayList<EclipseNode>(); } - + @Override public void handle(AnnotationValues<SuperBuilder> annotation, Annotation ast, EclipseNode annotationNode) { handleExperimentalFlagUsage(annotationNode, ConfigurationKeys.SUPERBUILDER_FLAG_USAGE, "@SuperBuilder"); long p = (long) ast.sourceStart << 32 | ast.sourceEnd; - + SuperBuilder builderInstance = annotation.getInstance(); - + String builderMethodName = builderInstance.builderMethodName(); String buildMethodName = builderInstance.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; + EclipseNode tdParent = annotationNode.up(); - + java.util.List<BuilderFieldData> builderFields = new ArrayList<BuilderFieldData>(); TypeReference returnType; TypeParameter[] typeParams; - + boolean addCleaning = false; - + if (!(tdParent.get() instanceof TypeDeclaration)) { annotationNode.addError("@SuperBuilder is only supported on types."); return; } TypeDeclaration td = (TypeDeclaration) tdParent.get(); - + // Gather all fields of the class that should be set by the builder. List<EclipseNode> allFields = new ArrayList<EclipseNode>(); boolean valuePresent = (hasAnnotation(lombok.Value.class, tdParent) || hasAnnotation("lombok.experimental.Value", tdParent)); @@ -158,31 +150,31 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> { FieldDeclaration fd = (FieldDeclaration) fieldNode.get(); EclipseNode isDefault = findAnnotation(Builder.Default.class, fieldNode); boolean isFinal = ((fd.modifiers & ClassFileConstants.AccFinal) != 0) || (valuePresent && !hasAnnotation(NonFinal.class, fieldNode)); - + BuilderFieldData bfd = new BuilderFieldData(); bfd.rawName = fieldNode.getName().toCharArray(); bfd.name = removePrefixFromField(fieldNode); bfd.type = fd.type; bfd.singularData = getSingularData(fieldNode, ast); bfd.originalFieldNode = fieldNode; - + if (bfd.singularData != null && isDefault != null) { isDefault.addError("@Builder.Default and @Singular cannot be mixed."); isDefault = null; } - + if (fd.initialization == null && isDefault != null) { isDefault.addWarning("@Builder.Default requires an initializing expression (' = something;')."); isDefault = null; } - + if (fd.initialization != null && isDefault == null) { if (isFinal) { continue; } fieldNode.addWarning("@Builder 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 = prefixWith(bfd.name, SET_PREFIX); // The @Builder annotation removes the initializing expression on the field and moves @@ -199,26 +191,24 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> { builderFields.add(bfd); allFields.add(fieldNode); } - + // Set the names of the builder classes. String builderClassName = String.valueOf(td.name) + "Builder"; String builderImplClassName = builderClassName + "Impl"; typeParams = td.typeParameters != null ? td.typeParameters : new TypeParameter[0]; returnType = namePlusTypeParamsToTypeReference(td.name, typeParams, p); - + // <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 (TypeParameter typeParam : typeParams) { - typeParamStrings.add(typeParam.toString()); - } + for (TypeParameter typeParam : typeParams) typeParamStrings.add(typeParam.toString()); classGenericName = generateNonclashingNameFor(classGenericName, typeParamStrings); builderGenericName = generateNonclashingNameFor(builderGenericName, typeParamStrings); - + TypeReference extendsClause = td.superclass; TypeReference superclassBuilderClass = null; TypeReference[] typeArguments = new TypeReference[] { @@ -229,12 +219,12 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> { QualifiedTypeReference qualifiedTypeReference = (QualifiedTypeReference)extendsClause; String superclassClassName = String.valueOf(qualifiedTypeReference.getLastToken()); String superclassBuilderClassName = superclassClassName + "Builder"; - + char[][] tokens = Arrays.copyOf(qualifiedTypeReference.tokens, qualifiedTypeReference.tokens.length + 1); tokens[tokens.length] = superclassBuilderClassName.toCharArray(); long[] poss = new long[tokens.length]; Arrays.fill(poss, p); - + TypeReference[] superclassTypeArgs = getTypeParametersFrom(extendsClause); // Every token may potentially have type args. Here, we only have @@ -246,7 +236,7 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> { } else if (extendsClause != null) { String superClass = String.valueOf(extendsClause.getTypeName()[0]); String superclassBuilderClassName = superClass + "Builder"; - + char[][] tokens = new char[][] {superClass.toCharArray(), superclassBuilderClassName.toCharArray()}; long[] poss = new long[tokens.length]; Arrays.fill(poss, p); @@ -262,21 +252,20 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> { } // If there is no superclass, superclassBuilderClassExpression is still == null at this point. // You can use it to check whether to inherit or not. - + generateBuilderBasedConstructor(tdParent, typeParams, builderFields, annotationNode, builderClassName, - superclassBuilderClass != null); - + superclassBuilderClass != null); + // Create the abstract builder class. EclipseNode builderType = findInnerClass(tdParent, builderClassName); if (builderType == null) { builderType = generateBuilderAbstractClass(tdParent, builderClassName, superclassBuilderClass, - typeParams, ast, classGenericName, builderGenericName); - + typeParams, ast, classGenericName, builderGenericName); } else { annotationNode.addError("@SuperBuilder does not support customized builders. Use @Builder instead."); return; } - + // 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) { @@ -296,7 +285,7 @@ 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); if (addCleaning) { @@ -306,16 +295,16 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> { cleanDecl.type = TypeReference.baseTypeReference(TypeIds.T_boolean, 0); injectFieldAndMarkGenerated(builderType, cleanDecl); } - + // Generate abstract self() and build() methods in the abstract builder. injectMethod(builderType, generateAbstractSelfMethod(tdParent, superclassBuilderClass != null, builderGenericName)); injectMethod(builderType, generateAbstractBuildMethod(tdParent, buildMethodName, superclassBuilderClass != null, classGenericName, ast)); - + // 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. if (methodExists("toString", builderType, 0) == MemberExistsResult.NOT_EXISTS) { java.util.List<EclipseNode> fieldNodes = new ArrayList<EclipseNode>(); @@ -328,16 +317,14 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> { injectMethod(builderType, md); } } - - if (addCleaning) { - injectMethod(builderType, generateCleanMethod(builderFields, builderType, ast)); - } - + + if (addCleaning) injectMethod(builderType, generateCleanMethod(builderFields, builderType, ast)); + if ((td.modifiers & ClassFileConstants.AccAbstract) != 0) { - // Abstract classes to not get the Builder implementation nor the builder() method. + // Only non-abstract classes get the Builder implementation. return; } - + // Create the builder implementation class. EclipseNode builderImplType = findInnerClass(tdParent, builderImplClassName); if (builderImplType == null) { @@ -346,30 +333,28 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> { annotationNode.addError("@SuperBuilder does not support customized builders. Use @Builder instead."); return; } - + // Create the self() and build() methods in the BuilderImpl. injectMethod(builderImplType, generateSelfMethod(builderImplType)); injectMethod(builderImplType, generateBuildMethod(tdParent, buildMethodName, returnType, ast)); - + // Add the builder() method to the annotated class. if (methodExists(builderMethodName, tdParent, -1) == MemberExistsResult.NOT_EXISTS) { MethodDeclaration md = generateBuilderMethod(builderMethodName, builderClassName, builderImplClassName, tdParent, typeParams, ast); - if (md != null) { - injectMethod(tdParent, md); - } + if (md != null) injectMethod(tdParent, md); } } - + private EclipseNode generateBuilderAbstractClass(EclipseNode tdParent, String builderClass, TypeReference superclassBuilderClass, TypeParameter[] typeParams, ASTNode source, String classGenericName, String builderGenericName) { - + TypeDeclaration parent = (TypeDeclaration) tdParent.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(); - + // Keep any type params of the annotated class. builder.typeParameters = Arrays.copyOf(copyTypeParams(typeParams, source), typeParams.length + 2); // Add builder-specific type params required for inheritable builders. @@ -384,15 +369,15 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> { TypeReference[] typerefs = appendBuilderTypeReferences(typeParams, classGenericName, builderGenericName); o.type = new ParameterizedSingleTypeReference(builderClass.toCharArray(), typerefs, 0, 0); builder.typeParameters[builder.typeParameters.length - 1] = o; - + builder.superclass = copyType(superclassBuilderClass, source); - - builder.createDefaultConstructor(false, true); + builder.createDefaultConstructor(false, true); + builder.traverse(new SetGeneratedByVisitor(source), (ClassScope) null); return injectType(tdParent, builder); } - + private EclipseNode generateBuilderImplClass(EclipseNode tdParent, String builderImplClass, String builderAbstractClass, TypeParameter[] typeParams, ASTNode source) { TypeDeclaration parent = (TypeDeclaration) tdParent.get(); TypeDeclaration builder = new TypeDeclaration(parent.compilationResult); @@ -401,9 +386,8 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> { builder.name = builderImplClass.toCharArray(); // Add type params if there are any. - if (typeParams != null && typeParams.length > 0) { - builder.typeParameters = copyTypeParams(typeParams, source); - } + if (typeParams != null && typeParams.length > 0) builder.typeParameters = copyTypeParams(typeParams, source); + if (builderAbstractClass != null) { // Extend the abstract builder. // 1. Add any type params of the annotated class. @@ -423,7 +407,7 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> { builder.traverse(new SetGeneratedByVisitor(source), (ClassScope) null); return injectType(tdParent, 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. @@ -441,14 +425,14 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> { */ private void generateBuilderBasedConstructor(EclipseNode typeNode, TypeParameter[] typeParams, List<BuilderFieldData> builderFields, EclipseNode sourceNode, String builderClassName, boolean callBuilderBasedSuperConstructor) { - + ASTNode source = sourceNode.get(); - + TypeDeclaration typeDeclaration = ((TypeDeclaration) typeNode.get()); long p = (long) source.sourceStart << 32 | source.sourceEnd; - + ConstructorDeclaration constructor = new ConstructorDeclaration(((CompilationUnitDeclaration) typeNode.top().get()).compilationResult); - + constructor.modifiers = toEclipseModifier(AccessLevel.PROTECTED); constructor.selector = typeDeclaration.name; if (callBuilderBasedSuperConstructor) { @@ -468,17 +452,17 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> { TypeReference[] wildcards = new TypeReference[] {new Wildcard(Wildcard.UNBOUND), new Wildcard(Wildcard.UNBOUND)}; TypeReference builderType = new ParameterizedSingleTypeReference(builderClassName.toCharArray(), mergeToTypeReferences(typeParams, wildcards), 0, p); constructor.arguments = new Argument[] {new Argument("b".toCharArray(), p, builderType, Modifier.FINAL)}; - + List<Statement> statements = new ArrayList<Statement>(); List<Statement> nullChecks = new ArrayList<Statement>(); - + for (BuilderFieldData fieldNode : builderFields) { char[] fieldName = removePrefixFromField(fieldNode.originalFieldNode); FieldReference thisX = new FieldReference(fieldNode.rawName, p); int s = (int) (p >> 32); int e = (int) p; thisX.receiver = new ThisReference(s, e); - + Expression assignmentExpr; if (fieldNode.singularData != null && fieldNode.singularData.getSingularizer() != null) { fieldNode.singularData.getSingularizer().appendBuildCode(fieldNode.singularData, typeNode, statements, fieldNode.name, "b"); @@ -507,51 +491,48 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> { } } } - + nullChecks.addAll(statements); constructor.statements = nullChecks.isEmpty() ? null : nullChecks.toArray(new Statement[nullChecks.size()]); - + constructor.traverse(new SetGeneratedByVisitor(source), typeDeclaration.scope); - + injectMethod(typeNode, constructor); } private MethodDeclaration generateBuilderMethod(String builderMethodName, String builderClassName, String builderImplClassName, EclipseNode type, TypeParameter[] typeParams, ASTNode source) { int pS = source.sourceStart, pE = source.sourceEnd; long p = (long) pS << 32 | pE; - + MethodDeclaration out = new MethodDeclaration(((CompilationUnitDeclaration) type.top().get()).compilationResult); out.selector = 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 (typeParams != null && typeParams.length > 0) out.typeParameters = copyTypeParams(typeParams, source); + TypeReference[] wildcards = new TypeReference[] {new Wildcard(Wildcard.UNBOUND), new Wildcard(Wildcard.UNBOUND) }; out.returnType = new ParameterizedSingleTypeReference(builderClassName.toCharArray(), mergeToTypeReferences(typeParams, wildcards), 0, p); AllocationExpression invoke = new AllocationExpression(); invoke.type = namePlusTypeParamsToTypeReference(builderImplClassName.toCharArray(), typeParams, p); out.statements = new Statement[] {new ReturnStatement(invoke, pS, pE)}; - + out.traverse(new SetGeneratedByVisitor(source), ((TypeDeclaration) type.get()).scope); return out; } - + private MethodDeclaration generateAbstractSelfMethod(EclipseNode tdParent, boolean override, String builderGenericName) { MethodDeclaration out = new MethodDeclaration(((CompilationUnitDeclaration) tdParent.top().get()).compilationResult); out.selector = SELF_METHOD_NAME; out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG; out.modifiers = ClassFileConstants.AccAbstract | ClassFileConstants.AccProtected | ExtraCompilerModifiers.AccSemicolonBody; - if (override) { - out.annotations = new Annotation[] {makeMarkerAnnotation(TypeConstants.JAVA_LANG_OVERRIDE, tdParent.get())}; - } + if (override) out.annotations = new Annotation[] {makeMarkerAnnotation(TypeConstants.JAVA_LANG_OVERRIDE, tdParent.get())}; out.returnType = new SingleTypeReference(builderGenericName.toCharArray(), 0); return out; } - + private MethodDeclaration generateSelfMethod(EclipseNode builderImplType) { MethodDeclaration out = new MethodDeclaration(((CompilationUnitDeclaration) builderImplType.top().get()).compilationResult); out.selector = SELF_METHOD_NAME; @@ -562,35 +543,33 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> { out.statements = new Statement[] {new ReturnStatement(new ThisReference(0, 0), 0, 0)}; return out; } - + private MethodDeclaration generateAbstractBuildMethod(EclipseNode tdParent, String methodName, boolean override, String classGenericName, ASTNode source) { + MethodDeclaration out = new MethodDeclaration(((CompilationUnitDeclaration) tdParent.top().get()).compilationResult); out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG; - + out.modifiers = ClassFileConstants.AccPublic | ClassFileConstants.AccAbstract | ExtraCompilerModifiers.AccSemicolonBody; out.selector = methodName.toCharArray(); out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG; out.returnType = new SingleTypeReference(classGenericName.toCharArray(), 0); - if (override) { - out.annotations = new Annotation[] {makeMarkerAnnotation(TypeConstants.JAVA_LANG_OVERRIDE, source)}; - } + if (override) out.annotations = new Annotation[] {makeMarkerAnnotation(TypeConstants.JAVA_LANG_OVERRIDE, source)}; out.traverse(new SetGeneratedByVisitor(source), (ClassScope) null); return out; } - - private MethodDeclaration generateBuildMethod(EclipseNode tdParent, String name, TypeReference returnType, ASTNode source) { + private MethodDeclaration generateBuildMethod(EclipseNode tdParent, String name, TypeReference returnType, ASTNode source) { MethodDeclaration out = new MethodDeclaration(((CompilationUnitDeclaration) tdParent.top().get()).compilationResult); out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG; List<Statement> statements = new ArrayList<Statement>(); - + out.modifiers = ClassFileConstants.AccPublic; out.selector = name.toCharArray(); out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG; out.returnType = returnType; out.annotations = new Annotation[] {makeMarkerAnnotation(TypeConstants.JAVA_LANG_OVERRIDE, source)}; - + AllocationExpression allocationStatement = new AllocationExpression(); allocationStatement.type = copyType(out.returnType); // Use a constructor that only has this builder as parameter. @@ -600,16 +579,16 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> { out.traverse(new SetGeneratedByVisitor(source), (ClassScope) null); return out; } - + private MethodDeclaration generateCleanMethod(List<BuilderFieldData> builderFields, EclipseNode builderType, ASTNode source) { List<Statement> statements = new ArrayList<Statement>(); - + for (BuilderFieldData bfd : builderFields) { if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) { bfd.singularData.getSingularizer().appendCleaningCode(bfd.singularData, 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)); @@ -622,15 +601,13 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> { decl.traverse(new SetGeneratedByVisitor(source), (ClassScope) null); return decl; } - + private void generateBuilderFields(EclipseNode builderType, List<BuilderFieldData> builderFields, ASTNode source) { List<EclipseNode> existing = new ArrayList<EclipseNode>(); for (EclipseNode child : builderType.down()) { - if (child.getKind() == Kind.FIELD) { - existing.add(child); - } + if (child.getKind() == Kind.FIELD) existing.add(child); } - + for (BuilderFieldData bfd : builderFields) { if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) { bfd.createdFields.addAll(bfd.singularData.getSingularizer().generateFields(bfd.singularData, builderType)); @@ -638,14 +615,10 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> { EclipseNode field = null, setFlag = null; for (EclipseNode exists : existing) { char[] n = ((FieldDeclaration) exists.get()).name; - if (Arrays.equals(n, bfd.name)) { - field = exists; - } - if (bfd.nameOfSetFlag != null && Arrays.equals(n, bfd.nameOfSetFlag)) { - setFlag = exists; - } + if (Arrays.equals(n, bfd.name)) field = exists; + if (bfd.nameOfSetFlag != null && Arrays.equals(n, bfd.nameOfSetFlag)) setFlag = exists; } - + if (field == null) { FieldDeclaration fd = new FieldDeclaration(bfd.name, 0, 0); fd.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG; @@ -666,70 +639,63 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> { } } } - + private void generateSetterMethodsForBuilder(EclipseNode builderType, BuilderFieldData bfd, EclipseNode sourceNode, final String builderGenericName) { boolean deprecate = isFieldDeprecated(bfd.originalFieldNode); - - // TODO: Make these lambdas when switching to a source level >= 1.8. - Supplier<TypeReference> returnType = new Supplier<TypeReference>() { - @Override public TypeReference get() { + + TypeReferenceMaker returnTypeMaker = new TypeReferenceMaker() { + @Override public TypeReference make() { return new SingleTypeReference(builderGenericName.toCharArray(), 0); } }; - Supplier<ReturnStatement> returnStatement = new Supplier<ReturnStatement>() { - @Override public ReturnStatement get() { + + StatementMaker returnStatementMaker = new StatementMaker() { + @Override public ReturnStatement make() { MessageSend returnCall = new MessageSend(); returnCall.receiver = ThisReference.implicitThis(); returnCall.selector = SELF_METHOD_NAME; return new ReturnStatement(returnCall, 0, 0); } }; + if (bfd.singularData == null || bfd.singularData.getSingularizer() == null) { - generateSimpleSetterMethodForBuilder(builderType, deprecate, bfd.createdFields.get(0), bfd.nameOfSetFlag, returnType.get(), returnStatement.get(), sourceNode); + generateSimpleSetterMethodForBuilder(builderType, deprecate, bfd.createdFields.get(0), bfd.nameOfSetFlag, returnTypeMaker.make(), returnStatementMaker.make(), sourceNode); } else { - bfd.singularData.getSingularizer().generateMethods(bfd.singularData, deprecate, builderType, true, returnType, returnStatement); + bfd.singularData.getSingularizer().generateMethods(bfd.singularData, deprecate, builderType, true, returnTypeMaker, returnStatementMaker); } } - private void generateSimpleSetterMethodForBuilder(EclipseNode builderType, boolean deprecate, EclipseNode fieldNode, char[] nameOfSetFlag, TypeReference returnType, ReturnStatement returnStatement, EclipseNode sourceNode) { + private void generateSimpleSetterMethodForBuilder(EclipseNode builderType, boolean deprecate, EclipseNode fieldNode, char[] nameOfSetFlag, TypeReference returnType, Statement returnStatement, EclipseNode sourceNode) { TypeDeclaration td = (TypeDeclaration) builderType.get(); AbstractMethodDeclaration[] existing = td.methods; - if (existing == null) { - existing = EMPTY_METHODS; - } + if (existing == null) existing = EMPTY_METHODS; int len = existing.length; FieldDeclaration fd = (FieldDeclaration) fieldNode.get(); char[] name = fd.name; - + for (int i = 0; i < len; i++) { - if (!(existing[i] instanceof MethodDeclaration)) { - continue; - } + if (!(existing[i] instanceof MethodDeclaration)) continue; char[] existingName = existing[i].selector; - if (Arrays.equals(name, existingName) && !isTolerate(fieldNode, existing[i])) { - return; - } + if (Arrays.equals(name, existingName) && !isTolerate(fieldNode, existing[i])) return; } - + String setterName = fieldNode.getName(); - + MethodDeclaration setter = HandleSetter.createSetter(td, deprecate, fieldNode, setterName, nameOfSetFlag, returnType, returnStatement, ClassFileConstants.AccPublic, sourceNode, Collections.<Annotation>emptyList(), Collections.<Annotation>emptyList()); injectMethod(builderType, setter); } - + private void addObtainVia(BuilderFieldData bfd, EclipseNode node) { for (EclipseNode 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; return; } } - + /** * Returns the explicitly requested singular annotation on this node (field * or parameter), or null if there's no {@code @Singular} annotation on it. @@ -738,9 +704,8 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> { */ private SingularData getSingularData(EclipseNode node, ASTNode source) { for (EclipseNode child : node.down()) { - if (!annotationTypeMatches(Singular.class, child)) { - continue; - } + if (!annotationTypeMatches(Singular.class, child)) continue; + char[] pluralName = node.getKind() == Kind.FIELD ? removePrefixFromField(node) : ((AbstractVariableDeclaration) node.get()).name; AnnotationValues<Singular> ann = createAnnotation(Singular.class, child); String explicitSingular = ann.getInstance().value(); @@ -757,7 +722,7 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> { } } char[] singularName = explicitSingular.toCharArray(); - + TypeReference type = ((AbstractVariableDeclaration) node.get()).type; TypeReference[] typeArgs = null; String typeName; @@ -766,59 +731,51 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> { typeName = new String(((ParameterizedSingleTypeReference) type).token); } else if (type instanceof ParameterizedQualifiedTypeReference) { TypeReference[][] tr = ((ParameterizedQualifiedTypeReference) type).typeArguments; - if (tr != null) { - typeArgs = tr[tr.length - 1]; - } + if (tr != null) typeArgs = tr[tr.length - 1]; char[][] tokens = ((ParameterizedQualifiedTypeReference) type).tokens; StringBuilder sb = new StringBuilder(); for (int i = 0; i < tokens.length; i++) { - if (i > 0) { - sb.append("."); - } + if (i > 0) sb.append("."); sb.append(tokens[i]); } typeName = sb.toString(); } else { typeName = type.toString(); } - + String targetFqn = EclipseSingularsRecipes.get().toQualified(typeName); EclipseSingularizer singularizer = EclipseSingularsRecipes.get().getSingularizer(targetFqn); if (singularizer == null) { node.addError("Lombok does not know how to create the singular-form builder methods for type '" + typeName + "'; they won't be generated."); return null; } - + return new SingularData(child, singularName, pluralName, typeArgs == null ? Collections.<TypeReference>emptyList() : Arrays.asList(typeArgs), targetFqn, singularizer, source); } - + 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 TypeReference[] appendBuilderTypeReferences(TypeParameter[] typeParams, String classGenericName, String builderGenericName) { TypeReference[] typeReferencesToAppend = new TypeReference[2]; typeReferencesToAppend[typeReferencesToAppend.length - 2] = new SingleTypeReference(classGenericName.toCharArray(), 0); typeReferencesToAppend[typeReferencesToAppend.length - 1] = new SingleTypeReference(builderGenericName.toCharArray(), 0); return mergeToTypeReferences(typeParams, typeReferencesToAppend); } - + private TypeReference[] getTypeParametersFrom(TypeReference typeRef) { TypeReference[][] typeArgss = null; if (typeRef instanceof ParameterizedQualifiedTypeReference) { - typeArgss = ((ParameterizedQualifiedTypeReference)typeRef).typeArguments; + typeArgss = ((ParameterizedQualifiedTypeReference) typeRef).typeArguments; } else if (typeRef instanceof ParameterizedSingleTypeReference) { - typeArgss = new TypeReference[][] {((ParameterizedSingleTypeReference)typeRef).typeArguments}; + typeArgss = new TypeReference[][] {((ParameterizedSingleTypeReference) typeRef).typeArguments}; } TypeReference[] typeArgs = new TypeReference[0]; if (typeArgss != null && typeArgss.length > 0) { @@ -826,7 +783,7 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> { } return typeArgs; } - + private static SingleTypeReference createTypeReferenceWithTypeParameters(String referenceName, TypeParameter[] typeParams) { if (typeParams.length > 0) { TypeReference[] typerefs = new TypeReference[typeParams.length]; @@ -837,7 +794,6 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> { } else { return new SingleTypeReference(referenceName.toCharArray(), 0); } - } private TypeReference[] mergeToTypeReferences(TypeParameter[] typeParams, TypeReference[] typeReferencesToAppend) { @@ -850,32 +806,24 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> { } return typerefs; } - + private TypeReference[] mergeTypeReferences(TypeReference[] refs1, TypeReference[] refs2) { TypeReference[] result = new TypeReference[refs1.length + refs2.length]; - for (int i = 0; i < refs1.length; i++) { - result[i] = refs1[i]; - } - for (int i = 0; i < refs2.length; i++) { - result[refs1.length + i] = refs2[i]; - } + for (int i = 0; i < refs1.length; i++) result[i] = refs1[i]; + for (int i = 0; i < refs2.length; i++) result[refs1.length + i] = refs2[i]; return result; } - + private EclipseNode findInnerClass(EclipseNode parent, String name) { char[] c = name.toCharArray(); for (EclipseNode child : parent.down()) { - if (child.getKind() != Kind.TYPE) { - continue; - } + if (child.getKind() != Kind.TYPE) continue; TypeDeclaration td = (TypeDeclaration) child.get(); - if (Arrays.equals(td.name, c)) { - return child; - } + if (Arrays.equals(td.name, c)) return child; } return null; } - + 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); diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java index d6c63944..f1687c9c 100644 --- a/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java +++ b/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015-2017 The Project Lombok Authors. + * Copyright (C) 2015-2018 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -27,7 +27,6 @@ import static lombok.eclipse.handlers.EclipseHandlerUtil.*; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.function.Supplier; import lombok.core.GuavaTypeMap; import lombok.core.LombokImmutableList; @@ -35,6 +34,8 @@ import lombok.core.handlers.HandlerUtil; import lombok.eclipse.EclipseNode; import lombok.eclipse.handlers.EclipseSingularsRecipes.EclipseSingularizer; import lombok.eclipse.handlers.EclipseSingularsRecipes.SingularData; +import lombok.eclipse.handlers.EclipseSingularsRecipes.StatementMaker; +import lombok.eclipse.handlers.EclipseSingularsRecipes.TypeReferenceMaker; import org.eclipse.jdt.internal.compiler.ast.Annotation; import org.eclipse.jdt.internal.compiler.ast.Argument; @@ -53,7 +54,6 @@ import org.eclipse.jdt.internal.compiler.ast.NullLiteral; import org.eclipse.jdt.internal.compiler.ast.OperatorIds; import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference; import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference; -import org.eclipse.jdt.internal.compiler.ast.ReturnStatement; import org.eclipse.jdt.internal.compiler.ast.SingleNameReference; import org.eclipse.jdt.internal.compiler.ast.Statement; import org.eclipse.jdt.internal.compiler.ast.ThisReference; @@ -97,10 +97,10 @@ abstract class EclipseGuavaSingularizer extends EclipseSingularizer { return Collections.singletonList(injectFieldAndMarkGenerated(builderType, buildField)); } - @Override public void generateMethods(SingularData data, boolean deprecate, EclipseNode builderType, boolean fluent, Supplier<TypeReference> returnType, Supplier<ReturnStatement> returnStatement) { - generateSingularMethod(deprecate, returnType.get(), returnStatement.get(), data, builderType, fluent); - generatePluralMethod(deprecate, returnType.get(), returnStatement.get(), data, builderType, fluent); - generateClearMethod(deprecate, returnType.get(), returnStatement.get(), data, builderType); + @Override public void generateMethods(SingularData data, boolean deprecate, EclipseNode builderType, boolean fluent, TypeReferenceMaker returnTypeMaker, StatementMaker returnStatementMaker) { + generateSingularMethod(deprecate, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, fluent); + generatePluralMethod(deprecate, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, fluent); + generateClearMethod(deprecate, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType); } void generateClearMethod(boolean deprecate, TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType) { diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java index 0851757f..5f86a4dc 100644 --- a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java +++ b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015-2017 The Project Lombok Authors. + * Copyright (C) 2015-2018 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -27,11 +27,12 @@ import static lombok.eclipse.handlers.EclipseHandlerUtil.*; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.function.Supplier; import lombok.core.handlers.HandlerUtil; import lombok.eclipse.EclipseNode; import lombok.eclipse.handlers.EclipseSingularsRecipes.SingularData; +import lombok.eclipse.handlers.EclipseSingularsRecipes.StatementMaker; +import lombok.eclipse.handlers.EclipseSingularsRecipes.TypeReferenceMaker; import org.eclipse.jdt.internal.compiler.ast.Annotation; import org.eclipse.jdt.internal.compiler.ast.Argument; @@ -46,7 +47,6 @@ import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration; import org.eclipse.jdt.internal.compiler.ast.NullLiteral; import org.eclipse.jdt.internal.compiler.ast.OperatorIds; import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference; -import org.eclipse.jdt.internal.compiler.ast.ReturnStatement; import org.eclipse.jdt.internal.compiler.ast.SingleNameReference; import org.eclipse.jdt.internal.compiler.ast.Statement; import org.eclipse.jdt.internal.compiler.ast.ThisReference; @@ -88,15 +88,15 @@ abstract class EclipseJavaUtilListSetSingularizer extends EclipseJavaUtilSingula return Collections.singletonList(injectFieldAndMarkGenerated(builderType, buildField)); } - @Override public void generateMethods(SingularData data, boolean deprecate, EclipseNode builderType, boolean fluent, Supplier<TypeReference> returnType, Supplier<ReturnStatement> returnStatement) { + @Override public void generateMethods(SingularData data, boolean deprecate, EclipseNode builderType, boolean fluent, TypeReferenceMaker returnTypeMaker, StatementMaker returnStatementMaker) { if (useGuavaInstead(builderType)) { - guavaListSetSingularizer.generateMethods(data, deprecate, builderType, fluent, returnType, returnStatement); + guavaListSetSingularizer.generateMethods(data, deprecate, builderType, fluent, returnTypeMaker, returnStatementMaker); return; } - generateSingularMethod(deprecate, returnType.get(), returnStatement.get(), data, builderType, fluent); - generatePluralMethod(deprecate, returnType.get(), returnStatement.get(), data, builderType, fluent); - generateClearMethod(deprecate, returnType.get(), returnStatement.get(), data, builderType); + generateSingularMethod(deprecate, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, fluent); + generatePluralMethod(deprecate, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, fluent); + generateClearMethod(deprecate, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType); } private void generateClearMethod(boolean deprecate, TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType) { diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java index 976d9265..69c2186a 100644 --- a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java +++ b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015-2017 The Project Lombok Authors. + * Copyright (C) 2015-2018 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -28,7 +28,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; -import java.util.function.Supplier; import org.eclipse.jdt.internal.compiler.ast.Annotation; import org.eclipse.jdt.internal.compiler.ast.Argument; @@ -46,7 +45,6 @@ import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration; import org.eclipse.jdt.internal.compiler.ast.NullLiteral; import org.eclipse.jdt.internal.compiler.ast.OperatorIds; import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference; -import org.eclipse.jdt.internal.compiler.ast.ReturnStatement; import org.eclipse.jdt.internal.compiler.ast.SingleNameReference; import org.eclipse.jdt.internal.compiler.ast.Statement; import org.eclipse.jdt.internal.compiler.ast.ThisReference; @@ -59,6 +57,8 @@ import lombok.core.handlers.HandlerUtil; import lombok.eclipse.EclipseNode; import lombok.eclipse.handlers.EclipseSingularsRecipes.EclipseSingularizer; import lombok.eclipse.handlers.EclipseSingularsRecipes.SingularData; +import lombok.eclipse.handlers.EclipseSingularsRecipes.StatementMaker; +import lombok.eclipse.handlers.EclipseSingularsRecipes.TypeReferenceMaker; @ProviderFor(EclipseSingularizer.class) public class EclipseJavaUtilMapSingularizer extends EclipseJavaUtilSingularizer { @@ -133,15 +133,15 @@ public class EclipseJavaUtilMapSingularizer extends EclipseJavaUtilSingularizer return Arrays.asList(keyFieldNode, valueFieldNode); } - @Override public void generateMethods(SingularData data, boolean deprecate, EclipseNode builderType, boolean fluent, Supplier<TypeReference> returnType, Supplier<ReturnStatement> returnStatement) { + @Override public void generateMethods(SingularData data, boolean deprecate, EclipseNode builderType, boolean fluent, TypeReferenceMaker returnTypeMaker, StatementMaker returnStatementMaker) { if (useGuavaInstead(builderType)) { - guavaMapSingularizer.generateMethods(data, deprecate, builderType, fluent, returnType, returnStatement); + guavaMapSingularizer.generateMethods(data, deprecate, builderType, fluent, returnTypeMaker, returnStatementMaker); return; } - generateSingularMethod(deprecate, returnType.get(), returnStatement.get(), data, builderType, fluent); - generatePluralMethod(deprecate, returnType.get(), returnStatement.get(), data, builderType, fluent); - generateClearMethod(deprecate, returnType.get(), returnStatement.get(), data, builderType); + generateSingularMethod(deprecate, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, fluent); + generatePluralMethod(deprecate, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, fluent); + generateClearMethod(deprecate, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType); } private void generateClearMethod(boolean deprecate, TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType) { diff --git a/src/core/lombok/javac/handlers/HandleSetter.java b/src/core/lombok/javac/handlers/HandleSetter.java index 50967121..be3337db 100644 --- a/src/core/lombok/javac/handlers/HandleSetter.java +++ b/src/core/lombok/javac/handlers/HandleSetter.java @@ -210,12 +210,17 @@ public class HandleSetter extends JavacAnnotationHandler<Setter> { } public static JCMethodDecl createSetter(long access, boolean deprecate, JavacNode field, JavacTreeMaker treeMaker, String setterName, Name booleanFieldToSet, boolean shouldReturnThis, JavacNode source, List<JCAnnotation> onMethod, List<JCAnnotation> onParam) { - JCExpression returnType = cloneSelfType(field); - JCReturn returnStatement = treeMaker.Return(treeMaker.Ident(field.toName("this"))); + JCExpression returnType = null; + JCReturn returnStatement = null; + if (shouldReturnThis) { + returnType = cloneSelfType(field); + returnStatement = treeMaker.Return(treeMaker.Ident(field.toName("this"))); + } + return createSetter(access, deprecate, field, treeMaker, setterName, booleanFieldToSet, returnType, returnStatement, source, onMethod, onParam); } - - public static JCMethodDecl createSetter(long access, boolean deprecate, JavacNode field, JavacTreeMaker treeMaker, String setterName, Name booleanFieldToSet, JCExpression methodType, JCReturn returnStatement, JavacNode source, List<JCAnnotation> onMethod, List<JCAnnotation> onParam) { + + public static JCMethodDecl createSetter(long access, boolean deprecate, JavacNode field, JavacTreeMaker treeMaker, String setterName, Name booleanFieldToSet, JCExpression methodType, JCStatement returnStatement, JavacNode source, List<JCAnnotation> onMethod, List<JCAnnotation> onParam) { if (setterName == null) return null; JCVariableDecl fieldDecl = (JCVariableDecl) field.get(); @@ -252,9 +257,7 @@ public class HandleSetter extends JavacAnnotationHandler<Setter> { returnStatement = null; } - if (returnStatement != null) { - statements.append(returnStatement); - } + if (returnStatement != null) statements.append(returnStatement); JCBlock methodBody = treeMaker.Block(0, statements.toList()); List<JCTypeParameter> methodGenericParams = List.nil(); 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) { diff --git a/src/core/lombok/javac/handlers/JavacSingularsRecipes.java b/src/core/lombok/javac/handlers/JavacSingularsRecipes.java index 67862355..ab8c3a42 100644 --- a/src/core/lombok/javac/handlers/JavacSingularsRecipes.java +++ b/src/core/lombok/javac/handlers/JavacSingularsRecipes.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015-2017 The Project Lombok Authors. + * Copyright (C) 2015-2018 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -29,7 +29,6 @@ import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.Map; -import java.util.function.Supplier; import lombok.core.LombokImmutableList; import lombok.core.SpiLoadUtil; @@ -54,6 +53,14 @@ import com.sun.tools.javac.util.ListBuffer; import com.sun.tools.javac.util.Name; public class JavacSingularsRecipes { + public interface ExpressionMaker { + JCExpression make(); + } + + public interface StatementMaker { + JCStatement make(); + } + private static final JavacSingularsRecipes INSTANCE = new JavacSingularsRecipes(); private final Map<String, JavacSingularizer> singularizers = new HashMap<String, JavacSingularizer>(); private final TypeLibrary singularizableTypes = new TypeLibrary(); @@ -197,32 +204,32 @@ public class JavacSingularsRecipes { public abstract java.util.List<JavacNode> generateFields(SingularData data, JavacNode builderType, JCTree source); /** - * Generates the singular, plural, and clear methods for the given - * {@link SingularData}.<br> - * Uses the given <code>builderType</code> as return type if - * <code>chain == true</code>, <code>void</code> otherwise. If you need more - * control over the return type and value, use - * {@link #generateMethods(SingularData, boolean, JavacNode, JCTree, boolean, JCExpression, JCStatement)}. + * Generates the singular, plural, and clear methods for the given {@link SingularData}. + * Uses the given {@code builderType} as return type if {@code chain == true}, {@code void} otherwise. + * If you need more control over the return type and value, use + * {@link #generateMethods(SingularData, boolean, JavacNode, JCTree, boolean, ExpressionMaker, StatementMaker)}. */ public void generateMethods(SingularData data, boolean deprecate, final JavacNode builderType, JCTree source, boolean fluent, final boolean chain) { 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 chain ? - cloneSelfType(builderType) : - maker.Type(createVoidType(builderType.getSymbolTable(), CTC_VOID)); + cloneSelfType(builderType) : + maker.Type(createVoidType(builderType.getSymbolTable(), CTC_VOID)); }}; - Supplier<JCStatement> returnStatement = new Supplier<JCStatement>() { @Override public JCStatement get() { + + StatementMaker returnStatementMaker = new StatementMaker() { @Override public JCStatement make() { return chain ? maker.Return(maker.Ident(builderType.toName("this"))) : null; }}; - generateMethods(data, deprecate, builderType, source, fluent, returnType, returnStatement); + + generateMethods(data, deprecate, builderType, source, fluent, returnTypeMaker, returnStatementMaker); } + /** - * Generates the singular, plural, and clear methods for the given - * {@link SingularData}.<br> - * Uses the given <code>returnType</code> and <code>returnStatement</code> for the generated methods. + * Generates the singular, plural, and clear methods for the given {@link SingularData}. + * Uses the given {@code returnTypeMaker} and {@code returnStatementMaker} for the generated methods. */ - public abstract void generateMethods(SingularData data, boolean deprecate, JavacNode builderType, JCTree source, boolean fluent, Supplier<JCExpression> returnType, Supplier<? extends JCStatement> returnStatement); + public abstract void generateMethods(SingularData data, boolean deprecate, JavacNode builderType, JCTree source, boolean fluent, ExpressionMaker returnTypeMaker, StatementMaker returnStatementMaker); public abstract void appendBuildCode(SingularData data, JavacNode builderType, JCTree source, ListBuffer<JCStatement> statements, Name targetVariableName, String builderVariable); diff --git a/src/core/lombok/javac/handlers/singulars/JavacGuavaSingularizer.java b/src/core/lombok/javac/handlers/singulars/JavacGuavaSingularizer.java index ecaf5c87..ffaf6674 100644 --- a/src/core/lombok/javac/handlers/singulars/JavacGuavaSingularizer.java +++ b/src/core/lombok/javac/handlers/singulars/JavacGuavaSingularizer.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015-2017 The Project Lombok Authors. + * Copyright (C) 2015-2018 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -25,7 +25,6 @@ import static lombok.javac.Javac.*; import static lombok.javac.handlers.JavacHandlerUtil.*; import java.util.Collections; -import java.util.function.Supplier; import lombok.core.GuavaTypeMap; import lombok.core.LombokImmutableList; @@ -33,8 +32,10 @@ import lombok.core.handlers.HandlerUtil; import lombok.javac.JavacNode; import lombok.javac.JavacTreeMaker; import lombok.javac.handlers.JavacHandlerUtil; +import lombok.javac.handlers.JavacSingularsRecipes.ExpressionMaker; import lombok.javac.handlers.JavacSingularsRecipes.JavacSingularizer; import lombok.javac.handlers.JavacSingularsRecipes.SingularData; +import lombok.javac.handlers.JavacSingularsRecipes.StatementMaker; import com.sun.tools.javac.code.Flags; import com.sun.tools.javac.tree.JCTree; @@ -70,11 +71,11 @@ abstract class JavacGuavaSingularizer extends JavacSingularizer { return Collections.singletonList(injectFieldAndMarkGenerated(builderType, buildField)); } - @Override public void generateMethods(SingularData data, boolean deprecate, JavacNode builderType, JCTree source, boolean fluent, Supplier<JCExpression> returnType, Supplier<? extends JCStatement> returnStatement) { + @Override public void generateMethods(SingularData data, boolean deprecate, JavacNode builderType, JCTree source, boolean fluent, ExpressionMaker returnTypeMaker, StatementMaker returnStatementMaker) { JavacTreeMaker maker = builderType.getTreeMaker(); - generateSingularMethod(deprecate, maker, returnType.get(), returnStatement.get(), data, builderType, source, fluent); - generatePluralMethod(deprecate, maker, returnType.get(), returnStatement.get(), data, builderType, source, fluent); - generateClearMethod(deprecate, maker, returnType.get(), returnStatement.get(), data, builderType, source); + generateSingularMethod(deprecate, maker, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, source, fluent); + generatePluralMethod(deprecate, maker, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, source, fluent); + generateClearMethod(deprecate, maker, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, source); } private void generateClearMethod(boolean deprecate, JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source) { diff --git a/src/core/lombok/javac/handlers/singulars/JavacJavaUtilListSetSingularizer.java b/src/core/lombok/javac/handlers/singulars/JavacJavaUtilListSetSingularizer.java index bd0f740e..39e53ebb 100644 --- a/src/core/lombok/javac/handlers/singulars/JavacJavaUtilListSetSingularizer.java +++ b/src/core/lombok/javac/handlers/singulars/JavacJavaUtilListSetSingularizer.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015-2017 The Project Lombok Authors. + * Copyright (C) 2015-2018 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -25,13 +25,14 @@ import static lombok.javac.Javac.*; import static lombok.javac.handlers.JavacHandlerUtil.*; import java.util.Collections; -import java.util.function.Supplier; import lombok.core.handlers.HandlerUtil; import lombok.javac.JavacNode; import lombok.javac.JavacTreeMaker; import lombok.javac.handlers.JavacHandlerUtil; +import lombok.javac.handlers.JavacSingularsRecipes.ExpressionMaker; import lombok.javac.handlers.JavacSingularsRecipes.SingularData; +import lombok.javac.handlers.JavacSingularsRecipes.StatementMaker; import com.sun.tools.javac.code.Flags; import com.sun.tools.javac.tree.JCTree; @@ -76,16 +77,16 @@ abstract class JavacJavaUtilListSetSingularizer extends JavacJavaUtilSingularize return Collections.singletonList(injectFieldAndMarkGenerated(builderType, buildField)); } - @Override public void generateMethods(SingularData data, boolean deprecate, JavacNode builderType, JCTree source, boolean fluent, Supplier<JCExpression> returnType, Supplier<? extends JCStatement> returnStatement) { + @Override public void generateMethods(SingularData data, boolean deprecate, JavacNode builderType, JCTree source, boolean fluent, ExpressionMaker returnTypeMaker, StatementMaker returnStatementMaker) { if (useGuavaInstead(builderType)) { - guavaListSetSingularizer.generateMethods(data, deprecate, builderType, source, fluent, returnType, returnStatement); + guavaListSetSingularizer.generateMethods(data, deprecate, builderType, source, fluent, returnTypeMaker, returnStatementMaker); return; } JavacTreeMaker maker = builderType.getTreeMaker(); - generateSingularMethod(deprecate, maker, returnType.get(), returnStatement.get(), data, builderType, source, fluent); - generatePluralMethod(deprecate, maker, returnType.get(), returnStatement.get(), data, builderType, source, fluent); - generateClearMethod(deprecate, maker, returnType.get(), returnStatement.get(), data, builderType, source); + generateSingularMethod(deprecate, maker, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, source, fluent); + generatePluralMethod(deprecate, maker, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, source, fluent); + generateClearMethod(deprecate, maker, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, source); } private void generateClearMethod(boolean deprecate, JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source) { diff --git a/src/core/lombok/javac/handlers/singulars/JavacJavaUtilMapSingularizer.java b/src/core/lombok/javac/handlers/singulars/JavacJavaUtilMapSingularizer.java index 1b4dd960..34350f40 100644 --- a/src/core/lombok/javac/handlers/singulars/JavacJavaUtilMapSingularizer.java +++ b/src/core/lombok/javac/handlers/singulars/JavacJavaUtilMapSingularizer.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015-2017 The Project Lombok Authors. + * Copyright (C) 2015-2018 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -25,15 +25,16 @@ import static lombok.javac.Javac.*; import static lombok.javac.handlers.JavacHandlerUtil.*; import java.util.Arrays; -import java.util.function.Supplier; import lombok.core.LombokImmutableList; import lombok.core.handlers.HandlerUtil; import lombok.javac.JavacNode; import lombok.javac.JavacTreeMaker; import lombok.javac.handlers.JavacHandlerUtil; +import lombok.javac.handlers.JavacSingularsRecipes.ExpressionMaker; import lombok.javac.handlers.JavacSingularsRecipes.JavacSingularizer; import lombok.javac.handlers.JavacSingularsRecipes.SingularData; +import lombok.javac.handlers.JavacSingularsRecipes.StatementMaker; import org.mangosdk.spi.ProviderFor; @@ -101,16 +102,16 @@ public class JavacJavaUtilMapSingularizer extends JavacJavaUtilSingularizer { return Arrays.asList(keyFieldNode, valueFieldNode); } - @Override public void generateMethods(SingularData data, boolean deprecate, JavacNode builderType, JCTree source, boolean fluent, Supplier<JCExpression> returnType, Supplier<? extends JCStatement> returnStatement) { + @Override public void generateMethods(SingularData data, boolean deprecate, JavacNode builderType, JCTree source, boolean fluent, ExpressionMaker returnTypeMaker, StatementMaker returnStatementMaker) { if (useGuavaInstead(builderType)) { - guavaMapSingularizer.generateMethods(data, deprecate, builderType, source, fluent, returnType, returnStatement); + guavaMapSingularizer.generateMethods(data, deprecate, builderType, source, fluent, returnTypeMaker, returnStatementMaker); return; } JavacTreeMaker maker = builderType.getTreeMaker(); - generateSingularMethod(deprecate, maker, returnType.get(), returnStatement.get(), data, builderType, source, fluent); - generatePluralMethod(deprecate, maker, returnType.get(), returnStatement.get(), data, builderType, source, fluent); - generateClearMethod(deprecate, maker, returnType.get(), returnStatement.get(), data, builderType, source); + generateSingularMethod(deprecate, maker, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, source, fluent); + generatePluralMethod(deprecate, maker, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, source, fluent); + generateClearMethod(deprecate, maker, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, source); } private void generateClearMethod(boolean deprecate, JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source) { |