mirror of
https://github.com/tiennm99/lombok.git
synced 2026-10-14 10:18:46 +00:00
code formatting, reordering, rename etc.
This commit is contained in:
1 parent
04269ef14b
commit
4c5a7cddab
3 files changed
+454
-412
No files matched your search
@@ -1,16 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2013-2018 The Project Lombok Authors.
|
||||
*
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
@@ -88,33 +88,41 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
|
||||
ObtainVia obtainVia;
|
||||
JavacNode obtainViaNode;
|
||||
JavacNode originalFieldNode;
|
||||
|
||||
|
||||
java.util.List<JavacNode> createdFields = new ArrayList<JavacNode>();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void handle(AnnotationValues<SuperBuilder> annotation, JCAnnotation ast, JavacNode annotationNode) {
|
||||
SuperBuilder builderInstance = annotation.getInstance();
|
||||
|
||||
String builderMethodName = builderInstance.builderMethodName();
|
||||
String buildMethodName = builderInstance.buildMethodName();
|
||||
|
||||
if (builderMethodName == null) builderMethodName = "builder";
|
||||
if (buildMethodName == null) buildMethodName = "build";
|
||||
|
||||
if (!checkName("builderMethodName", builderMethodName, annotationNode)) return;
|
||||
if (!checkName("buildMethodName", buildMethodName, annotationNode)) return;
|
||||
|
||||
SuperBuilder superbuilderAnnotation = annotation.getInstance();
|
||||
|
||||
String builderMethodName = superbuilderAnnotation.builderMethodName();
|
||||
String buildMethodName = superbuilderAnnotation.buildMethodName();
|
||||
|
||||
if (builderMethodName == null) {
|
||||
builderMethodName = "builder";
|
||||
}
|
||||
if (buildMethodName == null) {
|
||||
buildMethodName = "build";
|
||||
}
|
||||
|
||||
if (!checkName("builderMethodName", builderMethodName, annotationNode)) {
|
||||
return;
|
||||
}
|
||||
if (!checkName("buildMethodName", buildMethodName, annotationNode)) {
|
||||
return;
|
||||
}
|
||||
|
||||
JavacNode tdParent = annotationNode.up();
|
||||
|
||||
|
||||
java.util.List<BuilderFieldData> builderFields = new ArrayList<BuilderFieldData>();
|
||||
JCExpression returnType;
|
||||
List<JCTypeParameter> typeParams = List.nil();
|
||||
List<JCExpression> thrownExceptions = List.nil();
|
||||
List<JCExpression> superclassTypeParams = List.nil();
|
||||
|
||||
|
||||
boolean addCleaning = false;
|
||||
|
||||
|
||||
if (!(tdParent.get() instanceof JCClassDecl)) {
|
||||
annotationNode.addError("@SuperBuilder is only supported on types.");
|
||||
return;
|
||||
@@ -134,28 +142,32 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
|
||||
bfd.type = fd.vartype;
|
||||
bfd.singularData = getSingularData(fieldNode);
|
||||
bfd.originalFieldNode = fieldNode;
|
||||
|
||||
|
||||
if (bfd.singularData != null && isDefault != null) {
|
||||
isDefault.addError("@Builder.Default and @Singular cannot be mixed.");
|
||||
isDefault = null;
|
||||
}
|
||||
|
||||
|
||||
if (fd.init == null && isDefault != null) {
|
||||
isDefault.addWarning("@Builder.Default requires an initializing expression (' = something;').");
|
||||
isDefault = null;
|
||||
}
|
||||
|
||||
|
||||
if (fd.init != null && isDefault == null) {
|
||||
if (isFinal) continue;
|
||||
if (isFinal) {
|
||||
continue;
|
||||
}
|
||||
fieldNode.addWarning("@SuperBuilder will ignore the initializing expression entirely. If you want the initializing expression to serve as default, add @Builder.Default. If it is not supposed to be settable during building, make the field final.");
|
||||
}
|
||||
|
||||
|
||||
if (isDefault != null) {
|
||||
bfd.nameOfDefaultProvider = tdParent.toName("$default$" + bfd.name);
|
||||
bfd.nameOfSetFlag = tdParent.toName(bfd.name + "$set");
|
||||
JCMethodDecl md = generateDefaultProvider(bfd.nameOfDefaultProvider, fieldNode, td.typarams);
|
||||
recursiveSetGeneratedBy(md, ast, annotationNode.getContext());
|
||||
if (md != null) injectMethod(tdParent, md);
|
||||
if (md != null) {
|
||||
injectMethod(tdParent, md);
|
||||
}
|
||||
}
|
||||
addObtainVia(bfd, fieldNode);
|
||||
builderFields.add(bfd);
|
||||
@@ -172,11 +184,11 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
|
||||
superclassTypeParams = ((JCTypeApply)extendsClause).getTypeArguments();
|
||||
// A class name with a generics type, e.g., "Superclass<A>".
|
||||
extendsClause = ((JCTypeApply)extendsClause).getType();
|
||||
}
|
||||
}
|
||||
if (extendsClause instanceof JCFieldAccess) {
|
||||
Name superclassClassName = ((JCFieldAccess)extendsClause).getIdentifier();
|
||||
String superclassBuilderClassName = superclassClassName + "Builder";
|
||||
superclassBuilderClassExpression = tdParent.getTreeMaker().Select((JCFieldAccess)extendsClause,
|
||||
superclassBuilderClassExpression = tdParent.getTreeMaker().Select((JCFieldAccess)extendsClause,
|
||||
tdParent.toName(superclassBuilderClassName));
|
||||
} else if (extendsClause != null) {
|
||||
String superclassBuilderClassName = extendsClause.toString() + "Builder";
|
||||
@@ -187,7 +199,7 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
|
||||
|
||||
returnType = namePlusTypeParamsToTypeReference(tdParent.getTreeMaker(), td.name, td.typarams);
|
||||
typeParams = td.typarams;
|
||||
|
||||
|
||||
// <C, B> are the generics for our builder.
|
||||
String classGenericName = "C";
|
||||
String builderGenericName = "B";
|
||||
@@ -199,22 +211,9 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
|
||||
}
|
||||
classGenericName = generateNonclashingNameFor(classGenericName, typeParamStrings);
|
||||
builderGenericName = generateNonclashingNameFor(builderGenericName, typeParamStrings);
|
||||
|
||||
|
||||
thrownExceptions = List.nil();
|
||||
|
||||
generateBuilderBasedConstructor(tdParent, typeParams, builderFields, annotationNode, builderClassName,
|
||||
superclassBuilderClassExpression != null);
|
||||
|
||||
// Create the abstract builder class.
|
||||
JavacNode builderType = findInnerClass(tdParent, builderClassName);
|
||||
if (builderType == null) {
|
||||
builderType = makeBuilderAbstractClass(annotationNode, tdParent, builderClassName, superclassBuilderClassExpression,
|
||||
typeParams, superclassTypeParams, ast, classGenericName, builderGenericName);
|
||||
} else {
|
||||
annotationNode.addError("@SuperBuilder does not support customized builders. Use @Builder instead.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Check validity of @ObtainVia fields, and add check if adding cleaning for @Singular is necessary.
|
||||
for (BuilderFieldData bfd : builderFields) {
|
||||
if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) {
|
||||
@@ -235,7 +234,17 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
|
||||
}
|
||||
}
|
||||
|
||||
// Generate the fields in the abstract builder class that hold the values for the instance.
|
||||
// Create the abstract builder class.
|
||||
JavacNode builderType = findInnerClass(tdParent, builderClassName);
|
||||
if (builderType == null) {
|
||||
builderType = generateBuilderAbstractClass(annotationNode, tdParent, builderClassName, superclassBuilderClassExpression,
|
||||
typeParams, superclassTypeParams, ast, classGenericName, builderGenericName);
|
||||
} else {
|
||||
annotationNode.addError("@SuperBuilder does not support customized builders. Use @Builder instead.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Generate the fields in the abstract builder class that hold the values for the instance.
|
||||
generateBuilderFields(builderType, builderFields, ast);
|
||||
if (addCleaning) {
|
||||
JavacTreeMaker maker = builderType.getTreeMaker();
|
||||
@@ -249,9 +258,9 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
|
||||
|
||||
// Create the setter methods in the abstract builder.
|
||||
for (BuilderFieldData bfd : builderFields) {
|
||||
makeSetterMethodsForBuilder(builderType, bfd, annotationNode, builderGenericName);
|
||||
generateSetterMethodsForBuilder(builderType, bfd, annotationNode, builderGenericName);
|
||||
}
|
||||
|
||||
|
||||
// Create the toString() method for the abstract builder.
|
||||
if (methodExists("toString", builderType, 0) == MemberExistsResult.NOT_EXISTS) {
|
||||
java.util.List<JavacNode> fieldNodes = new ArrayList<JavacNode>();
|
||||
@@ -260,15 +269,19 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
|
||||
}
|
||||
// Let toString() call super.toString() if there is a superclass, so that it also shows fields from the superclass' builder.
|
||||
JCMethodDecl md = HandleToString.createToString(builderType, fieldNodes, true, superclassBuilderClassExpression != null, FieldAccess.ALWAYS_FIELD, ast);
|
||||
if (md != null) injectMethod(builderType, md);
|
||||
if (md != null) {
|
||||
injectMethod(builderType, md);
|
||||
}
|
||||
}
|
||||
|
||||
if (addCleaning) injectMethod(builderType, generateCleanMethod(builderFields, builderType, ast));
|
||||
|
||||
|
||||
if (addCleaning) {
|
||||
injectMethod(builderType, generateCleanMethod(builderFields, builderType, ast));
|
||||
}
|
||||
|
||||
// Create the builder implementation class.
|
||||
JavacNode builderImplType = findInnerClass(tdParent, builderImplClassName);
|
||||
if (builderImplType == null) {
|
||||
builderImplType = makeBuilderImplClass(annotationNode, tdParent, builderImplClassName, builderClassName, typeParams, ast);
|
||||
builderImplType = generateBuilderImplClass(annotationNode, tdParent, builderImplClassName, builderClassName, typeParams, ast);
|
||||
} else {
|
||||
annotationNode.addError("@SuperBuilder does not support customized builders. Use @Builder instead.");
|
||||
return;
|
||||
@@ -276,325 +289,37 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
|
||||
|
||||
// Create a simple constructor for the BuilderImpl class.
|
||||
JCMethodDecl cd = HandleConstructor.createConstructor(AccessLevel.PRIVATE, List.<JCAnnotation>nil(), builderImplType, List.<JavacNode>nil(), false, annotationNode);
|
||||
if (cd != null) injectMethod(builderImplType, cd);
|
||||
if (cd != null) {
|
||||
injectMethod(builderImplType, cd);
|
||||
}
|
||||
|
||||
// Create the self() and build() methods in the BuilderImpl.
|
||||
injectMethod(builderImplType, generateSelfMethod(builderImplType));
|
||||
injectMethod(builderImplType, generateBuildMethod(buildMethodName, returnType, builderImplType, thrownExceptions));
|
||||
|
||||
|
||||
// Generate a constructor in the annotated class that takes a builder as argument.
|
||||
generateBuilderBasedConstructor(tdParent, typeParams, builderFields, annotationNode, builderClassName,
|
||||
superclassBuilderClassExpression != null);
|
||||
|
||||
// Add the builder() method to the annotated class.
|
||||
// Allow users to specify their own builder() methods, e.g., to provide default values.
|
||||
if (methodExists(builderMethodName, tdParent, -1) == MemberExistsResult.NOT_EXISTS) {
|
||||
JCMethodDecl md = generateBuilderMethod(builderMethodName, builderClassName, builderImplClassName, annotationNode, tdParent, typeParams);
|
||||
recursiveSetGeneratedBy(md, ast, annotationNode.getContext());
|
||||
if (md != null) injectMethod(tdParent, md);
|
||||
if (md != null) {
|
||||
injectMethod(tdParent, md);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
recursiveSetGeneratedBy(builderType.get(), ast, annotationNode.getContext());
|
||||
recursiveSetGeneratedBy(builderImplType.get(), ast, annotationNode.getContext());
|
||||
}
|
||||
|
||||
private String generateNonclashingNameFor(String classGenericName, java.util.List<String> typeParamStrings) {
|
||||
if (!typeParamStrings.contains(classGenericName))
|
||||
return classGenericName;
|
||||
int counter = 2;
|
||||
while (typeParamStrings.contains(classGenericName + counter)) {
|
||||
counter++;
|
||||
}
|
||||
return classGenericName + counter;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generates a constructor that has a builder as the only parameter.
|
||||
* The values from the builder are used to initialize the fields of new instances.
|
||||
*
|
||||
* @param typeNode
|
||||
* the type (with the {@code @Builder} annotation) for which a
|
||||
* constructor should be generated.
|
||||
* @param typeParams
|
||||
* @param builderFields a list of fields in the builder which should be assigned to new instances.
|
||||
* @param source the annotation (used for setting source code locations for the generated code).
|
||||
* @param callBuilderBasedSuperConstructor
|
||||
* If {@code true}, the constructor will explicitly call a super
|
||||
* constructor with the builder as argument. Requires
|
||||
* {@code builderClassAsParameter != null}.
|
||||
* Creates and returns the abstract builder class and injects it into the annotated class.
|
||||
*/
|
||||
private void generateBuilderBasedConstructor(JavacNode typeNode, List<JCTypeParameter> typeParams, java.util.List<BuilderFieldData> builderFields, JavacNode source, String builderClassName, boolean callBuilderBasedSuperConstructor) {
|
||||
JavacTreeMaker maker = typeNode.getTreeMaker();
|
||||
|
||||
AccessLevel level = AccessLevel.PROTECTED;
|
||||
boolean isEnum = (((JCClassDecl) typeNode.get()).mods.flags & Flags.ENUM) != 0;
|
||||
if (isEnum) {
|
||||
level = AccessLevel.PRIVATE;
|
||||
}
|
||||
|
||||
ListBuffer<JCStatement> nullChecks = new ListBuffer<JCStatement>();
|
||||
ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>();
|
||||
|
||||
Name builderVariableName = typeNode.toName("b");
|
||||
for (BuilderFieldData bfd : builderFields) {
|
||||
List<JCAnnotation> nonNulls = findAnnotations(bfd.originalFieldNode, NON_NULL_PATTERN);
|
||||
if (!nonNulls.isEmpty()) {
|
||||
JCStatement nullCheck = generateNullCheck(maker, bfd.originalFieldNode, source);
|
||||
if (nullCheck != null) {
|
||||
nullChecks.append(nullCheck);
|
||||
}
|
||||
}
|
||||
|
||||
JCExpression rhs;
|
||||
if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) {
|
||||
bfd.singularData.getSingularizer().appendBuildCode(bfd.singularData, bfd.originalFieldNode, bfd.type, statements, bfd.name, "b");
|
||||
rhs = maker.Ident(bfd.singularData.getPluralName());
|
||||
} else {
|
||||
rhs = maker.Select(maker.Ident(builderVariableName), bfd.rawName);
|
||||
}
|
||||
JCFieldAccess thisX = maker.Select(maker.Ident(bfd.originalFieldNode.toName("this")), bfd.rawName);
|
||||
|
||||
JCExpression assign = maker.Assign(thisX, rhs);
|
||||
|
||||
statements.append(maker.Exec(assign));
|
||||
}
|
||||
|
||||
JCModifiers mods = maker.Modifiers(toJavacModifier(level), List.<JCAnnotation>nil());
|
||||
|
||||
// Create a constructor that has just the builder as parameter.
|
||||
ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>();
|
||||
long flags = JavacHandlerUtil.addFinalIfNeeded(Flags.PARAMETER, typeNode.getContext());
|
||||
Name builderClassname = typeNode.toName(builderClassName);
|
||||
// First add all generics that are present on the parent type.
|
||||
ListBuffer<JCExpression> typeParamsForBuilderParameter = getTypeParamExpressions(typeParams, maker);
|
||||
// Now add the <?, ?>.
|
||||
JCWildcard wildcard = maker.Wildcard(maker.TypeBoundKind(BoundKind.UNBOUND), null);
|
||||
typeParamsForBuilderParameter.add(wildcard);
|
||||
wildcard = maker.Wildcard(maker.TypeBoundKind(BoundKind.UNBOUND), null);
|
||||
typeParamsForBuilderParameter.add(wildcard);
|
||||
JCTypeApply paramType = maker.TypeApply(maker.Ident(builderClassname), typeParamsForBuilderParameter.toList());
|
||||
JCVariableDecl param = maker.VarDef(maker.Modifiers(flags), builderVariableName, paramType, null);
|
||||
params.append(param);
|
||||
|
||||
if (callBuilderBasedSuperConstructor) {
|
||||
// The first statement must be the call to the super constructor.
|
||||
JCMethodInvocation callToSuperConstructor = maker.Apply(List.<JCExpression>nil(),
|
||||
maker.Ident(typeNode.toName("super")),
|
||||
List.<JCExpression>of(maker.Ident(builderVariableName)));
|
||||
statements.prepend(maker.Exec(callToSuperConstructor));
|
||||
}
|
||||
|
||||
JCMethodDecl constr = recursiveSetGeneratedBy(maker.MethodDef(mods, typeNode.toName("<init>"),
|
||||
null, List.<JCTypeParameter>nil(), params.toList(), List.<JCExpression>nil(),
|
||||
maker.Block(0L, nullChecks.appendList(statements).toList()), null), source.get(), typeNode.getContext());
|
||||
|
||||
injectMethod(typeNode, constr, null, Javac.createVoidType(typeNode.getSymbolTable(), CTC_VOID));
|
||||
}
|
||||
|
||||
private ListBuffer<JCExpression> getTypeParamExpressions(List<? extends JCTree> typeParams, JavacTreeMaker maker) {
|
||||
ListBuffer<JCExpression> typeParamsForBuilderParameter = new ListBuffer<JCExpression>();
|
||||
for (JCTree typeParam : typeParams) {
|
||||
if (typeParam instanceof JCTypeParameter) {
|
||||
typeParamsForBuilderParameter.add(maker.Ident(((JCTypeParameter)typeParam).getName()));
|
||||
} else if (typeParam instanceof JCIdent) {
|
||||
typeParamsForBuilderParameter.add(maker.Ident(((JCIdent)typeParam).getName()));
|
||||
}
|
||||
}
|
||||
return typeParamsForBuilderParameter;
|
||||
}
|
||||
|
||||
private JCMethodDecl generateAbstractSelfMethod(JavacNode type, boolean override, String builderGenericName) {
|
||||
JavacTreeMaker maker = type.getTreeMaker();
|
||||
List<JCAnnotation> annotations = List.nil();
|
||||
if (override) {
|
||||
JCAnnotation overrideAnnotation = maker.Annotation(genJavaLangTypeRef(type, "Override"), List.<JCExpression>nil());
|
||||
annotations = List.of(overrideAnnotation);
|
||||
}
|
||||
JCModifiers modifiers = maker.Modifiers(Flags.PROTECTED | Flags.ABSTRACT, annotations);
|
||||
Name name = type.toName(SELF_METHOD);
|
||||
JCExpression returnType = maker.Ident(type.toName(builderGenericName));
|
||||
|
||||
return maker.MethodDef(modifiers, name, returnType, List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), null, null);
|
||||
}
|
||||
|
||||
private JCMethodDecl generateSelfMethod(JavacNode builderImplType) {
|
||||
JavacTreeMaker maker = builderImplType.getTreeMaker();
|
||||
|
||||
JCAnnotation overrideAnnotation = maker.Annotation(genJavaLangTypeRef(builderImplType, "Override"), List.<JCExpression>nil());
|
||||
JCModifiers modifiers = maker.Modifiers(Flags.PROTECTED, List.of(overrideAnnotation));
|
||||
Name name = builderImplType.toName(SELF_METHOD);
|
||||
JCExpression returnType = maker.Ident(builderImplType.toName(builderImplType.getName()));
|
||||
|
||||
JCStatement statement = maker.Return(maker.Ident(builderImplType.toName("this")));
|
||||
JCBlock body = maker.Block(0, List.<JCStatement>of(statement));
|
||||
|
||||
return maker.MethodDef(modifiers, name, returnType, List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null);
|
||||
}
|
||||
|
||||
private JCMethodDecl generateAbstractBuildMethod(JavacNode type, String methodName, boolean override, String classGenericName) {
|
||||
JavacTreeMaker maker = type.getTreeMaker();
|
||||
List<JCAnnotation> annotations = List.nil();
|
||||
if (override) {
|
||||
JCAnnotation overrideAnnotation = maker.Annotation(genJavaLangTypeRef(type, "Override"), List.<JCExpression>nil());
|
||||
annotations = List.of(overrideAnnotation);
|
||||
}
|
||||
JCModifiers modifiers = maker.Modifiers(Flags.PUBLIC | Flags.ABSTRACT, annotations);
|
||||
Name name = type.toName(methodName);
|
||||
JCExpression returnType = maker.Ident(type.toName(classGenericName));
|
||||
|
||||
return maker.MethodDef(modifiers, name, returnType, List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), null, null);
|
||||
}
|
||||
|
||||
private JCMethodDecl generateCleanMethod(java.util.List<BuilderFieldData> builderFields, JavacNode type, JCTree source) {
|
||||
JavacTreeMaker maker = type.getTreeMaker();
|
||||
ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>();
|
||||
|
||||
for (BuilderFieldData bfd : builderFields) {
|
||||
if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) {
|
||||
bfd.singularData.getSingularizer().appendCleaningCode(bfd.singularData, type, source, statements);
|
||||
}
|
||||
}
|
||||
|
||||
statements.append(maker.Exec(maker.Assign(maker.Select(maker.Ident(type.toName("this")), type.toName("$lombokUnclean")), maker.Literal(CTC_BOOLEAN, 0))));
|
||||
JCBlock body = maker.Block(0, statements.toList());
|
||||
return maker.MethodDef(maker.Modifiers(Flags.PUBLIC), type.toName("$lombokClean"), maker.Type(Javac.createVoidType(type.getSymbolTable(), CTC_VOID)), List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null);
|
||||
}
|
||||
|
||||
private JCMethodDecl generateBuildMethod(String buildName, JCExpression returnType, JavacNode type, List<JCExpression> thrownExceptions) {
|
||||
JavacTreeMaker maker = type.getTreeMaker();
|
||||
|
||||
JCExpression call;
|
||||
ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>();
|
||||
|
||||
// Use a constructor that only has this builder as parameter.
|
||||
List<JCExpression> builderArg = List.<JCExpression>of(maker.Ident(type.toName("this")));
|
||||
call = maker.NewClass(null, List.<JCExpression>nil(), returnType, builderArg, null);
|
||||
statements.append(maker.Return(call));
|
||||
|
||||
JCBlock body = maker.Block(0, statements.toList());
|
||||
|
||||
JCAnnotation overrideAnnotation = maker.Annotation(genJavaLangTypeRef(type, "Override"), List.<JCExpression>nil());
|
||||
JCModifiers modifiers = maker.Modifiers(Flags.PUBLIC, List.of(overrideAnnotation));
|
||||
|
||||
return maker.MethodDef(modifiers, type.toName(buildName), returnType, List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), thrownExceptions, body, null);
|
||||
}
|
||||
|
||||
public JCMethodDecl generateDefaultProvider(Name methodName, JavacNode fieldNode, List<JCTypeParameter> params) {
|
||||
JavacTreeMaker maker = fieldNode.getTreeMaker();
|
||||
JCVariableDecl field = (JCVariableDecl) fieldNode.get();
|
||||
|
||||
JCStatement statement = maker.Return(field.init);
|
||||
field.init = null;
|
||||
|
||||
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()), copyTypeParams(fieldNode, params), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null);
|
||||
}
|
||||
|
||||
public JCMethodDecl generateBuilderMethod(String builderMethodName, String builderClassName, String builderImplClassName, JavacNode source, JavacNode type, List<JCTypeParameter> typeParams) {
|
||||
JavacTreeMaker maker = type.getTreeMaker();
|
||||
|
||||
ListBuffer<JCExpression> typeArgs = new ListBuffer<JCExpression>();
|
||||
for (JCTypeParameter typeParam : typeParams) {
|
||||
typeArgs.append(maker.Ident(typeParam.name));
|
||||
}
|
||||
|
||||
JCExpression call = maker.NewClass(null, List.<JCExpression>nil(), namePlusTypeParamsToTypeReference(maker, type.toName(builderImplClassName), typeParams), List.<JCExpression>nil(), null);
|
||||
JCStatement statement = maker.Return(call);
|
||||
|
||||
JCBlock body = maker.Block(0, List.<JCStatement>of(statement));
|
||||
int modifiers = Flags.PUBLIC;
|
||||
modifiers |= Flags.STATIC;
|
||||
|
||||
// Add any type params of the annotated class to the return type.
|
||||
ListBuffer<JCExpression> typeParameterNames = new ListBuffer<JCExpression>();
|
||||
typeParameterNames.addAll(typeParameterNames(maker, typeParams));
|
||||
// Now add the <?, ?>.
|
||||
JCWildcard wildcard = maker.Wildcard(maker.TypeBoundKind(BoundKind.UNBOUND), null);
|
||||
typeParameterNames.add(wildcard);
|
||||
typeParameterNames.add(wildcard);
|
||||
JCTypeApply returnType = maker.TypeApply(maker.Ident(type.toName(builderClassName)), typeParameterNames.toList());
|
||||
|
||||
return maker.MethodDef(maker.Modifiers(modifiers), type.toName(builderMethodName), returnType, copyTypeParams(source, typeParams), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null);
|
||||
}
|
||||
|
||||
public void generateBuilderFields(JavacNode builderType, java.util.List<BuilderFieldData> builderFields, JCTree source) {
|
||||
int len = builderFields.size();
|
||||
java.util.List<JavacNode> existing = new ArrayList<JavacNode>();
|
||||
for (JavacNode child : builderType.down()) {
|
||||
if (child.getKind() == Kind.FIELD) existing.add(child);
|
||||
}
|
||||
|
||||
for (int i = len - 1; i >= 0; i--) {
|
||||
BuilderFieldData bfd = builderFields.get(i);
|
||||
if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) {
|
||||
bfd.createdFields.addAll(bfd.singularData.getSingularizer().generateFields(bfd.singularData, builderType, source));
|
||||
} else {
|
||||
JavacNode field = null, setFlag = null;
|
||||
for (JavacNode exists : existing) {
|
||||
Name n = ((JCVariableDecl) exists.get()).name;
|
||||
if (n.equals(bfd.name)) field = exists;
|
||||
if (n.equals(bfd.nameOfSetFlag)) setFlag = exists;
|
||||
}
|
||||
JavacTreeMaker maker = builderType.getTreeMaker();
|
||||
if (field == null) {
|
||||
JCModifiers mods = maker.Modifiers(Flags.PRIVATE);
|
||||
JCVariableDecl newField = maker.VarDef(mods, bfd.name, cloneType(maker, bfd.type, source, builderType.getContext()), null);
|
||||
field = injectFieldAndMarkGenerated(builderType, newField);
|
||||
}
|
||||
if (setFlag == null && bfd.nameOfSetFlag != null) {
|
||||
JCModifiers mods = maker.Modifiers(Flags.PRIVATE);
|
||||
JCVariableDecl newField = maker.VarDef(mods, bfd.nameOfSetFlag, maker.TypeIdent(CTC_BOOLEAN), null);
|
||||
injectFieldAndMarkGenerated(builderType, newField);
|
||||
}
|
||||
bfd.createdFields.add(field);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void makeSetterMethodsForBuilder(final JavacNode builderType, BuilderFieldData fieldNode, JavacNode source, final String builderGenericName) {
|
||||
boolean deprecate = isFieldDeprecated(fieldNode.originalFieldNode);
|
||||
final JavacTreeMaker maker = builderType.getTreeMaker();
|
||||
// TODO: Make these lambdas when switching to a source level >= 1.8.
|
||||
Supplier<JCExpression> returnType = new Supplier<JCExpression>() { @Override public JCExpression get() {
|
||||
return maker.Ident(builderType.toName(builderGenericName));
|
||||
}};
|
||||
Supplier<? extends JCReturn> returnStatement = new Supplier<JCReturn>() { @Override public JCReturn get() {
|
||||
return maker.Return(maker.Apply(List.<JCExpression>nil(), maker.Ident(builderType.toName(SELF_METHOD)), List.<JCExpression>nil()));
|
||||
}};
|
||||
if (fieldNode.singularData == null || fieldNode.singularData.getSingularizer() == null) {
|
||||
makeSimpleSetterMethodForBuilder(builderType, deprecate, fieldNode.createdFields.get(0), fieldNode.nameOfSetFlag, source, true, true, returnType.get(), returnStatement.get());
|
||||
} else {
|
||||
fieldNode.singularData.getSingularizer().generateMethods(fieldNode.singularData, deprecate, builderType, source.get(), true, returnType, returnStatement);
|
||||
}
|
||||
}
|
||||
|
||||
private void makeSimpleSetterMethodForBuilder(JavacNode builderType, boolean deprecate, JavacNode fieldNode, Name nameOfSetFlag, JavacNode source, boolean fluent, boolean chain, JCExpression returnType, JCReturn returnStatement) {
|
||||
Name fieldName = ((JCVariableDecl) fieldNode.get()).name;
|
||||
|
||||
for (JavacNode child : builderType.down()) {
|
||||
if (child.getKind() != Kind.METHOD) continue;
|
||||
JCMethodDecl methodDecl = (JCMethodDecl) child.get();
|
||||
Name existingName = methodDecl.name;
|
||||
if (existingName.equals(fieldName) && !isTolerate(fieldNode, methodDecl)) return;
|
||||
}
|
||||
|
||||
String setterName = fluent ? fieldNode.getName() : HandlerUtil.buildAccessorName("set", fieldNode.getName());
|
||||
|
||||
JavacTreeMaker maker = fieldNode.getTreeMaker();
|
||||
|
||||
JCMethodDecl newMethod = HandleSetter.createSetter(Flags.PUBLIC, deprecate, fieldNode, maker, setterName, nameOfSetFlag, returnType, returnStatement, source, List.<JCAnnotation>nil(), List.<JCAnnotation>nil());
|
||||
|
||||
injectMethod(builderType, newMethod);
|
||||
}
|
||||
|
||||
public JavacNode findInnerClass(JavacNode parent, String name) {
|
||||
for (JavacNode child : parent.down()) {
|
||||
if (child.getKind() != Kind.TYPE) continue;
|
||||
JCClassDecl td = (JCClassDecl) child.get();
|
||||
if (td.name.contentEquals(name)) return child;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public JavacNode makeBuilderAbstractClass(JavacNode source, JavacNode tdParent, String builderClass,
|
||||
JCExpression superclassBuilderClassExpression, List<JCTypeParameter> typeParams,
|
||||
private JavacNode generateBuilderAbstractClass(JavacNode source, JavacNode tdParent, String builderClass,
|
||||
JCExpression superclassBuilderClassExpression, List<JCTypeParameter> typeParams,
|
||||
List<JCExpression> superclassTypeParams, JCAnnotation ast, String classGenericName, String builderGenericName) {
|
||||
JavacTreeMaker maker = tdParent.getTreeMaker();
|
||||
JCModifiers mods = maker.Modifiers(Flags.STATIC | Flags.ABSTRACT | Flags.PUBLIC);
|
||||
@@ -628,15 +353,18 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
|
||||
typeParamsForBuilder.add(maker.Ident(tdParent.toName(builderGenericName)));
|
||||
extending = maker.TypeApply(superclassBuilderClassExpression, typeParamsForBuilder.toList());
|
||||
}
|
||||
|
||||
|
||||
JCClassDecl builder = maker.ClassDef(mods, builderClassName, allTypeParams.toList(), extending, List.<JCExpression>nil(), List.<JCTree>nil());
|
||||
return injectType(tdParent, builder);
|
||||
}
|
||||
|
||||
public JavacNode makeBuilderImplClass(JavacNode source, JavacNode tdParent, String builderImplClass, String builderAbstractClass, List<JCTypeParameter> typeParams, JCAnnotation ast) {
|
||||
|
||||
/**
|
||||
* Creates and returns the concrete builder implementation class and injects it into the annotated class.
|
||||
*/
|
||||
private JavacNode generateBuilderImplClass(JavacNode source, JavacNode tdParent, String builderImplClass, String builderAbstractClass, List<JCTypeParameter> typeParams, JCAnnotation ast) {
|
||||
JavacTreeMaker maker = tdParent.getTreeMaker();
|
||||
JCModifiers mods = maker.Modifiers(Flags.STATIC | Flags.PRIVATE | Flags.FINAL);
|
||||
|
||||
|
||||
// Extend the abstract builder.
|
||||
JCExpression extending = maker.Ident(tdParent.toName(builderAbstractClass));
|
||||
// Add any type params of the annotated class.
|
||||
@@ -658,14 +386,290 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
|
||||
typeParamsForBuilder.add(annotatedClass);
|
||||
typeParamsForBuilder.add(builderImplClassExpression);
|
||||
extending = maker.TypeApply(extending, typeParamsForBuilder.toList());
|
||||
|
||||
|
||||
JCClassDecl builder = maker.ClassDef(mods, tdParent.toName(builderImplClass), copyTypeParams(source, typeParams), extending, List.<JCExpression>nil(), List.<JCTree>nil());
|
||||
return injectType(tdParent, builder);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generates a constructor that has a builder as the only parameter.
|
||||
* The values from the builder are used to initialize the fields of new instances.
|
||||
*
|
||||
* @param typeNode
|
||||
* the type (with the {@code @Builder} annotation) for which a
|
||||
* constructor should be generated.
|
||||
* @param typeParams
|
||||
* @param builderFields a list of fields in the builder which should be assigned to new instances.
|
||||
* @param source the annotation (used for setting source code locations for the generated code).
|
||||
* @param callBuilderBasedSuperConstructor
|
||||
* If {@code true}, the constructor will explicitly call a super
|
||||
* constructor with the builder as argument. Requires
|
||||
* {@code builderClassAsParameter != null}.
|
||||
*/
|
||||
private void generateBuilderBasedConstructor(JavacNode typeNode, List<JCTypeParameter> typeParams, java.util.List<BuilderFieldData> builderFields, JavacNode source, String builderClassName, boolean callBuilderBasedSuperConstructor) {
|
||||
JavacTreeMaker maker = typeNode.getTreeMaker();
|
||||
|
||||
AccessLevel level = AccessLevel.PROTECTED;
|
||||
|
||||
ListBuffer<JCStatement> nullChecks = new ListBuffer<JCStatement>();
|
||||
ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>();
|
||||
|
||||
Name builderVariableName = typeNode.toName("b");
|
||||
for (BuilderFieldData bfd : builderFields) {
|
||||
List<JCAnnotation> nonNulls = findAnnotations(bfd.originalFieldNode, NON_NULL_PATTERN);
|
||||
if (!nonNulls.isEmpty()) {
|
||||
JCStatement nullCheck = generateNullCheck(maker, bfd.originalFieldNode, source);
|
||||
if (nullCheck != null) {
|
||||
nullChecks.append(nullCheck);
|
||||
}
|
||||
}
|
||||
|
||||
JCExpression rhs;
|
||||
if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) {
|
||||
bfd.singularData.getSingularizer().appendBuildCode(bfd.singularData, bfd.originalFieldNode, bfd.type, statements, bfd.name, "b");
|
||||
rhs = maker.Ident(bfd.singularData.getPluralName());
|
||||
} else {
|
||||
rhs = maker.Select(maker.Ident(builderVariableName), bfd.rawName);
|
||||
}
|
||||
JCFieldAccess thisX = maker.Select(maker.Ident(typeNode.toName("this")), bfd.rawName);
|
||||
|
||||
JCExpression assign = maker.Assign(thisX, rhs);
|
||||
|
||||
statements.append(maker.Exec(assign));
|
||||
}
|
||||
|
||||
JCModifiers mods = maker.Modifiers(toJavacModifier(level), List.<JCAnnotation>nil());
|
||||
|
||||
// Create a constructor that has just the builder as parameter.
|
||||
ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>();
|
||||
long flags = JavacHandlerUtil.addFinalIfNeeded(Flags.PARAMETER, typeNode.getContext());
|
||||
Name builderClassname = typeNode.toName(builderClassName);
|
||||
// First add all generics that are present on the parent type.
|
||||
ListBuffer<JCExpression> typeParamsForBuilderParameter = getTypeParamExpressions(typeParams, maker);
|
||||
// Now add the <?, ?>.
|
||||
JCWildcard wildcard = maker.Wildcard(maker.TypeBoundKind(BoundKind.UNBOUND), null);
|
||||
typeParamsForBuilderParameter.add(wildcard);
|
||||
wildcard = maker.Wildcard(maker.TypeBoundKind(BoundKind.UNBOUND), null);
|
||||
typeParamsForBuilderParameter.add(wildcard);
|
||||
JCTypeApply paramType = maker.TypeApply(maker.Ident(builderClassname), typeParamsForBuilderParameter.toList());
|
||||
JCVariableDecl param = maker.VarDef(maker.Modifiers(flags), builderVariableName, paramType, null);
|
||||
params.append(param);
|
||||
|
||||
if (callBuilderBasedSuperConstructor) {
|
||||
// The first statement must be the call to the super constructor.
|
||||
JCMethodInvocation callToSuperConstructor = maker.Apply(List.<JCExpression>nil(),
|
||||
maker.Ident(typeNode.toName("super")),
|
||||
List.<JCExpression>of(maker.Ident(builderVariableName)));
|
||||
statements.prepend(maker.Exec(callToSuperConstructor));
|
||||
}
|
||||
|
||||
JCMethodDecl constr = recursiveSetGeneratedBy(maker.MethodDef(mods, typeNode.toName("<init>"),
|
||||
null, List.<JCTypeParameter>nil(), params.toList(), List.<JCExpression>nil(),
|
||||
maker.Block(0L, nullChecks.appendList(statements).toList()), null), source.get(), typeNode.getContext());
|
||||
|
||||
injectMethod(typeNode, constr, null, Javac.createVoidType(typeNode.getSymbolTable(), CTC_VOID));
|
||||
}
|
||||
|
||||
private JCMethodDecl generateBuilderMethod(String builderMethodName, String builderClassName, String builderImplClassName, JavacNode source, JavacNode type, List<JCTypeParameter> typeParams) {
|
||||
JavacTreeMaker maker = type.getTreeMaker();
|
||||
|
||||
ListBuffer<JCExpression> typeArgs = new ListBuffer<JCExpression>();
|
||||
for (JCTypeParameter typeParam : typeParams) {
|
||||
typeArgs.append(maker.Ident(typeParam.name));
|
||||
}
|
||||
|
||||
JCExpression call = maker.NewClass(null, List.<JCExpression>nil(), namePlusTypeParamsToTypeReference(maker, type.toName(builderImplClassName), typeParams), List.<JCExpression>nil(), null);
|
||||
JCStatement statement = maker.Return(call);
|
||||
|
||||
JCBlock body = maker.Block(0, List.<JCStatement>of(statement));
|
||||
int modifiers = Flags.PUBLIC;
|
||||
modifiers |= Flags.STATIC;
|
||||
|
||||
// Add any type params of the annotated class to the return type.
|
||||
ListBuffer<JCExpression> typeParameterNames = new ListBuffer<JCExpression>();
|
||||
typeParameterNames.addAll(typeParameterNames(maker, typeParams));
|
||||
// Now add the <?, ?>.
|
||||
JCWildcard wildcard = maker.Wildcard(maker.TypeBoundKind(BoundKind.UNBOUND), null);
|
||||
typeParameterNames.add(wildcard);
|
||||
typeParameterNames.add(wildcard);
|
||||
JCTypeApply returnType = maker.TypeApply(maker.Ident(type.toName(builderClassName)), typeParameterNames.toList());
|
||||
|
||||
return maker.MethodDef(maker.Modifiers(modifiers), type.toName(builderMethodName), returnType, copyTypeParams(source, typeParams), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null);
|
||||
}
|
||||
|
||||
private JCMethodDecl generateAbstractSelfMethod(JavacNode type, boolean override, String builderGenericName) {
|
||||
JavacTreeMaker maker = type.getTreeMaker();
|
||||
List<JCAnnotation> annotations = List.nil();
|
||||
if (override) {
|
||||
JCAnnotation overrideAnnotation = maker.Annotation(genJavaLangTypeRef(type, "Override"), List.<JCExpression>nil());
|
||||
annotations = List.of(overrideAnnotation);
|
||||
}
|
||||
JCModifiers modifiers = maker.Modifiers(Flags.PROTECTED | Flags.ABSTRACT, annotations);
|
||||
Name name = type.toName(SELF_METHOD);
|
||||
JCExpression returnType = maker.Ident(type.toName(builderGenericName));
|
||||
|
||||
return maker.MethodDef(modifiers, name, returnType, List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), null, null);
|
||||
}
|
||||
|
||||
private JCMethodDecl generateSelfMethod(JavacNode builderImplType) {
|
||||
JavacTreeMaker maker = builderImplType.getTreeMaker();
|
||||
|
||||
JCAnnotation overrideAnnotation = maker.Annotation(genJavaLangTypeRef(builderImplType, "Override"), List.<JCExpression>nil());
|
||||
JCModifiers modifiers = maker.Modifiers(Flags.PROTECTED, List.of(overrideAnnotation));
|
||||
Name name = builderImplType.toName(SELF_METHOD);
|
||||
JCExpression returnType = maker.Ident(builderImplType.toName(builderImplType.getName()));
|
||||
|
||||
JCStatement statement = maker.Return(maker.Ident(builderImplType.toName("this")));
|
||||
JCBlock body = maker.Block(0, List.<JCStatement>of(statement));
|
||||
|
||||
return maker.MethodDef(modifiers, name, returnType, List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null);
|
||||
}
|
||||
|
||||
private JCMethodDecl generateAbstractBuildMethod(JavacNode type, String methodName, boolean override, String classGenericName) {
|
||||
JavacTreeMaker maker = type.getTreeMaker();
|
||||
List<JCAnnotation> annotations = List.nil();
|
||||
if (override) {
|
||||
JCAnnotation overrideAnnotation = maker.Annotation(genJavaLangTypeRef(type, "Override"), List.<JCExpression>nil());
|
||||
annotations = List.of(overrideAnnotation);
|
||||
}
|
||||
JCModifiers modifiers = maker.Modifiers(Flags.PUBLIC | Flags.ABSTRACT, annotations);
|
||||
Name name = type.toName(methodName);
|
||||
JCExpression returnType = maker.Ident(type.toName(classGenericName));
|
||||
|
||||
return maker.MethodDef(modifiers, name, returnType, List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), null, null);
|
||||
}
|
||||
|
||||
private JCMethodDecl generateBuildMethod(String buildName, JCExpression returnType, JavacNode type, List<JCExpression> thrownExceptions) {
|
||||
JavacTreeMaker maker = type.getTreeMaker();
|
||||
|
||||
JCExpression call;
|
||||
ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>();
|
||||
|
||||
// Use a constructor that only has this builder as parameter.
|
||||
List<JCExpression> builderArg = List.<JCExpression>of(maker.Ident(type.toName("this")));
|
||||
call = maker.NewClass(null, List.<JCExpression>nil(), returnType, builderArg, null);
|
||||
statements.append(maker.Return(call));
|
||||
|
||||
JCBlock body = maker.Block(0, statements.toList());
|
||||
|
||||
JCAnnotation overrideAnnotation = maker.Annotation(genJavaLangTypeRef(type, "Override"), List.<JCExpression>nil());
|
||||
JCModifiers modifiers = maker.Modifiers(Flags.PUBLIC, List.of(overrideAnnotation));
|
||||
|
||||
return maker.MethodDef(modifiers, type.toName(buildName), returnType, List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), thrownExceptions, body, null);
|
||||
}
|
||||
|
||||
private JCMethodDecl generateCleanMethod(java.util.List<BuilderFieldData> builderFields, JavacNode type, JCTree source) {
|
||||
JavacTreeMaker maker = type.getTreeMaker();
|
||||
ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>();
|
||||
|
||||
for (BuilderFieldData bfd : builderFields) {
|
||||
if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) {
|
||||
bfd.singularData.getSingularizer().appendCleaningCode(bfd.singularData, type, source, statements);
|
||||
}
|
||||
}
|
||||
|
||||
statements.append(maker.Exec(maker.Assign(maker.Select(maker.Ident(type.toName("this")), type.toName("$lombokUnclean")), maker.Literal(CTC_BOOLEAN, 0))));
|
||||
JCBlock body = maker.Block(0, statements.toList());
|
||||
return maker.MethodDef(maker.Modifiers(Flags.PUBLIC), type.toName("$lombokClean"), maker.Type(Javac.createVoidType(type.getSymbolTable(), CTC_VOID)), List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null);
|
||||
}
|
||||
|
||||
private JCMethodDecl generateDefaultProvider(Name methodName, JavacNode fieldNode, List<JCTypeParameter> params) {
|
||||
JavacTreeMaker maker = fieldNode.getTreeMaker();
|
||||
JCVariableDecl field = (JCVariableDecl) fieldNode.get();
|
||||
|
||||
JCStatement statement = maker.Return(field.init);
|
||||
field.init = null;
|
||||
|
||||
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()), copyTypeParams(fieldNode, params), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null);
|
||||
}
|
||||
|
||||
private void generateBuilderFields(JavacNode builderType, java.util.List<BuilderFieldData> builderFields, JCTree source) {
|
||||
int len = builderFields.size();
|
||||
java.util.List<JavacNode> existing = new ArrayList<JavacNode>();
|
||||
for (JavacNode child : builderType.down()) {
|
||||
if (child.getKind() == Kind.FIELD) {
|
||||
existing.add(child);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = len - 1; i >= 0; i--) {
|
||||
BuilderFieldData bfd = builderFields.get(i);
|
||||
if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) {
|
||||
bfd.createdFields.addAll(bfd.singularData.getSingularizer().generateFields(bfd.singularData, builderType, source));
|
||||
} else {
|
||||
JavacNode field = null, setFlag = null;
|
||||
for (JavacNode exists : existing) {
|
||||
Name n = ((JCVariableDecl) exists.get()).name;
|
||||
if (n.equals(bfd.name)) {
|
||||
field = exists;
|
||||
}
|
||||
if (n.equals(bfd.nameOfSetFlag)) {
|
||||
setFlag = exists;
|
||||
}
|
||||
}
|
||||
JavacTreeMaker maker = builderType.getTreeMaker();
|
||||
if (field == null) {
|
||||
JCModifiers mods = maker.Modifiers(Flags.PRIVATE);
|
||||
JCVariableDecl newField = maker.VarDef(mods, bfd.name, cloneType(maker, bfd.type, source, builderType.getContext()), null);
|
||||
field = injectFieldAndMarkGenerated(builderType, newField);
|
||||
}
|
||||
if (setFlag == null && bfd.nameOfSetFlag != null) {
|
||||
JCModifiers mods = maker.Modifiers(Flags.PRIVATE);
|
||||
JCVariableDecl newField = maker.VarDef(mods, bfd.nameOfSetFlag, maker.TypeIdent(CTC_BOOLEAN), null);
|
||||
injectFieldAndMarkGenerated(builderType, newField);
|
||||
}
|
||||
bfd.createdFields.add(field);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void generateSetterMethodsForBuilder(final JavacNode builderType, BuilderFieldData fieldNode, JavacNode source, final String builderGenericName) {
|
||||
boolean deprecate = isFieldDeprecated(fieldNode.originalFieldNode);
|
||||
final JavacTreeMaker maker = builderType.getTreeMaker();
|
||||
// TODO: Make these lambdas when switching to a source level >= 1.8.
|
||||
Supplier<JCExpression> returnType = new Supplier<JCExpression>() { @Override public JCExpression get() {
|
||||
return maker.Ident(builderType.toName(builderGenericName));
|
||||
}};
|
||||
Supplier<? extends JCReturn> returnStatement = new Supplier<JCReturn>() { @Override public JCReturn get() {
|
||||
return maker.Return(maker.Apply(List.<JCExpression>nil(), maker.Ident(builderType.toName(SELF_METHOD)), List.<JCExpression>nil()));
|
||||
}};
|
||||
if (fieldNode.singularData == null || fieldNode.singularData.getSingularizer() == null) {
|
||||
generateSimpleSetterMethodForBuilder(builderType, deprecate, fieldNode.createdFields.get(0), fieldNode.nameOfSetFlag, source, true, true, returnType.get(), returnStatement.get());
|
||||
} else {
|
||||
fieldNode.singularData.getSingularizer().generateMethods(fieldNode.singularData, deprecate, builderType, source.get(), true, returnType, returnStatement);
|
||||
}
|
||||
}
|
||||
|
||||
private void generateSimpleSetterMethodForBuilder(JavacNode builderType, boolean deprecate, JavacNode fieldNode, Name nameOfSetFlag, JavacNode source, boolean fluent, boolean chain, JCExpression returnType, JCReturn returnStatement) {
|
||||
Name fieldName = ((JCVariableDecl) fieldNode.get()).name;
|
||||
|
||||
for (JavacNode child : builderType.down()) {
|
||||
if (child.getKind() != Kind.METHOD) {
|
||||
continue;
|
||||
}
|
||||
JCMethodDecl methodDecl = (JCMethodDecl) child.get();
|
||||
Name existingName = methodDecl.name;
|
||||
if (existingName.equals(fieldName) && !isTolerate(fieldNode, methodDecl)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
String setterName = fluent ? fieldNode.getName() : HandlerUtil.buildAccessorName("set", fieldNode.getName());
|
||||
|
||||
JavacTreeMaker maker = fieldNode.getTreeMaker();
|
||||
|
||||
JCMethodDecl newMethod = HandleSetter.createSetter(Flags.PUBLIC, deprecate, fieldNode, maker, setterName, nameOfSetFlag, returnType, returnStatement, source, List.<JCAnnotation>nil(), List.<JCAnnotation>nil());
|
||||
|
||||
injectMethod(builderType, newMethod);
|
||||
}
|
||||
|
||||
private void addObtainVia(BuilderFieldData bfd, JavacNode node) {
|
||||
for (JavacNode child : node.down()) {
|
||||
if (!annotationTypeMatches(ObtainVia.class, child)) continue;
|
||||
if (!annotationTypeMatches(ObtainVia.class, child)) {
|
||||
continue;
|
||||
}
|
||||
AnnotationValues<ObtainVia> ann = createAnnotation(ObtainVia.class, child);
|
||||
bfd.obtainVia = ann.getInstance();
|
||||
bfd.obtainViaNode = child;
|
||||
@@ -673,16 +677,18 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the explicitly requested singular annotation on this node (field
|
||||
* or parameter), or null if there's no {@code @Singular} annotation on it.
|
||||
*
|
||||
*
|
||||
* @param node The node (field or method param) to inspect for its name and potential {@code @Singular} annotation.
|
||||
*/
|
||||
private SingularData getSingularData(JavacNode node) {
|
||||
for (JavacNode child : node.down()) {
|
||||
if (!annotationTypeMatches(Singular.class, child)) continue;
|
||||
if (!annotationTypeMatches(Singular.class, child)) {
|
||||
continue;
|
||||
}
|
||||
Name pluralName = node.getKind() == Kind.FIELD ? removePrefixFromField(node) : ((JCVariableDecl) node.get()).name;
|
||||
AnnotationValues<Singular> ann = createAnnotation(Singular.class, child);
|
||||
deleteAnnotationIfNeccessary(child, Singular.class);
|
||||
@@ -700,31 +706,67 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
|
||||
}
|
||||
}
|
||||
Name singularName = node.toName(explicitSingular);
|
||||
|
||||
|
||||
JCExpression type = null;
|
||||
if (node.get() instanceof JCVariableDecl) {
|
||||
type = ((JCVariableDecl) node.get()).vartype;
|
||||
}
|
||||
|
||||
|
||||
String name = null;
|
||||
List<JCExpression> typeArgs = List.nil();
|
||||
if (type instanceof JCTypeApply) {
|
||||
typeArgs = ((JCTypeApply) type).arguments;
|
||||
type = ((JCTypeApply) type).clazz;
|
||||
}
|
||||
|
||||
|
||||
name = type.toString();
|
||||
|
||||
|
||||
String targetFqn = JavacSingularsRecipes.get().toQualified(name);
|
||||
JavacSingularizer singularizer = JavacSingularsRecipes.get().getSingularizer(targetFqn);
|
||||
if (singularizer == null) {
|
||||
node.addError("Lombok does not know how to create the singular-form builder methods for type '" + name + "'; they won't be generated.");
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
return new SingularData(child, singularName, pluralName, typeArgs, targetFqn, singularizer);
|
||||
}
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private String generateNonclashingNameFor(String classGenericName, java.util.List<String> typeParamStrings) {
|
||||
if (!typeParamStrings.contains(classGenericName)) {
|
||||
return classGenericName;
|
||||
}
|
||||
int counter = 2;
|
||||
while (typeParamStrings.contains(classGenericName + counter)) {
|
||||
counter++;
|
||||
}
|
||||
return classGenericName + counter;
|
||||
}
|
||||
|
||||
private JavacNode findInnerClass(JavacNode parent, String name) {
|
||||
for (JavacNode child : parent.down()) {
|
||||
if (child.getKind() != Kind.TYPE) {
|
||||
continue;
|
||||
}
|
||||
JCClassDecl td = (JCClassDecl) child.get();
|
||||
if (td.name.contentEquals(name)) {
|
||||
return child;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private ListBuffer<JCExpression> getTypeParamExpressions(List<? extends JCTree> typeParams, JavacTreeMaker maker) {
|
||||
ListBuffer<JCExpression> typeParamsForBuilderParameter = new ListBuffer<JCExpression>();
|
||||
for (JCTree typeParam : typeParams) {
|
||||
if (typeParam instanceof JCTypeParameter) {
|
||||
typeParamsForBuilderParameter.add(maker.Ident(((JCTypeParameter)typeParam).getName()));
|
||||
} else if (typeParam instanceof JCIdent) {
|
||||
typeParamsForBuilderParameter.add(maker.Ident(((JCIdent)typeParam).getName()));
|
||||
}
|
||||
}
|
||||
return typeParamsForBuilderParameter;
|
||||
}
|
||||
}
|
||||
@@ -5,22 +5,6 @@ public class SuperBuilderBasic {
|
||||
int field1;
|
||||
List<String> items;
|
||||
@java.lang.SuppressWarnings("all")
|
||||
protected Parent(final ParentBuilder<?, ?> b) {
|
||||
this.field1 = b.field1;
|
||||
java.util.List<String> items;
|
||||
switch (b.items == null ? 0 : b.items.size()) {
|
||||
case 0:
|
||||
items = java.util.Collections.emptyList();
|
||||
break;
|
||||
case 1:
|
||||
items = java.util.Collections.singletonList(b.items.get(0));
|
||||
break;
|
||||
default:
|
||||
items = java.util.Collections.unmodifiableList(new java.util.ArrayList<String>(b.items));
|
||||
}
|
||||
this.items = items;
|
||||
}
|
||||
@java.lang.SuppressWarnings("all")
|
||||
public static abstract class ParentBuilder<C extends Parent, B extends ParentBuilder<C, B>> {
|
||||
@java.lang.SuppressWarnings("all")
|
||||
private int field1;
|
||||
@@ -75,6 +59,22 @@ public class SuperBuilderBasic {
|
||||
}
|
||||
}
|
||||
@java.lang.SuppressWarnings("all")
|
||||
protected Parent(final ParentBuilder<?, ?> b) {
|
||||
this.field1 = b.field1;
|
||||
java.util.List<String> items;
|
||||
switch (b.items == null ? 0 : b.items.size()) {
|
||||
case 0:
|
||||
items = java.util.Collections.emptyList();
|
||||
break;
|
||||
case 1:
|
||||
items = java.util.Collections.singletonList(b.items.get(0));
|
||||
break;
|
||||
default:
|
||||
items = java.util.Collections.unmodifiableList(new java.util.ArrayList<String>(b.items));
|
||||
}
|
||||
this.items = items;
|
||||
}
|
||||
@java.lang.SuppressWarnings("all")
|
||||
public static ParentBuilder<?, ?> builder() {
|
||||
return new ParentBuilderImpl();
|
||||
}
|
||||
@@ -83,11 +83,6 @@ public class SuperBuilderBasic {
|
||||
public static class Child extends Parent {
|
||||
double field3;
|
||||
@java.lang.SuppressWarnings("all")
|
||||
protected Child(final ChildBuilder<?, ?> b) {
|
||||
super(b);
|
||||
this.field3 = b.field3;
|
||||
}
|
||||
@java.lang.SuppressWarnings("all")
|
||||
public static abstract class ChildBuilder<C extends Child, B extends ChildBuilder<C, B>> extends Parent.ParentBuilder<C, B> {
|
||||
@java.lang.SuppressWarnings("all")
|
||||
private double field3;
|
||||
@@ -125,6 +120,11 @@ public class SuperBuilderBasic {
|
||||
}
|
||||
}
|
||||
@java.lang.SuppressWarnings("all")
|
||||
protected Child(final ChildBuilder<?, ?> b) {
|
||||
super(b);
|
||||
this.field3 = b.field3;
|
||||
}
|
||||
@java.lang.SuppressWarnings("all")
|
||||
public static ChildBuilder<?, ?> builder() {
|
||||
return new ChildBuilderImpl();
|
||||
}
|
||||
|
||||
@@ -5,22 +5,6 @@ public class SuperBuilderWithGenerics {
|
||||
A field1;
|
||||
List<String> items;
|
||||
@java.lang.SuppressWarnings("all")
|
||||
protected Parent(final ParentBuilder<A, ?, ?> b) {
|
||||
this.field1 = b.field1;
|
||||
java.util.List<String> items;
|
||||
switch (b.items == null ? 0 : b.items.size()) {
|
||||
case 0:
|
||||
items = java.util.Collections.emptyList();
|
||||
break;
|
||||
case 1:
|
||||
items = java.util.Collections.singletonList(b.items.get(0));
|
||||
break;
|
||||
default:
|
||||
items = java.util.Collections.unmodifiableList(new java.util.ArrayList<String>(b.items));
|
||||
}
|
||||
this.items = items;
|
||||
}
|
||||
@java.lang.SuppressWarnings("all")
|
||||
public static abstract class ParentBuilder<A, C extends Parent<A>, B extends ParentBuilder<A, C, B>> {
|
||||
@java.lang.SuppressWarnings("all")
|
||||
private A field1;
|
||||
@@ -75,6 +59,22 @@ public class SuperBuilderWithGenerics {
|
||||
}
|
||||
}
|
||||
@java.lang.SuppressWarnings("all")
|
||||
protected Parent(final ParentBuilder<A, ?, ?> b) {
|
||||
this.field1 = b.field1;
|
||||
java.util.List<String> items;
|
||||
switch (b.items == null ? 0 : b.items.size()) {
|
||||
case 0:
|
||||
items = java.util.Collections.emptyList();
|
||||
break;
|
||||
case 1:
|
||||
items = java.util.Collections.singletonList(b.items.get(0));
|
||||
break;
|
||||
default:
|
||||
items = java.util.Collections.unmodifiableList(new java.util.ArrayList<String>(b.items));
|
||||
}
|
||||
this.items = items;
|
||||
}
|
||||
@java.lang.SuppressWarnings("all")
|
||||
public static <A> ParentBuilder<A, ?, ?> builder() {
|
||||
return new ParentBuilderImpl<A>();
|
||||
}
|
||||
@@ -83,11 +83,6 @@ public class SuperBuilderWithGenerics {
|
||||
public static class Child<A> extends Parent<A> {
|
||||
double field3;
|
||||
@java.lang.SuppressWarnings("all")
|
||||
protected Child(final ChildBuilder<A, ?, ?> b) {
|
||||
super(b);
|
||||
this.field3 = b.field3;
|
||||
}
|
||||
@java.lang.SuppressWarnings("all")
|
||||
public static abstract class ChildBuilder<A, C extends Child<A>, B extends ChildBuilder<A, C, B>> extends Parent.ParentBuilder<A, C, B> {
|
||||
@java.lang.SuppressWarnings("all")
|
||||
private double field3;
|
||||
@@ -125,6 +120,11 @@ public class SuperBuilderWithGenerics {
|
||||
}
|
||||
}
|
||||
@java.lang.SuppressWarnings("all")
|
||||
protected Child(final ChildBuilder<A, ?, ?> b) {
|
||||
super(b);
|
||||
this.field3 = b.field3;
|
||||
}
|
||||
@java.lang.SuppressWarnings("all")
|
||||
public static <A> ChildBuilder<A, ?, ?> builder() {
|
||||
return new ChildBuilderImpl<A>();
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user