Closed t94126 closed 5 years ago
Hi there. I'm not a contributor, but a look at the source reveals that currently, the actual AST operations are being applied using the actions directly, rather than action trees, which accumulate operations in a subtree. For example, if a node is inserted, its children are also included as insertions in the actions. But when applying the actions, you should only insert that root node (as it already contains the children). This should be the reason behind the duplicate nodes you see in the output. (core/src/main/java/com/github/gumtreediff/actions/ActionUtil.java)
public class ActionUtil {
private ActionUtil() {}
public static TreeContext apply(TreeContext context, List<Action> actions) {
for (Action a: actions) {
if (a instanceof Insert) {
Insert action = ((Insert) a);
action.getParent().insertChild(action.getNode(), action.getPosition());
} else if (a instanceof Update) {
Update action = ((Update) a);
action.getNode().setLabel(action.getValue());
} else if (a instanceof Move) {
Move action = ((Move) a);
action.getNode().getParent().getChildren().remove(action.getNode());
action.getParent().insertChild(action.getNode(), action.getPosition());
} else if (a instanceof Delete) {
Delete action = ((Delete) a);
action.getNode().getParent().getChildren().remove(action.getNode());
} else throw new RuntimeException("No such action: " + a );
}
return context;
}
}
An example of this being done correctly is in the web differ (client.diff/src/main/java/com/github/gumtreediff/client/diff/web/HtmlDiffs.java)
public void produce() throws IOException {
TreeClassifier c = new RootAndLeavesClassifier(src, dst, matcher);
TIntIntMap mappingIds = new TIntIntHashMap();
int uId = 1;
int mId = 1;
TagIndex ltags = new TagIndex();
for (ITree t: src.getRoot().getTrees()) {
if (c.getSrcMvTrees().contains(t)) {
mappingIds.put(mappings.getDst(t).getId(), mId);
ltags.addStartTag(t.getPos(), String.format(ID_SPAN, uId++));
ltags.addTags(t.getPos(), String.format(
SRC_MV_SPAN, "token mv", mId++, tooltip(src, t)), t.getEndPos(), END_SPAN);
}
if (c.getSrcUpdTrees().contains(t)) {
mappingIds.put(mappings.getDst(t).getId(), mId);
ltags.addStartTag(t.getPos(), String.format(ID_SPAN, uId++));
ltags.addTags(t.getPos(), String.format(
SRC_MV_SPAN, "token upd", mId++, tooltip(src, t)), t.getEndPos(), END_SPAN);
List<int[]> hunks = StringAlgorithms.hunks(t.getLabel(), mappings.getDst(t).getLabel());
for (int[] hunk: hunks)
ltags.addTags(t.getPos() + hunk[0], UPD_SPAN, t.getPos() + hunk[1], END_SPAN);
}
if (c.getSrcDelTrees().contains(t)) {
ltags.addStartTag(t.getPos(), String.format(ID_SPAN, uId++));
ltags.addTags(t.getPos(), String.format(
ADD_DEL_SPAN, "token del", tooltip(src, t)), t.getEndPos(), END_SPAN);
}
}
Here, the RootsAndLeavesClassifier does the accumulation I described above. A fix in this regard should also solve #97.
Sorry for late replying. In a short word, should the correct way be: before the insertion, check the individual actions, and ignore the child node, whose parent also in the action list. Is my understanding correct? Thanks.
I am closing this since this method has been removed (see #97). However there are now the new insert-tree and delete-tree actions that should help solve the problem, if someone decide to implement this feature!
Hi, I use gumtree to diff two python files: file1.py:
file1.py:
First, I use the code in wiki to get the actions:
Then I print the srcTC
and the dstTC
Then I apply the actions to srcTC:
In my opinion, the result should be same as dstTrc, since it is the result by applying generated action to srcTC. However, following is what I get:
Do I misuse some function or is it a bug in project? Thanks.