mirror of
https://github.com/tiennm99/lombok.git
synced 2026-10-13 20:15:09 +00:00
generics for the Builder class; generate abstract methods
This commit is contained in:
1 parent
aef9cdc392
commit
0ffbd3eec7
2 files changed
+87
-37
No files matched your search
@@ -21,23 +21,14 @@
|
||||
*/
|
||||
package lombok.javac.handlers;
|
||||
|
||||
import static lombok.javac.Javac.*;
|
||||
import static lombok.core.handlers.HandlerUtil.*;
|
||||
import static lombok.javac.Javac.*;
|
||||
import static lombok.javac.handlers.JavacHandlerUtil.*;
|
||||
import static lombok.javac.handlers.JavacHandlerUtil.toAllSetterNames;
|
||||
import static lombok.javac.handlers.JavacHandlerUtil.toSetterName;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.ConfigurationKeys;
|
||||
import lombok.Setter;
|
||||
import lombok.core.AST.Kind;
|
||||
import lombok.core.AnnotationValues;
|
||||
import lombok.javac.Javac;
|
||||
import lombok.javac.JavacAnnotationHandler;
|
||||
import lombok.javac.JavacNode;
|
||||
import lombok.javac.JavacTreeMaker;
|
||||
import lombok.javac.handlers.JavacHandlerUtil.FieldAccess;
|
||||
|
||||
import org.mangosdk.spi.ProviderFor;
|
||||
|
||||
import com.sun.tools.javac.code.Flags;
|
||||
@@ -57,6 +48,18 @@ import com.sun.tools.javac.util.List;
|
||||
import com.sun.tools.javac.util.ListBuffer;
|
||||
import com.sun.tools.javac.util.Name;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.ConfigurationKeys;
|
||||
import lombok.Setter;
|
||||
import lombok.core.AST.Kind;
|
||||
import lombok.core.AnnotationValues;
|
||||
import lombok.javac.Javac;
|
||||
import lombok.javac.JavacAnnotationHandler;
|
||||
import lombok.javac.JavacNode;
|
||||
import lombok.javac.JavacTreeMaker;
|
||||
import lombok.javac.handlers.JavacHandlerUtil.CopyJavadoc;
|
||||
import lombok.javac.handlers.JavacHandlerUtil.FieldAccess;
|
||||
|
||||
/**
|
||||
* Handles the {@code lombok.Setter} annotation for javac.
|
||||
*/
|
||||
@@ -210,6 +213,12 @@ public class HandleSetter extends JavacAnnotationHandler<Setter> {
|
||||
}
|
||||
|
||||
public static JCMethodDecl createSetter(long access, boolean deprecate, JavacNode field, JavacTreeMaker treeMaker, String setterName, Name booleanFieldToSet, boolean shouldReturnThis, JavacNode source, List<JCAnnotation> onMethod, List<JCAnnotation> onParam) {
|
||||
JCExpression returnType = cloneSelfType(field);
|
||||
JCReturn returnStatement = treeMaker.Return(treeMaker.Ident(field.toName("this")));
|
||||
return createSetter(access, deprecate, field, treeMaker, setterName, booleanFieldToSet, returnType, returnStatement, source, onMethod, onParam);
|
||||
}
|
||||
|
||||
public static JCMethodDecl createSetter(long access, boolean deprecate, JavacNode field, JavacTreeMaker treeMaker, String setterName, Name booleanFieldToSet, JCExpression methodType, JCReturn returnStatement, JavacNode source, List<JCAnnotation> onMethod, List<JCAnnotation> onParam) {
|
||||
if (setterName == null) return null;
|
||||
|
||||
JCVariableDecl fieldDecl = (JCVariableDecl) field.get();
|
||||
@@ -240,19 +249,13 @@ public class HandleSetter extends JavacAnnotationHandler<Setter> {
|
||||
statements.append(treeMaker.Exec(setBool));
|
||||
}
|
||||
|
||||
JCExpression methodType = null;
|
||||
if (shouldReturnThis) {
|
||||
methodType = cloneSelfType(field);
|
||||
}
|
||||
|
||||
if (methodType == null) {
|
||||
//WARNING: Do not use field.getSymbolTable().voidType - that field has gone through non-backwards compatible API changes within javac1.6.
|
||||
methodType = treeMaker.Type(Javac.createVoidType(field.getSymbolTable(), CTC_VOID));
|
||||
shouldReturnThis = false;
|
||||
returnStatement = null;
|
||||
}
|
||||
|
||||
if (shouldReturnThis) {
|
||||
JCReturn returnStatement = treeMaker.Return(treeMaker.Ident(field.toName("this")));
|
||||
if (returnStatement != null) {
|
||||
statements.append(returnStatement);
|
||||
}
|
||||
|
||||
|
||||
@@ -36,9 +36,11 @@ import com.sun.tools.javac.tree.JCTree.JCBlock;
|
||||
import com.sun.tools.javac.tree.JCTree.JCClassDecl;
|
||||
import com.sun.tools.javac.tree.JCTree.JCExpression;
|
||||
import com.sun.tools.javac.tree.JCTree.JCFieldAccess;
|
||||
import com.sun.tools.javac.tree.JCTree.JCIdent;
|
||||
import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
|
||||
import com.sun.tools.javac.tree.JCTree.JCMethodInvocation;
|
||||
import com.sun.tools.javac.tree.JCTree.JCModifiers;
|
||||
import com.sun.tools.javac.tree.JCTree.JCReturn;
|
||||
import com.sun.tools.javac.tree.JCTree.JCStatement;
|
||||
import com.sun.tools.javac.tree.JCTree.JCTypeApply;
|
||||
import com.sun.tools.javac.tree.JCTree.JCTypeParameter;
|
||||
@@ -188,15 +190,15 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
|
||||
// Create the abstract builder class.
|
||||
JavacNode builderType = findInnerClass(tdParent, builderClassName);
|
||||
if (builderType == null) {
|
||||
builderType = makeBuilderClass(true, true, annotationNode, tdParent, builderClassName, useInheritanceOnBuilder ? superclassBuilderClassName : null, typeParams, ast);
|
||||
builderType = makeBuilderClass(annotationNode, tdParent, builderClassName, useInheritanceOnBuilder ? superclassBuilderClassName : null, typeParams, ast);
|
||||
} else {
|
||||
annotationNode.addError("@SuperBuilder does not support customized builders. Use @Builder instead.");
|
||||
}
|
||||
|
||||
|
||||
// Create the builder implementation class.
|
||||
JavacNode builderImplType = findInnerClass(tdParent, builderImplClassName);
|
||||
if (builderImplType == null) {
|
||||
builderImplType = makeBuilderClass(false, false, annotationNode, tdParent, builderImplClassName, builderClassName, typeParams, ast);
|
||||
builderImplType = makeBuilderImplClass(annotationNode, tdParent, builderImplClassName, builderClassName, typeParams, ast);
|
||||
} else {
|
||||
annotationNode.addError("@SuperBuilder does not support customized builders. Use @Builder instead.");
|
||||
}
|
||||
@@ -232,7 +234,11 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
|
||||
// Create a simple constructor for the builder class.
|
||||
JCMethodDecl cd = HandleConstructor.createConstructor(AccessLevel.PRIVATE, List.<JCAnnotation>nil(), builderImplType, List.<JavacNode>nil(), false, annotationNode);
|
||||
if (cd != null) injectMethod(builderImplType, cd);
|
||||
|
||||
|
||||
// Generate abstract getInstance() and build() methods.
|
||||
injectMethod(builderType, generateAbstractGetInstanceMethod(tdParent));
|
||||
injectMethod(builderType, generateAbstractBuildMethod(tdParent, builderMethodName));
|
||||
|
||||
// Create the setter methods in the abstract builder.
|
||||
for (BuilderFieldData bfd : builderFields) {
|
||||
makeSetterMethodsForBuilder(builderType, bfd, annotationNode);
|
||||
@@ -420,6 +426,24 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
|
||||
return maker.MethodDef(maker.Modifiers(Flags.PUBLIC), type.toName(toBuilderMethodName), namePlusTypeParamsToTypeReference(maker, type.toName(builderClassName), typeParams), List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null);
|
||||
}
|
||||
|
||||
private JCMethodDecl generateAbstractGetInstanceMethod(JavacNode type) {
|
||||
JavacTreeMaker maker = type.getTreeMaker();
|
||||
JCModifiers modifiers = maker.Modifiers(Flags.PUBLIC | Flags.ABSTRACT);
|
||||
Name name = type.toName("getInstance");
|
||||
JCExpression returnType = maker.Ident(type.toName("B"));
|
||||
|
||||
return maker.MethodDef(modifiers, name, returnType, List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), null, null);
|
||||
}
|
||||
|
||||
private JCMethodDecl generateAbstractBuildMethod(JavacNode type, String methodName) {
|
||||
JavacTreeMaker maker = type.getTreeMaker();
|
||||
JCModifiers modifiers = maker.Modifiers(Flags.PUBLIC | Flags.ABSTRACT);
|
||||
Name name = type.toName(methodName);
|
||||
JCExpression returnType = maker.Ident(type.toName("C"));
|
||||
|
||||
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>();
|
||||
@@ -549,7 +573,10 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
|
||||
|
||||
JavacTreeMaker maker = fieldNode.getTreeMaker();
|
||||
|
||||
JCMethodDecl newMethod = HandleSetter.createSetter(Flags.PUBLIC, deprecate, fieldNode, maker, setterName, nameOfSetFlag, chain, source, List.<JCAnnotation>nil(), List.<JCAnnotation>nil());
|
||||
JCExpression returnType = maker.Ident(builderType.toName("B"));
|
||||
JCReturn returnStatement = maker.Return(maker.Ident(builderType.toName("this")));
|
||||
|
||||
JCMethodDecl newMethod = HandleSetter.createSetter(Flags.PUBLIC, deprecate, fieldNode, maker, setterName, nameOfSetFlag, returnType, returnStatement, source, List.<JCAnnotation>nil(), List.<JCAnnotation>nil());
|
||||
|
||||
injectMethod(builderType, newMethod);
|
||||
}
|
||||
@@ -563,22 +590,42 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
|
||||
return null;
|
||||
}
|
||||
|
||||
public JavacNode makeBuilderClass(boolean isAbstract, boolean isPublic, JavacNode source, JavacNode tdParent, String builderClassName, String parentBuilderClassName, List<JCTypeParameter> typeParams, JCAnnotation ast) {
|
||||
public JavacNode makeBuilderClass(JavacNode source, JavacNode tdParent, String builderClass, String parentBuilderClass, List<JCTypeParameter> typeParams, JCAnnotation ast) {
|
||||
JavacTreeMaker maker = tdParent.getTreeMaker();
|
||||
int modifiers = Flags.STATIC;
|
||||
if (isAbstract) modifiers |= Flags.ABSTRACT;
|
||||
if (isPublic) {
|
||||
modifiers |= Flags.PUBLIC;
|
||||
} else {
|
||||
modifiers |= Flags.PRIVATE;
|
||||
}
|
||||
JCModifiers mods = maker.Modifiers(modifiers);
|
||||
JCModifiers mods = maker.Modifiers(Flags.STATIC | Flags.ABSTRACT | Flags.PUBLIC);
|
||||
|
||||
JCExpression extending = null;
|
||||
if (parentBuilderClassName != null) {
|
||||
extending = maker.Ident(tdParent.toName(parentBuilderClassName));
|
||||
if (parentBuilderClass != null) {
|
||||
extending = maker.Ident(tdParent.toName(parentBuilderClass));
|
||||
}
|
||||
JCClassDecl builder = maker.ClassDef(mods, tdParent.toName(builderClassName), copyTypeParams(source, typeParams), extending, List.<JCExpression>nil(), List.<JCTree>nil());
|
||||
|
||||
// Keep any type params of the annotated class.
|
||||
// TODO: Prevent name clashes with type params from annotated class.
|
||||
ListBuffer<JCTypeParameter> allTypeParams = new ListBuffer<JCTypeParameter>();
|
||||
allTypeParams.addAll(copyTypeParams(source, typeParams));
|
||||
// Add builder-specific type params required for inheritable builders.
|
||||
// 1. The return type for the build() method, named "C", which extends the annotated class.
|
||||
JCIdent annotatedClass = maker.Ident(tdParent.toName(tdParent.getName()));
|
||||
allTypeParams.add(maker.TypeParameter(tdParent.toName("C"), List.<JCExpression>of(annotatedClass)));
|
||||
// 2. The return type for all setter methods, named "B", which extends this builder class.
|
||||
Name builderClassName = tdParent.toName(builderClass);
|
||||
JCTypeApply typeApply = maker.TypeApply(maker.Ident(builderClassName),
|
||||
List.<JCExpression>of(maker.Ident(tdParent.toName("C")), maker.Ident(tdParent.toName("B"))));
|
||||
allTypeParams.add(maker.TypeParameter(tdParent.toName("B"), List.<JCExpression>of(typeApply)));
|
||||
|
||||
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 builderImplClassName, String builderClassName, List<JCTypeParameter> typeParams, JCAnnotation ast) {
|
||||
JavacTreeMaker maker = tdParent.getTreeMaker();
|
||||
JCModifiers mods = maker.Modifiers(Flags.STATIC | Flags.PRIVATE);
|
||||
|
||||
JCExpression extending = null;
|
||||
if (builderClassName != null) {
|
||||
extending = maker.Ident(tdParent.toName(builderClassName));
|
||||
}
|
||||
JCClassDecl builder = maker.ClassDef(mods, tdParent.toName(builderImplClassName), copyTypeParams(source, typeParams), extending, List.<JCExpression>nil(), List.<JCTree>nil());
|
||||
return injectType(tdParent, builder);
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user