All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
fr.inria.coming.repairability.repairtools.Nopol Maven / Gradle / Ivy
package fr.inria.coming.repairability.repairtools;
import fr.inria.coming.changeminer.analyzer.instancedetector.ChangePatternInstance;
import fr.inria.coming.changeminer.analyzer.patternspecification.ChangePatternSpecification;
import fr.inria.coming.changeminer.entity.IRevision;
import fr.inria.coming.changeminer.util.PatternXMLParser;
import fr.inria.coming.repairability.models.ASTData;
import fr.inria.coming.utils.ASTInfoResolver;
import gumtree.spoon.diff.Diff;
import gumtree.spoon.diff.operations.DeleteOperation;
import gumtree.spoon.diff.operations.InsertOperation;
import gumtree.spoon.diff.operations.MoveOperation;
import gumtree.spoon.diff.operations.Operation;
import gumtree.spoon.diff.operations.UpdateOperation;
import spoon.reflect.code.CtBlock;
import spoon.reflect.code.CtIf;
import spoon.reflect.declaration.CtElement;
import spoon.reflect.path.CtRole;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.github.gumtreediff.actions.model.Delete;
import com.github.gumtreediff.actions.model.Insert;
import com.github.gumtreediff.matchers.MappingStore;
import com.github.gumtreediff.tree.ITree;
public class Nopol extends AbstractRepairTool {
private static final String IF_UPD_SHALLOW_PATTERN = "if_condition_upd_shallow";
private static final String IF_UPD_DEEP_PATTERN = "if_condition_upd_deep";
private static final String IF_INS_SHALLOW_PATTERN = "if_condition_ins_shallow";
private static final String IF_INS_DEEP_PATTERN = "if_condition_ins_deep";
private static final String[] patternFileNames = { "if_upd_d.xml", "if_upd_s.xml", "if_ins_s.xml", "if_ins_d.xml" };
/**
* Encodes the search space of Nopol
*
* @return a List of ChangePatternSpecifications that are supposed to be mined
* by PatternInstanceAnalyzer
*/
@Override
protected List readPatterns() {
List patterns = new ArrayList<>();
for (String fileName : patternFileNames) {
patterns.add(PatternXMLParser.parseFile(getPathFromResources(fileName)));
}
return patterns;
}
/**
* Certain patterns/characteristics of search-space of a repair tool can't be
* represented by ChangePatternSpecification This filter is supposed to
* delete/remove such instances from the results given by
* PatternInstanceAnalyser.
*
* @param patternInstance
* @param revision
* @param diff
* @return
*/
@Override
public boolean filter(ChangePatternInstance instance, IRevision revision, Diff diff) {
String patternType = instance.getPattern().getName().split(File.pathSeparator)[1];
if (patternType.startsWith(IF_UPD_DEEP_PATTERN)) {
CtElement srcRootNode = null, dstCondition = null;
Operation op = instance.getActions().get(0);
if (op instanceof UpdateOperation) {
CtElement srcNode = op.getSrcNode(), dstNode = op.getDstNode();
dstCondition = getWrapperIfConditoin(dstNode);
if (dstCondition == null) {
return false;
}
srcRootNode = ASTInfoResolver.getRootNode(srcNode);
} else if (op instanceof MoveOperation) {
// FIXME: move operations should be handled as well.
return false;
} else if (op instanceof InsertOperation) {
dstCondition = getWrapperIfConditoin(op.getSrcNode());
ITree dstConditionParentTree = (ITree) dstCondition.getParent().getMetadata("gtnode");
MappingStore mapping = diff.getMappingsComp();
if (!mapping.hasDst(dstConditionParentTree))
return false;
CtElement srcNode = (CtElement) mapping.getSrc(dstConditionParentTree).getMetadata("spoon_object");
srcRootNode = ASTInfoResolver.getRootNode(srcNode);
} else if (op instanceof DeleteOperation) {
CtElement srcCondition = getWrapperIfConditoin(op.getSrcNode());
ITree srcConditionTree = (ITree) srcCondition.getMetadata("gtnode");
MappingStore mapping = diff.getMappingsComp();
if (mapping.hasSrc(srcConditionTree)) {
dstCondition = (CtElement) mapping.getDst(srcConditionTree).getMetadata("spoon_object");
} else if (mapping.hasSrc(srcConditionTree.getParent())) {
CtElement dstConditionParent = (CtElement) mapping.getDst(srcConditionTree.getParent())
.getMetadata("spoon_object");
if (dstConditionParent instanceof CtIf) {
dstCondition = ((CtIf) dstConditionParent).getCondition();
} else {
return false;
}
} else {
return false;
}
srcRootNode = ASTInfoResolver.getRootNode(op.getSrcNode());
} else {
return false;
}
return new ASTData(srcRootNode).canNopolGenerateCondition(dstCondition);
} else if (patternType.startsWith(IF_INS_SHALLOW_PATTERN) || patternType.startsWith(IF_INS_DEEP_PATTERN)) {
Operation insertOp = getInsertAction(instance);
CtIf insertedIf = (CtIf) insertOp.getSrcNode();
if (insertedIf.getElseStatement() != null)
return false;
CtElement srcRoot = null, dstRoot = ASTInfoResolver.getRootNode(insertedIf);
ITree dstRootTree = (ITree) dstRoot.getMetadata("gtnode");
MappingStore mapping = diff.getMappingsComp();
if (mapping.hasDst(dstRootTree)) {
srcRoot = (CtElement)mapping.getSrc(dstRootTree)
.getMetadata("spoon_object");
} else {
return false;
}
CtElement dstCondition = insertedIf.getCondition();
return new ASTData(srcRoot).canNopolGenerateCondition(dstCondition);
} else if (patternType.startsWith(IF_UPD_SHALLOW_PATTERN)) {
Operation op = instance.getActions().get(0);
CtElement srcRootNode = ASTInfoResolver.getRootNode(op.getSrcNode()), dstNode = op.getDstNode();
return new ASTData(srcRootNode).canNopolGenerateCondition(dstNode);
}
return false;
}
@Override
protected Set getInstanceCoveredNodes(ChangePatternInstance instance, Diff diff) {
String patternType = instance.getPattern().getName().split(File.pathSeparator)[1];
if (patternType.startsWith(IF_UPD_DEEP_PATTERN)) {
Set res = new HashSet();
Operation op = instance.getActions().get(0);
CtElement dstCondition = null, srcCondition = null;
if (op instanceof InsertOperation || op instanceof UpdateOperation) {
dstCondition = op instanceof InsertOperation ? getWrapperIfConditoin(op.getSrcNode())
: getWrapperIfConditoin(op.getDstNode());
res.add(dstCondition);
ITree dstConditionTree = (ITree) dstCondition.getMetadata("gtnode");
MappingStore mapping = diff.getMappingsComp();
if (mapping.hasDst(dstConditionTree)) {
res.add((CtElement) mapping.getSrc(dstConditionTree).getMetadata("spoon_object"));
} else if (mapping.hasDst(dstConditionTree.getParent())) {
CtElement srcConditionParent = (CtElement) mapping.getSrc(dstConditionTree.getParent())
.getMetadata("spoon_object");
if (srcConditionParent instanceof CtIf) {
res.add(((CtIf) srcConditionParent).getCondition());
}
}
} else if (op instanceof DeleteOperation) {
srcCondition = getWrapperIfConditoin(op.getSrcNode());
res.add(srcCondition);
ITree srcConditionTree = (ITree) srcCondition.getMetadata("gtnode");
MappingStore mapping = diff.getMappingsComp();
if (mapping.hasSrc(srcConditionTree)) {
res.add((CtElement) mapping.getDst(srcConditionTree).getMetadata("spoon_object"));
} else if (mapping.hasSrc(srcConditionTree.getParent())) {
CtElement dstConditionParent = (CtElement) mapping.getDst(srcConditionTree.getParent())
.getMetadata("spoon_object");
if (dstConditionParent instanceof CtIf) {
res.add(((CtIf) dstConditionParent).getCondition());
}
}
}
return res;
} else if (patternType.startsWith(IF_UPD_SHALLOW_PATTERN)) {
Operation op = instance.getActions().get(0);
Set res = new HashSet();
res.add(op.getSrcNode());
res.add(op.getDstNode());
return res;
}
return super.getInstanceCoveredNodes(instance, diff);
}
@Override
public List filterSelectedInstances(List lst, Diff diff) {
Map instanceToCoveredNodes = new HashMap<>();
List ret = new ArrayList<>();
for (ChangePatternInstance instance : lst) {
if (instance.getPattern().getName().contains(IF_UPD_SHALLOW_PATTERN)
|| instance.getPattern().getName().contains(IF_INS_SHALLOW_PATTERN)) {
ret.add(instance);
instanceToCoveredNodes.put(instance, getInstanceCoveredNodes(instance, diff));
}
}
for (ChangePatternInstance instance : lst) {
if (instance.getPattern().getName().contains(IF_INS_DEEP_PATTERN)) {
List changedNodes = new ArrayList<>();
changedNodes.add(instance.getActions().get(0).getSrcNode());
if (instance.getActions().get(0).getDstNode() != null)
changedNodes.add(instance.getActions().get(0).getDstNode());
changedNodes.add(instance.getActions().get(1).getSrcNode());
if (instance.getActions().get(1).getDstNode() != null)
changedNodes.add(instance.getActions().get(1).getDstNode());
updateSelectedInstances(instanceToCoveredNodes, ret, instance, changedNodes, diff);
}
}
for (ChangePatternInstance instance : lst) {
if (instance.getPattern().getName().contains(IF_UPD_DEEP_PATTERN)) {
List changedNodes = new ArrayList<>();
changedNodes.add(instance.getActions().get(0).getSrcNode());
if (instance.getActions().get(0).getDstNode() != null)
changedNodes.add(instance.getActions().get(0).getDstNode());
updateSelectedInstances(instanceToCoveredNodes, ret, instance, changedNodes, diff);
}
}
return ret;
}
@Override
public boolean coversTheWholeDiff(ChangePatternInstance instance, Diff diff) {
String patternType = instance.getPattern().getName().split(File.pathSeparator)[1];
CtElement instanceInsretedNode = null;
if (patternType.startsWith(IF_INS_SHALLOW_PATTERN) || patternType.startsWith(IF_INS_DEEP_PATTERN)) {
for (Operation op : instance.getActions()) {
if (op instanceof InsertOperation) {
instanceInsretedNode = op.getSrcNode();
}
}
}
Set instanceNodes = getInstanceCoveredNodes(instance, diff);
for (Operation diffOperation : diff.getRootOperations()) {
if (diffOperation instanceof InsertOperation) {
CtElement opInsertedNode = diffOperation.getSrcNode();
if (opInsertedNode instanceof CtBlock && instanceInsretedNode != null
&& opInsertedNode == instanceInsretedNode.getParent()) {
// Bug in Gumtree-diff?
continue;
}
}
boolean found = coveredByInstanceNodes(instance, instanceNodes, diffOperation);
if (found == false)
return false;
}
return true;
}
private void updateSelectedInstances(Map instanceToCoveredNodes,
List ret, ChangePatternInstance instance, Collection changedNodes,
Diff diff) {
boolean addedBefore = false;
for (ChangePatternInstance existingInstance : ret) {
Set instanceCoveredNodes = instanceToCoveredNodes.get(existingInstance);
for (CtElement changedNode : changedNodes) {
if (coveredByInstanceNodes(instanceCoveredNodes, changedNode)) {
addedBefore = true;
break;
}
}
if (addedBefore)
break;
}
if (!addedBefore) {
ret.add(instance);
instanceToCoveredNodes.put(instance, getInstanceCoveredNodes(instance, diff));
}
}
private CtElement getWrapperIfConditoin(CtElement node) {
List pathToRoot = ASTInfoResolver.getPathToRootNode(node);
for (int i = pathToRoot.size() - 1; i >= 0; i--) {
if (pathToRoot.get(i).getRoleInParent().equals(CtRole.CONDITION) && pathToRoot.get(i - 1) instanceof CtIf) {
return pathToRoot.get(i);
}
}
return null;
}
private Operation getInsertAction(ChangePatternInstance instance) {
String patternType = instance.getPattern().getName().split(File.pathSeparator)[1];
if(!patternType.startsWith(IF_INS_SHALLOW_PATTERN) && !patternType.startsWith(IF_INS_DEEP_PATTERN)) {
return null;
}
Operation insOp = instance.getActions().get(0) instanceof InsertOperation ? instance.getActions().get(0)
: instance.getActions().get(1);
return insOp;
}
}