diff options
Diffstat (limited to 'src/core/lombok/javac')
10 files changed, 692 insertions, 542 deletions
diff --git a/src/core/lombok/javac/handlers/HandleBuilder.java b/src/core/lombok/javac/handlers/HandleBuilder.java index 7e87ce11..1c74ce37 100644 --- a/src/core/lombok/javac/handlers/HandleBuilder.java +++ b/src/core/lombok/javac/handlers/HandleBuilder.java @@ -55,6 +55,7 @@ import com.sun.tools.javac.tree.JCTree.JCStatement; import com.sun.tools.javac.tree.JCTree.JCTypeApply; import com.sun.tools.javac.tree.JCTree.JCTypeParameter; import com.sun.tools.javac.tree.JCTree.JCVariableDecl; +import com.sun.tools.javac.util.Context; import com.sun.tools.javac.util.List; import com.sun.tools.javac.util.ListBuffer; import com.sun.tools.javac.util.Name; @@ -88,12 +89,96 @@ import lombok.javac.handlers.JavacSingularsRecipes.SingularData; public class HandleBuilder extends JavacAnnotationHandler<Builder> { private HandleConstructor handleConstructor = new HandleConstructor(); + static final String CLEAN_FIELD_NAME = "$lombokUnclean"; + static final String CLEAN_METHOD_NAME = "$lombokClean"; + static final String TO_BUILDER_METHOD_NAME = "toBuilder"; + static final String DEFAULT_PREFIX = "$default$"; + static final String SET_PREFIX = "$set"; + static final String VALUE_PREFIX = "$value"; + static final String BUILDER_TEMP_VAR = "builder"; + static final String TO_BUILDER_NOT_SUPPORTED = "@Builder(toBuilder=true) is only supported if you return your own type."; + private static final boolean toBoolean(Object expr, boolean defaultValue) { if (expr == null) return defaultValue; if (expr instanceof JCLiteral) return ((Integer) ((JCLiteral) expr).value) != 0; return ((Boolean) expr).booleanValue(); } + static class BuilderJob { + CheckerFrameworkVersion checkerFramework; + JavacNode parentType; + String builderMethodName, buildMethodName; + boolean isStatic; + List<JCTypeParameter> typeParams; + List<JCTypeParameter> builderTypeParams; + JCTree source; + JavacNode sourceNode; + java.util.List<BuilderFieldData> builderFields; + AccessLevel accessInners, accessOuters; + boolean oldFluent, oldChain, toBuilder; + + JavacNode builderType; + String builderClassName; + + void init(AnnotationValues<Builder> annValues, Builder ann, JavacNode node) { + accessOuters = ann.access(); + if (accessOuters == null) accessOuters = AccessLevel.PUBLIC; + if (accessOuters == AccessLevel.NONE) { + sourceNode.addError("AccessLevel.NONE is not valid here"); + accessOuters = AccessLevel.PUBLIC; + } + accessInners = accessOuters == AccessLevel.PROTECTED ? AccessLevel.PUBLIC : accessOuters; + + oldFluent = toBoolean(annValues.getActualExpression("fluent"), true); + oldChain = toBoolean(annValues.getActualExpression("chain"), true); + + builderMethodName = ann.builderMethodName(); + buildMethodName = ann.buildMethodName(); + builderClassName = fixBuilderClassName(node, ann.builderClassName()); + toBuilder = ann.toBuilder(); + + if (builderMethodName == null) builderMethodName = "builder"; + if (buildMethodName == null) buildMethodName = "build"; + if (builderClassName == null) builderClassName = ""; + } + + static String fixBuilderClassName(JavacNode node, String override) { + if (override != null && !override.isEmpty()) return override; + override = node.getAst().readConfiguration(ConfigurationKeys.BUILDER_CLASS_NAME); + if (override != null && !override.isEmpty()) return override; + return "*Builder"; + } + + String replaceBuilderClassName(Name name) { + if (builderClassName.indexOf('*') == -1) return builderClassName; + return builderClassName.replace("*", name.toString()); + } + + JCExpression createBuilderParentTypeReference() { + return namePlusTypeParamsToTypeReference(parentType.getTreeMaker(), parentType, typeParams); + } + + Name getBuilderClassName() { + return parentType.toName(builderClassName); + } + + List<JCTypeParameter> copyTypeParams() { + return JavacHandlerUtil.copyTypeParams(sourceNode, typeParams); + } + + Name toName(String name) { + return parentType.toName(name); + } + + Context getContext() { + return parentType.getContext(); + } + + JavacTreeMaker getTreeMaker() { + return parentType.getTreeMaker(); + } + } + static class BuilderFieldData { List<JCAnnotation> annotations; JCExpression type; @@ -112,73 +197,49 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { @Override public void handle(AnnotationValues<Builder> annotation, JCAnnotation ast, JavacNode annotationNode) { handleFlagUsage(annotationNode, ConfigurationKeys.BUILDER_FLAG_USAGE, "@Builder"); - CheckerFrameworkVersion cfv = getCheckerFrameworkVersion(annotationNode); - - Builder builderInstance = annotation.getInstance(); - AccessLevel accessForOuters = builderInstance.access(); - if (accessForOuters == null) accessForOuters = AccessLevel.PUBLIC; - if (accessForOuters == AccessLevel.NONE) { - annotationNode.addError("AccessLevel.NONE is not valid here"); - accessForOuters = AccessLevel.PUBLIC; - } - AccessLevel accessForInners = accessForOuters == AccessLevel.PROTECTED ? AccessLevel.PUBLIC : accessForOuters; - - // These exist just to support the 'old' lombok.experimental.Builder, which had these properties. lombok.Builder no longer has them. - boolean fluent = toBoolean(annotation.getActualExpression("fluent"), true); - boolean chain = toBoolean(annotation.getActualExpression("chain"), true); - - String builderMethodName = builderInstance.builderMethodName(); - String buildMethodName = builderInstance.buildMethodName(); - String builderClassName = builderInstance.builderClassName(); - String toBuilderMethodName = "toBuilder"; - boolean toBuilder = builderInstance.toBuilder(); + BuilderJob job = new BuilderJob(); + job.sourceNode = annotationNode; + job.source = ast; + job.checkerFramework = getCheckerFrameworkVersion(annotationNode); + job.isStatic = true; + + Builder annInstance = annotation.getInstance(); + job.init(annotation, annInstance, annotationNode); java.util.List<Name> typeArgsForToBuilder = null; - if (builderMethodName == null) builderMethodName = "builder"; - if (buildMethodName == null) buildMethodName = "build"; - if (builderClassName == null) builderClassName = ""; - boolean generateBuilderMethod; - if (builderMethodName.isEmpty()) { + if (job.builderMethodName.isEmpty()) { generateBuilderMethod = false; - } else if (!checkName("builderMethodName", builderMethodName, annotationNode)) { + } else if (!checkName("builderMethodName", job.builderMethodName, annotationNode)) { return; } else { generateBuilderMethod = true; } - if (!checkName("buildMethodName", buildMethodName, annotationNode)) return; - if (!builderClassName.isEmpty()) { - if (!checkName("builderClassName", builderClassName, annotationNode)) return; - } + if (!checkName("buildMethodName", job.buildMethodName, annotationNode)) return; - // Do not delete the Builder annotation here, we need it for @Jacksonized. + // Do not delete the Builder annotation yet, we need it for @Jacksonized. JavacNode parent = annotationNode.up(); - java.util.List<BuilderFieldData> builderFields = new ArrayList<BuilderFieldData>(); - JCExpression returnType; - List<JCTypeParameter> typeParams = List.nil(); - List<JCExpression> thrownExceptions = List.nil(); + job.builderFields = new ArrayList<BuilderFieldData>(); + JCExpression buildMethodReturnType; + job.typeParams = List.nil(); + List<JCExpression> buildMethodThrownExceptions; Name nameOfBuilderMethod; - JavacNode tdParent; JavacNode fillParametersFrom = parent.get() instanceof JCMethodDecl ? parent : null; boolean addCleaning = false; - boolean isStatic = true; ArrayList<JavacNode> nonFinalNonDefaultedFields = null; - if (builderClassName.isEmpty()) builderClassName = annotationNode.getAst().readConfiguration(ConfigurationKeys.BUILDER_CLASS_NAME); - if (builderClassName == null || builderClassName.isEmpty()) builderClassName = "*Builder"; - boolean replaceNameInBuilderClassName = builderClassName.contains("*"); - if (parent.get() instanceof JCClassDecl) { - tdParent = parent; - JCClassDecl td = (JCClassDecl) tdParent.get(); + job.parentType = parent; + JCClassDecl td = (JCClassDecl) parent.get(); + ListBuffer<JavacNode> allFields = new ListBuffer<JavacNode>(); boolean valuePresent = (hasAnnotation(lombok.Value.class, parent) || hasAnnotation("lombok.experimental.Value", parent)); - for (JavacNode fieldNode : HandleConstructor.findAllFields(tdParent, true)) { + for (JavacNode fieldNode : HandleConstructor.findAllFields(parent, true)) { JCVariableDecl fd = (JCVariableDecl) fieldNode.get(); JavacNode isDefault = findAnnotation(Builder.Default.class, fieldNode, false); boolean isFinal = (fd.mods.flags & Flags.FINAL) != 0 || (valuePresent && !hasAnnotation(NonFinal.class, fieldNode)); @@ -189,7 +250,7 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { bfd.builderFieldName = bfd.name; bfd.annotations = findCopyableAnnotations(fieldNode); bfd.type = fd.vartype; - bfd.singularData = getSingularData(fieldNode, builderInstance.setterPrefix()); + bfd.singularData = getSingularData(fieldNode, annInstance.setterPrefix()); bfd.originalFieldNode = fieldNode; if (bfd.singularData != null && isDefault != null) { @@ -211,26 +272,26 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { } if (isDefault != null) { - bfd.nameOfDefaultProvider = parent.toName("$default$" + bfd.name); - bfd.nameOfSetFlag = parent.toName(bfd.name + "$set"); - bfd.builderFieldName = parent.toName(bfd.name + "$value"); + bfd.nameOfDefaultProvider = parent.toName(DEFAULT_PREFIX + bfd.name); + bfd.nameOfSetFlag = parent.toName(bfd.name + SET_PREFIX); + bfd.builderFieldName = parent.toName(bfd.name + VALUE_PREFIX); JCMethodDecl md = generateDefaultProvider(bfd.nameOfDefaultProvider, fieldNode, td.typarams); recursiveSetGeneratedBy(md, ast, annotationNode.getContext()); - if (md != null) injectMethod(tdParent, md); + if (md != null) injectMethod(parent, md); } addObtainVia(bfd, fieldNode); - builderFields.add(bfd); + job.builderFields.add(bfd); allFields.append(fieldNode); } - handleConstructor.generateConstructor(tdParent, AccessLevel.PACKAGE, List.<JCAnnotation>nil(), allFields.toList(), false, null, SkipIfConstructorExists.I_AM_BUILDER, annotationNode); + handleConstructor.generateConstructor(parent, AccessLevel.PACKAGE, List.<JCAnnotation>nil(), allFields.toList(), false, null, SkipIfConstructorExists.I_AM_BUILDER, annotationNode); - returnType = namePlusTypeParamsToTypeReference(tdParent.getTreeMaker(), tdParent, td.typarams); - typeParams = td.typarams; - thrownExceptions = List.nil(); + buildMethodReturnType = namePlusTypeParamsToTypeReference(parent.getTreeMaker(), parent, td.typarams); + job.typeParams = job.builderTypeParams = td.typarams; + buildMethodThrownExceptions = List.nil(); nameOfBuilderMethod = null; - if (replaceNameInBuilderClassName) builderClassName = builderClassName.replace("*", td.name.toString()); - replaceNameInBuilderClassName = false; + job.builderClassName = job.replaceBuilderClassName(td.name); + if (!checkName("builderClassName", job.builderClassName, annotationNode)) return; } else if (fillParametersFrom != null && fillParametersFrom.getName().toString().equals("<init>")) { JCMethodDecl jmd = (JCMethodDecl) fillParametersFrom.get(); if (!jmd.typarams.isEmpty()) { @@ -238,38 +299,35 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { return; } - tdParent = parent.up(); - JCClassDecl td = (JCClassDecl) tdParent.get(); - returnType = namePlusTypeParamsToTypeReference(tdParent.getTreeMaker(), tdParent, td.typarams); - typeParams = td.typarams; - thrownExceptions = jmd.thrown; + job.parentType = parent.up(); + JCClassDecl td = (JCClassDecl) job.parentType.get(); + job.typeParams = job.builderTypeParams = td.typarams; + buildMethodReturnType = job.createBuilderParentTypeReference(); + buildMethodThrownExceptions = jmd.thrown; nameOfBuilderMethod = null; - if (replaceNameInBuilderClassName) builderClassName = builderClassName.replace("*", td.name.toString()); - replaceNameInBuilderClassName = false; + job.builderClassName = job.replaceBuilderClassName(td.name); + if (!checkName("builderClassName", job.builderClassName, annotationNode)) return; } else if (fillParametersFrom != null) { - tdParent = parent.up(); - JCClassDecl td = (JCClassDecl) tdParent.get(); + job.parentType = parent.up(); + JCClassDecl td = (JCClassDecl) job.parentType.get(); JCMethodDecl jmd = (JCMethodDecl) fillParametersFrom.get(); - isStatic = (jmd.mods.flags & Flags.STATIC) != 0; + job.isStatic = (jmd.mods.flags & Flags.STATIC) != 0; + JCExpression fullReturnType = jmd.restype; - returnType = fullReturnType; - typeParams = jmd.typarams; - thrownExceptions = jmd.thrown; + buildMethodReturnType = fullReturnType; + job.typeParams = job.builderTypeParams = jmd.typarams; + buildMethodThrownExceptions = jmd.thrown; nameOfBuilderMethod = jmd.name; - if (returnType instanceof JCTypeApply) { - returnType = cloneType(tdParent.getTreeMaker(), returnType, ast, annotationNode.getContext()); + if (buildMethodReturnType instanceof JCTypeApply) { + buildMethodReturnType = cloneType(job.getTreeMaker(), buildMethodReturnType, ast, annotationNode.getContext()); } - if (replaceNameInBuilderClassName) { - String replStr = returnTypeToBuilderClassName(annotationNode, td, returnType, typeParams); - if (replStr == null) - return; - builderClassName = builderClassName.replace("*", replStr); - replaceNameInBuilderClassName = false; + if (job.builderClassName.indexOf('*') > -1) { + String replStr = returnTypeToBuilderClassName(annotationNode, td, buildMethodReturnType, job.typeParams); + if (replStr == null) return; // shuold not happen + job.builderClassName = job.builderClassName.replace("*", replStr); } - if (replaceNameInBuilderClassName) builderClassName = builderClassName.replace("*", td.name.toString()); - if (toBuilder) { - final String TO_BUILDER_NOT_SUPPORTED = "@Builder(toBuilder=true) is only supported if you return your own type."; - if (returnType instanceof JCArrayTypeTree) { + if (job.toBuilder) { + if (fullReturnType instanceof JCArrayTypeTree) { annotationNode.addError(TO_BUILDER_NOT_SUPPORTED); return; } @@ -282,8 +340,8 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { tpOnRet = ((JCTypeApply) fullReturnType).arguments; } - JCExpression namingType = returnType; - if (returnType instanceof JCTypeApply) namingType = ((JCTypeApply) returnType).clazz; + JCExpression namingType = fullReturnType; + if (buildMethodReturnType instanceof JCTypeApply) namingType = ((JCTypeApply) buildMethodReturnType).clazz; if (namingType instanceof JCIdent) { simpleName = ((JCIdent) namingType).name; @@ -307,13 +365,13 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { return; } - if (!tdParent.getName().contentEquals(simpleName)) { + if (!job.parentType.getName().contentEquals(simpleName)) { annotationNode.addError(TO_BUILDER_NOT_SUPPORTED); return; } List<JCTypeParameter> tpOnMethod = jmd.typarams; - List<JCTypeParameter> tpOnType = ((JCClassDecl) tdParent.get()).typarams; + List<JCTypeParameter> tpOnType = ((JCClassDecl) job.builderType.get()).typarams; typeArgsForToBuilder = new ArrayList<Name>(); for (JCTypeParameter tp : tpOnMethod) { @@ -349,41 +407,41 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { bfd.rawName = raw.name; bfd.annotations = findCopyableAnnotations(param); bfd.type = raw.vartype; - bfd.singularData = getSingularData(param, builderInstance.setterPrefix()); + bfd.singularData = getSingularData(param, annInstance.setterPrefix()); bfd.originalFieldNode = param; addObtainVia(bfd, param); - builderFields.add(bfd); + job.builderFields.add(bfd); } } - JavacNode builderType = findInnerClass(tdParent, builderClassName); - if (builderType == null) { - builderType = makeBuilderClass(isStatic, annotationNode, tdParent, builderClassName, typeParams, ast, accessForOuters); - recursiveSetGeneratedBy(builderType.get(), ast, annotationNode.getContext()); + job.builderType = findInnerClass(job.parentType, job.builderClassName); + if (job.builderType == null) { + job.builderType = makeBuilderClass(job); + recursiveSetGeneratedBy(job.builderType.get(), ast, annotationNode.getContext()); } else { - JCClassDecl builderTypeDeclaration = (JCClassDecl) builderType.get(); - if (isStatic && !builderTypeDeclaration.getModifiers().getFlags().contains(Modifier.STATIC)) { + JCClassDecl builderTypeDeclaration = (JCClassDecl) job.builderType.get(); + if (job.isStatic && !builderTypeDeclaration.getModifiers().getFlags().contains(Modifier.STATIC)) { annotationNode.addError("Existing Builder must be a static inner class."); return; - } else if (!isStatic && builderTypeDeclaration.getModifiers().getFlags().contains(Modifier.STATIC)) { + } else if (!job.isStatic && builderTypeDeclaration.getModifiers().getFlags().contains(Modifier.STATIC)) { annotationNode.addError("Existing Builder must be a non-static inner class."); return; } - sanityCheckForMethodGeneratingAnnotationsOnBuilderClass(builderType, annotationNode); + sanityCheckForMethodGeneratingAnnotationsOnBuilderClass(job.builderType, annotationNode); /* generate errors for @Singular BFDs that have one already defined node. */ { - for (BuilderFieldData bfd : builderFields) { + for (BuilderFieldData bfd : job.builderFields) { SingularData sd = bfd.singularData; if (sd == null) continue; JavacSingularizer singularizer = sd.getSingularizer(); if (singularizer == null) continue; - if (singularizer.checkForAlreadyExistingNodesAndGenerateError(builderType, sd)) { + if (singularizer.checkForAlreadyExistingNodesAndGenerateError(job.builderType, sd)) { bfd.singularData = null; } } } } - for (BuilderFieldData bfd : builderFields) { + for (BuilderFieldData bfd : job.builderFields) { if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) { if (bfd.singularData.getSingularizer().requiresCleaning()) { addCleaning = true; @@ -402,75 +460,75 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { } } - generateBuilderFields(builderType, builderFields, ast); + generateBuilderFields(job); if (addCleaning) { - JavacTreeMaker maker = builderType.getTreeMaker(); - JCVariableDecl uncleanField = maker.VarDef(maker.Modifiers(Flags.PRIVATE), builderType.toName("$lombokUnclean"), maker.TypeIdent(CTC_BOOLEAN), null); - injectFieldAndMarkGenerated(builderType, uncleanField); + JavacTreeMaker maker = job.getTreeMaker(); + JCVariableDecl uncleanField = maker.VarDef(maker.Modifiers(Flags.PRIVATE), job.builderType.toName(CLEAN_FIELD_NAME), maker.TypeIdent(CTC_BOOLEAN), null); + injectFieldAndMarkGenerated(job.builderType, uncleanField); recursiveSetGeneratedBy(uncleanField, ast, annotationNode.getContext()); } - if (constructorExists(builderType) == MemberExistsResult.NOT_EXISTS) { - JCMethodDecl cd = HandleConstructor.createConstructor(AccessLevel.PACKAGE, List.<JCAnnotation>nil(), builderType, List.<JavacNode>nil(), false, annotationNode); - if (cd != null) injectMethod(builderType, cd); + if (constructorExists(job.builderType) == MemberExistsResult.NOT_EXISTS) { + JCMethodDecl cd = HandleConstructor.createConstructor(AccessLevel.PACKAGE, List.<JCAnnotation>nil(), job.builderType, List.<JavacNode>nil(), false, annotationNode); + if (cd != null) injectMethod(job.builderType, cd); } - for (BuilderFieldData bfd : builderFields) { - makePrefixedSetterMethodsForBuilder(cfv, builderType, bfd, annotationNode, fluent, chain, accessForInners, builderInstance.setterPrefix()); + for (BuilderFieldData bfd : job.builderFields) { + makePrefixedSetterMethodsForBuilder(job, bfd, annInstance.setterPrefix()); } { - MemberExistsResult methodExists = methodExists(buildMethodName, builderType, -1); - if (methodExists == MemberExistsResult.EXISTS_BY_LOMBOK) methodExists = methodExists(buildMethodName, builderType, 0); + MemberExistsResult methodExists = methodExists(job.buildMethodName, job.builderType, -1); + if (methodExists == MemberExistsResult.EXISTS_BY_LOMBOK) methodExists = methodExists(job.buildMethodName, job.builderType, 0); if (methodExists == MemberExistsResult.NOT_EXISTS) { - JCMethodDecl md = generateBuildMethod(cfv, tdParent, isStatic, buildMethodName, nameOfBuilderMethod, returnType, builderFields, builderType, thrownExceptions, ast, addCleaning, accessForInners); + JCMethodDecl md = generateBuildMethod(job, nameOfBuilderMethod, buildMethodReturnType, buildMethodThrownExceptions, addCleaning); if (md != null) { - injectMethod(builderType, md); + injectMethod(job.builderType, md); recursiveSetGeneratedBy(md, ast, annotationNode.getContext()); } } } - if (methodExists("toString", builderType, 0) == MemberExistsResult.NOT_EXISTS) { + if (methodExists("toString", job.builderType, 0) == MemberExistsResult.NOT_EXISTS) { java.util.List<Included<JavacNode, ToString.Include>> fieldNodes = new ArrayList<Included<JavacNode, ToString.Include>>(); - for (BuilderFieldData bfd : builderFields) { + for (BuilderFieldData bfd : job.builderFields) { for (JavacNode f : bfd.createdFields) { fieldNodes.add(new Included<JavacNode, ToString.Include>(f, null, true, false)); } } - JCMethodDecl md = HandleToString.createToString(builderType, fieldNodes, true, false, FieldAccess.ALWAYS_FIELD, ast); - if (md != null) injectMethod(builderType, md); + JCMethodDecl md = HandleToString.createToString(job.builderType, fieldNodes, true, false, FieldAccess.ALWAYS_FIELD, ast); + if (md != null) injectMethod(job.builderType, md); } - if (addCleaning) injectMethod(builderType, generateCleanMethod(builderFields, builderType, ast)); + if (addCleaning) injectMethod(job.builderType, generateCleanMethod(job)); - if (generateBuilderMethod && methodExists(builderMethodName, tdParent, -1) != MemberExistsResult.NOT_EXISTS) generateBuilderMethod = false; + if (generateBuilderMethod && methodExists(job.builderMethodName, job.parentType, -1) != MemberExistsResult.NOT_EXISTS) generateBuilderMethod = false; if (generateBuilderMethod) { - JCMethodDecl md = generateBuilderMethod(cfv, isStatic, builderMethodName, builderClassName, annotationNode, tdParent, typeParams, accessForOuters); + JCMethodDecl md = generateBuilderMethod(job); recursiveSetGeneratedBy(md, ast, annotationNode.getContext()); - if (md != null) injectMethod(tdParent, md); + if (md != null) injectMethod(job.parentType, md); } - if (toBuilder) { - switch (methodExists(toBuilderMethodName, tdParent, 0)) { + if (job.toBuilder) { + switch (methodExists(TO_BUILDER_METHOD_NAME, job.parentType, 0)) { case EXISTS_BY_USER: annotationNode.addWarning("Not generating toBuilder() as it already exists."); return; case NOT_EXISTS: - List<JCTypeParameter> tps = typeParams; + List<JCTypeParameter> tps = job.typeParams; if (typeArgsForToBuilder != null) { ListBuffer<JCTypeParameter> lb = new ListBuffer<JCTypeParameter>(); - JavacTreeMaker maker = tdParent.getTreeMaker(); + JavacTreeMaker maker = job.getTreeMaker(); for (Name n : typeArgsForToBuilder) { lb.append(maker.TypeParameter(n, List.<JCExpression>nil())); } tps = lb.toList(); } - JCMethodDecl md = generateToBuilderMethod(cfv, toBuilderMethodName, builderClassName, tdParent, isStatic, tps, builderFields, fluent, ast, accessForOuters, builderInstance.setterPrefix()); + JCMethodDecl md = generateToBuilderMethod(job, tps, annInstance.setterPrefix()); if (md != null) { recursiveSetGeneratedBy(md, ast, annotationNode.getContext()); - injectMethod(tdParent, md); + injectMethod(job.parentType, md); } } } @@ -551,47 +609,45 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { sb.append("__ERR__"); } - private static final String BUILDER_TEMP_VAR = "builder"; - private JCMethodDecl generateToBuilderMethod(CheckerFrameworkVersion cfv, String toBuilderMethodName, String builderClassName, JavacNode type, boolean isStatic, List<JCTypeParameter> typeParams, java.util.List<BuilderFieldData> builderFields, boolean fluent, JCAnnotation ast, AccessLevel access, String prefix) { + private JCMethodDecl generateToBuilderMethod(BuilderJob job, List<JCTypeParameter> typeParameters, String prefix) { // return new ThingieBuilder<A, B>().setA(this.a).setB(this.b); - JavacTreeMaker maker = type.getTreeMaker(); - + JavacTreeMaker maker = job.getTreeMaker(); ListBuffer<JCExpression> typeArgs = new ListBuffer<JCExpression>(); - for (JCTypeParameter typeParam : typeParams) { + for (JCTypeParameter typeParam : typeParameters) { typeArgs.append(maker.Ident(typeParam.name)); } - JCExpression call = maker.NewClass(null, List.<JCExpression>nil(), namePlusTypeParamsToTypeReference(maker, type, type.toName(builderClassName), !isStatic, typeParams), List.<JCExpression>nil(), null); + JCExpression call = maker.NewClass(null, List.<JCExpression>nil(), namePlusTypeParamsToTypeReference(maker, job.parentType, job.toName(job.builderClassName), !job.isStatic, job.builderTypeParams), List.<JCExpression>nil(), null); JCExpression invoke = call; ListBuffer<JCStatement> preStatements = null; ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>(); - for (BuilderFieldData bfd : builderFields) { - String setterPrefix = !prefix.isEmpty() ? prefix : fluent ? "" : "set"; + for (BuilderFieldData bfd : job.builderFields) { + String setterPrefix = !prefix.isEmpty() ? prefix : job.oldFluent ? "" : "set"; String prefixedSetterName = bfd.name.toString(); if (!setterPrefix.isEmpty()) prefixedSetterName = HandlerUtil.buildAccessorName(setterPrefix, prefixedSetterName); - Name setterName = type.toName(prefixedSetterName); + Name setterName = job.toName(prefixedSetterName); JCExpression[] tgt = new JCExpression[bfd.singularData == null ? 1 : 2]; if (bfd.obtainVia == null || !bfd.obtainVia.field().isEmpty()) { for (int i = 0; i < tgt.length; i++) { - tgt[i] = maker.Select(maker.Ident(type.toName("this")), bfd.obtainVia == null ? bfd.rawName : type.toName(bfd.obtainVia.field())); + tgt[i] = maker.Select(maker.Ident(job.toName("this")), bfd.obtainVia == null ? bfd.rawName : job.toName(bfd.obtainVia.field())); } } else { String name = bfd.obtainVia.method(); JCMethodInvocation inv; if (bfd.obtainVia.isStatic()) { - JCExpression c = maker.Select(maker.Ident(type.toName(type.getName())), type.toName(name)); - inv = maker.Apply(typeParameterNames(maker, typeParams), c, List.<JCExpression>of(maker.Ident(type.toName("this")))); + JCExpression c = maker.Select(maker.Ident(job.toName(job.parentType.getName())), job.toName(name)); + inv = maker.Apply(typeParameterNames(maker, typeParameters), c, List.<JCExpression>of(maker.Ident(job.toName("this")))); } else { - JCExpression c = maker.Select(maker.Ident(type.toName("this")), type.toName(name)); + JCExpression c = maker.Select(maker.Ident(job.toName("this")), job.toName(name)); inv = maker.Apply(List.<JCExpression>nil(), c, List.<JCExpression>nil()); } for (int i = 0; i < tgt.length; i++) tgt[i] = maker.Ident(bfd.name); // javac appears to cache the type of JCMethodInvocation expressions based on position, meaning, if you have 2 ObtainVia-based method invokes on different types, you get bizarre type mismatch errors. // going via a local variable declaration solves the problem. - JCExpression varType = JavacHandlerUtil.cloneType(maker, bfd.type, ast, type.getContext()); + JCExpression varType = JavacHandlerUtil.cloneType(maker, bfd.type, job.source, job.getContext()); if (preStatements == null) preStatements = new ListBuffer<JCStatement>(); preStatements.append(maker.VarDef(maker.Modifiers(Flags.FINAL), bfd.name, varType, inv)); } @@ -602,15 +658,15 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { invoke = maker.Apply(List.<JCExpression>nil(), maker.Select(invoke, setterName), List.of(arg)); } else { JCExpression isNotNull = maker.Binary(CTC_NOT_EQUAL, tgt[0], maker.Literal(CTC_BOT, null)); - JCExpression invokeBuilder = maker.Apply(List.<JCExpression>nil(), maker.Select(maker.Ident(type.toName(BUILDER_TEMP_VAR)), setterName), List.<JCExpression>of(tgt[1])); + JCExpression invokeBuilder = maker.Apply(List.<JCExpression>nil(), maker.Select(maker.Ident(job.toName(BUILDER_TEMP_VAR)), setterName), List.<JCExpression>of(tgt[1])); statements.append(maker.If(isNotNull, maker.Exec(invokeBuilder), null)); } } if (!statements.isEmpty()) { - JCExpression tempVarType = namePlusTypeParamsToTypeReference(maker, type, type.toName(builderClassName), !isStatic, typeParams); - statements.prepend(maker.VarDef(maker.Modifiers(Flags.FINAL), type.toName(BUILDER_TEMP_VAR), tempVarType, invoke)); - statements.append(maker.Return(maker.Ident(type.toName(BUILDER_TEMP_VAR)))); + JCExpression tempVarType = namePlusTypeParamsToTypeReference(maker, job.parentType, job.getBuilderClassName(), !job.isStatic, typeParameters); + statements.prepend(maker.VarDef(maker.Modifiers(Flags.FINAL), job.toName(BUILDER_TEMP_VAR), tempVarType, invoke)); + statements.append(maker.Return(maker.Ident(job.toName(BUILDER_TEMP_VAR)))); } else { statements.append(maker.Return(invoke)); } @@ -620,77 +676,78 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { statements = preStatements; } JCBlock body = maker.Block(0, statements.toList()); - List<JCAnnotation> annsOnMethod = cfv.generateUnique() ? List.of(maker.Annotation(genTypeRef(type, CheckerFrameworkVersion.NAME__UNIQUE), List.<JCExpression>nil())) : List.<JCAnnotation>nil(); - JCMethodDecl methodDef = maker.MethodDef(maker.Modifiers(toJavacModifier(access), annsOnMethod), type.toName(toBuilderMethodName), namePlusTypeParamsToTypeReference(maker, type, type.toName(builderClassName), !isStatic, typeParams), List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null); - createRelevantNonNullAnnotation(type, methodDef); + List<JCAnnotation> annsOnParamType = List.nil(); + if (job.checkerFramework.generateUnique()) annsOnParamType = List.of(maker.Annotation(genTypeRef(job.parentType, CheckerFrameworkVersion.NAME__UNIQUE), List.<JCExpression>nil())); + JCMethodDecl methodDef = maker.MethodDef(maker.Modifiers(toJavacModifier(job.accessOuters)), job.toName(TO_BUILDER_METHOD_NAME), namePlusTypeParamsToTypeReference(maker, job.parentType, job.getBuilderClassName(), !job.isStatic, typeParameters, annsOnParamType), List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null); + createRelevantNonNullAnnotation(job.parentType, methodDef); return methodDef; } - private JCMethodDecl generateCleanMethod(java.util.List<BuilderFieldData> builderFields, JavacNode type, JCTree source) { - JavacTreeMaker maker = type.getTreeMaker(); + private JCMethodDecl generateCleanMethod(BuilderJob job) { + JavacTreeMaker maker = job.getTreeMaker(); ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>(); - for (BuilderFieldData bfd : builderFields) { + for (BuilderFieldData bfd : job.builderFields) { if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) { - bfd.singularData.getSingularizer().appendCleaningCode(bfd.singularData, type, source, statements); + bfd.singularData.getSingularizer().appendCleaningCode(bfd.singularData, job.builderType, job.source, statements); } } - statements.append(maker.Exec(maker.Assign(maker.Select(maker.Ident(type.toName("this")), type.toName("$lombokUnclean")), maker.Literal(CTC_BOOLEAN, 0)))); + statements.append(maker.Exec(maker.Assign(maker.Select(maker.Ident(job.toName("this")), job.toName(CLEAN_FIELD_NAME)), maker.Literal(CTC_BOOLEAN, 0)))); JCBlock body = maker.Block(0, statements.toList()); - JCMethodDecl method = maker.MethodDef(maker.Modifiers(toJavacModifier(AccessLevel.PRIVATE)), type.toName("$lombokClean"), maker.Type(Javac.createVoidType(type.getSymbolTable(), CTC_VOID)), List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null); - recursiveSetGeneratedBy(method, source, type.getContext()); + JCMethodDecl method = maker.MethodDef(maker.Modifiers(toJavacModifier(AccessLevel.PRIVATE)), job.toName(CLEAN_METHOD_NAME), maker.Type(Javac.createVoidType(job.builderType.getSymbolTable(), CTC_VOID)), List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null); + recursiveSetGeneratedBy(method, job.source, job.getContext()); return method; } - static List<JCVariableDecl> generateBuildArgs(CheckerFrameworkVersion cfv, JavacNode type, java.util.List<BuilderFieldData> builderFields) { - if (!cfv.generateCalledMethods()) return List.<JCVariableDecl>nil(); - + static JCVariableDecl generateReceiver(BuilderJob job) { + if (!job.checkerFramework.generateCalledMethods()) return null; + ArrayList<String> mandatories = new ArrayList<String>(); - for (BuilderFieldData bfd : builderFields) { + for (BuilderFieldData bfd : job.builderFields) { if (bfd.singularData == null && bfd.nameOfSetFlag == null) mandatories.add(bfd.name.toString()); } - + JCExpression arg; - JavacTreeMaker maker = type.getTreeMaker(); - if (mandatories.size() == 0) return List.<JCVariableDecl>nil(); + JavacTreeMaker maker = job.getTreeMaker(); + if (mandatories.size() == 0) return null; if (mandatories.size() == 1) arg = maker.Literal(mandatories.get(0)); else { List<JCExpression> elems = List.nil(); for (int i = mandatories.size() - 1; i >= 0; i--) elems = elems.prepend(maker.Literal(mandatories.get(i))); arg = maker.NewArray(null, List.<JCExpression>nil(), elems); } - JCAnnotation recvAnno = maker.Annotation(genTypeRef(type, CheckerFrameworkVersion.NAME__CALLED), List.of(arg)); - JCClassDecl builderTypeNode = (JCClassDecl) type.get(); - JCVariableDecl recv = maker.VarDef(maker.Modifiers(0L, List.<JCAnnotation>of(recvAnno)), type.toName("this"), namePlusTypeParamsToTypeReference(maker, type, builderTypeNode.typarams), null); - return List.of(recv); + JCAnnotation recvAnno = maker.Annotation(genTypeRef(job.builderType, CheckerFrameworkVersion.NAME__CALLED), List.of(arg)); + JCClassDecl builderTypeNode = (JCClassDecl) job.builderType.get(); + JCVariableDecl recv = maker.VarDef(maker.Modifiers(Flags.PARAMETER, List.<JCAnnotation>nil()), job.toName("this"), namePlusTypeParamsToTypeReference(maker, job.builderType, builderTypeNode.typarams, List.<JCAnnotation>of(recvAnno)), null); + return recv; } - private JCMethodDecl generateBuildMethod(CheckerFrameworkVersion cfv, JavacNode tdParent, boolean isStatic, String buildName, Name builderName, JCExpression returnType, java.util.List<BuilderFieldData> builderFields, JavacNode type, List<JCExpression> thrownExceptions, JCTree source, boolean addCleaning, AccessLevel access) { - JavacTreeMaker maker = type.getTreeMaker(); + private JCMethodDecl generateBuildMethod(BuilderJob job, Name staticName, JCExpression returnType, List<JCExpression> thrownExceptions, boolean addCleaning) { + JavacTreeMaker maker = job.getTreeMaker(); JCExpression call; ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>(); if (addCleaning) { - JCExpression notClean = maker.Unary(CTC_NOT, maker.Select(maker.Ident(type.toName("this")), type.toName("$lombokUnclean"))); - JCStatement invokeClean = maker.Exec(maker.Apply(List.<JCExpression>nil(), maker.Ident(type.toName("$lombokClean")), List.<JCExpression>nil())); + JCExpression notClean = maker.Unary(CTC_NOT, maker.Select(maker.Ident(job.toName("this")), job.toName(CLEAN_FIELD_NAME))); + JCStatement invokeClean = maker.Exec(maker.Apply(List.<JCExpression>nil(), maker.Ident(job.toName(CLEAN_METHOD_NAME)), List.<JCExpression>nil())); JCIf ifUnclean = maker.If(notClean, invokeClean, null); statements.append(ifUnclean); } - for (BuilderFieldData bfd : builderFields) { + for (BuilderFieldData bfd : job.builderFields) { if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) { - bfd.singularData.getSingularizer().appendBuildCode(bfd.singularData, type, source, statements, bfd.builderFieldName, "this"); + bfd.singularData.getSingularizer().appendBuildCode(bfd.singularData, job.builderType, job.source, statements, bfd.builderFieldName, "this"); } } ListBuffer<JCExpression> args = new ListBuffer<JCExpression>(); - Name thisName = type.toName("this"); - for (BuilderFieldData bfd : builderFields) { + Name thisName = job.toName("this"); + for (BuilderFieldData bfd : job.builderFields) { if (bfd.nameOfSetFlag != null) { - statements.append(maker.VarDef(maker.Modifiers(0L), bfd.builderFieldName, cloneType(maker, bfd.type, source, tdParent.getContext()), maker.Select(maker.Ident(thisName), bfd.builderFieldName))); - statements.append(maker.If(maker.Unary(CTC_NOT, maker.Select(maker.Ident(thisName), bfd.nameOfSetFlag)), maker.Exec(maker.Assign(maker.Ident(bfd.builderFieldName), maker.Apply(typeParameterNames(maker, ((JCClassDecl) tdParent.get()).typarams), maker.Select(maker.Ident(((JCClassDecl) tdParent.get()).name), bfd.nameOfDefaultProvider), List.<JCExpression>nil()))), null)); + statements.append(maker.VarDef(maker.Modifiers(0L), bfd.builderFieldName, cloneType(maker, bfd.type, job.source, job.getContext()), maker.Select(maker.Ident(thisName), bfd.builderFieldName))); + statements.append(maker.If(maker.Unary(CTC_NOT, maker.Select(maker.Ident(thisName), bfd.nameOfSetFlag)), maker.Exec(maker.Assign(maker.Ident(bfd.builderFieldName), maker.Apply(typeParameterNames(maker, ((JCClassDecl) job.parentType.get()).typarams), maker.Select(maker.Ident(((JCClassDecl) job.parentType.get()).name), bfd.nameOfDefaultProvider), List.<JCExpression>nil()))), null)); } if (bfd.nameOfSetFlag != null || (bfd.singularData != null && bfd.singularData.getSingularizer().shadowedDuringBuild())) { args.append(maker.Ident(bfd.builderFieldName)); @@ -700,20 +757,20 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { } if (addCleaning) { - statements.append(maker.Exec(maker.Assign(maker.Select(maker.Ident(type.toName("this")), type.toName("$lombokUnclean")), maker.Literal(CTC_BOOLEAN, 1)))); + statements.append(maker.Exec(maker.Assign(maker.Select(maker.Ident(job.toName("this")), job.toName(CLEAN_FIELD_NAME)), maker.Literal(CTC_BOOLEAN, 1)))); } - if (builderName == null) { + if (staticName == null) { call = maker.NewClass(null, List.<JCExpression>nil(), returnType, args.toList(), null); statements.append(maker.Return(call)); } else { ListBuffer<JCExpression> typeParams = new ListBuffer<JCExpression>(); - for (JCTypeParameter tp : ((JCClassDecl) type.get()).typarams) { + for (JCTypeParameter tp : ((JCClassDecl) job.builderType.get()).typarams) { typeParams.append(maker.Ident(tp.name)); } - JCExpression callee = maker.Ident(((JCClassDecl) type.up().get()).name); - if (!isStatic) callee = maker.Select(callee, type.up().toName("this")); - JCExpression fn = maker.Select(callee, builderName); + JCExpression callee = maker.Ident(((JCClassDecl) job.parentType.get()).name); + if (!job.isStatic) callee = maker.Select(callee, job.toName("this")); + JCExpression fn = maker.Select(callee, staticName); call = maker.Apply(typeParams.toList(), fn, args.toList()); if (returnType instanceof JCPrimitiveTypeTree && CTC_VOID.equals(typeTag(returnType))) { statements.append(maker.Exec(call)); @@ -724,10 +781,15 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { JCBlock body = maker.Block(0, statements.toList()); - List<JCAnnotation> annsOnMethod = cfv.generateSideEffectFree() ? List.of(maker.Annotation(genTypeRef(type, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE), List.<JCExpression>nil())) : List.<JCAnnotation>nil(); - List<JCVariableDecl> params = generateBuildArgs(cfv, type, builderFields); - JCMethodDecl methodDef = maker.MethodDef(maker.Modifiers(toJavacModifier(access), annsOnMethod), type.toName(buildName), returnType, List.<JCTypeParameter>nil(), params, thrownExceptions, body, null); - if (builderName == null) createRelevantNonNullAnnotation(type, methodDef); + List<JCAnnotation> annsOnMethod = job.checkerFramework.generateSideEffectFree() ? List.of(maker.Annotation(genTypeRef(job.builderType, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE), List.<JCExpression>nil())) : List.<JCAnnotation>nil(); + JCVariableDecl recv = generateReceiver(job); + JCMethodDecl methodDef; + if (recv != null && maker.hasMethodDefWithRecvParam()) { + methodDef = maker.MethodDefWithRecvParam(maker.Modifiers(toJavacModifier(job.accessInners), annsOnMethod), job.toName(job.buildMethodName), returnType, List.<JCTypeParameter>nil(), recv, List.<JCVariableDecl>nil(), thrownExceptions, body, null); + } else { + methodDef = maker.MethodDef(maker.Modifiers(toJavacModifier(job.accessInners), annsOnMethod), job.toName(job.buildMethodName), returnType, List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), thrownExceptions, body, null); + } + if (staticName == null) createRelevantNonNullAnnotation(job.builderType, methodDef); return methodDef; } @@ -743,52 +805,54 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { return maker.MethodDef(maker.Modifiers(modifiers), methodName, cloneType(maker, field.vartype, field, fieldNode.getContext()), copyTypeParams(fieldNode, params), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null); } - public JCMethodDecl generateBuilderMethod(CheckerFrameworkVersion cfv, boolean isStatic, String builderMethodName, String builderClassName, JavacNode source, JavacNode type, List<JCTypeParameter> typeParams, AccessLevel access) { - JavacTreeMaker maker = type.getTreeMaker(); + public JCMethodDecl generateBuilderMethod(BuilderJob job) { + //String builderClassName, JavacNode source, JavacNode type, List<JCTypeParameter> typeParams, AccessLevel access) { + //builderClassName, annotationNode, tdParent, typeParams, accessForOuters); + + JavacTreeMaker maker = job.getTreeMaker(); ListBuffer<JCExpression> typeArgs = new ListBuffer<JCExpression>(); - for (JCTypeParameter typeParam : typeParams) { + for (JCTypeParameter typeParam : job.typeParams) { typeArgs.append(maker.Ident(typeParam.name)); } JCExpression call; - if (isStatic) { - call = maker.NewClass(null, List.<JCExpression>nil(), namePlusTypeParamsToTypeReference(maker, type, type.toName(builderClassName), false, typeParams), List.<JCExpression>nil(), null); + if (job.isStatic) { + call = maker.NewClass(null, List.<JCExpression>nil(), namePlusTypeParamsToTypeReference(maker, job.parentType, job.toName(job.builderClassName), false, job.typeParams), List.<JCExpression>nil(), null); } else { - call = maker.NewClass(null, List.<JCExpression>nil(), namePlusTypeParamsToTypeReference(maker, null, type.toName(builderClassName), false, typeParams), List.<JCExpression>nil(), null); - ((JCNewClass) call).encl = maker.Ident(type.toName("this")); + call = maker.NewClass(null, List.<JCExpression>nil(), namePlusTypeParamsToTypeReference(maker, null, job.toName(job.builderClassName), false, job.typeParams), List.<JCExpression>nil(), null); + ((JCNewClass) call).encl = maker.Ident(job.toName("this")); } JCStatement statement = maker.Return(call); JCBlock body = maker.Block(0, List.<JCStatement>of(statement)); - int modifiers = toJavacModifier(access); - if (isStatic) modifiers |= Flags.STATIC; - JCAnnotation annUnique = cfv.generateUnique() ? maker.Annotation(genTypeRef(type, CheckerFrameworkVersion.NAME__UNIQUE), List.<JCExpression>nil()) : null; - JCAnnotation annSef = cfv.generateSideEffectFree() ? maker.Annotation(genTypeRef(type, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE), List.<JCExpression>nil()) : null; - List<JCAnnotation> annsOnMethod; - if (annUnique != null && annSef != null) annsOnMethod = List.of(annUnique, annSef); - else if (annUnique != null) annsOnMethod = List.of(annUnique); - else if (annSef != null) annsOnMethod = List.of(annSef); - else annsOnMethod = List.nil(); - JCMethodDecl methodDef = maker.MethodDef(maker.Modifiers(modifiers, annsOnMethod), type.toName(builderMethodName), namePlusTypeParamsToTypeReference(maker, type, type.toName(builderClassName), !isStatic, typeParams), copyTypeParams(source, typeParams), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null); - createRelevantNonNullAnnotation(type, methodDef); + int modifiers = toJavacModifier(job.accessOuters); + if (job.isStatic) modifiers |= Flags.STATIC; + List<JCAnnotation> annsOnMethod = List.nil(); + if (job.checkerFramework.generateSideEffectFree()) annsOnMethod = List.of(maker.Annotation(genTypeRef(job.parentType, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE), List.<JCExpression>nil())); + List<JCAnnotation> annsOnParamType = List.nil(); + if (job.checkerFramework.generateUnique()) annsOnParamType = List.of(maker.Annotation(genTypeRef(job.parentType, CheckerFrameworkVersion.NAME__UNIQUE), List.<JCExpression>nil())); + + JCExpression returnType = namePlusTypeParamsToTypeReference(maker, job.parentType, job.getBuilderClassName(), !job.isStatic, job.builderTypeParams, annsOnParamType); + JCMethodDecl methodDef = maker.MethodDef(maker.Modifiers(modifiers, annsOnMethod), job.toName(job.builderMethodName), returnType, job.copyTypeParams(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null); + createRelevantNonNullAnnotation(job.parentType, methodDef); return methodDef; } - public void generateBuilderFields(JavacNode builderType, java.util.List<BuilderFieldData> builderFields, JCTree source) { - int len = builderFields.size(); + public void generateBuilderFields(BuilderJob job) { + int len = job.builderFields.size(); java.util.List<JavacNode> existing = new ArrayList<JavacNode>(); - for (JavacNode child : builderType.down()) { + for (JavacNode child : job.builderType.down()) { if (child.getKind() == Kind.FIELD) existing.add(child); } java.util.List<JCVariableDecl> generated = new ArrayList<JCVariableDecl>(); for (int i = len - 1; i >= 0; i--) { - BuilderFieldData bfd = builderFields.get(i); + BuilderFieldData bfd = job.builderFields.get(i); if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) { - bfd.createdFields.addAll(bfd.singularData.getSingularizer().generateFields(bfd.singularData, builderType, source)); + bfd.createdFields.addAll(bfd.singularData.getSingularizer().generateFields(bfd.singularData, job.builderType, job.source)); } else { JavacNode field = null, setFlag = null; for (JavacNode exists : existing) { @@ -796,40 +860,41 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { if (n.equals(bfd.builderFieldName)) field = exists; if (n.equals(bfd.nameOfSetFlag)) setFlag = exists; } - JavacTreeMaker maker = builderType.getTreeMaker(); + JavacTreeMaker maker = job.getTreeMaker(); if (field == null) { JCModifiers mods = maker.Modifiers(Flags.PRIVATE); - JCVariableDecl newField = maker.VarDef(mods, bfd.builderFieldName, cloneType(maker, bfd.type, source, builderType.getContext()), null); - field = injectFieldAndMarkGenerated(builderType, newField); + JCVariableDecl newField = maker.VarDef(mods, bfd.builderFieldName, cloneType(maker, bfd.type, job.source, job.getContext()), null); + field = injectFieldAndMarkGenerated(job.builderType, newField); generated.add(newField); } if (setFlag == null && bfd.nameOfSetFlag != null) { JCModifiers mods = maker.Modifiers(Flags.PRIVATE); JCVariableDecl newField = maker.VarDef(mods, bfd.nameOfSetFlag, maker.TypeIdent(CTC_BOOLEAN), null); - injectFieldAndMarkGenerated(builderType, newField); + injectFieldAndMarkGenerated(job.builderType, newField); generated.add(newField); } bfd.createdFields.add(field); } } - for (JCVariableDecl gen : generated) recursiveSetGeneratedBy(gen, source, builderType.getContext()); + for (JCVariableDecl gen : generated) recursiveSetGeneratedBy(gen, job.source, job.getContext()); } - public void makePrefixedSetterMethodsForBuilder(CheckerFrameworkVersion cfv, JavacNode builderType, BuilderFieldData fieldNode, JavacNode source, boolean fluent, boolean chain, AccessLevel access, String prefix) { - boolean deprecate = isFieldDeprecated(fieldNode.originalFieldNode); - if (fieldNode.singularData == null || fieldNode.singularData.getSingularizer() == null) { - makePrefixedSetterMethodForBuilder(cfv, builderType, deprecate, fieldNode.createdFields.get(0), fieldNode.name, fieldNode.nameOfSetFlag, source, fluent, chain, fieldNode.annotations, fieldNode.originalFieldNode, access, prefix); + public void makePrefixedSetterMethodsForBuilder(BuilderJob job, BuilderFieldData bfd, String prefix) { + boolean deprecate = isFieldDeprecated(bfd.originalFieldNode); + if (bfd.singularData == null || bfd.singularData.getSingularizer() == null) { + makePrefixedSetterMethodForBuilder(job, bfd, deprecate, prefix); } else { - fieldNode.singularData.getSingularizer().generateMethods(cfv, fieldNode.singularData, deprecate, builderType, source.get(), fluent, chain, access); + bfd.singularData.getSingularizer().generateMethods(job, bfd.singularData, deprecate); } } - private void makePrefixedSetterMethodForBuilder(CheckerFrameworkVersion cfv, JavacNode builderType, boolean deprecate, JavacNode fieldNode, Name paramName, Name nameOfSetFlag, JavacNode source, boolean fluent, boolean chain, List<JCAnnotation> annosOnParam, JavacNode originalFieldNode, AccessLevel access, String prefix) { - String setterPrefix = !prefix.isEmpty() ? prefix : fluent ? "" : "set"; - String setterName = HandlerUtil.buildAccessorName(setterPrefix, paramName.toString()); - Name setterName_ = builderType.toName(setterName); + private void makePrefixedSetterMethodForBuilder(BuilderJob job, BuilderFieldData bfd, boolean deprecate, String prefix) { + JavacNode fieldNode = bfd.createdFields.get(0); + String setterPrefix = !prefix.isEmpty() ? prefix : job.oldFluent ? "" : "set"; + String setterName = HandlerUtil.buildAccessorName(setterPrefix, bfd.name.toString()); + Name setterName_ = job.builderType.toName(setterName); - for (JavacNode child : builderType.down()) { + for (JavacNode child : job.builderType.down()) { if (child.getKind() != Kind.METHOD) continue; JCMethodDecl methodDecl = (JCMethodDecl) child.get(); Name existingName = methodDecl.name; @@ -838,23 +903,24 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { JavacTreeMaker maker = fieldNode.getTreeMaker(); - List<JCAnnotation> methodAnns = JavacHandlerUtil.findCopyableToSetterAnnotations(originalFieldNode); - JCMethodDecl newMethod = HandleSetter.createSetter(toJavacModifier(access), deprecate, fieldNode, maker, setterName, paramName, nameOfSetFlag, chain, source, methodAnns, annosOnParam); - if (cfv.generateCalledMethods()) { - JCAnnotation ncAnno = maker.Annotation(genTypeRef(source, CheckerFrameworkVersion.NAME__NOT_CALLED), List.<JCExpression>of(maker.Literal(newMethod.getName().toString()))); - JCClassDecl builderTypeNode = (JCClassDecl) builderType.get(); - JCExpression selfType = namePlusTypeParamsToTypeReference(maker, builderType, builderTypeNode.typarams); - JCVariableDecl recv = maker.VarDef(maker.Modifiers(0L, List.<JCAnnotation>of(ncAnno)), builderType.toName("this"), selfType, null); - newMethod.params = List.of(recv, newMethod.params.get(0)); - } - recursiveSetGeneratedBy(newMethod, source.get(), builderType.getContext()); - if (source.up().getKind() == Kind.METHOD) { - copyJavadocFromParam(originalFieldNode.up(), newMethod, paramName.toString()); + List<JCAnnotation> methodAnns = JavacHandlerUtil.findCopyableToSetterAnnotations(bfd.originalFieldNode); + JCMethodDecl newMethod = null; + if (job.checkerFramework.generateCalledMethods() && maker.hasMethodDefWithRecvParam()) { + JCAnnotation ncAnno = maker.Annotation(genTypeRef(job.sourceNode, CheckerFrameworkVersion.NAME__NOT_CALLED), List.<JCExpression>of(maker.Literal(setterName.toString()))); + JCClassDecl builderTypeNode = (JCClassDecl) job.builderType.get(); + JCExpression selfType = namePlusTypeParamsToTypeReference(maker, job.builderType, builderTypeNode.typarams, List.<JCAnnotation>of(ncAnno)); + JCVariableDecl recv = maker.VarDef(maker.Modifiers(Flags.PARAMETER, List.<JCAnnotation>nil()), job.builderType.toName("this"), selfType, null); + newMethod = HandleSetter.createSetterWithRecv(toJavacModifier(job.accessInners), deprecate, fieldNode, maker, setterName, bfd.name, bfd.nameOfSetFlag, job.oldChain, job.sourceNode, methodAnns, bfd.annotations, recv); + } + if (newMethod == null) newMethod = HandleSetter.createSetter(toJavacModifier(job.accessInners), deprecate, fieldNode, maker, setterName, bfd.name, bfd.nameOfSetFlag, job.oldChain, job.sourceNode, methodAnns, bfd.annotations); + recursiveSetGeneratedBy(newMethod, job.source, job.getContext()); + if (job.sourceNode.up().getKind() == Kind.METHOD) { + copyJavadocFromParam(bfd.originalFieldNode.up(), newMethod, bfd.name.toString()); } else { - copyJavadoc(originalFieldNode, newMethod, CopyJavadoc.SETTER, true); + copyJavadoc(bfd.originalFieldNode, newMethod, CopyJavadoc.SETTER, true); } - injectMethod(builderType, newMethod); + injectMethod(job.builderType, newMethod); } private void copyJavadocFromParam(JavacNode from, JCMethodDecl to, String param) { @@ -871,14 +937,16 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { } } catch (Exception ignore) {} } - - public JavacNode makeBuilderClass(boolean isStatic, JavacNode source, JavacNode tdParent, String builderClassName, List<JCTypeParameter> typeParams, JCAnnotation ast, AccessLevel access) { - JavacTreeMaker maker = tdParent.getTreeMaker(); - int modifiers = toJavacModifier(access); - if (isStatic) modifiers |= Flags.STATIC; + + public JavacNode makeBuilderClass(BuilderJob job) { + //boolean isStatic, JavacNode source, JavacNode tdParent, String builderClassName, List<JCTypeParameter> typeParams, JCAnnotation ast, AccessLevel access) { + //isStatic, annotationNode, tdParent, builderClassName, typeParams, ast, accessForOuters + JavacTreeMaker maker = job.getTreeMaker(); + int modifiers = toJavacModifier(job.accessOuters); + if (job.isStatic) modifiers |= Flags.STATIC; JCModifiers mods = maker.Modifiers(modifiers); - JCClassDecl builder = maker.ClassDef(mods, tdParent.toName(builderClassName), copyTypeParams(source, typeParams), null, List.<JCExpression>nil(), List.<JCTree>nil()); - return injectType(tdParent, builder); + JCClassDecl builder = maker.ClassDef(mods, job.getBuilderClassName(), job.copyTypeParams(), null, List.<JCExpression>nil(), List.<JCTree>nil()); + return injectType(job.parentType, builder); } private void addObtainVia(BuilderFieldData bfd, JavacNode node) { diff --git a/src/core/lombok/javac/handlers/HandleConstructor.java b/src/core/lombok/javac/handlers/HandleConstructor.java index 2a683767..f30320dc 100644 --- a/src/core/lombok/javac/handlers/HandleConstructor.java +++ b/src/core/lombok/javac/handlers/HandleConstructor.java @@ -377,7 +377,6 @@ public class HandleConstructor { addConstructorProperties(mods, typeNode, fieldsToParam); } if (onConstructor != null) mods.annotations = mods.annotations.appendList(copyAnnotations(onConstructor)); - if (getCheckerFrameworkVersion(source).generateUnique()) mods.annotations = mods.annotations.prepend(maker.Annotation(genTypeRef(source, CheckerFrameworkVersion.NAME__UNIQUE), List.<JCExpression>nil())); return recursiveSetGeneratedBy(maker.MethodDef(mods, typeNode.toName("<init>"), null, List.<JCTypeParameter>nil(), params.toList(), List.<JCExpression>nil(), maker.Block(0L, nullChecks.appendList(assigns).toList()), null), source.get(), typeNode.getContext()); @@ -456,7 +455,6 @@ public class HandleConstructor { JCClassDecl type = (JCClassDecl) typeNode.get(); JCModifiers mods = maker.Modifiers(Flags.STATIC | toJavacModifier(level)); - if (getCheckerFrameworkVersion(typeNode).generateUnique()) mods.annotations = mods.annotations.prepend(maker.Annotation(genTypeRef(typeNode, CheckerFrameworkVersion.NAME__UNIQUE), List.<JCExpression>nil())); JCExpression returnType, constructorType; @@ -469,7 +467,9 @@ public class HandleConstructor { typeParams.append(maker.TypeParameter(param.name, param.bounds)); } } - returnType = namePlusTypeParamsToTypeReference(maker, typeNode, type.typarams); + List<JCAnnotation> annsOnReturnType = List.nil(); + if (getCheckerFrameworkVersion(typeNode).generateUnique()) annsOnReturnType = List.of(maker.Annotation(genTypeRef(typeNode, CheckerFrameworkVersion.NAME__UNIQUE), List.<JCExpression>nil())); + returnType = namePlusTypeParamsToTypeReference(maker, typeNode, type.typarams, annsOnReturnType); constructorType = namePlusTypeParamsToTypeReference(maker, typeNode, type.typarams); for (JavacNode fieldNode : fields) { diff --git a/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java b/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java index d490738e..3935ab4e 100644 --- a/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java +++ b/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java @@ -234,7 +234,7 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas /* ... 1; */ init = maker.Literal(1); } - statements.append(maker.VarDef(maker.Modifiers(isEmpty ? finalFlag : 0), resultName, maker.TypeIdent(CTC_INT), init)); + statements.append(maker.VarDef(maker.Modifiers(isEmpty ? finalFlag : 0L), resultName, maker.TypeIdent(CTC_INT), init)); } for (Included<JavacNode, EqualsAndHashCode.Include> member : members) { diff --git a/src/core/lombok/javac/handlers/HandleGetter.java b/src/core/lombok/javac/handlers/HandleGetter.java index 110941d6..afe2c1b6 100644 --- a/src/core/lombok/javac/handlers/HandleGetter.java +++ b/src/core/lombok/javac/handlers/HandleGetter.java @@ -380,7 +380,7 @@ public class HandleGetter extends JavacAnnotationHandler<Getter> { /* java.lang.Object value = this.fieldName.get();*/ { JCExpression valueVarType = genJavaLangTypeRef(fieldNode, "Object"); - statements.append(maker.VarDef(maker.Modifiers(0), valueName, valueVarType, callGet(fieldNode, createFieldAccessor(maker, fieldNode, FieldAccess.ALWAYS_FIELD)))); + statements.append(maker.VarDef(maker.Modifiers(0L), valueName, valueVarType, callGet(fieldNode, createFieldAccessor(maker, fieldNode, FieldAccess.ALWAYS_FIELD)))); } /* if (value == null) { */ { diff --git a/src/core/lombok/javac/handlers/HandleSetter.java b/src/core/lombok/javac/handlers/HandleSetter.java index 82c95719..5c4c7681 100644 --- a/src/core/lombok/javac/handlers/HandleSetter.java +++ b/src/core/lombok/javac/handlers/HandleSetter.java @@ -226,7 +226,30 @@ public class HandleSetter extends JavacAnnotationHandler<Setter> { return d; } + public static JCMethodDecl createSetterWithRecv(long access, boolean deprecate, JavacNode field, JavacTreeMaker treeMaker, String setterName, Name paramName, Name booleanFieldToSet, boolean shouldReturnThis, JavacNode source, List<JCAnnotation> onMethod, List<JCAnnotation> onParam, JCVariableDecl recv) { + JCExpression returnType = null; + JCReturn returnStatement = null; + if (shouldReturnThis) { + returnType = cloneSelfType(field); + returnStatement = treeMaker.Return(treeMaker.Ident(field.toName("this"))); + } + + JCMethodDecl d = createSetterWithRecv(access, deprecate, field, treeMaker, setterName, paramName, booleanFieldToSet, returnType, returnStatement, source, onMethod, onParam, recv); + if (shouldReturnThis && getCheckerFrameworkVersion(source).generateReturnsReceiver()) { + List<JCAnnotation> annotations = d.mods.annotations; + if (annotations == null) annotations = List.nil(); + JCAnnotation anno = treeMaker.Annotation(genTypeRef(source, CheckerFrameworkVersion.NAME__RETURNS_RECEIVER), List.<JCExpression>nil()); + recursiveSetGeneratedBy(anno, source.get(), field.getContext()); + d.mods.annotations = annotations.prepend(anno); + } + return d; + } + public static JCMethodDecl createSetter(long access, boolean deprecate, JavacNode field, JavacTreeMaker treeMaker, String setterName, Name paramName, Name booleanFieldToSet, JCExpression methodType, JCStatement returnStatement, JavacNode source, List<JCAnnotation> onMethod, List<JCAnnotation> onParam) { + return createSetterWithRecv(access, deprecate, field, treeMaker, setterName, paramName, booleanFieldToSet, methodType, returnStatement, source, onMethod, onParam, null); + } + + public static JCMethodDecl createSetterWithRecv(long access, boolean deprecate, JavacNode field, JavacTreeMaker treeMaker, String setterName, Name paramName, Name booleanFieldToSet, JCExpression methodType, JCStatement returnStatement, JavacNode source, List<JCAnnotation> onMethod, List<JCAnnotation> onParam, JCVariableDecl recv) { if (setterName == null) return null; JCVariableDecl fieldDecl = (JCVariableDecl) field.get(); @@ -277,8 +300,14 @@ public class HandleSetter extends JavacAnnotationHandler<Setter> { annsOnMethod = annsOnMethod.prepend(treeMaker.Annotation(genJavaLangTypeRef(field, "Deprecated"), List.<JCExpression>nil())); } - JCMethodDecl methodDef = treeMaker.MethodDef(treeMaker.Modifiers(access, annsOnMethod), methodName, methodType, - methodGenericParams, parameters, throwsClauses, methodBody, annotationMethodDefaultValue); + JCMethodDecl methodDef; + if (recv != null && treeMaker.hasMethodDefWithRecvParam()) { + methodDef = treeMaker.MethodDefWithRecvParam(treeMaker.Modifiers(access, annsOnMethod), methodName, methodType, + methodGenericParams, recv, parameters, throwsClauses, methodBody, annotationMethodDefaultValue); + } else { + methodDef = treeMaker.MethodDef(treeMaker.Modifiers(access, annsOnMethod), methodName, methodType, + methodGenericParams, parameters, throwsClauses, methodBody, annotationMethodDefaultValue); + } if (returnStatement != null) createRelevantNonNullAnnotation(source, methodDef); JCMethodDecl decl = recursiveSetGeneratedBy(methodDef, source.get(), field.getContext()); copyJavadoc(field, decl, CopyJavadoc.SETTER, returnStatement != null); diff --git a/src/core/lombok/javac/handlers/HandleSuperBuilder.java b/src/core/lombok/javac/handlers/HandleSuperBuilder.java index f6bf9e1f..99f0ea6a 100644 --- a/src/core/lombok/javac/handlers/HandleSuperBuilder.java +++ b/src/core/lombok/javac/handlers/HandleSuperBuilder.java @@ -21,6 +21,7 @@ */ package lombok.javac.handlers; +import static lombok.javac.handlers.HandleBuilder.*; import static lombok.core.handlers.HandlerUtil.*; import static lombok.javac.Javac.*; import static lombok.javac.handlers.JavacHandlerUtil.*; @@ -78,6 +79,7 @@ import lombok.javac.JavacAnnotationHandler; import lombok.javac.JavacNode; import lombok.javac.JavacTreeMaker; import lombok.javac.handlers.HandleBuilder.BuilderFieldData; +import lombok.javac.handlers.HandleBuilder.BuilderJob; import lombok.javac.handlers.JavacHandlerUtil.MemberExistsResult; import lombok.javac.handlers.JavacSingularsRecipes.ExpressionMaker; import lombok.javac.handlers.JavacSingularsRecipes.JavacSingularizer; @@ -88,58 +90,91 @@ import lombok.javac.handlers.JavacSingularsRecipes.StatementMaker; @HandlerPriority(-1024) //-2^10; to ensure we've picked up @FieldDefault's changes (-2048) but @Value hasn't removed itself yet (-512), so that we can error on presence of it on the builder classes. public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { private static final String SELF_METHOD = "self"; - private static final String TO_BUILDER_METHOD_NAME = "toBuilder"; private static final String FILL_VALUES_METHOD_NAME = "$fillValuesFrom"; private static final String STATIC_FILL_VALUES_METHOD_NAME = "$fillValuesFromInstanceIntoBuilder"; private static final String INSTANCE_VARIABLE_NAME = "instance"; private static final String BUILDER_VARIABLE_NAME = "b"; - + + class SuperBuilderJob extends BuilderJob { + JavacNode builderAbstractType; + String builderAbstractClassName; + JavacNode builderImplType; + String builderImplClassName; + List<JCTypeParameter> builderTypeParams_; + + void init(AnnotationValues<SuperBuilder> annValues, SuperBuilder ann, JavacNode node) { + accessOuters = accessInners = AccessLevel.PUBLIC; + oldFluent = true; + oldChain = true; + + builderMethodName = ann.builderMethodName(); + buildMethodName = ann.buildMethodName(); + toBuilder = ann.toBuilder(); + + if (builderMethodName == null) builderMethodName = "builder"; + if (buildMethodName == null) buildMethodName = "build"; + builderClassName = fixBuilderClassName(node, ""); + } + + void setBuilderToImpl() { + builderType = builderImplType; + builderClassName = builderImplClassName; + builderTypeParams = typeParams; + } + + void setBuilderToAbstract() { + builderType = builderAbstractType; + builderClassName = builderAbstractClassName; + builderTypeParams = builderTypeParams_; + } + } + @Override public void handle(AnnotationValues<SuperBuilder> annotation, JCAnnotation ast, JavacNode annotationNode) { handleExperimentalFlagUsage(annotationNode, ConfigurationKeys.SUPERBUILDER_FLAG_USAGE, "@SuperBuilder"); - CheckerFrameworkVersion cfv = getCheckerFrameworkVersion(annotationNode); - SuperBuilder superbuilderAnnotation = annotation.getInstance(); - // Do not delete the SuperBuilder annotation here, we need it for @Jacksonized. + SuperBuilderJob job = new SuperBuilderJob(); + job.sourceNode = annotationNode; + job.source = ast; + job.checkerFramework = getCheckerFrameworkVersion(annotationNode); + job.isStatic = true; - String builderMethodName = superbuilderAnnotation.builderMethodName(); - String buildMethodName = superbuilderAnnotation.buildMethodName(); + SuperBuilder annInstance = annotation.getInstance(); - if (builderMethodName == null) builderMethodName = "builder"; - if (buildMethodName == null) buildMethodName = "build"; + job.init(annotation, annInstance, annotationNode); boolean generateBuilderMethod; - if (builderMethodName.isEmpty()) { + if (job.builderMethodName.isEmpty()) { generateBuilderMethod = false; - } else if (!checkName("builderMethodName", builderMethodName, annotationNode)) { + } else if (!checkName("builderMethodName", job.builderMethodName, annotationNode)) { return; } else { generateBuilderMethod = true; } - if (!checkName("buildMethodName", buildMethodName, annotationNode)) return; + if (!checkName("buildMethodName", job.buildMethodName, annotationNode)) return; - boolean toBuilder = superbuilderAnnotation.toBuilder(); + // Do not delete the SuperBuilder annotation here, we need it for @Jacksonized. - JavacNode tdParent = annotationNode.up(); + JavacNode parent = annotationNode.up(); - java.util.List<BuilderFieldData> builderFields = new ArrayList<BuilderFieldData>(); - List<JCTypeParameter> typeParams = List.nil(); - List<JCExpression> thrownExceptions = List.nil(); + job.builderFields = new ArrayList<BuilderFieldData>(); + job.typeParams = List.nil(); + List<JCExpression> buildMethodThrownExceptions = List.nil(); List<JCExpression> superclassTypeParams = List.nil(); - boolean addCleaning = false; - if (!(tdParent.get() instanceof JCClassDecl)) { + if (!(parent.get() instanceof JCClassDecl)) { annotationNode.addError("@SuperBuilder is only supported on types."); return; } // Gather all fields of the class that should be set by the builder. - JCClassDecl td = (JCClassDecl) tdParent.get(); + job.parentType = parent; + JCClassDecl td = (JCClassDecl) parent.get(); ListBuffer<JavacNode> allFields = new ListBuffer<JavacNode>(); ArrayList<JavacNode> nonFinalNonDefaultedFields = null; - boolean valuePresent = (hasAnnotation(lombok.Value.class, tdParent) || hasAnnotation("lombok.experimental.Value", tdParent)); - for (JavacNode fieldNode : HandleConstructor.findAllFields(tdParent, true)) { + boolean valuePresent = (hasAnnotation(lombok.Value.class, parent) || hasAnnotation("lombok.experimental.Value", parent)); + for (JavacNode fieldNode : HandleConstructor.findAllFields(parent, true)) { JCVariableDecl fd = (JCVariableDecl) fieldNode.get(); JavacNode isDefault = findAnnotation(Builder.Default.class, fieldNode, true); boolean isFinal = (fd.mods.flags & Flags.FINAL) != 0 || (valuePresent && !hasAnnotation(NonFinal.class, fieldNode)); @@ -149,7 +184,7 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { bfd.builderFieldName = bfd.name; bfd.annotations = findCopyableAnnotations(fieldNode); bfd.type = fd.vartype; - bfd.singularData = getSingularData(fieldNode, superbuilderAnnotation.setterPrefix()); + bfd.singularData = getSingularData(fieldNode, annInstance.setterPrefix()); bfd.originalFieldNode = fieldNode; if (bfd.singularData != null && isDefault != null) { @@ -169,44 +204,21 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { } if (isDefault != null) { - bfd.nameOfDefaultProvider = tdParent.toName("$default$" + bfd.name); - bfd.nameOfSetFlag = tdParent.toName(bfd.name + "$set"); - bfd.builderFieldName = tdParent.toName(bfd.name + "$value"); + bfd.nameOfDefaultProvider = parent.toName(DEFAULT_PREFIX + bfd.name); + bfd.nameOfSetFlag = parent.toName(bfd.name + SET_PREFIX); + bfd.builderFieldName = parent.toName(bfd.name + VALUE_PREFIX); JCMethodDecl md = HandleBuilder.generateDefaultProvider(bfd.nameOfDefaultProvider, fieldNode, td.typarams); recursiveSetGeneratedBy(md, ast, annotationNode.getContext()); - if (md != null) injectMethod(tdParent, md); + if (md != null) injectMethod(parent, md); } addObtainVia(bfd, fieldNode); - builderFields.add(bfd); + job.builderFields.add(bfd); allFields.append(fieldNode); } - // Set the names of the builder classes. - String builderClassNameTemplate = annotationNode.getAst().readConfiguration(ConfigurationKeys.BUILDER_CLASS_NAME); - if (builderClassNameTemplate == null || builderClassNameTemplate.isEmpty()) builderClassNameTemplate = "*Builder"; - String builderClassName = builderClassNameTemplate.replace("*", td.name.toString()); - String builderImplClassName = builderClassName + "Impl"; - JCTree extendsClause = Javac.getExtendsClause(td); - JCExpression superclassBuilderClassExpression = null; - if (extendsClause instanceof JCTypeApply) { - // Remember the type arguments, because we need them for the extends clause of our abstract builder class. - superclassTypeParams = ((JCTypeApply) extendsClause).getTypeArguments(); - // A class name with a generics type, e.g., "Superclass<A>". - extendsClause = ((JCTypeApply) extendsClause).getType(); - } - if (extendsClause instanceof JCFieldAccess) { - Name superclassClassName = ((JCFieldAccess)extendsClause).getIdentifier(); - String superclassBuilderClassName = builderClassNameTemplate.replace("*", superclassClassName); - superclassBuilderClassExpression = tdParent.getTreeMaker().Select((JCFieldAccess) extendsClause, - tdParent.toName(superclassBuilderClassName)); - } else if (extendsClause != null) { - String superclassBuilderClassName = builderClassNameTemplate.replace("*", extendsClause.toString()); - superclassBuilderClassExpression = chainDots(tdParent, extendsClause.toString(), superclassBuilderClassName); - } - // If there is no superclass, superclassBuilderClassExpression is still == null at this point. - // You can use it to check whether to inherit or not. - - typeParams = td.typarams; + job.typeParams = job.builderTypeParams = td.typarams; + job.builderClassName = job.replaceBuilderClassName(td.name); + if (!checkName("builderClassName", job.builderClassName, annotationNode)) return; // <C, B> are the generics for our builder. String classGenericName = "C"; @@ -214,14 +226,46 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { // We have to make sure that the generics' names do not collide with any generics on the annotated class, // the classname itself, or any member type name of the annotated class. // For instance, if there are generics <B, B2, C> on the annotated class, use "C2" and "B3" for our builder. - java.util.HashSet<String> usedNames = gatherUsedTypeNames(typeParams, td); + java.util.HashSet<String> usedNames = gatherUsedTypeNames(job.typeParams, td); classGenericName = generateNonclashingNameFor(classGenericName, usedNames); builderGenericName = generateNonclashingNameFor(builderGenericName, usedNames); - thrownExceptions = List.nil(); + JavacTreeMaker maker = annotationNode.getTreeMaker(); + + { + JCExpression annotatedClass = namePlusTypeParamsToTypeReference(maker, parent, job.typeParams); + JCTypeParameter c = maker.TypeParameter(parent.toName(classGenericName), List.<JCExpression>of(annotatedClass)); + ListBuffer<JCExpression> typeParamsForBuilder = getTypeParamExpressions(job.typeParams, maker, job.sourceNode.getContext()); + typeParamsForBuilder.add(maker.Ident(parent.toName(classGenericName))); + typeParamsForBuilder.add(maker.Ident(parent.toName(builderGenericName))); + JCTypeApply typeApply = maker.TypeApply(namePlusTypeParamsToTypeReference(maker, parent, job.getBuilderClassName(), false, List.<JCTypeParameter>nil()), typeParamsForBuilder.toList()); + JCTypeParameter d = maker.TypeParameter(parent.toName(builderGenericName), List.<JCExpression>of(typeApply)); + if (job.typeParams == null || job.typeParams.isEmpty()) { + job.builderTypeParams_ = List.of(c, d); + } else { + job.builderTypeParams_ = job.typeParams.append(c).append(d); + } + } + + JCTree extendsClause = Javac.getExtendsClause(td); + JCExpression superclassBuilderClass = null; + if (extendsClause instanceof JCTypeApply) { + // Remember the type arguments, because we need them for the extends clause of our abstract builder class. + superclassTypeParams = ((JCTypeApply) extendsClause).getTypeArguments(); + // A class name with a generics type, e.g., "Superclass<A>". + extendsClause = ((JCTypeApply) extendsClause).getType(); + } + if (extendsClause instanceof JCFieldAccess) { + Name superclassName = ((JCFieldAccess) extendsClause).getIdentifier(); + String superclassBuilderClassName = superclassName.toString() + "Builder"; + superclassBuilderClass = parent.getTreeMaker().Select((JCFieldAccess) extendsClause, parent.toName(superclassBuilderClassName)); + } else if (extendsClause != null) { + String superclassBuilderClassName = extendsClause.toString() + "Builder"; + superclassBuilderClass = chainDots(parent, extendsClause.toString(), superclassBuilderClassName); + } // Check validity of @ObtainVia fields, and add check if adding cleaning for @Singular is necessary. - for (BuilderFieldData bfd : builderFields) { + for (BuilderFieldData bfd : job.builderFields) { if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) { if (bfd.singularData.getSingularizer().requiresCleaning()) { addCleaning = true; @@ -240,83 +284,85 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { } } + job.builderAbstractClassName = job.builderClassName = job.replaceBuilderClassName(td.name); + job.builderImplClassName = job.builderAbstractClassName + "Impl"; + // Create the abstract builder class. - JavacNode builderType = findInnerClass(tdParent, builderClassName); - if (builderType == null) { - builderType = generateBuilderAbstractClass(annotationNode, tdParent, builderClassName, superclassBuilderClassExpression, - typeParams, superclassTypeParams, classGenericName, builderGenericName); - recursiveSetGeneratedBy(builderType.get(), ast, annotationNode.getContext()); + job.builderAbstractType = findInnerClass(parent, job.builderClassName); + if (job.builderAbstractType == null) { + job.builderAbstractType = generateBuilderAbstractClass(job, superclassBuilderClass, superclassTypeParams, classGenericName, builderGenericName); + recursiveSetGeneratedBy(job.builderAbstractType.get(), ast, annotationNode.getContext()); } else { - JCClassDecl builderTypeDeclaration = (JCClassDecl) builderType.get(); + JCClassDecl builderTypeDeclaration = (JCClassDecl) job.builderAbstractType.get(); if (!builderTypeDeclaration.getModifiers().getFlags().contains(Modifier.STATIC) || !builderTypeDeclaration.getModifiers().getFlags().contains(Modifier.ABSTRACT)) { annotationNode.addError("Existing Builder must be an abstract static inner class."); return; } - sanityCheckForMethodGeneratingAnnotationsOnBuilderClass(builderType, annotationNode); + sanityCheckForMethodGeneratingAnnotationsOnBuilderClass(job.builderAbstractType, annotationNode); // Generate errors for @Singular BFDs that have one already defined node. - for (BuilderFieldData bfd : builderFields) { + for (BuilderFieldData bfd : job.builderFields) { SingularData sd = bfd.singularData; if (sd == null) continue; JavacSingularizer singularizer = sd.getSingularizer(); if (singularizer == null) continue; - if (singularizer.checkForAlreadyExistingNodesAndGenerateError(builderType, sd)) { + if (singularizer.checkForAlreadyExistingNodesAndGenerateError(job.builderType, sd)) { bfd.singularData = null; } } } // Generate the fields in the abstract builder class that hold the values for the instance. - generateBuilderFields(builderType, builderFields, ast); + job.setBuilderToAbstract(); + generateBuilderFields(job.builderType, job.builderFields, ast); if (addCleaning) { - JavacTreeMaker maker = builderType.getTreeMaker(); - JCVariableDecl uncleanField = maker.VarDef(maker.Modifiers(Flags.PRIVATE), builderType.toName("$lombokUnclean"), maker.TypeIdent(CTC_BOOLEAN), null); + JCVariableDecl uncleanField = maker.VarDef(maker.Modifiers(Flags.PRIVATE), job.toName("$lombokUnclean"), maker.TypeIdent(CTC_BOOLEAN), null); recursiveSetGeneratedBy(uncleanField, ast, annotationNode.getContext()); - injectFieldAndMarkGenerated(builderType, uncleanField); + injectFieldAndMarkGenerated(job.builderType, uncleanField); } - if (toBuilder) { + if (job.toBuilder) { // Generate $fillValuesFrom() method in the abstract builder. - JCMethodDecl fvm = generateFillValuesMethod(tdParent, superclassBuilderClassExpression != null, builderGenericName, classGenericName, builderClassName); + JCMethodDecl fvm = generateFillValuesMethod(job, superclassBuilderClass != null, builderGenericName, classGenericName); recursiveSetGeneratedBy(fvm, ast, annotationNode.getContext()); - injectMethod(builderType, fvm); + injectMethod(job.builderType, fvm); // Generate $fillValuesFromInstanceIntoBuilder() method in the builder implementation class. - JCMethodDecl sfvm = generateStaticFillValuesMethod(tdParent, builderClassName, typeParams, builderFields, superbuilderAnnotation.setterPrefix()); + JCMethodDecl sfvm = generateStaticFillValuesMethod(job, annInstance.setterPrefix()); recursiveSetGeneratedBy(sfvm, ast, annotationNode.getContext()); - injectMethod(builderType, sfvm); + injectMethod(job.builderType, sfvm); } // Generate abstract self() and build() methods in the abstract builder. - JCMethodDecl asm = generateAbstractSelfMethod(cfv, tdParent, superclassBuilderClassExpression != null, builderGenericName); + JCMethodDecl asm = generateAbstractSelfMethod(job, superclassBuilderClass != null, builderGenericName); recursiveSetGeneratedBy(asm, ast, annotationNode.getContext()); - injectMethod(builderType, asm); - JCMethodDecl abm = generateAbstractBuildMethod(cfv, tdParent, buildMethodName, builderFields, superclassBuilderClassExpression != null, classGenericName); + injectMethod(job.builderType, asm); + JCMethodDecl abm = generateAbstractBuildMethod(job, superclassBuilderClass != null, classGenericName); recursiveSetGeneratedBy(abm, ast, annotationNode.getContext()); - injectMethod(builderType, abm); + injectMethod(job.builderType, abm); // Create the setter methods in the abstract builder. - for (BuilderFieldData bfd : builderFields) { - generateSetterMethodsForBuilder(cfv, builderType, bfd, annotationNode, builderGenericName, superbuilderAnnotation.setterPrefix()); + for (BuilderFieldData bfd : job.builderFields) { + generateSetterMethodsForBuilder(job, bfd, builderGenericName, annInstance.setterPrefix()); } // Create the toString() method for the abstract builder. java.util.List<Included<JavacNode, ToString.Include>> fieldNodes = new ArrayList<Included<JavacNode, ToString.Include>>(); - for (BuilderFieldData bfd : builderFields) { + for (BuilderFieldData bfd : job.builderFields) { for (JavacNode f : bfd.createdFields) { fieldNodes.add(new Included<JavacNode, ToString.Include>(f, null, true, false)); } } // Let toString() call super.toString() if there is a superclass, so that it also shows fields from the superclass' builder. - JCMethodDecl toStringMethod = HandleToString.createToString(builderType, fieldNodes, true, superclassBuilderClassExpression != null, FieldAccess.ALWAYS_FIELD, ast); - if (toStringMethod != null) injectMethod(builderType, toStringMethod); + JCMethodDecl toStringMethod = HandleToString.createToString(job.builderType, fieldNodes, true, superclassBuilderClass != null, FieldAccess.ALWAYS_FIELD, ast); + if (toStringMethod != null) injectMethod(job.builderType, toStringMethod); // If clean methods are requested, add them now. if (addCleaning) { - JCMethodDecl md = generateCleanMethod(builderFields, builderType, ast); + JCMethodDecl md = generateCleanMethod(job.builderFields, job.builderType, ast); recursiveSetGeneratedBy(md, ast, annotationNode.getContext()); - injectMethod(builderType, md); + injectMethod(job.builderType, md); } boolean isAbstract = (td.mods.flags & Flags.ABSTRACT) != 0; @@ -324,69 +370,71 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { // Only non-abstract classes get the Builder implementation. // Create the builder implementation class. - JavacNode builderImplType = findInnerClass(tdParent, builderImplClassName); - if (builderImplType == null) { - builderImplType = generateBuilderImplClass(annotationNode, tdParent, builderImplClassName, builderClassName, typeParams); - recursiveSetGeneratedBy(builderImplType.get(), ast, annotationNode.getContext()); + job.builderImplType = findInnerClass(parent, job.builderImplClassName); + if (job.builderImplType == null) { + job.builderImplType = generateBuilderImplClass(job); + recursiveSetGeneratedBy(job.builderImplType.get(), ast, annotationNode.getContext()); } else { - JCClassDecl builderImplTypeDeclaration = (JCClassDecl) builderImplType.get(); + JCClassDecl builderImplTypeDeclaration = (JCClassDecl) job.builderImplType.get(); if (!builderImplTypeDeclaration.getModifiers().getFlags().contains(Modifier.STATIC) || builderImplTypeDeclaration.getModifiers().getFlags().contains(Modifier.ABSTRACT)) { annotationNode.addError("Existing BuilderImpl must be a non-abstract static inner class."); return; } - sanityCheckForMethodGeneratingAnnotationsOnBuilderClass(builderImplType, annotationNode); + sanityCheckForMethodGeneratingAnnotationsOnBuilderClass(job.builderImplType, annotationNode); } // Create a simple constructor for the BuilderImpl class. - JCMethodDecl cd = HandleConstructor.createConstructor(AccessLevel.PRIVATE, List.<JCAnnotation>nil(), builderImplType, List.<JavacNode>nil(), false, annotationNode); - if (cd != null) injectMethod(builderImplType, cd); + JCMethodDecl cd = HandleConstructor.createConstructor(AccessLevel.PRIVATE, List.<JCAnnotation>nil(), job.builderImplType, List.<JavacNode>nil(), false, annotationNode); + if (cd != null) injectMethod(job.builderImplType, cd); + job.setBuilderToImpl(); // Create the self() and build() methods in the BuilderImpl. - JCMethodDecl selfMethod = generateSelfMethod(cfv, builderImplType, typeParams); + JCMethodDecl selfMethod = generateSelfMethod(job); recursiveSetGeneratedBy(selfMethod, ast, annotationNode.getContext()); - injectMethod(builderImplType, selfMethod); - if (methodExists(buildMethodName, builderImplType, -1) == MemberExistsResult.NOT_EXISTS) { - JCMethodDecl buildMethod = generateBuildMethod(cfv, buildMethodName, tdParent, builderImplType, builderFields, thrownExceptions); + injectMethod(job.builderType, selfMethod); + if (methodExists(job.buildMethodName, job.builderType, -1) == MemberExistsResult.NOT_EXISTS) { + JCMethodDecl buildMethod = generateBuildMethod(job, buildMethodThrownExceptions); recursiveSetGeneratedBy(buildMethod, ast, annotationNode.getContext()); - injectMethod(builderImplType, buildMethod); + injectMethod(job.builderType, buildMethod); } } // Generate a constructor in the annotated class that takes a builder as argument. - if (!constructorExists(tdParent, builderClassName)) { - generateBuilderBasedConstructor(cfv, tdParent, typeParams, builderFields, annotationNode, builderClassName, - superclassBuilderClassExpression != null); + if (!constructorExists(job.parentType, job.builderAbstractClassName)) { + job.setBuilderToAbstract(); + generateBuilderBasedConstructor(job, superclassBuilderClass != null); } - if (isAbstract) { + if (!isAbstract) { // Only non-abstract classes get the builder() and toBuilder() methods. - return; - } - // Add the builder() method to the annotated class. - // Allow users to specify their own builder() methods, e.g., to provide default values. - if (generateBuilderMethod && methodExists(builderMethodName, tdParent, -1) != MemberExistsResult.NOT_EXISTS) generateBuilderMethod = false; - if (generateBuilderMethod) { - JCMethodDecl builderMethod = generateBuilderMethod(cfv, builderMethodName, builderClassName, builderImplClassName, annotationNode, tdParent, typeParams); - recursiveSetGeneratedBy(builderMethod, ast, annotationNode.getContext()); - if (builderMethod != null) injectMethod(tdParent, builderMethod); - } - - // Add the toBuilder() method to the annotated class. - if (toBuilder) { - switch (methodExists(TO_BUILDER_METHOD_NAME, tdParent, 0)) { - case EXISTS_BY_USER: - break; - case NOT_EXISTS: - JCMethodDecl md = generateToBuilderMethod(cfv, builderClassName, builderImplClassName, annotationNode, tdParent, typeParams); - if (md != null) { - recursiveSetGeneratedBy(md, ast, annotationNode.getContext()); - injectMethod(tdParent, md); + // Add the builder() method to the annotated class. + // Allow users to specify their own builder() methods, e.g., to provide default values. + if (generateBuilderMethod && methodExists(job.builderMethodName, job.parentType, -1) != MemberExistsResult.NOT_EXISTS) generateBuilderMethod = false; + if (generateBuilderMethod) { + JCMethodDecl builderMethod = generateBuilderMethod(job); + if (builderMethod != null) { + recursiveSetGeneratedBy(builderMethod, ast, annotationNode.getContext()); + injectMethod(job.parentType, builderMethod); + } + } + + // Add the toBuilder() method to the annotated class. + if (job.toBuilder) { + switch (methodExists(TO_BUILDER_METHOD_NAME, job.parentType, 0)) { + case EXISTS_BY_USER: + break; + case NOT_EXISTS: + JCMethodDecl md = generateToBuilderMethod(job); + if (md != null) { + recursiveSetGeneratedBy(md, ast, annotationNode.getContext()); + injectMethod(job.parentType, md); + } + break; + default: + // Should not happen. } - break; - default: - // Should not happen. } } @@ -400,95 +448,86 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { /** * Creates and returns the abstract builder class and injects it into the annotated class. */ - private JavacNode generateBuilderAbstractClass(JavacNode source, JavacNode tdParent, String builderClass, - JCExpression superclassBuilderClassExpression, List<JCTypeParameter> typeParams, - List<JCExpression> superclassTypeParams, String classGenericName, String builderGenericName) { - - JavacTreeMaker maker = tdParent.getTreeMaker(); + private JavacNode generateBuilderAbstractClass(SuperBuilderJob job, JCExpression superclassBuilderClass, List<JCExpression> superclassTypeParams, String classGenericName, String builderGenericName) { + JavacTreeMaker maker = job.parentType.getTreeMaker(); JCModifiers mods = maker.Modifiers(Flags.STATIC | Flags.ABSTRACT | Flags.PUBLIC); // Keep any type params of the annotated class. ListBuffer<JCTypeParameter> allTypeParams = new ListBuffer<JCTypeParameter>(); - allTypeParams.addAll(copyTypeParams(source, typeParams)); + allTypeParams.addAll(copyTypeParams(job.sourceNode, job.typeParams)); // Add builder-specific type params required for inheritable builders. // 1. The return type for the build() method, named "C", which extends the annotated class. - JCExpression annotatedClass = namePlusTypeParamsToTypeReference(maker, tdParent, typeParams); + JCExpression annotatedClass = namePlusTypeParamsToTypeReference(maker, job.parentType, job.typeParams); - allTypeParams.add(maker.TypeParameter(tdParent.toName(classGenericName), List.<JCExpression>of(annotatedClass))); + allTypeParams.add(maker.TypeParameter(job.toName(classGenericName), List.<JCExpression>of(annotatedClass))); // 2. The return type for all setter methods, named "B", which extends this builder class. - Name builderClassName = tdParent.toName(builderClass); - ListBuffer<JCExpression> typeParamsForBuilder = getTypeParamExpressions(typeParams, maker, source.getContext()); - typeParamsForBuilder.add(maker.Ident(tdParent.toName(classGenericName))); - typeParamsForBuilder.add(maker.Ident(tdParent.toName(builderGenericName))); - JCTypeApply typeApply = maker.TypeApply(namePlusTypeParamsToTypeReference(maker, tdParent, builderClassName, false, List.<JCTypeParameter>nil()), typeParamsForBuilder.toList()); - allTypeParams.add(maker.TypeParameter(tdParent.toName(builderGenericName), List.<JCExpression>of(typeApply))); + Name builderClassName = job.toName(job.builderClassName); + ListBuffer<JCExpression> typeParamsForBuilder = getTypeParamExpressions(job.typeParams, maker, job.sourceNode.getContext()); + typeParamsForBuilder.add(maker.Ident(job.toName(classGenericName))); + typeParamsForBuilder.add(maker.Ident(job.toName(builderGenericName))); + JCTypeApply typeApply = maker.TypeApply(namePlusTypeParamsToTypeReference(maker, job.parentType, builderClassName, false, List.<JCTypeParameter>nil()), typeParamsForBuilder.toList()); + allTypeParams.add(maker.TypeParameter(job.toName(builderGenericName), List.<JCExpression>of(typeApply))); JCExpression extending = null; - if (superclassBuilderClassExpression != null) { + if (superclassBuilderClass != null) { // If the annotated class extends another class, we want this builder to extend the builder of the superclass. // 1. Add the type parameters of the superclass. - typeParamsForBuilder = getTypeParamExpressions(superclassTypeParams, maker, source.getContext()); + typeParamsForBuilder = getTypeParamExpressions(superclassTypeParams, maker, job.sourceNode.getContext()); // 2. Add the builder type params <C, B>. - typeParamsForBuilder.add(maker.Ident(tdParent.toName(classGenericName))); - typeParamsForBuilder.add(maker.Ident(tdParent.toName(builderGenericName))); - extending = maker.TypeApply(superclassBuilderClassExpression, typeParamsForBuilder.toList()); + typeParamsForBuilder.add(maker.Ident(job.toName(classGenericName))); + typeParamsForBuilder.add(maker.Ident(job.toName(builderGenericName))); + extending = maker.TypeApply(superclassBuilderClass, typeParamsForBuilder.toList()); } JCClassDecl builder = maker.ClassDef(mods, builderClassName, allTypeParams.toList(), extending, List.<JCExpression>nil(), List.<JCTree>nil()); - return injectType(tdParent, builder); + return injectType(job.parentType, builder); } /** * Creates and returns the concrete builder implementation class and injects it into the annotated class. */ - private JavacNode generateBuilderImplClass(JavacNode source, JavacNode tdParent, String builderImplClass, String builderAbstractClass, List<JCTypeParameter> typeParams) { - JavacTreeMaker maker = tdParent.getTreeMaker(); + private JavacNode generateBuilderImplClass(SuperBuilderJob job) { + JavacTreeMaker maker = job.getTreeMaker(); JCModifiers mods = maker.Modifiers(Flags.STATIC | Flags.PRIVATE | Flags.FINAL); // Extend the abstract builder. - JCExpression extending = namePlusTypeParamsToTypeReference(maker, tdParent, tdParent.toName(builderAbstractClass), false, List.<JCTypeParameter>nil()); + JCExpression extending = namePlusTypeParamsToTypeReference(maker, job.parentType, job.toName(job.builderAbstractClassName), false, List.<JCTypeParameter>nil()); // Add any type params of the annotated class. ListBuffer<JCTypeParameter> allTypeParams = new ListBuffer<JCTypeParameter>(); - allTypeParams.addAll(copyTypeParams(source, typeParams)); + allTypeParams.addAll(copyTypeParams(job.sourceNode, job.typeParams)); // Add builder-specific type params required for inheritable builders. // 1. The return type for the build() method (named "C" in the abstract builder), which is the annotated class. - JCExpression annotatedClass = namePlusTypeParamsToTypeReference(maker, tdParent, typeParams); + JCExpression annotatedClass = namePlusTypeParamsToTypeReference(maker, job.parentType, job.typeParams); // 2. The return type for all setter methods (named "B" in the abstract builder), which is this builder class. - JCExpression builderImplClassExpression = namePlusTypeParamsToTypeReference(maker, tdParent, tdParent.toName(builderImplClass), false, typeParams); + JCExpression builderImplClassExpression = namePlusTypeParamsToTypeReference(maker, job.parentType, job.toName(job.builderImplClassName), false, job.typeParams); - ListBuffer<JCExpression> typeParamsForBuilder = getTypeParamExpressions(typeParams, maker, source.getContext()); + ListBuffer<JCExpression> typeParamsForBuilder = getTypeParamExpressions(job.typeParams, maker, job.getContext()); typeParamsForBuilder.add(annotatedClass); typeParamsForBuilder.add(builderImplClassExpression); extending = maker.TypeApply(extending, typeParamsForBuilder.toList()); - JCClassDecl builder = maker.ClassDef(mods, tdParent.toName(builderImplClass), copyTypeParams(source, typeParams), extending, List.<JCExpression>nil(), List.<JCTree>nil()); - return injectType(tdParent, builder); + JCClassDecl builder = maker.ClassDef(mods, job.toName(job.builderImplClassName), copyTypeParams(job.parentType, job.typeParams), extending, List.<JCExpression>nil(), List.<JCTree>nil()); + return injectType(job.parentType, builder); } /** * Generates a constructor that has a builder as the only parameter. * The values from the builder are used to initialize the fields of new instances. * - * @param typeNode - * the type (with the {@code @Builder} annotation) for which a - * constructor should be generated. - * @param typeParams - * @param builderFields a list of fields in the builder which should be assigned to new instances. - * @param source the annotation (used for setting source code locations for the generated code). * @param callBuilderBasedSuperConstructor * If {@code true}, the constructor will explicitly call a super * constructor with the builder as argument. Requires * {@code builderClassAsParameter != null}. */ - private void generateBuilderBasedConstructor(CheckerFrameworkVersion cfv, JavacNode typeNode, List<JCTypeParameter> typeParams, java.util.List<BuilderFieldData> builderFields, JavacNode source, String builderClassName, boolean callBuilderBasedSuperConstructor) { - JavacTreeMaker maker = typeNode.getTreeMaker(); + private void generateBuilderBasedConstructor(SuperBuilderJob job, boolean callBuilderBasedSuperConstructor) { + JavacTreeMaker maker = job.getTreeMaker(); AccessLevel level = AccessLevel.PROTECTED; ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>(); - Name builderVariableName = typeNode.toName(BUILDER_VARIABLE_NAME); - for (BuilderFieldData bfd : builderFields) { + Name builderVariableName = job.toName(BUILDER_VARIABLE_NAME); + for (BuilderFieldData bfd : job.builderFields) { JCExpression rhs; if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) { bfd.singularData.getSingularizer().appendBuildCode(bfd.singularData, bfd.originalFieldNode, bfd.type, statements, bfd.builderFieldName, "b"); @@ -496,67 +535,66 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { } else { rhs = maker.Select(maker.Ident(builderVariableName), bfd.builderFieldName); } - JCFieldAccess fieldInThis = maker.Select(maker.Ident(typeNode.toName("this")), bfd.rawName); + JCFieldAccess fieldInThis = maker.Select(maker.Ident(job.toName("this")), bfd.rawName); JCStatement assign = maker.Exec(maker.Assign(fieldInThis, rhs)); // In case of @Builder.Default, set the value to the default if it was not set in the builder. if (bfd.nameOfSetFlag != null) { JCFieldAccess setField = maker.Select(maker.Ident(builderVariableName), bfd.nameOfSetFlag); - fieldInThis = maker.Select(maker.Ident(typeNode.toName("this")), bfd.rawName); - JCExpression parentTypeRef = namePlusTypeParamsToTypeReference(maker, typeNode, List.<JCTypeParameter>nil()); - JCAssign assignDefault = maker.Assign(fieldInThis, maker.Apply(typeParameterNames(maker, ((JCClassDecl) typeNode.get()).typarams), maker.Select(parentTypeRef, bfd.nameOfDefaultProvider), List.<JCExpression>nil())); + fieldInThis = maker.Select(maker.Ident(job.toName("this")), bfd.rawName); + JCExpression parentTypeRef = namePlusTypeParamsToTypeReference(maker, job.parentType, List.<JCTypeParameter>nil()); + JCAssign assignDefault = maker.Assign(fieldInThis, maker.Apply(typeParameterNames(maker, ((JCClassDecl) job.parentType.get()).typarams), maker.Select(parentTypeRef, bfd.nameOfDefaultProvider), List.<JCExpression>nil())); statements.append(maker.If(setField, assign, maker.Exec(assignDefault))); } else { statements.append(assign); } if (hasNonNullAnnotations(bfd.originalFieldNode)) { - JCStatement nullCheck = generateNullCheck(maker, bfd.originalFieldNode, source); + JCStatement nullCheck = generateNullCheck(maker, bfd.originalFieldNode, job.sourceNode); if (nullCheck != null) statements.append(nullCheck); } } - List<JCAnnotation> annsOnMethod = cfv.generateUnique() ? List.of(maker.Annotation(genTypeRef(typeNode, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE), List.<JCExpression>nil())) : List.<JCAnnotation>nil(); + List<JCAnnotation> annsOnMethod = job.checkerFramework.generateUnique() ? List.of(maker.Annotation(genTypeRef(job.parentType, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE), List.<JCExpression>nil())) : List.<JCAnnotation>nil(); JCModifiers mods = maker.Modifiers(toJavacModifier(level), annsOnMethod); // Create a constructor that has just the builder as parameter. ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>(); - long flags = JavacHandlerUtil.addFinalIfNeeded(Flags.PARAMETER, typeNode.getContext()); - Name builderClassname = typeNode.toName(builderClassName); + long flags = JavacHandlerUtil.addFinalIfNeeded(Flags.PARAMETER, job.getContext()); // First add all generics that are present on the parent type. - ListBuffer<JCExpression> typeParamsForBuilderParameter = getTypeParamExpressions(typeParams, maker, typeNode.getContext()); + ListBuffer<JCExpression> typeParamsForBuilderParameter = getTypeParamExpressions(job.typeParams, maker, job.getContext()); // Now add the <?, ?>. JCWildcard wildcard = maker.Wildcard(maker.TypeBoundKind(BoundKind.UNBOUND), null); typeParamsForBuilderParameter.add(wildcard); wildcard = maker.Wildcard(maker.TypeBoundKind(BoundKind.UNBOUND), null); typeParamsForBuilderParameter.add(wildcard); - JCTypeApply paramType = maker.TypeApply(namePlusTypeParamsToTypeReference(maker, typeNode, builderClassname, false, List.<JCTypeParameter>nil()), typeParamsForBuilderParameter.toList()); + JCTypeApply paramType = maker.TypeApply(namePlusTypeParamsToTypeReference(maker, job.parentType, job.getBuilderClassName(), false, List.<JCTypeParameter>nil()), typeParamsForBuilderParameter.toList()); JCVariableDecl param = maker.VarDef(maker.Modifiers(flags), builderVariableName, paramType, null); params.append(param); if (callBuilderBasedSuperConstructor) { // The first statement must be the call to the super constructor. JCMethodInvocation callToSuperConstructor = maker.Apply(List.<JCExpression>nil(), - maker.Ident(typeNode.toName("super")), + maker.Ident(job.toName("super")), List.<JCExpression>of(maker.Ident(builderVariableName))); statements.prepend(maker.Exec(callToSuperConstructor)); } - JCMethodDecl constr = recursiveSetGeneratedBy(maker.MethodDef(mods, typeNode.toName("<init>"), + JCMethodDecl constr = recursiveSetGeneratedBy(maker.MethodDef(mods, job.toName("<init>"), null, List.<JCTypeParameter>nil(), params.toList(), List.<JCExpression>nil(), - maker.Block(0L, statements.toList()), null), source.get(), typeNode.getContext()); + maker.Block(0L, statements.toList()), null), job.source, job.getContext()); - injectMethod(typeNode, constr, null, Javac.createVoidType(typeNode.getSymbolTable(), CTC_VOID)); + injectMethod(job.parentType, constr, null, Javac.createVoidType(job.builderType.getSymbolTable(), CTC_VOID)); } - private JCMethodDecl generateBuilderMethod(CheckerFrameworkVersion cfv, String builderMethodName, String builderClassName, String builderImplClassName, JavacNode source, JavacNode type, List<JCTypeParameter> typeParams) { - JavacTreeMaker maker = type.getTreeMaker(); + private JCMethodDecl generateBuilderMethod(SuperBuilderJob job) { + JavacTreeMaker maker = job.getTreeMaker(); ListBuffer<JCExpression> typeArgs = new ListBuffer<JCExpression>(); - for (JCTypeParameter typeParam : typeParams) typeArgs.append(maker.Ident(typeParam.name)); + for (JCTypeParameter typeParam : job.typeParams) typeArgs.append(maker.Ident(typeParam.name)); - JCExpression call = maker.NewClass(null, List.<JCExpression>nil(), namePlusTypeParamsToTypeReference(maker, type, type.toName(builderImplClassName), false, typeParams), List.<JCExpression>nil(), null); + JCExpression call = maker.NewClass(null, List.<JCExpression>nil(), namePlusTypeParamsToTypeReference(maker, job.parentType, job.toName(job.builderImplClassName), false, job.typeParams), List.<JCExpression>nil(), null); JCStatement statement = maker.Return(call); JCBlock body = maker.Block(0, List.<JCStatement>of(statement)); @@ -565,16 +603,16 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { // Add any type params of the annotated class to the return type. ListBuffer<JCExpression> typeParameterNames = new ListBuffer<JCExpression>(); - typeParameterNames.addAll(typeParameterNames(maker, typeParams)); + typeParameterNames.addAll(typeParameterNames(maker, job.typeParams)); // Now add the <?, ?>. JCWildcard wildcard = maker.Wildcard(maker.TypeBoundKind(BoundKind.UNBOUND), null); typeParameterNames.add(wildcard); typeParameterNames.add(wildcard); - JCTypeApply returnType = maker.TypeApply(namePlusTypeParamsToTypeReference(maker, type, type.toName(builderClassName), false, List.<JCTypeParameter>nil()), typeParameterNames.toList()); + JCTypeApply returnType = maker.TypeApply(namePlusTypeParamsToTypeReference(maker, job.parentType, job.toName(job.builderAbstractClassName), false, List.<JCTypeParameter>nil()), typeParameterNames.toList()); - List<JCAnnotation> annsOnMethod = cfv.generateUnique() ? List.of(maker.Annotation(genTypeRef(type, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE), List.<JCExpression>nil())) : List.<JCAnnotation>nil(); - JCMethodDecl methodDef = maker.MethodDef(maker.Modifiers(modifiers, annsOnMethod), type.toName(builderMethodName), returnType, copyTypeParams(source, typeParams), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null); - createRelevantNonNullAnnotation(type, methodDef); + List<JCAnnotation> annsOnMethod = job.checkerFramework.generateUnique() ? List.of(maker.Annotation(genTypeRef(job.parentType, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE), List.<JCExpression>nil())) : List.<JCAnnotation>nil(); + JCMethodDecl methodDef = maker.MethodDef(maker.Modifiers(modifiers, annsOnMethod), job.toName(job.builderMethodName), returnType, copyTypeParams(job.sourceNode, job.typeParams), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null); + createRelevantNonNullAnnotation(job.parentType, methodDef); return methodDef; } @@ -586,15 +624,15 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { * } * </pre> */ - private JCMethodDecl generateToBuilderMethod(CheckerFrameworkVersion cfv, String builderClassName, String builderImplClassName, JavacNode source, JavacNode type, List<JCTypeParameter> typeParams) { - JavacTreeMaker maker = type.getTreeMaker(); + private JCMethodDecl generateToBuilderMethod(SuperBuilderJob job) { + JavacTreeMaker maker = job.getTreeMaker(); ListBuffer<JCExpression> typeArgs = new ListBuffer<JCExpression>(); - for (JCTypeParameter typeParam : typeParams) typeArgs.append(maker.Ident(typeParam.name)); + for (JCTypeParameter typeParam : job.typeParams) typeArgs.append(maker.Ident(typeParam.name)); - JCExpression newClass = maker.NewClass(null, List.<JCExpression>nil(), namePlusTypeParamsToTypeReference(maker, type, type.toName(builderImplClassName), false, typeParams), List.<JCExpression>nil(), null); - List<JCExpression> methodArgs = List.<JCExpression>of(maker.Ident(type.toName("this"))); - JCMethodInvocation invokeFillMethod = maker.Apply(List.<JCExpression>nil(), maker.Select(newClass, type.toName(FILL_VALUES_METHOD_NAME)), methodArgs); + JCExpression newClass = maker.NewClass(null, List.<JCExpression>nil(), namePlusTypeParamsToTypeReference(maker, job.parentType, job.toName(job.builderImplClassName), false, job.typeParams), List.<JCExpression>nil(), null); + List<JCExpression> methodArgs = List.<JCExpression>of(maker.Ident(job.toName("this"))); + JCMethodInvocation invokeFillMethod = maker.Apply(List.<JCExpression>nil(), maker.Select(newClass, job.toName(FILL_VALUES_METHOD_NAME)), methodArgs); JCStatement statement = maker.Return(invokeFillMethod); JCBlock body = maker.Block(0, List.<JCStatement>of(statement)); @@ -602,16 +640,16 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { // Add any type params of the annotated class to the return type. ListBuffer<JCExpression> typeParameterNames = new ListBuffer<JCExpression>(); - typeParameterNames.addAll(typeParameterNames(maker, typeParams)); + typeParameterNames.addAll(typeParameterNames(maker, job.typeParams)); // Now add the <?, ?>. JCWildcard wildcard = maker.Wildcard(maker.TypeBoundKind(BoundKind.UNBOUND), null); typeParameterNames.add(wildcard); typeParameterNames.add(wildcard); - JCTypeApply returnType = maker.TypeApply(namePlusTypeParamsToTypeReference(maker, type, type.toName(builderClassName), false, List.<JCTypeParameter>nil()), typeParameterNames.toList()); + JCTypeApply returnType = maker.TypeApply(namePlusTypeParamsToTypeReference(maker, job.parentType, job.toName(job.builderAbstractClassName), false, List.<JCTypeParameter>nil()), typeParameterNames.toList()); - List<JCAnnotation> annsOnMethod = cfv.generateUnique() ? List.of(maker.Annotation(genTypeRef(type, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE), List.<JCExpression>nil())) : List.<JCAnnotation>nil(); - JCMethodDecl methodDef = maker.MethodDef(maker.Modifiers(modifiers, annsOnMethod), type.toName(TO_BUILDER_METHOD_NAME), returnType, List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null); - createRelevantNonNullAnnotation(type, methodDef); + List<JCAnnotation> annsOnMethod = job.checkerFramework.generateUnique() ? List.of(maker.Annotation(genTypeRef(job.parentType, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE), List.<JCExpression>nil())) : List.<JCAnnotation>nil(); + JCMethodDecl methodDef = maker.MethodDef(maker.Modifiers(modifiers, annsOnMethod), job.toName(TO_BUILDER_METHOD_NAME), returnType, List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null); + createRelevantNonNullAnnotation(job.parentType, methodDef); return methodDef; } @@ -621,43 +659,43 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { * <pre> * protected B $fillValuesFrom(final C instance) { * super.$fillValuesFrom(instance); - * FoobarBuilderImpl.$fillValuesFromInstanceIntoBuilder(instance, this); + * FoobarBuilder.$fillValuesFromInstanceIntoBuilder(instance, this); * return self(); * } * </pre> */ - private JCMethodDecl generateFillValuesMethod(JavacNode type, boolean inherited, String builderGenericName, String classGenericName, String builderImplClassName) { - JavacTreeMaker maker = type.getTreeMaker(); + private JCMethodDecl generateFillValuesMethod(SuperBuilderJob job, boolean inherited, String builderGenericName, String classGenericName) { + JavacTreeMaker maker = job.getTreeMaker(); List<JCAnnotation> annotations = List.nil(); if (inherited) { - JCAnnotation overrideAnnotation = maker.Annotation(genJavaLangTypeRef(type, "Override"), List.<JCExpression>nil()); + JCAnnotation overrideAnnotation = maker.Annotation(genJavaLangTypeRef(job.builderType, "Override"), List.<JCExpression>nil()); annotations = List.of(overrideAnnotation); } JCModifiers modifiers = maker.Modifiers(Flags.PROTECTED, annotations); - Name name = type.toName(FILL_VALUES_METHOD_NAME); - JCExpression returnType = maker.Ident(type.toName(builderGenericName)); + Name name = job.toName(FILL_VALUES_METHOD_NAME); + JCExpression returnType = maker.Ident(job.toName(builderGenericName)); - JCExpression classGenericNameExpr = maker.Ident(type.toName(classGenericName)); - JCVariableDecl param = maker.VarDef(maker.Modifiers(Flags.LocalVarFlags), type.toName(INSTANCE_VARIABLE_NAME), classGenericNameExpr, null); + JCExpression classGenericNameExpr = maker.Ident(job.toName(classGenericName)); + JCVariableDecl param = maker.VarDef(maker.Modifiers(Flags.PARAMETER | Flags.FINAL), job.toName(INSTANCE_VARIABLE_NAME), classGenericNameExpr, null); ListBuffer<JCStatement> body = new ListBuffer<JCStatement>(); if (inherited) { // Call super. JCMethodInvocation callToSuper = maker.Apply(List.<JCExpression>nil(), - maker.Select(maker.Ident(type.toName("super")), name), - List.<JCExpression>of(maker.Ident(type.toName(INSTANCE_VARIABLE_NAME)))); + maker.Select(maker.Ident(job.toName("super")), name), + List.<JCExpression>of(maker.Ident(job.toName(INSTANCE_VARIABLE_NAME)))); body.append(maker.Exec(callToSuper)); } // Call the builder implemention's helper method that actually fills the values from the instance. - JCExpression ref = namePlusTypeParamsToTypeReference(maker, type, type.toName(builderImplClassName), false, List.<JCTypeParameter>nil()); + JCExpression ref = namePlusTypeParamsToTypeReference(maker, job.parentType, job.getBuilderClassName(), false, List.<JCTypeParameter>nil()); JCMethodInvocation callStaticFillValuesMethod = maker.Apply(List.<JCExpression>nil(), - maker.Select(ref, type.toName(STATIC_FILL_VALUES_METHOD_NAME)), - List.<JCExpression>of(maker.Ident(type.toName(INSTANCE_VARIABLE_NAME)), maker.Ident(type.toName("this")))); + maker.Select(ref, job.toName(STATIC_FILL_VALUES_METHOD_NAME)), + List.<JCExpression>of(maker.Ident(job.toName(INSTANCE_VARIABLE_NAME)), maker.Ident(job.toName("this")))); body.append(maker.Exec(callStaticFillValuesMethod)); - JCReturn returnStatement = maker.Return(maker.Apply(List.<JCExpression>nil(), maker.Ident(type.toName(SELF_METHOD)), List.<JCExpression>nil())); + JCReturn returnStatement = maker.Return(maker.Apply(List.<JCExpression>nil(), maker.Ident(job.toName(SELF_METHOD)), List.<JCExpression>nil())); body.append(returnStatement); JCBlock bodyBlock = maker.Block(0, body.toList()); @@ -674,40 +712,39 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { * b.field(instance.field); * } * </pre> - * @param setterPrefix the prefix for setter methods */ - private JCMethodDecl generateStaticFillValuesMethod(JavacNode type, String builderClassname, List<JCTypeParameter> typeParams, java.util.List<BuilderFieldData> builderFields, String setterPrefix) { - JavacTreeMaker maker = type.getTreeMaker(); + private JCMethodDecl generateStaticFillValuesMethod(SuperBuilderJob job, String setterPrefix) { + JavacTreeMaker maker = job.getTreeMaker(); List<JCAnnotation> annotations = List.nil(); JCModifiers modifiers = maker.Modifiers(Flags.PRIVATE | Flags.STATIC, annotations); - Name name = type.toName(STATIC_FILL_VALUES_METHOD_NAME); + Name name = job.toName(STATIC_FILL_VALUES_METHOD_NAME); JCExpression returnType = maker.TypeIdent(CTC_VOID); // 1st parameter: "Foobar instance" - JCVariableDecl paramInstance = maker.VarDef(maker.Modifiers(Flags.LocalVarFlags), type.toName(INSTANCE_VARIABLE_NAME), cloneSelfType(type), null); + JCVariableDecl paramInstance = maker.VarDef(maker.Modifiers(Flags.PARAMETER | Flags.FINAL), job.toName(INSTANCE_VARIABLE_NAME), cloneSelfType(job.parentType), null); // 2nd parameter: "FoobarBuilder<?, ?> b" (plus generics on the annotated type) // First add all generics that are present on the parent type. - ListBuffer<JCExpression> typeParamsForBuilderParameter = getTypeParamExpressions(typeParams, maker, type.getContext()); + ListBuffer<JCExpression> typeParamsForBuilderParameter = getTypeParamExpressions(job.typeParams, maker, job.getContext()); // Now add the <?, ?>. JCWildcard wildcard = maker.Wildcard(maker.TypeBoundKind(BoundKind.UNBOUND), null); typeParamsForBuilderParameter.add(wildcard); wildcard = maker.Wildcard(maker.TypeBoundKind(BoundKind.UNBOUND), null); typeParamsForBuilderParameter.add(wildcard); - JCTypeApply builderType = maker.TypeApply(namePlusTypeParamsToTypeReference(maker, type, type.toName(builderClassname), false, List.<JCTypeParameter>nil()), typeParamsForBuilderParameter.toList()); - JCVariableDecl paramBuilder = maker.VarDef(maker.Modifiers(Flags.LocalVarFlags), type.toName(BUILDER_VARIABLE_NAME), builderType, null); - + JCTypeApply builderType = maker.TypeApply(namePlusTypeParamsToTypeReference(maker, job.parentType, job.getBuilderClassName(), false, List.<JCTypeParameter>nil()), typeParamsForBuilderParameter.toList()); + JCVariableDecl paramBuilder = maker.VarDef(maker.Modifiers(Flags.PARAMETER | Flags.FINAL), job.toName(BUILDER_VARIABLE_NAME), builderType, null); + ListBuffer<JCStatement> body = new ListBuffer<JCStatement>(); // Call the builder's setter methods to fill the values from the instance. - for (BuilderFieldData bfd : builderFields) { - JCExpressionStatement exec = createSetterCallWithInstanceValue(bfd, type, maker, setterPrefix); + for (BuilderFieldData bfd : job.builderFields) { + JCExpressionStatement exec = createSetterCallWithInstanceValue(bfd, job.parentType, maker, setterPrefix); body.append(exec); } JCBlock bodyBlock = maker.Block(0, body.toList()); - - return maker.MethodDef(modifiers, name, returnType, copyTypeParams(type, typeParams), List.of(paramInstance, paramBuilder), List.<JCExpression>nil(), bodyBlock, null); + + return maker.MethodDef(modifiers, name, returnType, copyTypeParams(job.builderType, job.typeParams), List.of(paramInstance, paramBuilder), List.<JCExpression>nil(), bodyBlock, null); } private JCExpressionStatement createSetterCallWithInstanceValue(BuilderFieldData bfd, JavacNode type, JavacTreeMaker maker, String setterPrefix) { @@ -747,80 +784,91 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { return exec; } - private JCMethodDecl generateAbstractSelfMethod(CheckerFrameworkVersion cfv, JavacNode type, boolean override, String builderGenericName) { - JavacTreeMaker maker = type.getTreeMaker(); + private JCMethodDecl generateAbstractSelfMethod(SuperBuilderJob job, boolean override, String builderGenericName) { + JavacTreeMaker maker = job.getTreeMaker(); List<JCAnnotation> annotations = List.nil(); - JCAnnotation overrideAnnotation = override ? maker.Annotation(genJavaLangTypeRef(type, "Override"), List.<JCExpression>nil()) : null; - JCAnnotation rrAnnotation = cfv.generateReturnsReceiver() ? maker.Annotation(genTypeRef(type, CheckerFrameworkVersion.NAME__RETURNS_RECEIVER), List.<JCExpression>nil()) : null; - JCAnnotation sefAnnotation = cfv.generatePure() ? maker.Annotation(genTypeRef(type, CheckerFrameworkVersion.NAME__PURE), List.<JCExpression>nil()) : null; + JCAnnotation overrideAnnotation = override ? maker.Annotation(genJavaLangTypeRef(job.builderType, "Override"), List.<JCExpression>nil()) : null; + JCAnnotation rrAnnotation = job.checkerFramework.generateReturnsReceiver() ? maker.Annotation(genTypeRef(job.builderType, CheckerFrameworkVersion.NAME__RETURNS_RECEIVER), List.<JCExpression>nil()) : null; + JCAnnotation sefAnnotation = job.checkerFramework.generatePure() ? maker.Annotation(genTypeRef(job.builderType, CheckerFrameworkVersion.NAME__PURE), List.<JCExpression>nil()) : null; if (sefAnnotation != null) annotations = annotations.prepend(sefAnnotation); if (rrAnnotation != null) annotations = annotations.prepend(rrAnnotation); if (overrideAnnotation != null) annotations = annotations.prepend(overrideAnnotation); JCModifiers modifiers = maker.Modifiers(Flags.PROTECTED | Flags.ABSTRACT, annotations); - Name name = type.toName(SELF_METHOD); - JCExpression returnType = maker.Ident(type.toName(builderGenericName)); + Name name = job.toName(SELF_METHOD); + JCExpression returnType = maker.Ident(job.toName(builderGenericName)); return maker.MethodDef(modifiers, name, returnType, List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), null, null); } - private JCMethodDecl generateSelfMethod(CheckerFrameworkVersion cfv, JavacNode builderImplType, List<JCTypeParameter> typeParams) { - JavacTreeMaker maker = builderImplType.getTreeMaker(); + private JCMethodDecl generateSelfMethod(SuperBuilderJob job) { + JavacTreeMaker maker = job.getTreeMaker(); - JCAnnotation overrideAnnotation = maker.Annotation(genJavaLangTypeRef(builderImplType, "Override"), List.<JCExpression>nil()); - JCAnnotation rrAnnotation = cfv.generateReturnsReceiver() ? maker.Annotation(genTypeRef(builderImplType, CheckerFrameworkVersion.NAME__RETURNS_RECEIVER), List.<JCExpression>nil()) : null; - JCAnnotation sefAnnotation = cfv.generatePure() ? maker.Annotation(genTypeRef(builderImplType, CheckerFrameworkVersion.NAME__PURE), List.<JCExpression>nil()) : null; + JCAnnotation overrideAnnotation = maker.Annotation(genJavaLangTypeRef(job.builderType, "Override"), List.<JCExpression>nil()); + JCAnnotation rrAnnotation = job.checkerFramework.generateReturnsReceiver() ? maker.Annotation(genTypeRef(job.builderType, CheckerFrameworkVersion.NAME__RETURNS_RECEIVER), List.<JCExpression>nil()) : null; + JCAnnotation sefAnnotation = job.checkerFramework.generatePure() ? maker.Annotation(genTypeRef(job.builderType, CheckerFrameworkVersion.NAME__PURE), List.<JCExpression>nil()) : null; List<JCAnnotation> annsOnMethod = List.nil(); if (sefAnnotation != null) annsOnMethod = annsOnMethod.prepend(sefAnnotation); if (rrAnnotation != null) annsOnMethod = annsOnMethod.prepend(rrAnnotation); annsOnMethod = annsOnMethod.prepend(overrideAnnotation); JCModifiers modifiers = maker.Modifiers(Flags.PROTECTED, annsOnMethod); - Name name = builderImplType.toName(SELF_METHOD); + Name name = job.toName(SELF_METHOD); - JCExpression returnType = namePlusTypeParamsToTypeReference(maker, builderImplType.up(), builderImplType.toName(builderImplType.getName()), false, typeParams); - JCStatement statement = maker.Return(maker.Ident(builderImplType.toName("this"))); + JCExpression returnType = namePlusTypeParamsToTypeReference(maker, job.builderType.up(), job.getBuilderClassName(), false, job.typeParams); + JCStatement statement = maker.Return(maker.Ident(job.toName("this"))); JCBlock body = maker.Block(0, List.<JCStatement>of(statement)); return maker.MethodDef(modifiers, name, returnType, List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null); } - private JCMethodDecl generateAbstractBuildMethod(CheckerFrameworkVersion cfv, JavacNode type, String methodName, java.util.List<BuilderFieldData> builderFields, boolean override, String classGenericName) { - JavacTreeMaker maker = type.getTreeMaker(); + private JCMethodDecl generateAbstractBuildMethod(SuperBuilderJob job, boolean override, String classGenericName) { + JavacTreeMaker maker = job.getTreeMaker(); List<JCAnnotation> annotations = List.nil(); if (override) { - JCAnnotation overrideAnnotation = maker.Annotation(genJavaLangTypeRef(type, "Override"), List.<JCExpression>nil()); + JCAnnotation overrideAnnotation = maker.Annotation(genJavaLangTypeRef(job.builderType, "Override"), List.<JCExpression>nil()); annotations = List.of(overrideAnnotation); } - if (cfv.generateSideEffectFree()) annotations = annotations.prepend(maker.Annotation(genTypeRef(type, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE), List.<JCExpression>nil())); + if (job.checkerFramework.generateSideEffectFree()) annotations = annotations.prepend(maker.Annotation(genTypeRef(job.builderType, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE), List.<JCExpression>nil())); JCModifiers modifiers = maker.Modifiers(Flags.PUBLIC | Flags.ABSTRACT, annotations); - Name name = type.toName(methodName); - JCExpression returnType = maker.Ident(type.toName(classGenericName)); + Name name = job.toName(job.buildMethodName); + JCExpression returnType = maker.Ident(job.toName(classGenericName)); - List<JCVariableDecl> params = HandleBuilder.generateBuildArgs(cfv, type, builderFields); - return maker.MethodDef(modifiers, name, returnType, List.<JCTypeParameter>nil(), params, List.<JCExpression>nil(), null, null); + JCVariableDecl recv = HandleBuilder.generateReceiver(job); + JCMethodDecl methodDef; + if (recv != null && maker.hasMethodDefWithRecvParam()) { + methodDef = maker.MethodDefWithRecvParam(modifiers, name, returnType, List.<JCTypeParameter>nil(), recv, List.<JCVariableDecl>nil(), List.<JCExpression>nil(), null, null); + } else { + methodDef = maker.MethodDef(modifiers, name, returnType, List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), null, null); + } + return methodDef; } - - private JCMethodDecl generateBuildMethod(CheckerFrameworkVersion cfv, String buildName, JavacNode returnType, JavacNode type, java.util.List<BuilderFieldData> builderFields, List<JCExpression> thrownExceptions) { - JavacTreeMaker maker = type.getTreeMaker(); + + private JCMethodDecl generateBuildMethod(SuperBuilderJob job, List<JCExpression> thrownExceptions) { + JavacTreeMaker maker = job.getTreeMaker(); JCExpression call; ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>(); // Use a constructor that only has this builder as parameter. - List<JCExpression> builderArg = List.<JCExpression>of(maker.Ident(type.toName("this"))); - call = maker.NewClass(null, List.<JCExpression>nil(), cloneSelfType(returnType), builderArg, null); + List<JCExpression> builderArg = List.<JCExpression>of(maker.Ident(job.toName("this"))); + call = maker.NewClass(null, List.<JCExpression>nil(), cloneSelfType(job.parentType), builderArg, null); statements.append(maker.Return(call)); JCBlock body = maker.Block(0, statements.toList()); - JCAnnotation overrideAnnotation = maker.Annotation(genJavaLangTypeRef(type, "Override"), List.<JCExpression>nil()); + JCAnnotation overrideAnnotation = maker.Annotation(genJavaLangTypeRef(job.builderType, "Override"), List.<JCExpression>nil()); List<JCAnnotation> annsOnMethod = List.of(overrideAnnotation); - if (cfv.generateSideEffectFree()) annsOnMethod = annsOnMethod.prepend(maker.Annotation(genTypeRef(type, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE), List.<JCExpression>nil())); + if (job.checkerFramework.generateSideEffectFree()) annsOnMethod = annsOnMethod.prepend(maker.Annotation(genTypeRef(job.builderType, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE), List.<JCExpression>nil())); JCModifiers modifiers = maker.Modifiers(Flags.PUBLIC, annsOnMethod); - List<JCVariableDecl> params = HandleBuilder.generateBuildArgs(cfv, type, builderFields); - JCMethodDecl methodDef = maker.MethodDef(modifiers, type.toName(buildName), cloneSelfType(returnType), List.<JCTypeParameter>nil(), params, thrownExceptions, body, null); - createRelevantNonNullAnnotation(type, methodDef); + JCVariableDecl recv = HandleBuilder.generateReceiver(job); + JCMethodDecl methodDef; + if (recv != null && maker.hasMethodDefWithRecvParam()) { + methodDef = maker.MethodDefWithRecvParam(modifiers, job.toName(job.buildMethodName), cloneSelfType(job.parentType), List.<JCTypeParameter>nil(), recv, List.<JCVariableDecl>nil(), thrownExceptions, body, null); + } else { + methodDef = maker.MethodDef(modifiers, job.toName(job.buildMethodName), cloneSelfType(job.parentType), List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), thrownExceptions, body, null); + } + createRelevantNonNullAnnotation(job.builderType, methodDef); return methodDef; } @@ -878,29 +926,30 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { for (JCVariableDecl gen : generated) recursiveSetGeneratedBy(gen, source, builderType.getContext()); } - private void generateSetterMethodsForBuilder(CheckerFrameworkVersion cfv, final JavacNode builderType, BuilderFieldData fieldNode, JavacNode source, final String builderGenericName, String setterPrefix) { + private void generateSetterMethodsForBuilder(final SuperBuilderJob job, BuilderFieldData fieldNode, final String builderGenericName, String setterPrefix) { boolean deprecate = isFieldDeprecated(fieldNode.originalFieldNode); - final JavacTreeMaker maker = builderType.getTreeMaker(); + final JavacTreeMaker maker = job.getTreeMaker(); ExpressionMaker returnTypeMaker = new ExpressionMaker() { @Override public JCExpression make() { - return maker.Ident(builderType.toName(builderGenericName)); + return maker.Ident(job.toName(builderGenericName)); }}; StatementMaker returnStatementMaker = new StatementMaker() { @Override public JCStatement make() { - return maker.Return(maker.Apply(List.<JCExpression>nil(), maker.Ident(builderType.toName(SELF_METHOD)), List.<JCExpression>nil())); + return maker.Return(maker.Apply(List.<JCExpression>nil(), maker.Ident(job.toName(SELF_METHOD)), List.<JCExpression>nil())); }}; if (fieldNode.singularData == null || fieldNode.singularData.getSingularizer() == null) { - generateSimpleSetterMethodForBuilder(cfv, builderType, deprecate, fieldNode.createdFields.get(0), fieldNode.name, fieldNode.nameOfSetFlag, source, returnTypeMaker.make(), returnStatementMaker.make(), fieldNode.annotations, fieldNode.originalFieldNode, setterPrefix); + generateSimpleSetterMethodForBuilder(job, deprecate, fieldNode.createdFields.get(0), fieldNode.name, fieldNode.nameOfSetFlag, returnTypeMaker.make(), returnStatementMaker.make(), fieldNode.annotations, fieldNode.originalFieldNode, setterPrefix); } else { - fieldNode.singularData.getSingularizer().generateMethods(cfv, fieldNode.singularData, deprecate, builderType, source.get(), true, returnTypeMaker, returnStatementMaker, AccessLevel.PUBLIC); + fieldNode.singularData.getSingularizer().generateMethods(job.checkerFramework, fieldNode.singularData, deprecate, job.builderType, + job.source, true, returnTypeMaker, returnStatementMaker, AccessLevel.PUBLIC); } } - private void generateSimpleSetterMethodForBuilder(CheckerFrameworkVersion cfv, JavacNode builderType, boolean deprecate, JavacNode fieldNode, Name paramName, Name nameOfSetFlag, JavacNode source, JCExpression returnType, JCStatement returnStatement, List<JCAnnotation> annosOnParam, JavacNode originalFieldNode, String setterPrefix) { + private void generateSimpleSetterMethodForBuilder(SuperBuilderJob job, boolean deprecate, JavacNode fieldNode, Name paramName, Name nameOfSetFlag, JCExpression returnType, JCStatement returnStatement, List<JCAnnotation> annosOnParam, JavacNode originalFieldNode, String setterPrefix) { String setterName = HandlerUtil.buildAccessorName(setterPrefix, paramName.toString()); - Name setterName_ = builderType.toName(setterName); + Name setterName_ = job.builderType.toName(setterName); - for (JavacNode child : builderType.down()) { + for (JavacNode child : job.builderType.down()) { if (child.getKind() != Kind.METHOD) continue; JCMethodDecl methodDecl = (JCMethodDecl) child.get(); Name existingName = methodDecl.name; @@ -910,23 +959,24 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { JavacTreeMaker maker = fieldNode.getTreeMaker(); List<JCAnnotation> methodAnns = JavacHandlerUtil.findCopyableToSetterAnnotations(originalFieldNode); - JCMethodDecl newMethod = HandleSetter.createSetter(Flags.PUBLIC, deprecate, fieldNode, maker, setterName, paramName, nameOfSetFlag, returnType, returnStatement, source, methodAnns, annosOnParam); - if (cfv.generateCalledMethods()) { - JCAnnotation ncAnno = maker.Annotation(genTypeRef(source, CheckerFrameworkVersion.NAME__NOT_CALLED), List.<JCExpression>of(maker.Literal(newMethod.getName().toString()))); - JCClassDecl builderTypeNode = (JCClassDecl) builderType.get(); - JCExpression selfType = namePlusTypeParamsToTypeReference(maker, builderType, builderTypeNode.typarams); - JCVariableDecl recv = maker.VarDef(maker.Modifiers(0L, List.<JCAnnotation>of(ncAnno)), builderType.toName("this"), selfType, null); - newMethod.params = List.of(recv, newMethod.params.get(0)); + JCMethodDecl newMethod = null; + if (job.checkerFramework.generateCalledMethods() && maker.hasMethodDefWithRecvParam()) { + JCAnnotation ncAnno = maker.Annotation(genTypeRef(job.sourceNode, CheckerFrameworkVersion.NAME__NOT_CALLED), List.<JCExpression>of(maker.Literal(setterName.toString()))); + JCClassDecl builderTypeNode = (JCClassDecl) job.builderType.get(); + JCExpression selfType = namePlusTypeParamsToTypeReference(maker, job.builderType, builderTypeNode.typarams, List.<JCAnnotation>of(ncAnno)); + JCVariableDecl recv = maker.VarDef(maker.Modifiers(0L, List.<JCAnnotation>nil()), job.toName("this"), selfType, null); + newMethod = HandleSetter.createSetterWithRecv(Flags.PUBLIC, deprecate, fieldNode, maker, setterName, paramName, nameOfSetFlag, returnType, returnStatement, job.sourceNode, methodAnns, annosOnParam, recv); } - if (cfv.generateReturnsReceiver()) { + if (newMethod == null) newMethod = HandleSetter.createSetter(Flags.PUBLIC, deprecate, fieldNode, maker, setterName, paramName, nameOfSetFlag, returnType, returnStatement, job.sourceNode, methodAnns, annosOnParam); + if (job.checkerFramework.generateReturnsReceiver()) { List<JCAnnotation> annotations = newMethod.mods.annotations; if (annotations == null) annotations = List.nil(); - JCAnnotation anno = maker.Annotation(genTypeRef(source, CheckerFrameworkVersion.NAME__RETURNS_RECEIVER), List.<JCExpression>nil()); - recursiveSetGeneratedBy(anno, source.get(), builderType.getContext()); + JCAnnotation anno = maker.Annotation(genTypeRef(job.builderType, CheckerFrameworkVersion.NAME__RETURNS_RECEIVER), List.<JCExpression>nil()); + recursiveSetGeneratedBy(anno, job.source, job.getContext()); newMethod.mods.annotations = annotations.prepend(anno); } - injectMethod(builderType, newMethod); + injectMethod(job.builderType, newMethod); } private void addObtainVia(BuilderFieldData bfd, JavacNode node) { diff --git a/src/core/lombok/javac/handlers/JavacSingularsRecipes.java b/src/core/lombok/javac/handlers/JavacSingularsRecipes.java index 7cd52c8c..2fc9329c 100644 --- a/src/core/lombok/javac/handlers/JavacSingularsRecipes.java +++ b/src/core/lombok/javac/handlers/JavacSingularsRecipes.java @@ -57,6 +57,7 @@ import lombok.core.configuration.CheckerFrameworkVersion; import lombok.core.handlers.HandlerUtil; import lombok.javac.JavacNode; import lombok.javac.JavacTreeMaker; +import lombok.javac.handlers.HandleBuilder.BuilderJob; public class JavacSingularsRecipes { public interface ExpressionMaker { @@ -243,20 +244,22 @@ public class JavacSingularsRecipes { * If you need more control over the return type and value, use * {@link #generateMethods(SingularData, boolean, JavacNode, JCTree, boolean, ExpressionMaker, StatementMaker)}. */ - public void generateMethods(CheckerFrameworkVersion cfv, SingularData data, boolean deprecate, final JavacNode builderType, JCTree source, boolean fluent, final boolean chain, AccessLevel access) { - final JavacTreeMaker maker = builderType.getTreeMaker(); + public void generateMethods(final BuilderJob job, SingularData data, boolean deprecate) { + //job.checkerFramework, job.builderType, job.source, job.oldFluent, job.oldChain, job.accessInners + //CheckerFrameworkVersion cfv, final JavacNode builderType, JCTree source, boolean fluent, final boolean chain, AccessLevel access) { + final JavacTreeMaker maker = job.builderType.getTreeMaker(); ExpressionMaker returnTypeMaker = new ExpressionMaker() { @Override public JCExpression make() { - return chain ? - cloneSelfType(builderType) : - maker.Type(createVoidType(builderType.getSymbolTable(), CTC_VOID)); + return job.oldChain ? + cloneSelfType(job.builderType) : + maker.Type(createVoidType(job.builderType.getSymbolTable(), CTC_VOID)); }}; StatementMaker returnStatementMaker = new StatementMaker() { @Override public JCStatement make() { - return chain ? maker.Return(maker.Ident(builderType.toName("this"))) : null; + return job.oldChain ? maker.Return(maker.Ident(job.builderType.toName("this"))) : null; }}; - generateMethods(cfv, data, deprecate, builderType, source, fluent, returnTypeMaker, returnStatementMaker, access); + generateMethods(job.checkerFramework, data, deprecate, job.builderType, job.source, job.oldFluent, returnTypeMaker, returnStatementMaker, job.accessInners); } /** diff --git a/src/core/lombok/javac/handlers/singulars/JavacGuavaSingularizer.java b/src/core/lombok/javac/handlers/singulars/JavacGuavaSingularizer.java index 7cd676c0..dadf881d 100644 --- a/src/core/lombok/javac/handlers/singulars/JavacGuavaSingularizer.java +++ b/src/core/lombok/javac/handlers/singulars/JavacGuavaSingularizer.java @@ -151,7 +151,7 @@ abstract class JavacGuavaSingularizer extends JavacSingularizer { JCExpression init = maker.Conditional(isNull, empty, invokeBuild); // this.pluralName == null ? ImmutableX.of() : this.pluralName.build() - JCStatement jcs = maker.VarDef(maker.Modifiers(0), data.getPluralName(), varType, init); + JCStatement jcs = maker.VarDef(maker.Modifiers(0L), data.getPluralName(), varType, init); statements.append(jcs); } diff --git a/src/core/lombok/javac/handlers/singulars/JavacJavaUtilListSingularizer.java b/src/core/lombok/javac/handlers/singulars/JavacJavaUtilListSingularizer.java index b4ad3428..1f8bbbe9 100644 --- a/src/core/lombok/javac/handlers/singulars/JavacJavaUtilListSingularizer.java +++ b/src/core/lombok/javac/handlers/singulars/JavacJavaUtilListSingularizer.java @@ -89,7 +89,7 @@ public class JavacJavaUtilListSingularizer extends JavacJavaUtilListSetSingulari JCStatement switchStat = maker.Switch(getSize(maker, builderType, data.getPluralName(), true, false, builderVariable), cases.toList()); JCExpression localShadowerType = chainDotsString(builderType, data.getTargetFqn()); localShadowerType = addTypeArgs(1, false, builderType, localShadowerType, data.getTypeArgs(), source); - JCStatement varDefStat = maker.VarDef(maker.Modifiers(0), data.getPluralName(), localShadowerType, null); + JCStatement varDefStat = maker.VarDef(maker.Modifiers(0L), data.getPluralName(), localShadowerType, null); statements.append(varDefStat); statements.append(switchStat); } diff --git a/src/core/lombok/javac/handlers/singulars/JavacJavaUtilSingularizer.java b/src/core/lombok/javac/handlers/singulars/JavacJavaUtilSingularizer.java index 50950915..5670b5e6 100644 --- a/src/core/lombok/javac/handlers/singulars/JavacJavaUtilSingularizer.java +++ b/src/core/lombok/javac/handlers/singulars/JavacJavaUtilSingularizer.java @@ -84,7 +84,7 @@ abstract class JavacJavaUtilSingularizer extends JavacSingularizer { JCStatement switchStat = maker.Switch(getSize(maker, builderType, mapMode ? builderType.toName(data.getPluralName() + "$key") : data.getPluralName(), true, false, builderVariable), cases.toList()); JCExpression localShadowerType = chainDotsString(builderType, data.getTargetFqn()); localShadowerType = addTypeArgs(mapMode ? 2 : 1, false, builderType, localShadowerType, data.getTypeArgs(), source); - JCStatement varDefStat = maker.VarDef(maker.Modifiers(0), data.getPluralName(), localShadowerType, null); + JCStatement varDefStat = maker.VarDef(maker.Modifiers(0L), data.getPluralName(), localShadowerType, null); return List.of(varDefStat, switchStat); } @@ -143,7 +143,7 @@ abstract class JavacJavaUtilSingularizer extends JavacSingularizer { if (defineVar) { JCExpression localShadowerType = chainDotsString(builderType, data.getTargetFqn()); localShadowerType = addTypeArgs(mapMode ? 2 : 1, false, builderType, localShadowerType, data.getTypeArgs(), source); - createStat = maker.VarDef(maker.Modifiers(0), data.getPluralName(), localShadowerType, constructorCall); + createStat = maker.VarDef(maker.Modifiers(0L), data.getPluralName(), localShadowerType, constructorCall); } else { createStat = maker.Exec(maker.Assign(maker.Ident(data.getPluralName()), constructorCall)); } @@ -161,7 +161,7 @@ abstract class JavacJavaUtilSingularizer extends JavacSingularizer { // error: method put in interface Map<K#2,V#2> cannot be applied to given types; arg2 = maker.TypeCast(createTypeArgs(2, false, builderType, data.getTypeArgs(), source).get(1), arg2); JCStatement putStatement = maker.Exec(maker.Apply(jceBlank, pluralnameDotPut, List.of(arg1, arg2))); - JCStatement forInit = maker.VarDef(maker.Modifiers(0), ivar, maker.TypeIdent(CTC_INT), maker.Literal(CTC_INT, 0)); + JCStatement forInit = maker.VarDef(maker.Modifiers(0L), ivar, maker.TypeIdent(CTC_INT), maker.Literal(CTC_INT, 0)); JCExpression checkExpr = maker.Binary(CTC_LESS_THAN, maker.Ident(ivar), getSize(maker, builderType, keyVarName, nullGuard, true, builderVariable)); JCExpression incrementExpr = maker.Unary(CTC_POSTINC, maker.Ident(ivar)); fillStat = maker.ForLoop(List.of(forInit), checkExpr, List.of(maker.Exec(incrementExpr)), putStatement); |