mirror of
https://github.com/tiennm99/lombok.git
synced 2026-10-19 20:15:21 +00:00
Merge branch 'feature/builder-setter-prefixes' of git://github.com/floralvikings/lombok into floralvikings-feature/builder-setter-prefixes
This commit is contained in:
81 files changed
+4507
-150
No files matched your search
@@ -153,6 +153,19 @@ public @interface Builder {
|
||||
* @return The builder class will be generated with this access modifier.
|
||||
*/
|
||||
AccessLevel access() default lombok.AccessLevel.PUBLIC;
|
||||
|
||||
/**
|
||||
* Prefix to prepend to set methods in the generated builder class. By default, generated methods to not include a
|
||||
* prefix. If this value populated, the first letter of the generated method name will be capitalized.
|
||||
*
|
||||
* For example, a method normally generated as {@code someField(String someField)} would instead be generated as {@code withSomeField(String someField)}
|
||||
*
|
||||
* Note that using "with" to prefix builder setter methods is strongly discouraged as as "with" normally
|
||||
* suggests immutable data structures, and builders by definition are mutable objects.
|
||||
*
|
||||
* @return The prefix to prepend to generated method names.
|
||||
*/
|
||||
String setterPrefix() default "";
|
||||
|
||||
/**
|
||||
* Put on a field (in case of {@code @Builder} on a type) or a parameter (for {@code @Builder} on a constructor or static method) to
|
||||
|
||||
@@ -122,6 +122,7 @@ public class EclipseSingularsRecipes {
|
||||
private final EclipseNode annotation;
|
||||
private final char[] singularName;
|
||||
private final char[] pluralName;
|
||||
private final char[] setterPrefix;
|
||||
private final List<TypeReference> typeArgs;
|
||||
private final String targetFqn;
|
||||
private final EclipseSingularizer singularizer;
|
||||
@@ -135,8 +136,20 @@ public class EclipseSingularsRecipes {
|
||||
this.targetFqn = targetFqn;
|
||||
this.singularizer = singularizer;
|
||||
this.source = source;
|
||||
this.setterPrefix = new char[0];
|
||||
}
|
||||
|
||||
|
||||
public SingularData(EclipseNode annotation, char[] singularName, char[] pluralName, List<TypeReference> typeArgs, String targetFqn, EclipseSingularizer singularizer, ASTNode source, char[] setterPrefix) {
|
||||
this.annotation = annotation;
|
||||
this.singularName = singularName;
|
||||
this.pluralName = pluralName;
|
||||
this.typeArgs = typeArgs;
|
||||
this.targetFqn = targetFqn;
|
||||
this.singularizer = singularizer;
|
||||
this.source = source;
|
||||
this.setterPrefix = setterPrefix;
|
||||
}
|
||||
|
||||
public void setGeneratedByRecursive(ASTNode target) {
|
||||
SetGeneratedByVisitor visitor = new SetGeneratedByVisitor(source);
|
||||
|
||||
@@ -164,7 +177,11 @@ public class EclipseSingularsRecipes {
|
||||
public char[] getPluralName() {
|
||||
return pluralName;
|
||||
}
|
||||
|
||||
|
||||
public char[] getSetterPrefix() {
|
||||
return setterPrefix;
|
||||
}
|
||||
|
||||
public List<TypeReference> getTypeArgs() {
|
||||
return typeArgs;
|
||||
}
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2013-2019 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
|
||||
@@ -101,17 +101,17 @@ import lombok.experimental.NonFinal;
|
||||
@HandlerPriority(-1024) //-2^10; to ensure we've picked up @FieldDefault's changes (-2048) but @Value hasn't removed itself yet (-512), so that we can error on presence of it on the builder classes.
|
||||
public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
|
||||
private HandleConstructor handleConstructor = new HandleConstructor();
|
||||
|
||||
|
||||
private static final char[] CLEAN_FIELD_NAME = "$lombokUnclean".toCharArray();
|
||||
private static final char[] CLEAN_METHOD_NAME = "$lombokClean".toCharArray();
|
||||
|
||||
|
||||
private static final boolean toBoolean(Object expr, boolean defaultValue) {
|
||||
if (expr == null) return defaultValue;
|
||||
if (expr instanceof FalseLiteral) return false;
|
||||
if (expr instanceof TrueLiteral) return true;
|
||||
return ((Boolean) expr).booleanValue();
|
||||
}
|
||||
|
||||
|
||||
static class BuilderFieldData {
|
||||
Annotation[] annotations;
|
||||
TypeReference type;
|
||||
@@ -124,10 +124,10 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
|
||||
ObtainVia obtainVia;
|
||||
EclipseNode obtainViaNode;
|
||||
EclipseNode originalFieldNode;
|
||||
|
||||
|
||||
List<EclipseNode> createdFields = new ArrayList<EclipseNode>();
|
||||
}
|
||||
|
||||
|
||||
private static boolean equals(String a, char[] b) {
|
||||
if (a.length() != b.length) return false;
|
||||
for (int i = 0; i < b.length; i++) {
|
||||
@@ -135,7 +135,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private static boolean equals(String a, char[][] b) {
|
||||
if (a == null || a.isEmpty()) return b.length == 0;
|
||||
String[] aParts = a.split("\\.");
|
||||
@@ -145,24 +145,24 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private static final char[] DEFAULT_PREFIX = {'$', 'd', 'e', 'f', 'a', 'u', 'l', 't', '$'};
|
||||
private static final char[] SET_PREFIX = {'$', 's', 'e', 't'};
|
||||
private static final char[] VALUE_PREFIX = {'$', 'v', 'a', 'l', 'u', 'e'};
|
||||
|
||||
|
||||
private static final char[] prefixWith(char[] prefix, char[] name) {
|
||||
char[] out = new char[prefix.length + name.length];
|
||||
System.arraycopy(prefix, 0, out, 0, prefix.length);
|
||||
System.arraycopy(name, 0, out, prefix.length, name.length);
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
@Override public void handle(AnnotationValues<Builder> annotation, Annotation ast, EclipseNode annotationNode) {
|
||||
handleFlagUsage(annotationNode, ConfigurationKeys.BUILDER_FLAG_USAGE, "@Builder");
|
||||
CheckerFrameworkVersion cfv = getCheckerFrameworkVersion(annotationNode);
|
||||
|
||||
|
||||
long p = (long) ast.sourceStart << 32 | ast.sourceEnd;
|
||||
|
||||
|
||||
Builder builderInstance = annotation.getInstance();
|
||||
AccessLevel accessForOuters = builderInstance.access();
|
||||
if (accessForOuters == null) accessForOuters = AccessLevel.PUBLIC;
|
||||
@@ -171,22 +171,22 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
|
||||
accessForOuters = AccessLevel.PUBLIC;
|
||||
}
|
||||
AccessLevel accessForInners = accessForOuters == AccessLevel.PROTECTED ? AccessLevel.PUBLIC : accessForOuters;
|
||||
|
||||
|
||||
// These exist just to support the 'old' lombok.experimental.Builder, which had these properties. lombok.Builder no longer has them.
|
||||
boolean fluent = toBoolean(annotation.getActualExpression("fluent"), true);
|
||||
boolean chain = toBoolean(annotation.getActualExpression("chain"), true);
|
||||
|
||||
|
||||
String builderMethodName = builderInstance.builderMethodName();
|
||||
String buildMethodName = builderInstance.buildMethodName();
|
||||
String builderClassName = builderInstance.builderClassName();
|
||||
String toBuilderMethodName = "toBuilder";
|
||||
boolean toBuilder = builderInstance.toBuilder();
|
||||
List<char[]> typeArgsForToBuilder = null;
|
||||
|
||||
|
||||
if (builderMethodName == null) builderMethodName = "builder";
|
||||
if (buildMethodName == null) buildMethodName = "build";
|
||||
if (builderClassName == null) builderClassName = "";
|
||||
|
||||
|
||||
boolean generateBuilderMethod;
|
||||
if (builderMethodName.isEmpty()) {
|
||||
generateBuilderMethod = false;
|
||||
@@ -195,74 +195,74 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
|
||||
} else {
|
||||
generateBuilderMethod = true;
|
||||
}
|
||||
|
||||
|
||||
if (!checkName("buildMethodName", buildMethodName, annotationNode)) return;
|
||||
if (!builderClassName.isEmpty()) {
|
||||
if (!checkName("builderClassName", builderClassName, annotationNode)) return;
|
||||
}
|
||||
|
||||
|
||||
EclipseNode parent = annotationNode.up();
|
||||
|
||||
|
||||
List<BuilderFieldData> builderFields = new ArrayList<BuilderFieldData>();
|
||||
TypeReference returnType;
|
||||
TypeParameter[] typeParams;
|
||||
TypeReference[] thrownExceptions;
|
||||
char[] nameOfStaticBuilderMethod;
|
||||
EclipseNode tdParent;
|
||||
|
||||
|
||||
EclipseNode fillParametersFrom = parent.get() instanceof AbstractMethodDeclaration ? parent : null;
|
||||
boolean addCleaning = false;
|
||||
boolean isStatic = true;
|
||||
|
||||
|
||||
List<EclipseNode> nonFinalNonDefaultedFields = null;
|
||||
|
||||
|
||||
if (builderClassName.isEmpty()) builderClassName = annotationNode.getAst().readConfiguration(ConfigurationKeys.BUILDER_CLASS_NAME);
|
||||
if (builderClassName == null || builderClassName.isEmpty()) builderClassName = "*Builder";
|
||||
boolean replaceNameInBuilderClassName = builderClassName.contains("*");
|
||||
|
||||
|
||||
if (parent.get() instanceof TypeDeclaration) {
|
||||
tdParent = parent;
|
||||
TypeDeclaration td = (TypeDeclaration) tdParent.get();
|
||||
|
||||
|
||||
List<EclipseNode> allFields = new ArrayList<EclipseNode>();
|
||||
boolean valuePresent = (hasAnnotation(lombok.Value.class, parent) || hasAnnotation("lombok.experimental.Value", parent));
|
||||
for (EclipseNode fieldNode : HandleConstructor.findAllFields(tdParent, true)) {
|
||||
FieldDeclaration fd = (FieldDeclaration) fieldNode.get();
|
||||
EclipseNode isDefault = findAnnotation(Builder.Default.class, fieldNode);
|
||||
boolean isFinal = ((fd.modifiers & ClassFileConstants.AccFinal) != 0) || (valuePresent && !hasAnnotation(NonFinal.class, fieldNode));
|
||||
|
||||
|
||||
Annotation[] copyableAnnotations = findCopyableAnnotations(fieldNode);
|
||||
|
||||
|
||||
BuilderFieldData bfd = new BuilderFieldData();
|
||||
bfd.rawName = fieldNode.getName().toCharArray();
|
||||
bfd.name = removePrefixFromField(fieldNode);
|
||||
bfd.builderFieldName = bfd.name;
|
||||
bfd.annotations = copyAnnotations(fd, copyableAnnotations);
|
||||
bfd.type = fd.type;
|
||||
bfd.singularData = getSingularData(fieldNode, ast);
|
||||
bfd.singularData = getSingularData(fieldNode, ast, builderInstance.setterPrefix());
|
||||
bfd.originalFieldNode = fieldNode;
|
||||
|
||||
|
||||
if (bfd.singularData != null && isDefault != null) {
|
||||
isDefault.addError("@Builder.Default and @Singular cannot be mixed.");
|
||||
isDefault = null;
|
||||
}
|
||||
|
||||
|
||||
if (fd.initialization == null && isDefault != null) {
|
||||
isDefault.addWarning("@Builder.Default requires an initializing expression (' = something;').");
|
||||
isDefault = null;
|
||||
}
|
||||
|
||||
|
||||
if (fd.initialization != null && isDefault == null) {
|
||||
if (isFinal) continue;
|
||||
if (nonFinalNonDefaultedFields == null) nonFinalNonDefaultedFields = new ArrayList<EclipseNode>();
|
||||
nonFinalNonDefaultedFields.add(fieldNode);
|
||||
}
|
||||
|
||||
|
||||
if (isDefault != null) {
|
||||
bfd.nameOfDefaultProvider = prefixWith(DEFAULT_PREFIX, bfd.name);
|
||||
bfd.nameOfSetFlag = prefixWith(bfd.name, SET_PREFIX);
|
||||
bfd.builderFieldName = prefixWith(bfd.name, VALUE_PREFIX);
|
||||
|
||||
|
||||
MethodDeclaration md = generateDefaultProvider(bfd.nameOfDefaultProvider, td.typeParameters, fieldNode, ast);
|
||||
if (md != null) injectMethod(tdParent, md);
|
||||
}
|
||||
@@ -270,10 +270,10 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
|
||||
builderFields.add(bfd);
|
||||
allFields.add(fieldNode);
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
thrownExceptions = null;
|
||||
@@ -286,7 +286,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
|
||||
annotationNode.addError("@Builder is not supported on constructors with constructor type parameters.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
tdParent = parent.up();
|
||||
TypeDeclaration td = (TypeDeclaration) tdParent.get();
|
||||
returnType = namePlusTypeParamsToTypeReference(td.name, td.typeParameters, p);
|
||||
@@ -299,7 +299,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
|
||||
MethodDeclaration md = (MethodDeclaration) parent.get();
|
||||
tdParent = parent.up();
|
||||
isStatic = md.isStatic();
|
||||
|
||||
|
||||
if (toBuilder) {
|
||||
final String TO_BUILDER_NOT_SUPPORTED = "@Builder(toBuilder=true) is only supported if you return your own type.";
|
||||
char[] token;
|
||||
@@ -308,7 +308,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
|
||||
annotationNode.addError(TO_BUILDER_NOT_SUPPORTED);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (md.returnType instanceof SingleTypeReference) {
|
||||
token = ((SingleTypeReference) md.returnType).token;
|
||||
} else if (md.returnType instanceof QualifiedTypeReference) {
|
||||
@@ -321,17 +321,17 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
|
||||
annotationNode.addError(TO_BUILDER_NOT_SUPPORTED);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (pkg != null && !equals(parent.getPackageDeclaration(), pkg)) {
|
||||
annotationNode.addError(TO_BUILDER_NOT_SUPPORTED);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (tdParent == null || !equals(tdParent.getName(), token)) {
|
||||
annotationNode.addError(TO_BUILDER_NOT_SUPPORTED);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
TypeParameter[] tpOnType = ((TypeDeclaration) tdParent.get()).typeParameters;
|
||||
TypeParameter[] tpOnMethod = md.typeParameters;
|
||||
TypeReference[][] tpOnRet_ = null;
|
||||
@@ -341,7 +341,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
|
||||
} else if (md.returnType instanceof ParameterizedQualifiedTypeReference) {
|
||||
tpOnRet_ = ((ParameterizedQualifiedTypeReference) md.returnType).typeArguments;
|
||||
}
|
||||
|
||||
|
||||
if (tpOnRet_ != null) for (int i = 0; i < tpOnRet_.length - 1; i++) {
|
||||
if (tpOnRet_[i] != null && tpOnRet_[i].length > 0) {
|
||||
annotationNode.addError("@Builder(toBuilder=true) is not supported if returning a type with generics applied to an intermediate.");
|
||||
@@ -350,11 +350,11 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
|
||||
}
|
||||
TypeReference[] tpOnRet = tpOnRet_ == null ? null : tpOnRet_[tpOnRet_.length - 1];
|
||||
typeArgsForToBuilder = new ArrayList<char[]>();
|
||||
|
||||
|
||||
// Every typearg on this method needs to be found in the return type, but the reverse is not true.
|
||||
// We also need to 'map' them.
|
||||
|
||||
|
||||
|
||||
|
||||
if (tpOnMethod != null) for (TypeParameter onMethod : tpOnMethod) {
|
||||
int pos = -1;
|
||||
if (tpOnRet != null) for (int i = 0; i < tpOnRet.length; i++) {
|
||||
@@ -366,11 +366,11 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
|
||||
annotationNode.addError("@Builder(toBuilder=true) requires that each type parameter on the static method is part of the typeargs of the return value. Type parameter " + new String(onMethod.name) + " is not part of the return type.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
typeArgsForToBuilder.add(tpOnType[pos].name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
returnType = copyType(md.returnType, ast);
|
||||
typeParams = md.typeParameters;
|
||||
thrownExceptions = md.thrownExceptions;
|
||||
@@ -394,41 +394,41 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
|
||||
annotationNode.addError("Unexpected kind of return type on annotated method. Specify 'builderClassName' to solve this problem.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (Character.isLowerCase(token[0])) {
|
||||
char[] newToken = new char[token.length];
|
||||
System.arraycopy(token, 1, newToken, 1, token.length - 1);
|
||||
newToken[0] = Character.toTitleCase(token[0]);
|
||||
token = newToken;
|
||||
}
|
||||
|
||||
|
||||
builderClassName = builderClassName.replace("*", new String(token));
|
||||
}
|
||||
} else {
|
||||
annotationNode.addError("@Builder is only supported on types, constructors, and methods.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (fillParametersFrom != null) {
|
||||
for (EclipseNode param : fillParametersFrom.down()) {
|
||||
if (param.getKind() != Kind.ARGUMENT) continue;
|
||||
BuilderFieldData bfd = new BuilderFieldData();
|
||||
Argument arg = (Argument) param.get();
|
||||
|
||||
|
||||
Annotation[] copyableAnnotations = findCopyableAnnotations(param);
|
||||
|
||||
|
||||
bfd.rawName = arg.name;
|
||||
bfd.name = arg.name;
|
||||
bfd.builderFieldName = bfd.name;
|
||||
bfd.annotations = copyAnnotations(arg, copyableAnnotations);
|
||||
bfd.type = arg.type;
|
||||
bfd.singularData = getSingularData(param, ast);
|
||||
bfd.singularData = getSingularData(param, ast, builderInstance.setterPrefix());
|
||||
bfd.originalFieldNode = param;
|
||||
addObtainVia(bfd, param);
|
||||
builderFields.add(bfd);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
EclipseNode builderType = findInnerClass(tdParent, builderClassName);
|
||||
if (builderType == null) {
|
||||
builderType = makeBuilderClass(isStatic, tdParent, builderClassName, typeParams, ast, accessForOuters);
|
||||
@@ -454,7 +454,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (BuilderFieldData bfd : builderFields) {
|
||||
if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) {
|
||||
if (bfd.singularData.getSingularizer().requiresCleaning()) {
|
||||
@@ -473,7 +473,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
generateBuilderFields(builderType, builderFields, ast);
|
||||
if (addCleaning) {
|
||||
FieldDeclaration cleanDecl = new FieldDeclaration(CLEAN_FIELD_NAME, 0, -1);
|
||||
@@ -483,18 +483,18 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
|
||||
cleanDecl.traverse(new SetGeneratedByVisitor(ast), (MethodScope) null);
|
||||
injectFieldAndMarkGenerated(builderType, cleanDecl);
|
||||
}
|
||||
|
||||
|
||||
if (constructorExists(builderType) == MemberExistsResult.NOT_EXISTS) {
|
||||
ConstructorDeclaration cd = HandleConstructor.createConstructor(
|
||||
AccessLevel.PACKAGE, builderType, Collections.<EclipseNode>emptyList(), false,
|
||||
annotationNode, Collections.<Annotation>emptyList());
|
||||
if (cd != null) injectMethod(builderType, cd);
|
||||
}
|
||||
|
||||
|
||||
for (BuilderFieldData bfd : builderFields) {
|
||||
makeSetterMethodsForBuilder(cfv, builderType, bfd, annotationNode, fluent, chain, accessForInners, bfd.originalFieldNode);
|
||||
makePrefixedSetterMethodsForBuilder(cfv, builderType, bfd, annotationNode, fluent, chain, accessForInners, bfd.originalFieldNode, builderInstance.setterPrefix());
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
MemberExistsResult methodExists = methodExists(buildMethodName, builderType, -1);
|
||||
if (methodExists == MemberExistsResult.EXISTS_BY_LOMBOK) methodExists = methodExists(buildMethodName, builderType, 0);
|
||||
@@ -503,7 +503,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
|
||||
if (md != null) injectMethod(builderType, md);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (methodExists("toString", builderType, 0) == MemberExistsResult.NOT_EXISTS) {
|
||||
List<Included<EclipseNode, ToString.Include>> fieldNodes = new ArrayList<Included<EclipseNode, ToString.Include>>();
|
||||
for (BuilderFieldData bfd : builderFields) {
|
||||
@@ -514,18 +514,18 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
|
||||
MethodDeclaration md = HandleToString.createToString(builderType, fieldNodes, true, false, ast, FieldAccess.ALWAYS_FIELD);
|
||||
if (md != null) injectMethod(builderType, md);
|
||||
}
|
||||
|
||||
|
||||
if (addCleaning) {
|
||||
MethodDeclaration cleanMethod = generateCleanMethod(builderFields, builderType, ast);
|
||||
if (cleanMethod != null) injectMethod(builderType, cleanMethod);
|
||||
}
|
||||
|
||||
|
||||
if (generateBuilderMethod && methodExists(builderMethodName, tdParent, -1) != MemberExistsResult.NOT_EXISTS) generateBuilderMethod = false;
|
||||
if (generateBuilderMethod) {
|
||||
MethodDeclaration md = generateBuilderMethod(cfv, isStatic, builderMethodName, builderClassName, tdParent, typeParams, ast, accessForOuters);
|
||||
if (md != null) injectMethod(tdParent, md);
|
||||
}
|
||||
|
||||
|
||||
if (toBuilder) switch (methodExists(toBuilderMethodName, tdParent, 0)) {
|
||||
case EXISTS_BY_USER:
|
||||
annotationNode.addWarning("Not generating toBuilder() as it already exists.");
|
||||
@@ -539,23 +539,23 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
|
||||
tps[i].name = typeArgsForToBuilder.get(i);
|
||||
}
|
||||
}
|
||||
MethodDeclaration md = generateToBuilderMethod(cfv, toBuilderMethodName, builderClassName, tdParent, tps, builderFields, fluent, ast, accessForOuters);
|
||||
|
||||
MethodDeclaration md = generateToBuilderMethod(cfv, toBuilderMethodName, builderClassName, tdParent, tps, builderFields, fluent, ast, accessForOuters, builderInstance.setterPrefix());
|
||||
|
||||
if (md != null) injectMethod(tdParent, md);
|
||||
}
|
||||
|
||||
|
||||
if (nonFinalNonDefaultedFields != null && generateBuilderMethod) {
|
||||
for (EclipseNode fieldNode : nonFinalNonDefaultedFields) {
|
||||
fieldNode.addWarning("@Builder 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.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static final char[] BUILDER_TEMP_VAR = {'b', 'u', 'i', 'l', 'd', 'e', 'r'};
|
||||
private MethodDeclaration generateToBuilderMethod(CheckerFrameworkVersion cfv, String methodName, String builderClassName, EclipseNode type, TypeParameter[] typeParams, List<BuilderFieldData> builderFields, boolean fluent, ASTNode source, AccessLevel access) {
|
||||
private MethodDeclaration generateToBuilderMethod(CheckerFrameworkVersion cfv, String methodName, String builderClassName, EclipseNode type, TypeParameter[] typeParams, List<BuilderFieldData> builderFields, boolean fluent, ASTNode source, AccessLevel access, String prefix) {
|
||||
int pS = source.sourceStart, pE = source.sourceEnd;
|
||||
long p = (long) pS << 32 | pE;
|
||||
|
||||
|
||||
MethodDeclaration out = new MethodDeclaration(((CompilationUnitDeclaration) type.top().get()).compilationResult);
|
||||
out.selector = methodName.toCharArray();
|
||||
out.modifiers = toEclipseModifier(access);
|
||||
@@ -563,14 +563,20 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
|
||||
out.returnType = namePlusTypeParamsToTypeReference(builderClassName.toCharArray(), typeParams, p);
|
||||
AllocationExpression invoke = new AllocationExpression();
|
||||
invoke.type = namePlusTypeParamsToTypeReference(builderClassName.toCharArray(), typeParams, p);
|
||||
|
||||
|
||||
Expression receiver = invoke;
|
||||
List<Statement> statements = null;
|
||||
for (BuilderFieldData bfd : builderFields) {
|
||||
char[] setterName = fluent ? bfd.name : HandlerUtil.buildAccessorName("set", new String(bfd.name)).toCharArray();
|
||||
String setterPrefix = prefix.isEmpty() ? "set" : prefix;
|
||||
String setterName;
|
||||
if(fluent) {
|
||||
setterName = prefix.isEmpty() ? new String(bfd.name) : HandlerUtil.buildAccessorName(setterPrefix, new String(bfd.name));
|
||||
} else {
|
||||
setterName = HandlerUtil.buildAccessorName(setterPrefix, new String(bfd.name));
|
||||
}
|
||||
MessageSend ms = new MessageSend();
|
||||
Expression[] tgt = new Expression[bfd.singularData == null ? 1 : 2];
|
||||
|
||||
|
||||
if (bfd.obtainVia == null || !bfd.obtainVia.field().isEmpty()) {
|
||||
char[] fieldName = bfd.obtainVia == null ? bfd.rawName : bfd.obtainVia.field().toCharArray();
|
||||
for (int i = 0; i < tgt.length; i++) {
|
||||
@@ -599,8 +605,8 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
|
||||
tgt[i] = obtainExpr;
|
||||
}
|
||||
}
|
||||
|
||||
ms.selector = setterName;
|
||||
|
||||
ms.selector = setterName.toCharArray();
|
||||
if (bfd.singularData == null) {
|
||||
ms.arguments = tgt;
|
||||
ms.receiver = receiver;
|
||||
@@ -613,7 +619,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
|
||||
statements.add(new IfStatement(isNotNull, ms, pS, pE));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (statements != null) {
|
||||
out.statements = new Statement[statements.size() + 2];
|
||||
for (int i = 0; i < statements.size(); i++) out.statements[i + 1] = statements.get(i);
|
||||
@@ -627,25 +633,25 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
|
||||
} else {
|
||||
out.statements = new Statement[] {new ReturnStatement(receiver, pS, pE)};
|
||||
}
|
||||
|
||||
|
||||
if (cfv.generateUnique()) {
|
||||
out.annotations = new Annotation[] {generateNamedAnnotation(source, CheckerFrameworkVersion.NAME__UNIQUE)};
|
||||
}
|
||||
|
||||
|
||||
out.traverse(new SetGeneratedByVisitor(source), ((TypeDeclaration) type.get()).scope);
|
||||
return out;
|
||||
|
||||
}
|
||||
|
||||
|
||||
private MethodDeclaration generateCleanMethod(List<BuilderFieldData> builderFields, EclipseNode builderType, ASTNode source) {
|
||||
List<Statement> statements = new ArrayList<Statement>();
|
||||
|
||||
|
||||
for (BuilderFieldData bfd : builderFields) {
|
||||
if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) {
|
||||
bfd.singularData.getSingularizer().appendCleaningCode(bfd.singularData, builderType, statements);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
FieldReference thisUnclean = new FieldReference(CLEAN_FIELD_NAME, 0);
|
||||
thisUnclean.receiver = new ThisReference(0, 0);
|
||||
statements.add(new Assignment(thisUnclean, new FalseLiteral(0, 0), 0));
|
||||
@@ -658,15 +664,15 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
|
||||
decl.traverse(new SetGeneratedByVisitor(source), (ClassScope) null);
|
||||
return decl;
|
||||
}
|
||||
|
||||
|
||||
static Argument[] generateBuildArgs(CheckerFrameworkVersion cfv, EclipseNode type, List<BuilderFieldData> builderFields, ASTNode source) {
|
||||
if (!cfv.generateCalledMethods()) return null;
|
||||
|
||||
|
||||
List<char[]> mandatories = new ArrayList<char[]>();
|
||||
for (BuilderFieldData bfd : builderFields) {
|
||||
if (bfd.singularData == null && bfd.nameOfSetFlag == null) mandatories.add(bfd.name);
|
||||
}
|
||||
|
||||
|
||||
if (mandatories.size() == 0) return null;
|
||||
char[][] nameCalled = fromQualifiedName(CheckerFrameworkVersion.NAME__CALLED);
|
||||
SingleMemberAnnotation ann = new SingleMemberAnnotation(new QualifiedTypeReference(nameCalled, poss(source, nameCalled.length)), source.sourceStart);
|
||||
@@ -686,12 +692,12 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
|
||||
arg.annotations = new Annotation[] {ann};
|
||||
return new Argument[] {arg};
|
||||
}
|
||||
|
||||
|
||||
public MethodDeclaration generateBuildMethod(CheckerFrameworkVersion cfv, EclipseNode tdParent, boolean isStatic, String name, char[] staticName, TypeReference returnType, List<BuilderFieldData> builderFields, EclipseNode type, TypeReference[] thrownExceptions, boolean addCleaning, ASTNode source, AccessLevel access) {
|
||||
MethodDeclaration out = new MethodDeclaration(((CompilationUnitDeclaration) type.top().get()).compilationResult);
|
||||
out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
|
||||
List<Statement> statements = new ArrayList<Statement>();
|
||||
|
||||
|
||||
if (addCleaning) {
|
||||
FieldReference thisUnclean = new FieldReference(CLEAN_FIELD_NAME, 0);
|
||||
thisUnclean.receiver = new ThisReference(0, 0);
|
||||
@@ -700,13 +706,13 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
|
||||
invokeClean.selector = CLEAN_METHOD_NAME;
|
||||
statements.add(new IfStatement(notClean, invokeClean, 0, 0));
|
||||
}
|
||||
|
||||
|
||||
for (BuilderFieldData bfd : builderFields) {
|
||||
if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) {
|
||||
bfd.singularData.getSingularizer().appendBuildCode(bfd.singularData, type, statements, bfd.builderFieldName, "this");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
List<Expression> args = new ArrayList<Expression>();
|
||||
for (BuilderFieldData bfd : builderFields) {
|
||||
if (bfd.nameOfSetFlag != null) {
|
||||
@@ -716,7 +722,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
|
||||
inv.receiver = new SingleNameReference(((TypeDeclaration) tdParent.get()).name, 0L);
|
||||
inv.selector = bfd.nameOfDefaultProvider;
|
||||
inv.typeArguments = typeParameterNames(((TypeDeclaration) type.get()).typeParameters);
|
||||
|
||||
|
||||
args.add(new ConditionalExpression(
|
||||
new SingleNameReference(bfd.nameOfSetFlag, 0L),
|
||||
new SingleNameReference(bfd.builderFieldName, 0L),
|
||||
@@ -725,19 +731,19 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
|
||||
args.add(new SingleNameReference(bfd.builderFieldName, 0L));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (addCleaning) {
|
||||
FieldReference thisUnclean = new FieldReference(CLEAN_FIELD_NAME, 0);
|
||||
thisUnclean.receiver = new ThisReference(0, 0);
|
||||
statements.add(new Assignment(thisUnclean, new TrueLiteral(0, 0), 0));
|
||||
}
|
||||
|
||||
|
||||
out.modifiers = toEclipseModifier(access);
|
||||
out.selector = name.toCharArray();
|
||||
out.thrownExceptions = copyTypes(thrownExceptions);
|
||||
out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
|
||||
out.returnType = returnType;
|
||||
|
||||
|
||||
if (staticName == null) {
|
||||
AllocationExpression allocationStatement = new AllocationExpression();
|
||||
allocationStatement.type = copyType(out.returnType);
|
||||
@@ -750,7 +756,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
|
||||
invoke.receiver = new SingleNameReference(type.up().getName().toCharArray(), 0);
|
||||
else
|
||||
invoke.receiver = new QualifiedThisReference(new SingleTypeReference(type.up().getName().toCharArray(), 0) , 0, 0);
|
||||
|
||||
|
||||
invoke.typeArguments = typeParameterNames(((TypeDeclaration) type.get()).typeParameters);
|
||||
invoke.arguments = args.isEmpty() ? null : args.toArray(new Expression[0]);
|
||||
if (returnType instanceof SingleTypeReference && Arrays.equals(TypeConstants.VOID, ((SingleTypeReference) returnType).token)) {
|
||||
@@ -767,20 +773,20 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
|
||||
out.traverse(new SetGeneratedByVisitor(source), (ClassScope) null);
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
private TypeReference[] typeParameterNames(TypeParameter[] typeParameters) {
|
||||
if (typeParameters == null) return null;
|
||||
|
||||
|
||||
TypeReference[] trs = new TypeReference[typeParameters.length];
|
||||
for (int i = 0; i < trs.length; i++) {
|
||||
trs[i] = new SingleTypeReference(typeParameters[i].name, 0);
|
||||
}
|
||||
return trs;
|
||||
}
|
||||
|
||||
|
||||
public static MethodDeclaration generateDefaultProvider(char[] methodName, TypeParameter[] typeParameters, EclipseNode fieldNode, ASTNode source) {
|
||||
int pS = source.sourceStart, pE = source.sourceEnd;
|
||||
|
||||
|
||||
MethodDeclaration out = new MethodDeclaration(((CompilationUnitDeclaration) fieldNode.top().get()).compilationResult);
|
||||
out.typeParameters = copyTypeParams(typeParameters, source);
|
||||
out.selector = methodName;
|
||||
@@ -790,15 +796,15 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
|
||||
out.returnType = copyType(fd.type, source);
|
||||
out.statements = new Statement[] {new ReturnStatement(fd.initialization, pS, pE)};
|
||||
fd.initialization = null;
|
||||
|
||||
|
||||
out.traverse(new SetGeneratedByVisitor(source), ((TypeDeclaration) fieldNode.up().get()).scope);
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
public MethodDeclaration generateBuilderMethod(CheckerFrameworkVersion cfv, boolean isStatic, String builderMethodName, String builderClassName, EclipseNode type, TypeParameter[] typeParams, ASTNode source, AccessLevel access) {
|
||||
int pS = source.sourceStart, pE = source.sourceEnd;
|
||||
long p = (long) pS << 32 | pE;
|
||||
|
||||
|
||||
MethodDeclaration out = new MethodDeclaration(((CompilationUnitDeclaration) type.top().get()).compilationResult);
|
||||
out.selector = builderMethodName.toCharArray();
|
||||
out.modifiers = toEclipseModifier(access);
|
||||
@@ -821,13 +827,13 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
|
||||
out.traverse(new SetGeneratedByVisitor(source), ((TypeDeclaration) type.get()).scope);
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
public void generateBuilderFields(EclipseNode builderType, List<BuilderFieldData> builderFields, ASTNode source) {
|
||||
List<EclipseNode> existing = new ArrayList<EclipseNode>();
|
||||
for (EclipseNode child : builderType.down()) {
|
||||
if (child.getKind() == Kind.FIELD) existing.add(child);
|
||||
}
|
||||
|
||||
|
||||
for (BuilderFieldData bfd : builderFields) {
|
||||
if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) {
|
||||
bfd.createdFields.addAll(bfd.singularData.getSingularizer().generateFields(bfd.singularData, builderType));
|
||||
@@ -838,7 +844,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
|
||||
if (Arrays.equals(n, bfd.builderFieldName)) field = exists;
|
||||
if (bfd.nameOfSetFlag != null && Arrays.equals(n, bfd.nameOfSetFlag)) setFlag = exists;
|
||||
}
|
||||
|
||||
|
||||
if (field == null) {
|
||||
FieldDeclaration fd = new FieldDeclaration(bfd.builderFieldName, 0, 0);
|
||||
fd.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG;
|
||||
@@ -859,9 +865,9 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static final AbstractMethodDeclaration[] EMPTY = {};
|
||||
|
||||
|
||||
public void makeSetterMethodsForBuilder(CheckerFrameworkVersion cfv, EclipseNode builderType, BuilderFieldData bfd, EclipseNode sourceNode, boolean fluent, boolean chain, AccessLevel access, EclipseNode originalFieldNode) {
|
||||
boolean deprecate = isFieldDeprecated(bfd.originalFieldNode);
|
||||
if (bfd.singularData == null || bfd.singularData.getSingularizer() == null) {
|
||||
@@ -870,7 +876,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
|
||||
bfd.singularData.getSingularizer().generateMethods(cfv, bfd.singularData, deprecate, builderType, fluent, chain, access);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void makeSimpleSetterMethodForBuilder(CheckerFrameworkVersion cfv, EclipseNode builderType, boolean deprecate, EclipseNode fieldNode, char[] paramName, char[] nameOfSetFlag, EclipseNode sourceNode, boolean fluent, boolean chain, Annotation[] annotations, AccessLevel access, EclipseNode originalFieldNode) {
|
||||
TypeDeclaration td = (TypeDeclaration) builderType.get();
|
||||
AbstractMethodDeclaration[] existing = td.methods;
|
||||
@@ -879,16 +885,67 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
|
||||
int len = existing.length;
|
||||
FieldDeclaration fd = (FieldDeclaration) fieldNode.get();
|
||||
char[] name = fd.name;
|
||||
|
||||
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (!(existing[i] instanceof MethodDeclaration)) continue;
|
||||
char[] existingName = existing[i].selector;
|
||||
if (Arrays.equals(name, existingName) && !isTolerate(fieldNode, existing[i])) return;
|
||||
}
|
||||
|
||||
|
||||
String setterName = fluent ? new String(paramName) : HandlerUtil.buildAccessorName("set", new String(paramName));
|
||||
|
||||
|
||||
List<Annotation> methodAnnsList = Arrays.asList(EclipseHandlerUtil.findCopyableToSetterAnnotations(originalFieldNode));
|
||||
Annotation[] methodAnns = EclipseHandlerUtil.findCopyableToSetterAnnotations(originalFieldNode);
|
||||
if (methodAnns != null && methodAnns.length > 0) methodAnnsList = Arrays.asList(methodAnns);
|
||||
MethodDeclaration setter = HandleSetter.createSetter(td, deprecate, fieldNode, setterName, paramName, nameOfSetFlag, chain, toEclipseModifier(access),
|
||||
sourceNode, methodAnnsList, annotations != null ? Arrays.asList(copyAnnotations(sourceNode.get(), annotations)) : Collections.<Annotation>emptyList());
|
||||
if (cfv.generateCalledMethods()) {
|
||||
Argument[] arr = setter.arguments == null ? new Argument[0] : setter.arguments;
|
||||
Argument[] newArr = new Argument[arr.length + 1];
|
||||
System.arraycopy(arr, 0, newArr, 1, arr.length);
|
||||
newArr[0] = new Argument(new char[] { 't', 'h', 'i', 's' }, 0, new SingleTypeReference(builderType.getName().toCharArray(), 0), Modifier.FINAL);
|
||||
char[][] nameNotCalled = fromQualifiedName(CheckerFrameworkVersion.NAME__NOT_CALLED);
|
||||
SingleMemberAnnotation ann = new SingleMemberAnnotation(new QualifiedTypeReference(nameNotCalled, poss(source, nameNotCalled.length)), source.sourceStart);
|
||||
ann.memberValue = new StringLiteral(setterName.toCharArray(), 0, 0, 0);
|
||||
newArr[0].annotations = new Annotation[] {ann};
|
||||
setter.arguments = newArr;
|
||||
}
|
||||
injectMethod(builderType, setter);
|
||||
}
|
||||
|
||||
public void makePrefixedSetterMethodsForBuilder(CheckerFrameworkVersion cfv, EclipseNode builderType, BuilderFieldData bfd, EclipseNode sourceNode, boolean fluent, boolean chain, AccessLevel access, EclipseNode originalFieldNode, String prefix) {
|
||||
boolean deprecate = isFieldDeprecated(bfd.originalFieldNode);
|
||||
if (bfd.singularData == null || bfd.singularData.getSingularizer() == null) {
|
||||
makePrefixedSetterMethodForBuilder(cfv, builderType, deprecate, bfd.createdFields.get(0), bfd.name, bfd.nameOfSetFlag, sourceNode, fluent, chain, bfd.annotations, access, originalFieldNode, prefix);
|
||||
} else {
|
||||
bfd.singularData.getSingularizer().generateMethods(cfv, bfd.singularData, deprecate, builderType, fluent, chain, access);
|
||||
}
|
||||
}
|
||||
|
||||
private void makePrefixedSetterMethodForBuilder(CheckerFrameworkVersion cfv, EclipseNode builderType, boolean deprecate, EclipseNode fieldNode, char[] paramName, char[] nameOfSetFlag, EclipseNode sourceNode, boolean fluent, boolean chain, Annotation[] annotations, AccessLevel access, EclipseNode originalFieldNode, String prefix) {
|
||||
TypeDeclaration td = (TypeDeclaration) builderType.get();
|
||||
AbstractMethodDeclaration[] existing = td.methods;
|
||||
if (existing == null) existing = EMPTY;
|
||||
int len = existing.length;
|
||||
|
||||
String setterPrefix = prefix.isEmpty() ? "set" : prefix;
|
||||
String setterName;
|
||||
if(fluent) {
|
||||
setterName = prefix.isEmpty() ? new String(paramName) : HandlerUtil.buildAccessorName(setterPrefix, new String(paramName));
|
||||
} else {
|
||||
setterName = HandlerUtil.buildAccessorName(setterPrefix, new String(paramName));
|
||||
}
|
||||
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (!(existing[i] instanceof MethodDeclaration)) continue;
|
||||
char[] existingName = existing[i].selector;
|
||||
if (Arrays.equals(setterName.toCharArray(), existingName) && !isTolerate(fieldNode, existing[i])) return;
|
||||
}
|
||||
|
||||
List<Annotation> methodAnnsList = Collections.<Annotation>emptyList();
|
||||
Annotation[] methodAnns = EclipseHandlerUtil.findCopyableToSetterAnnotations(originalFieldNode);
|
||||
if (methodAnns != null && methodAnns.length > 0) methodAnnsList = Arrays.asList(methodAnns);
|
||||
ASTNode source = sourceNode.get();
|
||||
MethodDeclaration setter = HandleSetter.createSetter(td, deprecate, fieldNode, setterName, paramName, nameOfSetFlag, chain, toEclipseModifier(access),
|
||||
sourceNode, methodAnnsList, annotations != null ? Arrays.asList(copyAnnotations(source, annotations)) : Collections.<Annotation>emptyList());
|
||||
if (cfv.generateCalledMethods()) {
|
||||
@@ -897,14 +954,15 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
|
||||
System.arraycopy(arr, 0, newArr, 1, arr.length);
|
||||
newArr[0] = new Argument(new char[] { 't', 'h', 'i', 's' }, 0, new SingleTypeReference(builderType.getName().toCharArray(), 0), Modifier.FINAL);
|
||||
char[][] nameNotCalled = fromQualifiedName(CheckerFrameworkVersion.NAME__NOT_CALLED);
|
||||
SingleMemberAnnotation ann = new SingleMemberAnnotation(new QualifiedTypeReference(nameNotCalled, poss(source, nameNotCalled.length)), source.sourceStart);
|
||||
SingleMemberAnnotation ann = new SingleMemberAnnotation(new QualifiedTypeReference(nameNotCalled, poss(
|
||||
source, nameNotCalled.length)), source.sourceStart);
|
||||
ann.memberValue = new StringLiteral(setterName.toCharArray(), 0, 0, 0);
|
||||
newArr[0].annotations = new Annotation[] {ann};
|
||||
setter.arguments = newArr;
|
||||
}
|
||||
injectMethod(builderType, setter);
|
||||
}
|
||||
|
||||
|
||||
public EclipseNode makeBuilderClass(boolean isStatic, EclipseNode tdParent, String builderClassName, TypeParameter[] typeParams, ASTNode source, AccessLevel access) {
|
||||
TypeDeclaration parent = (TypeDeclaration) tdParent.get();
|
||||
TypeDeclaration builder = new TypeDeclaration(parent.compilationResult);
|
||||
@@ -916,7 +974,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
|
||||
builder.traverse(new SetGeneratedByVisitor(source), (ClassScope) null);
|
||||
return injectType(tdParent, builder);
|
||||
}
|
||||
|
||||
|
||||
private void addObtainVia(BuilderFieldData bfd, EclipseNode node) {
|
||||
for (EclipseNode child : node.down()) {
|
||||
if (!annotationTypeMatches(ObtainVia.class, child)) continue;
|
||||
@@ -926,14 +984,15 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
|
||||
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.
|
||||
* @param setterPrefix
|
||||
*/
|
||||
private SingularData getSingularData(EclipseNode node, ASTNode source) {
|
||||
private SingularData getSingularData(EclipseNode node, ASTNode source, final String setterPrefix) {
|
||||
for (EclipseNode child : node.down()) {
|
||||
if (!annotationTypeMatches(Singular.class, child)) continue;
|
||||
char[] pluralName = node.getKind() == Kind.FIELD ? removePrefixFromField(node) : ((AbstractVariableDeclaration) node.get()).name;
|
||||
@@ -952,7 +1011,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
|
||||
}
|
||||
}
|
||||
char[] singularName = explicitSingular.toCharArray();
|
||||
|
||||
|
||||
TypeReference type = ((AbstractVariableDeclaration) node.get()).type;
|
||||
TypeReference[] typeArgs = null;
|
||||
String typeName;
|
||||
@@ -972,7 +1031,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
|
||||
} else {
|
||||
typeName = type.toString();
|
||||
}
|
||||
|
||||
|
||||
String targetFqn = EclipseSingularsRecipes.get().toQualified(typeName);
|
||||
EclipseSingularizer singularizer = EclipseSingularsRecipes.get().getSingularizer(targetFqn);
|
||||
if (singularizer == null) {
|
||||
@@ -980,9 +1039,9 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new SingularData(child, singularName, pluralName, typeArgs == null ? Collections.<TypeReference>emptyList() : Arrays.asList(typeArgs), targetFqn, singularizer, source);
|
||||
return new SingularData(child, singularName, pluralName, typeArgs == null ? Collections.<TypeReference>emptyList() : Arrays.asList(typeArgs), targetFqn, singularizer, source, setterPrefix.toCharArray());
|
||||
}
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -172,7 +172,8 @@ abstract class EclipseGuavaSingularizer extends EclipseSingularizer {
|
||||
md.arguments[i].annotations = typeUseAnns;
|
||||
}
|
||||
md.returnType = returnType;
|
||||
md.selector = fluent ? data.getSingularName() : HandlerUtil.buildAccessorName(getAddMethodName(), new String(data.getSingularName())).toCharArray();
|
||||
char[] prefixedSingularName = data.getSetterPrefix().length == 0 ? data.getSingularName() : HandlerUtil.buildAccessorName(new String(data.getSetterPrefix()), new String(data.getSingularName())).toCharArray();
|
||||
md.selector = fluent ? prefixedSingularName : HandlerUtil.buildAccessorName("add", new String(data.getSingularName())).toCharArray();
|
||||
md.annotations = generateSelfReturnAnnotations(deprecate, cfv, data.getSource());
|
||||
|
||||
data.setGeneratedByRecursive(md);
|
||||
@@ -204,7 +205,8 @@ abstract class EclipseGuavaSingularizer extends EclipseSingularizer {
|
||||
Argument param = new Argument(data.getPluralName(), 0, paramType, ClassFileConstants.AccFinal);
|
||||
md.arguments = new Argument[] {param};
|
||||
md.returnType = returnType;
|
||||
md.selector = fluent ? data.getPluralName() : HandlerUtil.buildAccessorName(getAddMethodName() + "All", new String(data.getPluralName())).toCharArray();
|
||||
char[] prefixedSelector = data.getSetterPrefix().length == 0 ? data.getPluralName() : HandlerUtil.buildAccessorName(new String(data.getSetterPrefix()), new String(data.getPluralName())).toCharArray();
|
||||
md.selector = fluent ? prefixedSelector : HandlerUtil.buildAccessorName("addAll", new String(data.getPluralName())).toCharArray();
|
||||
md.annotations = generateSelfReturnAnnotations(deprecate, cfv, data.getSource());
|
||||
|
||||
data.setGeneratedByRecursive(md);
|
||||
|
||||
@@ -150,7 +150,8 @@ abstract class EclipseJavaUtilListSetSingularizer extends EclipseJavaUtilSingula
|
||||
param.annotations = typeUseAnns;
|
||||
md.arguments = new Argument[] {param};
|
||||
md.returnType = returnType;
|
||||
md.selector = fluent ? data.getSingularName() : HandlerUtil.buildAccessorName("add", new String(data.getSingularName())).toCharArray();
|
||||
char[] prefixedSingularName = data.getSetterPrefix().length == 0 ? data.getSingularName() : HandlerUtil.buildAccessorName(new String(data.getSetterPrefix()), new String(data.getSingularName())).toCharArray();
|
||||
md.selector = fluent ? prefixedSingularName : HandlerUtil.buildAccessorName("add", new String(data.getSingularName())).toCharArray();
|
||||
md.annotations = generateSelfReturnAnnotations(deprecate, cfv, data.getSource());
|
||||
|
||||
data.setGeneratedByRecursive(md);
|
||||
@@ -181,7 +182,8 @@ abstract class EclipseJavaUtilListSetSingularizer extends EclipseJavaUtilSingula
|
||||
Argument param = new Argument(data.getPluralName(), 0, paramType, ClassFileConstants.AccFinal);
|
||||
md.arguments = new Argument[] {param};
|
||||
md.returnType = returnType;
|
||||
md.selector = fluent ? data.getPluralName() : HandlerUtil.buildAccessorName("addAll", new String(data.getPluralName())).toCharArray();
|
||||
char[] prefixedSelector = data.getSetterPrefix().length == 0 ? data.getPluralName() : HandlerUtil.buildAccessorName(new String(data.getSetterPrefix()), new String(data.getPluralName())).toCharArray();
|
||||
md.selector = fluent ? prefixedSelector : HandlerUtil.buildAccessorName("addAll", new String(data.getPluralName())).toCharArray();
|
||||
md.annotations = generateSelfReturnAnnotations(deprecate, cfv, data.getSource());
|
||||
|
||||
data.setGeneratedByRecursive(md);
|
||||
|
||||
@@ -28,6 +28,7 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.logging.Handler;
|
||||
|
||||
import org.eclipse.jdt.internal.compiler.ast.Annotation;
|
||||
import org.eclipse.jdt.internal.compiler.ast.Argument;
|
||||
@@ -62,6 +63,7 @@ import lombok.eclipse.handlers.EclipseSingularsRecipes.SingularData;
|
||||
import lombok.eclipse.handlers.EclipseSingularsRecipes.StatementMaker;
|
||||
import lombok.eclipse.handlers.EclipseSingularsRecipes.TypeReferenceMaker;
|
||||
import lombok.eclipse.handlers.HandleNonNull;
|
||||
import org.objectweb.asm.Handle;
|
||||
|
||||
@ProviderFor(EclipseSingularizer.class)
|
||||
public class EclipseJavaUtilMapSingularizer extends EclipseJavaUtilSingularizer {
|
||||
@@ -245,7 +247,13 @@ public class EclipseJavaUtilMapSingularizer extends EclipseJavaUtilSingularizer
|
||||
valueParam.annotations = typeUseAnnsValue;
|
||||
md.arguments = new Argument[] {keyParam, valueParam};
|
||||
md.returnType = returnType;
|
||||
md.selector = fluent ? data.getSingularName() : HandlerUtil.buildAccessorName("put", new String(data.getSingularName())).toCharArray();
|
||||
|
||||
String name = new String(data.getSingularName());
|
||||
String setterPrefix = new String(data.getSetterPrefix());
|
||||
String prefixedSingularName = setterPrefix.isEmpty() ? name : HandlerUtil.buildAccessorName(setterPrefix, name);
|
||||
String setterName = fluent ? prefixedSingularName : HandlerUtil.buildAccessorName("put", name);
|
||||
|
||||
md.selector = setterName.toCharArray();
|
||||
md.annotations = generateSelfReturnAnnotations(deprecate, cfv, data.getSource());
|
||||
|
||||
data.setGeneratedByRecursive(md);
|
||||
@@ -309,7 +317,13 @@ public class EclipseJavaUtilMapSingularizer extends EclipseJavaUtilSingularizer
|
||||
Argument param = new Argument(data.getPluralName(), 0, paramType, ClassFileConstants.AccFinal);
|
||||
md.arguments = new Argument[] {param};
|
||||
md.returnType = returnType;
|
||||
md.selector = fluent ? data.getPluralName() : HandlerUtil.buildAccessorName("putAll", new String(data.getPluralName())).toCharArray();
|
||||
|
||||
String name = new String(data.getPluralName());
|
||||
String setterPrefix = new String(data.getSetterPrefix());
|
||||
String prefixedSingularName = setterPrefix.isEmpty() ? name : HandlerUtil.buildAccessorName(setterPrefix, name);
|
||||
String setterName = fluent ? prefixedSingularName : HandlerUtil.buildAccessorName("put", name);
|
||||
|
||||
md.selector = setterName.toCharArray();
|
||||
md.annotations = generateSelfReturnAnnotations(deprecate, cfv, data.getSource());
|
||||
|
||||
data.setGeneratedByRecursive(md);
|
||||
|
||||
@@ -104,7 +104,7 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
|
||||
@Override public void handle(AnnotationValues<Builder> annotation, JCAnnotation ast, JavacNode annotationNode) {
|
||||
handleFlagUsage(annotationNode, ConfigurationKeys.BUILDER_FLAG_USAGE, "@Builder");
|
||||
CheckerFrameworkVersion cfv = getCheckerFrameworkVersion(annotationNode);
|
||||
|
||||
|
||||
Builder builderInstance = annotation.getInstance();
|
||||
AccessLevel accessForOuters = builderInstance.access();
|
||||
if (accessForOuters == null) accessForOuters = AccessLevel.PUBLIC;
|
||||
@@ -180,7 +180,7 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
|
||||
bfd.builderFieldName = bfd.name;
|
||||
bfd.annotations = findCopyableAnnotations(fieldNode);
|
||||
bfd.type = fd.vartype;
|
||||
bfd.singularData = getSingularData(fieldNode);
|
||||
bfd.singularData = getSingularData(fieldNode, builderInstance.setterPrefix());
|
||||
bfd.originalFieldNode = fieldNode;
|
||||
|
||||
if (bfd.singularData != null && isDefault != null) {
|
||||
@@ -369,7 +369,7 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
|
||||
bfd.rawName = raw.name;
|
||||
bfd.annotations = findCopyableAnnotations(param);
|
||||
bfd.type = raw.vartype;
|
||||
bfd.singularData = getSingularData(param);
|
||||
bfd.singularData = getSingularData(param, builderInstance.setterPrefix());
|
||||
bfd.originalFieldNode = param;
|
||||
addObtainVia(bfd, param);
|
||||
builderFields.add(bfd);
|
||||
@@ -436,7 +436,7 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
|
||||
}
|
||||
|
||||
for (BuilderFieldData bfd : builderFields) {
|
||||
makeSetterMethodsForBuilder(cfv, builderType, bfd, annotationNode, fluent, chain, accessForInners);
|
||||
makePrefixedSetterMethodsForBuilder(cfv, builderType, bfd, annotationNode, fluent, chain, accessForInners, builderInstance.setterPrefix());
|
||||
}
|
||||
|
||||
{
|
||||
@@ -487,7 +487,7 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
|
||||
}
|
||||
tps = lb.toList();
|
||||
}
|
||||
JCMethodDecl md = generateToBuilderMethod(cfv, toBuilderMethodName, builderClassName, tdParent, tps, builderFields, fluent, ast, accessForOuters);
|
||||
JCMethodDecl md = generateToBuilderMethod(cfv, toBuilderMethodName, builderClassName, tdParent, tps, builderFields, fluent, ast, accessForOuters, builderInstance.setterPrefix());
|
||||
if (md != null) {
|
||||
recursiveSetGeneratedBy(md, ast, annotationNode.getContext());
|
||||
injectMethod(tdParent, md);
|
||||
@@ -536,7 +536,7 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
|
||||
}
|
||||
|
||||
private static final String BUILDER_TEMP_VAR = "builder";
|
||||
private JCMethodDecl generateToBuilderMethod(CheckerFrameworkVersion cfv, String toBuilderMethodName, String builderClassName, JavacNode type, List<JCTypeParameter> typeParams, java.util.List<BuilderFieldData> builderFields, boolean fluent, JCAnnotation ast, AccessLevel access) {
|
||||
private JCMethodDecl generateToBuilderMethod(CheckerFrameworkVersion cfv, String toBuilderMethodName, String builderClassName, JavacNode type, List<JCTypeParameter> typeParams, java.util.List<BuilderFieldData> builderFields, boolean fluent, JCAnnotation ast, AccessLevel access, String prefix) {
|
||||
// return new ThingieBuilder<A, B>().setA(this.a).setB(this.b);
|
||||
JavacTreeMaker maker = type.getTreeMaker();
|
||||
|
||||
@@ -549,7 +549,13 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
|
||||
JCExpression invoke = call;
|
||||
ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>();
|
||||
for (BuilderFieldData bfd : builderFields) {
|
||||
Name setterName = fluent ? bfd.name : type.toName(HandlerUtil.buildAccessorName("set", bfd.name.toString()));
|
||||
String prefixedSetterName;
|
||||
if(fluent) {
|
||||
prefixedSetterName = prefix.isEmpty() ? bfd.name.toString() : HandlerUtil.buildAccessorName(prefix, bfd.name.toString());
|
||||
} else {
|
||||
prefixedSetterName = HandlerUtil.buildAccessorName(prefix, bfd.name.toString());
|
||||
}
|
||||
Name setterName = type.toName(prefixedSetterName);
|
||||
JCExpression[] tgt = new JCExpression[bfd.singularData == null ? 1 : 2];
|
||||
if (bfd.obtainVia == null || !bfd.obtainVia.field().isEmpty()) {
|
||||
for (int i = 0; i < tgt.length; i++) {
|
||||
@@ -622,12 +628,12 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
|
||||
|
||||
static List<JCVariableDecl> generateBuildArgs(CheckerFrameworkVersion cfv, JavacNode type, java.util.List<BuilderFieldData> builderFields) {
|
||||
if (!cfv.generateCalledMethods()) return List.<JCVariableDecl>nil();
|
||||
|
||||
|
||||
ArrayList<String> mandatories = new ArrayList<String>();
|
||||
for (BuilderFieldData bfd : builderFields) {
|
||||
if (bfd.singularData == null && bfd.nameOfSetFlag == null) mandatories.add(bfd.name.toString());
|
||||
}
|
||||
|
||||
|
||||
JCExpression arg;
|
||||
JavacTreeMaker maker = type.getTreeMaker();
|
||||
if (mandatories.size() == 0) return List.<JCVariableDecl>nil();
|
||||
@@ -642,7 +648,7 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
|
||||
JCVariableDecl recv = maker.VarDef(maker.Modifiers(0L, List.<JCAnnotation>of(recvAnno)), type.toName("this"), maker.Ident(builderTypeNode.name), null);
|
||||
return List.of(recv);
|
||||
}
|
||||
|
||||
|
||||
private JCMethodDecl generateBuildMethod(CheckerFrameworkVersion cfv, JavacNode tdParent, boolean isStatic, String buildName, Name builderName, JCExpression returnType, java.util.List<BuilderFieldData> builderFields, JavacNode type, List<JCExpression> thrownExceptions, JCTree source, boolean addCleaning, AccessLevel access) {
|
||||
JavacTreeMaker maker = type.getTreeMaker();
|
||||
|
||||
@@ -787,18 +793,56 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
|
||||
|
||||
private void makeSimpleSetterMethodForBuilder(CheckerFrameworkVersion cfv, JavacNode builderType, boolean deprecate, JavacNode fieldNode, Name paramName, Name nameOfSetFlag, JavacNode source, boolean fluent, boolean chain, List<JCAnnotation> annosOnParam, JavacNode originalFieldNode, AccessLevel access) {
|
||||
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 ? paramName.toString() : HandlerUtil.buildAccessorName("set", paramName.toString());
|
||||
|
||||
|
||||
JavacTreeMaker maker = fieldNode.getTreeMaker();
|
||||
|
||||
|
||||
List<JCAnnotation> methodAnns = JavacHandlerUtil.findCopyableToSetterAnnotations(originalFieldNode);
|
||||
JCMethodDecl newMethod = HandleSetter.createSetter(toJavacModifier(access), deprecate, fieldNode, maker, setterName, paramName, nameOfSetFlag, chain, source, methodAnns, annosOnParam);
|
||||
recursiveSetGeneratedBy(newMethod, source.get(), builderType.getContext());
|
||||
copyJavadoc(originalFieldNode, newMethod, CopyJavadoc.SETTER);
|
||||
|
||||
injectMethod(builderType, newMethod);
|
||||
}
|
||||
|
||||
public void makePrefixedSetterMethodsForBuilder(CheckerFrameworkVersion cfv, JavacNode builderType, BuilderFieldData fieldNode, JavacNode source, boolean fluent, boolean chain, AccessLevel access, String prefix) {
|
||||
boolean deprecate = isFieldDeprecated(fieldNode.originalFieldNode);
|
||||
if (fieldNode.singularData == null || fieldNode.singularData.getSingularizer() == null) {
|
||||
makePrefixedSetterMethodForBuilder(cfv, builderType, deprecate, fieldNode.createdFields.get(0), fieldNode.name, fieldNode.nameOfSetFlag, source, fluent, chain, fieldNode.annotations, fieldNode.originalFieldNode, access, prefix);
|
||||
} else {
|
||||
// TODO prefixed version
|
||||
fieldNode.singularData.getSingularizer().generateMethods(cfv, fieldNode.singularData, deprecate, builderType, source.get(), fluent, chain, access);
|
||||
}
|
||||
}
|
||||
|
||||
private void makePrefixedSetterMethodForBuilder(CheckerFrameworkVersion cfv, JavacNode builderType, boolean deprecate, JavacNode fieldNode, Name paramName, Name nameOfSetFlag, JavacNode source, boolean fluent, boolean chain, List<JCAnnotation> annosOnParam, JavacNode originalFieldNode, AccessLevel access, String prefix) {
|
||||
Name fieldName = ((JCVariableDecl) fieldNode.get()).name;
|
||||
|
||||
String setterPrefix = prefix.isEmpty() ? "set" : prefix;
|
||||
String setterName;
|
||||
if(fluent) {
|
||||
setterName = prefix.isEmpty() ? paramName.toString() : HandlerUtil.buildAccessorName(setterPrefix, paramName.toString());
|
||||
} else {
|
||||
setterName = HandlerUtil.buildAccessorName(setterPrefix, paramName.toString());
|
||||
}
|
||||
|
||||
for (JavacNode child : builderType.down()) {
|
||||
if (child.getKind() != Kind.METHOD) continue;
|
||||
JCMethodDecl methodDecl = (JCMethodDecl) child.get();
|
||||
Name existingName = methodDecl.name;
|
||||
if (existingName.equals(builderType.toName(setterName)) && !isTolerate(fieldNode, methodDecl)) return;
|
||||
}
|
||||
|
||||
JavacTreeMaker maker = fieldNode.getTreeMaker();
|
||||
|
||||
List<JCAnnotation> methodAnns = JavacHandlerUtil.findCopyableToSetterAnnotations(originalFieldNode);
|
||||
JCMethodDecl newMethod = HandleSetter.createSetter(toJavacModifier(access), deprecate, fieldNode, maker, setterName, paramName, nameOfSetFlag, chain, source, methodAnns, annosOnParam);
|
||||
if (cfv.generateCalledMethods()) {
|
||||
@@ -809,10 +853,10 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
|
||||
}
|
||||
recursiveSetGeneratedBy(newMethod, source.get(), builderType.getContext());
|
||||
copyJavadoc(originalFieldNode, newMethod, CopyJavadoc.SETTER);
|
||||
|
||||
|
||||
injectMethod(builderType, newMethod);
|
||||
}
|
||||
|
||||
|
||||
public JavacNode makeBuilderClass(boolean isStatic, JavacNode source, JavacNode tdParent, String builderClassName, List<JCTypeParameter> typeParams, JCAnnotation ast, AccessLevel access) {
|
||||
JavacTreeMaker maker = tdParent.getTreeMaker();
|
||||
int modifiers = toJavacModifier(access);
|
||||
@@ -838,8 +882,9 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
|
||||
* 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.
|
||||
* @param setterPrefix
|
||||
*/
|
||||
private SingularData getSingularData(JavacNode node) {
|
||||
private SingularData getSingularData(JavacNode node, final String setterPrefix) {
|
||||
for (JavacNode child : node.down()) {
|
||||
if (!annotationTypeMatches(Singular.class, child)) continue;
|
||||
Name pluralName = node.getKind() == Kind.FIELD ? removePrefixFromField(node) : ((JCVariableDecl) node.get()).name;
|
||||
@@ -881,7 +926,7 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new SingularData(child, singularName, pluralName, typeArgs, targetFqn, singularizer);
|
||||
return new SingularData(child, singularName, pluralName, typeArgs, targetFqn, singularizer, setterPrefix);
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
@@ -119,6 +119,7 @@ public class JavacSingularsRecipes {
|
||||
private final List<JCExpression> typeArgs;
|
||||
private final String targetFqn;
|
||||
private final JavacSingularizer singularizer;
|
||||
private final String setterPrefix;
|
||||
|
||||
public SingularData(JavacNode annotation, Name singularName, Name pluralName, List<JCExpression> typeArgs, String targetFqn, JavacSingularizer singularizer) {
|
||||
this.annotation = annotation;
|
||||
@@ -127,6 +128,17 @@ public class JavacSingularsRecipes {
|
||||
this.typeArgs = typeArgs;
|
||||
this.targetFqn = targetFqn;
|
||||
this.singularizer = singularizer;
|
||||
this.setterPrefix = "";
|
||||
}
|
||||
|
||||
public SingularData(JavacNode annotation, Name singularName, Name pluralName, List<JCExpression> typeArgs, String targetFqn, JavacSingularizer singularizer, String setterPrefix) {
|
||||
this.annotation = annotation;
|
||||
this.singularName = singularName;
|
||||
this.pluralName = pluralName;
|
||||
this.typeArgs = typeArgs;
|
||||
this.targetFqn = targetFqn;
|
||||
this.singularizer = singularizer;
|
||||
this.setterPrefix = setterPrefix;
|
||||
}
|
||||
|
||||
public JavacNode getAnnotation() {
|
||||
@@ -140,6 +152,8 @@ public class JavacSingularsRecipes {
|
||||
public Name getPluralName() {
|
||||
return pluralName;
|
||||
}
|
||||
|
||||
public String getSetterPrefix() { return setterPrefix; }
|
||||
|
||||
public List<JCExpression> getTypeArgs() {
|
||||
return typeArgs;
|
||||
@@ -281,8 +295,13 @@ public class JavacSingularsRecipes {
|
||||
ListBuffer<JCStatement> statements = generateSingularMethodStatements(maker, data, builderType, source);
|
||||
List<JCVariableDecl> params = generateSingularMethodParameters(maker, data, builderType, source);
|
||||
Name name = data.getSingularName();
|
||||
if (!fluent) name = builderType.toName(HandlerUtil.buildAccessorName(getAddMethodName(), name.toString()));
|
||||
|
||||
String setterPrefix = data.getSetterPrefix();
|
||||
Name prefixedSingularName = setterPrefix.isEmpty() ? name :
|
||||
builderType.toName(HandlerUtil.buildAccessorName(setterPrefix, name.toString()));
|
||||
|
||||
name = fluent ? prefixedSingularName : builderType.toName(HandlerUtil.buildAccessorName(getAddMethodName(),
|
||||
name.toString()));
|
||||
|
||||
statements.prepend(createConstructBuilderVarIfNeeded(maker, data, builderType, source));
|
||||
finishAndInjectMethod(cfv, maker, returnType, returnStatement, data, builderType, source, deprecate, statements, name, params, access);
|
||||
}
|
||||
@@ -309,7 +328,10 @@ public class JavacSingularsRecipes {
|
||||
private void generatePluralMethod(CheckerFrameworkVersion cfv, boolean deprecate, JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source, boolean fluent, AccessLevel access) {
|
||||
ListBuffer<JCStatement> statements = generatePluralMethodStatements(maker, data, builderType, source);
|
||||
Name name = data.getPluralName();
|
||||
if (!fluent) name = builderType.toName(HandlerUtil.buildAccessorName(getAddMethodName() + "All", name.toString()));
|
||||
|
||||
Name prefixedSingularName = data.getSetterPrefix().isEmpty() ? name : builderType.toName(HandlerUtil.buildAccessorName(data.getSetterPrefix(), data.getPluralName().toString()));
|
||||
name = fluent ? prefixedSingularName
|
||||
: builderType.toName(HandlerUtil.buildAccessorName(getAddMethodName() + "All", name.toString()));
|
||||
JCExpression paramType = getPluralMethodParamType(builderType);
|
||||
paramType = addTypeArgs(getTypeArgumentsCount(), true, builderType, paramType, data.getTypeArgs(), source);
|
||||
long paramFlags = JavacHandlerUtil.addFinalIfNeeded(Flags.PARAMETER, builderType.getContext());
|
||||
|
||||
Reference in new issue
Block a user