mirror of
https://github.com/tiennm99/lombok.git
synced 2026-10-13 22:16:11 +00:00
@SuperBuilder adapts @Builder.Default behavior from @Builder as #1347 is
fixed now (ecj)
This commit is contained in:
1 parent
f072827630
commit
479738da89
2 files changed
+60
-29
No files matched your search
@@ -48,6 +48,7 @@ import org.eclipse.jdt.internal.compiler.ast.FieldReference;
|
||||
import org.eclipse.jdt.internal.compiler.ast.IfStatement;
|
||||
import org.eclipse.jdt.internal.compiler.ast.MessageSend;
|
||||
import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
|
||||
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.QualifiedNameReference;
|
||||
@@ -60,6 +61,7 @@ import org.eclipse.jdt.internal.compiler.ast.ThisReference;
|
||||
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
|
||||
import org.eclipse.jdt.internal.compiler.ast.TypeParameter;
|
||||
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
|
||||
import org.eclipse.jdt.internal.compiler.ast.UnaryExpression;
|
||||
import org.eclipse.jdt.internal.compiler.ast.Wildcard;
|
||||
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
|
||||
import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
|
||||
@@ -95,6 +97,7 @@ import lombok.experimental.SuperBuilder;
|
||||
public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
|
||||
private static final char[] CLEAN_FIELD_NAME = "$lombokUnclean".toCharArray();
|
||||
private static final char[] CLEAN_METHOD_NAME = "$lombokClean".toCharArray();
|
||||
private static final char[] DEFAULT_PREFIX = "$default$".toCharArray();
|
||||
private static final char[] SET_PREFIX = "$set".toCharArray();
|
||||
private static final char[] SELF_METHOD_NAME = "self".toCharArray();
|
||||
|
||||
@@ -104,6 +107,7 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
|
||||
TypeReference type;
|
||||
char[] rawName;
|
||||
char[] name;
|
||||
char[] nameOfDefaultProvider;
|
||||
char[] nameOfSetFlag;
|
||||
SingularData singularData;
|
||||
ObtainVia obtainVia;
|
||||
@@ -177,16 +181,11 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
|
||||
}
|
||||
|
||||
if (isDefault != null) {
|
||||
bfd.nameOfDefaultProvider = prefixWith(DEFAULT_PREFIX, bfd.name);
|
||||
bfd.nameOfSetFlag = prefixWith(bfd.name, SET_PREFIX);
|
||||
// The @Builder annotation removes the initializing expression on the field and moves
|
||||
// it to a method called "$default$FIELDNAME". This method is then called upon building.
|
||||
// We do NOT do this, because this is unexpected and may lead to bugs when using other
|
||||
// constructors (see, e.g., issue #1347).
|
||||
// Instead, we keep the init expression and only set a new value in the builder-based
|
||||
// constructor if it was set in the builder. Drawback is that the init expression is
|
||||
// always executed, even if it was unnecessary because its value is overwritten by the
|
||||
// builder.
|
||||
// TODO: Once the issue is resolved in @Builder, we can adapt the solution here.
|
||||
|
||||
MethodDeclaration md = HandleBuilder.generateDefaultProvider(bfd.nameOfDefaultProvider, td.typeParameters, fieldNode, ast);
|
||||
if (md != null) injectMethod(tdParent, md);
|
||||
}
|
||||
addObtainVia(bfd, fieldNode);
|
||||
builderFields.add(bfd);
|
||||
@@ -461,10 +460,10 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
|
||||
|
||||
for (BuilderFieldData fieldNode : builderFields) {
|
||||
char[] fieldName = removePrefixFromField(fieldNode.originalFieldNode);
|
||||
FieldReference thisX = new FieldReference(fieldNode.rawName, p);
|
||||
FieldReference fieldInThis = new FieldReference(fieldNode.rawName, p);
|
||||
int s = (int) (p >> 32);
|
||||
int e = (int) p;
|
||||
thisX.receiver = new ThisReference(s, e);
|
||||
fieldInThis.receiver = new ThisReference(s, e);
|
||||
|
||||
Expression assignmentExpr;
|
||||
if (fieldNode.singularData != null && fieldNode.singularData.getSingularizer() != null) {
|
||||
@@ -475,17 +474,27 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
|
||||
long[] positions = new long[] {p, p};
|
||||
assignmentExpr = new QualifiedNameReference(variableInBuilder, positions, s, e);
|
||||
}
|
||||
Statement assignment = new Assignment(thisX, assignmentExpr, (int) p);
|
||||
|
||||
// In case of @Builder.Default, only set the value if it really was set in the builder.
|
||||
if (fieldNode.nameOfSetFlag != null) {
|
||||
char[][] variableInBuilder = new char[][] {"b".toCharArray(), fieldNode.nameOfSetFlag};
|
||||
long[] positions = new long[] {p, p};
|
||||
QualifiedNameReference builderRef = new QualifiedNameReference(variableInBuilder, positions, s, e);
|
||||
assignment = new IfStatement(builderRef, assignment, s, e);
|
||||
}
|
||||
Statement assignment = new Assignment(fieldInThis, assignmentExpr, (int) p);
|
||||
statements.add(assignment);
|
||||
|
||||
// In case of @Builder.Default, set the value to the default if it was NOT set in the builder.
|
||||
if (fieldNode.nameOfSetFlag != null) {
|
||||
char[][] setVariableInBuilder = new char[][] {"b".toCharArray(), fieldNode.nameOfSetFlag};
|
||||
long[] positions = new long[] {p, p};
|
||||
QualifiedNameReference setVariableInBuilderRef = new QualifiedNameReference(setVariableInBuilder, positions, s, e);
|
||||
|
||||
MessageSend inv = new MessageSend();
|
||||
inv.sourceStart = source.sourceStart;
|
||||
inv.sourceEnd = source.sourceEnd;
|
||||
inv.receiver = new SingleNameReference(((TypeDeclaration) typeNode.get()).name, 0L);
|
||||
inv.selector = fieldNode.nameOfDefaultProvider;
|
||||
inv.typeArguments = typeParameterNames(((TypeDeclaration) typeNode.get()).typeParameters);
|
||||
|
||||
assignment = new Assignment(fieldInThis, inv, (int) p);
|
||||
IfStatement ifBlockForDefault = new IfStatement(new UnaryExpression(setVariableInBuilderRef, OperatorIds.NOT), assignment, s, e);
|
||||
statements.add(ifBlockForDefault);
|
||||
}
|
||||
|
||||
Annotation[] nonNulls = findAnnotations((FieldDeclaration)fieldNode.originalFieldNode.get(), NON_NULL_PATTERN);
|
||||
if (nonNulls.length != 0) {
|
||||
Statement nullCheck = generateNullCheck((FieldDeclaration)fieldNode.originalFieldNode.get(), sourceNode);
|
||||
@@ -817,6 +826,16 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
|
||||
return result;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
private EclipseNode findInnerClass(EclipseNode parent, String name) {
|
||||
char[] c = name.toCharArray();
|
||||
for (EclipseNode child : parent.down()) {
|
||||
|
||||
@@ -36,14 +36,22 @@ public class SuperBuilderWithDefaults {
|
||||
return new Parent<N>(this);
|
||||
}
|
||||
}
|
||||
private @lombok.Builder.Default long millis = System.currentTimeMillis();
|
||||
private @lombok.Builder.Default N numberField = null;
|
||||
private @lombok.Builder.Default long millis;
|
||||
private @lombok.Builder.Default N numberField;
|
||||
private static @java.lang.SuppressWarnings("all") <N extends Number>long $default$millis() {
|
||||
return System.currentTimeMillis();
|
||||
}
|
||||
private static @java.lang.SuppressWarnings("all") <N extends Number>N $default$numberField() {
|
||||
return null;
|
||||
}
|
||||
protected @java.lang.SuppressWarnings("all") Parent(final ParentBuilder<N, ?, ?> b) {
|
||||
super();
|
||||
if (b.millis$set)
|
||||
this.millis = b.millis;
|
||||
if (b.numberField$set)
|
||||
this.numberField = b.numberField;
|
||||
this.millis = b.millis;
|
||||
if ((! b.millis$set))
|
||||
this.millis = Parent.<N>$default$millis();
|
||||
this.numberField = b.numberField;
|
||||
if ((! b.numberField$set))
|
||||
this.numberField = Parent.<N>$default$numberField();
|
||||
}
|
||||
public static @java.lang.SuppressWarnings("all") <N extends Number>ParentBuilder<N, ?, ?> builder() {
|
||||
return new ParentBuilderImpl<N>();
|
||||
@@ -78,11 +86,15 @@ public class SuperBuilderWithDefaults {
|
||||
return new Child(this);
|
||||
}
|
||||
}
|
||||
private @lombok.Builder.Default double doubleField = Math.PI;
|
||||
private @lombok.Builder.Default double doubleField;
|
||||
private static @java.lang.SuppressWarnings("all") double $default$doubleField() {
|
||||
return Math.PI;
|
||||
}
|
||||
protected @java.lang.SuppressWarnings("all") Child(final ChildBuilder<?, ?> b) {
|
||||
super(b);
|
||||
if (b.doubleField$set)
|
||||
this.doubleField = b.doubleField;
|
||||
this.doubleField = b.doubleField;
|
||||
if ((! b.doubleField$set))
|
||||
this.doubleField = Child.$default$doubleField();
|
||||
}
|
||||
public static @java.lang.SuppressWarnings("all") ChildBuilder<?, ?> builder() {
|
||||
return new ChildBuilderImpl();
|
||||
|
||||
Reference in new issue
Block a user