diff --git a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java index 4fc948a680..8151e8cc91 100644 --- a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java +++ b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2024 The Project Lombok Authors. + * Copyright (C) 2009-2025 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -2736,10 +2736,8 @@ public static boolean isClassEnumOrRecord(EclipseNode typeNode) { * Returns {@code true} if the provided node is a record declaration (so, not an annotation definition, interface, enum, or plain class). */ public static boolean isRecord(EclipseNode typeNode) { - TypeDeclaration typeDecl = null; - if (typeNode.get() instanceof TypeDeclaration) typeDecl = (TypeDeclaration) typeNode.get(); - int modifiers = typeDecl == null ? 0 : typeDecl.modifiers; - return (modifiers & AccRecord) != 0; + ASTNode node = typeNode.get(); + return node instanceof TypeDeclaration && isRecord((TypeDeclaration) node); } /** @@ -2773,6 +2771,14 @@ public static boolean isStaticAllowed(EclipseNode typeNode) { return typeNode.isStatic() || typeNode.up() == null || typeNode.up().getKind() == Kind.COMPILATION_UNIT || isRecord(typeNode); } + /** + * Returns {@code true} if the provided type declaration is a record declaration (so, not an annotation definition, interface, enum, or plain class). + */ + public static boolean isRecord(TypeDeclaration typeDecl) { + int modifiers = typeDecl == null ? 0 : typeDecl.modifiers; + return (modifiers & AccRecord) != 0; + } + public static AbstractVariableDeclaration[] getRecordComponents(TypeDeclaration typeDeclaration) { if (typeDeclaration == null || (typeDeclaration.modifiers & AccRecord) == 0) return null; try { diff --git a/src/eclipseAgent/lombok/eclipse/agent/PatchDelegate.java b/src/eclipseAgent/lombok/eclipse/agent/PatchDelegate.java index fee6db43cf..547810e90f 100644 --- a/src/eclipseAgent/lombok/eclipse/agent/PatchDelegate.java +++ b/src/eclipseAgent/lombok/eclipse/agent/PatchDelegate.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2024 The Project Lombok Authors. + * Copyright (C) 2010-2025 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -48,13 +48,13 @@ import org.eclipse.jdt.internal.compiler.CompilationResult; import org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; +import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration; import org.eclipse.jdt.internal.compiler.ast.Annotation; import org.eclipse.jdt.internal.compiler.ast.Argument; import org.eclipse.jdt.internal.compiler.ast.ArrayInitializer; import org.eclipse.jdt.internal.compiler.ast.ClassLiteralAccess; import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration; import org.eclipse.jdt.internal.compiler.ast.Expression; -import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration; import org.eclipse.jdt.internal.compiler.ast.FieldReference; import org.eclipse.jdt.internal.compiler.ast.MemberValuePair; import org.eclipse.jdt.internal.compiler.ast.MessageSend; @@ -129,7 +129,8 @@ private static String nameOfScope(ClassScope scope) { } private static boolean hasDelegateMarkedFieldsOrMethods(TypeDeclaration decl) { - if (decl.fields != null) for (FieldDeclaration field : decl.fields) { + AbstractVariableDeclaration[] fields = getFieldsOrRecordComponents(decl); + if (fields != null) for (AbstractVariableDeclaration field : fields) { if (field.annotations == null) continue; for (Annotation ann : field.annotations) { if (isDelegate(ann, decl)) return true; @@ -224,11 +225,19 @@ public static void markHandled(Annotation annotation) { Annotation_applied.set(annotation, true); } + private static AbstractVariableDeclaration[] getFieldsOrRecordComponents(TypeDeclaration decl) { + if (isRecord(decl)) return getRecordComponents(decl); + return decl.fields; + } + private static void fillMethodBindingsForFields(CompilationUnitDeclaration cud, ClassScope scope, List methodsToDelegate) { TypeDeclaration decl = scope.referenceContext; if (decl == null) return; - if (decl.fields != null) for (FieldDeclaration field : decl.fields) { + AbstractVariableDeclaration[] fields = getFieldsOrRecordComponents(decl); + if (fields == null) return; + + for (AbstractVariableDeclaration field : fields) { if (field.annotations == null) continue; for (Annotation ann : field.annotations) { if (!isDelegate(ann, decl)) continue; diff --git a/test/transform/resource/after-delombok/DelegateOnRecord.java b/test/transform/resource/after-delombok/DelegateOnRecord.java new file mode 100644 index 0000000000..fc5b974494 --- /dev/null +++ b/test/transform/resource/after-delombok/DelegateOnRecord.java @@ -0,0 +1,8 @@ +// version 14: +record DelegateOnRecord(Runnable runnable) { + @java.lang.SuppressWarnings("all") + @lombok.Generated + public void run() { + this.runnable.run(); + } +} diff --git a/test/transform/resource/after-ecj/DelegateOnRecord.java b/test/transform/resource/after-ecj/DelegateOnRecord.java new file mode 100644 index 0000000000..7194a014fb --- /dev/null +++ b/test/transform/resource/after-ecj/DelegateOnRecord.java @@ -0,0 +1,8 @@ +// version 14: +import lombok.experimental.Delegate; +record DelegateOnRecord(Runnable runnable) { +/* Implicit */ private final Runnable runnable; + public @java.lang.SuppressWarnings("all") @lombok.Generated void run() { + this.runnable.run(); + } +} diff --git a/test/transform/resource/before/DelegateOnRecord.java b/test/transform/resource/before/DelegateOnRecord.java new file mode 100644 index 0000000000..daaeba5b21 --- /dev/null +++ b/test/transform/resource/before/DelegateOnRecord.java @@ -0,0 +1,6 @@ +//platform !eclipse: Requires a 'full' eclipse with intialized workspace, and we don't (yet) have that set up properly in the test run. +//version 14: +import lombok.experimental.Delegate; + +record DelegateOnRecord(@Delegate Runnable runnable) { +}