mirror of
https://github.com/tiennm99/lombok.git
synced 2026-09-10 04:19:56 +00:00
[SuperBuilder] allow constructor customization
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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> {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user