mirror of
https://github.com/tiennm99/lombok.git
synced 2026-10-15 00:17:45 +00:00
moved code only relevant to builders to HandleBuilder (Eclipse)
reverted HandleConstructor to original state moved generation of builder-based constructor to HandleBuilder
This commit is contained in:
1 parent
549e1b9622
commit
cd2e2f2569
2 files changed
+124
-64
No files matched your search
@@ -25,6 +25,7 @@ import static lombok.eclipse.Eclipse.*;
|
||||
import static lombok.core.handlers.HandlerUtil.*;
|
||||
import static lombok.eclipse.handlers.EclipseHandlerUtil.*;
|
||||
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
@@ -39,6 +40,7 @@ import org.eclipse.jdt.internal.compiler.ast.Argument;
|
||||
import org.eclipse.jdt.internal.compiler.ast.Assignment;
|
||||
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
|
||||
import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
|
||||
import org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall;
|
||||
import org.eclipse.jdt.internal.compiler.ast.Expression;
|
||||
import org.eclipse.jdt.internal.compiler.ast.FalseLiteral;
|
||||
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
|
||||
@@ -49,6 +51,7 @@ 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;
|
||||
import org.eclipse.jdt.internal.compiler.ast.QualifiedThisReference;
|
||||
import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference;
|
||||
import org.eclipse.jdt.internal.compiler.ast.ReturnStatement;
|
||||
@@ -80,6 +83,7 @@ import lombok.core.HandlerPriority;
|
||||
import lombok.eclipse.Eclipse;
|
||||
import lombok.eclipse.EclipseAnnotationHandler;
|
||||
import lombok.eclipse.EclipseNode;
|
||||
import lombok.eclipse.handlers.EclipseHandlerUtil.MemberExistsResult;
|
||||
import lombok.eclipse.handlers.EclipseSingularsRecipes.EclipseSingularizer;
|
||||
import lombok.eclipse.handlers.EclipseSingularsRecipes.SingularData;
|
||||
import lombok.eclipse.handlers.HandleConstructor.SkipIfConstructorExists;
|
||||
@@ -99,6 +103,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
|
||||
}
|
||||
|
||||
private static class BuilderFieldData {
|
||||
EclipseNode fieldNode;
|
||||
TypeReference type;
|
||||
char[] rawName;
|
||||
char[] name;
|
||||
@@ -188,6 +193,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
|
||||
// Value will only skip making a field final if it has an explicit @NonFinal annotation, so we check for that.
|
||||
if (fd.initialization != null && valuePresent && !hasAnnotation(NonFinal.class, fieldNode)) continue;
|
||||
BuilderFieldData bfd = new BuilderFieldData();
|
||||
bfd.fieldNode = fieldNode;
|
||||
bfd.rawName = fieldNode.getName().toCharArray();
|
||||
bfd.name = removePrefixFromField(fieldNode);
|
||||
bfd.type = fd.type;
|
||||
@@ -205,8 +211,13 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
|
||||
}
|
||||
|
||||
boolean callBuilderBasedSuperConstructor = inherit && td.superclass != null;
|
||||
new HandleConstructor().generateConstructor(tdParent, extendable ? AccessLevel.PROTECTED : AccessLevel.PACKAGE, allFields, false, null, SkipIfConstructorExists.I_AM_BUILDER,
|
||||
Collections.<Annotation>emptyList(), annotationNode, extendable ? builderClassName : null, callBuilderBasedSuperConstructor);
|
||||
if (extendable) {
|
||||
generateConstructor(tdParent, builderFields, annotationNode,
|
||||
builderClassName, callBuilderBasedSuperConstructor);
|
||||
} else {
|
||||
new HandleConstructor().generateConstructor(tdParent, AccessLevel.PACKAGE, allFields, false, null, SkipIfConstructorExists.I_AM_BUILDER,
|
||||
Collections.<Annotation>emptyList(), annotationNode);
|
||||
}
|
||||
|
||||
returnType = namePlusTypeParamsToTypeReference(td.name, td.typeParameters, p);
|
||||
typeParams = td.typeParameters;
|
||||
@@ -427,7 +438,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
|
||||
if (constructorExists(builderType) == MemberExistsResult.NOT_EXISTS) {
|
||||
ConstructorDeclaration cd = HandleConstructor.createConstructor(
|
||||
AccessLevel.PACKAGE, builderType, Collections.<EclipseNode>emptyList(), false,
|
||||
annotationNode, Collections.<Annotation>emptyList(), null, false);
|
||||
annotationNode, Collections.<Annotation>emptyList());
|
||||
if (cd != null) injectMethod(builderType, cd);
|
||||
}
|
||||
|
||||
@@ -524,6 +535,105 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param builderClassnameAsParameter
|
||||
* if {@code != null}, the only parameter of the constructor will
|
||||
* be a builder with this classname; the constructor will then
|
||||
* use the values within this builder to assign the fields of new
|
||||
* instances.
|
||||
* @param callBuilderBasedSuperConstructor
|
||||
* if {@code true}, the constructor will explicitly call a super
|
||||
* constructor with the builder as argument. Requires
|
||||
* {@code builderClassAsParameter != null}.
|
||||
*/
|
||||
private void generateConstructor(EclipseNode typeNode, List<BuilderFieldData> builderFields, EclipseNode sourceNode,
|
||||
String builderClassnameAsParameter, boolean callBuilderBasedSuperConstructor) {
|
||||
|
||||
if (builderClassnameAsParameter == null || builderClassnameAsParameter.isEmpty()) {
|
||||
typeNode.addError("A builder-based constructor requires a non-empty 'builderClassnameAsParameter' value.");
|
||||
}
|
||||
|
||||
AccessLevel level = AccessLevel.PROTECTED;
|
||||
ASTNode source = sourceNode.get();
|
||||
|
||||
TypeDeclaration typeDeclaration = ((TypeDeclaration) typeNode.get());
|
||||
long p = (long) source.sourceStart << 32 | source.sourceEnd;
|
||||
|
||||
boolean isEnum = (((TypeDeclaration) typeNode.get()).modifiers & ClassFileConstants.AccEnum) != 0;
|
||||
if (isEnum) {
|
||||
level = AccessLevel.PRIVATE;
|
||||
}
|
||||
|
||||
// boolean suppressConstructorProperties = Boolean.TRUE.equals(typeNode.getAst().readConfiguration(ConfigurationKeys.ANY_CONSTRUCTOR_SUPPRESS_CONSTRUCTOR_PROPERTIES));
|
||||
|
||||
ConstructorDeclaration constructor = new ConstructorDeclaration(((CompilationUnitDeclaration) typeNode.top().get()).compilationResult);
|
||||
|
||||
constructor.modifiers = toEclipseModifier(level);
|
||||
constructor.selector = typeDeclaration.name;
|
||||
if (callBuilderBasedSuperConstructor) {
|
||||
constructor.constructorCall = new ExplicitConstructorCall(ExplicitConstructorCall.Super);
|
||||
constructor.constructorCall.arguments = new Expression[] {new SingleNameReference("b".toCharArray(), p)};
|
||||
} else {
|
||||
constructor.constructorCall = new ExplicitConstructorCall(ExplicitConstructorCall.ImplicitSuper);
|
||||
}
|
||||
constructor.constructorCall.sourceStart = source.sourceStart;
|
||||
constructor.constructorCall.sourceEnd = source.sourceEnd;
|
||||
constructor.thrownExceptions = null;
|
||||
constructor.typeParameters = null;
|
||||
constructor.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
|
||||
constructor.bodyStart = constructor.declarationSourceStart = constructor.sourceStart = source.sourceStart;
|
||||
constructor.bodyEnd = constructor.declarationSourceEnd = constructor.sourceEnd = source.sourceEnd;
|
||||
constructor.arguments = null;
|
||||
|
||||
List<Statement> assigns = new ArrayList<Statement>();
|
||||
List<Statement> nullChecks = new ArrayList<Statement>();
|
||||
|
||||
for (BuilderFieldData fieldNode : builderFields) {
|
||||
char[] fieldName = removePrefixFromField(fieldNode.fieldNode);
|
||||
FieldReference thisX = new FieldReference(fieldNode.rawName, p);
|
||||
int s = (int) (p >> 32);
|
||||
int e = (int) p;
|
||||
thisX.receiver = new ThisReference(s, e);
|
||||
|
||||
if (fieldNode.singularData != null && fieldNode.singularData.getSingularizer() != null) {
|
||||
fieldNode.singularData.getSingularizer().appendBuildCode(fieldNode.singularData, typeNode, assigns, fieldNode.name);
|
||||
}
|
||||
|
||||
Expression assignmentExpr;
|
||||
if (builderClassnameAsParameter != null) {
|
||||
char[][] variableInBuilder = new char[][] {"b".toCharArray(), fieldName};
|
||||
long[] positions = new long[] {p, p};
|
||||
assignmentExpr = new QualifiedNameReference(variableInBuilder, positions, s, e);
|
||||
} else {
|
||||
assignmentExpr = new SingleNameReference(fieldName, p);
|
||||
}
|
||||
|
||||
Assignment assignment = new Assignment(thisX, assignmentExpr, (int) p);
|
||||
assigns.add(assignment);
|
||||
Annotation[] nonNulls = findAnnotations((FieldDeclaration)fieldNode.fieldNode.get(), NON_NULL_PATTERN);
|
||||
if (nonNulls.length != 0) {
|
||||
Statement nullCheck = generateNullCheck((FieldDeclaration)fieldNode.fieldNode.get(), sourceNode);
|
||||
if (nullCheck != null) {
|
||||
nullChecks.add(nullCheck);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nullChecks.addAll(assigns);
|
||||
constructor.statements = nullChecks.isEmpty() ? null : nullChecks.toArray(new Statement[nullChecks.size()]);
|
||||
constructor.arguments = new Argument[] {new Argument("b".toCharArray(), p, new SingleTypeReference(builderClassnameAsParameter.toCharArray(), p), Modifier.FINAL)};
|
||||
|
||||
// Generate annotations that must be put on the generated method, and attach them.
|
||||
// Annotation[] constructorProperties = null;
|
||||
// if (!suppressConstructorProperties && level != AccessLevel.PRIVATE && level != AccessLevel.PACKAGE && !HandleConstructor.isLocalType(typeNode)) {
|
||||
// constructorProperties = HandleConstructor.createConstructorProperties(source, builderFields);
|
||||
// }
|
||||
|
||||
constructor.traverse(new SetGeneratedByVisitor(source), typeDeclaration.scope);
|
||||
|
||||
injectMethod(typeNode, constructor);
|
||||
}
|
||||
|
||||
private MethodDeclaration generateCleanMethod(List<BuilderFieldData> builderFields, EclipseNode builderType, ASTNode source) {
|
||||
List<Statement> statements = new ArrayList<Statement>();
|
||||
|
||||
|
||||
@@ -64,12 +64,10 @@ import org.eclipse.jdt.internal.compiler.ast.IntLiteral;
|
||||
import org.eclipse.jdt.internal.compiler.ast.LongLiteral;
|
||||
import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
|
||||
import org.eclipse.jdt.internal.compiler.ast.NullLiteral;
|
||||
import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference;
|
||||
import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference;
|
||||
import org.eclipse.jdt.internal.compiler.ast.ReturnStatement;
|
||||
import org.eclipse.jdt.internal.compiler.ast.SingleMemberAnnotation;
|
||||
import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
|
||||
import org.eclipse.jdt.internal.compiler.ast.SingleTypeReference;
|
||||
import org.eclipse.jdt.internal.compiler.ast.Statement;
|
||||
import org.eclipse.jdt.internal.compiler.ast.StringLiteral;
|
||||
import org.eclipse.jdt.internal.compiler.ast.ThisReference;
|
||||
@@ -97,7 +95,7 @@ public class HandleConstructor {
|
||||
List<EclipseNode> fields = force ? findFinalFields(typeNode) : Collections.<EclipseNode>emptyList();
|
||||
List<Annotation> onConstructor = unboxAndRemoveAnnotationParameter(ast, "onConstructor", "@NoArgsConstructor(onConstructor", annotationNode);
|
||||
|
||||
new HandleConstructor().generateConstructor(typeNode, level, fields, force, staticName, SkipIfConstructorExists.NO, onConstructor, annotationNode, null, false);
|
||||
new HandleConstructor().generateConstructor(typeNode, level, fields, force, staticName, SkipIfConstructorExists.NO, onConstructor, annotationNode);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,7 +118,7 @@ public class HandleConstructor {
|
||||
|
||||
new HandleConstructor().generateConstructor(
|
||||
typeNode, level, findRequiredFields(typeNode), false, staticName, SkipIfConstructorExists.NO,
|
||||
onConstructor, annotationNode, null, false);
|
||||
onConstructor, annotationNode);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,7 +177,7 @@ public class HandleConstructor {
|
||||
|
||||
new HandleConstructor().generateConstructor(
|
||||
typeNode, level, findAllFields(typeNode), false, staticName, SkipIfConstructorExists.NO,
|
||||
onConstructor, annotationNode, null, false);
|
||||
onConstructor, annotationNode);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -201,34 +199,23 @@ public class HandleConstructor {
|
||||
EclipseNode typeNode, AccessLevel level, String staticName, SkipIfConstructorExists skipIfConstructorExists,
|
||||
List<Annotation> onConstructor, EclipseNode sourceNode) {
|
||||
|
||||
generateConstructor(typeNode, level, findRequiredFields(typeNode), false, staticName, skipIfConstructorExists, onConstructor, sourceNode, null, false);
|
||||
generateConstructor(typeNode, level, findRequiredFields(typeNode), false, staticName, skipIfConstructorExists, onConstructor, sourceNode);
|
||||
}
|
||||
|
||||
public void generateAllArgsConstructor(
|
||||
EclipseNode typeNode, AccessLevel level, String staticName, SkipIfConstructorExists skipIfConstructorExists,
|
||||
List<Annotation> onConstructor, EclipseNode sourceNode) {
|
||||
|
||||
generateConstructor(typeNode, level, findAllFields(typeNode), false, staticName, skipIfConstructorExists, onConstructor, sourceNode, null, false);
|
||||
generateConstructor(typeNode, level, findAllFields(typeNode), false, staticName, skipIfConstructorExists, onConstructor, sourceNode);
|
||||
}
|
||||
|
||||
public enum SkipIfConstructorExists {
|
||||
YES, NO, I_AM_BUILDER;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param builderClassnameAsParameter
|
||||
* if {@code != null}, the only parameter of the constructor will
|
||||
* be a builder with this classname; the constructor will then
|
||||
* use the values within this builder to assign the fields of new
|
||||
* instances.
|
||||
* @param callBuilderBasedSuperConstructor
|
||||
* if {@code true}, the constructor will explicitly call a super
|
||||
* constructor with the builder as argument. Requires
|
||||
* {@code builderClassAsParameter != null}.
|
||||
*/
|
||||
public void generateConstructor(
|
||||
EclipseNode typeNode, AccessLevel level, List<EclipseNode> fields, boolean allToDefault, String staticName, SkipIfConstructorExists skipIfConstructorExists,
|
||||
List<Annotation> onConstructor, EclipseNode sourceNode, String builderClassnameAsParameter, boolean callBuilderBasedSuperConstructor) {
|
||||
List<Annotation> onConstructor, EclipseNode sourceNode) {
|
||||
|
||||
ASTNode source = sourceNode.get();
|
||||
boolean staticConstrRequired = staticName != null && !staticName.equals("");
|
||||
@@ -263,7 +250,7 @@ public class HandleConstructor {
|
||||
|
||||
ConstructorDeclaration constr = createConstructor(
|
||||
staticConstrRequired ? AccessLevel.PRIVATE : level, typeNode, fields, allToDefault,
|
||||
sourceNode, onConstructor, builderClassnameAsParameter, callBuilderBasedSuperConstructor);
|
||||
sourceNode, onConstructor);
|
||||
injectMethod(typeNode, constr);
|
||||
if (staticConstrRequired) {
|
||||
MethodDeclaration staticConstr = createStaticConstructor(level, staticName, typeNode, allToDefault ? Collections.<EclipseNode>emptyList() : fields, source);
|
||||
@@ -303,28 +290,9 @@ public class HandleConstructor {
|
||||
return new Annotation[] { ann };
|
||||
}
|
||||
|
||||
/**
|
||||
* @param builderClassnameAsParameter
|
||||
* if {@code != null}, the only parameter of the constructor will
|
||||
* be a builder with this classname; the constructor will then
|
||||
* use the values within this builder to assign the fields of new
|
||||
* instances.
|
||||
* @param callBuilderBasedSuperConstructor
|
||||
* if {@code true}, the constructor will explicitly call a super
|
||||
* constructor with the builder as argument. Requires
|
||||
* {@code builderClassnameAsParameter != null}.
|
||||
*/
|
||||
public static ConstructorDeclaration createConstructor(
|
||||
AccessLevel level, EclipseNode type, Collection<EclipseNode> fields, boolean allToDefault,
|
||||
EclipseNode sourceNode, List<Annotation> onConstructor,
|
||||
String builderClassnameAsParameter, boolean callBuilderBasedSuperConstructor) {
|
||||
|
||||
if (builderClassnameAsParameter != null && builderClassnameAsParameter.isEmpty()) {
|
||||
builderClassnameAsParameter = null;
|
||||
}
|
||||
if (callBuilderBasedSuperConstructor && builderClassnameAsParameter == null) {
|
||||
type.addError("Calling a builder-based superclass constructor ('callBuilderBasedSuperConstructor') requires a non-empty 'builderClassnameAsParameter' value.");
|
||||
}
|
||||
EclipseNode sourceNode, List<Annotation> onConstructor) {
|
||||
|
||||
ASTNode source = sourceNode.get();
|
||||
TypeDeclaration typeDeclaration = ((TypeDeclaration) type.get());
|
||||
@@ -345,12 +313,7 @@ public class HandleConstructor {
|
||||
|
||||
constructor.modifiers = toEclipseModifier(level);
|
||||
constructor.selector = typeDeclaration.name;
|
||||
if (callBuilderBasedSuperConstructor) {
|
||||
constructor.constructorCall = new ExplicitConstructorCall(ExplicitConstructorCall.Super);
|
||||
constructor.constructorCall.arguments = new Expression[] {new SingleNameReference("b".toCharArray(), p)};
|
||||
} else {
|
||||
constructor.constructorCall = new ExplicitConstructorCall(ExplicitConstructorCall.ImplicitSuper);
|
||||
}
|
||||
constructor.constructorCall = new ExplicitConstructorCall(ExplicitConstructorCall.ImplicitSuper);
|
||||
constructor.constructorCall.sourceStart = source.sourceStart;
|
||||
constructor.constructorCall.sourceEnd = source.sourceEnd;
|
||||
constructor.thrownExceptions = null;
|
||||
@@ -373,16 +336,7 @@ public class HandleConstructor {
|
||||
int e = (int) p;
|
||||
thisX.receiver = new ThisReference(s, e);
|
||||
|
||||
Expression assignmentExpr;
|
||||
if (allToDefault) {
|
||||
assignmentExpr = getDefaultExpr(field.type, s, e);
|
||||
} else if (builderClassnameAsParameter != null) {
|
||||
char[][] variableInBuilder = new char[][] {"b".toCharArray(), fieldName};
|
||||
long[] positions = new long[] {p, p};
|
||||
assignmentExpr = new QualifiedNameReference(variableInBuilder, positions, s, e);
|
||||
} else {
|
||||
assignmentExpr = new SingleNameReference(fieldName, p);
|
||||
}
|
||||
Expression assignmentExpr = allToDefault ? getDefaultExpr(field.type, s, e) : new SingleNameReference(fieldName, p);
|
||||
|
||||
Assignment assignment = new Assignment(thisX, assignmentExpr, (int) p);
|
||||
assignment.sourceStart = (int) (p >> 32); assignment.sourceEnd = assignment.statementEnd = (int) (p >> 32);
|
||||
@@ -403,11 +357,7 @@ public class HandleConstructor {
|
||||
|
||||
nullChecks.addAll(assigns);
|
||||
constructor.statements = nullChecks.isEmpty() ? null : nullChecks.toArray(new Statement[nullChecks.size()]);
|
||||
if (builderClassnameAsParameter != null) {
|
||||
constructor.arguments = new Argument[] {new Argument("b".toCharArray(), p, new SingleTypeReference(builderClassnameAsParameter.toCharArray(), p), Modifier.FINAL)};
|
||||
} else {
|
||||
constructor.arguments = params.isEmpty() ? null : params.toArray(new Argument[params.size()]);
|
||||
}
|
||||
constructor.arguments = params.isEmpty() ? null : params.toArray(new Argument[params.size()]);
|
||||
|
||||
/* Generate annotations that must be put on the generated method, and attach them. */ {
|
||||
Annotation[] constructorProperties = null;
|
||||
|
||||
Reference in new issue
Block a user