Skip to content

Commit

Permalink
Modify the TreeMatcher interface and update the subclasses accordingly
Browse files Browse the repository at this point in the history
  • Loading branch information
pouryafard75 committed Apr 28, 2023
1 parent b58854e commit b4fe6ce
Show file tree
Hide file tree
Showing 7 changed files with 129 additions and 139 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public class TreeMatcherTest {
public void testMappings(Tree srcTree, Tree dstTree, String expectedMappings, String folderPath)
{
ExtendedMultiMappingStore mappings = new ExtendedMultiMappingStore(srcTree,dstTree);
new LeafMatcher(true).match(srcTree,dstTree,null,mappings);
new LeafMatcher(true).match(srcTree,dstTree,mappings);
try {
String actual = MappingExportModel.exportString(mappings);
assertEquals(expectedMappings,actual);
Expand Down
55 changes: 34 additions & 21 deletions src/org/refactoringminer/astDiff/matchers/BasicTreeMatcher.java
Original file line number Diff line number Diff line change
@@ -1,41 +1,54 @@
package org.refactoringminer.astDiff.matchers;

import com.github.gumtreediff.matchers.Mapping;
import com.github.gumtreediff.matchers.MappingStore;
import com.github.gumtreediff.matchers.SimilarityMetrics;
import com.github.gumtreediff.tree.Tree;
import com.github.gumtreediff.tree.TreeUtils;
import com.github.gumtreediff.tree.Type;
import com.github.gumtreediff.utils.SequenceAlgorithms;
import gr.uom.java.xmi.decomposition.AbstractCodeFragment;
import gr.uom.java.xmi.decomposition.AbstractCodeMapping;
import com.github.gumtreediff.utils.Pair;
import org.refactoringminer.astDiff.utils.TreeUtilFunctions;

import java.util.*;
import java.util.ArrayList;
import java.util.List;

import static org.refactoringminer.astDiff.matchers.LeafMatcher.extracted;

/**
* @author Pourya Alikhani Fard [email protected]
*/
public class BasicTreeMatcher implements TreeMatcher {

@Override
public void match(Tree src, Tree dst, AbstractCodeMapping abstractCodeMapping, ExtendedMultiMappingStore mappingStore) {
public void match(Tree src, Tree dst, ExtendedMultiMappingStore mappingStore) {
basicMatcher(src, dst, mappingStore);
}
@Override
public void match(Tree src, Tree dst, AbstractCodeFragment abstractCodeFragment1, AbstractCodeFragment abstractCodeFragment2, ExtendedMultiMappingStore mappingStore) {
basicMatcher(src, dst, mappingStore);
private void basicMatcher(Tree src, Tree dst, ExtendedMultiMappingStore mappingStore) {
mappingStore.add(apply(src, dst));
}


private void basicMatcher(Tree src, Tree dst, ExtendedMultiMappingStore mappingStore) {
try {
MappingStore match = extracted(src, dst);
mappingStore.add(match);
public MappingStore apply(Tree src, Tree dst) {
MappingStore match;
match = new CustomGreedy(0, false).match(src, dst);
CustomBottomUpMatcher customBottomUpMatcher = new CustomBottomUpMatcher();
customBottomUpMatcher.match(src, dst, match);
List<Pair<Tree, Tree>> removeList = new ArrayList<>();
for (Mapping mapping : match) {
if (mapping.first.getType().name.equals(Constants.METHOD_INVOCATION)) {
Tree srcMethodName = TreeUtilFunctions.findChildByType(mapping.first, Constants.SIMPLE_NAME);
Tree dstMethodName = TreeUtilFunctions.findChildByType(mapping.second, Constants.SIMPLE_NAME);
if (srcMethodName == null || dstMethodName == null) continue;
if (!srcMethodName.getLabel().equals(dstMethodName.getLabel())) {
Tree srcMethodInvocationReceiver = TreeUtilFunctions.findChildByType(mapping.first, Constants.METHOD_INVOCATION_RECEIVER);
Tree dstMethodInvocationReceiver = TreeUtilFunctions.findChildByType(mapping.second, Constants.METHOD_INVOCATION_RECEIVER);
if ((srcMethodInvocationReceiver == null && dstMethodInvocationReceiver != null)
||
(srcMethodInvocationReceiver != null && dstMethodInvocationReceiver == null)) {
removeList.add(new Pair<>(mapping.first, mapping.second));
removeList.add(new Pair<>(srcMethodName, dstMethodName));
break;
}
}
}
}
catch (Exception exception)
{
System.out.println(exception.getMessage());
for (Pair<Tree, Tree> treeTreePair : removeList) {
match.removeMapping(treeTreePair.first, treeTreePair.second);
}
return match;
}
}
63 changes: 22 additions & 41 deletions src/org/refactoringminer/astDiff/matchers/CompositeMatcher.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,67 +11,48 @@
/**
* @author Pourya Alikhani Fard [email protected]
*/
public class CompositeMatcher implements TreeMatcher {
public class CompositeMatcher extends BasicTreeMatcher implements TreeMatcher {

private final CompositeStatementObject fragment1;
private final CompositeStatementObject fragment2;

public CompositeMatcher(AbstractCodeMapping abstractCodeMapping) {
CompositeStatementObjectMapping compositeStatementObjectMapping = (CompositeStatementObjectMapping) abstractCodeMapping;
fragment1 = (CompositeStatementObject) compositeStatementObjectMapping.getFragment1();
fragment2 = (CompositeStatementObject) compositeStatementObjectMapping.getFragment2();
}

public CompositeMatcher(CompositeStatementObject fragment1, CompositeStatementObject fragment2) {
this.fragment1 = fragment1;
this.fragment2 = fragment2;
}

@Override
public void match(Tree src, Tree dst, AbstractCodeMapping abstractCodeMapping, ExtendedMultiMappingStore mappingStore) {
public void match(Tree src, Tree dst, ExtendedMultiMappingStore mappingStore) {
String labeled = Constants.LABELED_STATEMENT;
if (src.getType().name.equals(labeled) && dst.getType().name.equals(labeled))
mappingStore.addMapping(src.getChild(0),dst.getChild(0));
else
compositeMatcher(src,dst,abstractCodeMapping,mappingStore);
}

@Override
public void match(Tree src, Tree dst, AbstractCodeFragment st1, AbstractCodeFragment st2, ExtendedMultiMappingStore mappingStore) {
if ((st1 instanceof CompositeStatementObject) && (st2 instanceof CompositeStatementObject)) {
compositeMatcher(src, dst, (CompositeStatementObject) st1, (CompositeStatementObject) st2, mappingStore);
return;
}
//Corner cases;
if (!(st1 instanceof CompositeStatementObject) &&
(st2 instanceof CompositeStatementObject)) {
CompositeStatementObject fragment2 = (CompositeStatementObject) st2;
for (AbstractExpression expression : fragment2.getExpressions()) {
Tree dstExpTree = TreeUtilFunctions.findByLocationInfo(dst, expression.getLocationInfo());
new LeafMatcher(false).match(src,dstExpTree,st1,expression,mappingStore);
}
} else if ((st1 instanceof CompositeStatementObject) &&
!(st2 instanceof CompositeStatementObject)) {
CompositeStatementObject fragment1 = (CompositeStatementObject) st1;
for (AbstractExpression expression : fragment1.getExpressions()) {
Tree srcExpTree = TreeUtilFunctions.findByLocationInfo(src, expression.getLocationInfo());
new LeafMatcher(false).match(srcExpTree,dst,expression,st2,mappingStore);
}
}

process(src,dst,mappingStore);
}

private void compositeMatcher(Tree src, Tree dst, AbstractCodeMapping abstractCodeMapping, ExtendedMultiMappingStore mappingStore) {
CompositeStatementObjectMapping compositeStatementObjectMapping = (CompositeStatementObjectMapping) abstractCodeMapping;
CompositeStatementObject fragment1 = (CompositeStatementObject) compositeStatementObjectMapping.getFragment1();
CompositeStatementObject fragment2 = (CompositeStatementObject) compositeStatementObjectMapping.getFragment2();
process(src, dst, mappingStore, fragment1, fragment2);
}

private void process(Tree src, Tree dst, ExtendedMultiMappingStore mappingStore, CompositeStatementObject fragment1, CompositeStatementObject fragment2) {
private void process(Tree src, Tree dst, ExtendedMultiMappingStore mappingStore) {
Map<Tree, Tree> cpyToSrc = new HashMap<>();
Map<Tree, Tree> cpyToDst = new HashMap<>();
Tree srcFakeTree = makeFakeTree(src,fragment1, cpyToSrc);
Tree dstFakeTree = makeFakeTree(dst,fragment2, cpyToDst);
ExtendedMultiMappingStore tempMapping = new ExtendedMultiMappingStore(null,null);
new BasicTreeMatcher().match(srcFakeTree,dstFakeTree,null,tempMapping);
super.match(srcFakeTree,dstFakeTree,tempMapping);
for(Mapping mapping : tempMapping) {
if (mapping.first == srcFakeTree) continue;
mappingStore.addMapping(cpyToSrc.get(mapping.first), cpyToDst.get(mapping.second));
}
}

private void compositeMatcher(Tree src, Tree dst, CompositeStatementObject fragment1, CompositeStatementObject fragment2, ExtendedMultiMappingStore mappingStore) {
process(src, dst, mappingStore, fragment1, fragment2);
private void compositeMatcher(Tree src, Tree dst, ExtendedMultiMappingStore mappingStore) {
process(src, dst, mappingStore);
}

private Tree makeFakeTree(Tree tree, CompositeStatementObject fragment, Map<Tree, Tree> cpyMap) {
private static Tree makeFakeTree(Tree tree, CompositeStatementObject fragment, Map<Tree, Tree> cpyMap) {
Tree cpy = TreeUtilFunctions.makeDefaultTree(tree);
cpyMap.put(cpy,tree);
for (AbstractExpression abstractExpression : fragment.getExpressions()) {
Expand Down
44 changes: 44 additions & 0 deletions src/org/refactoringminer/astDiff/matchers/GeneralTreeMatcher.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package org.refactoringminer.astDiff.matchers;

import com.github.gumtreediff.tree.Tree;
import gr.uom.java.xmi.decomposition.AbstractCodeFragment;
import gr.uom.java.xmi.decomposition.AbstractExpression;
import gr.uom.java.xmi.decomposition.CompositeStatementObject;
import org.refactoringminer.astDiff.utils.TreeUtilFunctions;

/* Created by pourya on 2023-04-25 1:08 p.m. */
public class GeneralTreeMatcher extends BasicTreeMatcher implements TreeMatcher {
AbstractCodeFragment st1;
AbstractCodeFragment st2;

public GeneralTreeMatcher(AbstractCodeFragment st1, AbstractCodeFragment st2) {
this.st1 = st1;
this.st2 = st2;
}
@Override
public void match(Tree src, Tree dst, ExtendedMultiMappingStore mappingStore) {
if ((st1 instanceof CompositeStatementObject) && (st2 instanceof CompositeStatementObject)) {
new CompositeMatcher((CompositeStatementObject) st1, (CompositeStatementObject) st2)
.match(src, dst, mappingStore);
return;
}
//Corner cases;
if (!(st1 instanceof CompositeStatementObject) &&
(st2 instanceof CompositeStatementObject)) {
CompositeStatementObject fragment2 = (CompositeStatementObject) st2;
for (AbstractExpression expression : fragment2.getExpressions()) {
Tree dstExpTree = TreeUtilFunctions.findByLocationInfo(dst, expression.getLocationInfo());
new LeafMatcher(false).match(src,dstExpTree,mappingStore);
}
} else if ((st1 instanceof CompositeStatementObject) &&
!(st2 instanceof CompositeStatementObject)) {
CompositeStatementObject fragment1 = (CompositeStatementObject) st1;
for (AbstractExpression expression : fragment1.getExpressions()) {
Tree srcExpTree = TreeUtilFunctions.findByLocationInfo(src, expression.getLocationInfo());
new LeafMatcher(false).match(srcExpTree,dst,mappingStore);
}
}

}

}
51 changes: 3 additions & 48 deletions src/org/refactoringminer/astDiff/matchers/LeafMatcher.java
Original file line number Diff line number Diff line change
@@ -1,34 +1,25 @@
package org.refactoringminer.astDiff.matchers;

import com.github.gumtreediff.matchers.Mapping;
import com.github.gumtreediff.matchers.MappingStore;
import com.github.gumtreediff.tree.Tree;
import com.github.gumtreediff.utils.Pair;
import gr.uom.java.xmi.decomposition.AbstractCodeFragment;
import gr.uom.java.xmi.decomposition.AbstractCodeMapping;
import gr.uom.java.xmi.decomposition.LeafMapping;
import org.refactoringminer.astDiff.utils.TreeUtilFunctions;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
* @author Pourya Alikhani Fard [email protected]
*/
public class LeafMatcher implements TreeMatcher {
public class LeafMatcher extends BasicTreeMatcher implements TreeMatcher {
private final boolean overwrite;

public LeafMatcher(boolean overwrite) {
this.overwrite = overwrite;
}

@Override
public void match(Tree src, Tree dst, AbstractCodeMapping abstractCodeMapping, ExtendedMultiMappingStore mappingStore) {
//if (abstractCodeMapping != null)
// if (abstractCodeMapping.getFragment1() instanceof AbstractExpression || abstractCodeMapping.getFragment2() instanceof AbstractExpression)
// return;
public void match(Tree src, Tree dst, ExtendedMultiMappingStore mappingStore) {
if (src == null || dst == null) return;
Map<Tree,Tree> srcCopy = new HashMap<>();
Map<Tree,Tree> dstCopy = new HashMap<>();
Expand All @@ -41,7 +32,7 @@ public void match(Tree src, Tree dst, AbstractCodeMapping abstractCodeMapping, E
match.addMappingRecursively(prunedPair.first, prunedPair.second);
}
else {
match = extracted(prunedPair.first, prunedPair.second);
match = apply(prunedPair.first, prunedPair.second);
}
if (!overwrite)
mappingStore.addWithMaps(match, srcCopy, dstCopy);
Expand All @@ -53,42 +44,6 @@ public void match(Tree src, Tree dst, AbstractCodeMapping abstractCodeMapping, E
System.out.println(exception.getMessage());
}
}

public static MappingStore extracted(Tree src, Tree dst) {
MappingStore match;
match = new CustomGreedy(0, false).match(src, dst);
CustomBottomUpMatcher customBottomUpMatcher = new CustomBottomUpMatcher();
customBottomUpMatcher.match(src, dst, match);
List<Pair<Tree, Tree>> removeList = new ArrayList<>();
for (Mapping mapping : match) {
if (mapping.first.getType().name.equals(Constants.METHOD_INVOCATION)) {
Tree srcMethodName = TreeUtilFunctions.findChildByType(mapping.first, Constants.SIMPLE_NAME);
Tree dstMethodName = TreeUtilFunctions.findChildByType(mapping.second, Constants.SIMPLE_NAME);
if (srcMethodName == null || dstMethodName == null) continue;
if (!srcMethodName.getLabel().equals(dstMethodName.getLabel())) {
Tree srcMethodInvocationReceiver = TreeUtilFunctions.findChildByType(mapping.first, Constants.METHOD_INVOCATION_RECEIVER);
Tree dstMethodInvocationReceiver = TreeUtilFunctions.findChildByType(mapping.second, Constants.METHOD_INVOCATION_RECEIVER);
if ((srcMethodInvocationReceiver == null && dstMethodInvocationReceiver != null)
||
(srcMethodInvocationReceiver != null && dstMethodInvocationReceiver == null)) {
removeList.add(new Pair<>(mapping.first, mapping.second));
removeList.add(new Pair<>(srcMethodName, dstMethodName));
break;
}
}
}
}
for (Pair<Tree, Tree> treeTreePair : removeList) {
match.removeMapping(treeTreePair.first, treeTreePair.second);
}
return match;
}

@Override
public void match(Tree src, Tree dst, AbstractCodeFragment abstractCodeFragment1, AbstractCodeFragment abstractCodeFragment2, ExtendedMultiMappingStore mappingStore) {
this.match(src,dst, new LeafMapping(abstractCodeFragment1, abstractCodeFragment2, null, null), mappingStore);
}

public Pair<Tree,Tree> pruneTrees(Tree src, Tree dst, Map<Tree,Tree> srcCopy, Map<Tree,Tree> dstCopy) {
Tree prunedSrc = TreeUtilFunctions.deepCopyWithMapPruning(src,srcCopy);
Tree prunedDst = TreeUtilFunctions.deepCopyWithMapPruning(dst,dstCopy);
Expand Down
Loading

0 comments on commit b4fe6ce

Please sign in to comment.