Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
package tfm.cli;
import com.github.javaparser.JavaParser;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.NodeList;
import com.github.javaparser.ast.comments.BlockComment;
import com.github.javaparser.symbolsolver.JavaSymbolSolver;
import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
import org.apache.commons.cli.*;
import tfm.graphs.cfg.CFG;
import tfm.graphs.exceptionsensitive.ESSDG;
import tfm.graphs.sdg.SDG;
import tfm.nodes.GraphNode;
import tfm.slicing.NodeIdSlicingCriterion;
import tfm.slicing.Slice;
import tfm.slicing.SlicingCriterion;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
public class PHPSlice {
protected static final Options OPTIONS = new Options();
static {
OPTIONS.addOption(Option
.builder("f")
.hasArg().argName("CriterionFile.java").type(File.class)
.required()
.desc("The file that contains the slicing criterion.")
.build());
OPTIONS.addOption(Option
.builder("i")
.hasArg().argName("node_id")
.required()
.desc("The slicing criterion, in the form of a node id (a positive integer).")
.build());
OPTIONS.addOption(Option
.builder("o")
.hasArg().argName("output_file")
.required()
.desc("The folder where the slice and the graphs should be placed")
.build());
OPTIONS.addOption("es", "exception-sensitive", false, "Enable exception-sensitive analysis");
OPTIONS.addOption(Option
.builder("h").longOpt("help")
.desc("Shows this text")
.build());
}
private final File outputDir;
private File scFile;
private int scId;
private final CommandLine cliOpts;
public PHPSlice(String... cliArgs) throws ParseException {
cliOpts = new DefaultParser().parse(OPTIONS, cliArgs);
if (cliOpts.hasOption('h'))
throw new ParseException(OPTIONS.toString());
setScId(Integer.parseInt(cliOpts.getOptionValue("i")));
setScFile(cliOpts.getOptionValue("f"));
outputDir = new File(cliOpts.getOptionValue("o"));
if (!outputDir.isDirectory())
throw new ParseException("The output directory is not a directory or not readable by us!");
}
private void setScFile(String fileName) throws ParseException {
File file = new File(fileName);
if (!(file.exists() && file.isFile()))
throw new ParseException("Slicing criterion file is not an existing file.");
scFile = file;
}
private void setScId(int line) throws ParseException {
if (line < 0)
throw new ParseException("The line of the slicing criterion must be strictly greater than zero.");
scId = line;
}
public void slice() throws ParseException, IOException {
// Configure JavaParser
CombinedTypeSolver combinedTypeSolver = new CombinedTypeSolver();
combinedTypeSolver.add(new ReflectionTypeSolver(true));
JavaParser.getStaticConfiguration().setSymbolResolver(new JavaSymbolSolver(combinedTypeSolver));
JavaParser.getStaticConfiguration().setAttributeComments(false);
// Build the SDG
NodeList<CompilationUnit> units = new NodeList<>();
try {
units.add(JavaParser.parse(scFile));
} catch (FileNotFoundException e) {
throw new ParseException(e.getMessage());
}
SDG sdg = cliOpts.hasOption("exception-sensitive") ? new ESSDG() : new SDG();
sdg.build(units);
SlicingCriterion sc = new NodeIdSlicingCriterion(0, "");
Slice slice = new Slice();
if (scId != 0) {
// Slice the SDG
sc = new NodeIdSlicingCriterion(scId, "");
slice = sdg.slice(sc);
// Convert the slice to code and output the result to `outputDir`
for (CompilationUnit cu : slice.toAst()) {
if (cu.getStorage().isEmpty())
throw new IllegalStateException("A synthetic CompilationUnit was discovered, with no file associated to it.");
File javaFile = new File(outputDir, cu.getStorage().get().getFileName());
try (PrintWriter pw = new PrintWriter(javaFile)) {
pw.print(new BlockComment(getDisclaimer(cu.getStorage().get())));
pw.print(cu);
} catch (FileNotFoundException e) {
System.err.println("Could not write file " + javaFile);
}
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
}
}
File imageDir = new File(outputDir, "images");
imageDir.mkdir();
// Output the sliced graph to the output directory
SDGLog sdgLog = new SlicedSDGLog(sdg, slice, sc);
sdgLog.setDirectory(outputDir);
sdgLog.generateImages("graph", "svg");
for (CFG cfg : sdg.getCFGs()) {
CFGLog log = new CFGLog(cfg);
log.setDirectory(imageDir);
log.generateImages("root" + cfg.getRootNode().map(GraphNode::getId).orElse(-1L), "svg");
}
}
protected String getDisclaimer(CompilationUnit.Storage s) {
return String.format("\n\tThis file was automatically generated as part of a slice with criterion" +
"\n\tnode id: %d\n\tOriginal file: %s\n", scId, s.getPath());
}
public static void main(String... args) {
try {
new PHPSlice(args).slice();
} catch (Exception e) {
System.err.println("Error!\n" + e.getMessage());