aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorReinier Zwitserloot <reinier@zwitserloot.com>2018-06-13 23:26:15 +0200
committerReinier Zwitserloot <reinier@zwitserloot.com>2018-06-13 23:26:15 +0200
commit5dea27f56fef57eef91697b25d630163193b2979 (patch)
treee7591c0579162a9598b97d1e9349f7a9a7d990d6
parent249256224a8bb928eb9037f2c111854896f39014 (diff)
parent19ad4fd57d32afad1a33f20613fbb2e7607cfee0 (diff)
downloadlombok-5dea27f56fef57eef91697b25d630163193b2979.tar.gz
lombok-5dea27f56fef57eef91697b25d630163193b2979.tar.bz2
lombok-5dea27f56fef57eef91697b25d630163193b2979.zip
Merge branch 'janrieke-superBuilder'
-rw-r--r--AUTHORS1
-rw-r--r--src/core/lombok/Builder.java8
-rw-r--r--src/core/lombok/ConfigurationKeys.java9
-rw-r--r--src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java61
-rw-r--r--src/core/lombok/eclipse/handlers/HandleBuilder.java4
-rw-r--r--src/core/lombok/eclipse/handlers/HandleBuilderDefault.java6
-rw-r--r--src/core/lombok/eclipse/handlers/HandleConstructor.java1
-rw-r--r--src/core/lombok/eclipse/handlers/HandleSetter.java34
-rw-r--r--src/core/lombok/eclipse/handlers/HandleSuperBuilder.java836
-rw-r--r--src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java28
-rw-r--r--src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java24
-rw-r--r--src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSingularizer.java11
-rw-r--r--src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java32
-rw-r--r--src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilSetSingularizer.java8
-rw-r--r--src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilSingularizer.java28
-rw-r--r--src/core/lombok/experimental/SuperBuilder.java66
-rw-r--r--src/core/lombok/javac/handlers/HandleBuilder.java2
-rw-r--r--src/core/lombok/javac/handlers/HandleBuilderDefault.java6
-rw-r--r--src/core/lombok/javac/handlers/HandleSetter.java23
-rw-r--r--src/core/lombok/javac/handlers/HandleSuperBuilder.java738
-rw-r--r--src/core/lombok/javac/handlers/JavacSingularsRecipes.java48
-rw-r--r--src/core/lombok/javac/handlers/singulars/JavacGuavaSingularizer.java28
-rw-r--r--src/core/lombok/javac/handlers/singulars/JavacJavaUtilListSetSingularizer.java26
-rw-r--r--src/core/lombok/javac/handlers/singulars/JavacJavaUtilListSingularizer.java14
-rw-r--r--src/core/lombok/javac/handlers/singulars/JavacJavaUtilMapSingularizer.java33
-rw-r--r--src/core/lombok/javac/handlers/singulars/JavacJavaUtilSetSingularizer.java8
-rw-r--r--src/core/lombok/javac/handlers/singulars/JavacJavaUtilSingularizer.java26
-rw-r--r--test/transform/resource/after-delombok/SuperBuilderAbstract.java129
-rw-r--r--test/transform/resource/after-delombok/SuperBuilderBasic.java133
-rw-r--r--test/transform/resource/after-delombok/SuperBuilderWithCustomBuilderMethod.java132
-rw-r--r--test/transform/resource/after-delombok/SuperBuilderWithDefaults.java119
-rw-r--r--test/transform/resource/after-delombok/SuperBuilderWithGenerics.java133
-rw-r--r--test/transform/resource/after-delombok/SuperBuilderWithGenerics2.java133
-rw-r--r--test/transform/resource/after-ecj/SuperBuilderAbstract.java102
-rw-r--r--test/transform/resource/after-ecj/SuperBuilderBasic.java112
-rw-r--r--test/transform/resource/after-ecj/SuperBuilderWithCustomBuilderMethod.java112
-rw-r--r--test/transform/resource/after-ecj/SuperBuilderWithDefaults.java97
-rw-r--r--test/transform/resource/after-ecj/SuperBuilderWithGenerics.java112
-rw-r--r--test/transform/resource/after-ecj/SuperBuilderWithGenerics2.java112
-rw-r--r--test/transform/resource/before/SuperBuilderAbstract.java20
-rw-r--r--test/transform/resource/before/SuperBuilderBasic.java18
-rw-r--r--test/transform/resource/before/SuperBuilderWithCustomBuilderMethod.java21
-rw-r--r--test/transform/resource/before/SuperBuilderWithDefaults.java18
-rw-r--r--test/transform/resource/before/SuperBuilderWithGenerics.java18
-rw-r--r--test/transform/resource/before/SuperBuilderWithGenerics2.java18
-rw-r--r--website/templates/features/experimental/SuperBuilder.html68
-rw-r--r--website/templates/features/experimental/index.html6
47 files changed, 3517 insertions, 205 deletions
diff --git a/AUTHORS b/AUTHORS
index 4e6f6e52..0e542693 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -7,6 +7,7 @@ DaveLaw <project.lombok@apconsult.de>
Dave Brosius <dbrosius@mebigfatguy.com>
Dawid Rusin <dawidrusin90@gmail.com>
Enrique da Costa Cambio <enrique.dacostacambio@gmail.com>
+Jan Rieke <it@janrieke.de>
Jappe van der Hel <jappe.vanderhel@gmail.com>
Kevin Chirls <kchirls@users.noreply.github.com>
Liu DongMiao <liudongmiao@gmail.com>
diff --git a/src/core/lombok/Builder.java b/src/core/lombok/Builder.java
index a16717cc..d7a2a109 100644
--- a/src/core/lombok/Builder.java
+++ b/src/core/lombok/Builder.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013-2017 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
@@ -55,8 +55,8 @@ import java.lang.annotation.Target;
*
* <pre>
* &#064;Builder
- * class Example {
- * private int foo;
+ * class Example&lt;T&gt; {
+ * private T foo;
* private final String bar;
* }
* </pre>
@@ -103,6 +103,8 @@ import java.lang.annotation.Target;
* }
* }
* </pre>
+ *
+ * @see Singular
*/
@Target({TYPE, METHOD, CONSTRUCTOR})
@Retention(SOURCE)
diff --git a/src/core/lombok/ConfigurationKeys.java b/src/core/lombok/ConfigurationKeys.java
index 46c3f770..f5134bbd 100644
--- a/src/core/lombok/ConfigurationKeys.java
+++ b/src/core/lombok/ConfigurationKeys.java
@@ -544,6 +544,15 @@ public class ConfigurationKeys {
*/
public static final ConfigurationKey<FlagUsageType> WITHER_FLAG_USAGE = new ConfigurationKey<FlagUsageType>("lombok.wither.flagUsage", "Emit a warning or error if @Wither is used.") {};
+ // ----- SuperBuilder -----
+
+ /**
+ * lombok configuration: {@code lombok.superBuilder.flagUsage} = {@code WARNING} | {@code ERROR}.
+ *
+ * If set, <em>any</em> usage of {@code @SuperBuilder} results in a warning / error.
+ */
+ public static final ConfigurationKey<FlagUsageType> SUPERBUILDER_FLAG_USAGE = new ConfigurationKey<FlagUsageType>("lombok.superBuilder.flagUsage", "Emit a warning or error if @SuperBuilder is used.") {};
+
// ----- Configuration System -----
/**
diff --git a/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java b/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java
index bc779dab..b9b9e07d 100644
--- a/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java
+++ b/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015-2017 The Project Lombok Authors.
+ * Copyright (C) 2015-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
@@ -45,6 +45,9 @@ 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.Reference;
+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;
@@ -53,6 +56,7 @@ import org.eclipse.jdt.internal.compiler.ast.Wildcard;
import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
import org.eclipse.jdt.internal.compiler.lookup.MethodScope;
import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
+import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
import lombok.core.LombokImmutableList;
import lombok.core.SpiLoadUtil;
@@ -60,6 +64,14 @@ import lombok.core.TypeLibrary;
import lombok.eclipse.EclipseNode;
public class EclipseSingularsRecipes {
+ public interface TypeReferenceMaker {
+ TypeReference make();
+ }
+
+ public interface StatementMaker {
+ Statement make();
+ }
+
private static final EclipseSingularsRecipes INSTANCE = new EclipseSingularsRecipes();
private final Map<String, EclipseSingularizer> singularizers = new HashMap<String, EclipseSingularizer>();
private final TypeLibrary singularizableTypes = new TypeLibrary();
@@ -215,8 +227,36 @@ public class EclipseSingularsRecipes {
}
public abstract List<EclipseNode> generateFields(SingularData data, EclipseNode builderType);
- 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);
+
+ /**
+ * Generates the singular, plural, and clear methods for the given {@link SingularData}.
+ * Uses the given {@code builderType} as return type if {@code chain == true}, {@code void} otherwise.
+ * If you need more control over the return type and value, use
+ * {@link #generateMethods(SingularData, boolean, EclipseNode, boolean, TypeReferenceMaker, StatementMaker)}.
+ */
+ public void generateMethods(SingularData data, boolean deprecate, final EclipseNode builderType, boolean fluent, final boolean chain) {
+ TypeReferenceMaker returnTypeMaker = new TypeReferenceMaker() {
+ @Override public TypeReference make() {
+ return chain ? cloneSelfType(builderType) : TypeReference.baseTypeReference(TypeIds.T_void, 0);
+ }
+ };
+
+ StatementMaker returnStatementMaker = new StatementMaker() {
+ @Override public ReturnStatement make() {
+ return chain ? new ReturnStatement(new ThisReference(0, 0), 0, 0) : null;
+ }
+ };
+
+ generateMethods(data, deprecate, builderType, fluent, returnTypeMaker, returnStatementMaker);
+ }
+
+ /**
+ * Generates the singular, plural, and clear methods for the given {@link SingularData}.
+ * Uses the given {@code returnTypeMaker} and {@code returnStatementMaker} for the generated methods.
+ */
+ public abstract void generateMethods(SingularData data, boolean deprecate, EclipseNode builderType, boolean fluent, TypeReferenceMaker returnTypeMaker, StatementMaker returnStatementMaker);
+
+ public abstract void appendBuildCode(SingularData data, EclipseNode builderType, List<Statement> statements, char[] targetVariableName, String builderVariable);
public boolean requiresCleaning() {
try {
@@ -307,16 +347,16 @@ 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(). */
- protected Expression getSize(EclipseNode builderType, char[] name, boolean nullGuard) {
+ protected Expression getSize(EclipseNode builderType, char[] name, boolean nullGuard, String builderVariable) {
MessageSend invoke = new MessageSend();
- ThisReference thisRef = new ThisReference(0, 0);
+ Reference thisRef = getBuilderReference(builderVariable);
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);
+ Reference cdnThisRef = getBuilderReference(builderVariable);
FieldReference cdnThisDotName = new FieldReference(name, 0L);
cdnThisDotName.receiver = cdnThisRef;
NullLiteral nullLiteral = new NullLiteral(0, 0);
@@ -345,5 +385,14 @@ public class EclipseSingularsRecipes {
return new QualifiedTypeReference(TypeConstants.JAVA_LANG_OBJECT, NULL_POSS);
}
+
+ /** @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);
+ } else {
+ return new SingleNameReference(builderVariable.toCharArray(), 0);
+ }
+ }
}
}
diff --git a/src/core/lombok/eclipse/handlers/HandleBuilder.java b/src/core/lombok/eclipse/handlers/HandleBuilder.java
index 38bd9b60..e1b1af26 100644
--- a/src/core/lombok/eclipse/handlers/HandleBuilder.java
+++ b/src/core/lombok/eclipse/handlers/HandleBuilder.java
@@ -573,7 +573,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
for (BuilderFieldData bfd : builderFields) {
if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) {
- bfd.singularData.getSingularizer().appendBuildCode(bfd.singularData, type, statements, bfd.name);
+ bfd.singularData.getSingularizer().appendBuildCode(bfd.singularData, type, statements, bfd.name, "this");
}
}
@@ -644,7 +644,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
return trs;
}
- public MethodDeclaration generateDefaultProvider(char[] methodName, TypeParameter[] typeParameters, EclipseNode fieldNode, ASTNode source) {
+ public static MethodDeclaration generateDefaultProvider(char[] methodName, TypeParameter[] typeParameters, EclipseNode fieldNode, ASTNode source) {
int pS = source.sourceStart, pE = source.sourceEnd;
MethodDeclaration out = new MethodDeclaration(((CompilationUnitDeclaration) fieldNode.top().get()).compilationResult);
diff --git a/src/core/lombok/eclipse/handlers/HandleBuilderDefault.java b/src/core/lombok/eclipse/handlers/HandleBuilderDefault.java
index be2b986d..d0c597fd 100644
--- a/src/core/lombok/eclipse/handlers/HandleBuilderDefault.java
+++ b/src/core/lombok/eclipse/handlers/HandleBuilderDefault.java
@@ -31,6 +31,7 @@ import lombok.core.AnnotationValues;
import lombok.core.HandlerPriority;
import lombok.eclipse.EclipseAnnotationHandler;
import lombok.eclipse.EclipseNode;
+import lombok.experimental.SuperBuilder;
@ProviderFor(EclipseAnnotationHandler.class)
@HandlerPriority(-1025) //HandleBuilder's level, minus one.
@@ -39,8 +40,9 @@ public class HandleBuilderDefault extends EclipseAnnotationHandler<Builder.Defau
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.");
+ if (!hasAnnotation(Builder.class, classWithAnnotatedField) && !hasAnnotation("lombok.experimental.Builder", classWithAnnotatedField)
+ && !hasAnnotation(SuperBuilder.class, classWithAnnotatedField)) {
+ annotationNode.addWarning("@Builder.Default requires @Builder or @SuperBuilder 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 eb7fd711..cab847e6 100644
--- a/src/core/lombok/eclipse/handlers/HandleConstructor.java
+++ b/src/core/lombok/eclipse/handlers/HandleConstructor.java
@@ -309,7 +309,6 @@ public class HandleConstructor {
return false;
}
-
private static final char[][] JAVA_BEANS_CONSTRUCTORPROPERTIES = new char[][] { "java".toCharArray(), "beans".toCharArray(), "ConstructorProperties".toCharArray() };
public static Annotation[] createConstructorProperties(ASTNode source, Collection<EclipseNode> fields) {
diff --git a/src/core/lombok/eclipse/handlers/HandleSetter.java b/src/core/lombok/eclipse/handlers/HandleSetter.java
index 64f7c3cf..d4df0deb 100644
--- a/src/core/lombok/eclipse/handlers/HandleSetter.java
+++ b/src/core/lombok/eclipse/handlers/HandleSetter.java
@@ -116,7 +116,7 @@ public class HandleSetter extends EclipseAnnotationHandler<Setter> {
createSetterForField(level, fieldNode, sourceNode, false, onMethod, onParam);
}
- public void handle(AnnotationValues<Setter> annotation, Annotation ast, EclipseNode annotationNode) {
+ @Override public void handle(AnnotationValues<Setter> annotation, Annotation ast, EclipseNode annotationNode) {
handleFlagUsage(annotationNode, ConfigurationKeys.SETTER_FLAG_USAGE, "@Setter");
EclipseNode node = annotationNode.up();
@@ -187,22 +187,34 @@ public class HandleSetter extends EclipseAnnotationHandler<Setter> {
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, boolean deprecate, EclipseNode fieldNode, String name, char[] booleanFieldToSet, boolean shouldReturnThis, int modifier, EclipseNode sourceNode, List<Annotation> onMethod, List<Annotation> onParam) {
+ ASTNode source = sourceNode.get();
+ int pS = source.sourceStart, pE = source.sourceEnd;
+
+ TypeReference returnType = null;
+ ReturnStatement returnThis = null;
+ if (shouldReturnThis) {
+ returnType = cloneSelfType(fieldNode, source);
+ ThisReference thisRef = new ThisReference(pS, pE);
+ returnThis = new ReturnStatement(thisRef, pS, pE);
+ }
+
+ return createSetter(parent, deprecate, fieldNode, name, booleanFieldToSet, returnType, returnThis, modifier, sourceNode, onMethod, onParam);
+ }
+
+ static MethodDeclaration createSetter(TypeDeclaration parent, boolean deprecate, EclipseNode fieldNode, String name, char[] booleanFieldToSet, TypeReference returnType, Statement returnStatement, 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;
long p = (long)pS << 32 | pE;
MethodDeclaration method = new MethodDeclaration(parent.compilationResult);
method.modifiers = modifier;
- if (shouldReturnThis) {
- method.returnType = cloneSelfType(fieldNode, source);
- }
-
- if (method.returnType == null) {
+ if (returnType != null) {
+ method.returnType = returnType;
+ } else {
method.returnType = TypeReference.baseTypeReference(TypeIds.T_void, 0);
method.returnType.sourceStart = pS; method.returnType.sourceEnd = pE;
- shouldReturnThis = false;
}
Annotation[] deprecated = null;
if (isFieldDeprecated(fieldNode) || deprecate) {
@@ -239,10 +251,8 @@ public class HandleSetter extends EclipseAnnotationHandler<Setter> {
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);
- statements.add(returnThis);
+ if (returnType != null && returnStatement != null) {
+ statements.add(returnStatement);
}
method.statements = statements.toArray(new Statement[0]);
param.annotations = copyAnnotations(source, nonNulls, nullables, onParam.toArray(new Annotation[0]));
diff --git a/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java b/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java
new file mode 100644
index 00000000..6b0275e4
--- /dev/null
+++ b/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java
@@ -0,0 +1,836 @@
+/*
+ * 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
+ * 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.core.handlers.HandlerUtil.*;
+import static lombok.eclipse.Eclipse.*;
+import static lombok.eclipse.handlers.EclipseHandlerUtil.*;
+
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+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.ExplicitConstructorCall;
+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.ParameterizedQualifiedTypeReference;
+import org.eclipse.jdt.internal.compiler.ast.ParameterizedSingleTypeReference;
+import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference;
+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.TypeDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.TypeParameter;
+import org.eclipse.jdt.internal.compiler.ast.TypeReference;
+import org.eclipse.jdt.internal.compiler.ast.Wildcard;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
+import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
+import org.eclipse.jdt.internal.compiler.lookup.MethodScope;
+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.Builder.ObtainVia;
+import lombok.ConfigurationKeys;
+import lombok.Singular;
+import lombok.ToString;
+import lombok.core.AST.Kind;
+import lombok.core.handlers.InclusionExclusionUtils.Included;
+import lombok.core.AnnotationValues;
+import lombok.core.HandlerPriority;
+import lombok.eclipse.Eclipse;
+import lombok.eclipse.EclipseAnnotationHandler;
+import lombok.eclipse.EclipseNode;
+import lombok.eclipse.handlers.EclipseHandlerUtil.MemberExistsResult;
+import lombok.eclipse.handlers.EclipseSingularsRecipes.EclipseSingularizer;
+import lombok.eclipse.handlers.EclipseSingularsRecipes.SingularData;
+import lombok.eclipse.handlers.EclipseSingularsRecipes.StatementMaker;
+import lombok.eclipse.handlers.EclipseSingularsRecipes.TypeReferenceMaker;
+import lombok.experimental.NonFinal;
+import lombok.experimental.SuperBuilder;
+
+@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 HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
+ private static final char[] CLEAN_FIELD_NAME = "$lombokUnclean".toCharArray();
+ private static final char[] CLEAN_METHOD_NAME = "$lombokClean".toCharArray();
+ private static final char[] SET_PREFIX = "$set".toCharArray();
+ private static final char[] SELF_METHOD_NAME = "self".toCharArray();
+
+ private static final AbstractMethodDeclaration[] EMPTY_METHODS = {};
+
+ private static class BuilderFieldData {
+ TypeReference type;
+ char[] rawName;
+ char[] name;
+ char[] nameOfSetFlag;
+ SingularData singularData;
+ ObtainVia obtainVia;
+ EclipseNode obtainViaNode;
+ EclipseNode originalFieldNode;
+
+ List<EclipseNode> createdFields = new ArrayList<EclipseNode>();
+ }
+
+ @Override
+ public void handle(AnnotationValues<SuperBuilder> annotation, Annotation ast, EclipseNode annotationNode) {
+ handleExperimentalFlagUsage(annotationNode, ConfigurationKeys.SUPERBUILDER_FLAG_USAGE, "@SuperBuilder");
+
+ long p = (long) ast.sourceStart << 32 | ast.sourceEnd;
+
+ SuperBuilder builderInstance = annotation.getInstance();
+
+ String builderMethodName = builderInstance.builderMethodName();
+ String buildMethodName = builderInstance.buildMethodName();
+
+ if (builderMethodName == null) builderMethodName = "builder";
+ if (buildMethodName == null) buildMethodName = "build";
+
+ if (!checkName("builderMethodName", builderMethodName, annotationNode)) return;
+ if (!checkName("buildMethodName", buildMethodName, annotationNode)) return;
+
+ EclipseNode tdParent = annotationNode.up();
+
+ java.util.List<BuilderFieldData> builderFields = new ArrayList<BuilderFieldData>();
+ TypeReference returnType;
+ TypeParameter[] typeParams;
+
+ boolean addCleaning = false;
+
+ if (!(tdParent.get() instanceof TypeDeclaration)) {
+ annotationNode.addError("@SuperBuilder is only supported on types.");
+ return;
+ }
+ TypeDeclaration td = (TypeDeclaration) tdParent.get();
+
+ // Gather all fields of the class that should be set by the builder.
+ List<EclipseNode> allFields = new ArrayList<EclipseNode>();
+ boolean valuePresent = (hasAnnotation(lombok.Value.class, tdParent) || hasAnnotation("lombok.experimental.Value", tdParent));
+ for (EclipseNode fieldNode : HandleConstructor.findAllFields(tdParent, true)) {
+ FieldDeclaration fd = (FieldDeclaration) fieldNode.get();
+ EclipseNode isDefault = findAnnotation(Builder.Default.class, fieldNode);
+ boolean isFinal = ((fd.modifiers & ClassFileConstants.AccFinal) != 0) || (valuePresent && !hasAnnotation(NonFinal.class, fieldNode));
+
+ BuilderFieldData bfd = new BuilderFieldData();
+ 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 && isDefa