diff options
Diffstat (limited to 'src/core/lombok')
7 files changed, 282 insertions, 120 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); } } diff --git a/src/core/lombok/javac/handlers/HandleBuilder.java b/src/core/lombok/javac/handlers/HandleBuilder.java index 349b1382..00741249 100644 --- a/src/core/lombok/javac/handlers/HandleBuilder.java +++ b/src/core/lombok/javac/handlers/HandleBuilder.java @@ -21,6 +21,12 @@ */ package lombok.javac.handlers; +import static lombok.core.handlers.HandlerUtil.*; +import static lombok.javac.Javac.*; +import static lombok.javac.JavacTreeMaker.TypeTag.typeTag; +import static lombok.javac.handlers.JavacHandlerUtil.*; +import static lombok.javac.handlers.JavacHandlerUtil.isFieldDeprecated; + import java.util.ArrayList; import javax.lang.model.element.Modifier; @@ -40,6 +46,7 @@ import com.sun.tools.javac.tree.JCTree.JCIf; import com.sun.tools.javac.tree.JCTree.JCLiteral; import com.sun.tools.javac.tree.JCTree.JCMethodDecl; import com.sun.tools.javac.tree.JCTree.JCModifiers; +import com.sun.tools.javac.tree.JCTree.JCNewClass; import com.sun.tools.javac.tree.JCTree.JCPrimitiveTypeTree; import com.sun.tools.javac.tree.JCTree.JCStatement; import com.sun.tools.javac.tree.JCTree.JCTypeApply; @@ -60,6 +67,7 @@ import lombok.core.AnnotationValues; import lombok.core.HandlerPriority; import lombok.core.configuration.CheckerFrameworkVersion; import lombok.core.handlers.HandlerUtil; +import lombok.core.handlers.HandlerUtil.FieldAccess; import lombok.core.handlers.InclusionExclusionUtils.Included; import lombok.experimental.NonFinal; import lombok.javac.Javac; @@ -67,12 +75,10 @@ import lombok.javac.JavacAnnotationHandler; import lombok.javac.JavacNode; import lombok.javac.JavacTreeMaker; import lombok.javac.handlers.HandleConstructor.SkipIfConstructorExists; +import lombok.javac.handlers.JavacHandlerUtil.CopyJavadoc; +import lombok.javac.handlers.JavacHandlerUtil.MemberExistsResult; import lombok.javac.handlers.JavacSingularsRecipes.JavacSingularizer; import lombok.javac.handlers.JavacSingularsRecipes.SingularData; -import static lombok.core.handlers.HandlerUtil.*; -import static lombok.javac.handlers.JavacHandlerUtil.*; -import static lombok.javac.Javac.*; -import static lombok.javac.JavacTreeMaker.TypeTag.*; @ProviderFor(JavacAnnotationHandler.class) @HandlerPriority(-1024) //-2^10; to ensure we've picked up @FieldDefault's changes (-2048) but @Value hasn't removed itself yet (-512), so that we can error on presence of it on the builder classes. @@ -216,7 +222,7 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { handleConstructor.generateConstructor(tdParent, AccessLevel.PACKAGE, List.<JCAnnotation>nil(), allFields.toList(), false, null, SkipIfConstructorExists.I_AM_BUILDER, annotationNode); - returnType = namePlusTypeParamsToTypeReference(tdParent.getTreeMaker(), td.name, td.typarams); + returnType = namePlusTypeParamsToTypeReference(tdParent.getTreeMaker(), tdParent, td.typarams); typeParams = td.typarams; thrownExceptions = List.nil(); nameOfBuilderMethod = null; @@ -231,7 +237,7 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { tdParent = parent.up(); JCClassDecl td = (JCClassDecl) tdParent.get(); - returnType = namePlusTypeParamsToTypeReference(tdParent.getTreeMaker(), td.name, td.typarams); + returnType = namePlusTypeParamsToTypeReference(tdParent.getTreeMaker(), tdParent, td.typarams); typeParams = td.typarams; thrownExceptions = jmd.thrown; nameOfBuilderMethod = null; @@ -487,7 +493,7 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { } tps = lb.toList(); } - JCMethodDecl md = generateToBuilderMethod(cfv, toBuilderMethodName, builderClassName, tdParent, tps, builderFields, fluent, ast, accessForOuters, builderInstance.setterPrefix()); + JCMethodDecl md = generateToBuilderMethod(cfv, toBuilderMethodName, builderClassName, tdParent, isStatic, tps, builderFields, fluent, ast, accessForOuters, builderInstance.setterPrefix()); if (md != null) { recursiveSetGeneratedBy(md, ast, annotationNode.getContext()); injectMethod(tdParent, md); @@ -536,7 +542,7 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { } private static final String BUILDER_TEMP_VAR = "builder"; - private JCMethodDecl generateToBuilderMethod(CheckerFrameworkVersion cfv, String toBuilderMethodName, String builderClassName, JavacNode type, List<JCTypeParameter> typeParams, java.util.List<BuilderFieldData> builderFields, boolean fluent, JCAnnotation ast, AccessLevel access, String prefix) { + 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) { // return new ThingieBuilder<A, B>().setA(this.a).setB(this.b); JavacTreeMaker maker = type.getTreeMaker(); @@ -545,7 +551,7 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { typeArgs.append(maker.Ident(typeParam.name)); } - JCExpression call = maker.NewClass(null, List.<JCExpression>nil(), namePlusTypeParamsToTypeReference(maker, type.toName(builderClassName), typeParams), List.<JCExpression>nil(), null); + JCExpression call = maker.NewClass(null, List.<JCExpression>nil(), namePlusTypeParamsToTypeReference(maker, type, type.toName(builderClassName), !isStatic, typeParams), List.<JCExpression>nil(), null); JCExpression invoke = call; ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>(); for (BuilderFieldData bfd : builderFields) { @@ -584,7 +590,7 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { } } if (!statements.isEmpty()) { - JCExpression tempVarType = namePlusTypeParamsToTypeReference(maker, type.toName(builderClassName), typeParams); + 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)))); } else { @@ -592,7 +598,7 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { } 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(); - return maker.MethodDef(maker.Modifiers(toJavacModifier(access), annsOnMethod), type.toName(toBuilderMethodName), namePlusTypeParamsToTypeReference(maker, type.toName(builderClassName), typeParams), List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null); + return 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); } private JCMethodDecl generateCleanMethod(java.util.List<BuilderFieldData> builderFields, JavacNode type, JCTree source) { @@ -610,18 +616,6 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { 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()); return method; - /* - * if (shouldReturnThis) { - methodType = cloneSelfType(field); - } - - if (methodType == null) { - //WARNING: Do not use field.getSymbolTable().voidType - that field has gone through non-backwards compatible API changes within javac1.6. - methodType = treeMaker.Type(Javac.createVoidType(treeMaker, CTC_VOID)); - shouldReturnThis = false; - } - - */ } static List<JCVariableDecl> generateBuildArgs(CheckerFrameworkVersion cfv, JavacNode type, java.util.List<BuilderFieldData> builderFields) { @@ -643,10 +637,10 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { } 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"), maker.Ident(builderTypeNode.name), null); + JCVariableDecl recv = maker.VarDef(maker.Modifiers(0L, List.<JCAnnotation>of(recvAnno)), type.toName("this"), namePlusTypeParamsToTypeReference(maker, type, builderTypeNode.typarams), null); return List.of(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(); @@ -725,7 +719,14 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { typeArgs.append(maker.Ident(typeParam.name)); } - JCExpression call = maker.NewClass(null, List.<JCExpression>nil(), namePlusTypeParamsToTypeReference(maker, type.toName(builderClassName), typeParams), List.<JCExpression>nil(), null); + JCExpression call; + if (isStatic) { + call = maker.NewClass(null, List.<JCExpression>nil(), namePlusTypeParamsToTypeReference(maker, type, type.toName(builderClassName), false, 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")); + + } JCStatement statement = maker.Return(call); JCBlock body = maker.Block(0, List.<JCStatement>of(statement)); @@ -738,7 +739,7 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { else if (annUnique != null) annsOnMethod = List.of(annUnique); else if (annSef != null) annsOnMethod = List.of(annSef); else annsOnMethod = List.nil(); - return maker.MethodDef(maker.Modifiers(modifiers, annsOnMethod), type.toName(builderMethodName), namePlusTypeParamsToTypeReference(maker, type.toName(builderClassName), typeParams), copyTypeParams(source, typeParams), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null); + return 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); } public void generateBuilderFields(JavacNode builderType, java.util.List<BuilderFieldData> builderFields, JCTree source) { @@ -785,7 +786,6 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { 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); } else { - // TODO prefixed version fieldNode.singularData.getSingularizer().generateMethods(cfv, fieldNode.singularData, deprecate, builderType, source.get(), fluent, chain, access); } } @@ -809,7 +809,8 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { 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(); - JCVariableDecl recv = maker.VarDef(maker.Modifiers(0L, List.<JCAnnotation>of(ncAnno)), builderType.toName("this"), maker.Ident(builderTypeNode.name), null); + 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()); diff --git a/src/core/lombok/javac/handlers/HandleSuperBuilder.java b/src/core/lombok/javac/handlers/HandleSuperBuilder.java index 83dc23d1..d37b3049 100644 --- a/src/core/lombok/javac/handlers/HandleSuperBuilder.java +++ b/src/core/lombok/javac/handlers/HandleSuperBuilder.java @@ -408,18 +408,15 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { allTypeParams.addAll(copyTypeParams(source, 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 = maker.Ident(tdParent.toName(tdParent.getName())); - if (typeParams.nonEmpty()) { - // Add type params of the annotated class. - annotatedClass = maker.TypeApply(annotatedClass, getTypeParamExpressions(typeParams, maker).toList()); - } + JCExpression annotatedClass = namePlusTypeParamsToTypeReference(maker, tdParent, typeParams); + 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(classGenericName))); typeParamsForBuilder.add(maker.Ident(tdParent.toName(builderGenericName))); - JCTypeApply typeApply = maker.TypeApply(maker.Ident(builderClassName), typeParamsForBuilder.toList()); + 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))); JCExpression extending = null; @@ -445,22 +442,16 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { JCModifiers mods = maker.Modifiers(Flags.STATIC | Flags.PRIVATE | Flags.FINAL); // Extend the abstract builder. - JCExpression extending = maker.Ident(tdParent.toName(builderAbstractClass)); + JCExpression extending = namePlusTypeParamsToTypeReference(maker, tdParent, tdParent.toName(builderAbstractClass), false, List.<JCTypeParameter>nil()); // Add any type params of the annotated class. ListBuffer<JCTypeParameter> allTypeParams = new ListBuffer<JCTypeParameter>(); allTypeParams.addAll(copyTypeParams(source, 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 = maker.Ident(tdParent.toName(tdParent.getName())); - if (typeParams.nonEmpty()) { - // Add type params of the annotated class. - annotatedClass = maker.TypeApply(annotatedClass, getTypeParamExpressions(typeParams, maker).toList()); - } + JCExpression annotatedClass = namePlusTypeParamsToTypeReference(maker, tdParent, typeParams); // 2. The return type for all setter methods (named "B" in the abstract builder), which is this builder class. - JCExpression builderImplClassExpression = maker.Ident(tdParent.toName(builderImplClass)); - if (typeParams.nonEmpty()) { - builderImplClassExpression = maker.TypeApply(builderImplClassExpression, getTypeParamExpressions(typeParams, maker).toList()); - } + JCExpression builderImplClassExpression = namePlusTypeParamsToTypeReference(maker, tdParent, tdParent.toName(builderImplClass), false, typeParams); + ListBuffer<JCExpression> typeParamsForBuilder = getTypeParamExpressions(typeParams, maker); typeParamsForBuilder.add(annotatedClass); typeParamsForBuilder.add(builderImplClassExpression); @@ -509,7 +500,8 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { if (bfd.nameOfSetFlag != null) { JCFieldAccess setField = maker.Select(maker.Ident(builderVariableName), bfd.nameOfSetFlag); fieldInThis = maker.Select(maker.Ident(typeNode.toName("this")), bfd.rawName); - JCAssign assignDefault = maker.Assign(fieldInThis, maker.Apply(typeParameterNames(maker, ((JCClassDecl) typeNode.get()).typarams), maker.Select(maker.Ident(((JCClassDecl) typeNode.get()).name), bfd.nameOfDefaultProvider), List.<JCExpression>nil())); + 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())); statements.append(maker.If(setField, assign, maker.Exec(assignDefault))); } else { statements.append(assign); @@ -535,7 +527,7 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { typeParamsForBuilderParameter.add(wildcard); wildcard = maker.Wildcard(maker.TypeBoundKind(BoundKind.UNBOUND), null); typeParamsForBuilderParameter.add(wildcard); - JCTypeApply paramType = maker.TypeApply(maker.Ident(builderClassname), typeParamsForBuilderParameter.toList()); + JCTypeApply paramType = maker.TypeApply(namePlusTypeParamsToTypeReference(maker, typeNode, builderClassname, false, List.<JCTypeParameter>nil()), typeParamsForBuilderParameter.toList()); JCVariableDecl param = maker.VarDef(maker.Modifiers(flags), builderVariableName, paramType, null); params.append(param); @@ -560,7 +552,7 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { ListBuffer<JCExpression> typeArgs = new ListBuffer<JCExpression>(); for (JCTypeParameter typeParam : typeParams) typeArgs.append(maker.Ident(typeParam.name)); - JCExpression call = maker.NewClass(null, List.<JCExpression>nil(), namePlusTypeParamsToTypeReference(maker, type.toName(builderImplClassName), typeParams), List.<JCExpression>nil(), null); + JCExpression call = maker.NewClass(null, List.<JCExpression>nil(), namePlusTypeParamsToTypeReference(maker, type, type.toName(builderImplClassName), false, typeParams), List.<JCExpression>nil(), null); JCStatement statement = maker.Return(call); JCBlock body = maker.Block(0, List.<JCStatement>of(statement)); @@ -574,7 +566,7 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { JCWildcard wildcard = maker.Wildcard(maker.TypeBoundKind(BoundKind.UNBOUND), null); typeParameterNames.add(wildcard); typeParameterNames.add(wildcard); - JCTypeApply returnType = maker.TypeApply(maker.Ident(type.toName(builderClassName)), typeParameterNames.toList()); + JCTypeApply returnType = maker.TypeApply(namePlusTypeParamsToTypeReference(maker, type, type.toName(builderClassName), 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(); return maker.MethodDef(maker.Modifiers(modifiers, annsOnMethod), type.toName(builderMethodName), returnType, copyTypeParams(source, typeParams), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null); @@ -594,7 +586,7 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { ListBuffer<JCExpression> typeArgs = new ListBuffer<JCExpression>(); for (JCTypeParameter typeParam : typeParams) typeArgs.append(maker.Ident(typeParam.name)); - JCExpression newClass = maker.NewClass(null, List.<JCExpression>nil(), namePlusTypeParamsToTypeReference(maker, type.toName(builderImplClassName), typeParams), List.<JCExpression>nil(), null); + 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); JCStatement statement = maker.Return(invokeFillMethod); @@ -609,7 +601,7 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { JCWildcard wildcard = maker.Wildcard(maker.TypeBoundKind(BoundKind.UNBOUND), null); typeParameterNames.add(wildcard); typeParameterNames.add(wildcard); - JCTypeApply returnType = maker.TypeApply(maker.Ident(type.toName(builderClassName)), typeParameterNames.toList()); + JCTypeApply returnType = maker.TypeApply(namePlusTypeParamsToTypeReference(maker, type, type.toName(builderClassName), 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(); return maker.MethodDef(maker.Modifiers(modifiers, annsOnMethod), type.toName(TO_BUILDER_METHOD_NAME), returnType, List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null); @@ -651,8 +643,9 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { } // 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()); JCMethodInvocation callStaticFillValuesMethod = maker.Apply(List.<JCExpression>nil(), - maker.Select(maker.Ident(type.toName(builderImplClassName)), type.toName(STATIC_FILL_VALUES_METHOD_NAME)), + 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")))); body.append(maker.Exec(callStaticFillValuesMethod)); @@ -692,7 +685,7 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { typeParamsForBuilderParameter.add(wildcard); wildcard = maker.Wildcard(maker.TypeBoundKind(BoundKind.UNBOUND), null); typeParamsForBuilderParameter.add(wildcard); - JCTypeApply builderType = maker.TypeApply(maker.Ident(type.toName(builderClassname)), typeParamsForBuilderParameter.toList()); + 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); ListBuffer<JCStatement> body = new ListBuffer<JCStatement>(); @@ -717,7 +710,8 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { } else { if (bfd.obtainVia.isStatic()) { for (int i = 0; i < tgt.length; i++) { - JCExpression c = maker.Select(maker.Ident(type.toName(type.getName())), type.toName(bfd.obtainVia.method())); + JCExpression typeRef = namePlusTypeParamsToTypeReference(maker, type, List.<JCTypeParameter>nil()); + JCExpression c = maker.Select(typeRef, type.toName(bfd.obtainVia.method())); tgt[i] = maker.Apply(List.<JCExpression>nil(), c, List.<JCExpression>of(maker.Ident(type.toName(INSTANCE_VARIABLE_NAME)))); } } else { @@ -772,7 +766,7 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { JCModifiers modifiers = maker.Modifiers(Flags.PROTECTED, annsOnMethod); Name name = builderImplType.toName(SELF_METHOD); - JCExpression returnType = namePlusTypeParamsToTypeReference(maker, builderImplType.toName(builderImplType.getName()), typeParams); + JCExpression returnType = namePlusTypeParamsToTypeReference(maker, builderImplType.up(), builderImplType.toName(builderImplType.getName()), false, typeParams); JCStatement statement = maker.Return(maker.Ident(builderImplType.toName("this"))); JCBlock body = maker.Block(0, List.<JCStatement>of(statement)); @@ -908,7 +902,8 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { 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(); - JCVariableDecl recv = maker.VarDef(maker.Modifiers(0L, List.<JCAnnotation>of(ncAnno)), builderType.toName("this"), maker.Ident(builderTypeNode.name), null); + 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)); } if (cfv.generateReturnsReceiver()) { diff --git a/src/core/lombok/javac/handlers/JavacHandlerUtil.java b/src/core/lombok/javac/handlers/JavacHandlerUtil.java index d12a980f..885d8ffb 100644 --- a/src/core/lombok/javac/handlers/JavacHandlerUtil.java +++ b/src/core/lombok/javac/handlers/JavacHandlerUtil.java @@ -622,20 +622,7 @@ public class JavacHandlerUtil { JavacNode typeNode = childOfType; JavacTreeMaker maker = childOfType.getTreeMaker(); while (typeNode != null && typeNode.getKind() != Kind.TYPE) typeNode = typeNode.up(); - if (typeNode != null && typeNode.get() instanceof JCClassDecl) { - JCClassDecl type = (JCClassDecl) typeNode.get(); - ListBuffer<JCExpression> typeArgs = new ListBuffer<JCExpression>(); - if (!type.typarams.isEmpty()) { - for (JCTypeParameter tp : type.typarams) { - typeArgs.append(maker.Ident(tp.name)); - } - return maker.TypeApply(maker.Ident(type.name), typeArgs.toList()); - } else { - return maker.Ident(type.name); - } - } else { - return null; - } + return JavacHandlerUtil.namePlusTypeParamsToTypeReference(maker, typeNode, ((JCClassDecl) typeNode.get()).typarams); } public static boolean isBoolean(JavacNode field) { @@ -1722,11 +1709,25 @@ public class JavacHandlerUtil { return JCAnnotatedTypeReflect.getUnderlyingType(from); } - public static JCExpression namePlusTypeParamsToTypeReference(JavacTreeMaker maker, Name typeName, List<JCTypeParameter> params) { - if (params.isEmpty()) { - return maker.Ident(typeName); + public static JCExpression namePlusTypeParamsToTypeReference(JavacTreeMaker maker, JavacNode type, List<JCTypeParameter> params) { + JCClassDecl td = (JCClassDecl) type.get(); + boolean instance = (td.mods.flags & Flags.STATIC) == 0; + return namePlusTypeParamsToTypeReference(maker, type.up(), td.name, instance, params); + } + + public static JCExpression namePlusTypeParamsToTypeReference(JavacTreeMaker maker, JavacNode parentType, Name typeName, boolean instance, List<JCTypeParameter> params) { + JCExpression r = null; + + if (parentType != null && parentType.getKind() == Kind.TYPE) { + JCClassDecl td = (JCClassDecl) parentType.get(); + boolean outerInstance = instance && ((td.mods.flags & Flags.STATIC) == 0); + List<JCTypeParameter> outerParams = instance ? td.typarams : List.<JCTypeParameter>nil(); + r = namePlusTypeParamsToTypeReference(maker, parentType.up(), td.name, outerInstance, outerParams); } - return maker.TypeApply(maker.Ident(typeName), typeParameterNames(maker, params)); + + r = r == null ? maker.Ident(typeName) : maker.Select(r, typeName); + if (!params.isEmpty()) r = maker.TypeApply(r, typeParameterNames(maker, params)); + return r; } public static List<JCExpression> typeParameterNames(JavacTreeMaker maker, List<JCTypeParameter> params) { |