apply generics on builder extends clause; fixed builder name generation

This commit is contained in:
Jan Rieke committed 2018-04-10 20:31:39 +02:00
1 parent e9929b100c
commit 8acc37011f
1 file changed
+36 -26
@@ -163,7 +163,14 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
String builderClassName = td.name.toString() + "Builder";
String builderImplClassName = builderClassName + "Impl";
JCTree extendsClause = Javac.getExtendsClause(td);
String superclassBuilderClassName= extendsClause + "Builder";
String superclassBuilderClassName = null;
if (extendsClause instanceof JCFieldAccess) {
// The extends clause consists of a fully-qualified name.
superclassBuilderClassName = ((JCFieldAccess)extendsClause).getIdentifier() + "Builder";
} else {
// A simple class name is used in the extends clause.
superclassBuilderClassName = extendsClause + "Builder";
}
boolean useInheritanceOnBuilder = extendsClause != null;
generateBuilderBasedConstructor(tdParent, builderFields, annotationNode, builderClassName, useInheritanceOnBuilder);
@@ -181,15 +188,6 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
return;
}
// Create the builder implementation class.
JavacNode builderImplType = findInnerClass(tdParent, builderImplClassName);
if (builderImplType == null) {
builderImplType = makeBuilderImplClass(annotationNode, tdParent, builderImplClassName, builderClassName, typeParams, ast);
} else {
annotationNode.addError("@SuperBuilder does not support customized builders. Use @Builder instead.");
return;
}
// Check that all builder fields for @Singular and @ObtainVia.
for (BuilderFieldData bfd : builderFields) {
if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) {
@@ -210,7 +208,7 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
}
}
// Generate the fields in the builder class that hold the values for the instance.
// 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();
@@ -218,11 +216,7 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
injectFieldAndMarkGenerated(builderType, uncleanField);
}
// 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 self() and build() methods.
// Generate abstract self() and build() methods in the abstract builder.
injectMethod(builderType, generateAbstractSelfMethod(tdParent));
injectMethod(builderType, generateAbstractBuildMethod(tdParent, buildMethodName));
@@ -231,10 +225,6 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
makeSetterMethodsForBuilder(builderType, bfd, annotationNode);
}
// Create the self() and build() methods in the BuilderImpl.
injectMethod(builderImplType, generateSelfMethod(builderImplType));
injectMethod(builderImplType, generateBuildMethod(tdParent, buildMethodName, returnType, builderImplType, thrownExceptions, ast));
// Create the toString() method for the abstract builder.
if (methodExists("toString", builderType, 0) == MemberExistsResult.NOT_EXISTS) {
java.util.List<JavacNode> fieldNodes = new ArrayList<JavacNode>();
@@ -247,6 +237,23 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
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);
} else {
annotationNode.addError("@SuperBuilder does not support customized builders. Use @Builder instead.");
return;
}
// 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);
// Create the self() and build() methods in the BuilderImpl.
injectMethod(builderImplType, generateSelfMethod(builderImplType));
injectMethod(builderImplType, generateBuildMethod(tdParent, buildMethodName, returnType, builderImplType, thrownExceptions, ast));
// Add the builder() method to the annotated class.
if (methodExists(builderMethodName, tdParent, -1) == MemberExistsResult.NOT_EXISTS) {
JCMethodDecl md = generateBuilderMethod(builderMethodName, builderClassName, builderImplClassName, annotationNode, tdParent, typeParams);
@@ -516,12 +523,7 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
public JavacNode makeBuilderClass(JavacNode source, JavacNode tdParent, String builderClass, String parentBuilderClass, List<JCTypeParameter> typeParams, JCAnnotation ast) {
JavacTreeMaker maker = tdParent.getTreeMaker();
JCModifiers mods = maker.Modifiers(Flags.STATIC | Flags.ABSTRACT | Flags.PUBLIC);
JCExpression extending = null;
if (parentBuilderClass != null) {
extending = maker.Ident(tdParent.toName(parentBuilderClass));
}
// Keep any type params of the annotated class.
// TODO: Prevent name clashes with type params from annotated class.
ListBuffer<JCTypeParameter> allTypeParams = new ListBuffer<JCTypeParameter>();
@@ -535,6 +537,14 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
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)));
JCExpression extending = null;
if (parentBuilderClass != null) {
// If the annotated class extends another class, we want this builder to extend the builder of the superclass.
extending = maker.TypeApply(maker.Ident(tdParent.toName(parentBuilderClass)),
List.<JCExpression>of(maker.Ident(tdParent.toName("C")), maker.Ident(tdParent.toName("B"))));
// TODO: type params from annotated class
}
JCClassDecl builder = maker.ClassDef(mods, builderClassName, allTypeParams.toList(), extending, List.<JCExpression>nil(), List.<JCTree>nil());
return injectType(tdParent, builder);