ecj @Builder @Singular support for j.u. sets and maps.

This commit is contained in:
Reinier Zwitserloot committed 2015-01-15 04:43:36 +01:00
1 parent d700d54ed6
commit a05360a8ea
16 files changed
+1810 -483

No files matched your search

+1 -1
View File
@@ -8,7 +8,7 @@ statuses = status
aliases = alias
alias = !
species = !
Axes = axis
Axes = !
-axes = axe
sexes = sex
Testes = testis
@@ -143,7 +143,7 @@ public class EclipseHandlerUtil {
return getGeneratedBy(node) != null;
}
public static ASTNode setGeneratedBy(ASTNode node, ASTNode source) {
public static <T extends ASTNode> T setGeneratedBy(T node, ASTNode source) {
ASTNode_generatedBy.set(node, source);
return node;
}
@@ -298,6 +298,10 @@ public class EclipseHandlerUtil {
return new SingleTypeReference(typeName, p);
}
public static TypeReference[] copyTypes(TypeReference[] refs) {
return copyTypes(refs, null);
}
/**
* Convenience method that creates a new array and copies each TypeReference in the source array via
* {@link #copyType(TypeReference, ASTNode)}.
@@ -312,6 +316,10 @@ public class EclipseHandlerUtil {
return outs;
}
public static TypeReference copyType(TypeReference ref) {
return copyType(ref, null);
}
/**
* You can't share TypeReference objects or subtle errors start happening.
* Unfortunately the TypeReference type hierarchy is complicated and there's no clone
@@ -336,22 +344,23 @@ public class EclipseHandlerUtil {
}
}
}
TypeReference typeRef = new ParameterizedQualifiedTypeReference(iRef.tokens, args, iRef.dimensions(), copy(iRef.sourcePositions));
setGeneratedBy(typeRef, source);
if (source != null) setGeneratedBy(typeRef, source);
return typeRef;
}
if (ref instanceof ArrayQualifiedTypeReference) {
ArrayQualifiedTypeReference iRef = (ArrayQualifiedTypeReference) ref;
TypeReference typeRef = new ArrayQualifiedTypeReference(iRef.tokens, iRef.dimensions(), copy(iRef.sourcePositions));
setGeneratedBy(typeRef, source);
if (source != null) setGeneratedBy(typeRef, source);
return typeRef;
}
if (ref instanceof QualifiedTypeReference) {
QualifiedTypeReference iRef = (QualifiedTypeReference) ref;
TypeReference typeRef = new QualifiedTypeReference(iRef.tokens, copy(iRef.sourcePositions));
setGeneratedBy(typeRef, source);
if (source != null) setGeneratedBy(typeRef, source);
return typeRef;
}
@@ -368,14 +377,14 @@ public class EclipseHandlerUtil {
}
TypeReference typeRef = new ParameterizedSingleTypeReference(iRef.token, args, iRef.dimensions(), (long)iRef.sourceStart << 32 | iRef.sourceEnd);
setGeneratedBy(typeRef, source);
if (source != null) setGeneratedBy(typeRef, source);
return typeRef;
}
if (ref instanceof ArrayTypeReference) {
ArrayTypeReference iRef = (ArrayTypeReference) ref;
TypeReference typeRef = new ArrayTypeReference(iRef.token, iRef.dimensions(), (long)iRef.sourceStart << 32 | iRef.sourceEnd);
setGeneratedBy(typeRef, source);
if (source != null) setGeneratedBy(typeRef, source);
return typeRef;
}
@@ -386,14 +395,14 @@ public class EclipseHandlerUtil {
wildcard.sourceStart = original.sourceStart;
wildcard.sourceEnd = original.sourceEnd;
if (original.bound != null) wildcard.bound = copyType(original.bound, source);
setGeneratedBy(wildcard, source);
if (source != null) setGeneratedBy(wildcard, source);
return wildcard;
}
if (ref instanceof SingleTypeReference) {
SingleTypeReference iRef = (SingleTypeReference) ref;
TypeReference typeRef = new SingleTypeReference(iRef.token, (long)iRef.sourceStart << 32 | iRef.sourceEnd);
setGeneratedBy(typeRef, source);
if (source != null) setGeneratedBy(typeRef, source);
return typeRef;
}
@@ -444,8 +453,12 @@ public class EclipseHandlerUtil {
return typeMatches(type, node, ((Annotation)node.get()).type);
}
public static TypeReference cloneSelfType(EclipseNode context) {
return cloneSelfType(context, null);
}
public static TypeReference cloneSelfType(EclipseNode context, ASTNode source) {
int pS = source.sourceStart, pE = source.sourceEnd;
int pS = source == null ? 0 : source.sourceStart, pE = source == null ? 0 : source.sourceEnd;
long p = (long)pS << 32 | pE;
EclipseNode type = context;
TypeReference result = null;
@@ -457,7 +470,7 @@ public class EclipseHandlerUtil {
int idx = 0;
for (TypeParameter param : typeDecl.typeParameters) {
TypeReference typeRef = new SingleTypeReference(param.name, (long)param.sourceStart << 32 | param.sourceEnd);
setGeneratedBy(typeRef, source);
if (source != null) setGeneratedBy(typeRef, source);
refs[idx++] = typeRef;
}
result = new ParameterizedSingleTypeReference(typeDecl.name, refs, 0, p);
@@ -465,7 +478,7 @@ public class EclipseHandlerUtil {
result = new SingleTypeReference(((TypeDeclaration)type.get()).name, p);
}
}
if (result != null) setGeneratedBy(result, source);
if (result != null && source != null) setGeneratedBy(result, source);
return result;
}
@@ -865,7 +878,7 @@ public class EclipseHandlerUtil {
}
static Expression createFieldAccessor(EclipseNode field, FieldAccess fieldAccess, ASTNode source) {
int pS = source.sourceStart, pE = source.sourceEnd;
int pS = source == null ? 0 : source.sourceStart, pE = source == null ? 0 : source.sourceEnd;
long p = (long)pS << 32 | pE;
boolean lookForGetter = lookForGetter(field, fieldAccess);
@@ -881,14 +894,17 @@ public class EclipseHandlerUtil {
ref.receiver = new SingleNameReference(((TypeDeclaration)containerNode.get()).name, p);
} else {
Expression smallRef = new FieldReference(field.getName().toCharArray(), p);
setGeneratedBy(smallRef, source);
if (source != null) setGeneratedBy(smallRef, source);
return smallRef;
}
} else {
ref.receiver = new ThisReference(pS, pE);
}
setGeneratedBy(ref, source);
setGeneratedBy(ref.receiver, source);
if (source != null) {
setGeneratedBy(ref, source);
setGeneratedBy(ref.receiver, source);
}
return ref;
}
@@ -1489,7 +1505,7 @@ public class EclipseHandlerUtil {
* with eclipse versions before 3.7.
*/
public static IntLiteral makeIntLiteral(char[] token, ASTNode source) {
int pS = source.sourceStart, pE = source.sourceEnd;
int pS = source == null ? 0 : source.sourceStart, pE = source == null ? 0 : source.sourceEnd;
IntLiteral result;
try {
if (intLiteralConstructor != null) {
@@ -1504,7 +1520,8 @@ public class EclipseHandlerUtil {
} catch (InstantiationException e) {
throw Lombok.sneakyThrow(e);
}
setGeneratedBy(result, source);
if (source != null) setGeneratedBy(result, source);
return result;
}
@@ -0,0 +1,274 @@
package lombok.eclipse.handlers;
import static lombok.eclipse.handlers.EclipseHandlerUtil.*;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.jdt.internal.compiler.ast.ConditionalExpression;
import org.eclipse.jdt.internal.compiler.ast.EqualExpression;
import org.eclipse.jdt.internal.compiler.ast.Expression;
import org.eclipse.jdt.internal.compiler.ast.FieldReference;
import org.eclipse.jdt.internal.compiler.ast.IntLiteral;
import org.eclipse.jdt.internal.compiler.ast.MessageSend;
import org.eclipse.jdt.internal.compiler.ast.NullLiteral;
import org.eclipse.jdt.internal.compiler.ast.OperatorIds;
import org.eclipse.jdt.internal.compiler.ast.ParameterizedQualifiedTypeReference;
import org.eclipse.jdt.internal.compiler.ast.ParameterizedSingleTypeReference;
import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference;
import org.eclipse.jdt.internal.compiler.ast.SingleTypeReference;
import org.eclipse.jdt.internal.compiler.ast.Statement;
import org.eclipse.jdt.internal.compiler.ast.ThisReference;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.eclipse.jdt.internal.compiler.ast.Wildcard;
import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
import lombok.core.LombokImmutableList;
import lombok.core.SpiLoadUtil;
import lombok.core.TypeLibrary;
import lombok.eclipse.EclipseNode;
/*
* Copyright (C) 2015 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
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
public class EclipseSingularsRecipes {
private static final EclipseSingularsRecipes INSTANCE = new EclipseSingularsRecipes();
private final Map<String, EclipseSingularizer> singularizers = new HashMap<String, EclipseSingularizer>();
private final TypeLibrary singularizableTypes = new TypeLibrary();
private EclipseSingularsRecipes() {
try {
loadAll(singularizableTypes, singularizers);
singularizableTypes.lock();
} catch (IOException e) {
System.err.println("Lombok's @Singularizable feature is broken due to misconfigured SPI files: " + e);
}
}
private static void loadAll(TypeLibrary library, Map<String, EclipseSingularizer> map) throws IOException {
for (EclipseSingularizer handler : SpiLoadUtil.findServices(EclipseSingularizer.class, EclipseSingularizer.class.getClassLoader())) {
for (String type : handler.getSupportedTypes()) {
EclipseSingularizer existingSingularizer = map.get(type);
if (existingSingularizer != null) {
EclipseSingularizer toKeep = existingSingularizer.getClass().getName().compareTo(handler.getClass().getName()) > 0 ? handler : existingSingularizer;
System.err.println("Multiple singularizers found for type " + type + "; the alphabetically first class is used: " + toKeep.getClass().getName());
map.put(type, toKeep);
} else {
map.put(type, handler);
library.addType(type);
}
}
}
}
public static EclipseSingularsRecipes get() {
return INSTANCE;
}
public String toQualified(String typeReference) {
return singularizableTypes.toQualified(typeReference);
}
public EclipseSingularizer getSingularizer(String fqn) {
return singularizers.get(fqn);
}
public static final class SingularData {
private final EclipseNode annotation;
private final char[] singularName;
private final char[] pluralName;
private final List<TypeReference> typeArgs;
private final String targetFqn;
private final EclipseSingularizer singularizer;
public SingularData(EclipseNode annotation, char[] singularName, char[] pluralName, List<TypeReference> typeArgs, String targetFqn, EclipseSingularizer singularizer) {
this.annotation = annotation;
this.singularName = singularName;
this.pluralName = pluralName;
this.typeArgs = typeArgs;
this.targetFqn = targetFqn;
this.singularizer = singularizer;
}
public EclipseNode getAnnotation() {
return annotation;
}
public char[] getSingularName() {
return singularName;
}
public char[] getPluralName() {
return pluralName;
}
public List<TypeReference> getTypeArgs() {
return typeArgs;
}
public String getTargetFqn() {
return targetFqn;
}
public EclipseSingularizer getSingularizer() {
return singularizer;
}
public String getTargetSimpleType() {
int idx = targetFqn.lastIndexOf(".");
return idx == -1 ? targetFqn : targetFqn.substring(idx + 1);
}
}
public static abstract class EclipseSingularizer {
protected static final long[] NULL_POSS = {0L};
public abstract LombokImmutableList<String> getSupportedTypes();
public abstract java.util.List<EclipseNode> generateFields(SingularData data, EclipseNode builderType);
public abstract void generateMethods(SingularData data, EclipseNode builderType, boolean fluent, boolean chain);
public abstract void appendBuildCode(SingularData data, EclipseNode builderType, List<Statement> statements, char[] targetVariableName);
public boolean requiresCleaning() {
try {
return !getClass().getMethod("appendCleaningCode", SingularData.class, EclipseNode.class, List.class).getDeclaringClass().equals(EclipseSingularizer.class);
} catch (NoSuchMethodException e) {
return false;
}
}
public void appendCleaningCode(SingularData data, EclipseNode builderType, List<Statement> statements) {
}
// -- Utility methods --
/**
* Adds the requested number of type arguments to the provided type, copying each argument in {@code typeArgs}. If typeArgs is too long, the extra elements are ignored.
* If {@code typeArgs} is null or too short, {@code java.lang.Object} will be substituted for each missing type argument.
*
* @param count The number of type arguments requested.
* @param addExtends If {@code true}, all bounds are either '? extends X' or just '?'. If false, the reverse is applied, and '? extends Foo' is converted to Foo, '?' to Object, etc.
* @param node Some node in the same AST. Just used to obtain makers and contexts and such.
* @param type The type to add generics to.
* @param typeArgs the list of type args to clone.
* @param source The source annotation that is the root cause of this code generation.
*/
protected TypeReference addTypeArgs(int count, boolean addExtends, EclipseNode node, TypeReference type, List<TypeReference> typeArgs) {
if (count < 0) throw new IllegalArgumentException("count is negative");
if (count == 0) return type;
List<TypeReference> arguments = new ArrayList<TypeReference>();
if (typeArgs != null) for (TypeReference orig : typeArgs) {
Wildcard wildcard = orig instanceof Wildcard ? (Wildcard) orig : null;
if (!addExtends) {
if (wildcard != null && (wildcard.kind == Wildcard.UNBOUND || wildcard.kind == Wildcard.SUPER)) {
arguments.add(new QualifiedTypeReference(TypeConstants.JAVA_LANG_OBJECT, NULL_POSS));
} else if (wildcard != null && wildcard.kind == Wildcard.EXTENDS) {
try {
arguments.add(copyType(wildcard.bound));
} catch (Exception e) {
arguments.add(new QualifiedTypeReference(TypeConstants.JAVA_LANG_OBJECT, NULL_POSS));
}
} else {
arguments.add(copyType(orig));
}
} else {
if (wildcard != null && (wildcard.kind == Wildcard.UNBOUND || wildcard.kind == Wildcard.SUPER)) {
Wildcard w = new Wildcard(Wildcard.UNBOUND);
arguments.add(w);
} else if (wildcard != null && wildcard.kind == Wildcard.EXTENDS) {
arguments.add(copyType(orig));
} else {
Wildcard w = new Wildcard(Wildcard.EXTENDS);
w.bound = copyType(orig);
arguments.add(w);
}
}
if (--count == 0) break;
}
while (count-- > 0) {
if (addExtends) {
arguments.add(new Wildcard(Wildcard.UNBOUND));
} else {
arguments.add(new QualifiedTypeReference(TypeConstants.JAVA_LANG_OBJECT, NULL_POSS));
}
}
if (type instanceof SingleTypeReference) {
type = new ParameterizedSingleTypeReference(((SingleTypeReference) type).token, arguments.toArray(new TypeReference[arguments.size()]), 0, 0L);
} else if (type instanceof QualifiedTypeReference) {
QualifiedTypeReference qtr = (QualifiedTypeReference) type;
TypeReference[][] trs = new TypeReference[qtr.tokens.length][];
trs[qtr.tokens.length - 1] = arguments.toArray(new TypeReference[arguments.size()]);
type = new ParameterizedQualifiedTypeReference(((QualifiedTypeReference) type).tokens, trs, 0, NULL_POSS);
} else {
node.addError("Don't know how to clone-and-parameterize type: " + type);
}
return type;
}
private static final char[] SIZE_TEXT = new char[] {'s', 'i', 'z', 'e'};
/** Generates 'this.<em>name</em>.size()' as an expression; if nullGuard is true, it's this.name == null ? 0 : this.name.size(). */
protected Expression getSize(EclipseNode builderType, char[] name, boolean nullGuard) {
MessageSend invoke = new MessageSend();
ThisReference thisRef = new ThisReference(0, 0);
FieldReference thisDotName = new FieldReference(name, 0L);
thisDotName.receiver = thisRef;
invoke.receiver = thisDotName;
invoke.selector = SIZE_TEXT;
if (!nullGuard) return invoke;
ThisReference cdnThisRef = new ThisReference(0, 0);
FieldReference cdnThisDotName = new FieldReference(name, 0L);
cdnThisDotName.receiver = cdnThisRef;
NullLiteral nullLiteral = new NullLiteral(0, 0);
EqualExpression isNull = new EqualExpression(cdnThisDotName, nullLiteral, OperatorIds.EQUAL_EQUAL);
IntLiteral zeroLiteral = makeIntLiteral(new char[] {'0'}, null);
ConditionalExpression conditional = new ConditionalExpression(isNull, zeroLiteral, invoke);
return conditional;
}
protected TypeReference cloneParamType(int index, List<TypeReference> typeArgs, EclipseNode builderType) {
if (typeArgs != null && typeArgs.size() > index) {
TypeReference originalType = typeArgs.get(index);
if (originalType instanceof Wildcard) {
Wildcard wOriginalType = (Wildcard) originalType;
if (wOriginalType.kind == Wildcard.EXTENDS) {
try {
return copyType(wOriginalType.bound);
} catch (Exception e) {
// fallthrough
}
}
} else {
return copyType(originalType);
}
}
return new QualifiedTypeReference(TypeConstants.JAVA_LANG_OBJECT, NULL_POSS);
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2013-2014 The Project Lombok Authors.
* Copyright (C) 2013-2015 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
@@ -32,49 +32,74 @@ import java.util.List;
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration;
import org.eclipse.jdt.internal.compiler.ast.AllocationExpression;
import org.eclipse.jdt.internal.compiler.ast.Annotation;
import org.eclipse.jdt.internal.compiler.ast.Argument;
import org.eclipse.jdt.internal.compiler.ast.Assignment;
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
import org.eclipse.jdt.internal.compiler.ast.Expression;
import org.eclipse.jdt.internal.compiler.ast.FalseLiteral;
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
import org.eclipse.jdt.internal.compiler.ast.FieldReference;
import org.eclipse.jdt.internal.compiler.ast.IfStatement;
import org.eclipse.jdt.internal.compiler.ast.MessageSend;
import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.OperatorIds;
import org.eclipse.jdt.internal.compiler.ast.ParameterizedQualifiedTypeReference;
import org.eclipse.jdt.internal.compiler.ast.ParameterizedSingleTypeReference;
import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference;
import org.eclipse.jdt.internal.compiler.ast.ReturnStatement;
import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
import org.eclipse.jdt.internal.compiler.ast.SingleTypeReference;
import org.eclipse.jdt.internal.compiler.ast.Statement;
import org.eclipse.jdt.internal.compiler.ast.ThisReference;
import org.eclipse.jdt.internal.compiler.ast.TrueLiteral;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.ast.TypeParameter;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.eclipse.jdt.internal.compiler.ast.UnaryExpression;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
import org.mangosdk.spi.ProviderFor;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.ConfigurationKeys;
import lombok.Singular;
import lombok.core.AST.Kind;
import lombok.core.AnnotationValues;
import lombok.core.HandlerPriority;
import lombok.eclipse.Eclipse;
import lombok.eclipse.EclipseAnnotationHandler;
import lombok.eclipse.EclipseNode;
import lombok.eclipse.handlers.EclipseSingularsRecipes.EclipseSingularizer;
import lombok.eclipse.handlers.EclipseSingularsRecipes.SingularData;
import lombok.eclipse.handlers.HandleConstructor.SkipIfConstructorExists;
import lombok.experimental.NonFinal;
@ProviderFor(EclipseAnnotationHandler.class)
@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 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;
return ((Boolean) expr).booleanValue();
}
private static class BuilderFieldData {
TypeReference type;
char[] name;
SingularData singularData;
List<EclipseNode> createdFields = new ArrayList<EclipseNode>();
}
@Override public void handle(AnnotationValues<Builder> annotation, Annotation ast, EclipseNode annotationNode) {
handleExperimentalFlagUsage(annotationNode, ConfigurationKeys.BUILDER_FLAG_USAGE, "@Builder");
@@ -102,21 +127,21 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
EclipseNode parent = annotationNode.up();
List<TypeReference> typesOfParameters = new ArrayList<TypeReference>();
List<char[]> namesOfParameters = new ArrayList<char[]>();
List<BuilderFieldData> builderFields = new ArrayList<BuilderFieldData>();
TypeReference returnType;
TypeParameter[] typeParams;
TypeReference[] thrownExceptions;
char[] nameOfStaticBuilderMethod;
EclipseNode tdParent;
AbstractMethodDeclaration fillParametersFrom = null;
EclipseNode fillParametersFrom = parent.get() instanceof AbstractMethodDeclaration ? parent : null;
boolean addCleaning = false;
if (parent.get() instanceof TypeDeclaration) {
tdParent = parent;
TypeDeclaration td = (TypeDeclaration) tdParent.get();
List<EclipseNode> fields = new ArrayList<EclipseNode>();
List<EclipseNode> allFields = new ArrayList<EclipseNode>();
@SuppressWarnings("deprecation")
boolean valuePresent = (hasAnnotation(lombok.Value.class, parent) || hasAnnotation(lombok.experimental.Value.class, parent));
for (EclipseNode fieldNode : HandleConstructor.findAllFields(tdParent)) {
@@ -125,12 +150,15 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
// non-final fields final, but @Value's handler hasn't done this yet, so we have to do this math ourselves.
// Value will only skip making a field final if it has an explicit @NonFinal annotation, so we check for that.
if (fd.initialization != null && valuePresent && !hasAnnotation(NonFinal.class, fieldNode)) continue;
namesOfParameters.add(removePrefixFromField(fieldNode));
typesOfParameters.add(fd.type);
fields.add(fieldNode);
BuilderFieldData bfd = new BuilderFieldData();
bfd.name = removePrefixFromField(fieldNode);
bfd.type = fd.type;
bfd.singularData = getSingularData(fieldNode);
builderFields.add(bfd);
allFields.add(fieldNode);
}
new HandleConstructor().generateConstructor(tdParent, AccessLevel.PACKAGE, fields, null, SkipIfConstructorExists.I_AM_BUILDER, null,
new HandleConstructor().generateConstructor(tdParent, AccessLevel.PACKAGE, allFields, null, SkipIfConstructorExists.I_AM_BUILDER, null,
Collections.<Annotation>emptyList(), annotationNode);
returnType = namePlusTypeParamsToTypeReference(td.name, td.typeParameters, p);
@@ -147,7 +175,6 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
tdParent = parent.up();
TypeDeclaration td = (TypeDeclaration) tdParent.get();
fillParametersFrom = cd;
returnType = namePlusTypeParamsToTypeReference(td.name, td.typeParameters, p);
typeParams = td.typeParameters;
thrownExceptions = cd.thrownExceptions;
@@ -160,7 +187,6 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
annotationNode.addError("@Builder is only supported on types, constructors, and static methods.");
return;
}
fillParametersFrom = md;
returnType = copyType(md.returnType, ast);
typeParams = md.typeParameters;
thrownExceptions = md.thrownExceptions;
@@ -200,9 +226,14 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
}
if (fillParametersFrom != null) {
if (fillParametersFrom.arguments != null) for (Argument a : fillParametersFrom.arguments) {
namesOfParameters.add(a.name);
typesOfParameters.add(a.type);
for (EclipseNode param : fillParametersFrom.down()) {
if (param.getKind() != Kind.ARGUMENT) continue;
BuilderFieldData bfd = new BuilderFieldData();
Argument arg = (Argument) param.get();
bfd.name = arg.name;
bfd.type = arg.type;
bfd.singularData = getSingularData(param);
builderFields.add(bfd);
}
}
@@ -212,11 +243,23 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
} else {
sanityCheckForMethodGeneratingAnnotationsOnBuilderClass(builderType, annotationNode);
}
List<EclipseNode> fieldNodes = addFieldsToBuilder(builderType, namesOfParameters, typesOfParameters, ast);
List<AbstractMethodDeclaration> newMethods = new ArrayList<AbstractMethodDeclaration>();
for (EclipseNode fieldNode : fieldNodes) {
MethodDeclaration newMethod = makeSetterMethodForBuilder(builderType, fieldNode, annotationNode, fluent, chain);
if (newMethod != null) newMethods.add(newMethod);
for (BuilderFieldData bfd : builderFields) {
if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) {
if (bfd.singularData.getSingularizer().requiresCleaning()) {
addCleaning = true;
break;
}
}
}
generateBuilderFields(builderType, builderFields);
if (addCleaning) {
FieldDeclaration cleanDecl = new FieldDeclaration(CLEAN_FIELD_NAME, 0, -1);
cleanDecl.declarationSourceEnd = -1;
cleanDecl.modifiers = ClassFileConstants.AccPrivate;
cleanDecl.type = TypeReference.baseTypeReference(TypeIds.T_boolean, 0);
injectField(builderType, cleanDecl);
}
if (constructorExists(builderType) == MemberExistsResult.NOT_EXISTS) {
@@ -226,21 +269,119 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
if (cd != null) injectMethod(builderType, cd);
}
for (AbstractMethodDeclaration newMethod : newMethods) injectMethod(builderType, newMethod);
for (BuilderFieldData bfd : builderFields) {
makeSetterMethodsForBuilder(builderType, bfd, annotationNode, fluent, chain);
}
if (methodExists(buildMethodName, builderType, -1) == MemberExistsResult.NOT_EXISTS) {
MethodDeclaration md = generateBuildMethod(buildMethodName, nameOfStaticBuilderMethod, returnType, namesOfParameters, builderType, ast, thrownExceptions);
MethodDeclaration md = generateBuildMethod(buildMethodName, nameOfStaticBuilderMethod, returnType, builderFields, builderType, thrownExceptions, addCleaning);
if (md != null) injectMethod(builderType, md);
}
if (methodExists("toString", builderType, 0) == MemberExistsResult.NOT_EXISTS) {
List<EclipseNode> fieldNodes = new ArrayList<EclipseNode>();
for (BuilderFieldData bfd : builderFields) {
fieldNodes.addAll(bfd.createdFields);
}
MethodDeclaration md = HandleToString.createToString(builderType, fieldNodes, true, false, ast, FieldAccess.ALWAYS_FIELD);
if (md != null) injectMethod(builderType, md);
}
if (addCleaning) injectMethod(builderType, generateCleanMethod(builderFields, builderType));
if (methodExists(builderMethodName, tdParent, -1) == MemberExistsResult.NOT_EXISTS) {
MethodDeclaration md = generateBuilderMethod(builderMethodName, builderClassName, tdParent, typeParams, ast);
if (md != null) injectMethod(tdParent, md);
}
builderType.get().traverse(new SetGeneratedByVisitor(ast), null);
}
private MethodDeclaration generateCleanMethod(List<BuilderFieldData> builderFields, EclipseNode builderType) {
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));
MethodDeclaration decl =new MethodDeclaration(((CompilationUnitDeclaration) builderType.top().get()).compilationResult);
decl.selector = CLEAN_METHOD_NAME;
decl.modifiers = ClassFileConstants.AccPrivate;
decl.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
decl.returnType = TypeReference.baseTypeReference(TypeIds.T_void, 0);
decl.statements = statements.toArray(new Statement[0]);
return decl;
}
public MethodDeclaration generateBuildMethod(String name, char[] staticName, TypeReference returnType, List<BuilderFieldData> builderFields, EclipseNode type, TypeReference[] thrownExceptions, boolean addCleaning) {
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);
Expression notClean = new UnaryExpression(thisUnclean, OperatorIds.NOT);
MessageSend invokeClean = new MessageSend();
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.name);
}
}
List<Expression> args = new ArrayList<Expression>();
for (BuilderFieldData bfd : builderFields) {
args.add(new SingleNameReference(bfd.name, 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 = ClassFileConstants.AccPublic;
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);
allocationStatement.arguments = args.isEmpty() ? null : args.toArray(new Expression[args.size()]);
statements.add(new ReturnStatement(allocationStatement, 0, 0));
} else {
MessageSend invoke = new MessageSend();
invoke.selector = staticName;
invoke.receiver = new SingleNameReference(type.up().getName().toCharArray(), 0);
TypeParameter[] tps = ((TypeDeclaration) type.get()).typeParameters;
if (tps != null) {
TypeReference[] trs = new TypeReference[tps.length];
for (int i = 0; i < trs.length; i++) {
trs[i] = new SingleTypeReference(tps[i].name, 0);
}
invoke.typeArguments = trs;
}
invoke.arguments = args.isEmpty() ? null : args.toArray(new Expression[args.size()]);
if (returnType instanceof SingleTypeReference && Arrays.equals(TypeConstants.VOID, ((SingleTypeReference) returnType).token)) {
statements.add(invoke);
} else {
statements.add(new ReturnStatement(invoke, 0, 0));
}
}
out.statements = statements.isEmpty() ? null : statements.toArray(new Statement[statements.size()]);
return out;
}
public MethodDeclaration generateBuilderMethod(String builderMethodName, String builderClassName, EclipseNode type, TypeParameter[] typeParams, ASTNode source) {
@@ -262,92 +403,47 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
return out;
}
public MethodDeclaration generateBuildMethod(String name, char[] staticName, TypeReference returnType, List<char[]> fieldNames, EclipseNode type, ASTNode source, TypeReference[] thrownExceptions) {
int pS = source.sourceStart, pE = source.sourceEnd;
long p = (long) pS << 32 | pE;
MethodDeclaration out = new MethodDeclaration(
((CompilationUnitDeclaration) type.top().get()).compilationResult);
out.modifiers = ClassFileConstants.AccPublic;
TypeDeclaration typeDecl = (TypeDeclaration) type.get();
out.selector = name.toCharArray();
out.thrownExceptions = copyTypes(thrownExceptions, source);
out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
out.returnType = returnType;
List<Expression> assigns = new ArrayList<Expression>();
for (char[] fieldName : fieldNames) {
SingleNameReference nameRef = new SingleNameReference(fieldName, p);
assigns.add(nameRef);
public void generateBuilderFields(EclipseNode builderType, List<BuilderFieldData> builderFields) {
int len = builderFields.size();
List<EclipseNode> existing = new ArrayList<EclipseNode>();
for (EclipseNode child : builderType.down()) {
if (child.getKind() == Kind.FIELD) existing.add(child);
}
Statement statement;
if (staticName == null) {
AllocationExpression allocationStatement = new AllocationExpression();
allocationStatement.type = copyType(out.returnType, source);
allocationStatement.arguments = assigns.isEmpty() ? null : assigns.toArray(new Expression[assigns.size()]);
statement = new ReturnStatement(allocationStatement, (int)(p >> 32), (int)p);
} else {
MessageSend invoke = new MessageSend();
invoke.selector = staticName;
invoke.receiver = new SingleNameReference(type.up().getName().toCharArray(), p);
TypeParameter[] tps = ((TypeDeclaration) type.get()).typeParameters;
if (tps != null) {
TypeReference[] trs = new TypeReference[tps.length];
for (int i = 0; i < trs.length; i++) {
trs[i] = new SingleTypeReference(tps[i].name, p);
}
invoke.typeArguments = trs;
}
invoke.arguments = assigns.isEmpty() ? null : assigns.toArray(new Expression[assigns.size()]);
if (returnType instanceof SingleTypeReference && Arrays.equals(TypeConstants.VOID, ((SingleTypeReference) returnType).token)) {
statement = invoke;
} else {
statement = new ReturnStatement(invoke, (int)(p >> 32), (int)p);
}
}
out.statements = new Statement[] { statement };
out.traverse(new SetGeneratedByVisitor(source), typeDecl.scope);
return out;
}
public List<EclipseNode> addFieldsToBuilder(EclipseNode builderType, List<char[]> namesOfParameters, List<TypeReference> typesOfParameters, ASTNode source) {
int len = namesOfParameters.size();
TypeDeclaration td = (TypeDeclaration) builderType.get();
FieldDeclaration[] existing = td.fields;
if (existing == null) existing = new FieldDeclaration[0];
List<EclipseNode> out = new ArrayList<EclipseNode>();
top:
for (int i = len - 1; i >= 0; i--) {
char[] name = namesOfParameters.get(i);
for (FieldDeclaration exists : existing) {
if (Arrays.equals(exists.name, name)) {
out.add(builderType.getNodeFor(exists));
continue top;
BuilderFieldData bfd = builderFields.get(i);
if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) {
bfd.createdFields.addAll(bfd.singularData.getSingularizer().generateFields(bfd.singularData, builderType));
} else {
for (EclipseNode exists : existing) {
char[] n = ((FieldDeclaration) exists.get()).name;
if (Arrays.equals(n, bfd.name)) {
bfd.createdFields.add(exists);
continue top;
}
}
FieldDeclaration fd = new FieldDeclaration(bfd.name, 0, 0);
fd.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG;
fd.modifiers = ClassFileConstants.AccPrivate;
fd.type = copyType(bfd.type);
bfd.createdFields.add(injectField(builderType, fd));
}
TypeReference fieldReference = copyType(typesOfParameters.get(i), source);
FieldDeclaration newField = new FieldDeclaration(name, 0, 0);
newField.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG;
newField.modifiers = ClassFileConstants.AccPrivate;
newField.type = fieldReference;
out.add(injectField(builderType, newField));
}
Collections.reverse(out);
return out;
}
private static final AbstractMethodDeclaration[] EMPTY = {};
public MethodDeclaration makeSetterMethodForBuilder(EclipseNode builderType, EclipseNode fieldNode, EclipseNode sourceNode, boolean fluent, boolean chain) {
public void makeSetterMethodsForBuilder(EclipseNode builderType, BuilderFieldData bfd, EclipseNode sourceNode, boolean fluent, boolean chain) {
if (bfd.singularData == null || bfd.singularData.getSingularizer() == null) {
makeSimpleSetterMethodForBuilder(builderType, bfd.createdFields.get(0), sourceNode, fluent, chain);
} else {
bfd.singularData.getSingularizer().generateMethods(bfd.singularData, builderType, fluent, chain);
}
}
private void makeSimpleSetterMethodForBuilder(EclipseNode builderType, EclipseNode fieldNode, EclipseNode sourceNode, boolean fluent, boolean chain) {
TypeDeclaration td = (TypeDeclaration) builderType.get();
AbstractMethodDeclaration[] existing = td.methods;
if (existing == null) existing = EMPTY;
@@ -358,14 +454,15 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
for (int i = 0; i < len; i++) {
if (!(existing[i] instanceof MethodDeclaration)) continue;
char[] existingName = existing[i].selector;
if (Arrays.equals(name, existingName)) return null;
if (Arrays.equals(name, existingName)) return;
}
boolean isBoolean = isBoolean(fd.type);
String setterName = fluent ? fieldNode.getName() : toSetterName(builderType.getAst(), null, fieldNode.getName(), isBoolean);
return HandleSetter.createSetter(td, fieldNode, setterName, chain, ClassFileConstants.AccPublic,
MethodDeclaration setter = HandleSetter.createSetter(td, fieldNode, setterName, chain, ClassFileConstants.AccPublic,
sourceNode, Collections.<Annotation>emptyList(), Collections.<Annotation>emptyList());
injectMethod(builderType, setter);
}
public EclipseNode findInnerClass(EclipseNode parent, String name) {
@@ -388,4 +485,59 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
builder.traverse(new SetGeneratedByVisitor(source), (ClassScope) null);
return injectType(tdParent, builder);
}
/**
* Returns the explicitly requested singular annotation on this node (field
* or parameter), or null if there's no {@code @Singular} annotation on it.
*
* @param node The node (field or method param) to inspect for its name and potential {@code @Singular} annotation.
*/
private SingularData getSingularData(EclipseNode node) {
for (EclipseNode child : node.down()) {
if (child.getKind() == Kind.ANNOTATION && annotationTypeMatches(Singular.class, child)) {
char[] pluralName = node.getKind() == Kind.FIELD ? removePrefixFromField(node) : ((AbstractVariableDeclaration) node.get()).name;
AnnotationValues<Singular> ann = createAnnotation(Singular.class, child);
String explicitSingular = ann.getInstance().value();
if (explicitSingular.isEmpty()) {
explicitSingular = autoSingularize(node.getName());
if (explicitSingular == null) {
node.addError("Can't singularize this name; please specify the singular explicitly (i.e. @Singular(\"sheep\"))");
explicitSingular = pluralName.toString();
}
}
char[] singularName = explicitSingular.toCharArray();
TypeReference type = ((AbstractVariableDeclaration) node.get()).type;
TypeReference[] typeArgs = null;
String typeName;
if (type instanceof ParameterizedSingleTypeReference) {
typeArgs = ((ParameterizedSingleTypeReference) type).typeArguments;
typeName = new String(((ParameterizedSingleTypeReference) type).token);
} else if (type instanceof ParameterizedQualifiedTypeReference) {
TypeReference[][] tr = ((ParameterizedQualifiedTypeReference) type).typeArguments;
if (tr != null) typeArgs = tr[tr.length - 1];
char[][] tokens = ((ParameterizedQualifiedTypeReference) type).tokens;
StringBuilder sb = new StringBuilder();
for (int i = 0; i < tokens.length; i++) {
if (i > 0) sb.append(".");
sb.append(tokens[i]);
}
typeName = sb.toString();
} else {
typeName = type.toString();
}
String targetFqn = EclipseSingularsRecipes.get().toQualified(typeName);
EclipseSingularizer singularizer = EclipseSingularsRecipes.get().getSingularizer(targetFqn);
if (singularizer == null) {
node.addError("Lombok does not know how to create the singular-form builder methods for type '" + typeName + "'; they won't be generated.");
return null;
}
return new SingularData(child, singularName, pluralName, typeArgs == null ? Collections.<TypeReference>emptyList() : Arrays.asList(typeArgs), targetFqn, singularizer);
}
}
return null;
}
}
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,220 @@
/*
* Copyright (C) 2015 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
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package lombok.eclipse.handlers.singulars;
import static lombok.eclipse.Eclipse.*;
import static lombok.eclipse.handlers.EclipseHandlerUtil.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.eclipse.jdt.internal.compiler.ast.Argument;
import org.eclipse.jdt.internal.compiler.ast.Block;
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
import org.eclipse.jdt.internal.compiler.ast.Expression;
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
import org.eclipse.jdt.internal.compiler.ast.FieldReference;
import org.eclipse.jdt.internal.compiler.ast.ForeachStatement;
import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
import org.eclipse.jdt.internal.compiler.ast.MessageSend;
import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference;
import org.eclipse.jdt.internal.compiler.ast.ReturnStatement;
import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
import org.eclipse.jdt.internal.compiler.ast.Statement;
import org.eclipse.jdt.internal.compiler.ast.ThisReference;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
import org.mangosdk.spi.ProviderFor;
import lombok.core.LombokImmutableList;
import lombok.core.handlers.HandlerUtil;
import lombok.eclipse.EclipseNode;
import lombok.eclipse.handlers.EclipseSingularsRecipes.EclipseSingularizer;
import lombok.eclipse.handlers.EclipseSingularsRecipes.SingularData;
@ProviderFor(EclipseSingularizer.class)
public class EclipseJavaUtilMapSingularizer extends EclipseJavaUtilSingularizer {
@Override public LombokImmutableList<String> getSupportedTypes() {
return LombokImmutableList.of("java.util.Map", "java.util.SortedMap", "java.util.NavigableMap");
}
@Override public java.util.List<EclipseNode> generateFields(SingularData data, EclipseNode builderType) {
char[] keyName = (new String(data.getPluralName()) + "$key").toCharArray();
char[] valueName = (new String(data.getPluralName()) + "$value").toCharArray();
FieldDeclaration buildKeyField; {
TypeReference type = new QualifiedTypeReference(JAVA_UTIL_ARRAYLIST, NULL_POSS);
type = addTypeArgs(1, false, builderType, type, data.getTypeArgs());
buildKeyField = new FieldDeclaration(keyName, 0, -1);
buildKeyField.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
buildKeyField.modifiers = ClassFileConstants.AccPrivate;
buildKeyField.declarationSourceEnd = -1;
buildKeyField.type = type;
}
FieldDeclaration buildValueField; {
TypeReference type = new QualifiedTypeReference(JAVA_UTIL_ARRAYLIST, NULL_POSS);
List<TypeReference> tArgs = data.getTypeArgs();
if (tArgs != null && tArgs.size() > 1) tArgs = Collections.singletonList(tArgs.get(1));
else tArgs = Collections.emptyList();
type = addTypeArgs(1, false, builderType, type, tArgs);
buildValueField = new FieldDeclaration(valueName, 0, -1);
buildValueField.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
buildValueField.modifiers = ClassFileConstants.AccPrivate;
buildValueField.declarationSourceEnd = -1;
buildValueField.type = type;
}
EclipseNode valueFieldNode = injectField(builderType, buildValueField);
EclipseNode keyFieldNode = injectField(builderType, buildKeyField);
return Arrays.asList(keyFieldNode, valueFieldNode);
}
@Override public void generateMethods(SingularData data, EclipseNode builderType, boolean fluent, boolean chain) {
TypeReference returnType = chain ? cloneSelfType(builderType) : TypeReference.baseTypeReference(TypeIds.T_void, 0);
Statement returnStatement = chain ? new ReturnStatement(new ThisReference(0, 0), 0, 0) : null;
generateSingularMethod(returnType, returnStatement, data, builderType, fluent);
returnType = chain ? cloneSelfType(builderType) : TypeReference.baseTypeReference(TypeIds.T_void, 0);
returnStatement = chain ? new ReturnStatement(new ThisReference(0, 0), 0, 0) : null;
generatePluralMethod(returnType, returnStatement, data, builderType, fluent);
}
private void generateSingularMethod(TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType, boolean fluent) {
MethodDeclaration md = new MethodDeclaration(((CompilationUnitDeclaration) builderType.top().get()).compilationResult);
md.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
md.modifiers = ClassFileConstants.AccPublic;
List<Statement> statements = new ArrayList<Statement>();
statements.add(createConstructBuilderVarIfNeeded(data, builderType, true));
String sN = new String(data.getSingularName());
String pN = new String(data.getPluralName());
char[] keyParamName = (sN + "Key").toCharArray();
char[] valueParamName = (sN + "Value").toCharArray();
char[] keyFieldName = (pN + "$key").toCharArray();
char[] valueFieldName = (pN + "$value").toCharArray();
/* this.pluralname$key.add(singularnameKey); */ {
FieldReference thisDotKeyField = new FieldReference(keyFieldName, 0L);
thisDotKeyField.receiver = new ThisReference(0, 0);
MessageSend thisDotKeyFieldDotAdd = new MessageSend();
thisDotKeyFieldDotAdd.arguments = new Expression[] {new SingleNameReference(keyParamName, 0L)};
thisDotKeyFieldDotAdd.receiver = thisDotKeyField;
thisDotKeyFieldDotAdd.selector = "add".toCharArray();
statements.add(thisDotKeyFieldDotAdd);
}
/* this.pluralname$value.add(singularnameValue); */ {
FieldReference thisDotValueField = new FieldReference(valueFieldName, 0L);
thisDotValueField.receiver = new ThisReference(0, 0);
MessageSend thisDotValueFieldDotAdd = new MessageSend();
thisDotValueFieldDotAdd.arguments = new Expression[] {new SingleNameReference(valueParamName, 0L)};
thisDotValueFieldDotAdd.receiver = thisDotValueField;
thisDotValueFieldDotAdd.selector = "add".toCharArray();
statements.add(thisDotValueFieldDotAdd);
}
if (returnStatement != null) statements.add(returnStatement);
md.statements = statements.toArray(new Statement[statements.size()]);
TypeReference keyParamType = cloneParamType(0, data.getTypeArgs(), builderType);
Argument keyParam = new Argument(keyParamName, 0, keyParamType, 0);
TypeReference valueParamType = cloneParamType(1, data.getTypeArgs(), builderType);
Argument valueParam = new Argument(valueParamName, 0, valueParamType, 0);
md.arguments = new Argument[] {keyParam, valueParam};
md.returnType = returnType;
md.selector = fluent ? data.getSingularName() : HandlerUtil.buildAccessorName("put", new String(data.getSingularName())).toCharArray();
injectMethod(builderType, md);
}
private void generatePluralMethod(TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType, boolean fluent) {
MethodDeclaration md = new MethodDeclaration(((CompilationUnitDeclaration) builderType.top().get()).compilationResult);
md.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
md.modifiers = ClassFileConstants.AccPublic;
String pN = new String(data.getPluralName());
char[] keyFieldName = (pN + "$key").toCharArray();
char[] valueFieldName = (pN + "$value").toCharArray();
List<Statement> statements = new ArrayList<Statement>();
statements.add(createConstructBuilderVarIfNeeded(data, builderType, true));
char[] entryName = "$lombokEntry".toCharArray();
TypeReference forEachType = new QualifiedTypeReference(JAVA_UTIL_MAP_ENTRY, NULL_POSS);
forEachType = addTypeArgs(2, true, builderType, forEachType, data.getTypeArgs());
MessageSend keyArg = new MessageSend();
keyArg.receiver = new SingleNameReference(entryName, 0L);
keyArg.selector = "getKey".toCharArray();
MessageSend addKey = new MessageSend();
FieldReference thisDotKeyField = new FieldReference(keyFieldName, 0L);
thisDotKeyField.receiver = new ThisReference(0, 0);
addKey.receiver = thisDotKeyField;
addKey.selector = new char[] {'a', 'd', 'd'};
addKey.arguments = new Expression[] {keyArg};
MessageSend valueArg = new MessageSend();
valueArg.receiver = new SingleNameReference(entryName, 0L);
valueArg.selector = "getValue".toCharArray();
MessageSend addValue = new MessageSend();
FieldReference thisDotValueField = new FieldReference(valueFieldName, 0L);
thisDotValueField.receiver = new ThisReference(0, 0);
addValue.receiver = thisDotValueField;
addValue.selector = new char[] {'a', 'd', 'd'};
addValue.arguments = new Expression[] {valueArg};
LocalDeclaration elementVariable = new LocalDeclaration(entryName, 0, 0);
elementVariable.type = forEachType;
ForeachStatement forEach = new ForeachStatement(elementVariable, 0);
MessageSend invokeEntrySet = new MessageSend();
invokeEntrySet.selector = new char[] { 'e', 'n', 't', 'r', 'y', 'S', 'e', 't'};
invokeEntrySet.receiver = new SingleNameReference(data.getPluralName(), 0L);
forEach.collection = invokeEntrySet;
Block forEachContent = new Block(0);
forEachContent.statements = new Statement[] {addKey, addValue};
forEach.action = forEachContent;
statements.add(forEach);
if (returnStatement != null) statements.add(returnStatement);
md.statements = statements.toArray(new Statement[statements.size()]);
TypeReference paramType = new QualifiedTypeReference(JAVA_UTIL_MAP, NULL_POSS);
paramType = addTypeArgs(2, true, builderType, paramType, data.getTypeArgs());
Argument param = new Argument(data.getPluralName(), 0, paramType, 0);
md.arguments = new Argument[] {param};
md.returnType = returnType;
md.selector = fluent ? data.getPluralName() : HandlerUtil.buildAccessorName("putAll", new String(data.getPluralName())).toCharArray();
injectMethod(builderType, md);
}
@Override public void appendBuildCode(SingularData data, EclipseNode builderType, List<Statement> statements, char[] targetVariableName) {
if (data.getTargetFqn().equals("java.util.Map")) {
statements.addAll(createJavaUtilSetMapInitialCapacitySwitchStatements(data, builderType, true, "emptyMap", "singletonMap", "LinkedHashMap"));
} else {
statements.addAll(createJavaUtilSimpleCreationAndFillStatements(data, builderType, true, true, false, true, "TreeMap"));
}
}
}
@@ -0,0 +1,146 @@
/*
* Copyright (C) 2015 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
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package lombok.eclipse.handlers.singulars;
import static lombok.eclipse.Eclipse.*;
import static lombok.eclipse.handlers.EclipseHandlerUtil.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import lombok.core.LombokImmutableList;
import lombok.core.handlers.HandlerUtil;
import lombok.eclipse.EclipseNode;
import lombok.eclipse.handlers.EclipseSingularsRecipes.EclipseSingularizer;
import lombok.eclipse.handlers.EclipseSingularsRecipes.SingularData;
import org.eclipse.jdt.internal.compiler.ast.Argument;
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
import org.eclipse.jdt.internal.compiler.ast.Expression;
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
import org.eclipse.jdt.internal.compiler.ast.FieldReference;
import org.eclipse.jdt.internal.compiler.ast.MessageSend;
import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference;
import org.eclipse.jdt.internal.compiler.ast.ReturnStatement;
import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
import org.eclipse.jdt.internal.compiler.ast.Statement;
import org.eclipse.jdt.internal.compiler.ast.ThisReference;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
import org.mangosdk.spi.ProviderFor;
@ProviderFor(EclipseSingularizer.class)
public class EclipseJavaUtilSetSingularizer extends EclipseJavaUtilSingularizer {
@Override public LombokImmutableList<String> getSupportedTypes() {
return LombokImmutableList.of("java.util.Set", "java.util.SortedSet", "java.util.NavigableSet");
}
@Override public List<EclipseNode> generateFields(SingularData data, EclipseNode builderType) {
TypeReference type = new QualifiedTypeReference(JAVA_UTIL_ARRAYLIST, NULL_POSS);
type = addTypeArgs(1, false, builderType, type, data.getTypeArgs());
FieldDeclaration buildField = new FieldDeclaration(data.getPluralName(), 0, -1);
buildField.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
buildField.modifiers = ClassFileConstants.AccPrivate;
buildField.declarationSourceEnd = -1;
buildField.type = type;
return Collections.singletonList(injectField(builderType, buildField));
}
@Override public void generateMethods(SingularData data, EclipseNode builderType, boolean fluent, boolean chain) {
TypeReference returnType = chain ? cloneSelfType(builderType) : TypeReference.baseTypeReference(TypeIds.T_void, 0);
Statement returnStatement = chain ? new ReturnStatement(new ThisReference(0, 0), 0, 0) : null;
generateSingularMethod(returnType, returnStatement, data, builderType, fluent);
returnType = chain ? cloneSelfType(builderType) : TypeReference.baseTypeReference(TypeIds.T_void, 0);
returnStatement = chain ? new ReturnStatement(new ThisReference(0, 0), 0, 0) : null;
generatePluralMethod(returnType, returnStatement, data, builderType, fluent);
}
private void generateSingularMethod(TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType, boolean fluent) {
MethodDeclaration md = new MethodDeclaration(((CompilationUnitDeclaration) builderType.top().get()).compilationResult);
md.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
md.modifiers = ClassFileConstants.AccPublic;
List<Statement> statements = new ArrayList<Statement>();
statements.add(createConstructBuilderVarIfNeeded(data, builderType, false));
FieldReference thisDotField = new FieldReference(data.getPluralName(), 0L);
thisDotField.receiver = new ThisReference(0, 0);
MessageSend thisDotFieldDotAdd = new MessageSend();
thisDotFieldDotAdd.arguments = new Expression[] {new SingleNameReference(data.getSingularName(), 0L)};
thisDotFieldDotAdd.receiver = thisDotField;
thisDotFieldDotAdd.selector = "add".toCharArray();
statements.add(thisDotFieldDotAdd);
if (returnStatement != null) statements.add(returnStatement);
md.statements = statements.toArray(new Statement[statements.size()]);
TypeReference paramType = cloneParamType(0, data.getTypeArgs(), builderType);
Argument param = new Argument(data.getSingularName(), 0, paramType, 0);
md.arguments = new Argument[] {param};
md.returnType = returnType;
md.selector = fluent ? data.getSingularName() : HandlerUtil.buildAccessorName("add", new String(data.getSingularName())).toCharArray();
injectMethod(builderType, md);
}
private void generatePluralMethod(TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType, boolean fluent) {
MethodDeclaration md = new MethodDeclaration(((CompilationUnitDeclaration) builderType.top().get()).compilationResult);
md.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
md.modifiers = ClassFileConstants.AccPublic;
List<Statement> statements = new ArrayList<Statement>();
statements.add(createConstructBuilderVarIfNeeded(data, builderType, false));
FieldReference thisDotField = new FieldReference(data.getPluralName(), 0L);
thisDotField.receiver = new ThisReference(0, 0);
MessageSend thisDotFieldDotAddAll = new MessageSend();
thisDotFieldDotAddAll.arguments = new Expression[] {new SingleNameReference(data.getPluralName(), 0L)};
thisDotFieldDotAddAll.receiver = thisDotField;
thisDotFieldDotAddAll.selector = "addAll".toCharArray();
statements.add(thisDotFieldDotAddAll);
if (returnStatement != null) statements.add(returnStatement);
md.statements = statements.toArray(new Statement[statements.size()]);
TypeReference paramType = new QualifiedTypeReference(TypeConstants.JAVA_UTIL_COLLECTION, NULL_POSS);
paramType = addTypeArgs(1, true, builderType, paramType, data.getTypeArgs());
Argument param = new Argument(data.getPluralName(), 0, paramType, 0);
md.arguments = new Argument[] {param};
md.returnType = returnType;
md.selector = fluent ? data.getPluralName() : HandlerUtil.buildAccessorName("addAll", new String(data.getPluralName())).toCharArray();
injectMethod(builderType, md);
}
@Override public void appendBuildCode(SingularData data, EclipseNode builderType, List<Statement> statements, char[] targetVariableName) {
if (data.getTargetFqn().equals("java.util.Set")) {
statements.addAll(createJavaUtilSetMapInitialCapacitySwitchStatements(data, builderType, false, "emptySet", "singleton", "LinkedHashSet"));
} else {
statements.addAll(createJavaUtilSimpleCreationAndFillStatements(data, builderType, false, true, false, true, "TreeSet"));
}
}
}
@@ -0,0 +1,288 @@
/*
* Copyright (C) 2015 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
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package lombok.eclipse.handlers.singulars;
import static lombok.eclipse.Eclipse.*;
import static lombok.eclipse.handlers.EclipseHandlerUtil.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.eclipse.jdt.internal.compiler.ast.AllocationExpression;
import org.eclipse.jdt.internal.compiler.ast.Assignment;
import org.eclipse.jdt.internal.compiler.ast.BinaryExpression;
import org.eclipse.jdt.internal.compiler.ast.Block;
import org.eclipse.jdt.internal.compiler.ast.BreakStatement;
import org.eclipse.jdt.internal.compiler.ast.CaseStatement;
import org.eclipse.jdt.internal.compiler.ast.ConditionalExpression;
import org.eclipse.jdt.internal.compiler.ast.EqualExpression;
import org.eclipse.jdt.internal.compiler.ast.Expression;
import org.eclipse.jdt.internal.compiler.ast.FieldReference;
import org.eclipse.jdt.internal.compiler.ast.ForStatement;
import org.eclipse.jdt.internal.compiler.ast.IfStatement;
import org.eclipse.jdt.internal.compiler.ast.IntLiteral;
import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
import org.eclipse.jdt.internal.compiler.ast.MessageSend;
import org.eclipse.jdt.internal.compiler.ast.NullLiteral;
import org.eclipse.jdt.internal.compiler.ast.OperatorIds;
import org.eclipse.jdt.internal.compiler.ast.PostfixExpression;
import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference;
import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference;
import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
import org.eclipse.jdt.internal.compiler.ast.Statement;
import org.eclipse.jdt.internal.compiler.ast.SwitchStatement;
import org.eclipse.jdt.internal.compiler.ast.ThisReference;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
import lombok.eclipse.EclipseNode;
import lombok.eclipse.handlers.EclipseSingularsRecipes.EclipseSingularizer;
import lombok.eclipse.handlers.EclipseSingularsRecipes.SingularData;
abstract class EclipseJavaUtilSingularizer extends EclipseSingularizer {
protected static final char[][] JAVA_UTIL_ARRAYLIST = {
{'j', 'a', 'v', 'a'}, {'u', 't', 'i', 'l'}, {'A', 'r', 'r', 'a', 'y', 'L', 'i', 's', 't'}
};
protected static final char[][] JAVA_UTIL_MAP = {
{'j', 'a', 'v', 'a'}, {'u', 't', 'i', 'l'}, {'M', 'a', 'p'}
};
protected static final char[][] JAVA_UTIL_MAP_ENTRY = {
{'j', 'a', 'v', 'a'}, {'u', 't', 'i', 'l'}, {'M', 'a', 'p'}, {'E', 'n', 't', 'r', 'y'}
};
protected static final char[][] JAVA_UTIL_COLLECTIONS = {
{'j', 'a', 'v', 'a'}, {'u', 't', 'i', 'l'}, {'C', 'o', 'l', 'l', 'e', 'c', 't', 'i', 'o', 'n', 's'}
};
protected List<Statement> createJavaUtilSetMapInitialCapacitySwitchStatements(SingularData data, EclipseNode builderType, boolean mapMode, String emptyCollectionMethod, String singletonCollectionMethod, String targetType) {
List<Statement> switchContents = new ArrayList<Statement>();
char[] keyName = mapMode ? (new String(data.getPluralName()) + "$key").toCharArray() : data.getPluralName();
if (emptyCollectionMethod != null) { // case 0: (empty); break;
switchContents.add(new CaseStatement(makeIntLiteral(new char[] {'0'}, null), 0, 0));
/* pluralName = java.util.Collections.emptyCollectionMethod(); */ {
MessageSend invoke = new MessageSend();
invoke.receiver = new QualifiedNameReference(JAVA_UTIL_COLLECTIONS, NULL_POSS, 0, 0);
invoke.selector = emptyCollectionMethod.toCharArray();
switchContents.add(new Assignment(new SingleNameReference(data.getPluralName(), 0), invoke, 0));
}
switchContents.add(new BreakStatement(null, 0, 0));
}
if (singletonCollectionMethod != null) { // case 1: (singleton); break;
switchContents.add(new CaseStatement(makeIntLiteral(new char[] {'1'}, null), 0, 0));
/* !mapMode: pluralName = java.util.Collections.singletonCollectionMethod(this.pluralName.get(0));
mapMode: pluralName = java.util.Collections.singletonCollectionMethod(this.pluralName$key.get(0), this.pluralName$value.get(0)); */ {
FieldReference thisDotKey = new FieldReference(keyName, 0L);
thisDotKey.receiver = new ThisReference(0, 0);
MessageSend thisDotKeyGet0 = new MessageSend();
thisDotKeyGet0.receiver = thisDotKey;
thisDotKeyGet0.selector = new char[] {'g', 'e', 't'};
thisDotKeyGet0.arguments = new Expression[] {makeIntLiteral(new char[] {'0'}, null)};
Expression[] args;
if (mapMode) {
char[] valueName = (new String(data.getPluralName()) + "$value").toCharArray();
FieldReference thisDotValue = new FieldReference(valueName, 0L);
thisDotValue.receiver = new ThisReference(0, 0);
MessageSend thisDotValueGet0 = new MessageSend();
thisDotValueGet0.receiver = thisDotValue;
thisDotValueGet0.selector = new char[] {'g', 'e', 't'};
thisDotValueGet0.arguments = new Expression[] {makeIntLiteral(new char[] {'0'}, null)};
args = new Expression[] {thisDotKeyGet0, thisDotValueGet0};
} else {
args = new Expression[] {thisDotKeyGet0};
}
MessageSend invoke = new MessageSend();
invoke.receiver = new QualifiedNameReference(JAVA_UTIL_COLLECTIONS, NULL_POSS, 0, 0);
invoke.selector = singletonCollectionMethod.toCharArray();
invoke.arguments = args;
switchContents.add(new Assignment(new SingleNameReference(data.getPluralName(), 0), invoke, 0));
}
switchContents.add(new BreakStatement(null, 0, 0));
}
{ // default:
switchContents.add(new CaseStatement(null, 0, 0));
switchContents.addAll(createJavaUtilSimpleCreationAndFillStatements(data, builderType, mapMode, false, true, emptyCollectionMethod == null, targetType));
}
SwitchStatement switchStat = new SwitchStatement();
switchStat.statements = switchContents.toArray(new Statement[switchContents.size()]);
switchStat.expression = getSize(builderType, keyName, true);
TypeReference localShadowerType = new QualifiedTypeReference(fromQualifiedName(data.getTargetFqn()), NULL_POSS);
localShadowerType = addTypeArgs(mapMode ? 2 : 1, false, builderType, localShadowerType, data.getTypeArgs());
LocalDeclaration varDefStat = new LocalDeclaration(data.getPluralName(), 0, 0);
varDefStat.type = localShadowerType;
return Arrays.asList(varDefStat, switchStat);
}
protected List<Statement> createJavaUtilSimpleCreationAndFillStatements(SingularData data, EclipseNode builderType, boolean mapMode, boolean defineVar, boolean addInitialCapacityArg, boolean nullGuard, String targetType) {
char[] varName = mapMode ? (new String(data.getPluralName()) + "$key").toCharArray() : data.getPluralName();
Statement createStat; {
// pluralName = new java.util.TargetType(initialCap);
Expression[] constructorArgs = null;
if (addInitialCapacityArg) {
// this.varName.size() < MAX_POWER_OF_2 ? 1 + this.varName.size() + (this.varName.size() - 3) / 3 : Integer.MAX_VALUE;
// lessThanCutOff = this.varName.size() < MAX_POWER_OF_2
Expression lessThanCutoff = new BinaryExpression(getSize(builderType, varName, nullGuard), makeIntLiteral("0x40000000".toCharArray(), null), OperatorIds.LESS);
FieldReference integerMaxValue = new FieldReference("MAX_VALUE".toCharArray(), 0L);
integerMaxValue.receiver = new QualifiedNameReference(TypeConstants.JAVA_LANG_INTEGER, NULL_POSS, 0, 0);
Expression sizeFormulaLeft = new BinaryExpression(makeIntLiteral(new char[] {'1'}, null), getSize(builderType, varName, nullGuard), OperatorIds.PLUS);
Expression sizeFormulaRightLeft = new BinaryExpression(getSize(builderType, varName, nullGuard), makeIntLiteral(new char[] {'3'}, null), OperatorIds.MINUS);
Expression sizeFormulaRight = new BinaryExpression(sizeFormulaRightLeft, makeIntLiteral(new char[] {'3'}, null), OperatorIds.DIVIDE);
Expression sizeFormula = new BinaryExpression(sizeFormulaLeft, sizeFormulaRight, OperatorIds.PLUS);
Expression cond = new ConditionalExpression(lessThanCutoff, sizeFormula, integerMaxValue);
constructorArgs = new Expression[] {cond};
}
TypeReference targetTypeRef = new QualifiedTypeReference(new char[][] {TypeConstants.JAVA, TypeConstants.UTIL, targetType.toCharArray()}, NULL_POSS);
targetTypeRef = addTypeArgs(mapMode ? 2 : 1, false, builderType, targetTypeRef, data.getTypeArgs());
AllocationExpression constructorCall = new AllocationExpression();
constructorCall.type = targetTypeRef;
constructorCall.arguments = constructorArgs;
if (defineVar) {
TypeReference localShadowerType = new QualifiedTypeReference(fromQualifiedName(data.getTargetFqn()), NULL_POSS);
localShadowerType = addTypeArgs(mapMode ? 2 : 1, false, builderType, localShadowerType, data.getTypeArgs());
LocalDeclaration localShadowerDecl = new LocalDeclaration(data.getPluralName(), 0, 0);
localShadowerDecl.type = localShadowerType;
localShadowerDecl.initialization = constructorCall;
createStat = localShadowerDecl;
} else {
createStat = new Assignment(new SingleNameReference(data.getPluralName(), 0L), constructorCall, 0);
}
}
Statement fillStat; {
if (mapMode) {
// for (int $i = 0; $i < this.pluralname$key.size(); i++) pluralname.put(this.pluralname$key.get($i), this.pluralname$value.get($i));
char[] iVar = new char[] {'$', 'i'};
MessageSend pluralnameDotPut = new MessageSend();
pluralnameDotPut.selector = new char[] {'p', 'u', 't'};
pluralnameDotPut.receiver = new SingleNameReference(data.getPluralName(), 0L);
FieldReference thisDotKey = new FieldReference(varName, 0L);
thisDotKey.receiver = new ThisReference(0, 0);
FieldReference thisDotValue = new FieldReference((new String(data.getPluralName()) + "$value").toCharArray(), 0L);
thisDotValue.receiver = new ThisReference(0, 0);
MessageSend keyArg = new MessageSend();
keyArg.receiver = thisDotKey;
keyArg.arguments = new Expression[] {new SingleNameReference(iVar, 0L)};
keyArg.selector = new char[] {'g', 'e', 't'};
MessageSend valueArg = new MessageSend();
valueArg.receiver = thisDotValue;
valueArg.arguments = new Expression[] {new SingleNameReference(iVar, 0L)};
valueArg.selector = new char[] {'g', 'e', 't'};
pluralnameDotPut.arguments = new Expression[] {keyArg, valueArg};
LocalDeclaration forInit = new LocalDeclaration(iVar, 0, 0);
forInit.type = TypeReference.baseTypeReference(TypeIds.T_int, 0);
forInit.initialization = makeIntLiteral(new char[] {'0'}, null);
Expression checkExpr = new BinaryExpression(new SingleNameReference(iVar, 0L), getSize(builderType, varName, nullGuard), OperatorIds.LESS);
Expression incrementExpr = new PostfixExpression(new SingleNameReference(iVar, 0L), IntLiteral.One, OperatorIds.PLUS, 0);
fillStat = new ForStatement(new Statement[] {forInit}, checkExpr, new Statement[] {incrementExpr}, pluralnameDotPut, true, 0, 0);
} else {
// pluralname.addAll(this.pluralname);
MessageSend pluralnameDotAddAll = new MessageSend();
pluralnameDotAddAll.selector = new char[] {'a', 'd', 'd', 'A', 'l', 'l'};
pluralnameDotAddAll.receiver = new SingleNameReference(data.getPluralName(), 0L);
FieldReference thisDotPluralname = new FieldReference(varName, 0L);
thisDotPluralname.receiver = new ThisReference(0, 0);
pluralnameDotAddAll.arguments = new Expression[] {thisDotPluralname};
fillStat = pluralnameDotAddAll;
}
if (nullGuard) {
FieldReference thisDotField = new FieldReference(varName, 0L);
thisDotField.receiver = new ThisReference(0, 0);
Expression cond = new EqualExpression(thisDotField, new NullLiteral(0, 0), OperatorIds.NOT_EQUAL);
fillStat = new IfStatement(cond, fillStat, 0, 0);
}
}
Statement unmodifiableStat; {
// pluralname = Collections.unmodifiableInterfaceType(pluralname);
Expression arg = new SingleNameReference(data.getPluralName(), 0L);
MessageSend invoke = new MessageSend();
invoke.arguments = new Expression[] {arg};
invoke.selector = ("unmodifiable" + data.getTargetSimpleType()).toCharArray();
invoke.receiver = new QualifiedNameReference(JAVA_UTIL_COLLECTIONS, NULL_POSS, 0, 0);
unmodifiableStat = new Assignment(new SingleNameReference(data.getPluralName(), 0L), invoke, 0);
}
return Arrays.asList(createStat, fillStat, unmodifiableStat);
}
protected Statement createConstructBuilderVarIfNeeded(SingularData data, EclipseNode builderType, boolean mapMode) {
char[] v1Name, v2Name;
if (mapMode) {
String n = new String(data.getPluralName());
v1Name = (n + "$key").toCharArray();
v2Name = (n + "$value").toCharArray();
} else {
v1Name = data.getPluralName();
v2Name = null;
}
FieldReference thisDotField = new FieldReference(v1Name, 0L);
thisDotField.receiver = new ThisReference(0, 0);
Expression cond = new EqualExpression(thisDotField, new NullLiteral(0, 0), OperatorIds.EQUAL_EQUAL);
thisDotField = new FieldReference(v1Name, 0L);
thisDotField.receiver = new ThisReference(0, 0);
TypeReference v1Type = new QualifiedTypeReference(JAVA_UTIL_ARRAYLIST, NULL_POSS);
v1Type = addTypeArgs(1, false, builderType, v1Type, data.getTypeArgs());
AllocationExpression constructArrayList = new AllocationExpression();
constructArrayList.type = v1Type;
Assignment initV1 = new Assignment(thisDotField, constructArrayList, 0);
Statement thenPart;
if (mapMode) {
thisDotField = new FieldReference(v2Name, 0L);
thisDotField.receiver = new ThisReference(0, 0);
TypeReference v2Type = new QualifiedTypeReference(JAVA_UTIL_ARRAYLIST, NULL_POSS);
List<TypeReference> tArgs = data.getTypeArgs();
if (tArgs != null && tArgs.size() > 1) tArgs = Collections.singletonList(tArgs.get(1));
else tArgs = Collections.emptyList();
v2Type = addTypeArgs(1, false, builderType, v2Type, tArgs);
constructArrayList = new AllocationExpression();
constructArrayList.type = v2Type;
Assignment initV2 = new Assignment(thisDotField, constructArrayList, 0);
Block b = new Block(0);
b.statements = new Statement[] {initV1, initV2};
thenPart = b;
} else {
thenPart = initV1;
}
return new IfStatement(cond, thenPart, 0, 0);
}
}
@@ -156,6 +156,7 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
annotationNode.addError("@Builder is not supported on constructors with constructor type parameters.");
return;
}
tdParent = parent.up();
JCClassDecl td = (JCClassDecl) tdParent.get();
returnType = namePlusTypeParamsToTypeReference(tdParent.getTreeMaker(), td.name, td.typarams);
@@ -248,8 +249,8 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
if (cd != null) injectMethod(builderType, cd);
}
for (BuilderFieldData builderFieldData : builderFields) {
makeSetterMethodForBuilder(builderType, builderFieldData, annotationNode, fluent, chain);
for (BuilderFieldData bfd : builderFields) {
makeSetterMethodsForBuilder(builderType, bfd, annotationNode, fluent, chain);
}
if (methodExists(buildMethodName, builderType, -1) == MemberExistsResult.NOT_EXISTS) {
@@ -287,7 +288,7 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
}
}
statements.append(maker.Exec(maker.Assign(maker.Ident(type.toName("$lombokUnclean")), maker.Literal(CTC_BOOLEAN, false))));
statements.append(maker.Exec(maker.Assign(maker.Select(maker.Ident(type.toName("this")), type.toName("$lombokUnclean")), maker.Literal(CTC_BOOLEAN, false))));
JCBlock body = maker.Block(0, statements.toList());
return maker.MethodDef(maker.Modifiers(Flags.PUBLIC), type.toName("$lombokClean"), maker.Type(Javac.createVoidType(maker, CTC_VOID)), List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null);
/*
@@ -311,7 +312,7 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>();
if (addCleaning) {
JCExpression notClean = maker.Unary(CTC_NOT, maker.Ident(type.toName("$lombokUnclean")));
JCExpression notClean = maker.Unary(CTC_NOT, maker.Select(maker.Ident(type.toName("this")), type.toName("$lombokUnclean")));
JCStatement invokeClean = maker.Exec(maker.Apply(List.<JCExpression>nil(), maker.Ident(type.toName("$lombokClean")), List.<JCExpression>nil()));
JCIf ifUnclean = maker.If(notClean, invokeClean, null);
statements.append(ifUnclean);
@@ -329,7 +330,7 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
}
if (addCleaning) {
statements.append(maker.Exec(maker.Assign(maker.Ident(type.toName("$lombokUnclean")), maker.Literal(CTC_BOOLEAN, true))));
statements.append(maker.Exec(maker.Assign(maker.Select(maker.Ident(type.toName("this")), type.toName("$lombokUnclean")), maker.Literal(CTC_BOOLEAN, true))));
}
if (staticName == null) {
@@ -398,7 +399,7 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
}
}
public void makeSetterMethodForBuilder(JavacNode builderType, BuilderFieldData fieldNode, JavacNode source, boolean fluent, boolean chain) {
public void makeSetterMethodsForBuilder(JavacNode builderType, BuilderFieldData fieldNode, JavacNode source, boolean fluent, boolean chain) {
if (fieldNode.singularData == null || fieldNode.singularData.getSingularizer() == null) {
makeSimpleSetterMethodForBuilder(builderType, fieldNode.createdFields.get(0), source, fluent, chain);
} else {
@@ -143,7 +143,7 @@ public class JavacSingularsRecipes {
public boolean requiresCleaning() {
try {
return !getClass().getMethod("appendCleaningCode", ListBuffer.class).getDeclaringClass().equals(JavacSingularizer.class);
return !getClass().getMethod("appendCleaningCode", SingularData.class, JavacNode.class, JCTree.class, ListBuffer.class).getDeclaringClass().equals(JavacSingularizer.class);
} catch (NoSuchMethodException e) {
return false;
}
+1 -1
View File
@@ -29,7 +29,7 @@ import org.junit.Test;
public class TestSingulars {
@Test
public void testSingulars() {
assertEquals("axis", autoSingularize("axes"));
assertEquals(null, autoSingularize("axes"));
assertEquals("adjective", autoSingularize("adjectives"));
assertEquals("bus", autoSingularize("buses"));
assertEquals("octopus", autoSingularize("octopodes"));
@@ -0,0 +1,177 @@
import java.util.Map;
import java.util.SortedMap;
import lombok.Singular;
@lombok.Builder class BuilderSingletonMaps<K, V> {
public static @java.lang.SuppressWarnings("all") class BuilderSingletonMapsBuilder<K, V> {
private java.util.ArrayList<K> women$key;
private java.util.ArrayList<V> women$value;
private java.util.ArrayList<K> men$key;
private java.util.ArrayList<Number> men$value;
private java.util.ArrayList<java.lang.Object> rawMap$key;
private java.util.ArrayList<java.lang.Object> rawMap$value;
private java.util.ArrayList<String> stringMap$key;
private java.util.ArrayList<V> stringMap$value;
@java.lang.SuppressWarnings("all") BuilderSingletonMapsBuilder() {
super();
}
public @java.lang.SuppressWarnings("all") BuilderSingletonMapsBuilder<K, V> woman(K womanKey, V womanValue) {
if ((this.women$key == null))
{
this.women$key = new java.util.ArrayList<K>();
this.women$value = new java.util.ArrayList<V>();
}
this.women$key.add(womanKey);
this.women$value.add(womanValue);
return this;
}
public @java.lang.SuppressWarnings("all") BuilderSingletonMapsBuilder<K, V> women(java.util.Map<? extends K, ? extends V> women) {
if ((this.women$key == null))
{
this.women$key = new java.util.ArrayList<K>();
this.women$value = new java.util.ArrayList<V>();
}
for (java.util.Map.Entry<? extends K, ? extends V> $lombokEntry : women.entrySet())
{
this.women$key.add($lombokEntry.getKey());
this.women$value.add($lombokEntry.getValue());
}
return this;
}
public @java.lang.SuppressWarnings("all") BuilderSingletonMapsBuilder<K, V> man(K manKey, Number manValue) {
if ((this.men$key == null))
{
this.men$key = new java.util.ArrayList<K>();
this.men$value = new java.util.ArrayList<Number>();
}
this.men$key.add(manKey);
this.men$value.add(manValue);
return this;
}
public @java.lang.SuppressWarnings("all") BuilderSingletonMapsBuilder<K, V> men(java.util.Map<? extends K, ? extends Number> men) {
if ((this.men$key == null))
{
this.men$key = new java.util.ArrayList<K>();
this.men$value = new java.util.ArrayList<Number>();
}
for (java.util.Map.Entry<? extends K, ? extends Number> $lombokEntry : men.entrySet())
{
this.men$key.add($lombokEntry.getKey());
this.men$value.add($lombokEntry.getValue());
}
return this;
}
public @java.lang.SuppressWarnings("all") BuilderSingletonMapsBuilder<K, V> rawMap(java.lang.Object rawMapKey, java.lang.Object rawMapValue) {
if ((this.rawMap$key == null))
{
this.rawMap$key = new java.util.ArrayList<java.lang.Object>();
this.rawMap$value = new java.util.ArrayList<java.lang.Object>();
}
this.rawMap$key.add(rawMapKey);
this.rawMap$value.add(rawMapValue);
return this;
}
public @java.lang.SuppressWarnings("all") BuilderSingletonMapsBuilder<K, V> rawMap(java.util.Map<?, ?> rawMap) {
if ((this.rawMap$key == null))
{
this.rawMap$key = new java.util.ArrayList<java.lang.Object>();
this.rawMap$value = new java.util.ArrayList<java.lang.Object>();
}
for (java.util.Map.Entry<?, ?> $lombokEntry : rawMap.entrySet())
{
this.rawMap$key.add($lombokEntry.getKey());
this.rawMap$value.add($lombokEntry.getValue());
}
return this;
}
public @java.lang.SuppressWarnings("all") BuilderSingletonMapsBuilder<K, V> stringMap(String stringMapKey, V stringMapValue) {
if ((this.stringMap$key == null))
{
this.stringMap$key = new java.util.ArrayList<String>();
this.stringMap$value = new java.util.ArrayList<V>();
}
this.stringMap$key.add(stringMapKey);
this.stringMap$value.add(stringMapValue);
return this;
}
public @java.lang.SuppressWarnings("all") BuilderSingletonMapsBuilder<K, V> stringMap(java.util.Map<? extends String, ? extends V> stringMap) {
if ((this.stringMap$key == null))
{
this.stringMap$key = new java.util.ArrayList<String>();
this.stringMap$value = new java.util.ArrayList<V>();
}
for (java.util.Map.Entry<? extends String, ? extends V> $lombokEntry : stringMap.entrySet())
{
this.stringMap$key.add($lombokEntry.getKey());
this.stringMap$value.add($lombokEntry.getValue());
}
return this;
}
public @java.lang.SuppressWarnings("all") BuilderSingletonMaps<K, V> build() {
java.util.Map<K, V> women;
switch (((this.women$key == null) ? 0 : this.women$key.size())) {
case 0 :
women = java.util.Collections.emptyMap();
break;
case 1 :
women = java.util.Collections.singletonMap(this.women$key.get(0), this.women$value.get(0));
break;
default :
women = new java.util.LinkedHashMap<K, V>(((this.women$key.size() < 0x40000000) ? ((1 + this.women$key.size()) + ((this.women$key.size() - 3) / 3)) : java.lang.Integer.MAX_VALUE));
for (int $i = 0;; ($i < this.women$key.size()); $i ++)
women.put(this.women$key.get($i), this.women$value.get($i));
women = java.util.Collections.unmodifiableMap(women);
}
java.util.SortedMap<K, Number> men = new java.util.TreeMap<K, Number>();
if ((this.men$key != null))
for (int $i = 0;; ($i < ((this.men$key == null) ? 0 : this.men$key.size())); $i ++)
men.put(this.men$key.get($i), this.men$value.get($i));
men = java.util.Collections.unmodifiableSortedMap(men);
java.util.Map<java.lang.Object, java.lang.Object> rawMap;
switch (((this.rawMap$key == null) ? 0 : this.rawMap$key.size())) {
case 0 :
rawMap = java.util.Collections.emptyMap();
break;
case 1 :
rawMap = java.util.Collections.singletonMap(this.rawMap$key.get(0), this.rawMap$value.get(0));
break;
default :
rawMap = new java.util.LinkedHashMap<java.lang.Object, java.lang.Object>(((this.rawMap$key.size() < 0x40000000) ? ((1 + this.rawMap$key.size()) + ((this.rawMap$key.size() - 3) / 3)) : java.lang.Integer.MAX_VALUE));
for (int $i = 0;; ($i < this.rawMap$key.size()); $i ++)
rawMap.put(this.rawMap$key.get($i), this.rawMap$value.get($i));
rawMap = java.util.Collections.unmodifiableMap(rawMap);
}
java.util.Map<String, V> stringMap;
switch (((this.stringMap$key == null) ? 0 : this.stringMap$key.size())) {
case 0 :
stringMap = java.util.Collections.emptyMap();
break;
case 1 :
stringMap = java.util.Collections.singletonMap(this.stringMap$key.get(0), this.stringMap$value.get(0));
break;
default :
stringMap = new java.util.LinkedHashMap<String, V>(((this.stringMap$key.size() < 0x40000000) ? ((1 + this.stringMap$key.size()) + ((this.stringMap$key.size() - 3) / 3)) : java.lang.Integer.MAX_VALUE));
for (int $i = 0;; ($i < this.stringMap$key.size()); $i ++)
stringMap.put(this.stringMap$key.get($i), this.stringMap$value.get($i));
stringMap = java.util.Collections.unmodifiableMap(stringMap);
}
return new BuilderSingletonMaps<K, V>(women, men, rawMap, stringMap);
}
public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() {
return (((((((((((((((("BuilderSingletonMaps.BuilderSingletonMapsBuilder(women$key=" + this.women$key) + ", women$value=") + this.women$value) + ", men$key=") + this.men$key) + ", men$value=") + this.men$value) + ", rawMap$key=") + this.rawMap$key) + ", rawMap$value=") + this.rawMap$value) + ", stringMap$key=") + this.stringMap$key) + ", stringMap$value=") + this.stringMap$value) + ")");
}
}
private @Singular Map<K, V> women;
private @Singular SortedMap<K, ? extends Number> men;
private @SuppressWarnings("all") @Singular("rawMap") Map rawMap;
private @Singular("stringMap") Map<String, V> stringMap;
@java.lang.SuppressWarnings("all") BuilderSingletonMaps(final Map<K, V> women, final SortedMap<K, ? extends Number> men, final Map rawMap, final Map<String, V> stringMap) {
super();
this.women = women;
this.men = men;
this.rawMap = rawMap;
this.stringMap = stringMap;
}
public static @java.lang.SuppressWarnings("all") <K, V>BuilderSingletonMapsBuilder<K, V> builder() {
return new BuilderSingletonMapsBuilder<K, V>();
}
}
@@ -0,0 +1,125 @@
import java.util.Set;
import java.util.SortedSet;
import lombok.Singular;
@lombok.Builder class BuilderSingletonSets<T> {
public static @java.lang.SuppressWarnings("all") class BuilderSingletonSetsBuilder<T> {
private java.util.ArrayList<T> dangerMice;
private java.util.ArrayList<Number> octopodes;
private java.util.ArrayList<java.lang.Object> rawSet;
private java.util.ArrayList<String> stringSet;
@java.lang.SuppressWarnings("all") BuilderSingletonSetsBuilder() {
super();
}
public @java.lang.SuppressWarnings("all") BuilderSingletonSetsBuilder<T> dangerMouse(T dangerMouse) {
if ((this.dangerMice == null))
this.dangerMice = new java.util.ArrayList<T>();
this.dangerMice.add(dangerMouse);
return this;
}
public @java.lang.SuppressWarnings("all") BuilderSingletonSetsBuilder<T> dangerMice(java.util.Collection<? extends T> dangerMice) {
if ((this.dangerMice == null))
this.dangerMice = new java.util.ArrayList<T>();
this.dangerMice.addAll(dangerMice);
return this;
}
public @java.lang.SuppressWarnings("all") BuilderSingletonSetsBuilder<T> octopus(Number octopus) {
if ((this.octopodes == null))
this.octopodes = new java.util.ArrayList<Number>();
this.octopodes.add(octopus);
return this;
}
public @java.lang.SuppressWarnings("all") BuilderSingletonSetsBuilder<T> octopodes(java.util.Collection<? extends Number> octopodes) {
if ((this.octopodes == null))
this.octopodes = new java.util.ArrayList<Number>();
this.octopodes.addAll(octopodes);
return this;
}
public @java.lang.SuppressWarnings("all") BuilderSingletonSetsBuilder<T> rawSet(java.lang.Object rawSet) {
if ((this.rawSet == null))
this.rawSet = new java.util.ArrayList<java.lang.Object>();
this.rawSet.add(rawSet);
return this;
}
public @java.lang.SuppressWarnings("all") BuilderSingletonSetsBuilder<T> rawSet(java.util.Collection<?> rawSet) {
if ((this.rawSet == null))
this.rawSet = new java.util.ArrayList<java.lang.Object>();
this.rawSet.addAll(rawSet);
return this;
}
public @java.lang.SuppressWarnings("all") BuilderSingletonSetsBuilder<T> stringSet(String stringSet) {
if ((this.stringSet == null))
this.stringSet = new java.util.ArrayList<String>();
this.stringSet.add(stringSet);
return this;
}
public @java.lang.SuppressWarnings("all") BuilderSingletonSetsBuilder<T> stringSet(java.util.Collection<? extends String> stringSet) {
if ((this.stringSet == null))
this.stringSet = new java.util.ArrayList<String>();
this.stringSet.addAll(stringSet);
return this;
}
public @java.lang.SuppressWarnings("all") BuilderSingletonSets<T> build() {
java.util.Set<T> dangerMice;
switch (((this.dangerMice == null) ? 0 : this.dangerMice.size())) {
case 0 :
dangerMice = java.util.Collections.emptySet();
break;
case 1 :
dangerMice = java.util.Collections.singleton(this.dangerMice.get(0));
break;
default :
dangerMice = new java.util.LinkedHashSet<T>(((this.dangerMice.size() < 0x40000000) ? ((1 + this.dangerMice.size()) + ((this.dangerMice.size() - 3) / 3)) : java.lang.Integer.MAX_VALUE));
dangerMice.addAll(this.dangerMice);
dangerMice = java.util.Collections.unmodifiableSet(dangerMice);
}
java.util.SortedSet<Number> octopodes = new java.util.TreeSet<Number>();
if ((this.octopodes != null))
octopodes.addAll(this.octopodes);
octopodes = java.util.Collections.unmodifiableSortedSet(octopodes);
java.util.Set<java.lang.Object> rawSet;
switch (((this.rawSet == null) ? 0 : this.rawSet.size())) {
case 0 :
rawSet = java.util.Collections.emptySet();
break;
case 1 :
rawSet = java.util.Collections.singleton(this.rawSet.get(0));
break;
default :
rawSet = new java.util.LinkedHashSet<java.lang.Object>(((this.rawSet.size() < 0x40000000) ? ((1 + this.rawSet.size()) + ((this.rawSet.size() - 3) / 3)) : java.lang.Integer.MAX_VALUE));
rawSet.addAll(this.rawSet);
rawSet = java.util.Collections.unmodifiableSet(rawSet);
}
java.util.Set<String> stringSet;
switch (((this.stringSet == null) ? 0 : this.stringSet.size())) {
case 0 :
stringSet = java.util.Collections.emptySet();
break;
case 1 :
stringSet = java.util.Collections.singleton(this.stringSet.get(0));
break;
default :
stringSet = new java.util.LinkedHashSet<String>(((this.stringSet.size() < 0x40000000) ? ((1 + this.stringSet.size()) + ((this.stringSet.size() - 3) / 3)) : java.lang.Integer.MAX_VALUE));
stringSet.addAll(this.stringSet);
stringSet = java.util.Collections.unmodifiableSet(stringSet);
}
return new BuilderSingletonSets<T>(dangerMice, octopodes, rawSet, stringSet);
}
public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() {
return (((((((("BuilderSingletonSets.BuilderSingletonSetsBuilder(dangerMice=" + this.dangerMice) + ", octopodes=") + this.octopodes) + ", rawSet=") + this.rawSet) + ", stringSet=") + this.stringSet) + ")");
}
}
private @Singular Set<T> dangerMice;
private @Singular SortedSet<? extends Number> octopodes;
private @SuppressWarnings("all") @Singular("rawSet") Set rawSet;
private @Singular("stringSet") Set<String> stringSet;
@java.lang.SuppressWarnings("all") BuilderSingletonSets(final Set<T> dangerMice, final SortedSet<? extends Number> octopodes, final Set rawSet, final Set<String> stringSet) {
super();
this.dangerMice = dangerMice;
this.octopodes = octopodes;
this.rawSet = rawSet;
this.stringSet = stringSet;
}
public static @java.lang.SuppressWarnings("all") <T>BuilderSingletonSetsBuilder<T> builder() {
return new BuilderSingletonSetsBuilder<T>();
}
}
@@ -7,6 +7,6 @@ import lombok.Singular;
class BuilderSingletonMaps<K, V> {
@Singular private Map<K, V> women;
@Singular private SortedMap<K, ? extends Number> men;
@Singular("rawMap") private Map rawMap;
@SuppressWarnings("all") @Singular("rawMap") private Map rawMap;
@Singular("stringMap") private Map<String, V> stringMap;
}
@@ -7,6 +7,6 @@ import lombok.Singular;
class BuilderSingletonSets<T> {
@Singular private Set<T> dangerMice;
@Singular private SortedSet<? extends Number> octopodes;
@Singular("rawSet") private Set rawSet;
@SuppressWarnings("all") @Singular("rawSet") private Set rawSet;
@Singular("stringSet") private Set<String> stringSet;
}
@@ -57,4 +57,8 @@ public class TestWithEcj extends DirectoryRunner.TestParams {
public File getMessagesDirectory() {
return new File("test/transform/resource/messages-ecj");
}
@Override public boolean accept(File file) {
return file.getName().startsWith("BuilderSingleton");
}
}