Merge pull request #2018 from emlun/refactor-singularizers

Reduce code duplication in singularizers
This commit is contained in:
Reinier Zwitserloot authored and GitHub committed 2019-02-12 01:25:39 +01:00
commit cf7855b1a1
9 files changed
+243 -295

No files matched your search

@@ -794,7 +794,7 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
name = type.toString();
String targetFqn = JavacSingularsRecipes.get().toQualified(name);
JavacSingularizer singularizer = JavacSingularsRecipes.get().getSingularizer(targetFqn);
JavacSingularizer singularizer = JavacSingularsRecipes.get().getSingularizer(targetFqn, node);
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;
@@ -919,7 +919,7 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
name = type.toString();
String targetFqn = JavacSingularsRecipes.get().toQualified(name);
JavacSingularizer singularizer = JavacSingularsRecipes.get().getSingularizer(targetFqn);
JavacSingularizer singularizer = JavacSingularsRecipes.get().getSingularizer(targetFqn, node);
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;
@@ -24,15 +24,19 @@ package lombok.javac.handlers;
import static lombok.javac.Javac.*;
import static lombok.javac.handlers.JavacHandlerUtil.*;
import com.sun.tools.javac.tree.JCTree.JCBlock;
import com.sun.tools.javac.tree.JCTree.JCTypeParameter;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import lombok.ConfigurationKeys;
import lombok.core.LombokImmutableList;
import lombok.core.SpiLoadUtil;
import lombok.core.TypeLibrary;
import lombok.core.handlers.HandlerUtil;
import lombok.javac.JavacNode;
import lombok.javac.JavacTreeMaker;
@@ -98,8 +102,10 @@ public class JavacSingularsRecipes {
return singularizableTypes.toQualified(typeReference);
}
public JavacSingularizer getSingularizer(String fqn) {
return singularizers.get(fqn);
public JavacSingularizer getSingularizer(String fqn, JavacNode node) {
final JavacSingularizer singularizer = singularizers.get(fqn);
final boolean useGuavaInstead = Boolean.TRUE.equals(node.getAst().readConfiguration(ConfigurationKeys.SINGULAR_USE_GUAVA));
return useGuavaInstead ? singularizer.getGuavaInstead(node) : singularizer;
}
public static final class SingularData {
@@ -151,6 +157,10 @@ public class JavacSingularsRecipes {
public static abstract class JavacSingularizer {
public abstract LombokImmutableList<String> getSupportedTypes();
protected JavacSingularizer getGuavaInstead(JavacNode node) {
return this;
}
protected JCModifiers makeMods(JavacTreeMaker maker, JavacNode node, boolean deprecate) {
if (deprecate) return maker.Modifiers(Flags.PUBLIC, List.<JCAnnotation>of(maker.Annotation(genJavaLangTypeRef(node, "Deprecated"), List.<JCExpression>nil())));
@@ -230,7 +240,87 @@ public class JavacSingularsRecipes {
* Uses the given {@code returnTypeMaker} and {@code returnStatementMaker} for the generated methods.
*/
public abstract void generateMethods(SingularData data, boolean deprecate, JavacNode builderType, JCTree source, boolean fluent, ExpressionMaker returnTypeMaker, StatementMaker returnStatementMaker);
protected void doGenerateMethods(SingularData data, boolean deprecate, JavacNode builderType, JCTree source, boolean fluent, ExpressionMaker returnTypeMaker, StatementMaker returnStatementMaker) {
JavacTreeMaker maker = builderType.getTreeMaker();
generateSingularMethod(deprecate, maker, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, source, fluent);
generatePluralMethod(deprecate, maker, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, source, fluent);
generateClearMethod(deprecate, maker, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, source);
}
private void finishAndInjectMethod(JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source, boolean deprecate, ListBuffer<JCStatement> statements, Name methodName, List<JCVariableDecl> jcVariableDecls) {
if (returnStatement != null) statements.append(returnStatement);
JCBlock body = maker.Block(0, statements.toList());
JCModifiers mods = makeMods(maker, builderType, deprecate);
List<JCTypeParameter> typeParams = List.nil();
List<JCExpression> thrown = List.nil();
JCMethodDecl method = maker.MethodDef(mods, methodName, returnType, typeParams, jcVariableDecls, thrown, body, null);
recursiveSetGeneratedBy(method, source, builderType.getContext());
injectMethod(builderType, method);
}
private void generateClearMethod(boolean deprecate, JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source) {
JCStatement clearStatement = generateClearStatements(maker, data, builderType);
ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>();
statements.add(clearStatement);
Name methodName = builderType.toName(HandlerUtil.buildAccessorName("clear", data.getPluralName().toString()));
finishAndInjectMethod(maker, returnType, returnStatement, data, builderType, source, deprecate, statements, methodName, List.<JCVariableDecl>nil());
}
protected abstract JCStatement generateClearStatements(JavacTreeMaker maker, SingularData data, JavacNode builderType);
private void generateSingularMethod(boolean deprecate, JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source, boolean fluent) {
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()));
statements.prepend(createConstructBuilderVarIfNeeded(maker, data, builderType, source));
finishAndInjectMethod(maker, returnType, returnStatement, data, builderType, source, deprecate, statements, name, params);
}
protected JCVariableDecl generateSingularMethodParameter(int typeIndex, JavacTreeMaker maker, SingularData data, JavacNode builderType, JCTree source, Name name) {
long flags = JavacHandlerUtil.addFinalIfNeeded(Flags.PARAMETER, builderType.getContext());
JCExpression type = cloneParamType(typeIndex, maker, data.getTypeArgs(), builderType, source);
List<JCAnnotation> typeUseAnns = getTypeUseAnnotations(type);
type = removeTypeUseAnnotations(type);
JCModifiers mods = typeUseAnns.isEmpty() ? maker.Modifiers(flags) : maker.Modifiers(flags, typeUseAnns);
return maker.VarDef(mods, name, type, null);
}
protected JCStatement generateSingularMethodAddStatement(JavacTreeMaker maker, JavacNode builderType, Name argumentName, String builderFieldName) {
JCExpression thisDotFieldDotAdd = chainDots(builderType, "this", builderFieldName, "add");
JCExpression invokeAdd = maker.Apply(List.<JCExpression>nil(), thisDotFieldDotAdd, List.<JCExpression>of(maker.Ident(argumentName)));
return maker.Exec(invokeAdd);
}
protected abstract ListBuffer<JCStatement> generateSingularMethodStatements(JavacTreeMaker maker, SingularData data, JavacNode builderType, JCTree source);
protected abstract List<JCVariableDecl> generateSingularMethodParameters(JavacTreeMaker maker, SingularData data, JavacNode builderType, JCTree source);
private void generatePluralMethod(boolean deprecate, JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source, boolean fluent) {
ListBuffer<JCStatement> statements = generatePluralMethodStatements(maker, data, builderType, source);
Name name = data.getPluralName();
if (!fluent) name = 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());
JCVariableDecl param = maker.VarDef(maker.Modifiers(paramFlags), data.getPluralName(), paramType, null);
statements.prepend(createConstructBuilderVarIfNeeded(maker, data, builderType, source));
finishAndInjectMethod(maker, returnType, returnStatement, data, builderType, source, deprecate, statements, name, List.of(param));
}
protected ListBuffer<JCStatement> generatePluralMethodStatements(JavacTreeMaker maker, SingularData data, JavacNode builderType, JCTree source) {
JCExpression thisDotFieldDotAdd = chainDots(builderType, "this", data.getPluralName().toString(), getAddMethodName() + "All");
JCExpression invokeAdd = maker.Apply(List.<JCExpression>nil(), thisDotFieldDotAdd, List.<JCExpression>of(maker.Ident(data.getPluralName())));
return new ListBuffer<JCStatement>().append(maker.Exec(invokeAdd));
}
protected abstract JCExpression getPluralMethodParamType(JavacNode builderType);
protected abstract JCStatement createConstructBuilderVarIfNeeded(JavacTreeMaker maker, SingularData data, JavacNode builderType, JCTree source);
public abstract void appendBuildCode(SingularData data, JavacNode builderType, JCTree source, ListBuffer<JCStatement> statements, Name targetVariableName, String builderVariable);
public boolean requiresCleaning() {
@@ -342,5 +432,9 @@ public class JavacSingularsRecipes {
}
}
}
protected abstract String getAddMethodName();
protected abstract int getTypeArgumentsCount();
}
}
@@ -28,7 +28,6 @@ import java.util.Collections;
import lombok.core.GuavaTypeMap;
import lombok.core.LombokImmutableList;
import lombok.core.handlers.HandlerUtil;
import lombok.javac.JavacNode;
import lombok.javac.JavacTreeMaker;
import lombok.javac.handlers.JavacHandlerUtil;
@@ -39,13 +38,8 @@ import lombok.javac.handlers.JavacSingularsRecipes.StatementMaker;
import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCAnnotation;
import com.sun.tools.javac.tree.JCTree.JCBlock;
import com.sun.tools.javac.tree.JCTree.JCExpression;
import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
import com.sun.tools.javac.tree.JCTree.JCModifiers;
import com.sun.tools.javac.tree.JCTree.JCStatement;
import com.sun.tools.javac.tree.JCTree.JCTypeParameter;
import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.ListBuffer;
@@ -73,86 +67,54 @@ abstract class JavacGuavaSingularizer extends JavacSingularizer {
}
@Override public void generateMethods(SingularData data, boolean deprecate, JavacNode builderType, JCTree source, boolean fluent, ExpressionMaker returnTypeMaker, StatementMaker returnStatementMaker) {
JavacTreeMaker maker = builderType.getTreeMaker();
generateSingularMethod(deprecate, maker, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, source, fluent);
generatePluralMethod(deprecate, maker, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, source, fluent);
generateClearMethod(deprecate, maker, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, source);
doGenerateMethods(data, deprecate, builderType, source, fluent, returnTypeMaker, returnStatementMaker);
}
private void generateClearMethod(boolean deprecate, JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source) {
JCModifiers mods = makeMods(maker, builderType, deprecate);
List<JCTypeParameter> typeParams = List.nil();
List<JCExpression> thrown = List.nil();
List<JCVariableDecl> params = List.nil();
@Override
protected JCStatement generateClearStatements(JavacTreeMaker maker, SingularData data, JavacNode builderType) {
JCExpression thisDotField = maker.Select(maker.Ident(builderType.toName("this")), data.getPluralName());
JCStatement clearField = maker.Exec(maker.Assign(thisDotField, maker.Literal(CTC_BOT, null)));
List<JCStatement> statements = returnStatement != null ? List.of(clearField, returnStatement) : List.of(clearField);
JCBlock body = maker.Block(0, statements);
Name methodName = builderType.toName(HandlerUtil.buildAccessorName("clear", data.getPluralName().toString()));
JCMethodDecl method = maker.MethodDef(mods, methodName, returnType, typeParams, params, thrown, body, null);
recursiveSetGeneratedBy(method, source, builderType.getContext());
injectMethod(builderType, method);
return maker.Exec(maker.Assign(thisDotField, maker.Literal(CTC_BOT, null)));
}
void generateSingularMethod(boolean deprecate, JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source, boolean fluent) {
List<JCTypeParameter> typeParams = List.nil();
List<JCExpression> thrown = List.nil();
@Override
protected List<JCVariableDecl> generateSingularMethodParameters(JavacTreeMaker maker, SingularData data, JavacNode builderType, JCTree source) {
Name[] names = generateSingularMethodParameterNames(data, builderType);
ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>();
for (int i = 0; i < names.length; i++) {
params.append(generateSingularMethodParameter(i, maker, data, builderType, source, names[i]));
}
return params.toList();
}
@Override
protected ListBuffer<JCStatement> generateSingularMethodStatements(JavacTreeMaker maker, SingularData data, JavacNode builderType, JCTree source) {
Name[] names = generateSingularMethodParameterNames(data, builderType);
JCExpression thisDotFieldDotAdd = chainDots(builderType, "this", data.getPluralName().toString(), getAddMethodName());
ListBuffer<JCExpression> invokeAddExprBuilder = new ListBuffer<JCExpression>();
for (Name name : names) {
invokeAddExprBuilder.append(maker.Ident(name));
}
List<JCExpression> invokeAddExpr = invokeAddExprBuilder.toList();
JCExpression invokeAdd = maker.Apply(List.<JCExpression>nil(), thisDotFieldDotAdd, invokeAddExpr);
JCStatement st = maker.Exec(invokeAdd);
return new ListBuffer<JCStatement>().append(st);
}
private Name[] generateSingularMethodParameterNames(SingularData data, JavacNode builderType) {
LombokImmutableList<String> suffixes = getArgumentSuffixes();
Name[] names = new Name[suffixes.size()];
for (int i = 0; i < suffixes.size(); i++) {
for (int i = 0; i < names.length; i++) {
String s = suffixes.get(i);
Name n = data.getSingularName();
names[i] = s.isEmpty() ? n : builderType.toName(s);
}
JCModifiers mods = makeMods(maker, builderType, deprecate);
ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>();
statements.append(createConstructBuilderVarIfNeeded(maker, data, builderType, source));
JCExpression thisDotFieldDotAdd = chainDots(builderType, "this", data.getPluralName().toString(), getAddMethodName());
ListBuffer<JCExpression> invokeAddExprBuilder = new ListBuffer<JCExpression>();
for (int i = 0; i < suffixes.size(); i++) {
invokeAddExprBuilder.append(maker.Ident(names[i]));
}
List<JCExpression> invokeAddExpr = invokeAddExprBuilder.toList();
JCExpression invokeAdd = maker.Apply(List.<JCExpression>nil(), thisDotFieldDotAdd, invokeAddExpr);
statements.append(maker.Exec(invokeAdd));
if (returnStatement != null) statements.append(returnStatement);
JCBlock body = maker.Block(0, statements.toList());
Name methodName = data.getSingularName();
long paramFlags = JavacHandlerUtil.addFinalIfNeeded(Flags.PARAMETER, builderType.getContext());
if (!fluent) methodName = builderType.toName(HandlerUtil.buildAccessorName(getAddMethodName(), methodName.toString()));
ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>();
for (int i = 0; i < suffixes.size(); i++) {
JCExpression pt = cloneParamType(i, maker, data.getTypeArgs(), builderType, source);
List<JCAnnotation> typeUseAnns = getTypeUseAnnotations(pt);
pt = removeTypeUseAnnotations(pt);
JCModifiers paramMods = typeUseAnns.isEmpty() ? maker.Modifiers(paramFlags) : maker.Modifiers(paramFlags, typeUseAnns);
JCVariableDecl p = maker.VarDef(paramMods, names[i], pt, null);
params.append(p);
}
JCMethodDecl method = maker.MethodDef(mods, methodName, returnType, typeParams, params.toList(), thrown, body, null);
recursiveSetGeneratedBy(method, source, builderType.getContext());
injectMethod(builderType, method);
return names;
}
protected void generatePluralMethod(boolean deprecate, JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source, boolean fluent) {
List<JCTypeParameter> typeParams = List.nil();
List<JCExpression> thrown = List.nil();
JCModifiers mods = makeMods(maker, builderType, deprecate);
ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>();
statements.append(createConstructBuilderVarIfNeeded(maker, data, builderType, source));
JCExpression thisDotFieldDotAddAll = chainDots(builderType, "this", data.getPluralName().toString(), getAddMethodName() + "All");
JCExpression invokeAddAll = maker.Apply(List.<JCExpression>nil(), thisDotFieldDotAddAll, List.<JCExpression>of(maker.Ident(data.getPluralName())));
statements.append(maker.Exec(invokeAddAll));
if (returnStatement != null) statements.append(returnStatement);
JCBlock body = maker.Block(0, statements.toList());
Name methodName = data.getPluralName();
long paramFlags = JavacHandlerUtil.addFinalIfNeeded(Flags.PARAMETER, builderType.getContext());
if (!fluent) methodName = builderType.toName(HandlerUtil.buildAccessorName(getAddMethodName() + "All", methodName.toString()));
@Override
protected JCExpression getPluralMethodParamType(JavacNode builderType) {
JCExpression paramType;
String aaTypeName = getAddAllTypeName();
if (aaTypeName.startsWith("java.lang.") && aaTypeName.indexOf('.', 11) == -1) {
@@ -160,13 +122,9 @@ abstract class JavacGuavaSingularizer extends JavacSingularizer {
} else {
paramType = chainDotsString(builderType, aaTypeName);
}
paramType = addTypeArgs(getTypeArgumentsCount(), true, builderType, paramType, data.getTypeArgs(), source);
JCVariableDecl param = maker.VarDef(maker.Modifiers(paramFlags), data.getPluralName(), paramType, null);
JCMethodDecl method = maker.MethodDef(mods, methodName, returnType, typeParams, List.of(param), thrown, body, null);
recursiveSetGeneratedBy(method, source, builderType.getContext());
injectMethod(builderType, method);
return paramType;
}
@Override public void appendBuildCode(SingularData data, JavacNode builderType, JCTree source, ListBuffer<JCStatement> statements, Name targetVariableName, String builderVariable) {
JavacTreeMaker maker = builderType.getTreeMaker();
List<JCExpression> jceBlank = List.nil();
@@ -197,7 +155,8 @@ abstract class JavacGuavaSingularizer extends JavacSingularizer {
JCStatement jcs = maker.VarDef(maker.Modifiers(0), data.getPluralName(), varType, init);
statements.append(jcs);
}
@Override
protected JCStatement createConstructBuilderVarIfNeeded(JavacTreeMaker maker, SingularData data, JavacNode builderType, JCTree source) {
List<JCExpression> jceBlank = List.nil();
@@ -212,9 +171,10 @@ abstract class JavacGuavaSingularizer extends JavacSingularizer {
}
protected abstract LombokImmutableList<String> getArgumentSuffixes();
protected abstract String getAddMethodName();
protected abstract String getAddAllTypeName();
@Override
protected int getTypeArgumentsCount() {
return getArgumentSuffixes().size();
}
@@ -26,50 +26,38 @@ import static lombok.javac.handlers.JavacHandlerUtil.*;
import java.util.Collections;
import lombok.core.handlers.HandlerUtil;
import lombok.javac.JavacNode;
import lombok.javac.JavacTreeMaker;
import lombok.javac.handlers.JavacHandlerUtil;
import lombok.javac.handlers.JavacSingularsRecipes.ExpressionMaker;
import lombok.javac.handlers.JavacSingularsRecipes.JavacSingularizer;
import lombok.javac.handlers.JavacSingularsRecipes.SingularData;
import lombok.javac.handlers.JavacSingularsRecipes.StatementMaker;
import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCAnnotation;
import com.sun.tools.javac.tree.JCTree.JCBlock;
import com.sun.tools.javac.tree.JCTree.JCExpression;
import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
import com.sun.tools.javac.tree.JCTree.JCModifiers;
import com.sun.tools.javac.tree.JCTree.JCStatement;
import com.sun.tools.javac.tree.JCTree.JCTypeParameter;
import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.ListBuffer;
import com.sun.tools.javac.util.Name;
abstract class JavacJavaUtilListSetSingularizer extends JavacJavaUtilSingularizer {
@Override protected JavacSingularizer getGuavaInstead(JavacNode node) {
return new JavacGuavaSetListSingularizer();
}
@Override public java.util.List<Name> listFieldsToBeGenerated(SingularData data, JavacNode builderType) {
if (useGuavaInstead(builderType)) {
return guavaListSetSingularizer.listFieldsToBeGenerated(data, builderType);
}
return super.listFieldsToBeGenerated(data, builderType);
}
@Override public java.util.List<Name> listMethodsToBeGenerated(SingularData data, JavacNode builderType) {
if (useGuavaInstead(builderType)) {
return guavaListSetSingularizer.listMethodsToBeGenerated(data, builderType);
}
return super.listMethodsToBeGenerated(data, builderType);
}
@Override public java.util.List<JavacNode> generateFields(SingularData data, JavacNode builderType, JCTree source) {
if (useGuavaInstead(builderType)) {
return guavaListSetSingularizer.generateFields(data, builderType, source);
}
JavacTreeMaker maker = builderType.getTreeMaker();
JCExpression type = JavacHandlerUtil.chainDots(builderType, "java", "util", "ArrayList");
type = addTypeArgs(1, false, builderType, type, data.getTypeArgs(), source);
@@ -79,81 +67,50 @@ abstract class JavacJavaUtilListSetSingularizer extends JavacJavaUtilSingularize
}
@Override public void generateMethods(SingularData data, boolean deprecate, JavacNode builderType, JCTree source, boolean fluent, ExpressionMaker returnTypeMaker, StatementMaker returnStatementMaker) {
if (useGuavaInstead(builderType)) {
guavaListSetSingularizer.generateMethods(data, deprecate, builderType, source, fluent, returnTypeMaker, returnStatementMaker);
return;
}
JavacTreeMaker maker = builderType.getTreeMaker();
generateSingularMethod(deprecate, maker, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, source, fluent);
generatePluralMethod(deprecate, maker, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, source, fluent);
generateClearMethod(deprecate, maker, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, source);
doGenerateMethods(data, deprecate, builderType, source, fluent, returnTypeMaker, returnStatementMaker);
}
private void generateClearMethod(boolean deprecate, JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source) {
JCModifiers mods = makeMods(maker, builderType, deprecate);
List<JCTypeParameter> typeParams = List.nil();
List<JCExpression> thrown = List.nil();
List<JCVariableDecl> params = List.nil();
@Override
protected JCStatement generateClearStatements(JavacTreeMaker maker, SingularData data, JavacNode builderType) {
List<JCExpression> jceBlank = List.nil();
JCExpression thisDotField = maker.Select(maker.Ident(builderType.toName("this")), data.getPluralName());
JCExpression thisDotFieldDotClear = maker.Select(maker.Select(maker.Ident(builderType.toName("this")), data.getPluralName()), builderType.toName("clear"));
JCStatement clearCall = maker.Exec(maker.Apply(jceBlank, thisDotFieldDotClear, jceBlank));
JCExpression cond = maker.Binary(CTC_NOT_EQUAL, thisDotField, maker.Literal(CTC_BOT, null));
JCStatement ifSetCallClear = maker.If(cond, clearCall, null);
List<JCStatement> statements = returnStatement != null ? List.of(ifSetCallClear, returnStatement) : List.of(ifSetCallClear);
JCBlock body = maker.Block(0, statements);
Name methodName = builderType.toName(HandlerUtil.buildAccessorName("clear", data.getPluralName().toString()));
JCMethodDecl method = maker.MethodDef(mods, methodName, returnType, typeParams, params, thrown, body, null);
recursiveSetGeneratedBy(method, source, builderType.getContext());
injectMethod(builderType, method);
return maker.If(cond, clearCall, null);
}
void generateSingularMethod(boolean deprecate, JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source, boolean fluent) {
List<JCTypeParameter> typeParams = List.nil();
List<JCExpression> thrown = List.nil();
JCModifiers mods = makeMods(maker, builderType, deprecate);
ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>();
statements.append(createConstructBuilderVarIfNeeded(maker, data, builderType, false, source));
JCExpression thisDotFieldDotAdd = chainDots(builderType, "this", data.getPluralName().toString(), "add");
JCExpression invokeAdd = maker.Apply(List.<JCExpression>nil(), thisDotFieldDotAdd, List.<JCExpression>of(maker.Ident(data.getSingularName())));
statements.append(maker.Exec(invokeAdd));
if (returnStatement != null) statements.append(returnStatement);
JCBlock body = maker.Block(0, statements.toList());
Name name = data.getSingularName();
long paramFlags = JavacHandlerUtil.addFinalIfNeeded(Flags.PARAMETER, builderType.getContext());
if (!fluent) name = builderType.toName(HandlerUtil.buildAccessorName("add", name.toString()));
JCExpression paramType = cloneParamType(0, maker, data.getTypeArgs(), builderType, source);
List<JCAnnotation> typeUseAnns = getTypeUseAnnotations(paramType);
paramType = removeTypeUseAnnotations(paramType);
JCModifiers paramMods = typeUseAnns.isEmpty() ? maker.Modifiers(paramFlags) : maker.Modifiers(paramFlags, typeUseAnns);
JCVariableDecl param = maker.VarDef(paramMods, data.getSingularName(), paramType, null);
JCMethodDecl method = maker.MethodDef(mods, name, returnType, typeParams, List.of(param), thrown, body, null);
recursiveSetGeneratedBy(method, source, builderType.getContext());
injectMethod(builderType, method);
@Override
protected ListBuffer<JCStatement> generateSingularMethodStatements(JavacTreeMaker maker, SingularData data, JavacNode builderType, JCTree source) {
return new ListBuffer<JCStatement>()
.append(generateSingularMethodAddStatement(maker, builderType, data.getSingularName(), data.getPluralName().toString()));
}
void generatePluralMethod(boolean deprecate, JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source, boolean fluent) {
List<JCTypeParameter> typeParams = List.nil();
List<JCExpression> thrown = List.nil();
JCModifiers mods = makeMods(maker, builderType, deprecate);
ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>();
statements.append(createConstructBuilderVarIfNeeded(maker, data, builderType, false, source));
JCExpression thisDotFieldDotAdd = chainDots(builderType, "this", data.getPluralName().toString(), "addAll");
JCExpression invokeAdd = maker.Apply(List.<JCExpression>nil(), thisDotFieldDotAdd, List.<JCExpression>of(maker.Ident(data.getPluralName())));
statements.append(maker.Exec(invokeAdd));
if (returnStatement != null) statements.append(returnStatement);
JCBlock body = maker.Block(0, statements.toList());
Name name = data.getPluralName();
long paramFlags = JavacHandlerUtil.addFinalIfNeeded(Flags.PARAMETER, builderType.getContext());
if (!fluent) name = builderType.toName(HandlerUtil.buildAccessorName("addAll", name.toString()));
JCExpression paramType = chainDots(builderType, "java", "util", "Collection");
paramType = addTypeArgs(1, true, builderType, paramType, data.getTypeArgs(), source);
JCVariableDecl param = maker.VarDef(maker.Modifiers(paramFlags), data.getPluralName(), paramType, null);
JCMethodDecl method = maker.MethodDef(mods, name, returnType, typeParams, List.of(param), thrown, body, null);
recursiveSetGeneratedBy(method, source, builderType.getContext());
injectMethod(builderType, method);
@Override
protected List<JCVariableDecl> generateSingularMethodParameters(JavacTreeMaker maker, SingularData data, JavacNode builderType, JCTree source) {
JCVariableDecl param = generateSingularMethodParameter(0, maker, data, builderType, source, data.getSingularName());
return List.of(param);
}
@Override
protected JCExpression getPluralMethodParamType(JavacNode builderType) {
return chainDots(builderType, "java", "util", "Collection");
}
@Override
protected JCStatement createConstructBuilderVarIfNeeded(JavacTreeMaker maker, SingularData data, JavacNode builderType, JCTree source) {
return createConstructBuilderVarIfNeeded(maker, data, builderType, false, source);
}
@Override
protected String getAddMethodName() {
return "add";
}
@Override
protected int getTypeArgumentsCount() {
return 1;
}
}
@@ -47,11 +47,6 @@ public class JavacJavaUtilListSingularizer extends JavacJavaUtilListSetSingulari
}
@Override public void appendBuildCode(SingularData data, JavacNode builderType, JCTree source, ListBuffer<JCStatement> statements, Name targetVariableName, String builderVariable) {
if (useGuavaInstead(builderType)) {
guavaListSetSingularizer.appendBuildCode(data, builderType, source, statements, targetVariableName, builderVariable);
return;
}
JavacTreeMaker maker = builderType.getTreeMaker();
List<JCExpression> jceBlank = List.nil();
ListBuffer<JCCase> cases = new ListBuffer<JCCase>();
@@ -27,7 +27,6 @@ import static lombok.javac.handlers.JavacHandlerUtil.*;
import java.util.Arrays;
import lombok.core.LombokImmutableList;
import lombok.core.handlers.HandlerUtil;
import lombok.javac.JavacNode;
import lombok.javac.JavacTreeMaker;
import lombok.javac.handlers.JavacHandlerUtil;
@@ -40,13 +39,9 @@ import org.mangosdk.spi.ProviderFor;
import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCAnnotation;
import com.sun.tools.javac.tree.JCTree.JCBlock;
import com.sun.tools.javac.tree.JCTree.JCExpression;
import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
import com.sun.tools.javac.tree.JCTree.JCModifiers;
import com.sun.tools.javac.tree.JCTree.JCStatement;
import com.sun.tools.javac.tree.JCTree.JCTypeParameter;
import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.ListBuffer;
@@ -54,32 +49,25 @@ import com.sun.tools.javac.util.Name;
@ProviderFor(JavacSingularizer.class)
public class JavacJavaUtilMapSingularizer extends JavacJavaUtilSingularizer {
@Override public LombokImmutableList<String> getSupportedTypes() {
return LombokImmutableList.of("java.util.Map", "java.util.SortedMap", "java.util.NavigableMap");
}
@Override protected JavacSingularizer getGuavaInstead(JavacNode node) {
return new JavacGuavaMapSingularizer();
}
@Override public java.util.List<Name> listFieldsToBeGenerated(SingularData data, JavacNode builderType) {
if (useGuavaInstead(builderType)) {
return guavaMapSingularizer.listFieldsToBeGenerated(data, builderType);
}
String p = data.getPluralName().toString();
return Arrays.asList(builderType.toName(p + "$key"), builderType.toName(p + "$value"));
}
@Override public java.util.List<Name> listMethodsToBeGenerated(SingularData data, JavacNode builderType) {
if (useGuavaInstead(builderType)) {
return guavaMapSingularizer.listMethodsToBeGenerated(data, builderType);
}
return super.listMethodsToBeGenerated(data, builderType);
}
@Override public java.util.List<JavacNode> generateFields(SingularData data, JavacNode builderType, JCTree source) {
if (useGuavaInstead(builderType)) {
return guavaMapSingularizer.generateFields(data, builderType, source);
}
JavacTreeMaker maker = builderType.getTreeMaker();
JCVariableDecl buildKeyField; {
@@ -104,23 +92,11 @@ public class JavacJavaUtilMapSingularizer extends JavacJavaUtilSingularizer {
}
@Override public void generateMethods(SingularData data, boolean deprecate, JavacNode builderType, JCTree source, boolean fluent, ExpressionMaker returnTypeMaker, StatementMaker returnStatementMaker) {
if (useGuavaInstead(builderType)) {
guavaMapSingularizer.generateMethods(data, deprecate, builderType, source, fluent, returnTypeMaker, returnStatementMaker);
return;
}
JavacTreeMaker maker = builderType.getTreeMaker();
generateSingularMethod(deprecate, maker, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, source, fluent);
generatePluralMethod(deprecate, maker, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, source, fluent);
generateClearMethod(deprecate, maker, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, source);
doGenerateMethods(data, deprecate, builderType, source, fluent, returnTypeMaker, returnStatementMaker);
}
private void generateClearMethod(boolean deprecate, JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source) {
JCModifiers mods = makeMods(maker, builderType, deprecate);
List<JCTypeParameter> typeParams = List.nil();
List<JCExpression> thrown = List.nil();
List<JCVariableDecl> params = List.nil();
@Override
protected JCStatement generateClearStatements(JavacTreeMaker maker, SingularData data, JavacNode builderType) {
List<JCExpression> jceBlank = List.nil();
JCExpression thisDotKeyField = chainDots(builderType, "this", data.getPluralName() + "$key");
@@ -130,63 +106,35 @@ public class JavacJavaUtilMapSingularizer extends JavacJavaUtilSingularizer {
JCStatement clearValueCall = maker.Exec(maker.Apply(jceBlank, thisDotValueFieldDotClear, jceBlank));
JCExpression cond = maker.Binary(CTC_NOT_EQUAL, thisDotKeyField, maker.Literal(CTC_BOT, null));
JCBlock clearCalls = maker.Block(0, List.of(clearKeyCall, clearValueCall));
JCStatement ifSetCallClear = maker.If(cond, clearCalls, null);
List<JCStatement> statements = returnStatement != null ? List.of(ifSetCallClear, returnStatement) : List.of(ifSetCallClear);
JCBlock body = maker.Block(0, statements);
Name methodName = builderType.toName(HandlerUtil.buildAccessorName("clear", data.getPluralName().toString()));
JCMethodDecl method = maker.MethodDef(mods, methodName, returnType, typeParams, params, thrown, body, null);
recursiveSetGeneratedBy(method, source, builderType.getContext());
injectMethod(builderType, method);
}
private void generateSingularMethod(boolean deprecate, JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source, boolean fluent) {
List<JCTypeParameter> typeParams = List.nil();
List<JCExpression> thrown = List.nil();
JCModifiers mods = makeMods(maker, builderType, deprecate);
ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>();
statements.append(createConstructBuilderVarIfNeeded(maker, data, builderType, true, source));
Name keyName = builderType.toName(data.getSingularName().toString() + "Key");
Name valueName = builderType.toName(data.getSingularName().toString() + "Value");
/* this.pluralname$key.add(singularnameKey); */ {
JCExpression thisDotKeyFieldDotAdd = chainDots(builderType, "this", data.getPluralName() + "$key", "add");
JCExpression invokeAdd = maker.Apply(List.<JCExpression>nil(), thisDotKeyFieldDotAdd, List.<JCExpression>of(maker.Ident(keyName)));
statements.append(maker.Exec(invokeAdd));
}
/* this.pluralname$value.add(singularnameValue); */ {
JCExpression thisDotValueFieldDotAdd = chainDots(builderType, "this", data.getPluralName() + "$value", "add");
JCExpression invokeAdd = maker.Apply(List.<JCExpression>nil(), thisDotValueFieldDotAdd, List.<JCExpression>of(maker.Ident(valueName)));
statements.append(maker.Exec(invokeAdd));
}
if (returnStatement != null) statements.append(returnStatement);
JCBlock body = maker.Block(0, statements.toList());
long paramFlags = JavacHandlerUtil.addFinalIfNeeded(Flags.PARAMETER, builderType.getContext());
Name name = data.getSingularName();
if (!fluent) name = builderType.toName(HandlerUtil.buildAccessorName("put", name.toString()));
JCExpression paramTypeKey = cloneParamType(0, maker, data.getTypeArgs(), builderType, source);
JCExpression paramTypeValue = cloneParamType(1, maker, data.getTypeArgs(), builderType, source);
List<JCAnnotation> typeUseAnnsKey = getTypeUseAnnotations(paramTypeKey);
List<JCAnnotation> typeUseAnnsValue = getTypeUseAnnotations(paramTypeValue);
paramTypeKey = removeTypeUseAnnotations(paramTypeKey);
paramTypeValue = removeTypeUseAnnotations(paramTypeValue);
JCModifiers paramModsKey = typeUseAnnsKey.isEmpty() ? maker.Modifiers(paramFlags) : maker.Modifiers(paramFlags, typeUseAnnsKey);
JCModifiers paramModsValue = typeUseAnnsValue.isEmpty() ? maker.Modifiers(paramFlags) : maker.Modifiers(paramFlags, typeUseAnnsValue);
JCVariableDecl paramKey = maker.VarDef(paramModsKey, keyName, paramTypeKey, null);
JCVariableDecl paramValue = maker.VarDef(paramModsValue, valueName, paramTypeValue, null);
JCMethodDecl method = maker.MethodDef(mods, name, returnType, typeParams, List.of(paramKey, paramValue), thrown, body, null);
recursiveSetGeneratedBy(method, source, builderType.getContext());
injectMethod(builderType, method);
return maker.If(cond, clearCalls, null);
}
private void generatePluralMethod(boolean deprecate, JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source, boolean fluent) {
List<JCTypeParameter> typeParams = List.nil();
@Override
protected ListBuffer<JCStatement> generateSingularMethodStatements(JavacTreeMaker maker, SingularData data, JavacNode builderType, JCTree source) {
Name keyName = builderType.toName(data.getSingularName().toString() + "Key");
Name valueName = builderType.toName(data.getSingularName().toString() + "Value");
ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>();
/* Generates: this.pluralname$key.add(singularnameKey); */
statements.append(generateSingularMethodAddStatement(maker, builderType, keyName, data.getPluralName() + "$key"));
/* Generates: this.pluralname$value.add(singularnameValue); */
statements.append(generateSingularMethodAddStatement(maker, builderType, valueName, data.getPluralName() + "$value"));
return statements;
}
@Override
protected List<JCVariableDecl> generateSingularMethodParameters(JavacTreeMaker maker, SingularData data, JavacNode builderType, JCTree source) {
Name keyName = builderType.toName(data.getSingularName().toString() + "Key");
Name valueName = builderType.toName(data.getSingularName().toString() + "Value");
JCVariableDecl paramKey = generateSingularMethodParameter(0, maker, data, builderType, source, keyName);
JCVariableDecl paramValue = generateSingularMethodParameter(1, maker, data, builderType, source, valueName);
return List.of(paramKey, paramValue);
}
@Override
protected ListBuffer<JCStatement> generatePluralMethodStatements(JavacTreeMaker maker, SingularData data, JavacNode builderType, JCTree source) {
List<JCExpression> jceBlank = List.nil();
JCModifiers mods = makeMods(maker, builderType, deprecate);
ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>();
statements.append(createConstructBuilderVarIfNeeded(maker, data, builderType, true, source));
long paramFlags = JavacHandlerUtil.addFinalIfNeeded(Flags.PARAMETER, builderType.getContext());
long baseFlags = JavacHandlerUtil.addFinalIfNeeded(0, builderType.getContext());
Name entryName = builderType.toName("$lombokEntry");
@@ -200,25 +148,20 @@ public class JavacJavaUtilMapSingularizer extends JavacJavaUtilSingularizer {
JCExpression entrySetInvocation = maker.Apply(jceBlank, maker.Select(maker.Ident(data.getPluralName()), builderType.toName("entrySet")), jceBlank);
JCStatement forEach = maker.ForeachLoop(maker.VarDef(maker.Modifiers(baseFlags), entryName, forEachType, null), entrySetInvocation, forEachBody);
statements.append(forEach);
if (returnStatement != null) statements.append(returnStatement);
JCBlock body = maker.Block(0, statements.toList());
Name name = data.getPluralName();
if (!fluent) name = builderType.toName(HandlerUtil.buildAccessorName("putAll", name.toString()));
JCExpression paramType = chainDots(builderType, "java", "util", "Map");
paramType = addTypeArgs(2, true, builderType, paramType, data.getTypeArgs(), source);
JCVariableDecl param = maker.VarDef(maker.Modifiers(paramFlags), data.getPluralName(), paramType, null);
JCMethodDecl method = maker.MethodDef(mods, name, returnType, typeParams, List.of(param), jceBlank, body, null);
recursiveSetGeneratedBy(method, source, builderType.getContext());
injectMethod(builderType, method);
return statements;
}
@Override
protected JCExpression getPluralMethodParamType(JavacNode builderType) {
return chainDots(builderType, "java", "util", "Map");
}
@Override
protected JCStatement createConstructBuilderVarIfNeeded(JavacTreeMaker maker, SingularData data, JavacNode builderType, JCTree source) {
return createConstructBuilderVarIfNeeded(maker, data, builderType, true, source);
}
@Override public void appendBuildCode(SingularData data, JavacNode builderType, JCTree source, ListBuffer<JCStatement> statements, Name targetVariableName, String builderVariable) {
if (useGuavaInstead(builderType)) {
guavaMapSingularizer.appendBuildCode(data, builderType, source, statements, targetVariableName, builderVariable);
return;
}
JavacTreeMaker maker = builderType.getTreeMaker();
if (data.getTargetFqn().equals("java.util.Map")) {
@@ -227,4 +170,14 @@ public class JavacJavaUtilMapSingularizer extends JavacJavaUtilSingularizer {
statements.appendList(createJavaUtilSimpleCreationAndFillStatements(maker, data, builderType, true, true, false, true, "TreeMap", source, builderVariable));
}
}
@Override
protected String getAddMethodName() {
return "put";
}
@Override
protected int getTypeArgumentsCount() {
return 2;
}
}
@@ -41,11 +41,6 @@ public class JavacJavaUtilSetSingularizer extends JavacJavaUtilListSetSingulariz
}
@Override public void appendBuildCode(SingularData data, JavacNode builderType, JCTree source, ListBuffer<JCStatement> statements, Name targetVariableName, String builderVariable) {
if (useGuavaInstead(builderType)) {
guavaListSetSingularizer.appendBuildCode(data, builderType, source, statements, targetVariableName, builderVariable);
return;
}
JavacTreeMaker maker = builderType.getTreeMaker();
if (data.getTargetFqn().equals("java.util.Set")) {
@@ -39,12 +39,6 @@ import lombok.javac.handlers.JavacSingularsRecipes.JavacSingularizer;
import lombok.javac.handlers.JavacSingularsRecipes.SingularData;
abstract class JavacJavaUtilSingularizer extends JavacSingularizer {
protected final JavacSingularizer guavaListSetSingularizer = new JavacGuavaSetListSingularizer();
protected final JavacSingularizer guavaMapSingularizer = new JavacGuavaMapSingularizer();
protected boolean useGuavaInstead(JavacNode node) {
return Boolean.TRUE.equals(node.getAst().readConfiguration(ConfigurationKeys.SINGULAR_USE_GUAVA));
}
protected List<JCStatement> createJavaUtilSetMapInitialCapacitySwitchStatements(JavacTreeMaker maker, SingularData data, JavacNode builderType, boolean mapMode, String emptyCollectionMethod, String singletonCollectionMethod, String targetType, JCTree source, String builderVariable) {
List<JCExpression> jceBlank = List.nil();