From 0232d9524461d5dc1e987f2a99b0c81c13cedfa7 Mon Sep 17 00:00:00 2001 From: Richard Harris Date: Tue, 25 Mar 2025 15:59:40 +0000 Subject: [PATCH 1/2] Allow annotation refactor to force use of a fully qualified name in cases where we aren't replacing all uses of an annotation. --- .../annotations/AnnotationChangeRefactor.java | 29 +++++++-- ...AnnotationChangeSameSimpleNameExample.java | 15 +++++ ...ationChangeSameSimpleNameExampleAfter.java | 15 +++++ ...ngeSameSimpleNameWithRemainderExample.java | 18 ++++++ ...meSimpleNameWithRemainderExampleAfter.java | 18 ++++++ .../annotations/TestAnnotationsRefactor.java | 64 ++++++++++++++++++- .../astra/moreexampletypes/AnnotationA.java | 9 +++ 7 files changed, 162 insertions(+), 6 deletions(-) create mode 100644 astra-core/src/test/java/org/alfasoftware/astra/core/refactoring/annotations/AnnotationChangeSameSimpleNameExample.java create mode 100644 astra-core/src/test/java/org/alfasoftware/astra/core/refactoring/annotations/AnnotationChangeSameSimpleNameExampleAfter.java create mode 100644 astra-core/src/test/java/org/alfasoftware/astra/core/refactoring/annotations/AnnotationChangeSameSimpleNameWithRemainderExample.java create mode 100644 astra-core/src/test/java/org/alfasoftware/astra/core/refactoring/annotations/AnnotationChangeSameSimpleNameWithRemainderExampleAfter.java create mode 100644 astra-core/src/test/java/org/alfasoftware/astra/moreexampletypes/AnnotationA.java diff --git a/astra-core/src/main/java/org/alfasoftware/astra/core/refactoring/operations/annotations/AnnotationChangeRefactor.java b/astra-core/src/main/java/org/alfasoftware/astra/core/refactoring/operations/annotations/AnnotationChangeRefactor.java index 4c0e899..25eb80f 100644 --- a/astra-core/src/main/java/org/alfasoftware/astra/core/refactoring/operations/annotations/AnnotationChangeRefactor.java +++ b/astra-core/src/main/java/org/alfasoftware/astra/core/refactoring/operations/annotations/AnnotationChangeRefactor.java @@ -1,7 +1,6 @@ package org.alfasoftware.astra.core.refactoring.operations.annotations; import java.io.IOException; -import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.Optional; @@ -32,6 +31,8 @@ *
  * com.google.inject.Inject -> javax.inject.Inject.
  * 
