aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Rieke <it@janrieke.de>2020-05-01 23:56:17 +0200
committerRoel Spilker <r.spilker@gmail.com>2020-05-28 21:18:35 +0200
commit48b1f17f7ef0e0b3d90dee74ee1b490a02cacff2 (patch)
tree1e7d52d4a53b3e9e9b8ba73edc99421a03102d24
parentfaa70bd21d2872e8354574cc98c7aa82ab996bcd (diff)
downloadlombok-48b1f17f7ef0e0b3d90dee74ee1b490a02cacff2.tar.gz
lombok-48b1f17f7ef0e0b3d90dee74ee1b490a02cacff2.tar.bz2
lombok-48b1f17f7ef0e0b3d90dee74ee1b490a02cacff2.zip
[SuperBuilder] allow constructor customization
-rw-r--r--src/core/lombok/eclipse/handlers/HandleSuperBuilder.java28
-rw-r--r--src/core/lombok/javac/handlers/HandleSuperBuilder.java35
-rw-r--r--test/transform/resource/after-delombok/SuperBuilderCustomized.java15
-rw-r--r--test/transform/resource/after-ecj/SuperBuilderCustomized.java8
-rw-r--r--test/transform/resource/before/SuperBuilderCustomized.java10
5 files changed, 81 insertions, 15 deletions
diff --git a/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java b/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java
index a49c20a4..455d40ed 100644
--- a/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java
+++ b/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java
@@ -274,8 +274,10 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
// If there is no superclass, superclassBuilderClassExpression is still == null at this point.
// You can use it to check whether to inherit or not.
- generateBuilderBasedConstructor(cfv, tdParent, typeParams, builderFields, annotationNode, builderClassName,
- superclassBuilderClass != null);
+ if (!constructorExists(tdParent, builderClassName)) {
+ generateBuilderBasedConstructor(cfv, tdParent, typeParams, builderFields, annotationNode, builderClassName,
+ superclassBuilderClass != null);
+ }
// Create the abstract builder class, or reuse an existing one.
EclipseNode builderType = findInnerClass(tdParent, builderClassName);
@@ -1159,4 +1161,26 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
System.arraycopy(name, 0, out, prefix.length, name.length);
return out;
}
+
+ private boolean constructorExists(EclipseNode type, String builderClassName) {
+ if (type != null && type.get() instanceof TypeDeclaration) {
+ TypeDeclaration typeDecl = (TypeDeclaration)type.get();
+ if (typeDecl.methods != null) for (AbstractMethodDeclaration def : typeDecl.methods) {
+ if (def instanceof ConstructorDeclaration) {
+ if ((def.bits & ASTNode.IsDefaultConstructor) != 0) continue;
+ if (!def.isConstructor()) continue;
+ if (isTolerate(type, def)) continue;
+ if (def.arguments.length != 1) continue;
+
+ // Cannot use typeMatches() here, because the parameter could be fully-qualified, partially-qualified, or not qualified.
+ // A string-compare of the last part should work. If it's a false-positive, users could still @Tolerate it.
+ char[] typeName = def.arguments[0].type.getLastToken();
+ if (builderClassName.equals(String.valueOf(typeName)))
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
}
diff --git a/src/core/lombok/javac/handlers/HandleSuperBuilder.java b/src/core/lombok/javac/handlers/HandleSuperBuilder.java
index 2dc3247d..b7cd6f9a 100644
--- a/src/core/lombok/javac/handlers/HandleSuperBuilder.java
+++ b/src/core/lombok/javac/handlers/HandleSuperBuilder.java
@@ -354,8 +354,10 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
}
// Generate a constructor in the annotated class that takes a builder as argument.
- generateBuilderBasedConstructor(cfv, tdParent, typeParams, builderFields, annotationNode, builderClassName,
- superclassBuilderClassExpression != null);
+ if (!constructorExists(tdParent, builderClassName)) {
+ generateBuilderBasedConstructor(cfv, tdParent, typeParams, builderFields, annotationNode, builderClassName,
+ superclassBuilderClassExpression != null);
+ }
if (isAbstract) {
// Only non-abstract classes get the builder() and toBuilder() methods.
@@ -1070,4 +1072,33 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
}
return typeParameter;
}
+
+ /**
+ * Checks if there is a manual constructor in the given type with a single parameter (builder).
+ */
+ private boolean constructorExists(JavacNode type, String builderClassName) {
+ if (type != null && type.get() instanceof JCClassDecl) {
+ for (JCTree def : ((JCClassDecl)type.get()).defs) {
+ if (def instanceof JCMethodDecl) {
+ JCMethodDecl md = (JCMethodDecl) def;
+ String name = md.name.toString();
+ boolean matches = name.equals("<init>");
+ if (isTolerate(type, md))
+ continue;
+ if (matches && md.params != null && md.params.length() == 1) {
+ // Cannot use typeMatches() here, because the parameter could be fully-qualified, partially-qualified, or not qualified.
+ // A string-compare of the last part should work. If it's a false-positive, users could still @Tolerate it.
+ String typeName = md.params.get(0).getType().toString();
+ int lastIndexOfDot = typeName.lastIndexOf('.');
+ if (lastIndexOfDot >= 0) {
+ typeName = typeName.substring(lastIndexOfDot+1);
+ }
+ if ((builderClassName+"<?, ?>").equals(typeName))
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
}
diff --git a/test/transform/resource/after-delombok/SuperBuilderCustomized.java b/test/transform/resource/after-delombok/SuperBuilderCustomized.java
index bffa72fa..f66133c9 100644
--- a/test/transform/resource/after-delombok/SuperBuilderCustomized.java
+++ b/test/transform/resource/after-delombok/SuperBuilderCustomized.java
@@ -23,6 +23,13 @@ public class SuperBuilderCustomized {
}
}
int field1;
+ protected Parent(ParentBuilder<?, ?> b) {
+ if (b.field1 == 0) throw new IllegalArgumentException("field1 must be != 0");
+ this.field1 = b.field1;
+ }
+ public static SuperBuilderCustomized.Parent.ParentBuilder<?, ?> builder(int field1) {
+ return new SuperBuilderCustomized.Parent.ParentBuilderImpl().field1(field1);
+ }
@java.lang.SuppressWarnings("all")
private static final class ParentBuilderImpl extends SuperBuilderCustomized.Parent.ParentBuilder<SuperBuilderCustomized.Parent, SuperBuilderCustomized.Parent.ParentBuilderImpl> {
@java.lang.SuppressWarnings("all")
@@ -39,14 +46,6 @@ public class SuperBuilderCustomized {
return new SuperBuilderCustomized.Parent(this);
}
}
- @java.lang.SuppressWarnings("all")
- protected Parent(final SuperBuilderCustomized.Parent.ParentBuilder<?, ?> b) {
- this.field1 = b.field1;
- }
- @java.lang.SuppressWarnings("all")
- public static SuperBuilderCustomized.Parent.ParentBuilder<?, ?> builder() {
- return new SuperBuilderCustomized.Parent.ParentBuilderImpl();
- }
}
public static class Child extends Parent {
private static final class ChildBuilderImpl extends ChildBuilder<Child, ChildBuilderImpl> {
diff --git a/test/transform/resource/after-ecj/SuperBuilderCustomized.java b/test/transform/resource/after-ecj/SuperBuilderCustomized.java
index 32317f6a..fe0e1238 100644
--- a/test/transform/resource/after-ecj/SuperBuilderCustomized.java
+++ b/test/transform/resource/after-ecj/SuperBuilderCustomized.java
@@ -32,12 +32,14 @@ public class SuperBuilderCustomized {
}
}
int field1;
- protected @java.lang.SuppressWarnings("all") Parent(final SuperBuilderCustomized.Parent.ParentBuilder<?, ?> b) {
+ protected Parent(ParentBuilder<?, ?> b) {
super();
+ if ((b.field1 == 0))
+ throw new IllegalArgumentException("field1 must be != 0");
this.field1 = b.field1;
}
- public static @java.lang.SuppressWarnings("all") SuperBuilderCustomized.Parent.ParentBuilder<?, ?> builder() {
- return new SuperBuilderCustomized.Parent.ParentBuilderImpl();
+ public static SuperBuilderCustomized.Parent.ParentBuilder<?, ?> builder(int field1) {
+ return new SuperBuilderCustomized.Parent.ParentBuilderImpl().field1(field1);
}
}
public static @lombok.experimental.SuperBuilder class Child extends Parent {
diff --git a/test/transform/resource/before/SuperBuilderCustomized.java b/test/transform/resource/before/SuperBuilderCustomized.java
index 77830587..8e641d90 100644
--- a/test/transform/resource/before/SuperBuilderCustomized.java
+++ b/test/transform/resource/before/SuperBuilderCustomized.java
@@ -14,6 +14,16 @@ public class SuperBuilderCustomized {
}
}
int field1;
+
+ protected Parent(ParentBuilder<?, ?> b) {
+ if (b.field1 == 0)
+ throw new IllegalArgumentException("field1 must be != 0");
+ this.field1 = b.field1;
+ }
+
+ public static SuperBuilderCustomized.Parent.ParentBuilder<?, ?> builder(int field1) {
+ return new SuperBuilderCustomized.Parent.ParentBuilderImpl().field1(field1);
+ }
}
@lombok.experimental.SuperBuilder