From 71c783c5481b669037971f05f183589ca1c72f76 Mon Sep 17 00:00:00 2001 From: Tim te Beek Date: Fri, 17 Oct 2025 15:16:06 +0200 Subject: [PATCH] Fix duplicate @Getter annotations on multiple variable declarations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When multiple variables are declared on one line (e.g., `int foo, bar = 9;`) with corresponding getter methods, the recipe was adding @Getter twice to the same field declaration. This happened because each getter method triggered a separate FieldAnnotator visitor, and both attempted to annotate the shared VariableDeclarations node. The fix adds a check to prevent duplicate annotations by verifying if the annotation already exists before applying it. Fixes #876 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .../java/migrate/lombok/FieldAnnotator.java | 20 ++++++++---- .../migrate/lombok/UseLombokGetterTest.java | 32 +++++++++++++++++++ 2 files changed, 45 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/openrewrite/java/migrate/lombok/FieldAnnotator.java b/src/main/java/org/openrewrite/java/migrate/lombok/FieldAnnotator.java index d834f1a0d2..9b0be977f4 100644 --- a/src/main/java/org/openrewrite/java/migrate/lombok/FieldAnnotator.java +++ b/src/main/java/org/openrewrite/java/migrate/lombok/FieldAnnotator.java @@ -40,13 +40,19 @@ class FieldAnnotator extends JavaIsoVisitor { public J.VariableDeclarations visitVariableDeclarations(J.VariableDeclarations multiVariable, ExecutionContext ctx) { for (J.VariableDeclarations.NamedVariable variable : multiVariable.getVariables()) { if (variable.getName().getFieldType() == field) { - maybeAddImport(annotation.getName()); - maybeAddImport("lombok.AccessLevel"); - String suffix = accessLevel == PUBLIC ? "" : String.format("(AccessLevel.%s)", accessLevel.name()); - return JavaTemplate.builder("@" + annotation.getSimpleName() + suffix) - .imports(annotation.getName(), "lombok.AccessLevel") - .javaParser(JavaParser.fromJavaVersion().classpath("lombok")) - .build().apply(getCursor(), multiVariable.getCoordinates().addAnnotation(comparing(J.Annotation::getSimpleName))); + // Check if the annotation already exists (can happen with multiple variable declarations) + String annotationName = annotation.getSimpleName(); + if (multiVariable.getLeadingAnnotations().stream() + .noneMatch(ann -> annotationName.equals(ann.getSimpleName()))) { + maybeAddImport(annotation.getName()); + maybeAddImport("lombok.AccessLevel"); + String suffix = accessLevel == PUBLIC ? "" : String.format("(AccessLevel.%s)", accessLevel.name()); + return JavaTemplate.builder("@" + annotation.getSimpleName() + suffix) + .imports(annotation.getName(), "lombok.AccessLevel") + .javaParser(JavaParser.fromJavaVersion().classpath("lombok")) + .build().apply(getCursor(), multiVariable.getCoordinates().addAnnotation(comparing(J.Annotation::getSimpleName))); + } + return multiVariable; } } return multiVariable; diff --git a/src/test/java/org/openrewrite/java/migrate/lombok/UseLombokGetterTest.java b/src/test/java/org/openrewrite/java/migrate/lombok/UseLombokGetterTest.java index 739b92875f..89778f52cb 100644 --- a/src/test/java/org/openrewrite/java/migrate/lombok/UseLombokGetterTest.java +++ b/src/test/java/org/openrewrite/java/migrate/lombok/UseLombokGetterTest.java @@ -638,4 +638,36 @@ private Long getNumber() { ) ); } + + @Issue("https://github.com/openrewrite/rewrite-migrate-java/issues/876") + @Test + void multipleVariableDeclarations() { + rewriteRun(// language=java + java( + """ + class A { + + int foo, bar = 9; + + public int getFoo() { + return foo; + } + + public int getBar() { + return bar; + } + } + """, + """ + import lombok.Getter; + + class A { + + @Getter + int foo, bar = 9; + } + """ + ) + ); + } }