diff options
author | Reinier Zwitserloot <r.zwitserloot@projectlombok.org> | 2019-12-19 21:26:35 +0100 |
---|---|---|
committer | Reinier Zwitserloot <r.zwitserloot@projectlombok.org> | 2020-01-06 05:19:37 +0100 |
commit | 889c935ec9f0e45bba1e88b0f256e1f29a734f39 (patch) | |
tree | bfa24b57a405115a491ba8bedc758dc66017698d /src/core/lombok/eclipse | |
parent | 0bb56192304905e2ae5bcee8ba6d72add950d381 (diff) | |
download | lombok-889c935ec9f0e45bba1e88b0f256e1f29a734f39.tar.gz lombok-889c935ec9f0e45bba1e88b0f256e1f29a734f39.tar.bz2 lombok-889c935ec9f0e45bba1e88b0f256e1f29a734f39.zip |
[fixes #2268] make lombok generate qualified types in order to avoid name clashes.
Diffstat (limited to 'src/core/lombok/eclipse')
4 files changed, 211 insertions, 46 deletions
diff --git a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java index 0955dba6..1c988d31 100644 --- a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java +++ b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java @@ -505,7 +505,13 @@ public class EclipseHandlerUtil { } catch (Exception ignore) {} } - public static TypeReference namePlusTypeParamsToTypeReference(char[] typeName, TypeParameter[] params, long p) { + public static TypeReference namePlusTypeParamsToTypeReference(EclipseNode type, TypeParameter[] params, long p) { + TypeDeclaration td = (TypeDeclaration) type.get(); + boolean instance = (td.modifiers & ClassFileConstants.AccStatic) == 0; + return namePlusTypeParamsToTypeReference(type.up(), td.name, instance, params, p); + } + + public static TypeReference namePlusTypeParamsToTypeReference(EclipseNode parentType, char[] typeName, boolean instance, TypeParameter[] params, long p) { if (params != null && params.length > 0) { TypeReference[] refs = new TypeReference[params.length]; int idx = 0; @@ -513,10 +519,10 @@ public class EclipseHandlerUtil { TypeReference typeRef = new SingleTypeReference(param.name, p); refs[idx++] = typeRef; } - return new ParameterizedSingleTypeReference(typeName, refs, 0, p); + return generateParameterizedTypeReference(parentType, typeName, instance, refs, p); } - return new SingleTypeReference(typeName, p); + return generateTypeReference(parentType, typeName, instance, p); } public static TypeReference[] copyTypes(TypeReference[] refs) { @@ -851,15 +857,150 @@ public class EclipseHandlerUtil { if (source != null) setGeneratedBy(typeRef, source); refs[idx++] = typeRef; } - result = new ParameterizedSingleTypeReference(typeDecl.name, refs, 0, p); + result = generateParameterizedTypeReference(type, refs, p); } else { - result = new SingleTypeReference(((TypeDeclaration)type.get()).name, p); + result = generateTypeReference(type, p); } } if (result != null && source != null) setGeneratedBy(result, source); return result; } + public static TypeReference generateParameterizedTypeReference(EclipseNode type, TypeReference[] typeParams, long p) { + TypeDeclaration td = (TypeDeclaration) type.get(); + char[][] tn = getQualifiedInnerName(type.up(), td.name); + if (tn.length == 1) return new ParameterizedSingleTypeReference(tn[0], typeParams, 0, p); + int tnLen = tn.length; + long[] ps = new long[tnLen]; + for (int i = 0; i < tnLen; i++) ps[i] = p; + TypeReference[][] rr = new TypeReference[tnLen][]; + rr[tnLen - 1] = typeParams; + boolean instance = (td.modifiers & ClassFileConstants.AccStatic) == 0; + if (instance) fillOuterTypeParams(rr, tnLen - 2, type.up(), p); + return new ParameterizedQualifiedTypeReference(tn, rr, 0, ps); + } + + public static TypeReference generateParameterizedTypeReference(EclipseNode parent, char[] name, boolean instance, TypeReference[] typeParams, long p) { + char[][] tn = getQualifiedInnerName(parent, name); + if (tn.length == 1) return new ParameterizedSingleTypeReference(tn[0], typeParams, 0, p); + int tnLen = tn.length; + long[] ps = new long[tnLen]; + for (int i = 0; i < tnLen; i++) ps[i] = p; + TypeReference[][] rr = new TypeReference[tnLen][]; + rr[tnLen - 1] = typeParams; + if (instance) fillOuterTypeParams(rr, tnLen - 2, parent, p); + return new ParameterizedQualifiedTypeReference(tn, rr, 0, ps); + } + + /** + * This class will add type params to fully qualified chain of type references for inner types, such as {@code GrandParent.Parent.Child}; this is needed only as long as the chain does not involve static. + * + * @return {@code true} if at least one parameterization is actually added, {@code false} otherwise. + */ + private static boolean fillOuterTypeParams(TypeReference[][] rr, int idx, EclipseNode node, long p) { + if (idx < 0 || node == null || !(node.get() instanceof TypeDeclaration)) return false; + boolean filled = false; + TypeDeclaration td = (TypeDeclaration) node.get(); + TypeParameter[] tps = td.typeParameters; + if (tps != null && tps.length > 0) { + TypeReference[] trs = new TypeReference[tps.length]; + for (int i = 0; i < tps.length; i++) { + trs[i] = new SingleTypeReference(tps[i].name, p); + } + rr[idx] = trs; + filled = true; + } + if ((td.modifiers & ClassFileConstants.AccStatic) != 0) return filled; // Once we hit a static class, no further typeparams needed. + boolean f2 = fillOuterTypeParams(rr, idx - 1, node.up(), p); + return f2 || filled; + } + + public static NameReference generateNameReference(EclipseNode type, long p) { + char[][] tn = getQualifiedInnerName(type.up(), ((TypeDeclaration) type.get()).name); + if (tn.length == 1) return new SingleNameReference(tn[0], p); + int tnLen = tn.length; + long[] ps = new long[tnLen]; + for (int i = 0; i < tnLen; i++) ps[i] = p; + int ss = (int) (p >> 32); + int se = (int) p; + return new QualifiedNameReference(tn, ps, ss, se); + } + + public static NameReference generateNameReference(EclipseNode parent, char[] name, long p) { + char[][] tn = getQualifiedInnerName(parent, name); + if (tn.length == 1) return new SingleNameReference(tn[0], p); + int tnLen = tn.length; + long[] ps = new long[tnLen]; + for (int i = 0; i < tnLen; i++) ps[i] = p; + int ss = (int) (p >> 32); + int se = (int) p; + return new QualifiedNameReference(tn, ps, ss, se); + } + + public static TypeReference generateTypeReference(EclipseNode type, long p) { + TypeDeclaration td = (TypeDeclaration) type.get(); + char[][] tn = getQualifiedInnerName(type.up(), td.name); + if (tn.length == 1) return new SingleTypeReference(tn[0], p); + int tnLen = tn.length; + long[] ps = new long[tnLen]; + for (int i = 0; i < tnLen; i++) ps[i] = p; + + boolean instance = (td.modifiers & ClassFileConstants.AccStatic) == 0 && type.up() != null && type.up().get() instanceof TypeDeclaration; + if (instance) { + TypeReference[][] trs = new TypeReference[tn.length][]; + boolean filled = fillOuterTypeParams(trs, trs.length - 2, type.up(), p); + if (filled) return new ParameterizedQualifiedTypeReference(tn, trs, 0, ps); + } + + return new QualifiedTypeReference(tn, ps); + } + + public static TypeReference generateTypeReference(EclipseNode parent, char[] name, boolean instance, long p) { + char[][] tn = getQualifiedInnerName(parent, name); + if (tn.length == 1) return new SingleTypeReference(tn[0], p); + int tnLen = tn.length; + long[] ps = new long[tnLen]; + for (int i = 0; i < tnLen; i++) ps[i] = p; + + if (instance && parent != null && parent.get() instanceof TypeDeclaration) { + TypeReference[][] trs = new TypeReference[tn.length][]; + if (fillOuterTypeParams(trs, tn.length - 2, parent, p)) return new ParameterizedQualifiedTypeReference(tn, trs, 0, ps); + } + + return new QualifiedTypeReference(tn, ps); + } + + /** + * Generate a chain of names for the enclosing classes. + * + * Given for example {@code class Outer { class Inner {} }} this would generate {@code char[][] { "Outer", "Inner" }}. + * For method local and top level types, this generates a size-1 char[][] where the only char[] element is {@code name} itself. + */ + private static char[][] getQualifiedInnerName(EclipseNode parent, char[] name) { + int count = 0; + + EclipseNode n = parent; + while (n != null && n.getKind() == Kind.TYPE && n.get() instanceof TypeDeclaration) { + TypeDeclaration td = (TypeDeclaration) n.get(); + if (td.name == null || td.name.length == 0) break; + count++; + n = n.up(); + } + + if (count == 0) return new char[][] { name }; + char[][] res = new char[count + 1][]; + res[count] = name; + + n = parent; + while (n != null && n.getKind() == Kind.TYPE && n.get() instanceof TypeDeclaration) { + TypeDeclaration td = (TypeDeclaration) n.get(); + res[--count] = td.name; + n = n.up(); + } + + return res; + } + public static TypeReference makeType(TypeBinding binding, ASTNode pos, boolean allowCompound) { if (binding.getClass() == EclipseReflectiveMembers.INTERSECTION_BINDING) { Object[] arr = (Object[]) EclipseReflectiveMembers.reflect(EclipseReflectiveMembers.INTERSECTION_BINDING_TYPES, binding); diff --git a/src/core/lombok/eclipse/handlers/HandleBuilder.java b/src/core/lombok/eclipse/handlers/HandleBuilder.java index 70978e23..6cc5bd57 100755 --- a/src/core/lombok/eclipse/handlers/HandleBuilder.java +++ b/src/core/lombok/eclipse/handlers/HandleBuilder.java @@ -55,6 +55,7 @@ import org.eclipse.jdt.internal.compiler.ast.NullLiteral; import org.eclipse.jdt.internal.compiler.ast.OperatorIds; import org.eclipse.jdt.internal.compiler.ast.ParameterizedQualifiedTypeReference; import org.eclipse.jdt.internal.compiler.ast.ParameterizedSingleTypeReference; +import org.eclipse.jdt.internal.compiler.ast.QualifiedAllocationExpression; import org.eclipse.jdt.internal.compiler.ast.QualifiedThisReference; import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference; import org.eclipse.jdt.internal.compiler.ast.ReturnStatement; @@ -274,7 +275,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { handleConstructor.generateConstructor(tdParent, AccessLevel.PACKAGE, allFields, false, null, SkipIfConstructorExists.I_AM_BUILDER, Collections.<Annotation>emptyList(), annotationNode); - returnType = namePlusTypeParamsToTypeReference(td.name, td.typeParameters, p); + returnType = namePlusTypeParamsToTypeReference(tdParent, td.typeParameters, p); typeParams = td.typeParameters; thrownExceptions = null; nameOfStaticBuilderMethod = null; @@ -289,7 +290,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { tdParent = parent.up(); TypeDeclaration td = (TypeDeclaration) tdParent.get(); - returnType = namePlusTypeParamsToTypeReference(td.name, td.typeParameters, p); + returnType = namePlusTypeParamsToTypeReference(tdParent, td.typeParameters, p); typeParams = td.typeParameters; thrownExceptions = cd.thrownExceptions; nameOfStaticBuilderMethod = null; @@ -539,7 +540,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { tps[i].name = typeArgsForToBuilder.get(i); } } - MethodDeclaration md = generateToBuilderMethod(cfv, toBuilderMethodName, builderClassName, tdParent, tps, builderFields, fluent, ast, accessForOuters, builderInstance.setterPrefix()); + MethodDeclaration md = generateToBuilderMethod(cfv, isStatic, toBuilderMethodName, builderClassName, tdParent, tps, builderFields, fluent, ast, accessForOuters, builderInstance.setterPrefix()); if (md != null) injectMethod(tdParent, md); } @@ -552,7 +553,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { } private static final char[] BUILDER_TEMP_VAR = {'b', 'u', 'i', 'l', 'd', 'e', 'r'}; - private MethodDeclaration generateToBuilderMethod(CheckerFrameworkVersion cfv, String methodName, String builderClassName, EclipseNode type, TypeParameter[] typeParams, List<BuilderFieldData> builderFields, boolean fluent, ASTNode source, AccessLevel access, String prefix) { + private MethodDeclaration generateToBuilderMethod(CheckerFrameworkVersion cfv, boolean isStatic, String methodName, String builderClassName, EclipseNode type, TypeParameter[] typeParams, List<BuilderFieldData> builderFields, boolean fluent, ASTNode source, AccessLevel access, String prefix) { int pS = source.sourceStart, pE = source.sourceEnd; long p = (long) pS << 32 | pE; @@ -560,9 +561,9 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { out.selector = methodName.toCharArray(); out.modifiers = toEclipseModifier(access); out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG; - out.returnType = namePlusTypeParamsToTypeReference(builderClassName.toCharArray(), typeParams, p); + out.returnType = namePlusTypeParamsToTypeReference(type, builderClassName.toCharArray(), !isStatic, typeParams, p); AllocationExpression invoke = new AllocationExpression(); - invoke.type = namePlusTypeParamsToTypeReference(builderClassName.toCharArray(), typeParams, p); + invoke.type = namePlusTypeParamsToTypeReference(type, builderClassName.toCharArray(), !isStatic, typeParams, p); Expression receiver = invoke; List<Statement> statements = null; @@ -593,7 +594,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { obtainExpr.typeArguments[j] = new SingleTypeReference(typeParams[j].name, 0); } } - obtainExpr.receiver = new SingleNameReference(type.getName().toCharArray(), 0); + obtainExpr.receiver = generateNameReference(type, 0); } else { obtainExpr.receiver = new ThisReference(0, 0); } @@ -623,7 +624,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { LocalDeclaration b = new LocalDeclaration(BUILDER_TEMP_VAR, pS, pE); out.statements[0] = b; b.modifiers |= Modifier.FINAL; - b.type = namePlusTypeParamsToTypeReference(builderClassName.toCharArray(), typeParams, p); + b.type = namePlusTypeParamsToTypeReference(type, builderClassName.toCharArray(), !isStatic, typeParams, p); b.type.sourceStart = pS; b.type.sourceEnd = pE; b.initialization = receiver; out.statements[out.statements.length - 1] = new ReturnStatement(new SingleNameReference(BUILDER_TEMP_VAR, p), pS, pE); @@ -684,7 +685,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { } ann.memberValue = arr; } - Argument arg = new Argument(new char[] { 't', 'h', 'i', 's' }, 0, new SingleTypeReference(type.getName().toCharArray(), source.sourceStart), Modifier.FINAL); + Argument arg = new Argument(new char[] { 't', 'h', 'i', 's' }, 0, generateTypeReference(type, source.sourceStart), Modifier.FINAL); arg.annotations = new Annotation[] {ann}; return new Argument[] {arg}; } @@ -751,7 +752,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { if (isStatic) { invoke.receiver = new SingleNameReference(type.up().getName().toCharArray(), 0); } else { - invoke.receiver = new QualifiedThisReference(new SingleTypeReference(type.up().getName().toCharArray(), 0) , 0, 0); + invoke.receiver = new QualifiedThisReference(generateTypeReference(type.up(), 0) , 0, 0); } invoke.typeArguments = typeParameterNames(((TypeDeclaration) type.get()).typeParameters); @@ -801,17 +802,31 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { public MethodDeclaration generateBuilderMethod(CheckerFrameworkVersion cfv, boolean isStatic, String builderMethodName, String builderClassName, EclipseNode type, TypeParameter[] typeParams, ASTNode source, AccessLevel access) { int pS = source.sourceStart, pE = source.sourceEnd; long p = (long) pS << 32 | pE; + char[] builderClassName_ = builderClassName.toCharArray(); MethodDeclaration out = new MethodDeclaration(((CompilationUnitDeclaration) type.top().get()).compilationResult); out.selector = builderMethodName.toCharArray(); out.modifiers = toEclipseModifier(access); if (isStatic) out.modifiers |= ClassFileConstants.AccStatic; out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG; - out.returnType = namePlusTypeParamsToTypeReference(builderClassName.toCharArray(), typeParams, p); + out.returnType = namePlusTypeParamsToTypeReference(type, builderClassName_, !isStatic, typeParams, p); out.typeParameters = copyTypeParams(typeParams, source); AllocationExpression invoke = new AllocationExpression(); - invoke.type = namePlusTypeParamsToTypeReference(builderClassName.toCharArray(), typeParams, p); - out.statements = new Statement[] {new ReturnStatement(invoke, pS, pE)}; + if (isStatic) { + invoke.type = namePlusTypeParamsToTypeReference(type, builderClassName_, false, typeParams, p); + out.statements = new Statement[] {new ReturnStatement(invoke, pS, pE)}; + } else { + // return this.new Builder(); + QualifiedAllocationExpression qualifiedInvoke = new QualifiedAllocationExpression(); + qualifiedInvoke.enclosingInstance = new ThisReference(pS, pE); + if (typeParams == null || typeParams.length == 0) { + qualifiedInvoke.type = new SingleTypeReference(builderClassName_, p); + } else { + qualifiedInvoke.type = namePlusTypeParamsToTypeReference(null, builderClassName_, false, typeParams, p); + } + + out.statements = new Statement[] {new ReturnStatement(qualifiedInvoke, pS, pE)}; + } Annotation uniqueAnn = cfv.generateUnique() ? generateNamedAnnotation(source, CheckerFrameworkVersion.NAME__UNIQUE) : null; Annotation sefAnn = cfv.generateSideEffectFree() ? generateNamedAnnotation(source, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE) : null; if (uniqueAnn != null && sefAnn != null) { @@ -904,7 +919,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { Argument[] arr = setter.arguments == null ? new Argument[0] : setter.arguments; Argument[] newArr = new Argument[arr.length + 1]; System.arraycopy(arr, 0, newArr, 1, arr.length); - newArr[0] = new Argument(new char[] { 't', 'h', 'i', 's' }, 0, new SingleTypeReference(builderType.getName().toCharArray(), 0), Modifier.FINAL); + newArr[0] = new Argument(new char[] { 't', 'h', 'i', 's' }, 0, generateTypeReference(builderType, 0), Modifier.FINAL); char[][] nameNotCalled = fromQualifiedName(CheckerFrameworkVersion.NAME__NOT_CALLED); SingleMemberAnnotation ann = new SingleMemberAnnotation(new QualifiedTypeReference(nameNotCalled, poss( source, nameNotCalled.length)), source.sourceStart); diff --git a/src/core/lombok/eclipse/handlers/HandleConstructor.java b/src/core/lombok/eclipse/handlers/HandleConstructor.java index 8f981c1a..7cb2036b 100755 --- a/src/core/lombok/eclipse/handlers/HandleConstructor.java +++ b/src/core/lombok/eclipse/handlers/HandleConstructor.java @@ -530,7 +530,7 @@ public class HandleConstructor { constructor.modifiers = toEclipseModifier(level) | ClassFileConstants.AccStatic; TypeDeclaration typeDecl = (TypeDeclaration) type.get(); - constructor.returnType = EclipseHandlerUtil.namePlusTypeParamsToTypeReference(typeDecl.name, typeDecl.typeParameters, p); + constructor.returnType = EclipseHandlerUtil.namePlusTypeParamsToTypeReference(type, typeDecl.typeParameters, p); constructor.annotations = null; constructor.selector = name.toCharArray(); constructor.thrownExceptions = null; diff --git a/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java b/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java index 8f0ef338..fbd4ce24 100755 --- a/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java +++ b/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java @@ -217,7 +217,7 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> { String builderImplClassName = builderClassName + "Impl"; typeParams = td.typeParameters != null ? td.typeParameters : new TypeParameter[0]; - returnType = namePlusTypeParamsToTypeReference(td.name, typeParams, p); + returnType = namePlusTypeParamsToTypeReference(tdParent, typeParams, p); // <C, B> are the generics for our builder. String classGenericName = "C"; @@ -438,7 +438,7 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> { o = new TypeParameter(); o.name = builderGenericName.toCharArray(); TypeReference[] typerefs = appendBuilderTypeReferences(typeParams, classGenericName, builderGenericName); - o.type = new ParameterizedSingleTypeReference(builderClass.toCharArray(), typerefs, 0, 0); + o.type = generateParameterizedTypeReference(tdParent, builderClass.toCharArray(), false, typerefs, 0); builder.typeParameters[builder.typeParameters.length - 1] = o; builder.superclass = copyType(superclassBuilderClass, source); @@ -469,8 +469,8 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> { // 2. The return type for the build() method (named "C" in the abstract builder), which is the annotated class. // 3. The return type for all setter methods (named "B" in the abstract builder), which is this builder class. typeArgs[typeArgs.length - 2] = cloneSelfType(tdParent, source); - typeArgs[typeArgs.length - 1] = createTypeReferenceWithTypeParameters(builderImplClass, typeParams); - builder.superclass = new ParameterizedSingleTypeReference(builderAbstractClass.toCharArray(), typeArgs, 0, 0); + typeArgs[typeArgs.length - 1] = createTypeReferenceWithTypeParameters(tdParent, builderImplClass, typeParams); + builder.superclass = generateParameterizedTypeReference(tdParent, builderAbstractClass.toCharArray(), false, typeArgs, 0); } builder.createDefaultConstructor(false, true); @@ -523,7 +523,7 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> { constructor.bodyEnd = constructor.declarationSourceEnd = constructor.sourceEnd = source.sourceEnd; TypeReference[] wildcards = new TypeReference[] {new Wildcard(Wildcard.UNBOUND), new Wildcard(Wildcard.UNBOUND)}; - TypeReference builderType = new ParameterizedSingleTypeReference(builderClassName.toCharArray(), mergeToTypeReferences(typeParams, wildcards), 0, p); + TypeReference builderType = generateParameterizedTypeReference(typeNode, builderClassName.toCharArray(), false, mergeToTypeReferences(typeParams, wildcards), p); constructor.arguments = new Argument[] {new Argument(BUILDER_VARIABLE_NAME, p, builderType, Modifier.FINAL)}; List<Statement> statements = new ArrayList<Statement>(); @@ -554,7 +554,7 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> { MessageSend defaultMethodCall = new MessageSend(); defaultMethodCall.sourceStart = source.sourceStart; defaultMethodCall.sourceEnd = source.sourceEnd; - defaultMethodCall.receiver = new SingleNameReference(((TypeDeclaration) typeNode.get()).name, 0L); + defaultMethodCall.receiver = generateNameReference(typeNode, 0L); defaultMethodCall.selector = fieldNode.nameOfDefaultProvider; defaultMethodCall.typeArguments = typeParameterNames(((TypeDeclaration) typeNode.get()).typeParameters); @@ -591,10 +591,10 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> { if (typeParams != null && typeParams.length > 0) out.typeParameters = copyTypeParams(typeParams, source); TypeReference[] wildcards = new TypeReference[] {new Wildcard(Wildcard.UNBOUND), new Wildcard(Wildcard.UNBOUND) }; - out.returnType = new ParameterizedSingleTypeReference(builderClassName.toCharArray(), mergeToTypeReferences(typeParams, wildcards), 0, p); + out.returnType = generateParameterizedTypeReference(type, builderClassName.toCharArray(), false, mergeToTypeReferences(typeParams, wildcards), p); AllocationExpression invoke = new AllocationExpression(); - invoke.type = namePlusTypeParamsToTypeReference(builderImplClassName.toCharArray(), typeParams, p); + invoke.type = namePlusTypeParamsToTypeReference(type, builderImplClassName.toCharArray(), false, typeParams, p); out.statements = new Statement[] {new ReturnStatement(invoke, pS, pE)}; if (cfv.generateUnique()) out.annotations = new Annotation[] {generateNamedAnnotation(source, CheckerFrameworkVersion.NAME__UNIQUE)}; @@ -606,8 +606,8 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> { /** * Generates a <code>toBuilder()</code> method in the annotated class that looks like this: * <pre> - * public ParentBuilder<?, ?> toBuilder() { - * return new <i>Foobar</i>BuilderImpl().$fillValuesFrom(this); + * public <i>Foobar</i>.<i>Foobar</i>Builder<?, ?> toBuilder() { + * return new <i.Foobar</i>.<i>Foobar</i>BuilderImpl().$fillValuesFrom(this); * } * </pre> */ @@ -621,10 +621,10 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> { out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG; TypeReference[] wildcards = new TypeReference[] {new Wildcard(Wildcard.UNBOUND), new Wildcard(Wildcard.UNBOUND) }; - out.returnType = new ParameterizedSingleTypeReference(builderClassName.toCharArray(), mergeToTypeReferences(typeParams, wildcards), 0, p); + out.returnType = generateParameterizedTypeReference(type, builderClassName.toCharArray(), false, mergeToTypeReferences(typeParams, wildcards), p); AllocationExpression newClass = new AllocationExpression(); - newClass.type = namePlusTypeParamsToTypeReference(builderImplClassName.toCharArray(), typeParams, p); + newClass.type = namePlusTypeParamsToTypeReference(type, builderImplClassName.toCharArray(), false, typeParams, p); MessageSend invokeFillMethod = new MessageSend(); invokeFillMethod.receiver = newClass; invokeFillMethod.selector = FILL_VALUES_METHOD_NAME; @@ -643,7 +643,7 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> { * <pre> * protected B $fillValuesFrom(final C instance) { * super.$fillValuesFrom(instance); - * FoobarBuilderImpl.$fillValuesFromInstanceIntoBuilder(instance, this); + * Foobar.FoobarBuilderImpl.$fillValuesFromInstanceIntoBuilder(instance, this); * return self(); * } * </pre> @@ -672,7 +672,7 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> { // Call the builder implemention's helper method that actually fills the values from the instance. MessageSend callStaticFillValuesMethod = new MessageSend(); - callStaticFillValuesMethod.receiver = new SingleNameReference(builderClassName.toCharArray(), 0); + callStaticFillValuesMethod.receiver = generateNameReference(tdParent, builderClassName.toCharArray(), 0); callStaticFillValuesMethod.selector = FILL_VALUES_STATIC_METHOD_NAME; callStaticFillValuesMethod.arguments = new Expression[] {new SingleNameReference(INSTANCE_VARIABLE_NAME, 0), new ThisReference(0, 0)}; body.add(callStaticFillValuesMethod); @@ -707,16 +707,25 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> { out.returnType = TypeReference.baseTypeReference(TypeIds.T_void, 0); TypeReference[] wildcards = new TypeReference[] {new Wildcard(Wildcard.UNBOUND), new Wildcard(Wildcard.UNBOUND)}; - TypeReference builderType = new ParameterizedSingleTypeReference(builderClassName.toCharArray(), mergeToTypeReferences(typeParams, wildcards), 0, 0); + TypeReference builderType = generateParameterizedTypeReference(tdParent, builderClassName.toCharArray(), false, mergeToTypeReferences(typeParams, wildcards), 0); Argument builderArgument = new Argument(BUILDER_VARIABLE_NAME, 0, builderType, Modifier.FINAL); - TypeReference parentArgument = createTypeReferenceWithTypeParameters(tdParent.getName(), typeParams); + TypeReference[] typerefs = null; + if (typeParams.length > 0) { + typerefs = new TypeReference[typeParams.length]; + for (int i = 0; i < typeParams.length; i++) typerefs[i] = new SingleTypeReference(typeParams[i].name, 0); + } + + long p = source.sourceStart; + p = (p << 32) | source.sourceEnd; + + TypeReference parentArgument = typerefs == null ? generateTypeReference(tdParent, p) : generateParameterizedTypeReference(tdParent, typerefs, p); out.arguments = new Argument[] {new Argument(INSTANCE_VARIABLE_NAME, 0, parentArgument, Modifier.FINAL), builderArgument}; - + // Add type params if there are any. if (typeParams.length > 0) out.typeParameters = copyTypeParams(typeParams, source); - + List<Statement> body = new ArrayList<Statement>(); - + // Call the builder's setter methods to fill the values from the instance. for (BuilderFieldData bfd : builderFields) { MessageSend exec = createSetterCallWithInstanceValue(bfd, tdParent, source); @@ -727,7 +736,7 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> { return out; } - + private MessageSend createSetterCallWithInstanceValue(BuilderFieldData bfd, EclipseNode type, ASTNode source) { char[] setterName = bfd.name; MessageSend ms = new MessageSend(); @@ -745,7 +754,7 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> { boolean obtainIsStatic = bfd.obtainVia.isStatic(); for (int i = 0; i < tgt.length; i++) { MessageSend obtainExpr = new MessageSend(); - obtainExpr.receiver = obtainIsStatic ? new SingleNameReference(type.getName().toCharArray(), 0) : new SingleNameReference(INSTANCE_VARIABLE_NAME, 0); + obtainExpr.receiver = obtainIsStatic ? generateNameReference(type, 0) : new SingleNameReference(INSTANCE_VARIABLE_NAME, 0); obtainExpr.selector = obtainName.toCharArray(); if (obtainIsStatic) obtainExpr.arguments = new Expression[] {new SingleNameReference(INSTANCE_VARIABLE_NAME, 0)}; tgt[i] = obtainExpr; @@ -796,7 +805,7 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> { else if (rrAnn != null) out.annotations = new Annotation[] {overrideAnn, rrAnn}; else if (sefAnn != null) out.annotations = new Annotation[] {overrideAnn, sefAnn}; else out.annotations = new Annotation[] {overrideAnn}; - out.returnType = namePlusTypeParamsToTypeReference(builderImplType.getName().toCharArray(), typeParams, p); + out.returnType = namePlusTypeParamsToTypeReference(builderImplType, typeParams, p); out.statements = new Statement[] {new ReturnStatement(new ThisReference(0, 0), 0, 0)}; return out; } @@ -959,7 +968,7 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> { Argument[] arr = setter.arguments == null ? new Argument[0] : setter.arguments; Argument[] newArr = new Argument[arr.length + 1]; System.arraycopy(arr, 0, newArr, 1, arr.length); - newArr[0] = new Argument(new char[] { 't', 'h', 'i', 's' }, 0, new SingleTypeReference(builderType.getName().toCharArray(), 0), Modifier.FINAL); + newArr[0] = new Argument(new char[] { 't', 'h', 'i', 's' }, 0, generateTypeReference(builderType, 0), Modifier.FINAL); char[][] nameNotCalled = fromQualifiedName(CheckerFrameworkVersion.NAME__NOT_CALLED); SingleMemberAnnotation ann = new SingleMemberAnnotation(new QualifiedTypeReference(nameNotCalled, poss(source, nameNotCalled.length)), source.sourceStart); ann.memberValue = new StringLiteral(setterName.toCharArray(), 0, 0, 0); @@ -1067,15 +1076,15 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> { return typeArgs; } - private static SingleTypeReference createTypeReferenceWithTypeParameters(String referenceName, TypeParameter[] typeParams) { + private static TypeReference createTypeReferenceWithTypeParameters(EclipseNode parent, String referenceName, TypeParameter[] typeParams) { if (typeParams.length > 0) { TypeReference[] typerefs = new TypeReference[typeParams.length]; for (int i = 0; i < typeParams.length; i++) { typerefs[i] = new SingleTypeReference(typeParams[i].name, 0); } - return new ParameterizedSingleTypeReference(referenceName.toCharArray(), typerefs, 0, 0); + return generateParameterizedTypeReference(parent, referenceName.toCharArray(), false, typerefs, 0); } else { - return new SingleTypeReference(referenceName.toCharArray(), 0); + return generateTypeReference(parent, referenceName.toCharArray(), false, 0); } } |