diff options
Diffstat (limited to 'src')
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); |
