From 889c935ec9f0e45bba1e88b0f256e1f29a734f39 Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Thu, 19 Dec 2019 21:26:35 +0100 Subject: [fixes #2268] make lombok generate qualified types in order to avoid name clashes. --- doc/changelog.markdown | 1 + .../eclipse/handlers/EclipseHandlerUtil.java | 151 ++++++++++++++++++++- .../lombok/eclipse/handlers/HandleBuilder.java | 43 ++++-- .../lombok/eclipse/handlers/HandleConstructor.java | 2 +- .../eclipse/handlers/HandleSuperBuilder.java | 61 +++++---- src/core/lombok/javac/handlers/HandleBuilder.java | 59 ++++---- .../lombok/javac/handlers/HandleSuperBuilder.java | 49 +++---- .../lombok/javac/handlers/JavacHandlerUtil.java | 37 ++--- .../resource/after-delombok/BuilderComplex.java | 12 +- .../resource/after-delombok/BuilderCustomName.java | 12 +- .../resource/after-delombok/BuilderDefaults.java | 10 +- .../after-delombok/BuilderDefaultsGenerics.java | 10 +- .../after-delombok/BuilderDefaultsWarnings.java | 18 +-- .../after-delombok/BuilderGenericMethod.java | 8 +- .../after-delombok/BuilderInstanceMethod.java | 12 +- .../resource/after-delombok/BuilderJavadoc.java | 8 +- .../resource/after-delombok/BuilderSimple.java | 8 +- .../BuilderSimpleWithSetterPrefix.java | 6 +- .../BuilderSingularAnnotatedTypes.java | 16 +-- ...lderSingularAnnotatedTypesWithSetterPrefix.java | 16 +-- .../BuilderSingularGuavaListsSets.java | 34 ++--- ...lderSingularGuavaListsSetsWithSetterPrefix.java | 140 ------------------- .../after-delombok/BuilderSingularGuavaMaps.java | 22 +-- .../BuilderSingularGuavaMapsWithSetterPrefix.java | 94 ------------- .../after-delombok/BuilderSingularLists.java | 22 +-- .../BuilderSingularListsWithSetterPrefix.java | 123 ----------------- .../after-delombok/BuilderSingularMaps.java | 28 ++-- .../BuilderSingularMapsWithSetterPrefix.java | 28 ++-- .../after-delombok/BuilderSingularNoAuto.java | 22 +-- .../BuilderSingularNoAutoWithSetterPrefix.java | 22 +-- .../BuilderSingularRedirectToGuava.java | 22 +-- ...derSingularRedirectToGuavaWithSetterPrefix.java | 93 ------------- .../after-delombok/BuilderSingularSets.java | 28 ++-- .../BuilderSingularSetsWithSetterPrefix.java | 28 ++-- .../BuilderSingularToBuilderWithNull.java | 14 +- ...rSingularToBuilderWithNullWithSetterPrefix.java | 14 +- .../BuilderSingularWildcardListsWithToBuilder.java | 20 +-- ...WildcardListsWithToBuilderWithSetterPrefix.java | 97 ------------- .../BuilderSingularWithPrefixes.java | 10 +- ...uilderSingularWithPrefixesWithSetterPrefix.java | 10 +- .../resource/after-delombok/BuilderTypeAnnos.java | 6 +- .../BuilderTypeAnnosWithSetterPrefix.java | 6 +- .../resource/after-delombok/BuilderValueData.java | 8 +- .../BuilderValueDataWithSetterPrefix.java | 8 +- .../after-delombok/BuilderWithAccessors.java | 12 +- .../BuilderWithAccessorsWithSetterPrefix.java | 60 -------- .../after-delombok/BuilderWithBadNames.java | 8 +- .../BuilderWithBadNamesWithSetterPrefix.java | 42 ------ .../after-delombok/BuilderWithDeprecated.java | 20 +-- .../BuilderWithDeprecatedWithSetterPrefix.java | 114 ---------------- .../BuilderWithExistingBuilderClass.java | 8 +- ...erWithExistingBuilderClassWithSetterPrefix.java | 8 +- .../after-delombok/BuilderWithNoBuilderMethod.java | 6 +- ...BuilderWithNoBuilderMethodWithSetterPrefix.java | 33 ----- .../after-delombok/BuilderWithNonNull.java | 6 +- .../BuilderWithNonNullWithSetterPrefix.java | 6 +- .../BuilderWithRecursiveGenerics.java | 12 +- ...ilderWithRecursiveGenericsWithSetterPrefix.java | 85 ------------ .../after-delombok/BuilderWithToBuilder.java | 34 ++--- .../BuilderWithToBuilderWithSetterPrefix.java | 146 -------------------- .../after-delombok/BuilderWithTolerate.java | 6 +- .../BuilderWithTolerateWithSetterPrefix.java | 40 ------ .../after-delombok/CheckerFrameworkBuilder.java | 18 +-- .../CheckerFrameworkSuperBuilder.java | 50 +++---- .../ConstructorsWithBuilderDefaults.java | 8 +- .../ConstructorsWithBuilderDefaults2.java | 10 +- .../after-delombok/JacksonJsonProperty.java | 6 +- .../after-delombok/SuperBuilderAbstract.java | 36 ++--- .../SuperBuilderAbstractToBuilder.java | 56 ++++---- .../resource/after-delombok/SuperBuilderBasic.java | 32 ++--- .../after-delombok/SuperBuilderBasicToBuilder.java | 50 +++---- .../after-delombok/SuperBuilderCustomized.java | 20 +-- .../SuperBuilderSingularAnnotatedTypes.java | 12 +- .../SuperBuilderWithCustomBuilderMethod.java | 28 ++-- .../after-delombok/SuperBuilderWithDefaults.java | 38 +++--- .../after-delombok/SuperBuilderWithGenerics.java | 32 ++--- .../after-delombok/SuperBuilderWithGenerics2.java | 32 ++--- .../after-delombok/SuperBuilderWithGenerics3.java | 32 ++--- .../SuperBuilderWithGenericsAndToBuilder.java | 48 +++---- .../after-delombok/SuperBuilderWithNonNull.java | 34 ++--- .../after-delombok/SuperBuilderWithPrefixes.java | 12 +- .../resource/after-ecj/BuilderComplex.java | 12 +- .../resource/after-ecj/BuilderCustomName.java | 12 +- .../resource/after-ecj/BuilderDefaults.java | 10 +- .../after-ecj/BuilderDefaultsGenerics.java | 10 +- .../after-ecj/BuilderDefaultsWarnings.java | 18 +-- .../resource/after-ecj/BuilderGenericMethod.java | 8 +- .../resource/after-ecj/BuilderInstanceMethod.java | 12 +- .../resource/after-ecj/BuilderJavadoc.java | 8 +- .../resource/after-ecj/BuilderSimple.java | 8 +- .../after-ecj/BuilderSimpleWithSetterPrefix.java | 6 +- .../after-ecj/BuilderSingularAnnotatedTypes.java | 16 +-- ...lderSingularAnnotatedTypesWithSetterPrefix.java | 16 +-- .../after-ecj/BuilderSingularGuavaListsSets.java | 34 ++--- ...lderSingularGuavaListsSetsWithSetterPrefix.java | 125 ----------------- .../after-ecj/BuilderSingularGuavaMaps.java | 22 +-- .../BuilderSingularGuavaMapsWithSetterPrefix.java | 83 ----------- .../resource/after-ecj/BuilderSingularLists.java | 22 +-- .../BuilderSingularListsWithSetterPrefix.java | 116 ---------------- .../resource/after-ecj/BuilderSingularMaps.java | 28 ++-- .../BuilderSingularMapsWithSetterPrefix.java | 28 ++-- .../resource/after-ecj/BuilderSingularNoAuto.java | 22 +-- .../BuilderSingularNoAutoWithSetterPrefix.java | 22 +-- .../after-ecj/BuilderSingularRedirectToGuava.java | 22 +-- ...derSingularRedirectToGuavaWithSetterPrefix.java | 83 ----------- .../resource/after-ecj/BuilderSingularSets.java | 28 ++-- .../BuilderSingularSetsWithSetterPrefix.java | 28 ++-- .../BuilderSingularToBuilderWithNull.java | 14 +- ...rSingularToBuilderWithNullWithSetterPrefix.java | 14 +- .../BuilderSingularWildcardListsWithToBuilder.java | 20 +-- ...WildcardListsWithToBuilderWithSetterPrefix.java | 92 ------------- .../after-ecj/BuilderSingularWithPrefixes.java | 10 +- ...uilderSingularWithPrefixesWithSetterPrefix.java | 10 +- .../resource/after-ecj/BuilderTypeAnnos.java | 6 +- .../BuilderTypeAnnosWithSetterPrefix.java | 6 +- .../resource/after-ecj/BuilderValueData.java | 8 +- .../BuilderValueDataWithSetterPrefix.java | 8 +- .../resource/after-ecj/BuilderWithAccessors.java | 12 +- .../BuilderWithAccessorsWithSetterPrefix.java | 47 ------- .../resource/after-ecj/BuilderWithBadNames.java | 8 +- .../BuilderWithBadNamesWithSetterPrefix.java | 33 ----- .../resource/after-ecj/BuilderWithDeprecated.java | 20 +-- .../BuilderWithDeprecatedWithSetterPrefix.java | 87 ------------ .../after-ecj/BuilderWithExistingBuilderClass.java | 8 +- ...erWithExistingBuilderClassWithSetterPrefix.java | 8 +- .../after-ecj/BuilderWithNoBuilderMethod.java | 6 +- ...BuilderWithNoBuilderMethodWithSetterPrefix.java | 27 ---- .../resource/after-ecj/BuilderWithNonNull.java | 6 +- .../BuilderWithNonNullWithSetterPrefix.java | 6 +- .../after-ecj/BuilderWithRecursiveGenerics.java | 12 +- ...ilderWithRecursiveGenericsWithSetterPrefix.java | 78 ----------- .../resource/after-ecj/BuilderWithToBuilder.java | 34 ++--- .../BuilderWithToBuilderWithSetterPrefix.java | 124 ----------------- .../resource/after-ecj/BuilderWithTolerate.java | 6 +- .../BuilderWithTolerateWithSetterPrefix.java | 34 ----- .../after-ecj/CheckerFrameworkBuilder.java | 18 +-- .../after-ecj/CheckerFrameworkSuperBuilder.java | 50 +++---- .../after-ecj/ConstructorsWithBuilderDefaults.java | 8 +- .../ConstructorsWithBuilderDefaults2.java | 10 +- .../resource/after-ecj/JacksonJsonProperty.java | 6 +- .../resource/after-ecj/SuperBuilderAbstract.java | 36 ++--- .../after-ecj/SuperBuilderAbstractToBuilder.java | 56 ++++---- .../resource/after-ecj/SuperBuilderBasic.java | 32 ++--- .../after-ecj/SuperBuilderBasicToBuilder.java | 50 +++---- .../resource/after-ecj/SuperBuilderCustomized.java | 20 +-- .../SuperBuilderSingularAnnotatedTypes.java | 12 +- .../SuperBuilderWithCustomBuilderMethod.java | 28 ++-- .../after-ecj/SuperBuilderWithDefaults.java | 38 +++--- .../after-ecj/SuperBuilderWithGenerics.java | 32 ++--- .../after-ecj/SuperBuilderWithGenerics2.java | 32 ++--- .../after-ecj/SuperBuilderWithGenerics3.java | 32 ++--- .../SuperBuilderWithGenericsAndToBuilder.java | 48 +++---- .../after-ecj/SuperBuilderWithNonNull.java | 34 ++--- .../after-ecj/SuperBuilderWithPrefixes.java | 12 +- ...lderSingularGuavaListsSetsWithSetterPrefix.java | 16 --- .../BuilderSingularGuavaMapsWithSetterPrefix.java | 12 -- .../BuilderSingularListsWithSetterPrefix.java | 11 -- ...derSingularRedirectToGuavaWithSetterPrefix.java | 13 -- ...WildcardListsWithToBuilderWithSetterPrefix.java | 10 -- .../BuilderWithAccessorsWithSetterPrefix.java | 7 - .../BuilderWithBadNamesWithSetterPrefix.java | 5 - .../BuilderWithDeprecatedWithSetterPrefix.java | 11 -- ...BuilderWithNoBuilderMethodWithSetterPrefix.java | 5 - ...ilderWithRecursiveGenericsWithSetterPrefix.java | 13 -- .../BuilderWithToBuilderWithSetterPrefix.java | 20 --- .../BuilderWithTolerateWithSetterPrefix.java | 18 --- 166 files changed, 1451 insertions(+), 3425 deletions(-) delete mode 100644 test/transform/resource/after-delombok/BuilderSingularGuavaListsSetsWithSetterPrefix.java delete mode 100644 test/transform/resource/after-delombok/BuilderSingularGuavaMapsWithSetterPrefix.java delete mode 100644 test/transform/resource/after-delombok/BuilderSingularListsWithSetterPrefix.java delete mode 100644 test/transform/resource/after-delombok/BuilderSingularRedirectToGuavaWithSetterPrefix.java delete mode 100644 test/transform/resource/after-delombok/BuilderSingularWildcardListsWithToBuilderWithSetterPrefix.java delete mode 100644 test/transform/resource/after-delombok/BuilderWithAccessorsWithSetterPrefix.java delete mode 100644 test/transform/resource/after-delombok/BuilderWithBadNamesWithSetterPrefix.java delete mode 100644 test/transform/resource/after-delombok/BuilderWithDeprecatedWithSetterPrefix.java delete mode 100644 test/transform/resource/after-delombok/BuilderWithNoBuilderMethodWithSetterPrefix.java delete mode 100644 test/transform/resource/after-delombok/BuilderWithRecursiveGenericsWithSetterPrefix.java delete mode 100644 test/transform/resource/after-delombok/BuilderWithToBuilderWithSetterPrefix.java delete mode 100644 test/transform/resource/after-delombok/BuilderWithTolerateWithSetterPrefix.java delete mode 100644 test/transform/resource/after-ecj/BuilderSingularGuavaListsSetsWithSetterPrefix.java delete mode 100644 test/transform/resource/after-ecj/BuilderSingularGuavaMapsWithSetterPrefix.java delete mode 100644 test/transform/resource/after-ecj/BuilderSingularListsWithSetterPrefix.java delete mode 100644 test/transform/resource/after-ecj/BuilderSingularRedirectToGuavaWithSetterPrefix.java delete mode 100644 test/transform/resource/after-ecj/BuilderSingularWildcardListsWithToBuilderWithSetterPrefix.java delete mode 100644 test/transform/resource/after-ecj/BuilderWithAccessorsWithSetterPrefix.java delete mode 100644 test/transform/resource/after-ecj/BuilderWithBadNamesWithSetterPrefix.java delete mode 100644 test/transform/resource/after-ecj/BuilderWithDeprecatedWithSetterPrefix.java delete mode 100644 test/transform/resource/after-ecj/BuilderWithNoBuilderMethodWithSetterPrefix.java delete mode 100644 test/transform/resource/after-ecj/BuilderWithRecursiveGenericsWithSetterPrefix.java delete mode 100644 test/transform/resource/after-ecj/BuilderWithToBuilderWithSetterPrefix.java delete mode 100644 test/transform/resource/after-ecj/BuilderWithTolerateWithSetterPrefix.java delete mode 100644 test/transform/resource/before/BuilderSingularGuavaListsSetsWithSetterPrefix.java delete mode 100644 test/transform/resource/before/BuilderSingularGuavaMapsWithSetterPrefix.java delete mode 100644 test/transform/resource/before/BuilderSingularListsWithSetterPrefix.java delete mode 100644 test/transform/resource/before/BuilderSingularRedirectToGuavaWithSetterPrefix.java delete mode 100644 test/transform/resource/before/BuilderSingularWildcardListsWithToBuilderWithSetterPrefix.java delete mode 100644 test/transform/resource/before/BuilderWithAccessorsWithSetterPrefix.java delete mode 100644 test/transform/resource/before/BuilderWithBadNamesWithSetterPrefix.java delete mode 100644 test/transform/resource/before/BuilderWithDeprecatedWithSetterPrefix.java delete mode 100644 test/transform/resource/before/BuilderWithNoBuilderMethodWithSetterPrefix.java delete mode 100644 test/transform/resource/before/BuilderWithRecursiveGenericsWithSetterPrefix.java delete mode 100644 test/transform/resource/before/BuilderWithToBuilderWithSetterPrefix.java delete mode 100644 test/transform/resource/before/BuilderWithTolerateWithSetterPrefix.java diff --git a/doc/changelog.markdown b/doc/changelog.markdown index 115ae609..13cceff8 100644 --- a/doc/changelog.markdown +++ b/doc/changelog.markdown @@ -5,6 +5,7 @@ Lombok Changelog * PLATFORM: Support for JDK13 (including `yield` in switch expressions, as well as delombok having a nicer style for arrow-style switch blocks, and text blocks). * FEATURE: You can now configure a builder's 'setter' prefixes via `@Builder(setterPrefix = "set")` for example. We discourage doing this, but if some library you use requires them, have at it. [Pull Request #2174](https://github.com/rzwitserloot/lombok/pull/2174], [Issue #1805](https://github.com/rzwitserloot/lombok/issues/1805). * BUGFIX: Referring to an inner class inside the generics on a class marked with `@SuperBuilder` would cause the error `wrong number of type arguments; required 3` [Issue #2262](https://github.com/rzwitserloot/lombok/issues/2262); fixed by github user [`@Lekanich`](https://github.com/rzwitserloot/lombok/issues/2262) - thank you! +* IMPROBABLE BREAKING CHANGE: Lombok now generates qualified types (so, `Outer.Inner` instead of just `Inner`) in most type signatures that it generates; this should avoid exotic scenarios where the types lombok puts in signatures end up referring to unintended other types, which can occur if your class implements an interface that itself defines a type with the same name as one defined in your source file. I told you it was exotic. Thanks to Hunter Anderson for doing some preliminary work on this change. [Issue #2268](https://github.com/rzwitserloot/lombok/issues/2268) ### v1.18.10 (September 10th, 2019) 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 { handleConstructor.generateConstructor(tdParent, AccessLevel.PACKAGE, allFields, false, null, SkipIfConstructorExists.I_AM_BUILDER, Collections.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 { 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 { 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 { } 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 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 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 { 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 statements = null; @@ -593,7 +594,7 @@ public class HandleBuilder extends EclipseAnnotationHandler { 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 { 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 { } 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 { 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 { 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 { 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 { String builderImplClassName = builderClassName + "Impl"; typeParams = td.typeParameters != null ? td.typeParameters : new TypeParameter[0]; - returnType = namePlusTypeParamsToTypeReference(td.name, typeParams, p); + returnType = namePlusTypeParamsToTypeReference(tdParent, typeParams, p); // are the generics for our builder. String classGenericName = "C"; @@ -438,7 +438,7 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler { 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 { // 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 { 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 statements = new ArrayList(); @@ -554,7 +554,7 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler { 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 { 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 { /** * Generates a toBuilder() method in the annotated class that looks like this: *
-	 * public ParentBuilder<?, ?> toBuilder() {
-	 *     return new FoobarBuilderImpl().$fillValuesFrom(this);
+	 * public Foobar.FoobarBuilder<?, ?> toBuilder() {
+	 *     return new .FoobarBuilderImpl().$fillValuesFrom(this);
 	 * }
 	 * 
*/ @@ -621,10 +621,10 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler { 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 { *
 	 * protected B $fillValuesFrom(final C instance) {
 	 *     super.$fillValuesFrom(instance);
-	 *     FoobarBuilderImpl.$fillValuesFromInstanceIntoBuilder(instance, this);
+	 *     Foobar.FoobarBuilderImpl.$fillValuesFromInstanceIntoBuilder(instance, this);
 	 *     return self();
 	 * }
 	 * 
@@ -672,7 +672,7 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler { // 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 { 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 body = new ArrayList(); - + // 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 { 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 { 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 { 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 { 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 { 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 { handleConstructor.generateConstructor(tdParent, AccessLevel.PACKAGE, List.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 { 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 { } 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 { } private static final String BUILDER_TEMP_VAR = "builder"; - private JCMethodDecl generateToBuilderMethod(CheckerFrameworkVersion cfv, String toBuilderMethodName, String builderClassName, JavacNode type, List typeParams, java.util.List builderFields, boolean fluent, JCAnnotation ast, AccessLevel access, String prefix) { + private JCMethodDecl generateToBuilderMethod(CheckerFrameworkVersion cfv, String toBuilderMethodName, String builderClassName, JavacNode type, boolean isStatic, List typeParams, java.util.List builderFields, boolean fluent, JCAnnotation ast, AccessLevel access, String prefix) { // return new ThingieBuilder().setA(this.a).setB(this.b); JavacTreeMaker maker = type.getTreeMaker(); @@ -545,7 +551,7 @@ public class HandleBuilder extends JavacAnnotationHandler { typeArgs.append(maker.Ident(typeParam.name)); } - JCExpression call = maker.NewClass(null, List.nil(), namePlusTypeParamsToTypeReference(maker, type.toName(builderClassName), typeParams), List.nil(), null); + JCExpression call = maker.NewClass(null, List.nil(), namePlusTypeParamsToTypeReference(maker, type, type.toName(builderClassName), !isStatic, typeParams), List.nil(), null); JCExpression invoke = call; ListBuffer statements = new ListBuffer(); for (BuilderFieldData bfd : builderFields) { @@ -584,7 +590,7 @@ public class HandleBuilder extends JavacAnnotationHandler { } } 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 { } JCBlock body = maker.Block(0, statements.toList()); List annsOnMethod = cfv.generateUnique() ? List.of(maker.Annotation(genTypeRef(type, CheckerFrameworkVersion.NAME__UNIQUE), List.nil())) : List.nil(); - return maker.MethodDef(maker.Modifiers(toJavacModifier(access), annsOnMethod), type.toName(toBuilderMethodName), namePlusTypeParamsToTypeReference(maker, type.toName(builderClassName), typeParams), List.nil(), List.nil(), List.nil(), body, null); + return maker.MethodDef(maker.Modifiers(toJavacModifier(access), annsOnMethod), type.toName(toBuilderMethodName), namePlusTypeParamsToTypeReference(maker, type, type.toName(builderClassName), !isStatic, typeParams), List.nil(), List.nil(), List.nil(), body, null); } private JCMethodDecl generateCleanMethod(java.util.List builderFields, JavacNode type, JCTree source) { @@ -610,18 +616,6 @@ public class HandleBuilder extends JavacAnnotationHandler { JCMethodDecl method = maker.MethodDef(maker.Modifiers(toJavacModifier(AccessLevel.PRIVATE)), type.toName("$lombokClean"), maker.Type(Javac.createVoidType(type.getSymbolTable(), CTC_VOID)), List.nil(), List.nil(), List.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 generateBuildArgs(CheckerFrameworkVersion cfv, JavacNode type, java.util.List builderFields) { @@ -643,10 +637,10 @@ public class HandleBuilder extends JavacAnnotationHandler { } 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.of(recvAnno)), type.toName("this"), maker.Ident(builderTypeNode.name), null); + JCVariableDecl recv = maker.VarDef(maker.Modifiers(0L, List.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 builderFields, JavacNode type, List thrownExceptions, JCTree source, boolean addCleaning, AccessLevel access) { JavacTreeMaker maker = type.getTreeMaker(); @@ -725,7 +719,14 @@ public class HandleBuilder extends JavacAnnotationHandler { typeArgs.append(maker.Ident(typeParam.name)); } - JCExpression call = maker.NewClass(null, List.nil(), namePlusTypeParamsToTypeReference(maker, type.toName(builderClassName), typeParams), List.nil(), null); + JCExpression call; + if (isStatic) { + call = maker.NewClass(null, List.nil(), namePlusTypeParamsToTypeReference(maker, type, type.toName(builderClassName), false, typeParams), List.nil(), null); + } else { + call = maker.NewClass(null, List.nil(), namePlusTypeParamsToTypeReference(maker, null, type.toName(builderClassName), false, typeParams), List.nil(), null); + ((JCNewClass) call).encl = maker.Ident(type.toName("this")); + + } JCStatement statement = maker.Return(call); JCBlock body = maker.Block(0, List.of(statement)); @@ -738,7 +739,7 @@ public class HandleBuilder extends JavacAnnotationHandler { 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.nil(), List.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.nil(), List.nil(), body, null); } public void generateBuilderFields(JavacNode builderType, java.util.List builderFields, JCTree source) { @@ -785,7 +786,6 @@ public class HandleBuilder extends JavacAnnotationHandler { 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 { if (cfv.generateCalledMethods()) { JCAnnotation ncAnno = maker.Annotation(genTypeRef(source, CheckerFrameworkVersion.NAME__NOT_CALLED), List.of(maker.Literal(newMethod.getName().toString()))); JCClassDecl builderTypeNode = (JCClassDecl) builderType.get(); - JCVariableDecl recv = maker.VarDef(maker.Modifiers(0L, List.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.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 { 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.of(annotatedClass))); // 2. The return type for all setter methods, named "B", which extends this builder class. Name builderClassName = tdParent.toName(builderClass); ListBuffer 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.nil()), typeParamsForBuilder.toList()); allTypeParams.add(maker.TypeParameter(tdParent.toName(builderGenericName), List.of(typeApply))); JCExpression extending = null; @@ -445,22 +442,16 @@ public class HandleSuperBuilder extends JavacAnnotationHandler { 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.nil()); // Add any type params of the annotated class. ListBuffer allTypeParams = new ListBuffer(); 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 typeParamsForBuilder = getTypeParamExpressions(typeParams, maker); typeParamsForBuilder.add(annotatedClass); typeParamsForBuilder.add(builderImplClassExpression); @@ -509,7 +500,8 @@ public class HandleSuperBuilder extends JavacAnnotationHandler { 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.nil())); + JCExpression parentTypeRef = namePlusTypeParamsToTypeReference(maker, typeNode, List.nil()); + JCAssign assignDefault = maker.Assign(fieldInThis, maker.Apply(typeParameterNames(maker, ((JCClassDecl) typeNode.get()).typarams), maker.Selec