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

Issue:
Wrapping super types using `CtWrapper` is not required
`CtWrapper` is used to wrap elements that are not inherited from `CtElement` and thus, are not a node in spoon metamodel. For example, modifiers are defined as enums in spoon and since diff is calculated on spoon elements, it was necessary to wrap them.

However, consider the following diff:
```diff
- class Child extends Parent1 { }
+ class Child extends Parent2 { }
```

Currently, its edit script contains an update operation for updating the **CtWrapper** to `Parent2`. Instead, I propose that we do not wrap such elements because these are instances of `CtTypeReferences` so the edit script involving these elements can simply say `Update CtTypeReference at Child from Parent1 to Parent2`. The patch to achieve so is:

```diff
diff --git a/src/main/java/gumtree/spoon/builder/NodeCreator.java b/src/main/java/gumtree/spoon/builder/NodeCreator.java
index 19c3cc6..7f10f6f 100644
--- a/src/main/java/gumtree/spoon/builder/NodeCreator.java
+++ b/src/main/java/gumtree/spoon/builder/NodeCreator.java
@@ -102,8 +102,7 @@ public class NodeCreator extends CtInheritanceScanner {
 
         if (reference instanceof CtTypeReference && reference.getRoleInParent() == CtRole.SUPER_TYPE) {
             ITree superType = builder.createNode("SUPER_TYPE", reference.toString());
-            CtWrapper<CtReference> k = new CtWrapper<CtReference>(reference, reference.getParent());
-            superType.setMetadata(SpoonGumTreeBuilder.SPOON_OBJECT, k);
+            superType.setMetadata(SpoonGumTreeBuilder.SPOON_OBJECT, reference);
             reference.putMetadata(SpoonGumTreeBuilder.GUMTREE_NODE, superType);
             builder.addSiblingNode(superType);
         } else {
```

Pull request:
Remove wrapper from instances of `CtTypeReference`
Fixes #166 

The PR refactors the node creation of `CtTypeReference`s. Initially, they were wrapped in `CtWrapper` and then stored as metadata. These changes **will not** wrap `CtTypeReference`s and directly store them corresponding to `spoon_object` key.

Patch:
diff --git a/src/main/java/gumtree/spoon/builder/NodeCreator.java b/src/main/java/gumtree/spoon/builder/NodeCreator.java
index 19c3cc6..7f10f6f 100644
--- a/src/main/java/gumtree/spoon/builder/NodeCreator.java
+++ b/src/main/java/gumtree/spoon/builder/NodeCreator.java
@@ -102,8 +102,7 @@ public class NodeCreator extends CtInheritanceScanner {
 
         if (reference instanceof CtTypeReference && reference.getRoleInParent() == CtRole.SUPER_TYPE) {
             ITree superType = builder.createNode("SUPER_TYPE", reference.toString());
-            CtWrapper<CtReference> k = new CtWrapper<CtReference>(reference, reference.getParent());
-            superType.setMetadata(SpoonGumTreeBuilder.SPOON_OBJECT, k);
+            superType.setMetadata(SpoonGumTreeBuilder.SPOON_OBJECT, reference);
             reference.putMetadata(SpoonGumTreeBuilder.GUMTREE_NODE, superType);
             builder.addSiblingNode(superType);
         } else {


Test patch:
diff --git a/src/test/java/gumtree/spoon/diff/support/SpoonSupportTest.java b/src/test/java/gumtree/spoon/diff/support/SpoonSupportTest.java
index 6245e3e..023216c 100644
--- a/src/test/java/gumtree/spoon/diff/support/SpoonSupportTest.java
+++ b/src/test/java/gumtree/spoon/diff/support/SpoonSupportTest.java
@@ -1,5 +1,7 @@
 package gumtree.spoon.diff.support;
 
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.hamcrest.MatcherAssert.assertThat;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
@@ -18,10 +20,10 @@ import gumtree.spoon.diff.operations.DeleteOperation;
 import gumtree.spoon.diff.operations.InsertOperation;
 import gumtree.spoon.diff.operations.Operation;
 import gumtree.spoon.diff.operations.UpdateOperation;
-import spoon.reflect.declaration.CtElement;
 import spoon.reflect.declaration.CtMethod;
 import spoon.reflect.declaration.ModifierKind;
 import spoon.reflect.path.CtRole;
+import spoon.reflect.reference.CtTypeReference;
 
 import java.io.File;
 import java.util.HashSet;
@@ -195,6 +197,19 @@ public class SpoonSupportTest {
 		assertEquals(CtRole.MODIFIER, modifiers.getRoleInParent());
 	}
 
+	@Test
+	public void test_typeOfUpdatedNodeShouldEqualCtTypeReference() {
+		String c1 = "class Child extends Parent1 { }";
+		String c2 = "class Child extends Parent2 { }";
+
+		Diff diff = new AstComparator().compare(c1, c2);
+
+		UpdateOperation updateOperation = (UpdateOperation) diff.getRootOperations().get(0);
+
+		assertThat(updateOperation.getSrcNode(), instanceOf(CtTypeReference.class));
+		assertThat(updateOperation.getDstNode(), instanceOf(CtTypeReference.class));
+	}
+
 	@Test
 	public void testGettingChildrenOfCtVirtualElement() {
 		String c1 = "class Test { }";