From 0064c534273d9fb877f7e570f7a430060c88a5fb Mon Sep 17 00:00:00 2001 From: Rawi01 Date: Thu, 10 Sep 2020 10:20:12 +0200 Subject: Add record support --- src/core/lombok/eclipse/EclipseAST.java | 17 ++-- .../eclipse/handlers/EclipseHandlerUtil.java | 91 ++++++++++++++++++++-- .../lombok/eclipse/handlers/HandleBuilder.java | 6 +- .../lombok/eclipse/handlers/HandleConstructor.java | 7 +- src/core/lombok/eclipse/handlers/HandleData.java | 11 +-- .../eclipse/handlers/HandleEqualsAndHashCode.java | 6 +- .../eclipse/handlers/HandleFieldDefaults.java | 8 +- src/core/lombok/eclipse/handlers/HandleGetter.java | 8 +- src/core/lombok/eclipse/handlers/HandleLog.java | 4 + .../lombok/eclipse/handlers/HandleNonNull.java | 18 ++++- src/core/lombok/eclipse/handlers/HandleSetter.java | 8 +- .../eclipse/handlers/HandleSuperBuilder.java | 2 +- .../eclipse/handlers/HandleSynchronized.java | 7 +- .../lombok/eclipse/handlers/HandleToString.java | 10 +-- .../eclipse/handlers/HandleUtilityClass.java | 9 +-- src/core/lombok/eclipse/handlers/HandleValue.java | 5 +- src/core/lombok/eclipse/handlers/HandleWithBy.java | 7 +- src/core/lombok/javac/handlers/HandleBuilder.java | 4 +- .../lombok/javac/handlers/HandleConstructor.java | 7 +- .../javac/handlers/HandleEqualsAndHashCode.java | 8 +- .../lombok/javac/handlers/HandleFieldDefaults.java | 7 +- src/core/lombok/javac/handlers/HandleGetter.java | 8 +- src/core/lombok/javac/handlers/HandleLog.java | 13 +++- src/core/lombok/javac/handlers/HandleNonNull.java | 15 ++++ src/core/lombok/javac/handlers/HandleSetter.java | 7 +- .../lombok/javac/handlers/HandleSuperBuilder.java | 2 +- .../lombok/javac/handlers/HandleSynchronized.java | 8 +- src/core/lombok/javac/handlers/HandleToString.java | 8 +- .../lombok/javac/handlers/HandleUtilityClass.java | 9 +-- .../lombok/javac/handlers/JavacHandlerUtil.java | 37 ++++++++- 30 files changed, 220 insertions(+), 137 deletions(-) (limited to 'src/core') diff --git a/src/core/lombok/eclipse/EclipseAST.java b/src/core/lombok/eclipse/EclipseAST.java index d53856af..2c860e14 100644 --- a/src/core/lombok/eclipse/EclipseAST.java +++ b/src/core/lombok/eclipse/EclipseAST.java @@ -21,6 +21,8 @@ */ package lombok.eclipse; +import static lombok.eclipse.handlers.EclipseHandlerUtil.*; + import java.io.File; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; @@ -34,7 +36,6 @@ import java.util.List; import lombok.Lombok; import lombok.core.AST; import lombok.core.LombokImmutableList; -import lombok.eclipse.handlers.EclipseHandlerUtil; import lombok.permit.Permit; import org.eclipse.core.resources.ResourcesPlugin; @@ -117,7 +118,7 @@ public class EclipseAST extends AST { try { return EclipseWorkspaceBasedFileResolver.resolve(fileName); } catch (IllegalArgumentException e) { - EclipseHandlerUtil.warning("Finding 'lombok.config' file failed for '" + fileName + "'", e); + warning("Finding 'lombok.config' file failed for '" + fileName + "'", e); // String msg = e.getMessage(); // if (msg != null && msg.startsWith("Path must include project and resource name")) { // // We shouldn't throw an exception at all, but we can't reproduce this so we need help from our users to figure this out. @@ -362,7 +363,7 @@ public class EclipseAST extends AST { case TYPE: return buildType((TypeDeclaration) node); case FIELD: - return buildField((FieldDeclaration) node); + return buildField((FieldDeclaration) node, null); case INITIALIZER: return buildInitializer((Initializer) node); case METHOD: @@ -401,16 +402,16 @@ public class EclipseAST extends AST { private EclipseNode buildType(TypeDeclaration type) { if (setAndGetAsHandled(type)) return null; List childNodes = new ArrayList(); - childNodes.addAll(buildFields(type.fields)); + childNodes.addAll(buildFields(type.fields, getRecordFieldAnnotations(type))); childNodes.addAll(buildTypes(type.memberTypes)); childNodes.addAll(buildMethods(type.methods)); childNodes.addAll(buildAnnotations(type.annotations, false)); return putInMap(new EclipseNode(this, type, childNodes, Kind.TYPE)); } - private Collection buildFields(FieldDeclaration[] children) { + private Collection buildFields(FieldDeclaration[] children, Annotation[][] annotations) { List childNodes = new ArrayList(); - if (children != null) for (FieldDeclaration child : children) addIfNotNull(childNodes, buildField(child)); + if (children != null) for (int i = 0; i < children.length; i++) addIfNotNull(childNodes, buildField(children[i], annotations[i])); return childNodes; } @@ -420,13 +421,13 @@ public class EclipseAST extends AST { return list; } - private EclipseNode buildField(FieldDeclaration field) { + private EclipseNode buildField(FieldDeclaration field, Annotation[] annotations) { if (field instanceof Initializer) return buildInitializer((Initializer)field); if (setAndGetAsHandled(field)) return null; List childNodes = new ArrayList(); addIfNotNull(childNodes, buildTypeUse(field.type)); addIfNotNull(childNodes, buildStatement(field.initialization)); - childNodes.addAll(buildAnnotations(field.annotations, true)); + childNodes.addAll(buildAnnotations(annotations != null ? annotations : field.annotations, true)); return putInMap(new EclipseNode(this, field, childNodes, Kind.FIELD)); } diff --git a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java index 6bfcf16e..c70e4e5c 100644 --- a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java +++ b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java @@ -124,6 +124,7 @@ import lombok.core.handlers.HandlerUtil.FieldAccess; import lombok.eclipse.Eclipse; import lombok.eclipse.EclipseAST; import lombok.eclipse.EclipseNode; +import lombok.eclipse.Java14Bits; import lombok.experimental.Accessors; import lombok.experimental.Tolerate; import lombok.permit.Permit; @@ -332,6 +333,7 @@ public class EclipseHandlerUtil { public static final Field TYPE_REFERENCE__ANNOTATIONS; public static final Class INTERSECTION_BINDING1, INTERSECTION_BINDING2; public static final Field INTERSECTION_BINDING_TYPES1, INTERSECTION_BINDING_TYPES2; + public static final Field TYPE_DECLARATION_RECORD_COMPONENTS; static { STRING_LITERAL__LINE_NUMBER = getField(StringLiteral.class, "lineNumber"); ANNOTATION__MEMBER_VALUE_PAIR_NAME = getField(Annotation.class, "memberValuePairName"); @@ -340,6 +342,7 @@ public class EclipseHandlerUtil { INTERSECTION_BINDING2 = getClass("org.eclipse.jdt.internal.compiler.lookup.IntersectionCastTypeBinding"); INTERSECTION_BINDING_TYPES1 = INTERSECTION_BINDING1 == null ? null : getField(INTERSECTION_BINDING1, "intersectingTypes"); INTERSECTION_BINDING_TYPES2 = INTERSECTION_BINDING2 == null ? null : getField(INTERSECTION_BINDING2, "intersectingTypes"); + TYPE_DECLARATION_RECORD_COMPONENTS = getField(TypeDeclaration.class, "recordComponents"); } public static int reflectInt(Field f, Object o) { @@ -771,12 +774,10 @@ public class EclipseHandlerUtil { } public static boolean hasNonNullAnnotations(EclipseNode node) { - AbstractVariableDeclaration avd = (AbstractVariableDeclaration) node.get(); - if (avd.annotations == null) return false; - for (Annotation annotation : avd.annotations) { - TypeReference typeRef = annotation.type; - if (typeRef != null && typeRef.getTypeName() != null) { - for (String bn : NONNULL_ANNOTATIONS) if (typeMatches(bn, node, typeRef)) return true; + for (EclipseNode child : node.down()) { + if (child.getKind() == Kind.ANNOTATION) { + Annotation annotation = (Annotation) child.get(); + for (String bn : NONNULL_ANNOTATIONS) if (typeMatches(bn, node, annotation.type)) return true; } } return false; @@ -1887,6 +1888,31 @@ public class EclipseHandlerUtil { return MemberExistsResult.NOT_EXISTS; } + /** + * Checks if there is a constructor generated by lombok. + * + * @param node Any node that represents the Type (TypeDeclaration) to look in, or any child node thereof. + */ + public static boolean lombokConstructorExists(EclipseNode node) { + node = upToTypeNode(node); + if (node != null && node.get() instanceof TypeDeclaration) { + TypeDeclaration typeDecl = (TypeDeclaration)node.get(); + if (typeDecl.methods != null) for (AbstractMethodDeclaration def : typeDecl.methods) { + if (def instanceof ConstructorDeclaration) { + if ((def.bits & (ASTNode.IsDefaultConstructor | Java14Bits.IsCanonicalConstructor)) != 0) continue; + + if (isTolerate(node, def)) continue; + + if (getGeneratedBy(def) != null) { + return true; + } + } + } + } + + return false; + } + /** * Inserts a field into an existing type. The type must represent a {@code TypeDeclaration}. * The field carries the @{@link SuppressWarnings}("all") annotation. @@ -2635,4 +2661,57 @@ public class EclipseHandlerUtil { setGeneratedBy(ref, source); return ref; } + + static boolean isClass(EclipseNode typeNode) { + return isClassAndDoesNotHaveFlags(typeNode, ClassFileConstants.AccInterface | ClassFileConstants.AccEnum | ClassFileConstants.AccAnnotation | Java14Bits.AccRecord); + } + + static boolean isClassOrEnum(EclipseNode typeNode) { + return isClassAndDoesNotHaveFlags(typeNode, ClassFileConstants.AccInterface | ClassFileConstants.AccAnnotation | Java14Bits.AccRecord); + } + + public static boolean isClassAndDoesNotHaveFlags(EclipseNode typeNode, long flags) { + TypeDeclaration typeDecl = null; + if (typeNode.get() instanceof TypeDeclaration) typeDecl = (TypeDeclaration) typeNode.get(); + int modifiers = typeDecl == null ? 0 : typeDecl.modifiers; + return (modifiers & flags) == 0; + } + + public static boolean isRecord(EclipseNode typeNode) { + return typeNode.getKind() == Kind.TYPE && isRecord((TypeDeclaration) typeNode.get()); + } + + public static boolean isRecord(TypeDeclaration typeDeclaration) { + return (typeDeclaration.modifiers & Java14Bits.AccRecord) != 0; + } + + public static boolean isRecordField(EclipseNode fieldNode) { + return fieldNode.getKind() == Kind.FIELD && (((FieldDeclaration) fieldNode.get()).modifiers & Java14Bits.AccRecord) != 0; + } + + public static AbstractVariableDeclaration[] getRecordComponents(TypeDeclaration typeDeclaration) { + if (!isRecord(typeDeclaration)) return null; + try { + return (AbstractVariableDeclaration[]) TYPE_DECLARATION_RECORD_COMPONENTS.get(typeDeclaration); + } catch (Exception e) { + // Ignore + } + return null; + } + + public static Annotation[][] getRecordFieldAnnotations(TypeDeclaration typeDeclaration) { + if (typeDeclaration.fields == null) return null; + Annotation[][] annotations = new Annotation[typeDeclaration.fields.length][]; + + AbstractVariableDeclaration[] recordComponents = getRecordComponents(typeDeclaration); + if (recordComponents != null) { + int j = 0; + for (int i = 0; i < typeDeclaration.fields.length; i++) { + if ((typeDeclaration.fields[i].modifiers & Java14Bits.AccRecord) != 0) { + annotations[i] = recordComponents[j++].annotations; + } + } + } + return annotations; + } } diff --git a/src/core/lombok/eclipse/handlers/HandleBuilder.java b/src/core/lombok/eclipse/handlers/HandleBuilder.java index 801fe7e7..5054703a 100755 --- a/src/core/lombok/eclipse/handlers/HandleBuilder.java +++ b/src/core/lombok/eclipse/handlers/HandleBuilder.java @@ -272,8 +272,10 @@ public class HandleBuilder extends EclipseAnnotationHandler { allFields.add(fieldNode); } - handleConstructor.generateConstructor(tdParent, AccessLevel.PACKAGE, allFields, false, null, SkipIfConstructorExists.I_AM_BUILDER, - Collections.emptyList(), annotationNode); + if (!isRecord(tdParent)) { + handleConstructor.generateConstructor(tdParent, AccessLevel.PACKAGE, allFields, false, null, SkipIfConstructorExists.I_AM_BUILDER, + Collections.emptyList(), annotationNode); + } returnType = namePlusTypeParamsToTypeReference(tdParent, td.typeParameters, p); typeParams = td.typeParameters; diff --git a/src/core/lombok/eclipse/handlers/HandleConstructor.java b/src/core/lombok/eclipse/handlers/HandleConstructor.java index 06c9ecd9..ff81b763 100755 --- a/src/core/lombok/eclipse/handlers/HandleConstructor.java +++ b/src/core/lombok/eclipse/handlers/HandleConstructor.java @@ -194,12 +194,7 @@ public class HandleConstructor { } static boolean checkLegality(EclipseNode typeNode, EclipseNode errorNode, String name) { - TypeDeclaration typeDecl = null; - if (typeNode.get() instanceof TypeDeclaration) typeDecl = (TypeDeclaration) typeNode.get(); - int modifiers = typeDecl == null ? 0 : typeDecl.modifiers; - boolean notAClass = (modifiers & (ClassFileConstants.AccInterface | ClassFileConstants.AccAnnotation)) != 0; - - if (typeDecl == null || notAClass) { + if (!isClassOrEnum(typeNode)) { errorNode.addError(name + " is only supported on a class or an enum."); return false; } diff --git a/src/core/lombok/eclipse/handlers/HandleData.java b/src/core/lombok/eclipse/handlers/HandleData.java index 4011890d..6663d7d0 100644 --- a/src/core/lombok/eclipse/handlers/HandleData.java +++ b/src/core/lombok/eclipse/handlers/HandleData.java @@ -22,6 +22,7 @@ package lombok.eclipse.handlers; import static lombok.core.handlers.HandlerUtil.*; +import static lombok.eclipse.handlers.EclipseHandlerUtil.isClass; import java.util.Collections; @@ -34,8 +35,6 @@ import lombok.eclipse.EclipseNode; import lombok.eclipse.handlers.HandleConstructor.SkipIfConstructorExists; import org.eclipse.jdt.internal.compiler.ast.Annotation; -import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; -import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.mangosdk.spi.ProviderFor; /** @@ -55,13 +54,7 @@ public class HandleData extends EclipseAnnotationHandler { Data ann = annotation.getInstance(); EclipseNode typeNode = annotationNode.up(); - TypeDeclaration typeDecl = null; - if (typeNode.get() instanceof TypeDeclaration) typeDecl = (TypeDeclaration) typeNode.get(); - int modifiers = typeDecl == null ? 0 : typeDecl.modifiers; - boolean notAClass = (modifiers & - (ClassFileConstants.AccInterface | ClassFileConstants.AccAnnotation | ClassFileConstants.AccEnum)) != 0; - - if (typeDecl == null || notAClass) { + if (!isClass(typeNode)) { annotationNode.addError("@Data is only supported on a class."); return; } diff --git a/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java b/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java index 7147343e..83e6de61 100755 --- a/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java +++ b/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java @@ -137,13 +137,9 @@ public class HandleEqualsAndHashCode extends EclipseAnnotationHandler onParam) { TypeDeclaration typeDecl = null; - if (typeNode.get() instanceof TypeDeclaration) typeDecl = (TypeDeclaration) typeNode.get(); - int modifiers = typeDecl == null ? 0 : typeDecl.modifiers; - boolean notAClass = (modifiers & - (ClassFileConstants.AccInterface | ClassFileConstants.AccAnnotation | ClassFileConstants.AccEnum)) != 0; - if (typeDecl == null || notAClass) { + if (!isClass(typeNode)) { errorNode.addError("@EqualsAndHashCode is only supported on a class."); return; } diff --git a/src/core/lombok/eclipse/handlers/HandleFieldDefaults.java b/src/core/lombok/eclipse/handlers/HandleFieldDefaults.java index 702713fe..4927a8fb 100644 --- a/src/core/lombok/eclipse/handlers/HandleFieldDefaults.java +++ b/src/core/lombok/eclipse/handlers/HandleFieldDefaults.java @@ -63,13 +63,7 @@ public class HandleFieldDefaults extends EclipseASTAdapter { } } - TypeDeclaration typeDecl = null; - if (typeNode.get() instanceof TypeDeclaration) typeDecl = (TypeDeclaration) typeNode.get(); - int modifiers = typeDecl == null ? 0 : typeDecl.modifiers; - boolean notAClass = (modifiers & - (ClassFileConstants.AccInterface | ClassFileConstants.AccAnnotation)) != 0; - - if (typeDecl == null || notAClass) { + if (!isClassOrEnum(typeNode)) { pos.addError("@FieldDefaults is only supported on a class or an enum."); return false; } diff --git a/src/core/lombok/eclipse/handlers/HandleGetter.java b/src/core/lombok/eclipse/handlers/HandleGetter.java index 9cd1e2a1..755311b1 100644 --- a/src/core/lombok/eclipse/handlers/HandleGetter.java +++ b/src/core/lombok/eclipse/handlers/HandleGetter.java @@ -90,13 +90,7 @@ public class HandleGetter extends EclipseAnnotationHandler { } } - TypeDeclaration typeDecl = null; - if (typeNode.get() instanceof TypeDeclaration) typeDecl = (TypeDeclaration) typeNode.get(); - int modifiers = typeDecl == null ? 0 : typeDecl.modifiers; - boolean notAClass = (modifiers & - (ClassFileConstants.AccInterface | ClassFileConstants.AccAnnotation)) != 0; - - if (typeDecl == null || notAClass) { + if (!isClassOrEnum(typeNode)) { pos.addError("@Getter is only supported on a class, an enum, or a field."); return false; } diff --git a/src/core/lombok/eclipse/handlers/HandleLog.java b/src/core/lombok/eclipse/handlers/HandleLog.java index a0e431e5..9eae601b 100644 --- a/src/core/lombok/eclipse/handlers/HandleLog.java +++ b/src/core/lombok/eclipse/handlers/HandleLog.java @@ -85,6 +85,10 @@ public class HandleLog { annotationNode.addWarning("Field '" + logFieldName + "' already exists."); return; } + if (isRecord(owner) && !useStatic) { + annotationNode.addError("Logger fields must be static in records."); + return; + } Object valueGuess = annotation.getValueGuess("topic"); Expression loggerTopic = (Expression) annotation.getActualExpression("topic"); diff --git a/src/core/lombok/eclipse/handlers/HandleNonNull.java b/src/core/lombok/eclipse/handlers/HandleNonNull.java index 903d098b..8dc4f4f7 100644 --- a/src/core/lombok/eclipse/handlers/HandleNonNull.java +++ b/src/core/lombok/eclipse/handlers/HandleNonNull.java @@ -26,6 +26,7 @@ import static lombok.eclipse.Eclipse.isPrimitive; import static lombok.eclipse.handlers.EclipseHandlerUtil.*; import java.util.Arrays; +import java.util.Collections; import org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; @@ -48,17 +49,18 @@ import org.eclipse.jdt.internal.compiler.ast.TryStatement; import org.eclipse.jdt.internal.compiler.ast.TypeReference; import org.mangosdk.spi.ProviderFor; +import lombok.AccessLevel; import lombok.ConfigurationKeys; import lombok.NonNull; import lombok.core.AST.Kind; import lombok.core.AnnotationValues; import lombok.core.HandlerPriority; -import lombok.eclipse.DeferUntilPostDiet; import lombok.eclipse.EclipseAST; import lombok.eclipse.EclipseAnnotationHandler; +import lombok.eclipse.EclipseAugments; import lombok.eclipse.EclipseNode; +import lombok.eclipse.handlers.HandleConstructor.SkipIfConstructorExists; -@DeferUntilPostDiet @ProviderFor(EclipseAnnotationHandler.class) @HandlerPriority(value = 512) // 2^9; onParameter=@__(@NonNull) has to run first. public class HandleNonNull extends EclipseAnnotationHandler { @@ -66,6 +68,7 @@ public class HandleNonNull extends EclipseAnnotationHandler { private static final char[] CHECK_NOT_NULL = "checkNotNull".toCharArray(); public static final HandleNonNull INSTANCE = new HandleNonNull(); + private HandleConstructor handleConstructor = new HandleConstructor(); public void fix(EclipseNode method) { for (EclipseNode m : method.down()) { @@ -81,6 +84,17 @@ public class HandleNonNull extends EclipseAnnotationHandler { } @Override public void handle(AnnotationValues annotation, Annotation ast, EclipseNode annotationNode) { + // Generating new methods is only possible during diet parse but modifying existing methods requires a full parse. + // As we need both for @NonNull we reset the handled flag during diet parse. + if (!annotationNode.isCompleteParse()) { + EclipseNode typeNode = upToTypeNode(annotationNode); + if (isRecordField(annotationNode.up()) && !lombokConstructorExists(typeNode)) { + handleConstructor.generateAllArgsConstructor(typeNode, AccessLevel.PUBLIC, null, SkipIfConstructorExists.NO, Collections.emptyList(), annotationNode); + } + EclipseAugments.ASTNode_handled.clear(ast); + return; + } + handle0(ast, annotationNode, false); } diff --git a/src/core/lombok/eclipse/handlers/HandleSetter.java b/src/core/lombok/eclipse/handlers/HandleSetter.java index cb2ca3bf..9ebbde6d 100644 --- a/src/core/lombok/eclipse/handlers/HandleSetter.java +++ b/src/core/lombok/eclipse/handlers/HandleSetter.java @@ -71,13 +71,7 @@ public class HandleSetter extends EclipseAnnotationHandler { } } - TypeDeclaration typeDecl = null; - if (typeNode.get() instanceof TypeDeclaration) typeDecl = (TypeDeclaration) typeNode.get(); - int modifiers = typeDecl == null ? 0 : typeDecl.modifiers; - boolean notAClass = (modifiers & - (ClassFileConstants.AccInterface | ClassFileConstants.AccAnnotation | ClassFileConstants.AccEnum)) != 0; - - if (typeDecl == null || notAClass) { + if (!isClass(typeNode)) { pos.addError("@Setter is only supported on a class or a field."); return false; } diff --git a/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java b/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java index b1e7c419..89c27fe3 100644 --- a/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java +++ b/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java @@ -156,7 +156,7 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler { boolean addCleaning = false; - if (!(tdParent.get() instanceof TypeDeclaration)) { + if (!isClass(tdParent)) { annotationNode.addError("@SuperBuilder is only supported on types."); return; } diff --git a/src/core/lombok/eclipse/handlers/HandleSynchronized.java b/src/core/lombok/eclipse/handlers/HandleSynchronized.java index 08d00d91..37d6755c 100644 --- a/src/core/lombok/eclipse/handlers/HandleSynchronized.java +++ b/src/core/lombok/eclipse/handlers/HandleSynchronized.java @@ -148,6 +148,12 @@ public class HandleSynchronized extends EclipseAnnotationHandler { return; } + EclipseNode typeNode = upToTypeNode(annotationNode); + if (!isClassOrEnum(typeNode)) { + annotationNode.addError("@Synchronized is legal only on methods in classes and enums."); + return; + } + boolean[] isStatic = { method.isStatic() }; char[] lockName = createLockField(annotation, annotationNode, isStatic, true); if (lockName == null) return; @@ -163,7 +169,6 @@ public class HandleSynchronized extends EclipseAnnotationHandler { Expression lockVariable; if (isStatic[0]) { - EclipseNode typeNode = upToTypeNode(annotationNode); char[][] n = getQualifiedInnerName(typeNode, lockName); long[] ps = new long[n.length]; Arrays.fill(ps, pos); diff --git a/src/core/lombok/eclipse/handlers/HandleToString.java b/src/core/lombok/eclipse/handlers/HandleToString.java index a6bcb24f..9b58474c 100644 --- a/src/core/lombok/eclipse/handlers/HandleToString.java +++ b/src/core/lombok/eclipse/handlers/HandleToString.java @@ -50,7 +50,6 @@ import org.eclipse.jdt.internal.compiler.ast.SuperReference; import org.eclipse.jdt.internal.compiler.ast.ThisReference; import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; import org.eclipse.jdt.internal.compiler.ast.TypeReference; -import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; import org.mangosdk.spi.ProviderFor; @@ -116,14 +115,7 @@ public class HandleToString extends EclipseAnnotationHandler { public void generateToString(EclipseNode typeNode, EclipseNode errorNode, List> members, boolean includeFieldNames, Boolean callSuper, boolean whineIfExists, FieldAccess fieldAccess) { - TypeDeclaration typeDecl = null; - - if (typeNode.get() instanceof TypeDeclaration) typeDecl = (TypeDeclaration) typeNode.get(); - int modifiers = typeDecl == null ? 0 : typeDecl.modifiers; - boolean notAClass = (modifiers & - (ClassFileConstants.AccInterface | ClassFileConstants.AccAnnotation)) != 0; - - if (typeDecl == null || notAClass) { + if (!isClassOrEnum(typeNode)) { errorNode.addError("@ToString is only supported on a class or enum."); return; } diff --git a/src/core/lombok/eclipse/handlers/HandleUtilityClass.java b/src/core/lombok/eclipse/handlers/HandleUtilityClass.java index 2349f839..338aab0d 100644 --- a/src/core/lombok/eclipse/handlers/HandleUtilityClass.java +++ b/src/core/lombok/eclipse/handlers/HandleUtilityClass.java @@ -70,13 +70,8 @@ public class HandleUtilityClass extends EclipseAnnotationHandler { } private static boolean checkLegality(EclipseNode typeNode, EclipseNode errorNode) { - TypeDeclaration typeDecl = null; - if (typeNode.get() instanceof TypeDeclaration) typeDecl = (TypeDeclaration) typeNode.get(); - int modifiers = typeDecl == null ? 0 : typeDecl.modifiers; - boolean notAClass = (modifiers & (ClassFileConstants.AccInterface | ClassFileConstants.AccAnnotation | ClassFileConstants.AccEnum)) != 0; - - if (typeDecl == null || notAClass) { - errorNode.addError("@UtilityClass is only supported on a class (can't be an interface, enum, or annotation)."); + if (!isClass(typeNode)) { + errorNode.addError("@UtilityClass is only supported on a class (can't be an interface, enum, annotation, or record)."); return false; } diff --git a/src/core/lombok/eclipse/handlers/HandleValue.java b/src/core/lombok/eclipse/handlers/HandleValue.java index 2e0338a8..abea5603 100644 --- a/src/core/lombok/eclipse/handlers/HandleValue.java +++ b/src/core/lombok/eclipse/handlers/HandleValue.java @@ -61,11 +61,8 @@ public class HandleValue extends EclipseAnnotationHandler { TypeDeclaration typeDecl = null; if (typeNode.get() instanceof TypeDeclaration) typeDecl = (TypeDeclaration) typeNode.get(); - int modifiers = typeDecl == null ? 0 : typeDecl.modifiers; - boolean notAClass = (modifiers & - (ClassFileConstants.AccInterface | ClassFileConstants.AccAnnotation | ClassFileConstants.AccEnum)) != 0; - if (typeDecl == null || notAClass) { + if (!isClass(typeNode)) { annotationNode.addError("@Value is only supported on a class."); return; } diff --git a/src/core/lombok/eclipse/handlers/HandleWithBy.java b/src/core/lombok/eclipse/handlers/HandleWithBy.java index 5f229aaf..40e2d524 100644 --- a/src/core/lombok/eclipse/handlers/HandleWithBy.java +++ b/src/core/lombok/eclipse/handlers/HandleWithBy.java @@ -29,7 +29,9 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.LinkedHashSet; import java.util.List; +import java.util.Set; import org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.eclipse.jdt.internal.compiler.ast.AllocationExpression; @@ -136,7 +138,10 @@ public class HandleWithBy extends EclipseAnnotationHandler { switch (node.getKind()) { case FIELD: - createWithByForFields(level, annotationNode.upFromAnnotationToFields(), annotationNode, true, onMethod); + Set fields = new LinkedHashSet(); + fields.add(node); + fields.addAll(annotationNode.upFromAnnotationToFields()); + createWithByForFields(level, fields, annotationNode, true, onMethod); break; case TYPE: if (!onMethod.isEmpty()) { diff --git a/src/core/lombok/javac/handlers/HandleBuilder.java b/src/core/lombok/javac/handlers/HandleBuilder.java index 7e87ce11..f9675813 100644 --- a/src/core/lombok/javac/handlers/HandleBuilder.java +++ b/src/core/lombok/javac/handlers/HandleBuilder.java @@ -223,7 +223,9 @@ public class HandleBuilder extends JavacAnnotationHandler { allFields.append(fieldNode); } - handleConstructor.generateConstructor(tdParent, AccessLevel.PACKAGE, List.nil(), allFields.toList(), false, null, SkipIfConstructorExists.I_AM_BUILDER, annotationNode); + if (!isRecord(tdParent)) { + handleConstructor.generateConstructor(tdParent, AccessLevel.PACKAGE, List.nil(), allFields.toList(), false, null, SkipIfConstructorExists.I_AM_BUILDER, annotationNode); + } returnType = namePlusTypeParamsToTypeReference(tdParent.getTreeMaker(), tdParent, td.typarams); typeParams = td.typarams; diff --git a/src/core/lombok/javac/handlers/HandleConstructor.java b/src/core/lombok/javac/handlers/HandleConstructor.java index 2a683767..54a9f821 100644 --- a/src/core/lombok/javac/handlers/HandleConstructor.java +++ b/src/core/lombok/javac/handlers/HandleConstructor.java @@ -184,12 +184,7 @@ public class HandleConstructor { } public static boolean checkLegality(JavacNode typeNode, JavacNode errorNode, String name) { - JCClassDecl typeDecl = null; - if (typeNode.get() instanceof JCClassDecl) typeDecl = (JCClassDecl) typeNode.get(); - long modifiers = typeDecl == null ? 0 : typeDecl.mods.flags; - boolean notAClass = (modifiers & (Flags.INTERFACE | Flags.ANNOTATION)) != 0; - - if (typeDecl == null || notAClass) { + if (!isClassOrEnum(typeNode)) { errorNode.addError(name + " is only supported on a class or an enum."); return false; } diff --git a/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java b/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java index d490738e..e35deb5b 100644 --- a/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java +++ b/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java @@ -113,13 +113,7 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler> members, Boolean callSuper, boolean whineIfExists, FieldAccess fieldAccess, List onParam) { - boolean notAClass = true; - if (typeNode.get() instanceof JCClassDecl) { - long flags = ((JCClassDecl) typeNode.get()).mods.flags; - notAClass = (flags & (Flags.INTERFACE | Flags.ANNOTATION | Flags.ENUM)) != 0; - } - - if (notAClass) { + if (!isClass(typeNode)) { source.addError("@EqualsAndHashCode is only supported on a class."); return; } diff --git a/src/core/lombok/javac/handlers/HandleFieldDefaults.java b/src/core/lombok/javac/handlers/HandleFieldDefaults.java index aa381c0d..c974bdb9 100644 --- a/src/core/lombok/javac/handlers/HandleFieldDefaults.java +++ b/src/core/lombok/javac/handlers/HandleFieldDefaults.java @@ -57,12 +57,7 @@ public class HandleFieldDefaults extends JavacASTAdapter { } } - JCClassDecl typeDecl = null; - if (typeNode.get() instanceof JCClassDecl) typeDecl = (JCClassDecl) typeNode.get(); - long modifiers = typeDecl == null ? 0 : typeDecl.mods.flags; - boolean notAClass = (modifiers & (Flags.INTERFACE | Flags.ANNOTATION)) != 0; - - if (typeDecl == null || notAClass) { + if (!isClassOrEnum(typeNode)) { errorNode.addError("@FieldDefaults is only supported on a class or an enum."); return false; } diff --git a/src/core/lombok/javac/handlers/HandleGetter.java b/src/core/lombok/javac/handlers/HandleGetter.java index 110941d6..1b4d404b 100644 --- a/src/core/lombok/javac/handlers/HandleGetter.java +++ b/src/core/lombok/javac/handlers/HandleGetter.java @@ -52,7 +52,6 @@ import com.sun.tools.javac.tree.JCTree; import com.sun.tools.javac.tree.JCTree.JCAnnotation; import com.sun.tools.javac.tree.JCTree.JCBinary; import com.sun.tools.javac.tree.JCTree.JCBlock; -import com.sun.tools.javac.tree.JCTree.JCClassDecl; import com.sun.tools.javac.tree.JCTree.JCExpression; import com.sun.tools.javac.tree.JCTree.JCExpressionStatement; import com.sun.tools.javac.tree.JCTree.JCIf; @@ -81,12 +80,7 @@ public class HandleGetter extends JavacAnnotationHandler { } } - JCClassDecl typeDecl = null; - if (typeNode.get() instanceof JCClassDecl) typeDecl = (JCClassDecl) typeNode.get(); - long modifiers = typeDecl == null ? 0 : typeDecl.mods.flags; - boolean notAClass = (modifiers & (Flags.INTERFACE | Flags.ANNOTATION)) != 0; - - if (typeDecl == null || notAClass) { + if (!isClassOrEnum(typeNode)) { errorNode.addError("@Getter is only supported on a class, an enum, or a field."); return; } diff --git a/src/core/lombok/javac/handlers/HandleLog.java b/src/core/lombok/javac/handlers/HandleLog.java index 3173b3ba..1ff10ad1 100644 --- a/src/core/lombok/javac/handlers/HandleLog.java +++ b/src/core/lombok/javac/handlers/HandleLog.java @@ -75,6 +75,10 @@ public class HandleLog { annotationNode.addWarning("Field '" + logFieldName + "' already exists."); return; } + if (isRecord(typeNode) && !useStatic) { + annotationNode.addError("Logger fields must be static in records."); + return; + } Object valueGuess = annotation.getValueGuess("topic"); JCExpression loggerTopic = (JCExpression) annotation.getActualExpression("topic"); @@ -120,10 +124,15 @@ public class HandleLog { maker.Modifiers(Flags.PRIVATE | Flags.FINAL | (useStatic ? Flags.STATIC : 0)), typeNode.toName(logFieldName), loggerType, factoryMethodCall), source, typeNode.getContext()); - injectFieldAndMarkGenerated(typeNode, fieldDecl); + // This is a workaround for https://bugs.openjdk.java.net/browse/JDK-8243057 + if (isRecord(typeNode)) { + injectField(typeNode, fieldDecl); + } else { + injectFieldAndMarkGenerated(typeNode, fieldDecl); + } return true; } - + private static JCExpression[] createFactoryParameters(JavacNode typeNode, JCFieldAccess loggingType, java.util.List parameters, JCExpression loggerTopic) { JCExpression[] expressions = new JCExpression[parameters.size()]; JavacTreeMaker maker = typeNode.getTreeMaker(); diff --git a/src/core/lombok/javac/handlers/HandleNonNull.java b/src/core/lombok/javac/handlers/HandleNonNull.java index 079d5b04..6b6b7efa 100644 --- a/src/core/lombok/javac/handlers/HandleNonNull.java +++ b/src/core/lombok/javac/handlers/HandleNonNull.java @@ -51,17 +51,23 @@ import com.sun.tools.javac.tree.JCTree.JCVariableDecl; import com.sun.tools.javac.util.List; import com.sun.tools.javac.util.Name; +import lombok.AccessLevel; import lombok.ConfigurationKeys; import lombok.NonNull; import lombok.core.AST.Kind; import lombok.core.AnnotationValues; import lombok.core.HandlerPriority; + +import lombok.javac.Java14Flags; import lombok.javac.JavacAnnotationHandler; import lombok.javac.JavacNode; +import lombok.javac.handlers.HandleConstructor.SkipIfConstructorExists; @ProviderFor(JavacAnnotationHandler.class) @HandlerPriority(value = 512) // 2^9; onParameter=@__(@NonNull) has to run first. public class HandleNonNull extends JavacAnnotationHandler { + private HandleConstructor handleConstructor = new HandleConstructor(); + @Override public void handle(AnnotationValues annotation, JCAnnotation ast, JavacNode annotationNode) { handleFlagUsage(annotationNode, ConfigurationKeys.NON_NULL_FLAG_USAGE, "@NonNull"); @@ -119,6 +125,15 @@ public class HandleNonNull extends JavacAnnotationHandler { return; } + JavacNode typeNode = upToTypeNode(annotationNode); + + if ((declaration.mods.flags & Java14Flags.RECORD) != 0) { + if (!lombokConstructorExists(typeNode)) { + handleConstructor.generateAllArgsConstructor(typeNode, AccessLevel.PUBLIC, null, SkipIfConstructorExists.NO, annotationNode); + } + return; + } + List statements = declaration.body.stats; String expectedName = paramNode.getName(); diff --git a/src/core/lombok/javac/handlers/HandleSetter.java b/src/core/lombok/javac/handlers/HandleSetter.java index 82c95719..b51574b7 100644 --- a/src/core/lombok/javac/handlers/HandleSetter.java +++ b/src/core/lombok/javac/handlers/HandleSetter.java @@ -70,12 +70,7 @@ public class HandleSetter extends JavacAnnotationHandler { } } - JCClassDecl typeDecl = null; - if (typeNode.get() instanceof JCClassDecl) typeDecl = (JCClassDecl) typeNode.get(); - long modifiers = typeDecl == null ? 0 : typeDecl.mods.flags; - boolean notAClass = (modifiers & (Flags.INTERFACE | Flags.ANNOTATION | Flags.ENUM)) != 0; - - if (typeDecl == null || notAClass) { + if (!isClass(typeNode)) { errorNode.addError("@Setter is only supported on a class or a field."); return; } diff --git a/src/core/lombok/javac/handlers/HandleSuperBuilder.java b/src/core/lombok/javac/handlers/HandleSuperBuilder.java index f6bf9e1f..be6ddae2 100644 --- a/src/core/lombok/javac/handlers/HandleSuperBuilder.java +++ b/src/core/lombok/javac/handlers/HandleSuperBuilder.java @@ -128,7 +128,7 @@ public class HandleSuperBuilder extends JavacAnnotationHandler { boolean addCleaning = false; - if (!(tdParent.get() instanceof JCClassDecl)) { + if (!isClass(tdParent)) { annotationNode.addError("@SuperBuilder is only supported on types."); return; } diff --git a/src/core/lombok/javac/handlers/HandleSynchronized.java b/src/core/lombok/javac/handlers/HandleSynchronized.java index b6f1e47f..85dc7e80 100644 --- a/src/core/lombok/javac/handlers/HandleSynchronized.java +++ b/src/core/lombok/javac/handlers/HandleSynchronized.java @@ -78,6 +78,12 @@ public class HandleSynchronized extends JavacAnnotationHandler { return; } + JavacNode typeNode = upToTypeNode(annotationNode); + if (!isClassOrEnum(typeNode)) { + annotationNode.addError("@Synchronized is legal only on methods in classes and enums."); + return; + } + boolean[] isStatic = new boolean[] {(method.mods.flags & Flags.STATIC) != 0}; String lockName = annotation.getInstance().value(); boolean autoMake = false; @@ -89,8 +95,6 @@ public class HandleSynchronized extends JavacAnnotationHandler { JavacTreeMaker maker = methodNode.getTreeMaker().at(ast.pos); Context context = methodNode.getContext(); - JavacNode typeNode = upToTypeNode(annotationNode); - MemberExistsResult exists = MemberExistsResult.NOT_EXISTS; if (typeNode != null && typeNode.get() instanceof JCClassDecl) { diff --git a/src/core/lombok/javac/handlers/HandleToString.java b/src/core/lombok/javac/handlers/HandleToString.java index 0a950f7c..ff0016e4 100644 --- a/src/core/lombok/javac/handlers/HandleToString.java +++ b/src/core/lombok/javac/handlers/HandleToString.java @@ -107,13 +107,7 @@ public class HandleToString extends JavacAnnotationHandler { public void generateToString(JavacNode typeNode, JavacNode source, java.util.List> members, boolean includeFieldNames, Boolean callSuper, boolean whineIfExists, FieldAccess fieldAccess) { - boolean notAClass = true; - if (typeNode.get() instanceof JCClassDecl) { - long flags = ((JCClassDecl) typeNode.get()).mods.flags; - notAClass = (flags & (Flags.INTERFACE | Flags.ANNOTATION)) != 0; - } - - if (notAClass) { + if (!isClassOrEnum(typeNode)) { source.addError("@ToString is only supported on a class or enum."); return; } diff --git a/src/core/lombok/javac/handlers/HandleUtilityClass.java b/src/core/lombok/javac/handlers/HandleUtilityClass.java index 5d651689..9ff33684 100644 --- a/src/core/lombok/javac/handlers/HandleUtilityClass.java +++ b/src/core/lombok/javac/handlers/HandleUtilityClass.java @@ -68,13 +68,8 @@ public class HandleUtilityClass extends JavacAnnotationHandler { } private static boolean checkLegality(JavacNode typeNode, JavacNode errorNode) { - JCClassDecl typeDecl = null; - if (typeNode.get() instanceof JCClassDecl) typeDecl = (JCClassDecl) typeNode.get(); - long modifiers = typeDecl == null ? 0 : typeDecl.mods.flags; - boolean notAClass = (modifiers & (Flags.INTERFACE | Flags.ANNOTATION | Flags.ENUM)) != 0; - - if (typeDecl == null || notAClass) { - errorNode.addError("@UtilityClass is only supported on a class (can't be an interface, enum, or annotation)."); + if (!isClass(typeNode)) { + errorNode.addError("@UtilityClass is only supported on a class (can't be an interface, enum, annotation, or record)."); return false; } diff --git a/src/core/lombok/javac/handlers/JavacHandlerUtil.java b/src/core/lombok/javac/handlers/JavacHandlerUtil.java index efc4bf61..cd4bc70a 100644 --- a/src/core/lombok/javac/handlers/JavacHandlerUtil.java +++ b/src/core/lombok/javac/handlers/JavacHandlerUtil.java @@ -103,6 +103,7 @@ import lombok.core.handlers.HandlerUtil.FieldAccess; import lombok.delombok.LombokOptionsFactory; import lombok.experimental.Accessors; import lombok.experimental.Tolerate; +import lombok.javac.Java14Flags; import lombok.javac.Javac; import lombok.javac.JavacNode; import lombok.javac.JavacTreeMaker; @@ -814,6 +815,32 @@ public class JavacHandlerUtil { return MemberExistsResult.NOT_EXISTS; } + /** + * Checks if there is a constructor generated by lombok. + * + * @param node Any node that represents the Type (JCClassDecl) to look in, or any child node thereof. + */ + public static boolean lombokConstructorExists(JavacNode node) { + node = upToTypeNode(node); + + if (node != null && node.get() instanceof JCClassDecl) { + for (JCTree def : ((JCClassDecl)node.get()).defs) { + if (def instanceof JCMethodDecl) { + JCMethodDecl md = (JCMethodDecl) def; + if (md.name.contentEquals("")) { + if ((md.mods.flags & Flags.GENERATEDCONSTR) != 0) continue; + if (isTolerate(node, md)) continue; + if (getGeneratedBy(def) != null) { + return true; + } + } + } + } + } + + return false; + } + public static boolean isConstructorCall(final JCStatement statement) { if (!(statement instanceof JCExpressionStatement)) return false; JCExpression expr = ((JCExpressionStatement) statement).expr; @@ -1900,14 +1927,14 @@ public class JavacHandlerUtil { } static boolean isClass(JavacNode typeNode) { - return isClassAndDoesNotHaveFlags(typeNode, Flags.INTERFACE | Flags.ENUM | Flags.ANNOTATION); + return isClassAndDoesNotHaveFlags(typeNode, Flags.INTERFACE | Flags.ENUM | Flags.ANNOTATION | Java14Flags.RECORD); } static boolean isClassOrEnum(JavacNode typeNode) { - return isClassAndDoesNotHaveFlags(typeNode, Flags.INTERFACE | Flags.ANNOTATION); + return isClassAndDoesNotHaveFlags(typeNode, Flags.INTERFACE | Flags.ANNOTATION | Java14Flags.RECORD); } - public static boolean isClassAndDoesNotHaveFlags(JavacNode typeNode, int flags) { + public static boolean isClassAndDoesNotHaveFlags(JavacNode typeNode, long flags) { JCClassDecl typeDecl = null; if (typeNode.get() instanceof JCClassDecl) typeDecl = (JCClassDecl)typeNode.get(); else return false; @@ -2260,4 +2287,8 @@ public class JavacHandlerUtil { arg.mods.annotations = arg.mods.annotations == null ? List.of(m) : arg.mods.annotations.prepend(m); } } + + public static boolean isRecord(JavacNode typeNode) { + return typeNode.getKind() == Kind.TYPE && (((JCClassDecl) typeNode.get()).mods.flags & Java14Flags.RECORD) != 0; + } } -- cgit From fa0b5249cf5fee28d9be13ecdf0225f651f686aa Mon Sep 17 00:00:00 2001 From: Rawi01 Date: Sat, 12 Sep 2020 14:35:40 +0200 Subject: Support With(By) on records and record components This also replaces the javac/eclipse specific code for searching the parent fields of an annotation by a search based on the lombok AST. --- src/core/lombok/core/LombokNode.java | 10 ++++------ src/core/lombok/eclipse/EclipseNode.java | 10 ---------- src/core/lombok/eclipse/handlers/HandleWithBy.java | 7 +------ src/core/lombok/javac/JavacNode.java | 10 ---------- test/transform/resource/after-delombok/WithByOnRecord.java | 5 +++++ .../resource/after-delombok/WithByOnRecordComponent.java | 6 ++++++ .../resource/after-delombok/WithOnRecordComponent.java | 6 ++++++ test/transform/resource/after-ecj/WithByOnRecord.java | 7 +++++-- .../resource/after-ecj/WithByOnRecordComponent.java | 13 +++++++++++++ .../transform/resource/after-ecj/WithOnRecordComponent.java | 13 +++++++++++++ test/transform/resource/before/WithByOnRecord.java | 3 ++- test/transform/resource/before/WithByOnRecordComponent.java | 6 ++++++ test/transform/resource/before/WithOnRecordComponent.java | 6 ++++++ 13 files changed, 67 insertions(+), 35 deletions(-) create mode 100644 test/transform/resource/after-delombok/WithByOnRecordComponent.java create mode 100644 test/transform/resource/after-delombok/WithOnRecordComponent.java create mode 100644 test/transform/resource/after-ecj/WithByOnRecordComponent.java create mode 100644 test/transform/resource/after-ecj/WithOnRecordComponent.java create mode 100644 test/transform/resource/before/WithByOnRecordComponent.java create mode 100644 test/transform/resource/before/WithOnRecordComponent.java (limited to 'src/core') diff --git a/src/core/lombok/core/LombokNode.java b/src/core/lombok/core/LombokNode.java index abfc66a6..34273a86 100644 --- a/src/core/lombok/core/LombokNode.java +++ b/src/core/lombok/core/LombokNode.java @@ -160,17 +160,15 @@ public abstract class LombokNode, L extends LombokNode fields = new ArrayList(); for (L potentialField : type.down()) { if (potentialField.getKind() != Kind.FIELD) continue; - if (fieldContainsAnnotation(potentialField.get(), get())) fields.add(potentialField); + for (L child : potentialField.down()) { + if (child.getKind() != Kind.ANNOTATION) continue; + if (child.get() == get()) fields.add(potentialField); + } } return fields; } - /** - * Return {@code true} if the annotation is attached to the field. - */ - protected abstract boolean fieldContainsAnnotation(N field, N annotation); - /** * Returns the direct parent node in the AST tree of this node. For example, a local variable declaration's * direct parent can be e.g. an If block, but its {@code up()} {@code LombokNode} is the {@code Method} that contains it. diff --git a/src/core/lombok/eclipse/EclipseNode.java b/src/core/lombok/eclipse/EclipseNode.java index 12e9ccdb..361a8d42 100644 --- a/src/core/lombok/eclipse/EclipseNode.java +++ b/src/core/lombok/eclipse/EclipseNode.java @@ -143,16 +143,6 @@ public class EclipseNode extends lombok.core.LombokNode { switch (node.getKind()) { case FIELD: - Set fields = new LinkedHashSet(); - fields.add(node); - fields.addAll(annotationNode.upFromAnnotationToFields()); - createWithByForFields(level, fields, annotationNode, true, onMethod); + createWithByForFields(level, annotationNode.upFromAnnotationToFields(), annotationNode, true, onMethod); break; case TYPE: if (!onMethod.isEmpty()) { diff --git a/src/core/lombok/javac/JavacNode.java b/src/core/lombok/javac/JavacNode.java index 3de3f38b..e648cd51 100644 --- a/src/core/lombok/javac/JavacNode.java +++ b/src/core/lombok/javac/JavacNode.java @@ -186,16 +186,6 @@ public class JavacNode extends lombok.core.LombokNode transformer) { return new WithByOnRecord(transformer.apply(this.a), this.b); } + + @java.lang.SuppressWarnings("all") + public WithByOnRecord withBBy(final java.util.function.Function transformer) { + return new WithByOnRecord(this.a, transformer.apply(this.b)); + } } diff --git a/test/transform/resource/after-delombok/WithByOnRecordComponent.java b/test/transform/resource/after-delombok/WithByOnRecordComponent.java new file mode 100644 index 00000000..5af50625 --- /dev/null +++ b/test/transform/resource/after-delombok/WithByOnRecordComponent.java @@ -0,0 +1,6 @@ +record WithByOnRecordComponent(String a, String b) { + @java.lang.SuppressWarnings("all") + public WithByOnRecordComponent withABy(final java.util.function.Function transformer) { + return new WithByOnRecordComponent(transformer.apply(this.a), this.b); + } +} diff --git a/test/transform/resource/after-delombok/WithOnRecordComponent.java b/test/transform/resource/after-delombok/WithOnRecordComponent.java new file mode 100644 index 00000000..a5f4ec36 --- /dev/null +++ b/test/transform/resource/after-delombok/WithOnRecordComponent.java @@ -0,0 +1,6 @@ +record WithOnRecordComponent(String a, String b) { + @java.lang.SuppressWarnings("all") + public WithOnRecordComponent withA(final String a) { + return this.a == a ? this : new WithOnRecordComponent(a, this.b); + } +} diff --git a/test/transform/resource/after-ecj/WithByOnRecord.java b/test/transform/resource/after-ecj/WithByOnRecord.java index 9048c9f4..c40841c8 100644 --- a/test/transform/resource/after-ecj/WithByOnRecord.java +++ b/test/transform/resource/after-ecj/WithByOnRecord.java @@ -1,8 +1,8 @@ import lombok.experimental.WithBy; -record WithByOnRecord(String a, String b) { +@WithBy record WithByOnRecord(String a, String b) { /* Implicit */ private final String a; /* Implicit */ private final String b; - public WithByOnRecord( String a, String b) { + public WithByOnRecord(String a, String b) { super(); .a = a; .b = b; @@ -10,4 +10,7 @@ record WithByOnRecord(String a, String b) { public @java.lang.SuppressWarnings("all") WithByOnRecord withABy(final java.util.function.Function transformer) { return new WithByOnRecord(transformer.apply(this.a), this.b); } + public @java.lang.SuppressWarnings("all") WithByOnRecord withBBy(final java.util.function.Function transformer) { + return new WithByOnRecord(this.a, transformer.apply(this.b)); + } } diff --git a/test/transform/resource/after-ecj/WithByOnRecordComponent.java b/test/transform/resource/after-ecj/WithByOnRecordComponent.java new file mode 100644 index 00000000..19fe508c --- /dev/null +++ b/test/transform/resource/after-ecj/WithByOnRecordComponent.java @@ -0,0 +1,13 @@ +import lombok.experimental.WithBy; +record WithByOnRecordComponent(String a, String b) { +/* Implicit */ private final String a; +/* Implicit */ private final String b; + public WithByOnRecordComponent( String a, String b) { + super(); + .a = a; + .b = b; + } + public @java.lang.SuppressWarnings("all") WithByOnRecordComponent withABy(final java.util.function.Function transformer) { + return new WithByOnRecordComponent(transformer.apply(this.a), this.b); + } +} diff --git a/test/transform/resource/after-ecj/WithOnRecordComponent.java b/test/transform/resource/after-ecj/WithOnRecordComponent.java new file mode 100644 index 00000000..42028f81 --- /dev/null +++ b/test/transform/resource/after-ecj/WithOnRecordComponent.java @@ -0,0 +1,13 @@ +import lombok.With; +record WithOnRecordComponent(String a, String b) { +/* Implicit */ private final String a; +/* Implicit */ private final String b; + public WithOnRecordComponent( String a, String b) { + super(); + .a = a; + .b = b; + } + public @java.lang.SuppressWarnings("all") WithOnRecordComponent withA(final String a) { + return ((this.a == a) ? this : new WithOnRecordComponent(a, this.b)); + } +} diff --git a/test/transform/resource/before/WithByOnRecord.java b/test/transform/resource/before/WithByOnRecord.java index 98cbff9b..6c7b8e2d 100644 --- a/test/transform/resource/before/WithByOnRecord.java +++ b/test/transform/resource/before/WithByOnRecord.java @@ -2,5 +2,6 @@ import lombok.experimental.WithBy; -record WithByOnRecord(@WithBy String a, String b) { +@WithBy +record WithByOnRecord(String a, String b) { } \ No newline at end of file diff --git a/test/transform/resource/before/WithByOnRecordComponent.java b/test/transform/resource/before/WithByOnRecordComponent.java new file mode 100644 index 00000000..7e0f0f19 --- /dev/null +++ b/test/transform/resource/before/WithByOnRecordComponent.java @@ -0,0 +1,6 @@ +// version 14: + +import lombok.experimental.WithBy; + +record WithByOnRecordComponent(@WithBy String a, String b) { +} \ No newline at end of file diff --git a/test/transform/resource/before/WithOnRecordComponent.java b/test/transform/resource/before/WithOnRecordComponent.java new file mode 100644 index 00000000..6f827851 --- /dev/null +++ b/test/transform/resource/before/WithOnRecordComponent.java @@ -0,0 +1,6 @@ +// version 14: + +import lombok.With; + +record WithOnRecordComponent(@With String a, String b) { +} \ No newline at end of file -- cgit