Repository: SpoonLabs/gumtree-spoon-ast-diff (java)

Issue:
`Diff` in annotations is not detected
Reference: https://github.com/SpoonLabs/gumtree-spoon-ast-diff/pull/171#discussion_r693703934.

Currently, there is no AST difference between `@Override` and `@override` which is a bug. Although the annotation node is a part of the `ITree` model, the diff is not detected. This could be because `LabelFinder` is not able to find the label for annotation nodes.

Pull request description:
fix: add labels in nodes for annotation
Fixes #174 

The changes add a visitor for `CtAnnotation` which gets the corresponding label.

Patch:
diff --git a/src/main/java/gumtree/spoon/builder/LabelFinder.java b/src/main/java/gumtree/spoon/builder/LabelFinder.java
index 1feffcc..19899ef 100644
--- a/src/main/java/gumtree/spoon/builder/LabelFinder.java
+++ b/src/main/java/gumtree/spoon/builder/LabelFinder.java
@@ -19,11 +19,14 @@ import spoon.reflect.code.CtTypeAccess;
 import spoon.reflect.code.CtUnaryOperator;
 import spoon.reflect.code.CtVariableAccess;
 import spoon.reflect.code.CtWhile;
+import spoon.reflect.declaration.CtAnnotation;
 import spoon.reflect.declaration.CtNamedElement;
 import spoon.reflect.path.CtRole;
 import spoon.reflect.reference.CtTypeReference;
 import spoon.reflect.visitor.CtInheritanceScanner;
 
+import java.lang.annotation.Annotation;
+
 class LabelFinder extends CtInheritanceScanner {
 	public String label = "";
 
@@ -144,4 +147,9 @@ class LabelFinder extends CtInheritanceScanner {
 	public void visitCtComment(CtComment comment) {
 		label = comment.getContent();
 	}
+
+	@Override
+	public <T extends Annotation> void visitCtAnnotation(CtAnnotation<T> annotation) {
+		label = annotation.toString();
+	}
 }


Test patch:
diff --git a/src/test/java/gumtree/spoon/TreeTest.java b/src/test/java/gumtree/spoon/TreeTest.java
index b7cdba7..0589c0f 100644
--- a/src/test/java/gumtree/spoon/TreeTest.java
+++ b/src/test/java/gumtree/spoon/TreeTest.java
@@ -511,4 +511,18 @@ public class TreeTest {
 		assertEquals(3, position.getLine());
 
 	}
+
+	@Test
+	public void test_getTree_labelExistsForAnnotations() {
+		String codeWithAnnotation = "class A { @Override public boolean equals(Object obj) { return false; }";
+
+		AstComparator comparator = new AstComparator();
+		CtType<?> spoonType = comparator.getCtType(codeWithAnnotation);
+
+		final SpoonGumTreeBuilder scanner = new SpoonGumTreeBuilder();
+		ITree root = scanner.getTree(spoonType);
+
+		ITree annotationNode = root.getChild(0).getChild(0).getChild(2);
+		assertEquals("@java.lang.Override", annotationNode.getLabel());
+	}
 }
diff --git a/src/test/java/gumtree/spoon/diff/DiffTest.java b/src/test/java/gumtree/spoon/diff/DiffTest.java
index 71b68cc..f889c36 100644
--- a/src/test/java/gumtree/spoon/diff/DiffTest.java
+++ b/src/test/java/gumtree/spoon/diff/DiffTest.java
@@ -229,4 +229,15 @@ public class DiffTest {
 		assertTrue(diff.containsOperation(OperationKind.Insert, "TypeReference"));
 		assertTrue(diff.containsOperation(OperationKind.Delete, "TypeParameterReference"));
 	}
+
+	@Test
+	public void test_diffOfAnnotations() throws Exception {
+		File left = new File("src/test/resources/examples/annotations/left.java");
+		File right = new File("src/test/resources/examples/annotations/right.java");
+
+		Diff diff = new AstComparator().compare(left, right);
+
+		assertEquals(1, diff.getRootOperations().size());
+		assertTrue(diff.containsOperation(OperationKind.Update, "Annotation"));
+	}
 }
diff --git a/src/test/resources/examples/annotations/left.java b/src/test/resources/examples/annotations/left.java
new file mode 100644
index 0000000..b48bc62
--- /dev/null
+++ b/src/test/resources/examples/annotations/left.java
@@ -0,0 +1,6 @@
+class Test {
+    @Override
+    public int hashCode() {
+        return -1;
+    }
+}
diff --git a/src/test/resources/examples/annotations/right.java b/src/test/resources/examples/annotations/right.java
new file mode 100644
index 0000000..c2ec890
--- /dev/null
+++ b/src/test/resources/examples/annotations/right.java
@@ -0,0 +1,6 @@
+class Test {
+    @Deprecated
+    public int hashCode() {
+        return -1;
+    }
+}