Skip to content

Commit c9a116f

Browse files
committed
Fix for tsantalis#958
1 parent e42d49c commit c9a116f

File tree

2 files changed

+254
-1
lines changed

2 files changed

+254
-1
lines changed

src/main/java/org/refactoringminer/astDiff/matchers/statement/LeafMatcher.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import com.github.gumtreediff.tree.Tree;
77
import com.github.gumtreediff.utils.Pair;
88
import gr.uom.java.xmi.decomposition.AbstractCodeMapping;
9+
import org.refactoringminer.astDiff.matchers.vanilla.FixedLeafMoveMatcherThetaE;
910
import org.refactoringminer.astDiff.utils.Constants;
1011
import org.refactoringminer.astDiff.models.ExtendedMultiMappingStore;
1112
import org.refactoringminer.astDiff.matchers.TreeMatcher;
@@ -156,7 +157,7 @@ public MoveOptimizedIsomorphic() {
156157
, new LcsOptMatcherThetaB()
157158
, new UnmappedLeavesMatcherThetaC()
158159
, new InnerNodesMatcherThetaD()
159-
, new LeafMoveMatcherThetaE()
160+
, new FixedLeafMoveMatcherThetaE()
160161
, new SafeCrossMoveMatcherThetaF()
161162
);
162163
}
Lines changed: 252 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,252 @@
1+
package org.refactoringminer.astDiff.matchers.vanilla;
2+
3+
import com.github.gumtreediff.matchers.Matcher;
4+
import java.util.Collections;
5+
import java.util.Comparator;
6+
import java.util.LinkedList;
7+
import java.util.List;
8+
9+
import com.github.gumtreediff.matchers.Mapping;
10+
import com.github.gumtreediff.matchers.MappingStore;
11+
import com.github.gumtreediff.tree.Tree;
12+
13+
/**
14+
* This implements the unmapped leaves optimization (Theta C), the inner node
15+
* repair optimization (Theta D) and the leaf move optimization (Theta E).
16+
*/
17+
public class FixedLeafMoveMatcherThetaE implements Matcher {
18+
19+
private Tree src;
20+
private Tree dst;
21+
private MappingStore mappings;
22+
23+
@Override
24+
public MappingStore match(Tree src, Tree dst, MappingStore mappings) {
25+
this.src = src;
26+
this.dst = dst;
27+
this.mappings = mappings;
28+
thetaE();
29+
return mappings;
30+
}
31+
32+
private class MappingComparator implements Comparator<Mapping> {
33+
34+
@Override
35+
public int compare(Mapping o1, Mapping o2) {
36+
37+
int posO1 = o1.first.getMetrics().position;
38+
int posO2 = o2.first.getMetrics().position;
39+
if (posO1 != posO2) {
40+
return Integer.compare(posO1, posO2);
41+
}
42+
43+
return Integer.compare(o1.second.getMetrics().position, o2.second.getMetrics().position);
44+
}
45+
46+
}
47+
48+
private void thetaE() {
49+
LinkedList<Mapping> workList = new LinkedList<>();
50+
LinkedList<Mapping> workListTmp = null;
51+
LinkedList<Mapping> changeMap = new LinkedList<>();
52+
53+
for (Mapping pair : mappings.asSet()) {
54+
if (pair.first.isLeaf() && pair.second.isLeaf()) {
55+
if (!pair.first.getLabel().equals(pair.second.getLabel())) {
56+
workList.add(pair);
57+
}
58+
}
59+
60+
}
61+
while (!workList.isEmpty()) {
62+
Collections.sort(workList, new FixedLeafMoveMatcherThetaE.MappingComparator());
63+
workListTmp = new LinkedList<>();
64+
for (Mapping pair : workList) {
65+
Tree firstParent = pair.first.getParent();
66+
if (!mappings.isDstMapped(firstParent)) {
67+
continue;
68+
}
69+
Tree secondParent = mappings.getDstForSrc(pair.first.getParent());
70+
reevaluateLeaves(firstParent, secondParent, pair, changeMap);
71+
}
72+
Collections.sort(changeMap, new FixedLeafMoveMatcherThetaE.MappingComparator());
73+
for (Mapping entry : changeMap) {
74+
if (mappings.areBothUnmapped(entry.first, entry.second)) {
75+
mappings.addMapping(entry.first, entry.second);
76+
}
77+
if (!entry.first.getLabel().equals(entry.second.getLabel()) && entry.first.isLeaf()
78+
&& entry.second.isLeaf()) {
79+
workListTmp.add(new Mapping(entry.first, entry.second));
80+
}
81+
}
82+
changeMap.clear();
83+
workList = workListTmp;
84+
}
85+
86+
workList = new LinkedList<>();
87+
workListTmp = null;
88+
89+
for (Mapping pair : mappings.asSet()) {
90+
if (pair.first.isLeaf() && pair.second.isLeaf()) {
91+
if (!pair.first.getLabel().equals(pair.second.getLabel())) {
92+
workList.add(pair);
93+
}
94+
}
95+
96+
}
97+
while (!workList.isEmpty()) {
98+
Collections.sort(workList, new FixedLeafMoveMatcherThetaE.MappingComparator());
99+
workListTmp = new LinkedList<>();
100+
for (Mapping pair : workList) {
101+
Tree firstParent = pair.first.getParent();
102+
Tree secondParent = pair.second.getParent();
103+
reevaluateLeaves(firstParent, secondParent, pair, changeMap);
104+
}
105+
Collections.sort(changeMap, new FixedLeafMoveMatcherThetaE.MappingComparator());
106+
for (Mapping entry : changeMap) {
107+
if (mappings.areBothUnmapped(entry.first, entry.second)) {
108+
mappings.addMapping(entry.first, entry.second);
109+
}
110+
if (!entry.first.getLabel().equals(entry.second.getLabel()) && entry.first.isLeaf()
111+
&& entry.second.isLeaf()) {
112+
workListTmp.add(new Mapping(entry.first, entry.second));
113+
}
114+
}
115+
changeMap.clear();
116+
workList = workListTmp;
117+
}
118+
}
119+
120+
private void reevaluateLeaves(Tree firstParent, Tree secondParent, Mapping pair, List<Mapping> changeMap) {
121+
122+
int count = 0;
123+
Tree foundDstNode = null;
124+
Tree foundPosDstNode = null;
125+
int pos = firstParent.getChildren().indexOf(pair.first);
126+
127+
for (int i = 0; i < secondParent.getChildren().size(); i++) {
128+
Tree child = secondParent.getChildren().get(i);
129+
if (child.getType() == pair.first.getType() && child.getLabel().equals(pair.first.getLabel())) {
130+
count++;
131+
foundDstNode = child;
132+
if (i == pos) {
133+
foundPosDstNode = child;
134+
}
135+
}
136+
}
137+
Mapping addedMappingKey = null;
138+
139+
if ((count == 1 && foundDstNode != null) || foundPosDstNode != null) {
140+
if (count != 1 && foundPosDstNode != null) {
141+
foundDstNode = foundPosDstNode;
142+
}
143+
if (mappings.isDstMapped(foundDstNode)) {
144+
145+
Tree foundSrc = mappings.getSrcForDst(foundDstNode);
146+
if (!foundSrc.getLabel().equals(foundDstNode.getLabel())) {
147+
mappings.removeMapping(pair.first, pair.second);
148+
mappings.removeMapping(foundSrc, foundDstNode);
149+
changeMap.add(new Mapping(pair.first, foundDstNode));
150+
addedMappingKey = new Mapping(foundSrc, foundDstNode);
151+
if (foundDstNode != pair.second && foundSrc != pair.first) {
152+
changeMap.add(new Mapping(foundSrc, pair.second));
153+
}
154+
}
155+
} else {
156+
157+
mappings.removeMapping(pair.first, pair.second);
158+
if (pair.first.getLabel().equals(foundDstNode.getLabel())) {
159+
LinkedList<Mapping> toRemove = new LinkedList<>();
160+
for (Mapping mapPair : changeMap) {
161+
if (mapPair.first == pair.first) {
162+
if (!mapPair.first.getLabel().equals(mapPair.second.getLabel())) {
163+
toRemove.add(mapPair);
164+
}
165+
} else if (mapPair.second == foundDstNode) {
166+
if (!mapPair.first.getLabel().equals(mapPair.second.getLabel())) {
167+
toRemove.add(mapPair);
168+
}
169+
}
170+
}
171+
changeMap.removeAll(toRemove);
172+
}
173+
changeMap.add(new Mapping(pair.first, foundDstNode));
174+
for (Tree child : firstParent.getChildren()) {
175+
if (child.isLeaf() && !mappings.isDstMapped(child) && child.getType() == pair.second.getType()
176+
&& child.getLabel().equals(pair.second.getLabel())) {
177+
Tree dstForSrc = mappings.getDstForSrc(child);
178+
if (dstForSrc != null)
179+
mappings.removeMapping(child, dstForSrc);
180+
Tree srcForDst = mappings.getSrcForDst(pair.second);
181+
if (srcForDst != null)
182+
mappings.removeMapping(srcForDst, pair.second);
183+
mappings.addMapping(child, pair.second);
184+
break;
185+
}
186+
}
187+
}
188+
}
189+
Tree foundSrcNode = null;
190+
Tree foundPosSrcNode = null;
191+
pos = secondParent.getChildren().indexOf(pair.second);
192+
for (int i = 0; i < firstParent.getChildren().size(); i++) {
193+
Tree child = firstParent.getChildren().get(i);
194+
if (child.getType() == pair.second.getType() && child.getLabel().equals(pair.second.getLabel())) {
195+
count++;
196+
foundSrcNode = child;
197+
if (i == pos) {
198+
foundPosSrcNode = child;
199+
}
200+
}
201+
}
202+
if ((count == 1 && foundSrcNode != null) || foundPosSrcNode != null) {
203+
if (count != 1 && foundPosSrcNode != null) {
204+
foundSrcNode = foundPosSrcNode;
205+
} else if (foundSrcNode == null) {
206+
foundSrcNode = foundPosSrcNode;
207+
}
208+
if (addedMappingKey != null) {
209+
changeMap.remove(addedMappingKey);
210+
}
211+
if (mappings.isSrcMapped(foundSrcNode)) {
212+
Tree foundDst = mappings.getSrcForDst(foundSrcNode);
213+
if (foundDst != null && foundSrcNode != null && !foundDst.getLabel().equals(foundSrcNode.getLabel())) {
214+
mappings.removeMapping(pair.first, pair.second);
215+
mappings.removeMapping(foundSrcNode, foundDst);
216+
changeMap.add(new Mapping(foundSrcNode, pair.second));
217+
if (addedMappingKey == null && foundDst != null) {
218+
if (foundSrcNode != pair.first && foundDst != pair.second) {
219+
changeMap.add(new Mapping(pair.first, foundDst));
220+
}
221+
}
222+
}
223+
} else {
224+
mappings.removeMapping(pair.first, pair.second);
225+
if (foundSrcNode.getLabel().equals(pair.second.getLabel())) {
226+
LinkedList<Mapping> toRemove = new LinkedList<>();
227+
for (Mapping mapPair : changeMap) {
228+
if (mapPair.first == foundSrcNode) {
229+
if (!mapPair.first.getLabel().equals(mapPair.second.getLabel())) {
230+
toRemove.add(mapPair);
231+
}
232+
} else if (mapPair.second == pair.second) {
233+
if (!mapPair.first.getLabel().equals(mapPair.second.getLabel())) {
234+
toRemove.add(mapPair);
235+
}
236+
}
237+
}
238+
changeMap.removeAll(toRemove);
239+
}
240+
changeMap.add(new Mapping(foundSrcNode, pair.second));
241+
for (Tree child : secondParent.getChildren()) {
242+
if (child.isLeaf() && !mappings.isSrcMapped(child) && child.getType() == pair.first.getType()
243+
&& child.getLabel().equals(pair.first.getLabel())) {
244+
mappings.addMapping(pair.first, child);
245+
break;
246+
}
247+
}
248+
}
249+
}
250+
}
251+
252+
}

0 commit comments

Comments
 (0)