Regrouper of GumTree results.

This commit is contained in:
Kui LIU
2018-02-02 21:42:12 +01:00
parent 8907fabbc7
commit deaa1dd672
13 changed files with 161 additions and 808 deletions
@@ -13,7 +13,6 @@ import edu.lu.uni.serval.gumtree.GumTreeComparer;
import edu.lu.uni.serval.gumtree.regroup.ActionFilter;
import edu.lu.uni.serval.gumtree.regroup.HierarchicalActionSet;
import edu.lu.uni.serval.gumtree.regroup.HierarchicalRegrouper;
import edu.lu.uni.serval.gumtree.regroup.SimpleTree;
import edu.lu.uni.serval.gumtree.regroup.SimplifyTree;
/**
@@ -1,9 +1,6 @@
package edu.lu.uni.serval.FixPatternParser.violations;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
@@ -13,8 +10,6 @@ import edu.lu.uni.serval.FixPatternParser.Tokenizer;
import edu.lu.uni.serval.config.Configuration;
import edu.lu.uni.serval.diffentry.DiffEntryHunk;
import edu.lu.uni.serval.diffentry.DiffEntryReader;
import edu.lu.uni.serval.gumtree.GumTreeGenerator;
import edu.lu.uni.serval.gumtree.GumTreeGenerator.GumTreeType;
import edu.lu.uni.serval.gumtree.regroup.HierarchicalActionSet;
import edu.lu.uni.serval.gumtree.regroup.HunkActionFilter;
import edu.lu.uni.serval.gumtree.regroup.SimpleTree;
@@ -29,8 +24,6 @@ import edu.lu.uni.serval.violation.code.parser.ViolationSourceCodeTree;
*/
public class FixedViolationHunkParser extends FixedViolationParser {
private static final int THRESHOLD_LINE = 3;
public String testingInfo = "";
public int nullMappingGumTreeResult = 0;
@@ -39,47 +32,31 @@ public class FixedViolationHunkParser extends FixedViolationParser {
public int nullSourceCode = 0;
public int nullMatchedDiffEntry = 0;
public int testInfos = 0;
public FixedViolationHunkParser() {
}
public FixedViolationHunkParser(File positionFile) {
setPositionFile(positionFile);
}
public String unfixedViolations = "";
@Override
public void parseFixPatterns(File prevFile, File revFile, File diffentryFile) {
List<Violation> allViolations = readViolations(prevFile, revFile);
// if (allViolations.size() >= 0) return;
// GumTree results
List<HierarchicalActionSet> actionSets = parseChangedSourceCodeWithGumTree2(prevFile, revFile);
if (this.resultType != 0) {
String type = "";
if (this.resultType == 1) {
type = "#NullGumTreeResult:";
} else if (this.resultType == 2) {
type = "#NoSourceCodeChange:";
} else if (this.resultType == 3) {
type = "#NoStatementChange:";
}
for (Violation v : allViolations) {
this.unfixedViolations += type + revFile.getName() + ":" + v.getStartLineNum() + ":" + v.getEndLineNum() + ":" + v.getViolationType() + "\n";
}
// String type = "";
// if (this.resultType == 1) {
// type = "#NullGumTreeResult:";
// } else if (this.resultType == 2) {
// type = "#NoSourceCodeChange:";
// } else if (this.resultType == 3) {
// type = "#NoStatementChange:";
// }
} else {
List<DiffEntryHunk> diffentryHunks = new DiffEntryReader().readHunks2(diffentryFile);
// Identify DiffEntry hunks by positions of violations.
List<Violation> violations = identifyFixRangeHeuristically(allViolations, diffentryHunks, revFile);
//Filter out the modify actions, which are not in the DiffEntry hunks.
HunkActionFilter hunkFilter = new HunkActionFilter();
List<Violation> selectedViolations = hunkFilter.filterActionsByModifiedRange2(violations, actionSets, revFile, prevFile);
this.unfixedViolations += hunkFilter.unfixedViolations;
this.nullMappingGumTreeResult += violations.size() - selectedViolations.size();
List<DiffEntryHunk> selectedPatchHunks = hunkFilter.filterActionsByModifiedRange2(diffentryHunks, actionSets, revFile, prevFile);
for (Violation violation : selectedViolations) {
List<HierarchicalActionSet> hunkActionSets = violation.getActionSets();
for (DiffEntryHunk patchHunk : selectedPatchHunks) {
List<HierarchicalActionSet> hunkActionSets = patchHunk.getActionSets();
// multiple UPD, and some UPD contain other UPD.
removeOverlapperdUPD(hunkActionSets);
@@ -117,43 +94,27 @@ public class FixedViolationHunkParser extends FixedViolationParser {
}
if (fixStartLine == 0 && bugStartLine == 0) {
this.unfixedViolations += "#WRONG: " + revFile.getName() + ":" + violation.getStartLineNum() + ":" + violation.getEndLineNum() + ":" + violation.getViolationType() + "\n";
this.unfixedViolations += "#WRONG: " + revFile.getName() + ":" + patchHunk.getBugLineStartNum() + ", " + patchHunk.getBuggyHunkSize() + "\n";
this.nullMappingGumTreeResult ++;
continue;
}
if (fixStartLine == 0 && bugStartLine != 0) {// pure delete actions.
// this.pureDeletions ++;
// this.unfixedViolations += "#PureDeletion:" + revFile.getName() + ":" + violation.getStartLineNum() + ":" + violation.getEndLineNum() + ":" + violation.getViolationType() + "\n";
// get the exact buggy code by violation's position. TODO later
}
// if (children.size() == 0) continue;
boolean isPureInsert = false;
if (bugStartLine == 0 && violation.getBugStartLineNum() > 0) {
bugStartLine = violation.getStartLineNum();
bugEndLine = violation.getEndLineNum();
if (bugStartLine == 0 && patchHunk.getBugLineStartNum() > 0) {
bugStartLine = patchHunk.getBugLineStartNum();
bugEndLine = bugStartLine + patchHunk.getBuggyHunkSize() - 1;
isPureInsert = true;
// continue;
}
if ((bugEndLine - bugStartLine > Configuration.HUNK_SIZE && !isPureInsert) || fixEndLine - fixStartLine > Configuration.HUNK_SIZE) {
// this.largeHunk ++;
// this.unfixedViolations += "#LargeHunk:" + revFile.getName() + ":" + violation.getStartLineNum()
// + ":" + violation.getEndLineNum() + ":" + violation.getViolationType() + "\n";
// continue;
}
// Obtain Source Code of patches from DiffEntries.
String patchSourceCode = this.readPatchSourceCode(violation, bugStartLine, bugEndLine, fixStartLine, fixEndLine);
if ("".equals(patchSourceCode)) {
patchSourceCode = getPatchSourceCode(prevFile, revFile, bugStartLine, bugEndLine, fixStartLine, fixEndLine, isPureInsert);
if ("".equals(patchSourceCode)) {
this.nullSourceCode ++;
this.unfixedViolations += "#NullSourceCode:" + revFile.getName() + ":" + violation.getStartLineNum()
+ ":" + violation.getEndLineNum() + ":" + violation.getViolationType() + "\n";
continue;
}
}
/**
* Select edit scripts for deep learning.
@@ -162,8 +123,7 @@ public class FixedViolationHunkParser extends FixedViolationParser {
// 1. First level: AST node type.
String astEditScripts = getASTEditScriptsDeepFirst(hunkActionSets, bugEndPosition, fixEndPosition);
if (astEditScripts.contains("\n") || astEditScripts.split(" ").length % 3 != 0) {
System.err.println("===+++===: " + revFile.getName() + ":" +violation.getStartLineNum() + ":" +
violation.getEndLineNum() + ":" + violation.getViolationType());
System.err.println("===+++===: " + revFile.getName() + ":" +patchHunk.getBugLineStartNum() + ", " + patchHunk.getBuggyHunkSize());
}
// 2. source code: raw tokens
// 3. abstract identifiers:
@@ -171,141 +131,82 @@ public class FixedViolationHunkParser extends FixedViolationParser {
String[] editScriptTokens = astEditScripts.split(" ");
int size = editScriptTokens.length;
if (size == 1) {
// if ("MOVMethodDeclaration".equals(astEditScripts)) {
// this.nullMappingGumTreeResult ++;
// this.unfixedViolations += "#NullMatchedGumTreeResult:" + revFile.getName() + ":" +violation.getStartLineNum() + ":" +
// violation.getEndLineNum() + ":" + violation.getViolationType() + "\n";
// continue;
// }
this.nullMappingGumTreeResult ++;
this.unfixedViolations += "#NullMatchedGumTreeResult1:" + revFile.getName() + ":" +violation.getStartLineNum() + ":" +
violation.getEndLineNum() + ":" + violation.getViolationType() + "\n";
this.unfixedViolations += "#NullMatchedGumTreeResult1:" + revFile.getName() + ":" + patchHunk.getBugLineStartNum() + ", " + patchHunk.getBuggyHunkSize() + "\n";
continue;
}
String alarmType = violation.getViolationType();
String patchPosition = "\n" + revFile.getName() + "\nPosition: " + violation.getStartLineNum() + " --> " + violation.getEndLineNum() + "\n@@ -" + bugStartLine + ", " + bugEndLine + " +" + fixStartLine + ", " + fixEndLine + "@@\n";
// String patchPosition = "\n" + "Position: " + violation.getStartLineNum() + " --> " + violation.getEndLineNum() + "\n@@ -" + bugStartLine + ", " + bugEndLine + " +" + fixStartLine + ", " + fixEndLine + "@@\n";
String info = Configuration.PATCH_SIGNAL + "\nAlarm Type :" + alarmType + "\n" + patchPosition + patchSourceCode + "\nAST Diff###:\n" + getAstEditScripts(hunkActionSets, bugEndPosition, fixEndPosition) + "\n";
// String patchPosition = "\n" + "Position: " + violation.getStartLineNum() + " --> " + violation.getEndLineNum() + "\n@@ -" + bugStartLine + ", " + bugEndLine + " +" + fixStartLine + ", " + fixEndLine + "@@\n";
// String info = Configuration.PATCH_SIGNAL + "\nAlarm Type :" + alarmType + "\n" + patchSourceCode + "\n\n";// + patchPosition + revFile.getName() + "\n";
String patchPosition = "\n" + revFile.getName() + "\n@@ -" + bugStartLine + ", " + bugEndLine + " +" + fixStartLine + ", " + fixEndLine + "@@\n";
// String info = Configuration.PATCH_SIGNAL + "\n" + patchPosition + patchHunk.getHunk() + "\nAST Diff###:\n" + getAstEditScripts(hunkActionSets, bugEndPosition, fixEndPosition) + "\n";
String info = Configuration.PATCH_SIGNAL + "\n" + patchPosition + patchHunk.getHunk() + "\nAST Diff###:\n" + getAstEditScripts(hunkActionSets) + "\n";
// if (noUpdate(editScriptTokens)) {
//
// if (!"SE_NO_SERIALVERSIONID".equals(alarmType)) {
// if (containsFiledDeclaration(hunkActionSets)) {
//// this.nullMappingGumTreeResult ++;
// this.testingInfo += info + revFile.getName() + "\n";
// this.testingInfo += "#TestingInfo: " + revFile.getName() + ":" + violation.getStartLineNum()
// + ":" + violation.getEndLineNum() + ":" + violation.getViolationType();
// this.unfixedViolations += "#TestingInfo:" + revFile.getName() + ":" + violation.getStartLineNum()
// + ":" + violation.getEndLineNum() + ":" + violation.getViolationType() + "\n";
// this.testInfos ++;
// continue;
// }
// }
//
// if ("UL_UNRELEASED_LOCK".equals(alarmType) ||
// "SF_SWITCH_NO_DEFAULT".equals(alarmType) ||
// "SF_SWITCH_FALLTHROUGH".equals(alarmType) ||
// "SE_NO_SERIALVERSIONID".equals(alarmType) ||
// "REC_CATCH_EXCEPTION".equals(alarmType) ||
// "OS_OPEN_STREAM".equals(alarmType) ||
// "NP_ALWAYS_NULL".equals(alarmType) ||
// "IS2_INCONSISTENT_SYNC".equals(alarmType) ||
// "EI_EXPOSE_REP".equals(alarmType) ) {
//
// } else if (containSpecialStmt(hunkActionSets, bugEndPosition, fixEndPosition)) {
//
// } else {
//// this.nullMappingGumTreeResult ++;
// this.testingInfo += info + revFile.getName() + "\n";
// this.testingInfo += "#TestingInfo: " + revFile.getName() + ":" + violation.getStartLineNum()
// + ":" + violation.getEndLineNum() + ":" + violation.getViolationType();
// this.unfixedViolations += "#TestingInfo:" + revFile.getName() + ":" + violation.getStartLineNum()
// + ":" + violation.getEndLineNum() + ":" + violation.getViolationType() + "\n";
// this.testInfos ++;
// continue;
// }
// }
this.patchesSourceCode += info;
this.sizes += size + "\n";
this.astEditScripts += astEditScripts + "\n";
this.violationTypes += alarmType + "\n";
// this.buggyTrees += Configuration.BUGGY_TREE_TOKEN + "\n" + simpleTree.toString() + "\n";
SimpleTree simpleTree = getBuggyCodeTree(violation, bugEndPosition, prevFile, bugStartLine, bugEndLine);
SimpleTree simpleTree = getBuggyCodeTree(patchHunk, bugEndPosition, prevFile, bugStartLine, bugEndLine);
String tokens = Tokenizer.getTokensDeepFirst(simpleTree).trim();
if ("Block Block".equals(tokens)) {
tokens = getContextTokens(patchSourceCode);
}
this.tokensOfSourceCode += tokens + "\n";
// this.actionSets += Configuration.BUGGY_TREE_TOKEN + "\n" + readActionSet(actionSet, "") + "\n";
// this.originalTree += Configuration.BUGGY_TREE_TOKEN + "\n" + actionSet.getOriginalTree().toString() + "\n";
}
}
}
private SimpleTree getBuggyCodeTree(Violation violation, int bugEndPosition, File prevFile, int bugStartLine, int bugEndLine) {
SimpleTree simpleTree = null;
private String getAstEditScripts(List<HierarchicalActionSet> hunkActionSets) {
String scripts = "";
for (HierarchicalActionSet hunkActionSet : hunkActionSets) {
scripts += hunkActionSet.toString() + "\n";
}
return scripts;
}
private SimpleTree getBuggyCodeTree(DiffEntryHunk patchHunk, int bugEndPosition, File prevFile, int bugStartLine, int bugEndLine) {
SimpleTree simpleTree = new SimpleTree();
simpleTree.setLabel("Block");
simpleTree.setNodeType("Block");
List<SimpleTree> children = new ArrayList<>();
String type = violation.getViolationType();
if ("EQ_DOESNT_OVERRIDE_EQUALS".equals(type)|| "HE_EQUALS_USE_HASHCODE".equals(type) || "HE_INHERITS_EQUALS_USE_HASHCODE".equals(type)||
"SE_NO_SUITABLE_CONSTRUCTOR".equals(type) || "RI_REDUNDANT_INTERFACES".equals(type)
||"CN_IDIOM".equals(type)||"SE_NO_SERIALVERSIONID".equals(type) || "SE_COMPARATOR_SHOULD_BE_SERIALIZABLE".equals(type)) {
// Class name level, tokens
// classStartP <= vS <= vE <= classEndP
ViolationSourceCodeTree parser = new ViolationSourceCodeTree(prevFile, violation.getStartLineNum(), violation.getEndLineNum());
ITree classNameTree = parser.getClassNameTokens();
simpleTree = new SimplifyTree().canonicalizeSourceCodeTree(classNameTree, null);
} else {
simpleTree = new SimpleTree();
simpleTree.setLabel("Block");
simpleTree.setNodeType("Block");
List<SimpleTree> children = new ArrayList<>();
int vStartLine = violation.getStartLineNum();
int vEndLine = violation.getEndLineNum();
if (bugStartLine < vStartLine && vEndLine < bugEndLine) {
ViolationSourceCodeTree parser = new ViolationSourceCodeTree(prevFile, violation.getStartLineNum(), violation.getEndLineNum());
parser.extract();
List<ITree> matchedTrees = parser.getViolationSourceCodeTrees();
if (matchedTrees.size() > 0) {
for (ITree matchedTree : matchedTrees) {
SimpleTree simpleT = new SimplifyTree().canonicalizeSourceCodeTree(matchedTree, simpleTree);
children.add(simpleT);
}
}
}
if (children.size() == 0) {
List<HierarchicalActionSet> hunkActionSets = violation.getActionSets();
/*
* Convert the ITree of buggy code to a simple tree.
* It will be used to compute the similarity.
*/
for (HierarchicalActionSet hunkActionSet : hunkActionSets) {
// TODO simplify buggy tree with buggy code.
/**
* Select edit scripts for deep learning.
* Edit scripts will be used to mine common fix patterns.
*/
// // 1. First level: AST node type.
// // 2. source code: raw tokens
// // 3. abstract identifiers:
// // 4. semi-source code:
SimplifyTree abstractIdentifier = new SimplifyTree();
abstractIdentifier.abstractTree(hunkActionSet, bugEndPosition);
SimpleTree simpleT = hunkActionSet.getSimpleTree();
if (simpleT == null) { // Failed to get the simple tree for INS actions.
continue;
}
int vStartLine = patchHunk.getBugLineStartNum();
int vEndLine = vStartLine + patchHunk.getBuggyHunkSize() + 1;
if (bugStartLine < vStartLine && vEndLine < bugEndLine) {
ViolationSourceCodeTree parser = new ViolationSourceCodeTree(prevFile, vStartLine, vEndLine);
parser.extract();
List<ITree> matchedTrees = parser.getViolationSourceCodeTrees();
if (matchedTrees.size() > 0) {
for (ITree matchedTree : matchedTrees) {
SimpleTree simpleT = new SimplifyTree().canonicalizeSourceCodeTree(matchedTree, simpleTree);
children.add(simpleT);
}
}
simpleTree.setChildren(children);
simpleTree.setParent(null);
}
if (children.size() == 0) {
List<HierarchicalActionSet> hunkActionSets = patchHunk.getActionSets();
/*
* Convert the ITree of buggy code to a simple tree.
* It will be used to compute the similarity.
*/
for (HierarchicalActionSet hunkActionSet : hunkActionSets) {
// TODO simplify buggy tree with buggy code.
/**
* Select edit scripts for deep learning.
* Edit scripts will be used to mine common fix patterns.
*/
// // 1. First level: AST node type.
// // 2. source code: raw tokens
// // 3. abstract identifiers:
// // 4. semi-source code:
SimplifyTree abstractIdentifier = new SimplifyTree();
abstractIdentifier.abstractTree(hunkActionSet, bugEndPosition);
SimpleTree simpleT = hunkActionSet.getSimpleTree();
if (simpleT == null) { // Failed to get the simple tree for INS actions.
continue;
}
children.add(simpleT);
}
}
simpleTree.setChildren(children);
simpleTree.setParent(null);
return simpleTree;
}
@@ -344,170 +245,4 @@ public class FixedViolationHunkParser extends FixedViolationParser {
actionSets.removeAll(overlappedUpdates);
}
private List<Violation> identifyFixRangeHeuristically(List<Violation> violations, List<DiffEntryHunk> diffentryHunks, File revFile) {
List<Violation> selectedViolations = new ArrayList<>();
for (Violation violation : violations) {
int violationStartLineNum = violation.getBugStartLineNum();
if (violationStartLineNum > 0) {
int violationEndLineNum = violation.getEndLineNum();
for (int index = 0, hunkListSize = diffentryHunks.size(); index < hunkListSize; index ++) {
DiffEntryHunk hunk = diffentryHunks.get(index);
int bugStartLine = hunk.getBugLineStartNum();
int bugRange = hunk.getBugRange();
if (violationStartLineNum > bugStartLine + bugRange - 1) continue;
if (violationEndLineNum < bugStartLine) break;
int fixStartLine = hunk.getFixLineStartNum();
String diffentry = hunk.getHunk();
BufferedReader reader = new BufferedReader(new StringReader(diffentry));
String line = null;
try {
int currentBugLine = bugStartLine - 1;
int currentFixLine = fixStartLine - 1;
int fixedLines = 0;
int bugS = 0;
int fixS = 0;
int fixE = 0;
int bugFixStartLine = 0; // the heuristic inferred fix start line of the corresponding bug
int bugFixEndLine = 0; // the heuristic inferred fix end line of the corresponding bug
boolean isFixRange= false;
while ((line = reader.readLine()) != null) {
if (line.startsWith("+")) {
currentFixLine ++;
fixedLines++;
if ((violationStartLineNum <= currentBugLine && currentBugLine <= violationEndLineNum) ||
(violationStartLineNum <= bugS && bugS <= violationEndLineNum)) {
if (fixS == 0) fixS = currentFixLine;
if (bugFixStartLine == -1) bugFixStartLine = currentFixLine;
if (isFixRange) bugFixEndLine = currentFixLine;
fixE = currentFixLine;
} else {
fixedLines = 0;
bugS = 0;
}
} else if (line.startsWith("-")) {
currentBugLine ++;
if (bugS == 0 || fixS != 0) bugS = currentBugLine;// currentBugLine may be larger than the violation end line.
// INS combined with DEL, UPD or MOV.
// Infer the fix range for a violation heuristically.
if (currentBugLine >= violation.getStartLineNum() && currentBugLine <= violation.getEndLineNum()) {
bugFixStartLine = -1;
}
if (currentBugLine <= violation.getEndLineNum() && bugFixStartLine != 0) {
isFixRange = true;
}
if (bugFixEndLine > 0) isFixRange = false;
if (bugFixStartLine <= 0) fixS = 0;
} else {
currentBugLine ++;
currentFixLine ++;
// pure INS
// Infer the fix range for a violation heuristically.
if (currentBugLine == violation.getStartLineNum()) {
if (bugFixStartLine <= 0) {
if (fixedLines != 0) {
if (fixedLines > THRESHOLD_LINE) {
fixedLines = THRESHOLD_LINE;// insert 3 lines.
}
bugFixStartLine = currentFixLine - fixedLines;
if (bugFixStartLine < violationStartLineNum) {
bugFixStartLine = violationStartLineNum;
}
}
else bugFixStartLine = currentFixLine;
}
}
if (currentBugLine == violation.getEndLineNum()) {
if (bugFixStartLine != 0 && bugFixEndLine == 0) {
bugFixEndLine = currentFixLine + THRESHOLD_LINE;
if (bugFixEndLine > violationEndLineNum) {
bugFixEndLine = violationEndLineNum;
}
}
}
if (bugFixEndLine > 0) isFixRange = false;
}
if ((violationStartLineNum <= currentBugLine && currentBugLine <= violationEndLineNum)) {
if (!violation.getHunks().contains(hunk))
violation.getHunks().add(hunk);
}
}
if (violation.getFixStartLineNum() == 0) {
violation.setFixStartLineNum(fixS);
}
violation.setFixEndLineNum(fixE);
if (violation.getBugFixStartLineNum() == 0 && bugFixStartLine > 0) {
violation.setBugFixStartLineNum(bugFixStartLine);
}
if (bugFixEndLine > 0) {
violation.setBugFixEndLineNum(bugFixEndLine);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
if (violation.getHunks().size() == 0) {
// This fixed violation cannot be matched with a DiffEntry, it is difficult to identify related source code change for it.
this.nullMatchedDiffEntry ++;
this.unfixedViolations += "#NullDiffEntry: " + revFile.getName() + " : " +violation.getStartLineNum() + " : "
+ violation.getEndLineNum() + " : " + violation.getViolationType() + "\n";
} else {
selectedViolations.add(violation);
}
} else {
selectedViolations.add(violation);
}
}
return selectedViolations;
}
private String getContextTokens(String patchSourceCode) {
BufferedReader reader = new BufferedReader(new StringReader(patchSourceCode));
String line = null;
String context = "";
try {
while ((line = reader.readLine()) != null) {
if (line.startsWith("+") || line.startsWith("-")) {
continue;
}
context += line + "\n";
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if ("".equals(context)) {
return "Block Block";
} else {
ITree tree = new GumTreeGenerator().generateITreeForCodeBlock(context, GumTreeType.EXP_JDT);
if (tree == null) {
return "Block Block";
}
SimpleTree simpleTree = new SimplifyTree().canonicalizeSourceCodeTree(tree, null);
String tokens = Tokenizer.getTokensDeepFirst(simpleTree).trim();
return tokens;
}
}
}
@@ -10,13 +10,11 @@ import java.util.List;
import com.github.gumtreediff.actions.model.Action;
import edu.lu.uni.serval.FixPatternParser.Parser;
import edu.lu.uni.serval.diffentry.DiffEntryHunk;
import edu.lu.uni.serval.gumtree.GumTreeComparer;
import edu.lu.uni.serval.gumtree.regroup.HierarchicalActionSet;
import edu.lu.uni.serval.gumtree.regroup.HierarchicalRegrouper;
import edu.lu.uni.serval.utils.FileHelper;
import edu.lu.uni.serval.utils.ListSorter;
import edu.lu.uni.serval.violation.code.parser.ViolationSourceCodeTree;
/**
* Parse fix patterns with GumTree.
@@ -36,13 +34,7 @@ public class FixedViolationParser extends Parser {
*/
public int resultType = 0;
private File positionFile = null;
protected String violationTypes = "";
// protected List<Violation> uselessViolations;
public void setPositionFile(File positionFile) {
this.positionFile = positionFile;
}
@Override
public void parseFixPatterns(File prevFile, File revFile, File diffentryFile) {
@@ -90,60 +82,6 @@ public class FixedViolationParser extends Parser {
}
}
protected List<Violation> readViolations(File prevFile, File revFile) {
String fileName = revFile.getName();
List<Violation> violations = new ArrayList<>();
String fileContent = FileHelper.readFile(positionFile);
BufferedReader reader = null;
reader = new BufferedReader(new StringReader(fileContent));
String line = null;
try {
while ((line = reader.readLine()) != null) {
String[] positionStr = line.split(":");
int startLine = Integer.parseInt(positionStr[1]);
int endLine = Integer.parseInt(positionStr[2]);
String violationType = positionStr[0];
Violation violation = new Violation(startLine, endLine, violationType);
violation.setFileName(fileName);
if (startLine == -1) {
violation.setBugStartLineNum(0);
continue;
}
/*
* Get the parent range of a violation.
* Read DiffEntries with this range to get the start line and end line of a violation.
*/
ViolationSourceCodeTree alarmTree = new ViolationSourceCodeTree(prevFile, startLine, endLine);
alarmTree.locateParentNode(violationType);
int violationStartLine = alarmTree.getViolationFinalStartLine();
violation.setBugStartLineNum(violationStartLine);
if (violationStartLine > 0) {// 0: no source code, -1: range is too large, which contains several inner classes, methods or fields.
violation.setBugEndLineNum(alarmTree.getViolationFinalEndLine());
// if (violationType.equals("SE_NO_SERIALVERSIONID")){
// FileHelper.outputToFile("OUTPUT/list1.txt", line + ":" + revFile.getName() + "\n", true);
// }
} else {
// if (!violationType.equals("SE_NO_SERIALVERSIONID")) {
// FileHelper.outputToFile("OUTPUT/list.txt", line + ":" + revFile.getName() + "\n", true);
// }
}
violations.add(violation);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return violations;
}
/**
* Read patch source code from buggy and fixed files.
* @param prevFile
@@ -193,60 +131,6 @@ public class FixedViolationParser extends Parser {
return sourceCode;
}
/**
* Read patch source code from diffentries.
* @param violation
* @param bugStartLine
* @param bugEndLine
* @param fixStartLine
* @param fixEndLine
* @return
*/
protected String readPatchSourceCode(Violation violation, int bugStartLine, int bugEndLine, int fixStartLine, int fixEndLine) {
String patch = "";
List<DiffEntryHunk> diffentries = violation.getHunks();
for (DiffEntryHunk diffentry : diffentries) {
int currentBugLine = diffentry.getBugLineStartNum() - 1;
int currentFixLine = diffentry.getFixLineStartNum() - 1;
String sourceCode = diffentry.getHunk();
BufferedReader reader = new BufferedReader(new StringReader(sourceCode));
String line = null;
try {
while ((line = reader.readLine()) != null) {
if (line.startsWith("+")) {
currentFixLine ++;
if (fixStartLine <= currentFixLine && currentFixLine <= fixEndLine) {
patch += line + "\n";
}
} else if (line.startsWith("-")) {
currentBugLine ++;
if (bugStartLine <= currentBugLine && currentBugLine <= bugEndLine) {
patch += line + "\n";
}
} else {
currentFixLine ++;
currentBugLine ++;
if ((bugStartLine <= currentBugLine && currentBugLine <= bugEndLine) ||
(fixStartLine <= currentFixLine && currentFixLine <= fixEndLine)) {
patch += line + "\n";
}
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return patch;
}
public String getAlarmTypes() {
return violationTypes;
}
@@ -39,7 +39,6 @@ public class FixedViolationSingleStatementParser extends FixedViolationParser {
}
// Read the positions of checked violations
List<Violation> violations = readViolations(prevFile, revFile);
for (HierarchicalActionSet actionSet : actionSets) {
// position of buggy statements
int startPosition = 0;
@@ -95,7 +94,7 @@ public class FixedViolationSingleStatementParser extends FixedViolationParser {
int startLine2 = revUnit.getLineNumber(startPosition2);
int endLine2 = revUnit.getLineNumber(endPosition2);
Violation violation = findViolation(startLine, endLine, violations);
Violation violation = null;//findViolation(startLine, endLine, violations);
if (violation == null) continue;
if (endLine - startLine >= Configuration.HUNK_SIZE - 2 || endLine2 - startLine2 >= Configuration.HUNK_SIZE - 2 ) continue;
@@ -54,7 +54,6 @@ public class TestHunkParser {
// int counter = 0;
for (MessageFile msgFile : msgFiles) {
FixedViolationHunkParser parser = new FixedViolationHunkParser();
parser.setPositionFile(msgFile.getPositionFile());
final ExecutorService executor = Executors.newSingleThreadExecutor();
// schedule the work
@@ -22,11 +22,28 @@ public class AkkaParser {
private static Logger log = LoggerFactory.getLogger(AkkaParser.class);
/**
* Two parameters:
* First one: the root path of input data.
* Second one: the number of threads.
* Third one: the threshold of selecting patch hunks.
* @param args
*/
@SuppressWarnings("deprecation")
public static void main(String[] args) {
String inputRootPath = args[0];
int numberOfWorkers = Integer.parseInt(args[1]);
int hunkThreshold = 0;
try {
hunkThreshold = Integer.parseInt(args[2]);
} catch (NumberFormatException e1) {
hunkThreshold = 10;
}
Configuration.ROOT_PATH = inputRootPath;
Configuration.HUNK_SIZE = hunkThreshold;
// input data
log.info("Get the input data...");
// final List<MessageFile> msgFiles = getMessageFiles();
final List<MessageFile> msgFiles = getMessageFiles(Configuration.GUM_TREE_INPUT);
log.info("MessageFiles: " + msgFiles.size());
@@ -35,22 +52,19 @@ public class AkkaParser {
final String patchesSourceCodeFilePath = Configuration.PATCH_SOURCECODE_FILE_PATH;
final String buggyTokensFilePath = Configuration.BUGGY_CODE_TOKEN_FILE_PATH;
final String editScriptSizesFilePath = Configuration.EDITSCRIPT_SIZES_FILE_PATH;
final String alarmTypesFilePath = Configuration.ALARM_TYPES_FILE_PATH;
FileHelper.deleteDirectory(editScriptsFilePath);
FileHelper.deleteDirectory(patchesSourceCodeFilePath);
FileHelper.deleteDirectory(buggyTokensFilePath);
FileHelper.deleteDirectory(editScriptSizesFilePath);
FileHelper.deleteDirectory(alarmTypesFilePath);
ActorSystem system = null;
ActorRef parsingActor = null;
int numberOfWorkers = 431;
final WorkMessage msg = new WorkMessage(0, msgFiles);
try {
log.info("Akka begins...");
system = ActorSystem.create("Mining-FixPattern-System");
parsingActor = system.actorOf(ParseFixPatternActor.props(numberOfWorkers, editScriptsFilePath,
patchesSourceCodeFilePath, buggyTokensFilePath, editScriptSizesFilePath, alarmTypesFilePath), "mine-fix-pattern-actor");
patchesSourceCodeFilePath, buggyTokensFilePath, editScriptSizesFilePath), "mine-fix-pattern-actor");
parsingActor.tell(msg, ActorRef.noSender());
} catch (Exception e) {
system.shutdown();
@@ -59,47 +73,6 @@ public class AkkaParser {
}
/**
* Get bug commit-related files.
*
* @return
*/
public static List<MessageFile> getMessageFiles() {
String inputPath = Configuration.GUM_TREE_INPUT; //DiffEntries prevFiles revFiles
File inputFileDirector = new File(inputPath);
File[] files = inputFileDirector.listFiles(); // project folders
log.info("Projects: " + files.length);
List<MessageFile> msgFiles = new ArrayList<>();
for (File file : files) {
if (!file.isDirectory()) continue;
// if (!(file.getName().startsWith("k") || file.getName().startsWith("l"))) continue;
if (file.getName().startsWith("a") || file.getName().startsWith("b")
|| file.getName().startsWith("c") || file.getName().startsWith("d")
|| file.getName().startsWith("e") || file.getName().startsWith("f")
|| file.getName().startsWith("g") || file.getName().startsWith("h")
||file.getName().startsWith("h") || file.getName().startsWith("i")
|| file.getName().startsWith("k") || file.getName().startsWith("l")
|| file.getName().startsWith("j") || file.getName().startsWith("t")) continue;
// if (!file.getName().startsWith("j")) continue;
log.info("Project name: " + file.getName());
String projectFolder = file.getPath();
File revFileFolder = new File(projectFolder + "/revFiles/");// revised file folder
File[] revFiles = revFileFolder.listFiles();
for (File revFile : revFiles) {
if (revFile.getName().endsWith(".java")) {
File prevFile = new File(projectFolder + "/prevFiles/prev_" + revFile.getName());// previous file
File diffentryFile = new File(projectFolder + "/DiffEntries/" + revFile.getName().replace(".java", ".txt")); // DiffEntry file
MessageFile msgFile = new MessageFile(revFile, prevFile, diffentryFile);
msgFiles.add(msgFile);
}
}
}
return msgFiles;
}
/**
* Get violation-related files.
*
@@ -1,6 +1,5 @@
package edu.lu.uni.serval.MultipleThreadsParser;
import java.util.ArrayList;
import java.util.List;
import org.slf4j.Logger;
@@ -21,15 +20,15 @@ public class ParseFixPatternActor extends UntypedActor {
private int counter = 0;
public ParseFixPatternActor(int numberOfWorkers, String editScriptsFilePath, String patchesSourceCodeFilePath,
String buggyTokensFilePath, String editScriptSizesFilePath, String alarmTypesFilePath) {
String buggyTokensFilePath, String editScriptSizesFilePath) {
mineRouter = this.getContext().actorOf(new RoundRobinPool(numberOfWorkers)
.props(ParseFixPatternWorker.props(editScriptsFilePath, patchesSourceCodeFilePath,
buggyTokensFilePath, editScriptSizesFilePath, alarmTypesFilePath)), "mine-fix-pattern-router");
buggyTokensFilePath, editScriptSizesFilePath)), "mine-fix-pattern-router");
this.numberOfWorkers = numberOfWorkers;
}
public static Props props(final int numberOfWorkers, final String editScriptsFilePath, final String patchesSourceCodeFilePath,
final String buggyTokensFilePath, final String editScriptSizesFilePath, final String alarmTypesFilePath) {
final String buggyTokensFilePath, final String editScriptSizesFilePath) {
return Props.create(new Creator<ParseFixPatternActor>() {
@@ -38,7 +37,7 @@ public class ParseFixPatternActor extends UntypedActor {
@Override
public ParseFixPatternActor create() throws Exception {
return new ParseFixPatternActor(numberOfWorkers, editScriptsFilePath, patchesSourceCodeFilePath,
buggyTokensFilePath, editScriptSizesFilePath, alarmTypesFilePath);
buggyTokensFilePath, editScriptSizesFilePath);
}
});
@@ -50,26 +49,25 @@ public class ParseFixPatternActor extends UntypedActor {
if (message instanceof WorkMessage) {
List<MessageFile> files = ((WorkMessage) message).getMsgFiles();
int size = files.size();
int average = (int) Math.round((double) size / numberOfWorkers);
int average = size / numberOfWorkers;
int reminder = size % numberOfWorkers;
int counter = 0;
for (int i = 0; i < numberOfWorkers; i ++) {
int fromIndex = i * average;
int toIndex = (i + 1) * average;
if (i == numberOfWorkers - 1) {
toIndex = size;
}
int fromIndex = i * average + counter;
if (counter < reminder) counter ++;
int toIndex = (i + 1) * average + counter;
List<MessageFile> filesOfWorkers = new ArrayList<>();
filesOfWorkers.addAll(files.subList(fromIndex, toIndex));
List<MessageFile> filesOfWorkers = files.subList(fromIndex, toIndex);
final WorkMessage workMsg = new WorkMessage(i + 1, filesOfWorkers);
mineRouter.tell(workMsg, getSelf());
logger.info("Assign a task to worker #" + (i + 1) + "...");
}
} else if ("STOP".equals(message.toString())) {
counter ++;
logger.info(counter + " workers finished their work...");
logger.info(counter + " workers finailized their work...");
if (counter >= numberOfWorkers) {
logger.info("All workers finished their work...");
logger.info("All workers finailized their work...");
this.getContext().stop(mineRouter);
this.getContext().stop(getSelf());
this.getContext().system().shutdown();
@@ -31,19 +31,17 @@ public class ParseFixPatternWorker extends UntypedActor {
private String patchesSourceCodeFilePath;
private String editScriptSizesFilePath;
private String buggyTokensFilePath;
private String alarmTypesFilePath;
public ParseFixPatternWorker(String editScriptsFilePath, String patchesSourceCodeFilePath,
String buggyTokensFilePath, String editScriptSizesFilePath, String alarmTypesFilePath) {
String buggyTokensFilePath, String editScriptSizesFilePath) {
this.editScriptsFilePath = editScriptsFilePath;
this.patchesSourceCodeFilePath = patchesSourceCodeFilePath;
this.editScriptSizesFilePath = editScriptSizesFilePath;
this.buggyTokensFilePath = buggyTokensFilePath;
this.alarmTypesFilePath = alarmTypesFilePath;
}
public static Props props(final String editScriptsFile, final String patchesSourceCodeFile, final String buggyTokensFilePath,
final String editScriptSizesFilePath, final String alarmTypesFilePath) {
final String editScriptSizesFilePath) {
return Props.create(new Creator<ParseFixPatternWorker>() {
private static final long serialVersionUID = -7615153844097275009L;
@@ -51,7 +49,7 @@ public class ParseFixPatternWorker extends UntypedActor {
@Override
public ParseFixPatternWorker create() throws Exception {
return new ParseFixPatternWorker(editScriptsFile, patchesSourceCodeFile,
buggyTokensFilePath, editScriptSizesFilePath, alarmTypesFilePath);
buggyTokensFilePath, editScriptSizesFilePath);
}
});
@@ -66,13 +64,11 @@ public class ParseFixPatternWorker extends UntypedActor {
StringBuilder patchesSourceCode = new StringBuilder();
StringBuilder sizes = new StringBuilder();
StringBuilder tokens = new StringBuilder();
StringBuilder alarmTypes = new StringBuilder();
StringBuilder testingInfo = new StringBuilder();
int id = msg.getId();
int counter = 0;
int testViolations = 0;
int nullGumTreeResults = 0;
int noSourceCodeChanges = 0;
int noStatementChanges = 0;
@@ -85,28 +81,15 @@ public class ParseFixPatternWorker extends UntypedActor {
int timeouts = 0;
StringBuilder builder = new StringBuilder();
// Read violations with Null_Violation_Hunk or Illegal_Line_Position
// List<Violation> uselessViolations = new ArrayList<>();// readUselessViolations("logs/FixedViolationCodeParseResults.log");
for (MessageFile msgFile : files) {
File revFile = msgFile.getRevFile();
File prevFile = msgFile.getPrevFile();
File diffentryFile = msgFile.getDiffEntryFile();
File positionFile = msgFile.getPositionFile();
if (revFile.getName().toLowerCase().contains("test#") || revFile.getName().toLowerCase().contains("tests#")) {
// testViolations += countAlarms(positionFile, "#TestViolation:", uselessViolations);
testViolations += countAlarms(positionFile, "#TestViolation:");
if (revFile.getName().toLowerCase().contains("test")) {
continue;
}
// Parser parser = null;
// if (containsAlarmTypes || positionFile != null) {
// parser = new FixedViolationHunkParser(positionFile);
// containsAlarmTypes = true;
// } else {
// parser = new CommitPatchSingleStatementParser();
// }
FixedViolationHunkParser parser = new FixedViolationHunkParser(positionFile);
// parser.setUselessViolations(uselessViolations);
FixedViolationHunkParser parser = new FixedViolationHunkParser();
final ExecutorService executor = Executors.newSingleThreadExecutor();
// schedule the work
@@ -128,20 +111,15 @@ public class ParseFixPatternWorker extends UntypedActor {
if ("".equals(editScript)) {
if (parser.resultType == 1) {
nullGumTreeResults += countAlarms(positionFile, "");
// System.err.println("#NullGumTreeResult:" + revFile.getName());
} else if (parser.resultType == 2) {
noSourceCodeChanges += countAlarms(positionFile, "");
} else if (parser.resultType == 3) {
noStatementChanges += countAlarms(positionFile, "");
// } else if (parser.resultType == 4) {
// illegalV += countAlarms(positionFile, "", uselessViolations);
}
} else {
editScripts.append(editScript);
patchesSourceCode.append(parser.getPatchesSourceCode());
sizes.append(parser.getSizes());
// tokens.append(parser.getTokensOfSourceCode());
alarmTypes.append(parser.getAlarmTypes());
tokens.append(parser.getTokensOfSourceCode());
counter ++;
@@ -154,26 +132,23 @@ public class ParseFixPatternWorker extends UntypedActor {
patchesSourceCode.setLength(0);
sizes.setLength(0);
tokens.setLength(0);
FileHelper.outputToFile(alarmTypesFilePath + "alarmTypes_" + id + ".list", alarmTypes, true);
alarmTypes.setLength(0);
log.info("Worker #" + id +"Finish of parsing " + counter + " files...");
log.info("Worker #" + id +" finialized parsing " + counter + " files...");
FileHelper.outputToFile("OUTPUT/testingInfo_" + id + ".list", testingInfo, true);
testingInfo.setLength(0);
}
}
} catch (TimeoutException e) {
// err.println("task timed out");
future.cancel(true);
timeouts += countAlarms(positionFile, "#Timeout:");
// System.err.println("#Timeout: " + revFile.getName());
System.err.println("#Timeout: " + revFile.getName());
} catch (InterruptedException e) {
timeouts += countAlarms(positionFile, "#TimeInterrupted:");
// err.println("task interrupted");
// System.err.println("#TimeInterrupted: " + revFile.getName());
System.err.println("#TimeInterrupted: " + revFile.getName());
e.printStackTrace();
} catch (ExecutionException e) {
timeouts += countAlarms(positionFile, "#TimeAborted:");
// err.println("task aborted");
// System.err.println("#TimeAborted: " + revFile.getName());
System.err.println("#TimeAborted: " + revFile.getName());
e.printStackTrace();
} finally {
executor.shutdownNow();
}
@@ -189,58 +164,24 @@ public class ParseFixPatternWorker extends UntypedActor {
sizes.setLength(0);
tokens.setLength(0);
FileHelper.outputToFile(alarmTypesFilePath + "alarmTypes_" + id + ".list", alarmTypes, true);
alarmTypes.setLength(0);
FileHelper.outputToFile("OUTPUT/testingInfo_" + id + ".list", testingInfo, true);
testingInfo.setLength(0);
}
String statistic = "TestViolations: " + testViolations + "\nNullGumTreeResults: " + nullGumTreeResults + "\nNoSourceCodeChanges: " + noSourceCodeChanges +
String statistic = "\nNullGumTreeResults: " + nullGumTreeResults + "\nNoSourceCodeChanges: " + noSourceCodeChanges +
"\nNoStatementChanges: " + noStatementChanges + "\nNullDiffEntry: " + nullDiffEntry + "\nNullMatchedGumTreeResults: " + nullMappingGumTreeResults +
"\nPureDeletion: " + pureDeletion + "\nLargeHunk: " + largeHunk + "\nNullSourceCode: " + nullSourceCode +
"\nTestingInfo: " + testInfos + "\nTimeout: " + timeouts;
FileHelper.outputToFile("OUTPUT/statistic_" + id + ".list", statistic, false);
FileHelper.outputToFile("OUTPUT/UnfixedV_" + id + ".list", builder, false);
log.info("Worker #" + id +"Finish of parsing " + counter + " files...");
log.info("Worker #" + id + " finished the work...");
log.info("Worker #" + id +"finialized parsing " + counter + " files...");
log.info("Worker #" + id + " finialized the work...");
this.getSender().tell("STOP", getSelf());
} else {
unhandled(message);
}
}
// private List<Violation> readUselessViolations(String filePath) {
// List<Violation> uselessViolations = new ArrayList<>();
//
// String content = FileHelper.readFile(filePath);
// BufferedReader reader = new BufferedReader(new StringReader(content));
// String line = null;
// try {
// while ((line = reader.readLine()) != null) {
// if (line.startsWith("#")) {
// String[] elements = line.split(":");
// String fileName = elements[1];
// int startLine = Integer.parseInt(elements[2]);
// int endLine = Integer.parseInt(elements[3]);
// String violationType = elements[4];
//
// Violation violation = new Violation(startLine, endLine, violationType);
// violation.setFileName(fileName);
// uselessViolations.add(violation);
// }
// }
// } catch (IOException e) {
// e.printStackTrace();
// } finally {
// try {
// reader.close();
// } catch (IOException e) {
// e.printStackTrace();
// }
// }
// return uselessViolations;
// }
private int countAlarms(File positionFile, String type) {//, List<Violation> uselessViolations) {
int counter = 0;
String content = FileHelper.readFile(positionFile);
@@ -66,7 +66,7 @@ public class SingleThreadParser {
testViolations += countAlarms(positionFile, "#TestViolation:");
continue;
}
FixedViolationHunkParser parser = new FixedViolationHunkParser(positionFile);
FixedViolationHunkParser parser = new FixedViolationHunkParser();
// parser.setUselessViolations(uselessViolations);
final ExecutorService executor = Executors.newSingleThreadExecutor();
@@ -2,11 +2,11 @@ package edu.lu.uni.serval.config;
public class Configuration {
public static final long SECONDS_TO_WAIT = 300000L;
public static final long SECONDS_TO_WAIT = 300L;
public static final String ROOT_PATH = "../FPM_Violations/"; // The root path of all output data.
public static String ROOT_PATH = "../FPM_Violations/"; // The root path of all output data.
public static final int HUNK_SIZE = 10; // The limitation of source code lines of each DiffEntry, which will be selected as training data.
public static int HUNK_SIZE = 10; // The limitation of source code lines of each DiffEntry, which will be selected as training data.
public static final String BUGGY_TREE_SIGNAL = "BUGGY_TREE###"; // The starting signal of the tree of buggy source code .
public static final String PATCH_SIGNAL = "PATCH###"; // The starting signal of each patch.
@@ -86,9 +86,5 @@ public class Configuration {
public static final String SUPERVISED_LEARNING_MODEL = ROOT_PATH + "TestingOutput/SupervisedLearningModel.zip";
public static final String FEATURES_OF_COMMON_CLUSTERS = ROOT_PATH + "FeaturesOfCommonClusters/";
public static final String TESTING_DATA_BUGS90 = ROOT_PATH + "Bugs/bugs90.list";
public static final String TESTING_DATA_BUGS80 = ROOT_PATH + "Bugs/bugs80.list";
public static final String TESTING_DATA_BUGS70 = ROOT_PATH + "Bugs/bugs70.list";
public static final String TESTING_DATA_BUGS60 = ROOT_PATH + "Bugs/bugs60.list";
}
@@ -1,5 +1,10 @@
package edu.lu.uni.serval.diffentry;
import java.util.ArrayList;
import java.util.List;
import edu.lu.uni.serval.gumtree.regroup.HierarchicalActionSet;
public class DiffEntryHunk {
private int bugLineStartNum;
@@ -10,6 +15,7 @@ public class DiffEntryHunk {
private int buggyHunkSize;
private int fixedHunkSize;
private String file;
private List<HierarchicalActionSet> actionSets = new ArrayList<>();
public DiffEntryHunk(int bugLineStartNum, int fixLineStartNum, int bugRange, int fixRange) {
super();
@@ -66,6 +72,10 @@ public class DiffEntryHunk {
public void setFile(String file) {
this.file = file;
}
public List<HierarchicalActionSet> getActionSets() {
return actionSets;
}
@Override
public String toString() {
@@ -214,7 +214,7 @@ public class HierarchicalActionSet implements Comparable<HierarchicalActionSet>
actionSet.toString();
List<String> strList1 = actionSet.strList;
for (String str1 : strList1) {
strList.add("----" + str1);
strList.add("---" + str1);
}
}
} else {
@@ -224,7 +224,7 @@ public class HierarchicalActionSet implements Comparable<HierarchicalActionSet>
actionSet.toString();
List<String> strList1 = actionSet.strList;
for (String str1 : strList1) {
strList.add("----" + str1);
strList.add("---" + str1);
}
}
}
@@ -361,237 +361,56 @@ public class HunkActionFilter {
* @param prevFile
* @return
*/
public List<Violation> filterActionsByModifiedRange2(List<Violation> violations,
public List<DiffEntryHunk> filterActionsByModifiedRange2(List<DiffEntryHunk> diffentryHunks,
List<HierarchicalActionSet> actionSets, File revFile, File prevFile) {
List<Violation> selectedViolations = new ArrayList<>();
List<DiffEntryHunk> selectedViolations = new ArrayList<>();
CUCreator cuCreator = new CUCreator();
CompilationUnit prevUnit = cuCreator.createCompilationUnit(prevFile);
CompilationUnit revUnit = cuCreator.createCompilationUnit(revFile);
if (prevUnit == null || revUnit == null) {
for (Violation violation : violations) {
this.unfixedViolations += "#NullMatchedGumTreeResult:" + revFile.getName() + ":" +violation.getStartLineNum() + ":" +
violation.getEndLineNum() + ":" + violation.getViolationType() + "\n";
}
return selectedViolations;
}
for (Violation violation : violations) {
int violationStartLine = violation.getStartLineNum();
int violationEndLine = violation.getEndLineNum();
int bugHunkStartLine = violation.getBugStartLineNum();
for (DiffEntryHunk diffentryHunk : diffentryHunks) {
// int violationEndLine = violationStartLine + diffentryHunk.getBugRange();
int bugHunkStartLine = diffentryHunk.getBugLineStartNum();
int bugHunkEndLine = bugHunkStartLine + diffentryHunk.getBugRange() - 1;
int fixHunkStartLine = diffentryHunk.getFixLineStartNum();
int fixHunkEndLine = fixHunkStartLine + diffentryHunk.getFixedHunkSize() - 1;
if (!specialVioaltionTypes(violation, actionSets, prevUnit, revUnit)) {
if (bugHunkStartLine == 0) {// Null source code matched for this violation.
// String type = getType(violation);
} else if (bugHunkStartLine == -1) {//
// specialVioaltionTypes(violation, actionSets, prevUnit, revUnit);
} else {
int bugHunkEndLine = violation.getBugEndLineNum();
int fixHunkStartLine = violation.getFixStartLineNum();
int fixHunkEndLine = violation.getFixEndLineNum();
int bugFixStartLineNum = violation.getBugFixStartLineNum();
int bugFixEndLineNum = violation.getBugFixEndLineNum();
for (HierarchicalActionSet actionSet : actionSets) {
int actionBugStartLine = actionSet.getBugStartLineNum();
if (actionBugStartLine == 0) {
actionBugStartLine = setLineNumbers(actionSet, prevUnit, revUnit);
}
int actionBugEndLine = actionSet.getBugEndLineNum();
int actionFixStartLine = actionSet.getFixStartLineNum();
int actionFixEndLine = actionSet.getFixEndLineNum();
String actionStr = actionSet.getActionString();
if (actionStr.startsWith("INS")) {
if (fixHunkStartLine <= actionFixStartLine && actionFixEndLine <= fixHunkEndLine) {
if (actionBugStartLine != 0) {
if (violationStartLine <= actionBugEndLine && violationEndLine >= actionBugStartLine) {
violation.getActionSets().add(actionSet);
continue;
}
}
// INS with MOV actions that are not identified in previous IF predicate, and pure INS actions
if (bugFixStartLineNum >= actionFixEndLine && actionFixStartLine <= bugFixEndLineNum && Math.abs(bugFixStartLineNum - actionFixStartLine) <= 3
&& Math.abs(bugFixEndLineNum - actionFixEndLine) <= 3) {
violation.getActionSets().add(actionSet);
}
}
} else {//if (!actionStr.startsWith("MOV")){// ignore move actions.
if (bugHunkStartLine <= actionBugStartLine && violationEndLine <= bugHunkEndLine) {
if (violationStartLine <= actionBugEndLine && violationEndLine >= actionBugStartLine) {
violation.getActionSets().add(actionSet);
}
}
for (HierarchicalActionSet actionSet : actionSets) {
int actionBugStartLine = actionSet.getBugStartLineNum();
if (actionBugStartLine == 0) {
actionBugStartLine = setLineNumbers(actionSet, prevUnit, revUnit);
}
int actionBugEndLine = actionSet.getBugEndLineNum();
int actionFixStartLine = actionSet.getFixStartLineNum();
int actionFixEndLine = actionSet.getFixEndLineNum();
String actionStr = actionSet.getActionString();
if (actionStr.startsWith("INS")) {
if (fixHunkStartLine <= actionFixEndLine && fixHunkEndLine >= actionFixStartLine ) {
if (actionBugStartLine != 0) {
diffentryHunk.getActionSets().add(actionSet);
}
}
} else {
if (bugHunkStartLine <= actionBugEndLine && bugHunkEndLine >= actionBugStartLine) {
diffentryHunk.getActionSets().add(actionSet);
}
}
}
if (violation.getActionSets().size() > 0) {
selectedViolations.add(violation);
} else {
this.unfixedViolations += "#NullMatchedGumTreeResult:" + revFile.getName() + ":" +violation.getStartLineNum() + ":" +
violation.getEndLineNum() + ":" + violation.getViolationType() + "\n";
if (diffentryHunk.getActionSets().size() > 0) {
selectedViolations.add(diffentryHunk);
}
}
return selectedViolations;
}
public String unfixedViolations = "";
private boolean specialVioaltionTypes(Violation violation, List<HierarchicalActionSet> actionSets, CompilationUnit prevUnit, CompilationUnit revUnit) {
String type = violation.getViolationType();
if ("NM_METHOD_NAMING_CONVENTION".equals(type) || "SE_NO_SUITABLE_CONSTRUCTOR_FOR_EXTERNALIZATION".equals(type)) {
int startLine = violation.getStartLineNum();
for (HierarchicalActionSet actionSet : actionSets) {
int actionBugStartLine = actionSet.getBugStartLineNum();
if (actionBugStartLine == 0) {
actionBugStartLine = setLineNumbers(actionSet, prevUnit, revUnit);
}
if (actionSet.getActionString().startsWith("UPD MethodDeclaration@@")) {
if (Math.abs(startLine - actionBugStartLine) <= 2) {
violation.getActionSets().add(actionSet);
break;
}
}
}
} else if ("EQ_DOESNT_OVERRIDE_EQUALS".equals(type)) {
for (HierarchicalActionSet actionSet : actionSets) {
int actionBugStartLine = actionSet.getBugStartLineNum();
if (actionBugStartLine == 0) {
actionBugStartLine = setLineNumbers(actionSet, prevUnit, revUnit);
}
if (actionSet.getActionString().startsWith("INS MethodDeclaration@@MethodName:equals")) {
violation.getActionSets().add(actionSet);
break;
}
}
} else if ("HE_EQUALS_USE_HASHCODE".equals(type) || "HE_INHERITS_EQUALS_USE_HASHCODE".equals(type)) {
for (HierarchicalActionSet actionSet : actionSets) {
int actionBugStartLine = actionSet.getBugStartLineNum();
if (actionBugStartLine == 0) {
actionBugStartLine = setLineNumbers(actionSet, prevUnit, revUnit);
}
if (actionSet.getActionString().startsWith("INS MethodDeclaration@@MethodName:hashCode")) {
violation.getActionSets().add(actionSet);
break;
}
}
} else if ("SE_NO_SUITABLE_CONSTRUCTOR".equals(type) || "RI_REDUNDANT_INTERFACES".equals(type)) {
int startLine = violation.getStartLineNum();
for (HierarchicalActionSet actionSet : actionSets) {
int actionBugStartLine = actionSet.getBugStartLineNum();
if (actionBugStartLine == 0) {
actionBugStartLine = setLineNumbers(actionSet, prevUnit, revUnit);
}
if (actionSet.getActionString().startsWith("UPD TypeDeclaration@@")) {
if (Math.abs(startLine - actionBugStartLine) <= 2) {
violation.getActionSets().add(actionSet);
break;
}
}
}
} else if ("CN_IDIOM".equals(type)) { // 202 23
//add clone method. or update clone method
for (HierarchicalActionSet actionSet : actionSets) {
int actionBugStartLine = actionSet.getBugStartLineNum();
if (actionBugStartLine == 0) {
actionBugStartLine = setLineNumbers(actionSet, prevUnit, revUnit);
}
if (actionSet.getActionString().startsWith("INS MethodDeclaration@@MethodName:clone")) {
// || actionSet.getActionString().startsWith("UPD MethodDeclaration@@clone")) {
violation.getActionSets().add(actionSet);
break;
}
}
} else if ("SE_NO_SERIALVERSIONID".equals(type) || "SE_COMPARATOR_SHOULD_BE_SERIALIZABLE".equals(type)) {// 12 1960
// change superclass or interface, add field or remove @SuppressWarnings("serial"), some are inner class
for (HierarchicalActionSet actionSet : actionSets) {
int actionBugStartLine = actionSet.getBugStartLineNum();
if (actionBugStartLine == 0) {
actionBugStartLine = setLineNumbers(actionSet, prevUnit, revUnit);
}
if (actionSet.getActionString().startsWith("INS FieldDeclaration@") && actionSet.getNode().getLabel().contains("serialVersionUID")) {
violation.getActionSets().add(actionSet);
break;
}
if (actionSet.getActionString().startsWith("UPD TypeDeclaration@")) {
int startLine = violation.getStartLineNum();
if (Math.abs(startLine - actionBugStartLine) <= 2) {
violation.getActionSets().add(actionSet);
break;
}
}
}
} else {
return false;
}
return true;
}
private String getType(Violation violation) {
String type = violation.getViolationType();
switch (type) {
case "CI_CONFUSED_INHERITANCE":// field
// update fieldDeclaration
break;
case "CO_ABSTRACT_SELF":
// java file is an interface, and delete compareTo().
break;
case "EQ_ABSTRACT_SELF":
// java file is an interface, and delete equals().
break;
case "SE_NO_SERIALVERSIONID":
// add a field: serialVersionUID
break;
case "EQ_COMPARETO_USE_OBJECT_EQUALS":
//Update or Delete compareTo(), Add equals()
break;
case "EQ_DOESNT_OVERRIDE_EQUALS":
//override equals()
break;
case "HE_SIGNATURE_DECLARES_HASHING_OF_UNHASHABLE_CLASS":
//remove equals()
break;
case "ME_MUTABLE_ENUM_FIELD":
// under enum, field add final keyword
break;
case "MF_CLASS_MASKS_FIELD":
// change super class or delete the field with a same name in super class.
break;
case "MS_SHOULD_BE_FINAL":
// add final to field
break;
case "STCAL_STATIC_SIMPLE_DATE_FORMAT_INSTANCE":
//remove public static final DateFormat DATE_FORMAT.... or SimpleDateFormat
break;
case "UUF_UNUSED_FIELD":
//remove unused fields. not sure
break;
case "UUF_UNUSED_PUBLIC_OR_PROTECTED_FIELD":
//remove unused fields. not sure
case "UWF_NULL_FIELD":
//update field, remove field
break;
case "UWF_UNWRITTEN_FIELD":
//field
break;
case "UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD":
//remove field
break;
case "VO_VOLATILE_REFERENCE_TO_ARRAY":
//field
break;
default:
break;
}
return null;
}
/**
* Filter out the modify actions, which are not in the DiffEntry hunks, without considering DiffEntry hunks.