GumTreeDiff / gumtree

An awesome code differencing tool
https://github.com/GumTreeDiff/gumtree/wiki
GNU Lesser General Public License v3.0
917 stars 173 forks source link

Confusing results generated by GTD #319

Closed Feng-Jay closed 1 year ago

Feng-Jay commented 1 year ago

Hi! Thanks for the timely reply to #318 .

I got two more questions when using GTD.

// example1
public class test1 {
    public int add(int a, int b) {
        return a+b;
    }

    public void test (int x, int a) {
        int x1 = add(x,a);
        return ;
    }
}
// example2
public class test2 {
    public int add(int a, int b) {
        return a+b;
    }

    public void test (int x, int a) {
        int x1 = add(x,0);
        int x2 = 0;
        if(x1 == x2)
            return;
    }
}

The outcome is:

action: === update-node --- SimpleName: test1 [13,18] replace test1 by test2
action: === insert-node --- MethodDeclaration [87,214] to TypeDeclaration [0,172] at 4
action: === insert-node --- Modifier: public [87,93] to MethodDeclaration [87,214] at 0
action: === insert-node --- PrimitiveType: void [94,98] to MethodDeclaration [87,214] at 1
action: === insert-node --- SimpleName: test [99,103] to MethodDeclaration [87,214] at 2
action: === move-tree --- SingleVariableDeclaration [105,110]     PrimitiveType: int [105,108]     SimpleName: x [109,110] to MethodDeclaration [87,214] at 3
action: === move-tree --- SingleVariableDeclaration [112,117]     PrimitiveType: int [112,115]     SimpleName: a [116,117] to MethodDeclaration [87,214] at 4
action: === insert-tree --- Block [119,214]     VariableDeclarationStatement [129,147]         PrimitiveType: int [129,132]         VariableDeclarationFragment [133,146]             SimpleName: x1 [133,135]             MethodInvocation [138,146]                 SimpleName: add [138,141]                 METHOD_INVOCATION_ARGUMENTS [142,145]                     SimpleName: x [142,143]                     NumberLiteral: 0 [144,145]     VariableDeclarationStatement [156,167]         PrimitiveType: int [156,159]         VariableDeclarationFragment [160,166]             SimpleName: x2 [160,162]             NumberLiteral: 0 [165,166]     IfStatement [176,208]         InfixExpression [179,187]             SimpleName: x1 [179,181]             INFIX_EXPRESSION_OPERATOR: == [182,184]             SimpleName: x2 [185,187]         ReturnStatement [201,208] to MethodDeclaration [87,214] at 5
action: === delete-node --- Modifier: public [87,93] ===
action: === delete-node --- PrimitiveType: void [94,98] ===
action: === delete-node --- SimpleName: test [99,103] ===
action: === delete-tree --- Block [119,170]     VariableDeclarationStatement [129,147]         PrimitiveType: int [129,132]         VariableDeclarationFragment [133,146]             SimpleName: x1 [133,135]             MethodInvocation [138,146]                 SimpleName: add [138,141]                 METHOD_INVOCATION_ARGUMENTS [142,145]                     SimpleName: x [142,143]                     SimpleName: a [144,145]     ReturnStatement [156,164]
action: === delete-node --- MethodDeclaration [87,170] ===

It seems GTD treat test2's method which named test as a brand new one and not the modification on example1's method.

I don't know whether it is a bug but the output like this is not normal.

Apart from this confusing output, I want to know is there any way to get the insertion position in the old code(when comparing old code and new code ) when encoutered with an insert-tree action.

Now, I get the insertion position by:

  1. Parsing the output string to get the node's start&end position like extract TypeDeclaration [0,172] at 4 from === insert-node --- MethodDeclaration [87,214] to TypeDeclaration [0,172] at 4
  2. Find it in the compilation unit by using NodeFiner method of JDT.

It is a little miscellaneous and may have more potential bugs. So I want to know is there any better way to do this.

jrfaller commented 1 year ago

Hi!

I cannot reproduce this problem with my version of GumTree, sorry.

W.r.t. to your question, by using GumTree's Java API you have both ASTs with the textual position of every node, would it suffice?

Cheers.

Feng-Jay commented 1 year ago

Thanks for your reply.

I tried the example again by doing this:

String srcFile = "/path/to/test1.java";
String dstFile = "/path/to/test2.java";
Tree t1 = new JdtTreeGenerator().generateFrom().file(srcFile).getRoot();
Tree t2 = new JdtTreeGenerator().generateFrom().file(dstFile).getRoot();
 Matcher defaultMatcher = new CompositeMatchers.SimpleGumtree();
MappingStore mappings  = defaultMatcher.match(t1, t2);
EditScriptGenerator editScriptGenerator = new SimplifiedChawatheScriptGenerator();
EditScript actions = editScriptGenerator.computeActions(mappings);
for(Action ac : actions){
      System.out.println("action: "+ac.toString().replace("\n"," "));
}

It seems the IF-STATMENT in second example will cheat GTD that these are two different method, like it exceeds some threshold or something else.

I have solved my problem by utilizing the textual information of AST and GTD's action outcomes.😄

Thanks!