aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/lombok/EqualsAndHashCode.java23
-rw-r--r--src/core/lombok/core/AnnotationProcessor.java51
-rw-r--r--src/core/lombok/core/configuration/CheckerFrameworkVersion.java6
-rw-r--r--src/core/lombok/eclipse/EcjAugments.java (renamed from src/core/lombok/eclipse/EclipseAugments.java)15
-rw-r--r--src/core/lombok/eclipse/HandlerLibrary.java2
-rw-r--r--src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java46
-rwxr-xr-xsrc/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java9
-rwxr-xr-xsrc/core/lombok/eclipse/handlers/HandleBuilder.java582
-rwxr-xr-xsrc/core/lombok/eclipse/handlers/HandleConstructor.java15
-rwxr-xr-xsrc/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java105
-rw-r--r--src/core/lombok/eclipse/handlers/HandleSuperBuilder.java517
-rw-r--r--src/core/lombok/javac/JavacASTVisitor.java26
-rw-r--r--src/core/lombok/javac/apt/LombokProcessor.java69
-rw-r--r--src/core/lombok/javac/handlers/HandleBuilder.java554
-rw-r--r--src/core/lombok/javac/handlers/HandleConstructor.java6
-rw-r--r--src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java68
-rw-r--r--src/core/lombok/javac/handlers/HandleGetter.java2
-rw-r--r--src/core/lombok/javac/handlers/HandleSetter.java33
-rw-r--r--src/core/lombok/javac/handlers/HandleSuperBuilder.java610
-rw-r--r--src/core/lombok/javac/handlers/JavacHandlerUtil.java54
-rw-r--r--src/core/lombok/javac/handlers/JavacSingularsRecipes.java17
-rw-r--r--src/core/lombok/javac/handlers/singulars/JavacGuavaSingularizer.java2
-rw-r--r--src/core/lombok/javac/handlers/singulars/JavacJavaUtilListSingularizer.java2
-rw-r--r--src/core/lombok/javac/handlers/singulars/JavacJavaUtilSingularizer.java6
-rwxr-xr-xsrc/delombok/lombok/delombok/Delombok.java8
-rw-r--r--src/eclipseAgent/lombok/eclipse/agent/EclipsePatcher.java11
-rw-r--r--src/eclipseAgent/lombok/eclipse/agent/PatchDelegate.java6
-rw-r--r--src/eclipseAgent/lombok/eclipse/agent/PatchJavadoc.java8
-rwxr-xr-xsrc/eclipseAgent/lombok/launch/PatchFixesHider.java10
-rw-r--r--src/stubs/com/sun/tools/javac/main/Arguments.java3
-rw-r--r--src/utils/lombok/javac/JavacTreeMaker.java127
31 files changed, 1830 insertions, 1163 deletions
diff --git a/src/core/lombok/EqualsAndHashCode.java b/src/core/lombok/EqualsAndHashCode.java
index 6805d214..279e6e3d 100644
--- a/src/core/lombok/EqualsAndHashCode.java
+++ b/src/core/lombok/EqualsAndHashCode.java
@@ -71,6 +71,14 @@ public @interface EqualsAndHashCode {
* @return If {@code true}, always use direct field access instead of calling the getter method.
*/
boolean doNotUseGetters() default false;
+
+ /**
+ * Determines how the result of the {@code hashCode} method will be cached.
+ * <strong>default: {@link CacheStrategy#NEVER}</strong>
+ *
+ * @return The {@code hashCode} cache strategy to be used.
+ */
+ CacheStrategy cacheStrategy() default CacheStrategy.NEVER;
/**
* Any annotations listed here are put on the generated parameter of {@code equals} and {@code canEqual}.
@@ -132,4 +140,19 @@ public @interface EqualsAndHashCode {
*/
int rank() default 0;
}
+
+ public enum CacheStrategy {
+ /**
+ * Never cache. Perform the calculation every time the method is called.
+ */
+ NEVER,
+ /**
+ * Cache the result of the first invocation of {@code hashCode} and use it for subsequent invocations.
+ * This can improve performance if all fields used for calculating the {@code hashCode} are immutable
+ * and thus every invocation of {@code hashCode} will always return the same value.
+ * <strong>Do not use this if there's <em>any</em> chance that different invocations of {@code hashCode}
+ * might return different values.</strong>
+ */
+ LAZY
+ }
}
diff --git a/src/core/lombok/core/AnnotationProcessor.java b/src/core/lombok/core/AnnotationProcessor.java
index d4a92408..c72d1bb2 100644
--- a/src/core/lombok/core/AnnotationProcessor.java
+++ b/src/core/lombok/core/AnnotationProcessor.java
@@ -26,8 +26,9 @@ import static lombok.core.Augments.ClassLoader_lombokAlreadyAddedTo;
import java.io.File;
import java.io.PrintWriter;
import java.io.StringWriter;
-import java.lang.reflect.Field;
+import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
@@ -83,15 +84,11 @@ public class AnnotationProcessor extends AbstractProcessor {
for (Class<?> procEnvClass = procEnv.getClass(); procEnvClass != null; procEnvClass = procEnvClass.getSuperclass()) {
try {
- Field field;
- try {
- field = Permit.getField(procEnvClass, "delegate");
- } catch (NoSuchFieldException e) {
- field = Permit.getField(procEnvClass, "processingEnv");
- }
- Object delegate = field.get(procEnv);
-
- return tryRecursivelyObtainJavacProcessingEnvironment((ProcessingEnvironment) delegate);
+ Object delegate = tryGetDelegateField(procEnvClass, procEnv);
+ if (delegate == null) delegate = tryGetProcessingEnvField(procEnvClass, procEnv);
+ if (delegate == null) delegate = tryGetProxyDelegateToField(procEnvClass, procEnv);
+
+ if (delegate != null) return tryRecursivelyObtainJavacProcessingEnvironment((ProcessingEnvironment) delegate);
} catch (final Exception e) {
// no valid delegate, try superclass
}
@@ -100,6 +97,40 @@ public class AnnotationProcessor extends AbstractProcessor {
return null;
}
+ /**
+ * Gradle incremental processing
+ */
+ private static Object tryGetDelegateField(Class<?> delegateClass, Object instance) {
+ try {
+ return Permit.getField(delegateClass, "delegate").get(instance);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ /**
+ * Kotlin incremental processing
+ */
+ private static Object tryGetProcessingEnvField(Class<?> delegateClass, Object instance) {
+ try {
+ return Permit.getField(delegateClass, "processingEnv").get(instance);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ /**
+ * InteliJ >= 2020.3
+ */
+ private static Object tryGetProxyDelegateToField(Class<?> delegateClass, Object instance) {
+ try {
+ InvocationHandler handler = Proxy.getInvocationHandler(instance);
+ return Permit.getField(handler.getClass(), "val$delegateTo").get(handler);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
static class JavacDescriptor extends ProcessorDescriptor {
private Processor processor;
diff --git a/src/core/lombok/core/configuration/CheckerFrameworkVersion.java b/src/core/lombok/core/configuration/CheckerFrameworkVersion.java
index 5805678f..c37ba91d 100644
--- a/src/core/lombok/core/configuration/CheckerFrameworkVersion.java
+++ b/src/core/lombok/core/configuration/CheckerFrameworkVersion.java
@@ -32,9 +32,9 @@ public final class CheckerFrameworkVersion implements ConfigurationValueType {
public static final String NAME__SIDE_EFFECT_FREE = "org.checkerframework.dataflow.qual.SideEffectFree";
public static final String NAME__PURE = "org.checkerframework.dataflow.qual.Pure";
public static final String NAME__UNIQUE = "org.checkerframework.common.aliasing.qual.Unique";
- public static final String NAME__RETURNS_RECEIVER = "org.checkerframework.checker.builder.qual.ReturnsReceiver";
- public static final String NAME__NOT_CALLED = "org.checkerframework.checker.builder.qual.NotCalledMethods";
- public static final String NAME__CALLED = "org.checkerframework.checker.builder.qual.CalledMethods";
+ public static final String NAME__RETURNS_RECEIVER = "org.checkerframework.common.returnsreceiver.qual.This";
+ public static final String NAME__NOT_CALLED = "org.checkerframework.checker.calledmethods.qual.NotCalledMethods";
+ public static final String NAME__CALLED = "org.checkerframework.checker.calledmethods.qual.CalledMethods";
public static final CheckerFrameworkVersion NONE = new CheckerFrameworkVersion(0);
diff --git a/src/core/lombok/eclipse/EclipseAugments.java b/src/core/lombok/eclipse/EcjAugments.java
index 783e25c9..965c4fb6 100644
--- a/src/core/lombok/eclipse/EclipseAugments.java
+++ b/src/core/lombok/eclipse/EcjAugments.java
@@ -33,8 +33,8 @@ import org.eclipse.jdt.internal.core.SourceMethod;
import lombok.core.FieldAugment;
-public final class EclipseAugments {
- private EclipseAugments() {
+public final class EcjAugments {
+ private EcjAugments() {
// Prevent instantiation
}
@@ -42,6 +42,13 @@ public final class EclipseAugments {
public static final FieldAugment<ASTNode, Boolean> ASTNode_handled = FieldAugment.augment(ASTNode.class, boolean.class, "lombok$handled");
public static final FieldAugment<ASTNode, ASTNode> ASTNode_generatedBy = FieldAugment.augment(ASTNode.class, ASTNode.class, "$generatedBy");
public static final FieldAugment<Annotation, Boolean> Annotation_applied = FieldAugment.augment(Annotation.class, boolean.class, "lombok$applied");
- public static final FieldAugment<CompilationUnit, Map<String, String>> CompilationUnit_javadoc = FieldAugment.augment(CompilationUnit.class, Map.class, "$javadoc");
- public static final FieldAugment<CompilationUnit, ConcurrentMap<String, List<SourceMethod>>> CompilationUnit_delegateMethods = FieldAugment.augment(CompilationUnit.class, ConcurrentMap.class, "$delegateMethods");
+
+ public static final class EclipseAugments {
+ private EclipseAugments() {
+ // Prevent instantiation
+ }
+
+ public static final FieldAugment<CompilationUnit, Map<String, String>> CompilationUnit_javadoc = FieldAugment.augment(CompilationUnit.class, Map.class, "$javadoc");
+ public static final FieldAugment<CompilationUnit, ConcurrentMap<String, List<SourceMethod>>> CompilationUnit_delegateMethods = FieldAugment.augment(CompilationUnit.class, ConcurrentMap.class, "$delegateMethods");
+ }
}
diff --git a/src/core/lombok/eclipse/HandlerLibrary.java b/src/core/lombok/eclipse/HandlerLibrary.java
index 0e72fb38..8d69325e 100644
--- a/src/core/lombok/eclipse/HandlerLibrary.java
+++ b/src/core/lombok/eclipse/HandlerLibrary.java
@@ -23,7 +23,7 @@ package lombok.eclipse;
import static lombok.eclipse.Eclipse.*;
import static lombok.eclipse.handlers.EclipseHandlerUtil.*;
-import static lombok.eclipse.EclipseAugments.ASTNode_handled;
+import static lombok.eclipse.EcjAugments.ASTNode_handled;
import java.io.IOException;
import java.lang.annotation.Annotation;
diff --git a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java
index d85c2ee8..03f26341 100644
--- a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java
+++ b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java
@@ -23,7 +23,7 @@ package lombok.eclipse.handlers;
import static lombok.core.handlers.HandlerUtil.*;
import static lombok.eclipse.Eclipse.*;
-import static lombok.eclipse.EclipseAugments.*;
+import static lombok.eclipse.EcjAugments.*;
import static lombok.eclipse.handlers.EclipseHandlerUtil.EclipseReflectiveMembers.*;
import java.lang.reflect.Array;
@@ -2649,22 +2649,42 @@ public class EclipseHandlerUtil {
return null;
}
+ private static class EclipseOnlyUtil {
+ public static void setDocComment(CompilationUnitDeclaration cud, TypeDeclaration type, ASTNode node, String doc) {
+ if (cud.compilationResult.compilationUnit instanceof CompilationUnit) {
+ CompilationUnit compilationUnit = (CompilationUnit) cud.compilationResult.compilationUnit;
+ Map<String, String> docs = EclipseAugments.CompilationUnit_javadoc.setIfAbsent(compilationUnit, new HashMap<String, String>());
+
+ if (node instanceof AbstractMethodDeclaration) {
+ AbstractMethodDeclaration methodDeclaration = (AbstractMethodDeclaration) node;
+ String signature = getSignature(type, methodDeclaration);
+ /* Add javadoc start marker, add leading asterisks to each line, add javadoc end marker */
+ docs.put(signature, String.format("/**%n%s%n */", doc.replaceAll("(?m)^", " * ")));
+ }
+ }
+ }
+ }
+
+ private static Boolean eclipseMode;
+ private static boolean eclipseMode() {
+ if (eclipseMode != null) return eclipseMode.booleanValue();
+ try {
+ Class.forName("org.eclipse.jdt.internal.core.CompilationUnit");
+ eclipseMode = true;
+ } catch (Exception e) {
+ eclipseMode = false;
+ }
+ return eclipseMode;
+ }
+
public static void setDocComment(CompilationUnitDeclaration cud, EclipseNode eclipseNode, String doc) {
+ if (!eclipseMode()) return;
setDocComment(cud, (TypeDeclaration) upToTypeNode(eclipseNode).get(), eclipseNode.get(), doc);
}
-
+
public static void setDocComment(CompilationUnitDeclaration cud, TypeDeclaration type, ASTNode node, String doc) {
- if (cud.compilationResult.compilationUnit instanceof CompilationUnit) {
- CompilationUnit compilationUnit = (CompilationUnit) cud.compilationResult.compilationUnit;
- Map<String, String> docs = CompilationUnit_javadoc.setIfAbsent(compilationUnit, new HashMap<String, String>());
-
- if (node instanceof AbstractMethodDeclaration) {
- AbstractMethodDeclaration methodDeclaration = (AbstractMethodDeclaration) node;
- String signature = getSignature(type, methodDeclaration);
- /* Add javadoc start marker, add leading asterisks to each line, add javadoc end marker */
- docs.put(signature, String.format("/**%n%s%n */", doc.replaceAll("(?m)^", " * ")));
- }
- }
+ if (!eclipseMode()) return;
+ EclipseOnlyUtil.setDocComment(cud, type, node, doc);
}
public static String getSignature(TypeDeclaration type, AbstractMethodDeclaration methodDeclaration) {
diff --git a/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java b/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java
index 85243ec1..760f5282 100755
--- a/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java
+++ b/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java
@@ -68,6 +68,7 @@ import lombok.core.SpiLoadUtil;
import lombok.core.TypeLibrary;
import lombok.core.configuration.CheckerFrameworkVersion;
import lombok.eclipse.EclipseNode;
+import lombok.eclipse.handlers.HandleBuilder.BuilderJob;
public class EclipseSingularsRecipes {
public interface TypeReferenceMaker {
@@ -258,20 +259,20 @@ public class EclipseSingularsRecipes {
* If you need more control over the return type and value, use
* {@link #generateMethods(SingularData, boolean, EclipseNode, boolean, TypeReferenceMaker, StatementMaker)}.
*/
- public void generateMethods(CheckerFrameworkVersion cfv, SingularData data, boolean deprecate, final EclipseNode builderType, boolean fluent, final boolean chain, AccessLevel access) {
+ public void generateMethods(final BuilderJob job, SingularData data, boolean deprecate) {
TypeReferenceMaker returnTypeMaker = new TypeReferenceMaker() {
@Override public TypeReference make() {
- return chain ? cloneSelfType(builderType) : TypeReference.baseTypeReference(TypeIds.T_void, 0);
+ return job.oldChain ? cloneSelfType(job.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;
+ return job.oldChain ? new ReturnStatement(new ThisReference(0, 0), 0, 0) : null;
}
};
- generateMethods(cfv, data, deprecate, builderType, fluent, returnTypeMaker, returnStatementMaker, access);
+ generateMethods(job.checkerFramework, data, deprecate, job.builderType, job.oldFluent, returnTypeMaker, returnStatementMaker, job.accessInners);
}
/**
diff --git a/src/core/lombok/eclipse/handlers/HandleBuilder.java b/src/core/lombok/eclipse/handlers/HandleBuilder.java
index 9e6c28e8..f8eb9ed0 100755
--- a/src/core/lombok/eclipse/handlers/HandleBuilder.java
+++ b/src/core/lombok/eclipse/handlers/HandleBuilder.java
@@ -25,7 +25,6 @@ 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;
@@ -107,8 +106,16 @@ import lombok.experimental.NonFinal;
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();
+ static final char[] CLEAN_FIELD_NAME = "$lombokUnclean".toCharArray();
+ static final char[] CLEAN_METHOD_NAME = "$lombokClean".toCharArray();
+ static final String TO_BUILDER_METHOD_NAME_STRING = "toBuilder";
+ static final char[] TO_BUILDER_METHOD_NAME = TO_BUILDER_METHOD_NAME_STRING.toCharArray();
+ static final char[] DEFAULT_PREFIX = {'$', 'd', 'e', 'f', 'a', 'u', 'l', 't', '$'};
+ static final char[] SET_PREFIX = {'$', 's', 'e', 't'};
+ static final char[] VALUE_PREFIX = {'$', 'v', 'a', 'l', 'u', 'e'};
+ static final char[] BUILDER_TEMP_VAR = {'b', 'u', 'i', 'l', 'd', 'e', 'r'};
+ static final AbstractMethodDeclaration[] EMPTY_METHODS = {};
+ static final String TO_BUILDER_NOT_SUPPORTED = "@Builder(toBuilder=true) is only supported if you return your own type.";
private static final boolean toBoolean(Object expr, boolean defaultValue) {
if (expr == null) return defaultValue;
@@ -117,6 +124,95 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
return ((Boolean) expr).booleanValue();
}
+ static class BuilderJob {
+ CheckerFrameworkVersion checkerFramework;
+ EclipseNode parentType;
+ String builderMethodName, buildMethodName;
+ boolean isStatic;
+ TypeParameter[] typeParams;
+ TypeParameter[] builderTypeParams;
+ ASTNode source;
+ EclipseNode sourceNode;
+ List<BuilderFieldData> builderFields;
+ AccessLevel accessInners, accessOuters;
+ boolean oldFluent, oldChain, toBuilder;
+
+ EclipseNode builderType;
+ String builderClassName;
+ char[] builderClassNameArr;
+
+ void setBuilderClassName(String builderClassName) {
+ this.builderClassName = builderClassName;
+ this.builderClassNameArr = builderClassName.toCharArray();
+ }
+
+ TypeParameter[] copyTypeParams() {
+ return EclipseHandlerUtil.copyTypeParams(typeParams, source);
+ }
+
+ long getPos() {
+ return ((long) source.sourceStart) << 32 | source.sourceEnd;
+ }
+
+ public TypeReference createBuilderTypeReference() {
+ return namePlusTypeParamsToTypeReference(parentType, builderClassNameArr, !isStatic, builderTypeParams, getPos());
+ }
+
+ public TypeReference createBuilderTypeReferenceForceStatic() {
+ return namePlusTypeParamsToTypeReference(parentType, builderClassNameArr, false, builderTypeParams, getPos());
+ }
+
+ public TypeReference createBuilderParentTypeReference() {
+ return namePlusTypeParamsToTypeReference(parentType, typeParams, getPos());
+ }
+
+ public EclipseNode getTopNode() {
+ return parentType.top();
+ }
+
+ void init(AnnotationValues<Builder> annValues, Builder ann, EclipseNode node) {
+ accessOuters = ann.access();
+ if (accessOuters == null) accessOuters = AccessLevel.PUBLIC;
+ if (accessOuters == AccessLevel.NONE) {
+ sourceNode.addError("AccessLevel.NONE is not valid here");
+ accessOuters = AccessLevel.PUBLIC;
+ }
+ accessInners = accessOuters == AccessLevel.PROTECTED ? AccessLevel.PUBLIC : accessOuters;
+
+ // These exist just to support the 'old' lombok.experimental.Builder, which had these properties. lombok.Builder no longer has them.
+ oldFluent = toBoolean(annValues.getActualExpression("fluent"), true);
+ oldChain = toBoolean(annValues.getActualExpression("chain"), true);
+
+ builderMethodName = ann.builderMethodName();
+ buildMethodName = ann.buildMethodName();
+ setBuilderClassName(fixBuilderClassName(node, ann.builderClassName()));
+ toBuilder = ann.toBuilder();
+
+ if (builderMethodName == null) builderMethodName = "builder";
+ if (buildMethodName == null) buildMethodName = "build";
+ }
+
+ static String fixBuilderClassName(EclipseNode node, String override) {
+ if (override != null && !override.isEmpty()) return override;
+ override = node.getAst().readConfiguration(ConfigurationKeys.BUILDER_CLASS_NAME);
+ if (override != null && !override.isEmpty()) return override;
+ return "*Builder";
+ }
+
+ MethodDeclaration createNewMethodDeclaration() {
+ return new MethodDeclaration(((CompilationUnitDeclaration) getTopNode().get()).compilationResult);
+ }
+
+ String replaceBuilderClassName(char[] name) {
+ if (builderClassName.indexOf('*') == -1) return builderClassName;
+ return builderClassName.replace("*", new String(name));
+ }
+
+ String replaceBuilderClassName(String name) {
+ return builderClassName.replace("*", name);
+ }
+ }
+
static class BuilderFieldData {
Annotation[] annotations;
TypeReference type;
@@ -151,10 +247,6 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
return true;
}
- private static final char[] DEFAULT_PREFIX = {'$', 'd', 'e', 'f', 'a', 'u', 'l', 't', '$'};
- private static final char[] SET_PREFIX = {'$', 's', 'e', 't'};
- private static final char[] VALUE_PREFIX = {'$', 'v', 'a', 'l', 'u', 'e'};
-
private static final char[] prefixWith(char[] prefix, char[] name) {
char[] out = new char[prefix.length + name.length];
System.arraycopy(prefix, 0, out, 0, prefix.length);
@@ -164,87 +256,57 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
@Override public void handle(AnnotationValues<Builder> annotation, Annotation ast, EclipseNode annotationNode) {
handleFlagUsage(annotationNode, ConfigurationKeys.BUILDER_FLAG_USAGE, "@Builder");
- CheckerFrameworkVersion cfv = getCheckerFrameworkVersion(annotationNode);
+ BuilderJob job = new BuilderJob();
+ job.sourceNode = annotationNode;
+ job.source = ast;
+ job.checkerFramework = getCheckerFrameworkVersion(annotationNode);
+ job.isStatic = true;
- long p = (long) ast.sourceStart << 32 | ast.sourceEnd;
-
- Builder builderInstance = annotation.getInstance();
- AccessLevel accessForOuters = builderInstance.access();
- if (accessForOuters == null) accessForOuters = AccessLevel.PUBLIC;
- if (builderInstance.access() == AccessLevel.NONE) {
- annotationNode.addError("AccessLevel.NONE is not valid here");
- accessForOuters = AccessLevel.PUBLIC;
- }
- AccessLevel accessForInners = accessForOuters == AccessLevel.PROTECTED ? AccessLevel.PUBLIC : accessForOuters;
-
- // These exist just to support the 'old' lombok.experimental.Builder, which had these properties. lombok.Builder no longer has them.
- boolean fluent = toBoolean(annotation.getActualExpression("fluent"), true);
- boolean chain = toBoolean(annotation.getActualExpression("chain"), true);
-
- String builderMethodName = builderInstance.builderMethodName();
- String buildMethodName = builderInstance.buildMethodName();
- String builderClassName = builderInstance.builderClassName();
- String toBuilderMethodName = "toBuilder";
- boolean toBuilder = builderInstance.toBuilder();
+ Builder annInstance = annotation.getInstance();
+ job.init(annotation, annInstance, annotationNode);
List<char[]> typeArgsForToBuilder = null;
- if (builderMethodName == null) builderMethodName = "builder";
- if (buildMethodName == null) buildMethodName = "build";
- if (builderClassName == null) builderClassName = "";
-
boolean generateBuilderMethod;
- if (builderMethodName.isEmpty()) {
+ if (job.builderMethodName.isEmpty()) {
generateBuilderMethod = false;
- } else if (!checkName("builderMethodName", builderMethodName, annotationNode)) {
+ } else if (!checkName("builderMethodName", job.builderMethodName, annotationNode)) {
return;
} else {
generateBuilderMethod = true;
}
- if (!checkName("buildMethodName", buildMethodName, annotationNode)) return;
- if (!builderClassName.isEmpty()) {
- if (!checkName("builderClassName", builderClassName, annotationNode)) return;
- }
+ if (!checkName("buildMethodName", job.buildMethodName, annotationNode)) return;
EclipseNode parent = annotationNode.up();
- List<BuilderFieldData> builderFields = new ArrayList<BuilderFieldData>();
- TypeReference returnType;
- TypeParameter[] typeParams;
- TypeReference[] thrownExceptions;
- char[] nameOfStaticBuilderMethod;
- EclipseNode tdParent;
+ job.builderFields = new ArrayList<BuilderFieldData>();
+ TypeReference buildMethodReturnType;
+ TypeReference[] buildMethodThrownExceptions;
+ char[] nameOfBuilderMethod;
EclipseNode fillParametersFrom = parent.get() instanceof AbstractMethodDeclaration ? parent : null;
boolean addCleaning = false;
- boolean isStatic = true;
List<EclipseNode> nonFinalNonDefaultedFields = null;
- if (builderClassName.isEmpty()) builderClassName = annotationNode.getAst().readConfiguration(ConfigurationKeys.BUILDER_CLASS_NAME);
- if (builderClassName == null || builderClassName.isEmpty()) builderClassName = "*Builder";
- boolean replaceNameInBuilderClassName = builderClassName.contains("*");
-
if (parent.get() instanceof TypeDeclaration) {
- tdParent = parent;
- TypeDeclaration td = (TypeDeclaration) tdParent.get();
+ job.parentType = parent;
+ TypeDeclaration td = (TypeDeclaration) parent.get();
List<EclipseNode> allFields = new ArrayList<EclipseNode>();
boolean valuePresent = (hasAnnotation(lombok.Value.class, parent) || hasAnnotation("lombok.experimental.Value", parent));
- for (EclipseNode fieldNode : HandleConstructor.findAllFields(tdParent, true)) {
+ for (EclipseNode fieldNode : HandleConstructor.findAllFields(parent, true)) {
FieldDeclaration fd = (FieldDeclaration) fieldNode.get();
EclipseNode isDefault = findAnnotation(Builder.Default.class, fieldNode);
boolean isFinal = ((fd.modifiers & ClassFileConstants.AccFinal) != 0) || (valuePresent && !hasAnnotation(NonFinal.class, fieldNode));
- Annotation[] copyableAnnotations = findCopyableAnnotations(fieldNode);
-
BuilderFieldData bfd = new BuilderFieldData();
bfd.rawName = fieldNode.getName().toCharArray();
bfd.name = removePrefixFromField(fieldNode);
bfd.builderFieldName = bfd.name;
- bfd.annotations = copyAnnotations(fd, copyableAnnotations);
+ bfd.annotations = copyAnnotations(fd, findCopyableAnnotations(fieldNode));
bfd.type = fd.type;
- bfd.singularData = getSingularData(fieldNode, ast, builderInstance.setterPrefix());
+ bfd.singularData = getSingularData(fieldNode, ast, annInstance.setterPrefix());
bfd.originalFieldNode = fieldNode;
if (bfd.singularData != null && isDefault != null) {
@@ -269,22 +331,22 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
bfd.builderFieldName = prefixWith(bfd.name, VALUE_PREFIX);
MethodDeclaration md = generateDefaultProvider(bfd.nameOfDefaultProvider, td.typeParameters, fieldNode, ast);
- if (md != null) injectMethod(tdParent, md);
+ if (md != null) injectMethod(parent, md);
}
addObtainVia(bfd, fieldNode);
- builderFields.add(bfd);
+ job.builderFields.add(bfd);
allFields.add(fieldNode);
}
- handleConstructor.generateConstructor(tdParent, AccessLevel.PACKAGE, allFields, false, null, SkipIfConstructorExists.I_AM_BUILDER,
+ handleConstructor.generateConstructor(parent, AccessLevel.PACKAGE, allFields, false, null, SkipIfConstructorExists.I_AM_BUILDER,
Collections.<Annotation>emptyList(), annotationNode);
- returnType = namePlusTypeParamsToTypeReference(tdParent, td.typeParameters, p);
- typeParams = td.typeParameters;
- thrownExceptions = null;
- nameOfStaticBuilderMethod = null;
- if (replaceNameInBuilderClassName) builderClassName = builderClassName.replace("*", new String(td.name));
- replaceNameInBuilderClassName = false;
+ job.typeParams = job.builderTypeParams = td.typeParameters;
+ buildMethodReturnType = job.createBuilderParentTypeReference();
+ buildMethodThrownExceptions = null;
+ nameOfBuilderMethod = null;
+ job.setBuilderClassName(job.replaceBuilderClassName(td.name));
+ if (!checkName("builderClassName", job.builderClassName, annotationNode)) return;
} else if (parent.get() instanceof ConstructorDeclaration) {
ConstructorDeclaration cd = (ConstructorDeclaration) parent.get();
if (cd.typeParameters != null && cd.typeParameters.length > 0) {
@@ -292,21 +354,20 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
return;
}
- tdParent = parent.up();
- TypeDeclaration td = (TypeDeclaration) tdParent.get();
- returnType = namePlusTypeParamsToTypeReference(tdParent, td.typeParameters, p);
- typeParams = td.typeParameters;
- thrownExceptions = cd.thrownExceptions;
- nameOfStaticBuilderMethod = null;
- if (replaceNameInBuilderClassName) builderClassName = builderClassName.replace("*", new String(cd.selector));
- replaceNameInBuilderClassName = false;
+ job.parentType = parent.up();
+ TypeDeclaration td = (TypeDeclaration) job.parentType.get();
+ job.typeParams = job.builderTypeParams = td.typeParameters;
+ buildMethodReturnType = job.createBuilderParentTypeReference();
+ buildMethodThrownExceptions = cd.thrownExceptions;
+ nameOfBuilderMethod = null;
+ job.setBuilderClassName(job.replaceBuilderClassName(cd.selector));
+ if (!checkName("builderClassName", job.builderClassName, annotationNode)) return;
} else if (parent.get() instanceof MethodDeclaration) {
MethodDeclaration md = (MethodDeclaration) parent.get();
- tdParent = parent.up();
- isStatic = md.isStatic();
+ job.parentType = parent.up();
+ job.isStatic = md.isStatic();
- if (toBuilder) {
- final String TO_BUILDER_NOT_SUPPORTED = "@Builder(toBuilder=true) is only supported if you return your own type.";
+ if (job.toBuilder) {
char[] token;
char[][] pkg = null;
if (md.returnType.dimensions() > 0) {
@@ -332,12 +393,12 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
return;
}
- if (tdParent == null || !equals(tdParent.getName(), token)) {
+ if (job.parentType == null || !equals(job.parentType.getName(), token)) {
annotationNode.addError(TO_BUILDER_NOT_SUPPORTED);
return;
}
- TypeParameter[] tpOnType = ((TypeDeclaration) tdParent.get()).typeParameters;
+ TypeParameter[] tpOnType = ((TypeDeclaration) job.parentType.get()).typeParameters;
TypeParameter[] tpOnMethod = md.typeParameters;
TypeReference[][] tpOnRet_ = null;
if (md.returnType instanceof ParameterizedSingleTypeReference) {
@@ -376,15 +437,15 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
}
}
- returnType = copyType(md.returnType, ast);