diff options
author | Jan Rieke <it@janrieke.de> | 2018-04-16 20:15:44 +0200 |
---|---|---|
committer | Jan Rieke <it@janrieke.de> | 2018-04-16 20:15:44 +0200 |
commit | 054a966bad3037a758af50d5801461c8995fffa9 (patch) | |
tree | 97d2e422b8c1f0fd36e685ef2fa587ecfb59197b /src | |
parent | 9df65559122a572e7ee0ea355f05d2f9a934c7e5 (diff) | |
download | lombok-054a966bad3037a758af50d5801461c8995fffa9.tar.gz lombok-054a966bad3037a758af50d5801461c8995fffa9.tar.bz2 lombok-054a966bad3037a758af50d5801461c8995fffa9.zip |
avoid name clashes with generics on the annotated class
Diffstat (limited to 'src')
-rw-r--r-- | src/core/lombok/javac/handlers/HandleSuperBuilder.java | 65 |
1 files changed, 46 insertions, 19 deletions
diff --git a/src/core/lombok/javac/handlers/HandleSuperBuilder.java b/src/core/lombok/javac/handlers/HandleSuperBuilder.java index 740b8e89..31976447 100644 --- a/src/core/lombok/javac/handlers/HandleSuperBuilder.java +++ b/src/core/lombok/javac/handlers/HandleSuperBuilder.java @@ -186,14 +186,29 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { returnType = namePlusTypeParamsToTypeReference(tdParent.getTreeMaker(), td.name, td.typarams); typeParams = td.typarams; + + // <C, B> are the generics for our builder. + String classGenericName = "C"; + String builderGenericName = "B"; + // If these generics' names collide with any generics on the annotated class, modify them. + // For instance, if there are generics <B, B2, C> on the annotated class, use "C2" and "B3" for our builder. + java.util.List<String> typeParamStrings = new ArrayList<String>(); + for (JCTypeParameter typeParam : typeParams) { + typeParamStrings.add(typeParam.getName().toString()); + } + classGenericName = generateNonclashingNameFor(classGenericName, typeParamStrings); + builderGenericName = generateNonclashingNameFor(builderGenericName, typeParamStrings); + thrownExceptions = List.nil(); - generateBuilderBasedConstructor(tdParent, typeParams, builderFields, annotationNode, builderClassName, superclassBuilderClassExpression != null); + generateBuilderBasedConstructor(tdParent, typeParams, builderFields, annotationNode, builderClassName, + superclassBuilderClassExpression != null); // Create the abstract builder class. JavacNode builderType = findInnerClass(tdParent, builderClassName); if (builderType == null) { - builderType = makeBuilderAbstractClass(annotationNode, tdParent, builderClassName, superclassBuilderClassExpression, typeParams, superclassTypeParams, ast); + builderType = makeBuilderAbstractClass(annotationNode, tdParent, builderClassName, superclassBuilderClassExpression, + typeParams, superclassTypeParams, ast, classGenericName, builderGenericName); } else { annotationNode.addError("@SuperBuilder does not support customized builders. Use @Builder instead."); return; @@ -228,12 +243,12 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { } // Generate abstract self() and build() methods in the abstract builder. - injectMethod(builderType, generateAbstractSelfMethod(tdParent, superclassBuilderClassExpression != null)); - injectMethod(builderType, generateAbstractBuildMethod(tdParent, buildMethodName, superclassBuilderClassExpression != null)); + injectMethod(builderType, generateAbstractSelfMethod(tdParent, superclassBuilderClassExpression != null, builderGenericName)); + injectMethod(builderType, generateAbstractBuildMethod(tdParent, buildMethodName, superclassBuilderClassExpression != null, classGenericName)); // Create the setter methods in the abstract builder. for (BuilderFieldData bfd : builderFields) { - makeSetterMethodsForBuilder(builderType, bfd, annotationNode); + makeSetterMethodsForBuilder(builderType, bfd, annotationNode, builderGenericName); } // Create the toString() method for the abstract builder. @@ -277,6 +292,17 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { recursiveSetGeneratedBy(builderImplType.get(), ast, annotationNode.getContext()); } + private String generateNonclashingNameFor(String classGenericName, java.util.List<String> typeParamStrings) { + if (!typeParamStrings.contains(classGenericName)) + return classGenericName; + int counter = 2; + while (typeParamStrings.contains(classGenericName + counter)) { + counter++; + } + return classGenericName + counter; + } + + /** * 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. @@ -371,7 +397,7 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { return typeParamsForBuilderParameter; } - private JCMethodDecl generateAbstractSelfMethod(JavacNode type, boolean override) { + private JCMethodDecl generateAbstractSelfMethod(JavacNode type, boolean override, String builderGenericName) { JavacTreeMaker maker = type.getTreeMaker(); List<JCAnnotation> annotations = List.nil(); if (override) { @@ -380,7 +406,7 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { } JCModifiers modifiers = maker.Modifiers(Flags.PROTECTED | Flags.ABSTRACT, annotations); Name name = type.toName(SELF_METHOD); - JCExpression returnType = maker.Ident(type.toName("B")); + JCExpression returnType = maker.Ident(type.toName(builderGenericName)); return maker.MethodDef(modifiers, name, returnType, List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), null, null); } @@ -399,7 +425,7 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { return maker.MethodDef(modifiers, name, returnType, List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null); } - private JCMethodDecl generateAbstractBuildMethod(JavacNode type, String methodName, boolean override) { + private JCMethodDecl generateAbstractBuildMethod(JavacNode type, String methodName, boolean override, String classGenericName) { JavacTreeMaker maker = type.getTreeMaker(); List<JCAnnotation> annotations = List.nil(); if (override) { @@ -408,7 +434,7 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { } JCModifiers modifiers = maker.Modifiers(Flags.PUBLIC | Flags.ABSTRACT, annotations); Name name = type.toName(methodName); - JCExpression returnType = maker.Ident(type.toName("C")); + JCExpression returnType = maker.Ident(type.toName(classGenericName)); return maker.MethodDef(modifiers, name, returnType, List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), null, null); } @@ -520,10 +546,10 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { } } - public void makeSetterMethodsForBuilder(JavacNode builderType, BuilderFieldData fieldNode, JavacNode source) { + public void makeSetterMethodsForBuilder(JavacNode builderType, BuilderFieldData fieldNode, JavacNode source, String builderGenericName) { boolean deprecate = isFieldDeprecated(fieldNode.originalFieldNode); JavacTreeMaker maker = builderType.getTreeMaker(); - JCExpression returnType = maker.Ident(builderType.toName("B")); + JCExpression returnType = maker.Ident(builderType.toName(builderGenericName)); JCReturn returnStatement = maker.Return(maker.Apply(List.<JCExpression>nil(), maker.Ident(builderType.toName(SELF_METHOD)), List.<JCExpression>nil())); if (fieldNode.singularData == null || fieldNode.singularData.getSingularizer() == null) { makeSimpleSetterMethodForBuilder(builderType, deprecate, fieldNode.createdFields.get(0), fieldNode.nameOfSetFlag, source, true, true, returnType, returnStatement); @@ -560,12 +586,13 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { return null; } - public JavacNode makeBuilderAbstractClass(JavacNode source, JavacNode tdParent, String builderClass, JCExpression superclassBuilderClassExpression, List<JCTypeParameter> typeParams, List<JCExpression> superclassTypeParams, JCAnnotation ast) { + public JavacNode makeBuilderAbstractClass(JavacNode source, JavacNode tdParent, String builderClass, + JCExpression superclassBuilderClassExpression, List<JCTypeParameter> typeParams, + List<JCExpression> superclassTypeParams, JCAnnotation ast, String classGenericName, String builderGenericName) { JavacTreeMaker maker = tdParent.getTreeMaker(); JCModifiers mods = maker.Modifiers(Flags.STATIC | Flags.ABSTRACT | Flags.PUBLIC); // Keep any type params of the annotated class. - // TODO: Prevent name clashes with type params from annotated class. ListBuffer<JCTypeParameter> allTypeParams = new ListBuffer<JCTypeParameter>(); allTypeParams.addAll(copyTypeParams(source, typeParams)); // Add builder-specific type params required for inheritable builders. @@ -575,14 +602,14 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { // Add type params of the annotated class. annotatedClass = maker.TypeApply(annotatedClass, getTypeParamExpressions(typeParams, maker).toList()); } - allTypeParams.add(maker.TypeParameter(tdParent.toName("C"), List.<JCExpression>of(annotatedClass))); + allTypeParams.add(maker.TypeParameter(tdParent.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); - typeParamsForBuilder.add(maker.Ident(tdParent.toName("C"))); - typeParamsForBuilder.add(maker.Ident(tdParent.toName("B"))); + typeParamsForBuilder.add(maker.Ident(tdParent.toName(classGenericName))); + typeParamsForBuilder.add(maker.Ident(tdParent.toName(builderGenericName))); JCTypeApply typeApply = maker.TypeApply(maker.Ident(builderClassName), typeParamsForBuilder.toList()); - allTypeParams.add(maker.TypeParameter(tdParent.toName("B"), List.<JCExpression>of(typeApply))); + allTypeParams.add(maker.TypeParameter(tdParent.toName(builderGenericName), List.<JCExpression>of(typeApply))); JCExpression extending = null; if (superclassBuilderClassExpression != null) { @@ -590,8 +617,8 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { // 1. Add the type parameters of the superclass. typeParamsForBuilder = getTypeParamExpressions(superclassTypeParams, maker); // 2. Add the builder type params <C, B>. - typeParamsForBuilder.add(maker.Ident(tdParent.toName("C"))); - typeParamsForBuilder.add(maker.Ident(tdParent.toName("B"))); + typeParamsForBuilder.add(maker.Ident(tdParent.toName(classGenericName))); + typeParamsForBuilder.add(maker.Ident(tdParent.toName(builderGenericName))); extending = maker.TypeApply(superclassBuilderClassExpression, typeParamsForBuilder.toList()); } |