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.ActionFilter;
import edu.lu.uni.serval.gumtree.regroup.HierarchicalActionSet; import edu.lu.uni.serval.gumtree.regroup.HierarchicalActionSet;
import edu.lu.uni.serval.gumtree.regroup.HierarchicalRegrouper; import edu.lu.uni.serval.gumtree.regroup.HierarchicalRegrouper;
import edu.lu.uni.serval.gumtree.regroup.SimpleTree;
import edu.lu.uni.serval.gumtree.regroup.SimplifyTree; import edu.lu.uni.serval.gumtree.regroup.SimplifyTree;
/** /**
@@ -1,9 +1,6 @@
package edu.lu.uni.serval.FixPatternParser.violations; package edu.lu.uni.serval.FixPatternParser.violations;
import java.io.BufferedReader;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; 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.config.Configuration;
import edu.lu.uni.serval.diffentry.DiffEntryHunk; import edu.lu.uni.serval.diffentry.DiffEntryHunk;
import edu.lu.uni.serval.diffentry.DiffEntryReader; 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.HierarchicalActionSet;
import edu.lu.uni.serval.gumtree.regroup.HunkActionFilter; import edu.lu.uni.serval.gumtree.regroup.HunkActionFilter;
import edu.lu.uni.serval.gumtree.regroup.SimpleTree; 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 { public class FixedViolationHunkParser extends FixedViolationParser {
private static final int THRESHOLD_LINE = 3;
public String testingInfo = ""; public String testingInfo = "";
public int nullMappingGumTreeResult = 0; public int nullMappingGumTreeResult = 0;
@@ -39,47 +32,31 @@ public class FixedViolationHunkParser extends FixedViolationParser {
public int nullSourceCode = 0; public int nullSourceCode = 0;
public int nullMatchedDiffEntry = 0; public int nullMatchedDiffEntry = 0;
public int testInfos = 0; public int testInfos = 0;
public FixedViolationHunkParser() {
}
public FixedViolationHunkParser(File positionFile) {
setPositionFile(positionFile);
}
public String unfixedViolations = ""; public String unfixedViolations = "";
@Override @Override
public void parseFixPatterns(File prevFile, File revFile, File diffentryFile) { public void parseFixPatterns(File prevFile, File revFile, File diffentryFile) {
List<Violation> allViolations = readViolations(prevFile, revFile);
// if (allViolations.size() >= 0) return;
// GumTree results // GumTree results
List<HierarchicalActionSet> actionSets = parseChangedSourceCodeWithGumTree2(prevFile, revFile); List<HierarchicalActionSet> actionSets = parseChangedSourceCodeWithGumTree2(prevFile, revFile);
if (this.resultType != 0) { if (this.resultType != 0) {
String type = ""; // String type = "";
if (this.resultType == 1) { // if (this.resultType == 1) {
type = "#NullGumTreeResult:"; // type = "#NullGumTreeResult:";
} else if (this.resultType == 2) { // } else if (this.resultType == 2) {
type = "#NoSourceCodeChange:"; // type = "#NoSourceCodeChange:";
} else if (this.resultType == 3) { // } else if (this.resultType == 3) {
type = "#NoStatementChange:"; // type = "#NoStatementChange:";
} // }
for (Violation v : allViolations) {
this.unfixedViolations += type + revFile.getName() + ":" + v.getStartLineNum() + ":" + v.getEndLineNum() + ":" + v.getViolationType() + "\n";
}
} else { } else {
List<DiffEntryHunk> diffentryHunks = new DiffEntryReader().readHunks2(diffentryFile); 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. //Filter out the modify actions, which are not in the DiffEntry hunks.
HunkActionFilter hunkFilter = new HunkActionFilter(); HunkActionFilter hunkFilter = new HunkActionFilter();
List<Violation> selectedViolations = hunkFilter.filterActionsByModifiedRange2(violations, actionSets, revFile, prevFile); List<DiffEntryHunk> selectedPatchHunks = hunkFilter.filterActionsByModifiedRange2(diffentryHunks, actionSets, revFile, prevFile);
this.unfixedViolations += hunkFilter.unfixedViolations;
this.nullMappingGumTreeResult += violations.size() - selectedViolations.size();
for (Violation violation : selectedViolations) { for (DiffEntryHunk patchHunk : selectedPatchHunks) {
List<HierarchicalActionSet> hunkActionSets = violation.getActionSets(); List<HierarchicalActionSet> hunkActionSets = patchHunk.getActionSets();
// multiple UPD, and some UPD contain other UPD. // multiple UPD, and some UPD contain other UPD.
removeOverlapperdUPD(hunkActionSets); removeOverlapperdUPD(hunkActionSets);
@@ -117,43 +94,27 @@ public class FixedViolationHunkParser extends FixedViolationParser {
} }
if (fixStartLine == 0 && bugStartLine == 0) { 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 ++; this.nullMappingGumTreeResult ++;
continue; continue;
} }
if (fixStartLine == 0 && bugStartLine != 0) {// pure delete actions. 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 // get the exact buggy code by violation's position. TODO later
} }
// if (children.size() == 0) continue; // if (children.size() == 0) continue;
boolean isPureInsert = false; boolean isPureInsert = false;
if (bugStartLine == 0 && violation.getBugStartLineNum() > 0) { if (bugStartLine == 0 && patchHunk.getBugLineStartNum() > 0) {
bugStartLine = violation.getStartLineNum(); bugStartLine = patchHunk.getBugLineStartNum();
bugEndLine = violation.getEndLineNum(); bugEndLine = bugStartLine + patchHunk.getBuggyHunkSize() - 1;
isPureInsert = true; isPureInsert = true;
// continue; // continue;
} }
if ((bugEndLine - bugStartLine > Configuration.HUNK_SIZE && !isPureInsert) || fixEndLine - fixStartLine > Configuration.HUNK_SIZE) { 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; // 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. * Select edit scripts for deep learning.
@@ -162,8 +123,7 @@ public class FixedViolationHunkParser extends FixedViolationParser {
// 1. First level: AST node type. // 1. First level: AST node type.
String astEditScripts = getASTEditScriptsDeepFirst(hunkActionSets, bugEndPosition, fixEndPosition); String astEditScripts = getASTEditScriptsDeepFirst(hunkActionSets, bugEndPosition, fixEndPosition);
if (astEditScripts.contains("\n") || astEditScripts.split(" ").length % 3 != 0) { if (astEditScripts.contains("\n") || astEditScripts.split(" ").length % 3 != 0) {
System.err.println("===+++===: " + revFile.getName() + ":" +violation.getStartLineNum() + ":" + System.err.println("===+++===: " + revFile.getName() + ":" +patchHunk.getBugLineStartNum() + ", " + patchHunk.getBuggyHunkSize());
violation.getEndLineNum() + ":" + violation.getViolationType());
} }
// 2. source code: raw tokens // 2. source code: raw tokens
// 3. abstract identifiers: // 3. abstract identifiers:
@@ -171,141 +131,82 @@ public class FixedViolationHunkParser extends FixedViolationParser {
String[] editScriptTokens = astEditScripts.split(" "); String[] editScriptTokens = astEditScripts.split(" ");
int size = editScriptTokens.length; int size = editScriptTokens.length;
if (size == 1) { 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.nullMappingGumTreeResult ++;
this.unfixedViolations += "#NullMatchedGumTreeResult1:" + revFile.getName() + ":" +violation.getStartLineNum() + ":" + this.unfixedViolations += "#NullMatchedGumTreeResult1:" + revFile.getName() + ":" + patchHunk.getBugLineStartNum() + ", " + patchHunk.getBuggyHunkSize() + "\n";
violation.getEndLineNum() + ":" + violation.getViolationType() + "\n";
continue; continue;
} }
String alarmType = violation.getViolationType();
String patchPosition = "\n" + revFile.getName() + "\nPosition: " + violation.getStartLineNum() + " --> " + violation.getEndLineNum() + "\n@@ -" + bugStartLine + ", " + bugEndLine + " +" + fixStartLine + ", " + fixEndLine + "@@\n"; String patchPosition = "\n" + revFile.getName() + "\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 + "\n" + patchPosition + patchHunk.getHunk() + "\nAST Diff###:\n" + getAstEditScripts(hunkActionSets, bugEndPosition, fixEndPosition) + "\n";
String info = Configuration.PATCH_SIGNAL + "\nAlarm Type :" + alarmType + "\n" + patchPosition + patchSourceCode + "\nAST Diff###:\n" + getAstEditScripts(hunkActionSets, bugEndPosition, fixEndPosition) + "\n"; String info = Configuration.PATCH_SIGNAL + "\n" + patchPosition + patchHunk.getHunk() + "\nAST Diff###:\n" + getAstEditScripts(hunkActionSets) + "\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";
// if (noUpdate(editScriptTokens)) { // 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.patchesSourceCode += info;
this.sizes += size + "\n"; this.sizes += size + "\n";
this.astEditScripts += astEditScripts + "\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(); String tokens = Tokenizer.getTokensDeepFirst(simpleTree).trim();
if ("Block Block".equals(tokens)) {
tokens = getContextTokens(patchSourceCode);
}
this.tokensOfSourceCode += tokens + "\n"; 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) { private String getAstEditScripts(List<HierarchicalActionSet> hunkActionSets) {
SimpleTree simpleTree = null; 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(); int vStartLine = patchHunk.getBugLineStartNum();
if ("EQ_DOESNT_OVERRIDE_EQUALS".equals(type)|| "HE_EQUALS_USE_HASHCODE".equals(type) || "HE_INHERITS_EQUALS_USE_HASHCODE".equals(type)|| int vEndLine = vStartLine + patchHunk.getBuggyHunkSize() + 1;
"SE_NO_SUITABLE_CONSTRUCTOR".equals(type) || "RI_REDUNDANT_INTERFACES".equals(type) if (bugStartLine < vStartLine && vEndLine < bugEndLine) {
||"CN_IDIOM".equals(type)||"SE_NO_SERIALVERSIONID".equals(type) || "SE_COMPARATOR_SHOULD_BE_SERIALIZABLE".equals(type)) { ViolationSourceCodeTree parser = new ViolationSourceCodeTree(prevFile, vStartLine, vEndLine);
// Class name level, tokens parser.extract();
// classStartP <= vS <= vE <= classEndP List<ITree> matchedTrees = parser.getViolationSourceCodeTrees();
ViolationSourceCodeTree parser = new ViolationSourceCodeTree(prevFile, violation.getStartLineNum(), violation.getEndLineNum()); if (matchedTrees.size() > 0) {
ITree classNameTree = parser.getClassNameTokens(); for (ITree matchedTree : matchedTrees) {
simpleTree = new SimplifyTree().canonicalizeSourceCodeTree(classNameTree, null); SimpleTree simpleT = new SimplifyTree().canonicalizeSourceCodeTree(matchedTree, simpleTree);
} 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;
}
children.add(simpleT); 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; return simpleTree;
} }
@@ -344,170 +245,4 @@ public class FixedViolationHunkParser extends FixedViolationParser {
actionSets.removeAll(overlappedUpdates); 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 com.github.gumtreediff.actions.model.Action;
import edu.lu.uni.serval.FixPatternParser.Parser; 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.GumTreeComparer;
import edu.lu.uni.serval.gumtree.regroup.HierarchicalActionSet; import edu.lu.uni.serval.gumtree.regroup.HierarchicalActionSet;
import edu.lu.uni.serval.gumtree.regroup.HierarchicalRegrouper; import edu.lu.uni.serval.gumtree.regroup.HierarchicalRegrouper;
import edu.lu.uni.serval.utils.FileHelper; import edu.lu.uni.serval.utils.FileHelper;
import edu.lu.uni.serval.utils.ListSorter; import edu.lu.uni.serval.utils.ListSorter;
import edu.lu.uni.serval.violation.code.parser.ViolationSourceCodeTree;
/** /**
* Parse fix patterns with GumTree. * Parse fix patterns with GumTree.
@@ -36,13 +34,7 @@ public class FixedViolationParser extends Parser {
*/ */
public int resultType = 0; public int resultType = 0;
private File positionFile = null;
protected String violationTypes = ""; protected String violationTypes = "";
// protected List<Violation> uselessViolations;
public void setPositionFile(File positionFile) {
this.positionFile = positionFile;
}
@Override @Override
public void parseFixPatterns(File prevFile, File revFile, File diffentryFile) { 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. * Read patch source code from buggy and fixed files.
* @param prevFile * @param prevFile
@@ -193,60 +131,6 @@ public class FixedViolationParser extends Parser {
return sourceCode; 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() { public String getAlarmTypes() {
return violationTypes; return violationTypes;
} }
@@ -39,7 +39,6 @@ public class FixedViolationSingleStatementParser extends FixedViolationParser {
} }
// Read the positions of checked violations // Read the positions of checked violations
List<Violation> violations = readViolations(prevFile, revFile);
for (HierarchicalActionSet actionSet : actionSets) { for (HierarchicalActionSet actionSet : actionSets) {
// position of buggy statements // position of buggy statements
int startPosition = 0; int startPosition = 0;
@@ -95,7 +94,7 @@ public class FixedViolationSingleStatementParser extends FixedViolationParser {
int startLine2 = revUnit.getLineNumber(startPosition2); int startLine2 = revUnit.getLineNumber(startPosition2);
int endLine2 = revUnit.getLineNumber(endPosition2); int endLine2 = revUnit.getLineNumber(endPosition2);
Violation violation = findViolation(startLine, endLine, violations); Violation violation = null;//findViolation(startLine, endLine, violations);
if (violation == null) continue; if (violation == null) continue;
if (endLine - startLine >= Configuration.HUNK_SIZE - 2 || endLine2 - startLine2 >= Configuration.HUNK_SIZE - 2 ) 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; // int counter = 0;
for (MessageFile msgFile : msgFiles) { for (MessageFile msgFile : msgFiles) {
FixedViolationHunkParser parser = new FixedViolationHunkParser(); FixedViolationHunkParser parser = new FixedViolationHunkParser();
parser.setPositionFile(msgFile.getPositionFile());
final ExecutorService executor = Executors.newSingleThreadExecutor(); final ExecutorService executor = Executors.newSingleThreadExecutor();
// schedule the work // schedule the work
@@ -22,11 +22,28 @@ public class AkkaParser {
private static Logger log = LoggerFactory.getLogger(AkkaParser.class); 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") @SuppressWarnings("deprecation")
public static void main(String[] args) { 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 // input data
log.info("Get the input data..."); log.info("Get the input data...");
// final List<MessageFile> msgFiles = getMessageFiles();
final List<MessageFile> msgFiles = getMessageFiles(Configuration.GUM_TREE_INPUT); final List<MessageFile> msgFiles = getMessageFiles(Configuration.GUM_TREE_INPUT);
log.info("MessageFiles: " + msgFiles.size()); log.info("MessageFiles: " + msgFiles.size());
@@ -35,22 +52,19 @@ public class AkkaParser {
final String patchesSourceCodeFilePath = Configuration.PATCH_SOURCECODE_FILE_PATH; final String patchesSourceCodeFilePath = Configuration.PATCH_SOURCECODE_FILE_PATH;
final String buggyTokensFilePath = Configuration.BUGGY_CODE_TOKEN_FILE_PATH; final String buggyTokensFilePath = Configuration.BUGGY_CODE_TOKEN_FILE_PATH;
final String editScriptSizesFilePath = Configuration.EDITSCRIPT_SIZES_FILE_PATH; final String editScriptSizesFilePath = Configuration.EDITSCRIPT_SIZES_FILE_PATH;
final String alarmTypesFilePath = Configuration.ALARM_TYPES_FILE_PATH;
FileHelper.deleteDirectory(editScriptsFilePath); FileHelper.deleteDirectory(editScriptsFilePath);
FileHelper.deleteDirectory(patchesSourceCodeFilePath); FileHelper.deleteDirectory(patchesSourceCodeFilePath);
FileHelper.deleteDirectory(buggyTokensFilePath); FileHelper.deleteDirectory(buggyTokensFilePath);
FileHelper.deleteDirectory(editScriptSizesFilePath); FileHelper.deleteDirectory(editScriptSizesFilePath);
FileHelper.deleteDirectory(alarmTypesFilePath);
ActorSystem system = null; ActorSystem system = null;
ActorRef parsingActor = null; ActorRef parsingActor = null;
int numberOfWorkers = 431;
final WorkMessage msg = new WorkMessage(0, msgFiles); final WorkMessage msg = new WorkMessage(0, msgFiles);
try { try {
log.info("Akka begins..."); log.info("Akka begins...");
system = ActorSystem.create("Mining-FixPattern-System"); system = ActorSystem.create("Mining-FixPattern-System");
parsingActor = system.actorOf(ParseFixPatternActor.props(numberOfWorkers, editScriptsFilePath, 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()); parsingActor.tell(msg, ActorRef.noSender());
} catch (Exception e) { } catch (Exception e) {
system.shutdown(); 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. * Get violation-related files.
* *
@@ -1,6 +1,5 @@
package edu.lu.uni.serval.MultipleThreadsParser; package edu.lu.uni.serval.MultipleThreadsParser;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.slf4j.Logger; import org.slf4j.Logger;
@@ -21,15 +20,15 @@ public class ParseFixPatternActor extends UntypedActor {
private int counter = 0; private int counter = 0;
public ParseFixPatternActor(int numberOfWorkers, String editScriptsFilePath, String patchesSourceCodeFilePath, 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) mineRouter = this.getContext().actorOf(new RoundRobinPool(numberOfWorkers)
.props(ParseFixPatternWorker.props(editScriptsFilePath, patchesSourceCodeFilePath, .props(ParseFixPatternWorker.props(editScriptsFilePath, patchesSourceCodeFilePath,
buggyTokensFilePath, editScriptSizesFilePath, alarmTypesFilePath)), "mine-fix-pattern-router"); buggyTokensFilePath, editScriptSizesFilePath)), "mine-fix-pattern-router");
this.numberOfWorkers = numberOfWorkers; this.numberOfWorkers = numberOfWorkers;
} }
public static Props props(final int numberOfWorkers, final String editScriptsFilePath, final String patchesSourceCodeFilePath, 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>() { return Props.create(new Creator<ParseFixPatternActor>() {
@@ -38,7 +37,7 @@ public class ParseFixPatternActor extends UntypedActor {
@Override @Override
public ParseFixPatternActor create() throws Exception { public ParseFixPatternActor create() throws Exception {
return new ParseFixPatternActor(numberOfWorkers, editScriptsFilePath, patchesSourceCodeFilePath, return new ParseFixPatternActor(numberOfWorkers, editScriptsFilePath, patchesSourceCodeFilePath,
buggyTokensFilePath, editScriptSizesFilePath, alarmTypesFilePath); buggyTokensFilePath, editScriptSizesFilePath);
} }
}); });
@@ -50,26 +49,25 @@ public class ParseFixPatternActor extends UntypedActor {
if (message instanceof WorkMessage) { if (message instanceof WorkMessage) {
List<MessageFile> files = ((WorkMessage) message).getMsgFiles(); List<MessageFile> files = ((WorkMessage) message).getMsgFiles();
int size = files.size(); 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 ++) { for (int i = 0; i < numberOfWorkers; i ++) {
int fromIndex = i * average; int fromIndex = i * average + counter;
int toIndex = (i + 1) * average; if (counter < reminder) counter ++;
if (i == numberOfWorkers - 1) { int toIndex = (i + 1) * average + counter;
toIndex = size;
}
List<MessageFile> filesOfWorkers = new ArrayList<>(); List<MessageFile> filesOfWorkers = files.subList(fromIndex, toIndex);
filesOfWorkers.addAll(files.subList(fromIndex, toIndex));
final WorkMessage workMsg = new WorkMessage(i + 1, filesOfWorkers); final WorkMessage workMsg = new WorkMessage(i + 1, filesOfWorkers);
mineRouter.tell(workMsg, getSelf()); mineRouter.tell(workMsg, getSelf());
logger.info("Assign a task to worker #" + (i + 1) + "..."); logger.info("Assign a task to worker #" + (i + 1) + "...");
} }
} else if ("STOP".equals(message.toString())) { } else if ("STOP".equals(message.toString())) {
counter ++; counter ++;
logger.info(counter + " workers finished their work..."); logger.info(counter + " workers finailized their work...");
if (counter >= numberOfWorkers) { if (counter >= numberOfWorkers) {
logger.info("All workers finished their work..."); logger.info("All workers finailized their work...");
this.getContext().stop(mineRouter); this.getContext().stop(mineRouter);
this.getContext().stop(getSelf()); this.getContext().stop(getSelf());
this.getContext().system().shutdown(); this.getContext().system().shutdown();
@@ -31,19 +31,17 @@ public class ParseFixPatternWorker extends UntypedActor {
private String patchesSourceCodeFilePath; private String patchesSourceCodeFilePath;
private String editScriptSizesFilePath; private String editScriptSizesFilePath;
private String buggyTokensFilePath; private String buggyTokensFilePath;
private String alarmTypesFilePath;
public ParseFixPatternWorker(String editScriptsFilePath, String patchesSourceCodeFilePath, public ParseFixPatternWorker(String editScriptsFilePath, String patchesSourceCodeFilePath,
String buggyTokensFilePath, String editScriptSizesFilePath, String alarmTypesFilePath) { String buggyTokensFilePath, String editScriptSizesFilePath) {
this.editScriptsFilePath = editScriptsFilePath; this.editScriptsFilePath = editScriptsFilePath;
this.patchesSourceCodeFilePath = patchesSourceCodeFilePath; this.patchesSourceCodeFilePath = patchesSourceCodeFilePath;
this.editScriptSizesFilePath = editScriptSizesFilePath; this.editScriptSizesFilePath = editScriptSizesFilePath;
this.buggyTokensFilePath = buggyTokensFilePath; this.buggyTokensFilePath = buggyTokensFilePath;
this.alarmTypesFilePath = alarmTypesFilePath;
} }
public static Props props(final String editScriptsFile, final String patchesSourceCodeFile, final String buggyTokensFilePath, 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>() { return Props.create(new Creator<ParseFixPatternWorker>() {
private static final long serialVersionUID = -7615153844097275009L; private static final long serialVersionUID = -7615153844097275009L;
@@ -51,7 +49,7 @@ public class ParseFixPatternWorker extends UntypedActor {
@Override @Override
public ParseFixPatternWorker create() throws Exception { public ParseFixPatternWorker create() throws Exception {
return new ParseFixPatternWorker(editScriptsFile, patchesSourceCodeFile, return new ParseFixPatternWorker(editScriptsFile, patchesSourceCodeFile,
buggyTokensFilePath, editScriptSizesFilePath, alarmTypesFilePath); buggyTokensFilePath, editScriptSizesFilePath);
} }
}); });
@@ -66,13 +64,11 @@ public class ParseFixPatternWorker extends UntypedActor {
StringBuilder patchesSourceCode = new StringBuilder(); StringBuilder patchesSourceCode = new StringBuilder();
StringBuilder sizes = new StringBuilder(); StringBuilder sizes = new StringBuilder();
StringBuilder tokens = new StringBuilder(); StringBuilder tokens = new StringBuilder();
StringBuilder alarmTypes = new StringBuilder();
StringBuilder testingInfo = new StringBuilder(); StringBuilder testingInfo = new StringBuilder();
int id = msg.getId(); int id = msg.getId();
int counter = 0; int counter = 0;
int testViolations = 0;
int nullGumTreeResults = 0; int nullGumTreeResults = 0;
int noSourceCodeChanges = 0; int noSourceCodeChanges = 0;
int noStatementChanges = 0; int noStatementChanges = 0;
@@ -85,28 +81,15 @@ public class ParseFixPatternWorker extends UntypedActor {
int timeouts = 0; int timeouts = 0;
StringBuilder builder = new StringBuilder(); 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) { for (MessageFile msgFile : files) {
File revFile = msgFile.getRevFile(); File revFile = msgFile.getRevFile();
File prevFile = msgFile.getPrevFile(); File prevFile = msgFile.getPrevFile();
File diffentryFile = msgFile.getDiffEntryFile(); File diffentryFile = msgFile.getDiffEntryFile();
File positionFile = msgFile.getPositionFile(); File positionFile = msgFile.getPositionFile();
if (revFile.getName().toLowerCase().contains("test#") || revFile.getName().toLowerCase().contains("tests#")) { if (revFile.getName().toLowerCase().contains("test")) {
// testViolations += countAlarms(positionFile, "#TestViolation:", uselessViolations);
testViolations += countAlarms(positionFile, "#TestViolation:");
continue; continue;
} }
// Parser parser = null; FixedViolationHunkParser parser = new FixedViolationHunkParser();
// if (containsAlarmTypes || positionFile != null) {
// parser = new FixedViolationHunkParser(positionFile);
// containsAlarmTypes = true;
// } else {
// parser = new CommitPatchSingleStatementParser();
// }
FixedViolationHunkParser parser = new FixedViolationHunkParser(positionFile);
// parser.setUselessViolations(uselessViolations);
final ExecutorService executor = Executors.newSingleThreadExecutor(); final ExecutorService executor = Executors.newSingleThreadExecutor();
// schedule the work // schedule the work
@@ -128,20 +111,15 @@ public class ParseFixPatternWorker extends UntypedActor {
if ("".equals(editScript)) { if ("".equals(editScript)) {
if (parser.resultType == 1) { if (parser.resultType == 1) {
nullGumTreeResults += countAlarms(positionFile, ""); nullGumTreeResults += countAlarms(positionFile, "");
// System.err.println("#NullGumTreeResult:" + revFile.getName());
} else if (parser.resultType == 2) { } else if (parser.resultType == 2) {
noSourceCodeChanges += countAlarms(positionFile, ""); noSourceCodeChanges += countAlarms(positionFile, "");
} else if (parser.resultType == 3) { } else if (parser.resultType == 3) {
noStatementChanges += countAlarms(positionFile, ""); noStatementChanges += countAlarms(positionFile, "");
// } else if (parser.resultType == 4) {
// illegalV += countAlarms(positionFile, "", uselessViolations);
} }
} else { } else {
editScripts.append(editScript); editScripts.append(editScript);
patchesSourceCode.append(parser.getPatchesSourceCode()); patchesSourceCode.append(parser.getPatchesSourceCode());
sizes.append(parser.getSizes()); sizes.append(parser.getSizes());
// tokens.append(parser.getTokensOfSourceCode());
alarmTypes.append(parser.getAlarmTypes());
tokens.append(parser.getTokensOfSourceCode()); tokens.append(parser.getTokensOfSourceCode());
counter ++; counter ++;
@@ -154,26 +132,23 @@ public class ParseFixPatternWorker extends UntypedActor {
patchesSourceCode.setLength(0); patchesSourceCode.setLength(0);
sizes.setLength(0); sizes.setLength(0);
tokens.setLength(0); tokens.setLength(0);
FileHelper.outputToFile(alarmTypesFilePath + "alarmTypes_" + id + ".list", alarmTypes, true); log.info("Worker #" + id +" finialized parsing " + counter + " files...");
alarmTypes.setLength(0);
log.info("Worker #" + id +"Finish of parsing " + counter + " files...");
FileHelper.outputToFile("OUTPUT/testingInfo_" + id + ".list", testingInfo, true); FileHelper.outputToFile("OUTPUT/testingInfo_" + id + ".list", testingInfo, true);
testingInfo.setLength(0); testingInfo.setLength(0);
} }
} }
} catch (TimeoutException e) { } catch (TimeoutException e) {
// err.println("task timed out");
future.cancel(true); future.cancel(true);
timeouts += countAlarms(positionFile, "#Timeout:"); timeouts += countAlarms(positionFile, "#Timeout:");
// System.err.println("#Timeout: " + revFile.getName()); System.err.println("#Timeout: " + revFile.getName());
} catch (InterruptedException e) { } catch (InterruptedException e) {
timeouts += countAlarms(positionFile, "#TimeInterrupted:"); 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) { } catch (ExecutionException e) {
timeouts += countAlarms(positionFile, "#TimeAborted:"); timeouts += countAlarms(positionFile, "#TimeAborted:");
// err.println("task aborted"); System.err.println("#TimeAborted: " + revFile.getName());
// System.err.println("#TimeAborted: " + revFile.getName()); e.printStackTrace();
} finally { } finally {
executor.shutdownNow(); executor.shutdownNow();
} }
@@ -189,58 +164,24 @@ public class ParseFixPatternWorker extends UntypedActor {
sizes.setLength(0); sizes.setLength(0);
tokens.setLength(0); tokens.setLength(0);
FileHelper.outputToFile(alarmTypesFilePath + "alarmTypes_" + id + ".list", alarmTypes, true);
alarmTypes.setLength(0);
FileHelper.outputToFile("OUTPUT/testingInfo_" + id + ".list", testingInfo, true); FileHelper.outputToFile("OUTPUT/testingInfo_" + id + ".list", testingInfo, true);
testingInfo.setLength(0); testingInfo.setLength(0);
} }
String statistic = "TestViolations: " + testViolations + "\nNullGumTreeResults: " + nullGumTreeResults + "\nNoSourceCodeChanges: " + noSourceCodeChanges + String statistic = "\nNullGumTreeResults: " + nullGumTreeResults + "\nNoSourceCodeChanges: " + noSourceCodeChanges +
"\nNoStatementChanges: " + noStatementChanges + "\nNullDiffEntry: " + nullDiffEntry + "\nNullMatchedGumTreeResults: " + nullMappingGumTreeResults + "\nNoStatementChanges: " + noStatementChanges + "\nNullDiffEntry: " + nullDiffEntry + "\nNullMatchedGumTreeResults: " + nullMappingGumTreeResults +
"\nPureDeletion: " + pureDeletion + "\nLargeHunk: " + largeHunk + "\nNullSourceCode: " + nullSourceCode + "\nPureDeletion: " + pureDeletion + "\nLargeHunk: " + largeHunk + "\nNullSourceCode: " + nullSourceCode +
"\nTestingInfo: " + testInfos + "\nTimeout: " + timeouts; "\nTestingInfo: " + testInfos + "\nTimeout: " + timeouts;
FileHelper.outputToFile("OUTPUT/statistic_" + id + ".list", statistic, false); FileHelper.outputToFile("OUTPUT/statistic_" + id + ".list", statistic, false);
FileHelper.outputToFile("OUTPUT/UnfixedV_" + id + ".list", builder, false); FileHelper.outputToFile("OUTPUT/UnfixedV_" + id + ".list", builder, false);
log.info("Worker #" + id +"Finish of parsing " + counter + " files..."); log.info("Worker #" + id +"finialized parsing " + counter + " files...");
log.info("Worker #" + id + " finished the work..."); log.info("Worker #" + id + " finialized the work...");
this.getSender().tell("STOP", getSelf()); this.getSender().tell("STOP", getSelf());
} else { } else {
unhandled(message); 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) { private int countAlarms(File positionFile, String type) {//, List<Violation> uselessViolations) {
int counter = 0; int counter = 0;
String content = FileHelper.readFile(positionFile); String content = FileHelper.readFile(positionFile);
@@ -66,7 +66,7 @@ public class SingleThreadParser {
testViolations += countAlarms(positionFile, "#TestViolation:"); testViolations += countAlarms(positionFile, "#TestViolation:");
continue; continue;
} }
FixedViolationHunkParser parser = new FixedViolationHunkParser(positionFile); FixedViolationHunkParser parser = new FixedViolationHunkParser();
// parser.setUselessViolations(uselessViolations); // parser.setUselessViolations(uselessViolations);
final ExecutorService executor = Executors.newSingleThreadExecutor(); final ExecutorService executor = Executors.newSingleThreadExecutor();
@@ -2,11 +2,11 @@ package edu.lu.uni.serval.config;
public class Configuration { 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 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. 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 SUPERVISED_LEARNING_MODEL = ROOT_PATH + "TestingOutput/SupervisedLearningModel.zip";
public static final String FEATURES_OF_COMMON_CLUSTERS = ROOT_PATH + "FeaturesOfCommonClusters/"; 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; 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 { public class DiffEntryHunk {
private int bugLineStartNum; private int bugLineStartNum;
@@ -10,6 +15,7 @@ public class DiffEntryHunk {
private int buggyHunkSize; private int buggyHunkSize;
private int fixedHunkSize; private int fixedHunkSize;
private String file; private String file;
private List<HierarchicalActionSet> actionSets = new ArrayList<>();
public DiffEntryHunk(int bugLineStartNum, int fixLineStartNum, int bugRange, int fixRange) { public DiffEntryHunk(int bugLineStartNum, int fixLineStartNum, int bugRange, int fixRange) {
super(); super();
@@ -66,6 +72,10 @@ public class DiffEntryHunk {
public void setFile(String file) { public void setFile(String file) {
this.file = file; this.file = file;
} }
public List<HierarchicalActionSet> getActionSets() {
return actionSets;
}
@Override @Override
public String toString() { public String toString() {
@@ -214,7 +214,7 @@ public class HierarchicalActionSet implements Comparable<HierarchicalActionSet>
actionSet.toString(); actionSet.toString();
List<String> strList1 = actionSet.strList; List<String> strList1 = actionSet.strList;
for (String str1 : strList1) { for (String str1 : strList1) {
strList.add("----" + str1); strList.add("---" + str1);
} }
} }
} else { } else {
@@ -224,7 +224,7 @@ public class HierarchicalActionSet implements Comparable<HierarchicalActionSet>
actionSet.toString(); actionSet.toString();
List<String> strList1 = actionSet.strList; List<String> strList1 = actionSet.strList;
for (String str1 : strList1) { for (String str1 : strList1) {
strList.add("----" + str1); strList.add("---" + str1);
} }
} }
} }
@@ -361,237 +361,56 @@ public class HunkActionFilter {
* @param prevFile * @param prevFile
* @return * @return
*/ */
public List<Violation> filterActionsByModifiedRange2(List<Violation> violations, public List<DiffEntryHunk> filterActionsByModifiedRange2(List<DiffEntryHunk> diffentryHunks,
List<HierarchicalActionSet> actionSets, File revFile, File prevFile) { List<HierarchicalActionSet> actionSets, File revFile, File prevFile) {
List<Violation> selectedViolations = new ArrayList<>(); List<DiffEntryHunk> selectedViolations = new ArrayList<>();
CUCreator cuCreator = new CUCreator(); CUCreator cuCreator = new CUCreator();
CompilationUnit prevUnit = cuCreator.createCompilationUnit(prevFile); CompilationUnit prevUnit = cuCreator.createCompilationUnit(prevFile);
CompilationUnit revUnit = cuCreator.createCompilationUnit(revFile); CompilationUnit revUnit = cuCreator.createCompilationUnit(revFile);
if (prevUnit == null || revUnit == null) { if (prevUnit == null || revUnit == null) {
for (Violation violation : violations) {
this.unfixedViolations += "#NullMatchedGumTreeResult:" + revFile.getName() + ":" +violation.getStartLineNum() + ":" +
violation.getEndLineNum() + ":" + violation.getViolationType() + "\n";
}
return selectedViolations; return selectedViolations;
} }
for (Violation violation : violations) { for (DiffEntryHunk diffentryHunk : diffentryHunks) {
int violationStartLine = violation.getStartLineNum(); // int violationEndLine = violationStartLine + diffentryHunk.getBugRange();
int violationEndLine = violation.getEndLineNum(); int bugHunkStartLine = diffentryHunk.getBugLineStartNum();
int bugHunkStartLine = violation.getBugStartLineNum(); int bugHunkEndLine = bugHunkStartLine + diffentryHunk.getBugRange() - 1;
int fixHunkStartLine = diffentryHunk.getFixLineStartNum();
int fixHunkEndLine = fixHunkStartLine + diffentryHunk.getFixedHunkSize() - 1;
if (!specialVioaltionTypes(violation, actionSets, prevUnit, revUnit)) { for (HierarchicalActionSet actionSet : actionSets) {
if (bugHunkStartLine == 0) {// Null source code matched for this violation. int actionBugStartLine = actionSet.getBugStartLineNum();
// String type = getType(violation); if (actionBugStartLine == 0) {
} else if (bugHunkStartLine == -1) {// actionBugStartLine = setLineNumbers(actionSet, prevUnit, revUnit);
// specialVioaltionTypes(violation, actionSets, prevUnit, revUnit); }
} else { int actionBugEndLine = actionSet.getBugEndLineNum();
int bugHunkEndLine = violation.getBugEndLineNum(); int actionFixStartLine = actionSet.getFixStartLineNum();
int fixHunkStartLine = violation.getFixStartLineNum(); int actionFixEndLine = actionSet.getFixEndLineNum();
int fixHunkEndLine = violation.getFixEndLineNum();
int bugFixStartLineNum = violation.getBugFixStartLineNum(); String actionStr = actionSet.getActionString();
int bugFixEndLineNum = violation.getBugFixEndLineNum(); if (actionStr.startsWith("INS")) {
if (fixHunkStartLine <= actionFixEndLine && fixHunkEndLine >= actionFixStartLine ) {
for (HierarchicalActionSet actionSet : actionSets) { if (actionBugStartLine != 0) {
int actionBugStartLine = actionSet.getBugStartLineNum(); diffentryHunk.getActionSets().add(actionSet);
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);
}
}
} }
} }
} else {
if (bugHunkStartLine <= actionBugEndLine && bugHunkEndLine >= actionBugStartLine) {
diffentryHunk.getActionSets().add(actionSet);
}
} }
} }
if (violation.getActionSets().size() > 0) { if (diffentryHunk.getActionSets().size() > 0) {
selectedViolations.add(violation); selectedViolations.add(diffentryHunk);
} else {
this.unfixedViolations += "#NullMatchedGumTreeResult:" + revFile.getName() + ":" +violation.getStartLineNum() + ":" +
violation.getEndLineNum() + ":" + violation.getViolationType() + "\n";
} }
} }
return selectedViolations; 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. * Filter out the modify actions, which are not in the DiffEntry hunks, without considering DiffEntry hunks.