+ * By default the import for an annotation will be swapped over.
+ * If this is not required use {@link Builder#forceQualifiedName()}.
  */
 public class AnnotationChangeRefactor implements ASTOperation {
 
@@ -47,8 +48,11 @@ public class AnnotationChangeRefactor implements ASTOperation {
   private final Map memberNameUpdates;
   private final Map memberNamesToUpdateWithNewValues;
   private final Optional transform;
+  private final boolean forceQualifiedName;
 
-  public AnnotationChangeRefactor(AnnotationMatcher fromType, String toType, Map membersAndValuesToAdd, Map memberAndTypesToAdd, Set namesForMembersToRemove, Map memberNameUpdates, Map memberNamesToUpdateWithNewValues, Optional transform) {
+  public AnnotationChangeRefactor(AnnotationMatcher fromType, String toType, Map membersAndValuesToAdd,
+      Map memberAndTypesToAdd, Set namesForMembersToRemove, Map memberNameUpdates,
+      Map memberNamesToUpdateWithNewValues, Optional transform, boolean forceQualifiedName) {
     this.fromType = fromType;
     this.toType = toType;
     this.membersAndValuesToAdd = membersAndValuesToAdd;
@@ -57,6 +61,7 @@ public AnnotationChangeRefactor(AnnotationMatcher fromType, String toType, Map memberNameUpdates = Map.of();
     private Optional transform = Optional.empty();
     private Map memberNamesToUpdateWithNewValues = Map.of();
+    private boolean forceQualifiedName;
 
     private Builder() {
       super();
@@ -132,6 +138,17 @@ public Builder withTransform(Transform transform) {
       return this;
     }
 
+    /**
+     * Forces use of the qualified name for the annotation.
+     * This is helpful if not all instances of an annotation are going to be replaced.
+     *
+     * @return this for method chaining
+     */
+    public Builder forceQualifiedName() {
+      this.forceQualifiedName = true;
+      return this;
+    }
+
     public AnnotationChangeRefactor build() {
       return new AnnotationChangeRefactor(fromType,
               toType,
@@ -140,8 +157,10 @@ public AnnotationChangeRefactor build() {
               namesForMembersToRemove,
               memberNameUpdates,
               memberNamesToUpdateWithNewValues,
-              transform);
+              transform,
+              forceQualifiedName);
     }
+
   }
 
 
@@ -162,7 +181,7 @@ public void run(CompilationUnit compilationUnit, ASTNode node, ASTRewrite rewrit
             + "to [" + toType + "] "
             + "in [" + AstraUtils.getNameForCompilationUnit(compilationUnit) + "]");
 
-        if (! AstraUtils.getSimpleName(toType).equals(AstraUtils.getSimpleName(annotation.getTypeName().getFullyQualifiedName()))) {
+        if (!forceQualifiedName && !annotation.getTypeName().isQualifiedName()) {
           AstraUtils.updateImport(compilationUnit, fromType.getFullyQualifiedName(), toType, rewriter);
         }
 
@@ -193,7 +212,7 @@ private void rewriteAnnotation(CompilationUnit compilationUnit, Annotation annot
 
   private Annotation changeAnnotationName(ASTRewrite rewriter, Annotation annotation) {
     Name name;
-    if (annotation.getTypeName().isQualifiedName()) {
+    if (forceQualifiedName || annotation.getTypeName().isQualifiedName()) {
       name = annotation.getAST().newName(toType);
     } else {
       name = annotation.getAST().newSimpleName(AstraUtils.getSimpleName(toType));
diff --git a/astra-core/src/test/java/org/alfasoftware/astra/core/refactoring/annotations/AnnotationChangeSameSimpleNameExample.java b/astra-core/src/test/java/org/alfasoftware/astra/core/refactoring/annotations/AnnotationChangeSameSimpleNameExample.java
new file mode 100644
index 0000000..6460ee7
--- /dev/null
+++ b/astra-core/src/test/java/org/alfasoftware/astra/core/refactoring/annotations/AnnotationChangeSameSimpleNameExample.java
@@ -0,0 +1,15 @@
+package org.alfasoftware.astra.core.refactoring.annotations;
+
+import org.alfasoftware.astra.exampleTypes.AnnotationA;
+
+@AnnotationA("")
+public class AnnotationChangeSameSimpleNameExample {
+
+    @AnnotationA(value="A")
+    protected long someField;
+
+    @AnnotationA("BAR")
+    public char getBar(){
+        return 'a';
+    }
+}
diff --git a/astra-core/src/test/java/org/alfasoftware/astra/core/refactoring/annotations/AnnotationChangeSameSimpleNameExampleAfter.java b/astra-core/src/test/java/org/alfasoftware/astra/core/refactoring/annotations/AnnotationChangeSameSimpleNameExampleAfter.java
new file mode 100644
index 0000000..06ba75e
--- /dev/null
+++ b/astra-core/src/test/java/org/alfasoftware/astra/core/refactoring/annotations/AnnotationChangeSameSimpleNameExampleAfter.java
@@ -0,0 +1,15 @@
+package org.alfasoftware.astra.core.refactoring.annotations;
+
+import org.alfasoftware.astra.moreexampletypes.AnnotationA;
+
+@AnnotationA("")
+public class AnnotationChangeSameSimpleNameExampleAfter {
+
+    @AnnotationA(value="A")
+    protected long someField;
+
+    @AnnotationA("BAR")
+    public char getBar(){
+        return 'a';
+    }
+}
diff --git a/astra-core/src/test/java/org/alfasoftware/astra/core/refactoring/annotations/AnnotationChangeSameSimpleNameWithRemainderExample.java b/astra-core/src/test/java/org/alfasoftware/astra/core/refactoring/annotations/AnnotationChangeSameSimpleNameWithRemainderExample.java
new file mode 100644
index 0000000..e45632c
--- /dev/null
+++ b/astra-core/src/test/java/org/alfasoftware/astra/core/refactoring/annotations/AnnotationChangeSameSimpleNameWithRemainderExample.java
@@ -0,0 +1,18 @@
+package org.alfasoftware.astra.core.refactoring.annotations;
+
+import org.alfasoftware.astra.exampleTypes.AnnotationA;
+
+@AnnotationA("")
+public class AnnotationChangeSameSimpleNameWithRemainderExample {
+
+    /**
+     * This annotation should not change
+     */
+    @AnnotationA(value="A")
+    protected long someField;
+
+    @AnnotationA("BAR")
+    public char getBar(){
+        return 'a';
+    }
+}
diff --git a/astra-core/src/test/java/org/alfasoftware/astra/core/refactoring/annotations/AnnotationChangeSameSimpleNameWithRemainderExampleAfter.java b/astra-core/src/test/java/org/alfasoftware/astra/core/refactoring/annotations/AnnotationChangeSameSimpleNameWithRemainderExampleAfter.java
new file mode 100644
index 0000000..9e4b582
--- /dev/null
+++ b/astra-core/src/test/java/org/alfasoftware/astra/core/refactoring/annotations/AnnotationChangeSameSimpleNameWithRemainderExampleAfter.java
@@ -0,0 +1,18 @@
+package org.alfasoftware.astra.core.refactoring.annotations;
+
+import org.alfasoftware.astra.exampleTypes.AnnotationA;
+
+@org.alfasoftware.astra.moreexampletypes.AnnotationA("")
+public class AnnotationChangeSameSimpleNameWithRemainderExampleAfter {
+
+    /**
+     * This annotation should not change
+     */
+    @AnnotationA(value="A")
+    protected long someField;
+
+    @org.alfasoftware.astra.moreexampletypes.AnnotationA("BAR")
+    public char getBar(){
+        return 'a';
+    }
+}
diff --git a/astra-core/src/test/java/org/alfasoftware/astra/core/refactoring/annotations/TestAnnotationsRefactor.java b/astra-core/src/test/java/org/alfasoftware/astra/core/refactoring/annotations/TestAnnotationsRefactor.java
index e17ad22..a75f4c3 100644
--- a/astra-core/src/test/java/org/alfasoftware/astra/core/refactoring/annotations/TestAnnotationsRefactor.java
+++ b/astra-core/src/test/java/org/alfasoftware/astra/core/refactoring/annotations/TestAnnotationsRefactor.java
@@ -1,5 +1,7 @@
 package org.alfasoftware.astra.core.refactoring.annotations;
 
+import static org.alfasoftware.astra.core.utils.AstraUtils.addImport;
+
 import java.util.Arrays;
 import java.util.HashSet;
 import java.util.Map;
@@ -22,7 +24,13 @@
 import org.eclipse.jdt.core.dom.TypeDeclaration;
 import org.junit.Test;
 
-import static org.alfasoftware.astra.core.utils.AstraUtils.addImport;
+/**
+ * TODO TestAnnotationsRefactor class-level Javadoc.
+ *
+ * 

...

+ * + * @author Copyright (c) Alfa Financial Software Limited. 2025 + */ public class TestAnnotationsRefactor extends AbstractRefactorTest { @@ -91,6 +99,60 @@ public void testAnnotationChange() { ))); } + @Test + public void testSameSimpleNameAnnotationChange() { + assertRefactor( + AnnotationChangeSameSimpleNameExample.class, + new HashSet<>(Arrays.asList( + AnnotationChangeRefactor.builder() + .from(AnnotationMatcher.builder() + .withFullyQualifiedName(AnnotationA.class.getName()) + .withValue("") + .build()) + .to(org.alfasoftware.astra.moreexampletypes.AnnotationA.class.getTypeName()).build(), + AnnotationChangeRefactor.builder() + .from(AnnotationMatcher.builder() + .withFullyQualifiedName(AnnotationA.class.getName()) + .withValue("A") + .build()) + .to(org.alfasoftware.astra.moreexampletypes.AnnotationA.class.getTypeName()).build(), + AnnotationChangeRefactor.builder() + .from(AnnotationMatcher.builder() + .withFullyQualifiedName(AnnotationA.class.getName()) + .withValue("BAR") + .build()) + .to(org.alfasoftware.astra.moreexampletypes.AnnotationA.class.getTypeName()).build() + ))); + } + + /** + * Example where we are not swapping over all instances of an annotation with the same simple name + * therefore we force the new annotation to be fully qualified. + */ + @Test + public void testSameSimpleNameAnnotationChangeWithRemainder() { + assertRefactor( + AnnotationChangeSameSimpleNameWithRemainderExample.class, + new HashSet<>(Arrays.asList( + AnnotationChangeRefactor.builder() + .from(AnnotationMatcher.builder() + .withFullyQualifiedName(AnnotationA.class.getName()) + .withValue("") + .build()) + .to(org.alfasoftware.astra.moreexampletypes.AnnotationA.class.getTypeName()) + .forceQualifiedName() + .build(), + AnnotationChangeRefactor.builder() + .from(AnnotationMatcher.builder() + .withFullyQualifiedName(AnnotationA.class.getName()) + .withValue("BAR") + .build()) + .to(org.alfasoftware.astra.moreexampletypes.AnnotationA.class.getTypeName()) + .forceQualifiedName() + .build() + ))); + } + @Test public void testRemoveAnnotation() { assertRefactor( diff --git a/astra-core/src/test/java/org/alfasoftware/astra/moreexampletypes/AnnotationA.java b/astra-core/src/test/java/org/alfasoftware/astra/moreexampletypes/AnnotationA.java new file mode 100644 index 0000000..a485e26 --- /dev/null +++ b/astra-core/src/test/java/org/alfasoftware/astra/moreexampletypes/AnnotationA.java @@ -0,0 +1,9 @@ +package org.alfasoftware.astra.moreexampletypes; + +public @interface AnnotationA { + + String value() default ""; + + String othervalue() default ""; +} + From 0ed8f0de72eb2c4d8479b8f0ab44c177cba39275 Mon Sep 17 00:00:00 2001 From: Richard Harris Date: Tue, 25 Mar 2025 17:08:48 +0000 Subject: [PATCH 2/2] Remove accidental javadoc --- .../refactoring/annotations/TestAnnotationsRefactor.java | 8 -------- 1 file changed, 8 deletions(-) diff --git a/astra-core/src/test/java/org/alfasoftware/astra/core/refactoring/annotations/TestAnnotationsRefactor.java b/astra-core/src/test/java/org/alfasoftware/astra/core/refactoring/annotations/TestAnnotationsRefactor.java index a75f4c3..3d37d1f 100644 --- a/astra-core/src/test/java/org/alfasoftware/astra/core/refactoring/annotations/TestAnnotationsRefactor.java +++ b/astra-core/src/test/java/org/alfasoftware/astra/core/refactoring/annotations/TestAnnotationsRefactor.java @@ -24,14 +24,6 @@ import org.eclipse.jdt.core.dom.TypeDeclaration; import org.junit.Test; -/** - * TODO TestAnnotationsRefactor class-level Javadoc. - * - *

...

- * - * @author Copyright (c) Alfa Financial Software Limited. 2025 - */ - public class TestAnnotationsRefactor extends AbstractRefactorTest { @Test