diff options
7 files changed, 170 insertions, 23 deletions
diff --git a/doc/changelog.markdown b/doc/changelog.markdown index 2672bbc6..fd4af685 100644 --- a/doc/changelog.markdown +++ b/doc/changelog.markdown @@ -9,6 +9,7 @@ Lombok Changelog * DEVELOPMENT: Compiling lombok on JDK1.9 is now possible. * BUGFIX: The generated hashCode would break the contract if `callSuper=true,of={}`. [Issue #1505](https://github.com/rzwitserloot/lombok/issues/1505) * BUGFIX: `delombok` no longer prints the synthetic outer-class parameter. [Issue #1521](https://github.com/rzwitserloot/lombok/issues/1521) +* BUGFIX: @Builder.Default now also works when type parameters are present. [Issue #1527](https://github.com/rzwitserloot/lombok/issues/1527) * INSTALLER: By default, the lombok installer now inserts an absolute path in `eclipse.ini` and friends, instead of a relative path. If you want the old behavior, you can use `java -jar -Dlombok.installer.fullpath=false lombok.jar`. ### v1.16.18 (July 3rd, 2017) diff --git a/src/core/lombok/eclipse/handlers/HandleBuilder.java b/src/core/lombok/eclipse/handlers/HandleBuilder.java index 5f2e8fe3..12b8f6bc 100644 --- a/src/core/lombok/eclipse/handlers/HandleBuilder.java +++ b/src/core/lombok/eclipse/handlers/HandleBuilder.java @@ -218,7 +218,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { bfd.nameOfDefaultProvider = prefixWith(DEFAULT_PREFIX, bfd.name); bfd.nameOfSetFlag = prefixWith(bfd.name, SET_PREFIX); - MethodDeclaration md = generateDefaultProvider(bfd.nameOfDefaultProvider, fieldNode, ast); + MethodDeclaration md = generateDefaultProvider(bfd.nameOfDefaultProvider, td.typeParameters, fieldNode, ast); if (md != null) injectMethod(tdParent, md); } addObtainVia(bfd, fieldNode); @@ -580,6 +580,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { inv.sourceEnd = source.sourceEnd; inv.receiver = new SingleNameReference(((TypeDeclaration) tdParent.get()).name, 0L); inv.selector = bfd.nameOfDefaultProvider; + inv.typeArguments = typeParameterNames(((TypeDeclaration) type.get()).typeParameters); args.add(new ConditionalExpression( new SingleNameReference(bfd.nameOfSetFlag, 0L), @@ -614,14 +615,8 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { invoke.receiver = new SingleNameReference(type.up().getName().toCharArray(), 0); else invoke.receiver = new QualifiedThisReference(new SingleTypeReference(type.up().getName().toCharArray(), 0) , 0, 0); - TypeParameter[] tps = ((TypeDeclaration) type.get()).typeParameters; - if (tps != null) { - TypeReference[] trs = new TypeReference[tps.length]; - for (int i = 0; i < trs.length; i++) { - trs[i] = new SingleTypeReference(tps[i].name, 0); - } - invoke.typeArguments = trs; - } + + invoke.typeArguments = typeParameterNames(((TypeDeclaration) type.get()).typeParameters); invoke.arguments = args.isEmpty() ? null : args.toArray(new Expression[args.size()]); if (returnType instanceof SingleTypeReference && Arrays.equals(TypeConstants.VOID, ((SingleTypeReference) returnType).token)) { statements.add(invoke); @@ -634,10 +629,21 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { return out; } - public MethodDeclaration generateDefaultProvider(char[] methodName, EclipseNode fieldNode, ASTNode source) { + private TypeReference[] typeParameterNames(TypeParameter[] typeParameters) { + if (typeParameters == null) return null; + + TypeReference[] trs = new TypeReference[typeParameters.length]; + for (int i = 0; i < trs.length; i++) { + trs[i] = new SingleTypeReference(typeParameters[i].name, 0); + } + return trs; + } + + public MethodDeclaration generateDefaultProvider(char[] methodName, TypeParameter[] typeParameters, EclipseNode fieldNode, ASTNode source) { int pS = source.sourceStart, pE = source.sourceEnd; MethodDeclaration out = new MethodDeclaration(((CompilationUnitDeclaration) fieldNode.top().get()).compilationResult); + out.typeParameters = copyTypeParams(typeParameters, source); out.selector = methodName; out.modifiers = ClassFileConstants.AccPrivate | ClassFileConstants.AccStatic; out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG; diff --git a/src/core/lombok/javac/handlers/HandleBuilder.java b/src/core/lombok/javac/handlers/HandleBuilder.java index 157828a0..ea436422 100644 --- a/src/core/lombok/javac/handlers/HandleBuilder.java +++ b/src/core/lombok/javac/handlers/HandleBuilder.java @@ -171,7 +171,7 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { if (isDefault != null) { bfd.nameOfDefaultProvider = parent.toName("$default$" + bfd.name); bfd.nameOfSetFlag = parent.toName(bfd.name + "$set"); - JCMethodDecl md = generateDefaultProvider(bfd.nameOfDefaultProvider, fieldNode); + JCMethodDecl md = generateDefaultProvider(bfd.nameOfDefaultProvider, fieldNode, td.typarams); recursiveSetGeneratedBy(md, ast, annotationNode.getContext()); if (md != null) injectMethod(tdParent, md); } @@ -543,7 +543,7 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { for (BuilderFieldData bfd : builderFields) { if (bfd.nameOfSetFlag != null) { args.append(maker.Conditional(maker.Ident(bfd.nameOfSetFlag), maker.Ident(bfd.name), - maker.Apply(List.<JCExpression>nil(), maker.Select(maker.Ident(((JCClassDecl) tdParent.get()).name), bfd.nameOfDefaultProvider), List.<JCExpression>nil()))); + maker.Apply(typeParameterNames(maker, ((JCClassDecl) tdParent.get()).typarams), maker.Select(maker.Ident(((JCClassDecl) tdParent.get()).name), bfd.nameOfDefaultProvider), List.<JCExpression>nil()))); } else { args.append(maker.Ident(bfd.name)); } @@ -577,7 +577,7 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { return maker.MethodDef(maker.Modifiers(Flags.PUBLIC), type.toName(buildName), returnType, List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), thrownExceptions, body, null); } - public JCMethodDecl generateDefaultProvider(Name methodName, JavacNode fieldNode) { + public JCMethodDecl generateDefaultProvider(Name methodName, JavacNode fieldNode, List<JCTypeParameter> params) { JavacTreeMaker maker = fieldNode.getTreeMaker(); JCVariableDecl field = (JCVariableDecl) fieldNode.get(); @@ -586,7 +586,7 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { JCBlock body = maker.Block(0, List.<JCStatement>of(statement)); int modifiers = Flags.PRIVATE | Flags.STATIC; - return maker.MethodDef(maker.Modifiers(modifiers), methodName, cloneType(maker, field.vartype, field, fieldNode.getContext()), List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null); + return maker.MethodDef(maker.Modifiers(modifiers), methodName, cloneType(maker, field.vartype, field, fieldNode.getContext()), copyTypeParams(fieldNode, params), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null); } public JCMethodDecl generateBuilderMethod(boolean isStatic, String builderMethodName, String builderClassName, JavacNode source, JavacNode type, List<JCTypeParameter> typeParams) { diff --git a/src/core/lombok/javac/handlers/JavacHandlerUtil.java b/src/core/lombok/javac/handlers/JavacHandlerUtil.java index 23206b43..956ab446 100644 --- a/src/core/lombok/javac/handlers/JavacHandlerUtil.java +++ b/src/core/lombok/javac/handlers/JavacHandlerUtil.java @@ -1388,17 +1388,18 @@ public class JavacHandlerUtil { } public static JCExpression namePlusTypeParamsToTypeReference(JavacTreeMaker maker, Name typeName, List<JCTypeParameter> params) { + if (params.isEmpty()) { + return maker.Ident(typeName); + } + return maker.TypeApply(maker.Ident(typeName), typeParameterNames(maker, params)); + } + + public static List<JCExpression> typeParameterNames(JavacTreeMaker maker, List<JCTypeParameter> params) { ListBuffer<JCExpression> typeArgs = new ListBuffer<JCExpression>(); - - if (!params.isEmpty()) { - for (JCTypeParameter param : params) { - typeArgs.append(maker.Ident(param.name)); - } - - return maker.TypeApply(maker.Ident(typeName), typeArgs.toList()); + for (JCTypeParameter param : params) { + typeArgs.append(maker.Ident(param.name)); } - - return maker.Ident(typeName); + return typeArgs.toList(); } public static void sanityCheckForMethodGeneratingAnnotationsOnBuilderClass(JavacNode typeNode, JavacNode errorNode) { diff --git a/test/transform/resource/after-delombok/BuilderDefaultsGenerics.java b/test/transform/resource/after-delombok/BuilderDefaultsGenerics.java new file mode 100644 index 00000000..18dd375e --- /dev/null +++ b/test/transform/resource/after-delombok/BuilderDefaultsGenerics.java @@ -0,0 +1,73 @@ +import java.util.*; +public class BuilderDefaultsGenerics<N extends Number, T, R extends List<T>> { + private java.util.concurrent.Callable<N> callable; + private T tee; + private R arrr; + @java.lang.SuppressWarnings("all") + private static <N extends Number, T, R extends List<T>> java.util.concurrent.Callable<N> $default$callable() { + return null; + } + @java.lang.SuppressWarnings("all") + private static <N extends Number, T, R extends List<T>> T $default$tee() { + return null; + } + @java.lang.SuppressWarnings("all") + private static <N extends Number, T, R extends List<T>> R $default$arrr() { + return null; + } + @java.lang.SuppressWarnings("all") + BuilderDefaultsGenerics(final java.util.concurrent.Callable<N> callable, final T tee, final R arrr) { + this.callable = callable; + this.tee = tee; + this.arrr = arrr; + } + @java.lang.SuppressWarnings("all") + public static class BuilderDefaultsGenericsBuilder<N extends Number, T, R extends List<T>> { + @java.lang.SuppressWarnings("all") + private boolean callable$set; + @java.lang.SuppressWarnings("all") + private java.util.concurrent.Callable<N> callable; + @java.lang.SuppressWarnings("all") + private boolean tee$set; + @java.lang.SuppressWarnings("all") + private T tee; + @java.lang.SuppressWarnings("all") + private boolean arrr$set; + @java.lang.SuppressWarnings("all") + private R arrr; + @java.lang.SuppressWarnings("all") + BuilderDefaultsGenericsBuilder() { + } + @java.lang.SuppressWarnings("all") + public BuilderDefaultsGenericsBuilder<N, T, R> callable(final java.util.concurrent.Callable<N> callable) { + this.callable = callable; + callable$set = true; + return this; + } + @java.lang.SuppressWarnings("all") + public BuilderDefaultsGenericsBuilder<N, T, R> tee(final T tee) { + this.tee = tee; + tee$set = true; + return this; + } + @java.lang.SuppressWarnings("all") + public BuilderDefaultsGenericsBuilder<N, T, R> arrr(final R arrr) { + this.arrr = arrr; + arrr$set = true; + return this; + } + @java.lang.SuppressWarnings("all") + public BuilderDefaultsGenerics<N, T, R> build() { + return new BuilderDefaultsGenerics<N, T, R>(callable$set ? callable : BuilderDefaultsGenerics.<N, T, R>$default$callable(), tee$set ? tee : BuilderDefaultsGenerics.<N, T, R>$default$tee(), arrr$set ? arrr : BuilderDefaultsGenerics.<N, T, R>$default$arrr()); + } + @java.lang.Override + @java.lang.SuppressWarnings("all") + public java.lang.String toString() { + return "BuilderDefaultsGenerics.BuilderDefaultsGenericsBuilder(callable=" + this.callable + ", tee=" + this.tee + ", arrr=" + this.arrr + ")"; + } + } + @java.lang.SuppressWarnings("all") + public static <N extends Number, T, R extends List<T>> BuilderDefaultsGenericsBuilder<N, T, R> builder() { + return new BuilderDefaultsGenericsBuilder<N, T, R>(); + } +} diff --git a/test/transform/resource/after-ecj/BuilderDefaultsGenerics.java b/test/transform/resource/after-ecj/BuilderDefaultsGenerics.java new file mode 100644 index 00000000..a8f81afa --- /dev/null +++ b/test/transform/resource/after-ecj/BuilderDefaultsGenerics.java @@ -0,0 +1,57 @@ +import lombok.Builder; +import java.util.*; +public @Builder class BuilderDefaultsGenerics<N extends Number, T, R extends List<T>> { + public static @java.lang.SuppressWarnings("all") class BuilderDefaultsGenericsBuilder<N extends Number, T, R extends List<T>> { + private @java.lang.SuppressWarnings("all") java.util.concurrent.Callable<N> callable; + private @java.lang.SuppressWarnings("all") boolean callable$set; + private @java.lang.SuppressWarnings("all") T tee; + private @java.lang.SuppressWarnings("all") boolean tee$set; + private @java.lang.SuppressWarnings("all") R arrr; + private @java.lang.SuppressWarnings("all") boolean arrr$set; + @java.lang.SuppressWarnings("all") BuilderDefaultsGenericsBuilder() { + super(); + } + public @java.lang.SuppressWarnings("all") BuilderDefaultsGenericsBuilder<N, T, R> callable(final java.util.concurrent.Callable<N> callable) { + this.callable = callable; + callable$set = true; + return this; + } + public @java.lang.SuppressWarnings("all") BuilderDefaultsGenericsBuilder<N, T, R> tee(final T tee) { + this.tee = tee; + tee$set = true; + return this; + } + public @java.lang.SuppressWarnings("all") BuilderDefaultsGenericsBuilder<N, T, R> arrr(final R arrr) { + this.arrr = arrr; + arrr$set = true; + return this; + } + public @java.lang.SuppressWarnings("all") BuilderDefaultsGenerics<N, T, R> build() { + return new BuilderDefaultsGenerics<N, T, R>((callable$set ? callable : BuilderDefaultsGenerics.<N, T, R>$default$callable()), (tee$set ? tee : BuilderDefaultsGenerics.<N, T, R>$default$tee()), (arrr$set ? arrr : BuilderDefaultsGenerics.<N, T, R>$default$arrr())); + } + public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() { + return (((((("BuilderDefaultsGenerics.BuilderDefaultsGenericsBuilder(callable=" + this.callable) + ", tee=") + this.tee) + ", arrr=") + this.arrr) + ")"); + } + } + private @Builder.Default java.util.concurrent.Callable<N> callable; + private @Builder.Default T tee; + private @Builder.Default R arrr; + private static @java.lang.SuppressWarnings("all") <N extends Number, T, R extends List<T>>java.util.concurrent.Callable<N> $default$callable() { + return null; + } + private static @java.lang.SuppressWarnings("all") <N extends Number, T, R extends List<T>>T $default$tee() { + return null; + } + private static @java.lang.SuppressWarnings("all") <N extends Number, T, R extends List<T>>R $default$arrr() { + return null; + } + @java.lang.SuppressWarnings("all") BuilderDefaultsGenerics(final java.util.concurrent.Callable<N> callable, final T tee, final R arrr) { + super(); + this.callable = callable; + this.tee = tee; + this.arrr = arrr; + } + public static @java.lang.SuppressWarnings("all") <N extends Number, T, R extends List<T>>BuilderDefaultsGenericsBuilder<N, T, R> builder() { + return new BuilderDefaultsGenericsBuilder<N, T, R>(); + } +} diff --git a/test/transform/resource/before/BuilderDefaultsGenerics.java b/test/transform/resource/before/BuilderDefaultsGenerics.java new file mode 100644 index 00000000..fffc9739 --- /dev/null +++ b/test/transform/resource/before/BuilderDefaultsGenerics.java @@ -0,0 +1,9 @@ +import lombok.Builder; +import java.util.*; + +@Builder +public class BuilderDefaultsGenerics<N extends Number, T, R extends List<T>> { + @Builder.Default private java.util.concurrent.Callable<N> callable = null; + @Builder.Default private T tee = null; + @Builder.Default private R arrr = null; +} |