aboutsummaryrefslogtreecommitdiff
path: root/src/core/lombok/eclipse
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/lombok/eclipse')
-rw-r--r--src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java74
-rw-r--r--src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java15
-rw-r--r--src/core/lombok/eclipse/handlers/HandleBuilder.java235
-rw-r--r--src/core/lombok/eclipse/handlers/HandleBuilderDefault.java46
-rw-r--r--src/core/lombok/eclipse/handlers/HandleConstructor.java35
-rw-r--r--src/core/lombok/eclipse/handlers/HandleData.java16
-rw-r--r--src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java98
-rw-r--r--src/core/lombok/eclipse/handlers/HandleGetter.java2
-rw-r--r--src/core/lombok/eclipse/handlers/HandleSetter.java13
-rw-r--r--src/core/lombok/eclipse/handlers/HandleToString.java6
-rw-r--r--src/core/lombok/eclipse/handlers/HandleVal.java14
-rw-r--r--src/core/lombok/eclipse/handlers/HandleValue.java16
-rw-r--r--src/core/lombok/eclipse/handlers/SetGeneratedByVisitor.java5
-rw-r--r--src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java21
-rw-r--r--src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java22
-rw-r--r--src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java23
16 files changed, 451 insertions, 190 deletions
diff --git a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java
index 4726b17e..6617d21a 100644
--- a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java
+++ b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2017 The Project Lombok Authors.
+ * Copyright (C) 2009-2018 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
@@ -167,6 +167,7 @@ public class EclipseHandlerUtil {
}
public static boolean isFieldDeprecated(EclipseNode fieldNode) {
+ if (!(fieldNode.get() instanceof FieldDeclaration)) return false;
FieldDeclaration field = (FieldDeclaration) fieldNode.get();
if ((field.modifiers & ClassFileConstants.AccDeprecated) != 0) {
return true;
@@ -196,17 +197,36 @@ public class EclipseHandlerUtil {
TypeResolver resolver = new TypeResolver(node.getImportList());
return resolver.typeMatches(node, type.getName(), typeName);
+ }
+
+ /**
+ * Checks if the given TypeReference node is likely to be a reference to the provided class.
+ *
+ * @param type An actual type. This method checks if {@code typeNode} is likely to be a reference to this type.
+ * @param node A Lombok AST node. Any node in the appropriate compilation unit will do (used to get access to import statements).
+ * @param typeRef A type reference to check.
+ */
+ public static boolean typeMatches(String type, EclipseNode node, TypeReference typeRef) {
+ if (typeRef == null || typeRef.getTypeName() == null || typeRef.getTypeName().length == 0) return false;
+ String lastPartA = new String(typeRef.getTypeName()[typeRef.getTypeName().length -1]);
+ int lastIndex = type.lastIndexOf('.');
+ String lastPartB = lastIndex == -1 ? type : type.substring(lastIndex + 1);
+ if (!lastPartA.equals(lastPartB)) return false;
+ String typeName = toQualifiedName(typeRef.getTypeName());
+ TypeResolver resolver = new TypeResolver(node.getImportList());
+ return resolver.typeMatches(node, type, typeName);
}
public static void sanityCheckForMethodGeneratingAnnotationsOnBuilderClass(EclipseNode typeNode, EclipseNode errorNode) {
List<String> disallowed = null;
for (EclipseNode child : typeNode.down()) {
if (child.getKind() != Kind.ANNOTATION) continue;
- for (Class<? extends java.lang.annotation.Annotation> annType : INVALID_ON_BUILDERS) {
+ for (String annType : INVALID_ON_BUILDERS) {
if (annotationTypeMatches(annType, child)) {
if (disallowed == null) disallowed = new ArrayList<String>();
- disallowed.add(annType.getSimpleName());
+ int lastIndex = annType.lastIndexOf('.');
+ disallowed.add(lastIndex == -1 ? annType : annType.substring(lastIndex + 1));
}
}
}
@@ -443,6 +463,42 @@ public class EclipseHandlerUtil {
}
}
+ public static boolean hasAnnotation(String type, EclipseNode node) {
+ if (node == null) return false;
+ if (type == null) return false;
+ switch (node.getKind()) {
+ case ARGUMENT:
+ case FIELD:
+ case LOCAL:
+ case TYPE:
+ case METHOD:
+ for (EclipseNode child : node.down()) {
+ if (annotationTypeMatches(type, child)) return true;
+ }
+ // intentional fallthrough
+ default:
+ return false;
+ }
+ }
+
+ public static EclipseNode findAnnotation(Class<? extends java.lang.annotation.Annotation> type, EclipseNode node) {
+ if (node == null) return null;
+ if (type == null) return null;
+ switch (node.getKind()) {
+ case ARGUMENT:
+ case FIELD:
+ case LOCAL:
+ case TYPE:
+ case METHOD:
+ for (EclipseNode child : node.down()) {
+ if (annotationTypeMatches(type, child)) return child;
+ }
+ // intentional fallthrough
+ default:
+ return null;
+ }
+ }
+
/**
* Checks if the provided annotation type is likely to be the intended type for the given annotation node.
*
@@ -453,6 +509,16 @@ public class EclipseHandlerUtil {
return typeMatches(type, node, ((Annotation) node.get()).type);
}
+ /**
+ * Checks if the provided annotation type is likely to be the intended type for the given annotation node.
+ *
+ * This is a guess, but a decent one.
+ */
+ public static boolean annotationTypeMatches(String type, EclipseNode node) {
+ if (node.getKind() != Kind.ANNOTATION) return false;
+ return typeMatches(type, node, ((Annotation) node.get()).type);
+ }
+
public static TypeReference cloneSelfType(EclipseNode context) {
return cloneSelfType(context, null);
}
@@ -831,7 +897,7 @@ public class EclipseHandlerUtil {
// Check if the class has a @Getter annotation.
- if (!hasGetterAnnotation && new HandleGetter().fieldQualifiesForGetterGeneration(field)) {
+ if (!hasGetterAnnotation && HandleGetter.fieldQualifiesForGetterGeneration(field)) {
//Check if the class has @Getter or @Data annotation.
EclipseNode containingType = field.up();
diff --git a/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java b/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java
index 10ed7fbb..2cec2388 100644
--- a/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java
+++ b/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015 The Project Lombok Authors.
+ * Copyright (C) 2015-2017 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
@@ -134,6 +134,10 @@ public class EclipseSingularsRecipes {
}
}
+ public ASTNode getSource() {
+ return source;
+ }
+
public EclipseNode getAnnotation() {
return annotation;
}
@@ -213,7 +217,7 @@ public class EclipseSingularsRecipes {
}
public abstract List<EclipseNode> generateFields(SingularData data, EclipseNode builderType);
- public abstract void generateMethods(SingularData data, EclipseNode builderType, boolean fluent, boolean chain);
+ public abstract void generateMethods(SingularData data, boolean deprecate, EclipseNode builderType, boolean fluent, boolean chain);
public abstract void appendBuildCode(SingularData data, EclipseNode builderType, List<Statement> statements, char[] targetVariableName, String builderVariable);
public boolean requiresCleaning() {
@@ -304,8 +308,7 @@ public class EclipseSingularsRecipes {
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().
- * @param builderVariable */
+ /** 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, String builderVariable) {
MessageSend invoke = new MessageSend();
Reference thisRef = getBuilderReference(builderVariable);
@@ -345,9 +348,7 @@ public class EclipseSingularsRecipes {
return new QualifiedTypeReference(TypeConstants.JAVA_LANG_OBJECT, NULL_POSS);
}
- /**
- * @return a {@link SingleNameReference} to the builder in the variable <code>builderVariable</code>. If <code>builderVariable == "this"</code>, a {@link ThisReference} is returned.
- */
+ /** @return a {@code SingleNameReference} to the builder in the variable <code>builderVariable</code>. If {@ code builderVariable == "this"}, a {@code ThisReference} is returned. */
protected static Reference getBuilderReference(String builderVariable) {
if ("this".equals(builderVariable)) {
return new ThisReference(0, 0);
diff --git a/src/core/lombok/eclipse/handlers/HandleBuilder.java b/src/core/lombok/eclipse/handlers/HandleBuilder.java
index 3795c3de..b5c6e793 100644
--- a/src/core/lombok/eclipse/handlers/HandleBuilder.java
+++ b/src/core/lombok/eclipse/handlers/HandleBuilder.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013-2015 The Project Lombok Authors.
+ * Copyright (C) 2013-2018 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
@@ -39,6 +39,7 @@ 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.ConditionalExpression;
import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
import org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall;
import org.eclipse.jdt.internal.compiler.ast.Expression;
@@ -92,6 +93,8 @@ 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 HandleConstructor handleConstructor = new HandleConstructor();
+
private static final char[] CLEAN_FIELD_NAME = "$lombokUnclean".toCharArray();
private static final char[] CLEAN_METHOD_NAME = "$lombokClean".toCharArray();
@@ -107,9 +110,12 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
TypeReference type;
char[] rawName;
char[] name;
+ char[] nameOfDefaultProvider;
+ char[] nameOfSetFlag;
SingularData singularData;
ObtainVia obtainVia;
EclipseNode obtainViaNode;
+ EclipseNode originalFieldNode;
List<EclipseNode> createdFields = new ArrayList<EclipseNode>();
}
@@ -132,6 +138,16 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
return true;
}
+ private static final char[] DEFAULT_PREFIX = {'$', 'd', 'e', 'f', 'a', 'u', 'l', 't', '$'};
+ private static final char[] SET_PREFIX = {'$', 's', 'e', 't'};
+
+ private static final char[] prefixWith(char[] prefix, char[] name) {
+ char[] out = new char[prefix.length + name.length];
+ System.arraycopy(prefix, 0, out, 0, prefix.length);
+ System.arraycopy(name, 0, out, prefix.length, name.length);
+ return out;
+ }
+
@Override public void handle(AnnotationValues<Builder> annotation, Annotation ast, EclipseNode annotationNode) {
long p = (long) ast.sourceStart << 32 | ast.sourceEnd;
@@ -146,9 +162,8 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
String builderClassName = builderInstance.builderClassName();
boolean inherit = builderInstance.inherit();
- boolean extendable = inherit || builderInstance.extendable(); // inherit implies extendable
- String superclassBuilderClassName = builderInstance.superclassBuilderClassName();
-
+ boolean extensible = inherit || builderInstance.extensible(); // inherit implies extendable
+
String toBuilderMethodName = "toBuilder";
boolean toBuilder = builderInstance.toBuilder();
List<char[]> typeArgsForToBuilder = null;
@@ -156,9 +171,6 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
if (builderMethodName == null) builderMethodName = "builder";
if (buildMethodName == null) builderMethodName = "build";
if (builderClassName == null) builderClassName = "";
- if (superclassBuilderClassName == null) {
- superclassBuilderClassName = "";
- }
if (!checkName("builderMethodName", builderMethodName, annotationNode)) return;
if (!checkName("buildMethodName", buildMethodName, annotationNode)) return;
@@ -179,43 +191,61 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
boolean addCleaning = false;
boolean isStatic = true;
+ TypeDeclaration td = null;
+
if (parent.get() instanceof TypeDeclaration) {
tdParent = parent;
- TypeDeclaration td = (TypeDeclaration) tdParent.get();
+ td = (TypeDeclaration) tdParent.get();
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)) {
+ boolean valuePresent = (hasAnnotation(lombok.Value.class, parent) || hasAnnotation("lombok.experimental.Value", parent));
+ for (EclipseNode fieldNode : HandleConstructor.findAllFields(tdParent, true)) {
FieldDeclaration fd = (FieldDeclaration) fieldNode.get();
- // final fields with an initializer cannot be written to, so they can't be 'builderized'. Unfortunately presence of @Value makes
- // 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;
+ EclipseNode isDefault = findAnnotation(Builder.Default.class, fieldNode);
+ boolean isFinal = ((fd.modifiers & ClassFileConstants.AccFinal) != 0) || (valuePresent && !hasAnnotation(NonFinal.class, fieldNode));
+
BuilderFieldData bfd = new BuilderFieldData();
bfd.fieldNode = fieldNode;
bfd.rawName = fieldNode.getName().toCharArray();
bfd.name = removePrefixFromField(fieldNode);
bfd.type = fd.type;
bfd.singularData = getSingularData(fieldNode, ast);
+ bfd.originalFieldNode = fieldNode;
+
+ if (bfd.singularData != null && isDefault != null) {
+ isDefault.addError("@Builder.Default and @Singular cannot be mixed.");
+ isDefault = null;
+ }
+
+ if (fd.initialization == null && isDefault != null) {
+ isDefault.addWarning("@Builder.Default requires an initializing expression (' = something;').");
+ isDefault = null;
+ }
+
+ if (fd.initialization != null && isDefault == null) {
+ if (isFinal) continue;
+ fieldNode.addWarning("@Builder will ignore the initializing expression entirely. If you want the initializing expression to serve as default, add @Builder.Default. If it is not supposed to be settable during building, make the field final.");
+ }
+
+ if (isDefault != null) {
+ bfd.nameOfDefaultProvider = prefixWith(DEFAULT_PREFIX, bfd.name);
+ bfd.nameOfSetFlag = prefixWith(bfd.name, SET_PREFIX);
+
+ MethodDeclaration md = generateDefaultProvider(bfd.nameOfDefaultProvider, td.typeParameters, fieldNode, ast);
+ if (md != null) injectMethod(tdParent, md);
+ }
addObtainVia(bfd, fieldNode);
builderFields.add(bfd);
allFields.add(fieldNode);
}
- if (builderClassName.isEmpty()) {
- builderClassName = new String(td.name) + "Builder";
- }
- if (superclassBuilderClassName.isEmpty() && td.superclass != null) {
- superclassBuilderClassName = new String(td.superclass.getLastToken()) + "Builder";
- }
+ if (builderClassName.isEmpty()) builderClassName = new String(td.name) + "Builder";
- if (extendable) {
+ if (extensible) {
boolean callBuilderBasedSuperConstructor = td.superclass != null;
- generateBuilderBasedConstructor(tdParent, builderFields, annotationNode,
- builderClassName, callBuilderBasedSuperConstructor);
+ generateBuilderBasedConstructor(tdParent, builderFields, annotationNode, builderClassName, callBuilderBasedSuperConstructor);
} else {
- new HandleConstructor().generateConstructor(tdParent, AccessLevel.PACKAGE, allFields, false, null, SkipIfConstructorExists.I_AM_BUILDER,
+ handleConstructor.generateConstructor(tdParent, AccessLevel.PACKAGE, allFields, false, null, SkipIfConstructorExists.I_AM_BUILDER,
Collections.<Annotation>emptyList(), annotationNode);
}
@@ -228,8 +258,8 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
annotationNode.addError("@Builder(inherit=true) is only supported for type builders.");
return;
}
- if (extendable) {
- annotationNode.addError("@Builder(extendable=true) is only supported for type builders.");
+ if (extensible) {
+ annotationNode.addError("@Builder(extensible=true) is only supported for type builders.");
return;
}
ConstructorDeclaration cd = (ConstructorDeclaration) parent.get();
@@ -239,7 +269,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
}
tdParent = parent.up();
- TypeDeclaration td = (TypeDeclaration) tdParent.get();
+ td = (TypeDeclaration) tdParent.get();
returnType = namePlusTypeParamsToTypeReference(td.name, td.typeParameters, p);
typeParams = td.typeParameters;
thrownExceptions = cd.thrownExceptions;
@@ -250,7 +280,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
annotationNode.addError("@Builder(inherit=true) is only supported for type builders.");
return;
}
- if (extendable) {
+ if (extensible) {
annotationNode.addError("@Builder(extendable=true) is only supported for type builders.");
return;
}
@@ -376,6 +406,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
bfd.name = arg.name;
bfd.type = arg.type;
bfd.singularData = getSingularData(param, ast);
+ bfd.originalFieldNode = param;
addObtainVia(bfd, param);
builderFields.add(bfd);
}
@@ -383,7 +414,20 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
EclipseNode builderType = findInnerClass(tdParent, builderClassName);
if (builderType == null) {
- builderType = makeBuilderClass(isStatic, tdParent, builderClassName, typeParams, ast, inherit ? superclassBuilderClassName : null);
+ String superclassBuilderClassName = null;
+ if (inherit) {
+ if (td.superclass == null) {
+ annotationNode.addError("@Builder(inherit = true) requires that your class has an 'extends' clause.");
+ return;
+ }
+
+ superclassBuilderClassName = builderInstance.superclassBuilderClassName();
+ if (superclassBuilderClassName == null || superclassBuilderClassName.isEmpty()) {
+ superclassBuilderClassName = new String(td.superclass.getLastToken()) + "Builder";
+ }
+ }
+
+ builderType = makeBuilderClass(isStatic, tdParent, builderClassName, typeParams, ast, superclassBuilderClassName);
} else {
TypeDeclaration builderTypeDeclaration = (TypeDeclaration) builderType.get();
if (isStatic && (builderTypeDeclaration.modifiers & ClassFileConstants.AccStatic) == 0) {
@@ -447,8 +491,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
}
if (methodExists(buildMethodName, builderType, -1) == MemberExistsResult.NOT_EXISTS) {
- boolean useBuilderBasedConstructor = parent.get() instanceof TypeDeclaration && extendable;
- MethodDeclaration md = generateBuildMethod(isStatic, buildMethodName, nameOfStaticBuilderMethod, returnType, builderFields, builderType, thrownExceptions, addCleaning, ast, useBuilderBasedConstructor);
+ MethodDeclaration md = generateBuildMethod(tdParent, isStatic, buildMethodName, nameOfStaticBuilderMethod, returnType, builderFields, builderType, thrownExceptions, addCleaning, ast, extensible);
if (md != null) injectMethod(builderType, md);
}
@@ -496,8 +539,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
int pS = source.sourceStart, pE = source.sourceEnd;
long p = (long) pS << 32 | pE;
- MethodDeclaration out = new MethodDeclaration(
- ((CompilationUnitDeclaration) type.top().get()).compilationResult);
+ MethodDeclaration out = new MethodDeclaration(((CompilationUnitDeclaration) type.top().get()).compilationResult);
out.selector = methodName.toCharArray();
out.modifiers = ClassFileConstants.AccPublic;
out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
@@ -556,23 +598,15 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
*/
private void generateBuilderBasedConstructor(EclipseNode typeNode, List<BuilderFieldData> builderFields, EclipseNode sourceNode,
String builderClassnameAsParameter, boolean callBuilderBasedSuperConstructor) {
-
- if (builderClassnameAsParameter == null || builderClassnameAsParameter.isEmpty()) {
- typeNode.addError("A builder-based constructor requires a non-empty 'builderClassnameAsParameter' value.");
- return;
- }
-
- AccessLevel level = AccessLevel.PROTECTED;
+
ASTNode source = sourceNode.get();
-
+
TypeDeclaration typeDeclaration = ((TypeDeclaration) typeNode.get());
long p = (long) source.sourceStart << 32 | source.sourceEnd;
boolean isEnum = (((TypeDeclaration) typeNode.get()).modifiers & ClassFileConstants.AccEnum) != 0;
- if (isEnum) {
- level = AccessLevel.PRIVATE;
- }
-
+ AccessLevel level = isEnum ? AccessLevel.PRIVATE : AccessLevel.PROTECTED;
+
ConstructorDeclaration constructor = new ConstructorDeclaration(((CompilationUnitDeclaration) typeNode.top().get()).compilationResult);
constructor.modifiers = toEclipseModifier(level);
@@ -601,7 +635,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
int s = (int) (p >> 32);
int e = (int) p;
thisX.receiver = new ThisReference(s, e);
-
+
Expression assignmentExpr;
if (fieldNode.singularData != null && fieldNode.singularData.getSingularizer() != null) {
fieldNode.singularData.getSingularizer().appendBuildCode(fieldNode.singularData, typeNode, statements, fieldNode.name, "b");
@@ -628,7 +662,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
constructor.arguments = new Argument[] {new Argument("b".toCharArray(), p, new SingleTypeReference(builderClassnameAsParameter.toCharArray(), p), Modifier.FINAL)};
constructor.traverse(new SetGeneratedByVisitor(source), typeDeclaration.scope);
-
+
injectMethod(typeNode, constructor);
}
@@ -660,7 +694,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
* that takes the builder instance as parameter (instead of a
* constructor with all relevant fields as parameters)
*/
- public MethodDeclaration generateBuildMethod(boolean isStatic, String name, char[] staticName, TypeReference returnType, List<BuilderFieldData> builderFields, EclipseNode type, TypeReference[] thrownExceptions, boolean addCleaning, ASTNode source, boolean useBuilderBasedConstructor) {
+ public MethodDeclaration generateBuildMethod(EclipseNode tdParent, boolean isStatic, String name, char[] staticName, TypeReference returnType, List<BuilderFieldData> builderFields, EclipseNode type, TypeReference[] thrownExceptions, boolean addCleaning, ASTNode source, boolean useBuilderBasedConstructor) {
MethodDeclaration out = new MethodDeclaration(((CompilationUnitDeclaration) type.top().get()).compilationResult);
out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
List<Statement> statements = new ArrayList<Statement>();
@@ -676,17 +710,31 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
invokeClean.selector = CLEAN_METHOD_NAME;
statements.add(new IfStatement(notClean, invokeClean, 0, 0));
}
-
+
for (BuilderFieldData bfd : builderFields) {
if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) {
bfd.singularData.getSingularizer().appendBuildCode(bfd.singularData, type, statements, bfd.name, "this");
}
}
-
+
for (BuilderFieldData bfd : builderFields) {
- args.add(new SingleNameReference(bfd.name, 0L));
+ if (bfd.nameOfSetFlag != null) {
+ MessageSend inv = new MessageSend();
+ inv.sourceStart = source.sourceStart;
+ inv.sourceEnd = source.sourceEnd;
+ inv.receiver = new SingleNameReference(((TypeDeclaration) tdParent.get()).name, 0L);
+ inv.selector = bfd.nameOfDefaultProvider;
+ inv.typeArguments = typeParameterNames(((TypeDeclaration) type.get()).typeParameters);
+
+ args.add(new ConditionalExpression(
+ new SingleNameReference(bfd.nameOfSetFlag, 0L),
+ new SingleNameReference(bfd.name, 0L),
+ inv));
+ } else {
+ args.add(new SingleNameReference(bfd.name, 0L));
+ }
}
-
+
if (addCleaning) {
FieldReference thisUnclean = new FieldReference(CLEAN_FIELD_NAME, 0);
thisUnclean.receiver = new ThisReference(0, 0);
@@ -718,14 +766,8 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
invoke.receiver = new SingleNameReference(type.up().getName().toCharArray(), 0);
else
invoke.receiver = new QualifiedThisReference(new SingleTypeReference(type.up().getName().toCharArray(), 0) , 0, 0);
- 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.typeArguments = typeParameterNames(((TypeDeclaration) type.get()).typeParameters);
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);
@@ -738,6 +780,33 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
return out;
}
+ private TypeReference[] typeParameterNames(TypeParameter[] typeParameters) {
+ if (typeParameters == null) return null;
+
+ TypeReference[] trs = new TypeReference[typeParameters.length];
+ for (int i = 0; i < trs.length; i++) {
+ trs[i] = new SingleTypeReference(typeParameters[i].name, 0);
+ }
+ return trs;
+ }
+
+ public MethodDeclaration generateDefaultProvider(char[] methodName, TypeParameter[] typeParameters, EclipseNode fieldNode, ASTNode source) {
+ int pS = source.sourceStart, pE = source.sourceEnd;
+
+ MethodDeclaration out = new MethodDeclaration(((CompilationUnitDeclaration) fieldNode.top().get()).compilationResult);
+ out.typeParameters = copyTypeParams(typeParameters, source);
+ out.selector = methodName;
+ out.modifiers = ClassFileConstants.AccPrivate | ClassFileConstants.AccStatic;
+ out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
+ FieldDeclaration fd = (FieldDeclaration) fieldNode.get();
+ out.returnType = copyType(fd.type, source);
+ out.statements = new Statement[] {new ReturnStatement(fd.initialization, pS, pE)};
+ fd.initialization = null;
+
+ out.traverse(new SetGeneratedByVisitor(source), ((TypeDeclaration) fieldNode.up().get()).scope);
+ return out;
+ }
+
public MethodDeclaration generateBuilderMethod(boolean isStatic, String builderMethodName, String builderClassName, EclipseNode type, TypeParameter[] typeParams, ASTNode source) {
int pS = source.sourceStart, pE = source.sourceEnd;
long p = (long) pS << 32 | pE;
@@ -763,25 +832,34 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
if (child.getKind() == Kind.FIELD) existing.add(child);
}
- top:
for (BuilderFieldData bfd : builderFields) {
if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) {
bfd.createdFields.addAll(bfd.singularData.getSingularizer().generateFields(bfd.singularData, builderType));
} else {
+ EclipseNode field = null, setFlag = null;
for (EclipseNode exists : existing) {
char[] n = ((FieldDeclaration) exists.get()).name;
- if (Arrays.equals(n, bfd.name)) {
- bfd.createdFields.add(exists);
- continue top;
- }
+ if (Arrays.equals(n, bfd.name)) field = exists;
+ if (bfd.nameOfSetFlag != null && Arrays.equals(n, bfd.nameOfSetFlag)) setFlag = exists;
}
- 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);
- fd.traverse(new SetGeneratedByVisitor(source), (MethodScope) null);
- bfd.createdFields.add(injectFieldAndMarkGenerated(builderType, fd));
+ if (field == null) {
+ 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);
+ fd.traverse(new SetGeneratedByVisitor(source), (MethodScope) null);
+ field = injectFieldAndMarkGenerated(builderType, fd);
+ }
+ if (setFlag == null && bfd.nameOfSetFlag != null) {
+ FieldDeclaration fd = new FieldDeclaration(bfd.nameOfSetFlag, 0, 0);
+ fd.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG;
+ fd.modifiers = ClassFileConstants.AccPrivate;
+ fd.type = TypeReference.baseTypeReference(TypeIds.T_boolean, 0);
+ fd.traverse(new SetGeneratedByVisitor(source), (MethodScope) null);
+ injectFieldAndMarkGenerated(builderType, fd);
+ }
+ bfd.createdFields.add(field);
}
}
}
@@ -789,14 +867,15 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
private static final AbstractMethodDeclaration[] EMPTY = {};
public void makeSetterMethodsForBuilder(EclipseNode builderType, BuilderFieldData bfd, EclipseNode sourceNode, boolean fluent, boolean chain) {
+ boolean deprecate = isFieldDeprecated(bfd.originalFieldNode);
if (bfd.singularData == null || bfd.singularData.getSingularizer() == null) {
- makeSimpleSetterMethodForBuilder(builderType, bfd.createdFields.get(0), sourceNode, fluent, chain);
+ makeSimpleSetterMethodForBuilder(builderType, deprecate, bfd.createdFields.get(0), bfd.nameOfSetFlag, sourceNode, fluent, chain);
} else {
- bfd.singularData.getSingularizer().generateMethods(bfd.singularData, builderType, fluent, chain);
+ bfd.singularData.getSingularizer().generateMethods(bfd.singularData, deprecate, builderType, fluent, chain);
}
}
- private void makeSimpleSetterMethodForBuilder(EclipseNode builderType, EclipseNode fieldNode, EclipseNode sourceNode, boolean fluent, boolean chain) {
+ private void makeSimpleSetterMethodForBuilder(EclipseNode builderType, boolean deprecate, EclipseNode fieldNode, char[] nameOfSetFlag, EclipseNode sourceNode, boolean fluent, boolean chain) {
TypeDeclaration td = (TypeDeclaration) builderType.get();
AbstractMethodDeclaration[] existing = td.methods;
if (existing == null) existing = EMPTY;
@@ -812,7 +891,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
String setterName = fluent ? fieldNode.getName() : HandlerUtil.buildAccessorName("set", fieldNode.getName());
- MethodDeclaration setter = HandleSetter.createSetter(td, fieldNode, setterName, chain, ClassFileConstants.AccPublic,
+ MethodDeclaration setter = HandleSetter.createSetter(td, deprecate, fieldNode, setterName, nameOfSetFlag, chain, ClassFileConstants.AccPublic,
sourceNode, Collections.<Annotation>emptyList(), Collections.<Annotation>emptyList());
injectMethod(builderType, setter);
}
@@ -835,9 +914,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
if (isStatic) builder.modifiers |= ClassFileConstants.AccStatic;
builder.typeParameters = copyTypeParams(typeParams, source);
builder.name = builderClassName.toCharArray();
- if (parentBuilderClassName != null) {
- builder.superclass = new SingleTypeReference(parentBuilderClassName.toCharArray(), 0);
- }
+ if (parentBuilderClassName != null) builder.superclass = new SingleTypeReference(parentBuilderClassName.toCharArray(), 0);
builder.traverse(new SetGeneratedByVisitor(source), (ClassScope) null);
return injectType(tdParent, builder);
}
diff --git a/src/core/lombok/eclipse/handlers/HandleBuilderDefault.java b/src/core/lombok/eclipse/handlers/HandleBuilderDefault.java
new file mode 100644
index 00000000..be2b986d
--- /dev/null
+++ b/src/core/lombok/eclipse/handlers/HandleBuilderDefault.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2017-2018 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;
+
+import static lombok.eclipse.handlers.EclipseHandlerUtil.*;
+import org.eclipse.jdt.internal.compiler.ast.Annotation;
+import org.mangosdk.spi.ProviderFor;
+
+import lombok.Builder;
+import lombok.core.AST.Kind;
+import lombok.core.AnnotationValues;
+import lombok.core.HandlerPriority;
+import lombok.eclipse.EclipseAnnotationHandler;
+import lombok.eclipse.EclipseNode;
+
+@ProviderFor(EclipseAnnotationHandler.class)
+@HandlerPriority(-1025) //HandleBuilder's level, minus one.
+public class HandleBuilderDefault extends EclipseAnnotationHandler<Builder.Default> {
+ @Override public void handle(AnnotationValues<Builder.Default> annotation, Annotation ast, EclipseNode annotationNode) {
+ EclipseNode annotatedField = annotationNode.up();
+ if (annotatedField.getKind() != Kind.FIELD) return;
+ EclipseNode classWithAnnotatedField = annotatedField.up();
+ if (!hasAnnotation(Builder.class, classWithAnnotatedField) && !hasAnnotation("lombok.experimental.Builder", classWithAnnotatedField)) {
+ annotationNode.addWarning("@Builder.Default requires @Builder on the class for it to mean anything.");
+ }
+ }
+}
diff --git a/src/core/lombok/eclipse/handlers/HandleConstructor.java b/src/core/lombok/eclipse/handlers/HandleConstructor.java
index b504495d..a2940b88 100644
--- a/src/core/lombok/eclipse/handlers/HandleConstructor.java
+++ b/src/core/lombok/eclipse/handlers/HandleConstructor.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2015 The Project Lombok Authors.
+ * Copyright (C) 2010-2017 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
@@ -80,6 +80,8 @@ import org.mangosdk.spi.ProviderFor;
public class HandleConstructor {
@ProviderFor(EclipseAnnotationHandler.class)
public static class HandleNoArgsConstructor extends EclipseAnnotationHandler<NoArgsConstructor> {
+ private HandleConstructor handleConstructor = new HandleConstructor();
+
@Override public void handle(AnnotationValues<NoArgsConstructor> annotation, Annotation ast, EclipseNode annotationNode) {
handleFlagUsage(annotationNode, ConfigurationKeys.NO_ARGS_CONSTRUCTOR_FLAG_USAGE, "@NoArgsConstructor", ConfigurationKeys.ANY_CONSTRUCTOR_FLAG_USAGE, "any @xArgsConstructor");
@@ -95,12 +97,14 @@ public class HandleConstructor {
List<EclipseNode> fields = force ? findFinalFields(typeNode) : Collections.<EclipseNode>emptyList();
List<Annotation> onConstructor = unboxAndRemoveAnnotationParameter(ast, "onConstructor", "@NoArgsConstructor(onConstructor", annotationNode);
- new HandleConstructor().generateConstructor(typeNode, level, fields, force, staticName, SkipIfConstructorExists.NO, onConstructor, annotationNode);
+ handleConstructor.generateConstructor(typeNode, level, fields, force, staticName, SkipIfConstructorExists.NO, onConstructor, annotationNode);
}
}
@ProviderFor(EclipseAnnotationHandler.class)
public static class HandleRequiredArgsConstructor extends EclipseAnnotationHandler<RequiredArgsConstructor> {
+ private HandleConstructor handleConstructor = new HandleConstructor();
+
@Override public void handle(AnnotationValues<RequiredArgsConstructor> annotation, Annotation ast, EclipseNode annotationNode) {
handleFlagUsage(annotationNode, ConfigurationKeys.REQUIRED_ARGS_CONSTRUCTOR_FLAG_USAGE, "@RequiredArgsConstructor", ConfigurationKeys.ANY_CONSTRUCTOR_FLAG_USAGE, "any @xArgsConstructor");
@@ -116,7 +120,7 @@ public class HandleConstructor {
List<Annotation> onConstructor = unboxAndRemoveAnnotationParameter(ast, "onConstructor", "@RequiredArgsConstructor(onConstructor", annotationNode);
- new HandleConstructor().generateConstructor(
+ handleConstructor.generateConstructor(
typeNode, level, findRequiredFields(typeNode), false, staticName, SkipIfConstructorExists.NO,
onConstructor, annotationNode);
}
@@ -144,14 +148,17 @@ public class HandleConstructor {
}
static List<EclipseNode> findAllFields(EclipseNode typeNode) {
+ return findAllFields(typeNode, false);
+ }
+
+ static List<EclipseNode> findAllFields(EclipseNode typeNode, boolean evenFinalInitialized) {
List<EclipseNode> fields = new ArrayList<EclipseNode>();
for (EclipseNode child : typeNode.down()) {
if (child.getKind() != Kind.FIELD) continue;
FieldDeclaration fieldDecl = (FieldDeclaration) child.get();
if (!filterField(fieldDecl)) continue;
- // Skip initialized final fields.
- if (((fieldDecl.modifiers & ClassFileConstants.AccFinal) != 0) && fieldDecl.initialization != null) continue;
+ if (!evenFinalInitialized && ((fieldDecl.modifiers & ClassFileConstants.AccFinal) != 0) && fieldDecl.initialization != null) continue;
fields.add(child);
}
@@ -160,6 +167,8 @@ public class HandleConstructor {
@ProviderFor(EclipseAnnotationHandler.class)
public static class HandleAllArgsConstructor extends EclipseAnnotationHandler<AllArgsConstructor> {
+ private HandleConstructor handleConstructor = new HandleConstructor();
+
@Override public void handle(AnnotationValues<AllArgsConstructor> annotation, Annotation ast, EclipseNode annotationNode) {
handleFlagUsage(annotationNode, ConfigurationKeys.ALL_ARGS_CONSTRUCTOR_FLAG_USAGE, "@AllArgsConstructor", ConfigurationKeys.ANY_CONSTRUCTOR_FLAG_USAGE, "any @xArgsConstructor");
@@ -175,7 +184,7 @@ public class HandleConstructor {
List<Annotation> onConstructor = unboxAndRemoveAnnotationParameter(ast, "onConstructor", "@AllArgsConstructor(onConstructor", annotationNode);
- new HandleConstructor().generateConstructor(
+ handleConstructor.generateConstructor(
typeNode, level, findAllFields(typeNode), false, staticName, SkipIfConstructorExists.NO,
onConstructor, annotationNode);
}
@@ -290,7 +299,7 @@ public class HandleConstructor {
return new Annotation[] { ann };
}
- public static ConstructorDeclaration createConstructor(
+ @SuppressWarnings("deprecation") public static ConstructorDeclaration createConstructor(
AccessLevel level, EclipseNode type, Collection<EclipseNode> fields, boolean allToDefault,
EclipseNode sourceNode, List<Annotation> onConstructor) {
@@ -302,11 +311,13 @@ public class HandleConstructor {
if (isEnum) level = AccessLevel.PRIVATE;
- boolean suppressConstructorProperties;
+ boolean addConstructorProperties;
if (fields.isEmpty()) {
- suppressConstructorProperties = false;
+ addConstructorProperties = false;
} else {
- suppressConstructorProperties = Boolean.TRUE.equals(type.getAst().readConfiguration(ConfigurationKeys.ANY_CONSTRUCTOR_SUPPRESS_CONSTRUCTOR_PROPERTIES));
+ Boolean v = type.getAst().readConfiguration(ConfigurationKeys.ANY_CONSTRUCTOR_ADD_CONSTRUCTOR_PROPERTIES);
+ addConstructorProperties = v != null ? v.booleanValue() :
+ Boolean.FALSE.equals(type.getAst().readConfiguration(ConfigurationKeys.ANY_CONSTRUCTOR_SUPPRESS_CONSTRUCTOR_PROPERTIES));
}
ConstructorDeclaration constructor = new ConstructorDeclaration(((CompilationUnitDeclaration) type.top().get()).compilationResult);
@@ -347,7 +358,7 @@ public class HandleConstructor {
Annotation[] nonNulls = findAnnotations(field, NON_NULL_PATTERN);
Annotation[] nullables = findAnnotations(field, NULLABLE_PATTERN);
if (nonNulls.length != 0) {
- Statement nullCheck = generateNullCheck(field, sourceNode);
+ Statement nullCheck = generateNullCheck(parameter, sourceNode);
if (nullCheck != null) nullChecks.add(nullCheck);
}
parameter.annotations = copyAnnotations(source, nonNulls, nullables);
@@ -361,7 +372,7 @@ public class HandleConstructor {
/* Generate annotations that must be put on the generated method, and attach them. */ {
Annotation[] constructorProperties = null;
- if (!allToDefault && !suppressConstructorProperties && level != AccessLevel.PRIVATE && level != AccessLevel.PACKAGE && !isLocalType(type)) {
+ if (!allToDefault && addConstructorProperties && !isLocalType(type)) {
constructorProperties = createConstructorProperties(source, fields);
}
diff --git a/src/core/lombok/eclipse/handlers/HandleData.java b/src/core/lombok/eclipse/handlers/HandleData.java
index 0ff65a47..025ceefd 100644
--- a/src/core/lombok/eclipse/handlers/HandleData.java
+++ b/src/core/lombok/eclipse/handlers/HandleData.java
@@ -43,6 +43,12 @@ import org.mangosdk.spi.ProviderFor;
*/
@ProviderFor(EclipseAnnotationHandler.class)
public class HandleData extends EclipseAnnotationHandler<Data> {
+ private HandleGetter handleGetter = new HandleGetter();
+ private HandleSetter handleSetter = new HandleSetter();
+ private HandleEqualsAndHashCode handleEqualsAndHashCode = new HandleEqualsAndHashCode();
+ private HandleToString handleToString = new HandleToString();
+ private HandleConstructor handleConstructor = new HandleConstructor();
+
@Override public void handle(AnnotationValues<Data> annotation, Annotation ast, EclipseNode annotationNode) {
handleFlagUsage(annotationNode, ConfigurationKeys.DATA_FLAG_USAGE, "@Data");
@@ -66,11 +72,11 @@ public class HandleData extends EclipseAnnotationHandler<Data> {
//for whatever reason, though you can find callers of that one by focusing on the class name itself
//and hitting 'find callers'.
- new HandleGetter().generateGetterForType(typeNode, annotationNode, AccessLevel.PUBLIC, true);
- new HandleSetter().generateSetterForType(typeNode, annotationNode, AccessLevel.PUBLIC, true);
- new HandleEqualsAndHashCode().generateEqualsAndHashCodeForType(typeNode, annotationNode);
- new HandleToString().generateToStringForType(typeNode, annotationNode);
- new HandleConstructor().generateRequiredArgsConstructor(
+ handleGetter.generateGetterForType(typeNode, annotationNode, AccessLevel.PUBLIC, true);
+ handleSetter.generateSetterForType(typeNode, annotationNode, AccessLevel.PUBLIC, true);
+ handleEqualsAndHashCode.generateEqualsAndHashCodeForType(typeNode, annotationNode);
+ handleToString.generateToStringForType(typeNode, annotationNode);
+ handleConstructor.generateRequiredArgsConstructor(
typeNode, AccessLevel.PUBLIC, ann.staticConstructor(), SkipIfConstructorExists.YES,
Collections.<Annotation>emptyList(), annotationNode);
}
diff --git a/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java b/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java
index ceef3d3c..75339f7c 100644
--- a/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java
+++ b/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java
@@ -118,7 +118,10 @@ public class HandleEqualsAndHashCode extends EclipseAnnotationHandler<EqualsAndH
return;
}
- generateMethods(typeNode, errorNode, null, null, null, false, FieldAccess.GETTER, new ArrayList<Annotation>());
+ Boolean doNotUseGettersConfiguration = typeNode.getAst().readConfiguration(ConfigurationKeys.EQUALS_AND_HASH_CODE_DO_NOT_USE_GETTERS);
+ FieldAccess access = doNotUseGettersConfiguration == null || !doNotUseGettersConfiguration ? FieldAccess.GETTER : FieldAccess.PREFER_FIELD;
+
+ generateMethods(typeNode, errorNode, null, null, null, false, access, new ArrayList<Annotation>());
}
@Override public void handle(AnnotationValues<EqualsAndHashCode> annotation, Annotation ast, EclipseNode annotationNode) {
@@ -296,7 +299,7 @@ public class HandleEqualsAndHashCode extends EclipseAnnotationHandler<EqualsAndH
/* final int PRIME = X; */ {
/* Without fields, PRIME isn't used, and that would trigger a 'local variable not used' warning. */
- if (!isEmpty || callSuper) {
+ if (!isEmpty) {
LocalDeclaration primeDecl = new LocalDeclaration(PRIME, pS, pE);
setGeneratedBy(primeDecl, source);
primeDecl.modifiers |= Modifier.FINAL;
@@ -308,26 +311,30 @@ public class HandleEqualsAndHashCode extends EclipseAnnotationHandler<EqualsAndH
}
}
- /* int result = 1; */ {
- LocalDeclaration resultDecl = new LocalDeclaration(RESULT, pS, pE);
+ /*int result = ... */{
+ LocalDeclaration resultDecl = new LocalDeclaration(RESULT, pS, pE);
setGeneratedBy(resultDecl, source);
- resultDecl.initialization = makeIntLiteral("1".toCharArray(), source);
+ final Expression init;
+ if (callSuper) {
+ /* ... super.hashCode(); */
+ MessageSend callToSuper = new MessageSend();
+ setGeneratedBy(callToSuper, source);
+ callToSuper.sourceStart = pS; callToSuper.sourceEnd = pE;
+ callToSuper.receiver = new SuperReference(pS, pE);
+ setGeneratedBy(callToSuper.receiver, source);
+ callToSuper.selector = "hashCode".toCharArray();
+ init = callToSuper;
+ } else {
+ /* ... 1; */
+ init = makeIntLiteral("1".toCharArray(), source);
+ }
+ resultDecl.initialization = init;
resultDecl.type = TypeReference.baseTypeReference(TypeIds.T_int, 0);
resultDecl.type.sourceStart = pS; resultDecl.type.sourceEnd = pE;
setGeneratedBy(resultDecl.type, source);
statements.add(resultDecl);
}
- if (callSuper) {
- MessageSend callToSuper = new MessageSend();
- setGeneratedBy(callToSuper, source);
- callToSuper.sourceStart = pS; callToSuper.sourceEnd = pE;
- callToSuper.receiver = new SuperReference(pS, pE);
- setGeneratedBy(callToSuper.receiver, source);
- callToSuper.selector = "hashCode".toCharArray();
- statements.add(createResultCalculation(source, callToSuper));
- }
-
for (EclipseNode field : fields) {
TypeReference fType = getFieldType(field, fieldAccess);
char[] dollarFieldName = ("$" + field.getName()).toCharArray();
@@ -468,47 +475,62 @@ public class HandleEqualsAndHashCode extends EclipseAnnotationHandler<EqualsAndH
public TypeReference createTypeReference(EclipseNode type, long p, ASTNode source, boolean addWildcards) {
int pS = source.sourceStart; int pE = source.sourceEnd;
List<String> list = new ArrayList<String>();
+ List<Integer> genericsCount = addWildcards ? new ArrayList<Integer>() : null;
+
list.add(type.getName());
+ if (addWildcards) genericsCount.add(arraySizeOf(((TypeDeclaration) type.get()).typeParameters));
+ boolean staticContext = (((TypeDeclaration) type.get()).modifiers & Modifier.STATIC) != 0;
EclipseNode tNode = type.up();
+
while (tNode != null && tNode.getKind() == Kind.TYPE) {
list.add(tNode.getName());
+ if (addWildcards) genericsCount.add(staticContext ? 0 : arraySizeOf(((TypeDeclaration) tNode.get()).typeParameters));
+ if (!staticContext) staticContext = (((TypeDeclaration) tNode.get()).modifiers & Modifier.STATIC) != 0;
tNode = tNode.up();
}
Collections.reverse(list);
-
- TypeDeclaration typeDecl = (TypeDeclaration) type.get();
- int typeParamCount = typeDecl.typeParameters == null ? 0 : typeDecl.typeParameters.length;
- if (typeParamCount == 0) addWildcards = false;
- TypeReference[] typeArgs = null;
- if (addWildcards) {
- typeArgs = new TypeReference[typeParamCount];
- for (int i = 0; i < typeParamCount; i++) {
- typeArgs[i] = new Wildcard(Wildcard.UNBOUND);
- typeArgs[i].sourceStart = pS; typeArgs[i].sourceEnd = pE;
- setGeneratedBy(typeArgs[i], source);
- }
- }
+ if (addWildcards) Collections.reverse(genericsCount);
if (list.size() == 1) {
- if (addWildcards) {
- return new ParameterizedSingleTypeReference(list.get(0).toCharArray(), typeArgs, 0, p);
- } else {
+ if (!addWildcards || genericsCount.get(0) == 0) {
return new SingleTypeReference(list.get(0).toCharArray(), p);
+ } else {
+ return new ParameterizedSingleTypeReference(list.get(0).toCharArray(), wildcardify(pS, pE, source, genericsCount.get(0)), 0, p);
}
}
+
+ if (addWildcards) {
+ addWildcards = false;
+ for (int i : genericsCount) if (i > 0) addWildcards = true;
+ }
+
long[] ps = new long[list.size()];
char[][] tokens = new char[list.size()][];
for (int i = 0; i < list.size(); i++) {
ps[i] = p;
tokens[i] = list.get(i).toCharArray();
}
- if (addWildcards) {
- TypeReference[][] typeArgs2 = new TypeReference[tokens.length][];
- typeArgs2[typeArgs2.length - 1] = typeArgs;
- return new ParameterizedQualifiedTypeReference(tokens, typeArgs2, 0, ps);
- } else {
- return new QualifiedTypeReference(tokens, ps);
+
+ if (!addWildcards) return new QualifiedTypeReference(tokens, ps);
+ TypeReference[][] typeArgs2 = new TypeReference[tokens.length][];
+ for (int i = 0; i < tokens.length; i++) typeArgs2[i] = wildcardify(pS, pE, source, genericsCount.get(i));
+ return new ParameterizedQualifiedTypeReference(tokens, typeArgs2, 0, ps);
+ }
+
+ private TypeReference[] wildcardify(int pS, int pE, ASTNode source, int count) {
+ if (count == 0) return null;
+ TypeReference[] typeArgs = new TypeReference[count];
+ for (int i = 0; i < count; i++) {
+ typeArgs[i] = new Wildcard(Wildcard.UNBOUND);
+ typeArgs[i].sourceStart = pS; typeArgs[i].sourceEnd = pE;
+ setGeneratedBy(typeArgs[i], source);
}
+
+ return typeArgs;
+ }
+
+ private int arraySizeOf(Object[] arr) {
+ return arr == null ? 0 : arr.length;
}
public MethodDeclaration createEquals(EclipseNode type, Collection<EclipseNode> fields, boolean callSuper, ASTNode source, FieldAccess fieldAccess, boolean needsCanEqual, List<Annotation> onParam) {
@@ -676,7 +698,7 @@ public class HandleEqualsAndHashCode extends EclipseAnnotationHandler<EqualsAndH
} else /* objects */ {
/* final java.lang.Object this$fieldName = this.fieldName; */
/* final java.lang.Object other$fieldName = other.fieldName; */
- /* if (this$fieldName == null ? other$fieldName != null : !this$fieldName.equals(other$fieldName)) return false;; */
+ /* if (this$fieldName == null ? other$fieldName != null : !this$fieldName.equals(other$fieldName)) return false; */
char[] thisDollarFieldName = ("this$" + field.getName()).toCharArray();
char[] otherDollarFieldName = ("other$" + field.getName()).toCharArray();
diff --git a/src/core/lombok/eclipse/handlers/HandleGetter.java b/src/core/lombok/eclipse/handlers/HandleGetter.java
index c11303f3..f417aca5 100644
--- a/src/core/lombok/eclipse/handlers/HandleGetter.java
+++ b/src/core/lombok/eclipse/handlers/HandleGetter.java
@@ -105,7 +105,7 @@ public class HandleGetter extends EclipseAnnotationHandler<Getter> {
return true;
}
- public boolean fieldQualifiesForGetterGeneration(EclipseNode field) {
+ public static boolean fieldQualifiesForGetterGeneration(EclipseNode field) {
if (field.getKind() != Kind.FIELD) return false;
FieldDeclaration fieldDecl = (FieldDeclaration) field.get();
return filterField(fieldDecl);
diff --git a/src/core/lombok/eclipse/handlers/HandleSetter.java b/src/core/lombok/eclipse/handlers/HandleSetter.java
index 7e7ea121..6a9a5123 100644
--- a/src/core/lombok/eclipse/handlers/HandleSetter.java
+++ b/src/core/lombok/eclipse/handlers/HandleSetter.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2014 The Project Lombok Authors.
+ * Copyright (C) 2009-2017 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
@@ -52,6 +52,7 @@ 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.TrueLiteral;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
@@ -192,11 +193,11 @@ public class HandleSetter extends EclipseAnnotationHandler<Setter> {
}
}
- MethodDeclaration method = createSetter((TypeDeclaration) fieldNode.up().get(), fieldNode, setterName, shouldReturnThis, modifier, sourceNode, onMethod, onParam);
+ MethodDeclaration method = createSetter((TypeDeclaration) fieldNode.up().get(), false, fieldNode, setterName, null, shouldReturnThis, modifier, sourceNode, onMethod, onParam);
injectMethod(fieldNode.up(), method);
}
- static MethodDeclaration createSetter(TypeDeclaration parent, EclipseNode fieldNode, String name, boolean shouldReturnThis, int modifier, EclipseNode sourceNode, List<Annotation> onMethod, List<Annotation> onParam) {
+ static MethodDeclaration createSetter(TypeDeclaration parent, boolean deprecate, EclipseNode fieldNode, String name, char[] booleanFieldToSet, boolean shouldReturnThis, int modifier, EclipseNode sourceNode, List<Annotation> onMethod, List<Annotation> onParam) {
FieldDeclaration field = (FieldDeclaration) fieldNode.get();
ASTNode source = sourceNode.get();
int pS = source.sourceStart, pE = source.sourceEnd;
@@ -213,7 +214,7 @@ public class HandleSetter extends EclipseAnnotationHandler<Setter> {
shouldReturnThis = false;
}
Annotation[] deprecated = null;
- if (isFieldDeprecated(fieldNode)) {
+ if (isFieldDeprecated(fieldNode) || deprecate) {
deprecated = new Annotation[] { generateDeprecatedAnnotation(source) };
}
method.annotations = copyAnnotations(source, onMethod.toArray(new Annotation[0]), deprecated);
@@ -243,6 +244,10 @@ public class HandleSetter extends EclipseAnnotationHandler<Setter> {
statements.add(assignment);
}
+ if (booleanFieldToSet != null) {
+ statements.add(new Assignment(new SingleNameReference(booleanFieldToSet, p), new TrueLiteral(pS, pE), pE));
+ }
+
if (shouldReturnThis) {
ThisReference thisRef = new ThisReference(pS, pE);
ReturnStatement returnThis = new ReturnStatement(thisRef, pS, pE);
diff --git a/src/core/lombok/eclipse/handlers/HandleToString.java b/src/core/lombok/eclipse/handlers/HandleToString.java
index a4ed254a..d8f4c569 100644
--- a/src/core/lombok/eclipse/handlers/HandleToString.java
+++ b/src/core/lombok/eclipse/handlers/HandleToString.java
@@ -94,7 +94,11 @@ public class HandleToString extends EclipseAnnotationHandler<ToString> {
Boolean configuration = typeNode.getAst().readConfiguration(ConfigurationKeys.TO_STRING_INCLUDE_FIELD_NAMES);
includeFieldNames = configuration != null ? configuration : ((Boolean)ToString.class.getMethod("includeFieldNames").getDefaultValue()).booleanValue();
} catch (Exception ignore) {}
- generateToString(typeNode, errorNode, null, null, includeFieldNames, null, false, FieldAccess.GETTER);
+
+ Boolean doNotUseGettersConfiguration = typeNode.getAst().readConfiguration(ConfigurationKeys.TO_STRING_DO_NOT_USE_GETTERS);
+ FieldAccess access = doNotUseGettersConfiguration == null || !doNotUseGettersConfiguration ? FieldAccess.GETTER : FieldAccess.PREFER_FIELD;
+
+ generateToString(typeNode, errorNode, null, null, includeFieldNames, null, false, access);
}
public void handle(AnnotationValues<ToString> annotation, Annotation ast, EclipseNode annotationNode) {
diff --git a/src/core/lombok/eclipse/handlers/HandleVal.java b/src/core/lombok/eclipse/handlers/HandleVal.java
index d8901067..3742ac00 100644
--- a/src/core/lombok/eclipse/handlers/HandleVal.java
+++ b/src/core/lombok/eclipse/handlers/HandleVal.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2016 The Project Lombok Authors.
+ * Copyright (C) 2010-2018 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
@@ -25,13 +25,14 @@ import static lombok.core.handlers.HandlerUtil.handleFlagUsage;
import static lombok.eclipse.handlers.EclipseHandlerUtil.typeMatches;
import lombok.ConfigurationKeys;
import lombok.val;
+import lombok.var;
import lombok.core.HandlerPriority;
import lombok.eclipse.DeferUntilPostDiet;
import lombok.eclipse.EclipseASTAdapter;
import lombok.eclipse.EclipseASTVisitor;
import lombok.eclipse.EclipseNode;
-import lombok.experimental.var;
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.ast.ArrayInitializer;
import org.eclipse.jdt.internal.compiler.ast.ForStatement;
import org.eclipse.jdt.internal.compiler.ast.ForeachStatement;
@@ -74,11 +75,18 @@ public class HandleVal extends EclipseASTAdapter {
return;
}
- if (isVal && localNode.directUp().get() instanceof ForStatement) {
+ ASTNode parentRaw = localNode.directUp().get();
+
+ if (isVal && parentRaw instanceof ForStatement) {
localNode.addError("'val' is not allowed in old-style for loops");
return;
}
+ if (parentRaw instanceof ForStatement && ((ForStatement) parentRaw).initializations != null && ((ForStatement) parentRaw).initializations.length > 1) {
+ localNode.addError("'var' is not allowed in old-style for loops if there is more than 1 initializer");
+ return;
+ }
+
if (local.initialization != null && local.initialization.getClass().getName().equals("org.eclipse.jdt.internal.compiler.ast.LambdaExpression")) {
localNode.addError("'" + annotation + "' is not allowed with lambda expressions.");
return;
diff --git a/src/core/lombok/eclipse/handlers/HandleValue.java b/src/core/lombok/eclipse/handlers/HandleValue.java
index 79c11771..a61ca6c3 100644
--- a/src/core/lombok/eclipse/handlers/HandleValue.java
+++ b/src/core/lombok/eclipse/handlers/HandleValue.java
@@ -47,6 +47,12 @@ import org.mangosdk.spi.ProviderFor;
@ProviderFor(EclipseAnnotationHandler.class)
@HandlerPriority(-512) //-2^9; to ensure @EqualsAndHashCode and such pick up on this handler making the class final and messing with the fields' access levels, run earlier.
public class HandleValue extends EclipseAnnotationHandler<Value> {
+ private HandleFieldDefaults handleFieldDefaults = new HandleFieldDefaults();
+ private HandleGetter handleGetter = new HandleGetter();
+ private HandleEqualsAndHashCode handleEqualsAndHashCode = new HandleEqualsAndHashCode();
+ private HandleToString handleToString = new HandleToString();
+ private HandleConstructor handleConstructor = new HandleConstructor();
+
public void handle(AnnotationValues<Value> annotation, Annotation ast, EclipseNode annotationNode) {
handleFlagUsage(annotationNode, ConfigurationKeys.VALUE_FLAG_USAGE, "@Value");
@@ -72,7 +78,7 @@ public class HandleValue extends EclipseAnnotationHandler<Value> {
}
}
- new HandleFieldDefaults().generateFieldDefaultsForType(typeNode, annotationNode, AccessLevel.PRIVATE, true, true);
+ handleFieldDefaults.generateFieldDefaultsForType(typeNode, annotationNode, AccessLevel.PRIVATE, true, true);
//Careful: Generate the public static constructor (if there is one) LAST, so that any attempt to
//'find callers' on the annotation node will find callers of the constructor, which is by far the
@@ -80,10 +86,10 @@ public class HandleValue extends EclipseAnnotationHandler<Value> {
//for whatever reason, though you can find callers of that one by focusing on the class name itself
//and hitting 'find callers'.
- new HandleGetter().generateGetterForType(typeNode, annotationNode, AccessLevel.PUBLIC, true);
- new HandleEqualsAndHashCode().generateEqualsAndHashCodeForType(typeNode, annotationNode);
- new HandleToString().generateToStringForType(typeNode, annotationNode);
- new HandleConstructor().generateAllArgsConstructor(typeNode, AccessLevel.PUBLIC, ann.staticConstructor(), SkipIfConstructorExists.YES,
+ handleGetter.generateGetterForType(typeNode, annotationNode, AccessLevel.PUBLIC, true);
+ handleEqualsAndHashCode.generateEqualsAndHashCodeForType(typeNode, annotationNode);
+ handleToString.generateToStringForType(typeNode, annotationNode);
+ handleConstructor.generateAllArgsConstructor(typeNode, AccessLevel.PUBLIC, ann.staticConstructor(), SkipIfConstructorExists.YES,
Collections.<Annotation>emptyList(), annotationNode);
}
}
diff --git a/src/core/lombok/eclipse/handlers/SetGeneratedByVisitor.java b/src/core/lombok/eclipse/handlers/SetGeneratedByVisitor.java
index b42761f4..89964914 100644
--- a/src/core/lombok/eclipse/handlers/SetGeneratedByVisitor.java
+++ b/src/core/lombok/eclipse/handlers/SetGeneratedByVisitor.java
@@ -369,11 +369,6 @@ public final class SetGeneratedByVisitor extends ASTVisitor {
return super.visit(node, scope);
}
- @Override public boolean visit(ArrayInitializer node, ClassScope scope) {
- fixPositions(setGeneratedBy(node, source));
- return super.visit(node, scope);
- }
-
@Override public boolean visit(ArrayQualifiedTypeReference node, BlockScope scope) {
fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java
index d9f4cb73..eb2c9b35 100644
--- a/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java
+++ b/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015 The Project Lombok Authors.
+ * Copyright (C) 2015-2017 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
@@ -35,6 +35,7 @@ import lombok.eclipse.EclipseNode;
import lombok.eclipse.handlers.EclipseSingularsRecipes.EclipseSingularizer;
import lombok.eclipse.handlers.EclipseSingularsRecipes.SingularData;
+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;
@@ -96,21 +97,21 @@ abstract class EclipseGuavaSingularizer extends EclipseSingularizer {
return Collections.singletonList(injectFieldAndMarkGenerated(builderType, buildField));
}
- @Override public void generateMethods(SingularData data, EclipseNode builderType, boolean fluent, boolean chain) {
+ @Override public void generateMethods(SingularData data, boolean deprecate, 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);
+ generateSingularMethod(deprecate, 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);
+ generatePluralMethod(deprecate, 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;
- generateClearMethod(returnType, returnStatement, data, builderType);
+ generateClearMethod(deprecate, returnType, returnStatement, data, builderType);
}
- void generateClearMethod(TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType) {
+ void generateClearMethod(boolean deprecate, TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType) {
MethodDeclaration md = new MethodDeclaration(((CompilationUnitDeclaration) builderType.top().get()).compilationResult);
md.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
md.modifiers = ClassFileConstants.AccPublic;
@@ -121,10 +122,12 @@ abstract class EclipseGuavaSingularizer extends EclipseSingularizer {
md.selector = HandlerUtil.buildAccessorName("clear", new String(data.getPluralName())).toCharArray();
md.statements = returnStatement != null ? new Statement[] {a, returnStatement} : new Statement[] {a};
md.returnType = returnType;
+ md.annotations = deprecate ? new Annotation[] { generateDeprecatedAnnotation(data.getSource()) } : null;
+
injectMethod(builderType, md);
}
- void generateSingularMethod(TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType, boolean fluent) {
+ void generateSingularMethod(boolean deprecate, TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType, boolean fluent) {
LombokImmutableList<String> suffixes = getArgumentSuffixes();
char[][] names = new char[suffixes.size()][];
for (int i = 0; i < suffixes.size(); i++) {
@@ -159,12 +162,13 @@ abstract class EclipseGuavaSingularizer extends EclipseSingularizer {
}
md.returnType = returnType;
md.selector = fluent ? data.getSingularName() : HandlerUtil.buildAccessorName(getAddMethodName(), new String(data.getSingularName())).toCharArray();
+ md.annotations = deprecate ? new Annotation[] { generateDeprecatedAnnotation(data.getSource()) } : null;
data.setGeneratedByRecursive(md);
injectMethod(builderType, md);
}
- void generatePluralMethod(TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType, boolean fluent) {
+ void generatePluralMethod(boolean deprecate, 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;
@@ -190,6 +194,7 @@ abstract class EclipseGuavaSingularizer extends EclipseSingularizer {
md.arguments = new Argument[] {param};
md.returnType = returnType;
md.selector = fluent ? data.getPluralName() : HandlerUtil.buildAccessorName(getAddMethodName() + "All", new String(data.getPluralName())).toCharArray();
+ md.annotations = deprecate ? new Annotation[] { generateDeprecatedAnnotation(data.getSource()) } : null;
data.setGeneratedByRecursive(md);
injectMethod(builderType, md);
diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java
index 2d8083d3..cfa48eaf 100644
--- a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java
+++ b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015 The Project Lombok Authors.
+ * Copyright (C) 2015-2017 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,6 +32,7 @@ import lombok.core.handlers.HandlerUtil;
import lombok.eclipse.EclipseNode;
import lombok.eclipse.handlers.EclipseSingularsRecipes.SingularData;
+import org.eclipse.jdt.internal.compiler.ast.Annotation;
import org.eclipse.jdt.internal.compiler.ast.Argument;
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
import org.eclipse.jdt.internal.compiler.ast.EqualExpression;
@@ -87,26 +88,26 @@ abstract class EclipseJavaUtilListSetSingularizer extends EclipseJavaUtilSingula
return Collections.singletonList(injectFieldAndMarkGenerated(builderType, buildField));
}
- @Override public void generateMethods(SingularData data, EclipseNode builderType, boolean fluent, boolean chain) {
+ @Override public void generateMethods(SingularData data, boolean deprecate, EclipseNode builderType, boolean fluent, boolean chain) {
if (useGuavaInstead(builderType)) {
- guavaListSetSingularizer.generateMethods(data, builderType, fluent, chain);
+ guavaListSetSingularizer.generateMethods(data, deprecate, builderType, fluent, chain);
return;
}
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);
+ generateSingularMethod(deprecate, 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);
+ generatePluralMethod(deprecate, 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;
- generateClearMethod(returnType, returnStatement, data, builderType);
+ generateClearMethod(deprecate, returnType, returnStatement, data, builderType);
}
- private void generateClearMethod(TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType) {
+ private void generateClearMethod(boolean deprecate, TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType) {
MethodDeclaration md = new MethodDeclaration(((CompilationUnitDeclaration) builderType.top().get()).compilationResult);
md.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
md.modifiers = ClassFileConstants.AccPublic;
@@ -122,10 +123,11 @@ abstract class EclipseJavaUtilListSetSingularizer extends EclipseJavaUtilSingula
Statement clearStatement = new IfStatement(new EqualExpression(thisDotField, new NullLiteral(0, 0), OperatorIds.NOT_EQUAL), clearMsg, 0, 0);
md.statements = returnStatement != null ? new Statement[] {clearStatement, returnStatement} : new Statement[] {clearStatement};
md.returnType = returnType;
+ md.annotations = deprecate ? new Annotation[] { generateDeprecatedAnnotation(data.getSource()) } : null;
injectMethod(builderType, md);
}
- void generateSingularMethod(TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType, boolean fluent) {
+ void generateSingularMethod(boolean deprecate, 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;
@@ -148,12 +150,13 @@ abstract class EclipseJavaUtilListSetSingularizer extends EclipseJavaUtilSingula
md.arguments = new Argument[] {param};
md.returnType = returnType;
md.selector = fluent ? data.getSingularName() : HandlerUtil.buildAccessorName("add", new String(data.getSingularName())).toCharArray();
+ md.annotations = deprecate ? new Annotation[] { generateDeprecatedAnnotation(data.getSource()) } : null;
data.setGeneratedByRecursive(md);
injectMethod(builderType, md);
}
- void generatePluralMethod(TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType, boolean fluent) {
+ void generatePluralMethod(boolean deprecate, 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;
@@ -178,6 +181,7 @@ abstract class EclipseJavaUtilListSetSingularizer extends EclipseJavaUtilSingula
md.arguments = new Argument[] {param};
md.returnType = returnType;
md.selector = fluent ? data.getPluralName() : HandlerUtil.buildAccessorName("addAll", new String(data.getPluralName())).toCharArray();
+ md.annotations = deprecate ? new Annotation[] { generateDeprecatedAnnotation(data.getSource()) } : null;
data.setGeneratedByRecursive(md);
injectMethod(builderType, md);
diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java
index 3d7b05ed..ee0e6409 100644
--- a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java
+++ b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015 The Project Lombok Authors.
+ * Copyright (C) 2015-2017 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
@@ -29,6 +29,7 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.List;
+import org.eclipse.jdt.internal.compiler.ast.Annotation;
import org.eclipse.jdt.internal.compiler.ast.Argument;
import org.eclipse.jdt.internal.compiler.ast.Block;
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
@@ -132,26 +133,26 @@ public class EclipseJavaUtilMapSingularizer extends EclipseJavaUtilSingularizer
return Arrays.asList(keyFieldNode, valueFieldNode);
}
- @Override public void generateMethods(SingularData data, EclipseNode builderType, boolean fluent, boolean chain) {
+ @Override public void generateMethods(SingularData data, boolean deprecate, EclipseNode builderType, boolean fluent, boolean chain) {
if (useGuavaInstead(builderType)) {
- guavaMapSingularizer.generateMethods(data, builderType, fluent, chain);
+ guavaMapSingularizer.generateMethods(data, deprecate, builderType, fluent, chain);
return;
}
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);
+ generateSingularMethod(deprecate, 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);
+ generatePluralMethod(deprecate, 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;
- generateClearMethod(returnType, returnStatement, data, builderType);
+ generateClearMethod(deprecate, returnType, returnStatement, data, builderType);
}
- private void generateClearMethod(TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType) {
+ private void generateClearMethod(boolean deprecate, TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType) {
MethodDeclaration md = new MethodDeclaration(((CompilationUnitDeclaration) builderType.top().get()).compilationResult);
md.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
md.modifiers = ClassFileConstants.AccPublic;
@@ -178,10 +179,12 @@ public class EclipseJavaUtilMapSingularizer extends EclipseJavaUtilSingularizer
Statement clearStatement = new IfStatement(new EqualExpression(thisDotField, new NullLiteral(0, 0), OperatorIds.NOT_EQUAL), clearMsgs, 0, 0);
md.statements = returnStatement != null ? new Statement[] {clearStatement, returnStatement} : new Statement[] {clearStatement};
md.returnType = returnType;
+ md.annotations = deprecate ? new Annotation[] { generateDeprecatedAnnotation(data.getSource()) } : null;
+
injectMethod(builderType, md);
}
- private void generateSingularMethod(TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType, boolean fluent) {
+ private void generateSingularMethod(boolean deprecate, 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;
@@ -225,12 +228,13 @@ public class EclipseJavaUtilMapSingularizer extends EclipseJavaUtilSingularizer
md.arguments = new Argument[] {keyParam, valueParam};
md.returnType = returnType;
md.selector = fluent ? data.getSingularName() : HandlerUtil.buildAccessorName("put", new String(data.getSingularName())).toCharArray();
+ md.annotations = deprecate ? new Annotation[] { generateDeprecatedAnnotation(data.getSource()) } : null;
data.setGeneratedByRecursive(md);
injectMethod(builderType, md);
}
- private void generatePluralMethod(TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType, boolean fluent) {
+ private void generatePluralMethod(boolean deprecate, 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;
@@ -288,6 +292,7 @@ public class EclipseJavaUtilMapSingularizer extends EclipseJavaUtilSingularizer
md.arguments = new Argument[] {param};
md.returnType = returnType;
md.selector = fluent ? data.getPluralName() : HandlerUtil.buildAccessorName("putAll", new String(data.getPluralName())).toCharArray();
+ md.annotations = deprecate ? new Annotation[] { generateDeprecatedAnnotation(data.getSource()) } : null;
data.setGeneratedByRecursive(md);
injectMethod(builderType, md);