Loading iacfg/src/main/java/es/upv/mist/slicing/graphs/icfg/ICFG.java +50 −29 Original line number Diff line number Diff line Loading @@ -12,7 +12,6 @@ import es.upv.mist.slicing.arcs.cfg.ControlFlowArc; import es.upv.mist.slicing.graphs.Buildable; import es.upv.mist.slicing.graphs.CallGraph; import es.upv.mist.slicing.graphs.ClassGraph; import es.upv.mist.slicing.graphs.Graph; import es.upv.mist.slicing.graphs.augmented.ACFG; import es.upv.mist.slicing.graphs.cfg.CFG; import es.upv.mist.slicing.graphs.sdg.InterproceduralDefinitionFinder; Loading @@ -23,8 +22,10 @@ import es.upv.mist.slicing.nodes.io.ActualIONode; import es.upv.mist.slicing.nodes.io.CallNode; import es.upv.mist.slicing.nodes.io.MethodExitNode; import es.upv.mist.slicing.utils.ASTUtils; import org.jgrapht.Graph; import org.jgrapht.alg.connectivity.KosarajuStrongConnectivityInspector; import org.jgrapht.graph.DefaultDirectedGraph; import org.jgrapht.graph.DefaultEdge; import java.util.*; Loading @@ -33,13 +34,15 @@ import static es.upv.mist.slicing.util.SingletonCollector.toSingleton; /** * An interprocedural CFG, whose component CFGs are built as ACFGs. */ public class ICFG extends Graph implements Buildable<NodeList<CompilationUnit>> { public class ICFG extends es.upv.mist.slicing.graphs.Graph implements Buildable<NodeList<CompilationUnit>> { protected final Map<CallableDeclaration<?>, CFG> cfgMap = ASTUtils.newIdentityHashMap(); protected boolean built = false; public void addControlFlowArc(GraphNode<?> from, GraphNode<?> to) { addEdge(from, to, new ControlFlowArc()); public ControlFlowArc addControlFlowArc(GraphNode<?> from, GraphNode<?> to) { ControlFlowArc a = new ControlFlowArc(); addEdge(from, to, a); return a; } public void addNonExecControlFlowArc(GraphNode<?> from, GraphNode<?> to) { Loading Loading @@ -68,7 +71,9 @@ public class ICFG extends Graph implements Buildable<NodeList<CompilationUnit>> public class Builder { protected CallGraph callGraph; protected List<Set<Object>> scrs; protected final Map<CallGraph.Edge<?>, List<ControlFlowArc>> callGraphEdge2ICFGArcMap = new HashMap<>(); protected Graph<Graph<GraphNode<?>, Arc>, DefaultEdge> intraSCRs = new DefaultDirectedGraph<>(null, null, false); public void build(NodeList<CompilationUnit> units) { createClassGraph(units); Loading @@ -87,36 +92,51 @@ public class ICFG extends Graph implements Buildable<NodeList<CompilationUnit>> copyCFGs(); expandCalls(); joinCFGs(); getSCRs(callGraph); intraSCRs = computeIntraSCRs(); } protected void getSCRs(CallGraph callGraph) { DefaultDirectedGraph<Object, CallGraph.Edge> convertedCallGraph = deleteDuplicatedEdges(callGraph); KosarajuStrongConnectivityInspector<Object, CallGraph.Edge> inspector = new KosarajuStrongConnectivityInspector<>(convertedCallGraph); scrs = inspector.stronglyConnectedSets(); protected Graph<Graph<GraphNode<?>, Arc>, DefaultEdge> computeIntraSCRs() { // 1. Copiar el ICFG a un nuevo grafo sin arcos duplicados. (opcional) var simpleICFG = deleteDuplicatedEdges(ICFG.this); // 2. Compute cSCR graph var cSCRs = computeCallSCRs(); // 3. Borrar del ICFG todos los arcos que aparecen en cSCRs for (DefaultEdge e : cSCRs.edgeSet()) { int callsDeleted = 0; for (CallGraph.Vertex src : cSCRs.getEdgeSource(e).vertexSet()) { for (CallGraph.Vertex tgt : cSCRs.getEdgeTarget(e).vertexSet()) { // 3a. Buscar el arco(s) correspondiente en el callgraph for (CallGraph.Edge<?> callEdge : callGraph.getAllEdges(src, tgt)) { // 3b. Buscar el arco(s) correspondientes en el simpleICFG y borrarlos for (ControlFlowArc controlFlowArc : callGraphEdge2ICFGArcMap.get(callEdge)) if (simpleICFG.removeEdge(controlFlowArc)) callsDeleted++; } public static DefaultDirectedGraph<Object, CallGraph.Edge> deleteDuplicatedEdges(CallGraph callGraph) { DefaultDirectedGraph<Object, CallGraph.Edge> simpleGraph = new DefaultDirectedGraph<>(CallGraph.Edge.class); for (CallGraph.Vertex v : callGraph.vertexSet()) { simpleGraph.addVertex(v); } } if (callsDeleted < 2) throw new IllegalStateException("The creation of intraSCRs did not delete the minimum amount of call/return arcs"); if (callsDeleted % 2 == 1) throw new IllegalStateException("The creation of intraSCRs missed a call or a return arc"); } // 4. Generar los SCR del simpleICFG, para producir los intraSCRs return new KosarajuStrongConnectivityInspector<>(simpleICFG).getCondensation(); } Map<String, CallGraph.Edge<?>> edgeMap = new HashMap<>(); for (CallGraph.Edge<?> edge : callGraph.edgeSet()) { CallGraph.Vertex src = callGraph.getEdgeSource(edge); CallGraph.Vertex tgt = callGraph.getEdgeTarget(edge); protected Graph<Graph<CallGraph.Vertex, CallGraph.Edge<?>>, DefaultEdge> computeCallSCRs() { return new KosarajuStrongConnectivityInspector<>(deleteDuplicatedEdges(callGraph)).getCondensation(); } String key = src.getDeclaration().getDeclarationAsString() + "->" + tgt.getDeclaration().getDeclarationAsString(); public static <V, E> DefaultDirectedGraph<V, E> deleteDuplicatedEdges(Graph<V, E> baseGraph) { DefaultDirectedGraph<V, E> simpleGraph = new DefaultDirectedGraph<>(null, null, false); if (!edgeMap.containsKey(key)) { for (V v : baseGraph.vertexSet()) simpleGraph.addVertex(v); for (E edge : baseGraph.edgeSet()) { V src = baseGraph.getEdgeSource(edge); V tgt = baseGraph.getEdgeTarget(edge); if (!simpleGraph.containsEdge(src, tgt)) simpleGraph.addEdge(src, tgt, edge); edgeMap.put(key, edge); } } return simpleGraph; Loading Loading @@ -358,8 +378,9 @@ public class ICFG extends Graph implements Buildable<NodeList<CompilationUnit>> GraphNode<?> enterNode = cfgMap.get(callGraph.getEdgeTarget(call).getDeclaration()).getRootNode(); GraphNode<?> exitNode = cfgMap.get(callGraph.getEdgeTarget(call).getDeclaration()).getExitNode(); // Connections addControlFlowArc(callNode, enterNode); addControlFlowArc(exitNode, returnNode); ControlFlowArc call2enter = addControlFlowArc(callNode, enterNode); ControlFlowArc exit2return = addControlFlowArc(exitNode, returnNode); callGraphEdge2ICFGArcMap.put(call, List.of(call2enter, exit2return)); } } Loading iacfg/src/test/java/es/upv/mist/slicing/graphs/icfg/GraphLogIntraSCR.java 0 → 100644 +153 −0 Original line number Diff line number Diff line package es.upv.mist.slicing.graphs.icfg; import es.upv.mist.slicing.arcs.Arc; import es.upv.mist.slicing.cli.DOTAttributes; import es.upv.mist.slicing.nodes.GraphNode; import es.upv.mist.slicing.utils.Logger; import org.jgrapht.Graph; import org.jgrapht.graph.DefaultEdge; import org.jgrapht.nio.dot.DOTExporter; import java.awt.*; import java.io.*; import java.util.stream.Collectors; public abstract class GraphLogIntraSCR<G extends Graph<Graph<GraphNode<?>, Arc>, DefaultEdge>> { protected G graph; protected String imageName; protected String format; protected boolean generated = false; protected File outputDir = new File("./out/"); public GraphLogIntraSCR() { this(null); } public GraphLogIntraSCR(G graph) { this.graph = graph; } public void setDirectory(File outputDir) { this.outputDir = outputDir; } public void log() throws IOException { Logger.log( "****************************\n" + "* GRAPH *\n" + "****************************" ); Logger.log(graph); Logger.log( "****************************\n" + "* GRAPHVIZ *\n" + "****************************" ); try (StringWriter stringWriter = new StringWriter()) { getDOTExporter().exportGraph(graph, stringWriter); stringWriter.append('\n'); Logger.log(stringWriter.toString()); } } public void generateImages() throws IOException { generateImages("graph"); } public void generateImages(String imageName) throws IOException { generateImages(imageName, "pdf"); } public void generateImages(String imageName, String format) throws IOException { this.format = format; generated = true; File tmpDot = getDotFile(imageName); // Graph -> DOT -> file try (Writer w = new FileWriter(tmpDot)) { getDOTExporter().exportGraph(graph, w); } // Execute dot ProcessBuilder pb = new ProcessBuilder("dot", tmpDot.getAbsolutePath(), "-T" + format, "-o", getImageFile().getAbsolutePath()); try { int result = pb.start().waitFor(); if (result == 0) tmpDot.deleteOnExit(); else Logger.log("Image generation failed, try running \"" + pb.toString() + "\" on your terminal."); } catch (InterruptedException e) { Logger.log("Image generation failed\n" + e.getMessage()); } } public File getDotFile(String imageName) throws IOException { this.imageName = imageName + "-" + graph.getClass().getSimpleName(); File tmpDot = File.createTempFile("graph-source-", ".dot"); tmpDot.getParentFile().mkdirs(); getImageFile().getParentFile().mkdirs(); // Graph -> DOT -> file try (Writer w = new FileWriter(tmpDot)) { getDOTExporter().exportGraph(graph, w); } return tmpDot; } public void openVisualRepresentation() throws IOException { if (!generated) generateImages(); openFileForUser(getImageFile()); } protected static void openFileForUser(File file) throws IOException { if (Desktop.isDesktopSupported()) { Desktop.getDesktop().open(file); return; } // Alternative manual opening of the file String os = System.getProperty("os.name").toLowerCase(); String cmd = null; if (os.contains("win")) { cmd = ""; } else if (os.contains("mac")) { cmd = "open"; } else if (os.contains("nix") || os.contains("nux") || os.contains("aix")) { cmd = "xdg-open"; } if (cmd != null) { new ProcessBuilder(cmd, file.getAbsolutePath()).start(); } else { Logger.format("Warning: cannot open file %s in your system (%s)", file.getName(), os); } } public File getImageFile() { return new File(outputDir, imageName + "." + format); } protected DOTExporter<Graph<GraphNode<?>, Arc>, DefaultEdge> getDOTExporter() { DOTExporter<Graph<GraphNode<?>, Arc>, DefaultEdge> exporter = new DOTExporter<>(); exporter.setVertexIdProvider(node -> String.valueOf(node.vertexSet().stream().map(GraphNode::getId).findFirst().orElse(-1L))); exporter.setVertexAttributeProvider(v -> vertexAttributes(v).build()); exporter.setEdgeAttributeProvider(v -> edgeAttributes(v).build()); return exporter; } protected DOTAttributes vertexAttributes(Graph<GraphNode<?>, Arc> vertex) { DOTAttributes res = new DOTAttributes(); res.set("label", vertex.vertexSet().stream() .map(graphNode -> "%04d: %s".formatted(graphNode.getId(), graphNode.getLabel())) .sorted() .collect(Collectors.joining("\n"))); return res; } protected DOTAttributes edgeAttributes(DefaultEdge arc) { return new DOTAttributes(); } } iacfg/src/test/java/es/upv/mist/slicing/graphs/icfg/ICFGTest.java +4 −1 Original line number Diff line number Diff line Loading @@ -26,8 +26,11 @@ public class ICFGTest { createGraph("TestInlineFunctions.java", "grafoInlineVariables"); System.out.println("Grafo 4 generado..."); createGraph("TestExamplePaper.java", "grafoInlineVariables"); createGraph("TestExamplePaper.java", "grafoPaper"); System.out.println("Grafo 5 generado..."); createGraph("TestExamplePaperSimple.java", "grafoPaperSimple"); System.out.println("Grafo 6 generado..."); } private static void createGraph(String fileName, String graphName) throws IOException { Loading iacfg/src/test/resources/TestExamplePaperSimple.java 0 → 100644 +78 −0 Original line number Diff line number Diff line public class TestExamplePaperSimple { public static void main(String[] args) { System.out.println("LLAMAMOS P"); while (1 > 2) { System.out.println("S1"); p1(); System.out.println("S2"); p1(); System.out.println("S3"); } if (1 > 2) { System.out.println("S4"); r1(); System.out.println("S5"); } else { System.out.println("S6"); r1(); System.out.println("S7"); } if (20 < 10) { while (10 > 0) { r1(); System.out.println("S9"); } } else { while (10 > 0) { r1(); System.out.println("S10"); } } System.out.println("S11"); l(); System.out.println("S12"); } public static void p1() { p2(); } public static void p2() { p3(); } public static void p3() { while (1 > 2) { System.out.println("P3!"); } } public static void r1() { System.out.println("S20"); if (21 > 0) { r1(); } System.out.println("S23"); System.out.println("S24"); } public static void l() { if (1 > 0) { m(); System.out.println("L3"); } } public static void m() { if (1 > 0) { n(); System.out.println("M3"); } } public static void n() { if (1 > 0) { l(); System.out.println("N3"); } } } No newline at end of file Loading
iacfg/src/main/java/es/upv/mist/slicing/graphs/icfg/ICFG.java +50 −29 Original line number Diff line number Diff line Loading @@ -12,7 +12,6 @@ import es.upv.mist.slicing.arcs.cfg.ControlFlowArc; import es.upv.mist.slicing.graphs.Buildable; import es.upv.mist.slicing.graphs.CallGraph; import es.upv.mist.slicing.graphs.ClassGraph; import es.upv.mist.slicing.graphs.Graph; import es.upv.mist.slicing.graphs.augmented.ACFG; import es.upv.mist.slicing.graphs.cfg.CFG; import es.upv.mist.slicing.graphs.sdg.InterproceduralDefinitionFinder; Loading @@ -23,8 +22,10 @@ import es.upv.mist.slicing.nodes.io.ActualIONode; import es.upv.mist.slicing.nodes.io.CallNode; import es.upv.mist.slicing.nodes.io.MethodExitNode; import es.upv.mist.slicing.utils.ASTUtils; import org.jgrapht.Graph; import org.jgrapht.alg.connectivity.KosarajuStrongConnectivityInspector; import org.jgrapht.graph.DefaultDirectedGraph; import org.jgrapht.graph.DefaultEdge; import java.util.*; Loading @@ -33,13 +34,15 @@ import static es.upv.mist.slicing.util.SingletonCollector.toSingleton; /** * An interprocedural CFG, whose component CFGs are built as ACFGs. */ public class ICFG extends Graph implements Buildable<NodeList<CompilationUnit>> { public class ICFG extends es.upv.mist.slicing.graphs.Graph implements Buildable<NodeList<CompilationUnit>> { protected final Map<CallableDeclaration<?>, CFG> cfgMap = ASTUtils.newIdentityHashMap(); protected boolean built = false; public void addControlFlowArc(GraphNode<?> from, GraphNode<?> to) { addEdge(from, to, new ControlFlowArc()); public ControlFlowArc addControlFlowArc(GraphNode<?> from, GraphNode<?> to) { ControlFlowArc a = new ControlFlowArc(); addEdge(from, to, a); return a; } public void addNonExecControlFlowArc(GraphNode<?> from, GraphNode<?> to) { Loading Loading @@ -68,7 +71,9 @@ public class ICFG extends Graph implements Buildable<NodeList<CompilationUnit>> public class Builder { protected CallGraph callGraph; protected List<Set<Object>> scrs; protected final Map<CallGraph.Edge<?>, List<ControlFlowArc>> callGraphEdge2ICFGArcMap = new HashMap<>(); protected Graph<Graph<GraphNode<?>, Arc>, DefaultEdge> intraSCRs = new DefaultDirectedGraph<>(null, null, false); public void build(NodeList<CompilationUnit> units) { createClassGraph(units); Loading @@ -87,36 +92,51 @@ public class ICFG extends Graph implements Buildable<NodeList<CompilationUnit>> copyCFGs(); expandCalls(); joinCFGs(); getSCRs(callGraph); intraSCRs = computeIntraSCRs(); } protected void getSCRs(CallGraph callGraph) { DefaultDirectedGraph<Object, CallGraph.Edge> convertedCallGraph = deleteDuplicatedEdges(callGraph); KosarajuStrongConnectivityInspector<Object, CallGraph.Edge> inspector = new KosarajuStrongConnectivityInspector<>(convertedCallGraph); scrs = inspector.stronglyConnectedSets(); protected Graph<Graph<GraphNode<?>, Arc>, DefaultEdge> computeIntraSCRs() { // 1. Copiar el ICFG a un nuevo grafo sin arcos duplicados. (opcional) var simpleICFG = deleteDuplicatedEdges(ICFG.this); // 2. Compute cSCR graph var cSCRs = computeCallSCRs(); // 3. Borrar del ICFG todos los arcos que aparecen en cSCRs for (DefaultEdge e : cSCRs.edgeSet()) { int callsDeleted = 0; for (CallGraph.Vertex src : cSCRs.getEdgeSource(e).vertexSet()) { for (CallGraph.Vertex tgt : cSCRs.getEdgeTarget(e).vertexSet()) { // 3a. Buscar el arco(s) correspondiente en el callgraph for (CallGraph.Edge<?> callEdge : callGraph.getAllEdges(src, tgt)) { // 3b. Buscar el arco(s) correspondientes en el simpleICFG y borrarlos for (ControlFlowArc controlFlowArc : callGraphEdge2ICFGArcMap.get(callEdge)) if (simpleICFG.removeEdge(controlFlowArc)) callsDeleted++; } public static DefaultDirectedGraph<Object, CallGraph.Edge> deleteDuplicatedEdges(CallGraph callGraph) { DefaultDirectedGraph<Object, CallGraph.Edge> simpleGraph = new DefaultDirectedGraph<>(CallGraph.Edge.class); for (CallGraph.Vertex v : callGraph.vertexSet()) { simpleGraph.addVertex(v); } } if (callsDeleted < 2) throw new IllegalStateException("The creation of intraSCRs did not delete the minimum amount of call/return arcs"); if (callsDeleted % 2 == 1) throw new IllegalStateException("The creation of intraSCRs missed a call or a return arc"); } // 4. Generar los SCR del simpleICFG, para producir los intraSCRs return new KosarajuStrongConnectivityInspector<>(simpleICFG).getCondensation(); } Map<String, CallGraph.Edge<?>> edgeMap = new HashMap<>(); for (CallGraph.Edge<?> edge : callGraph.edgeSet()) { CallGraph.Vertex src = callGraph.getEdgeSource(edge); CallGraph.Vertex tgt = callGraph.getEdgeTarget(edge); protected Graph<Graph<CallGraph.Vertex, CallGraph.Edge<?>>, DefaultEdge> computeCallSCRs() { return new KosarajuStrongConnectivityInspector<>(deleteDuplicatedEdges(callGraph)).getCondensation(); } String key = src.getDeclaration().getDeclarationAsString() + "->" + tgt.getDeclaration().getDeclarationAsString(); public static <V, E> DefaultDirectedGraph<V, E> deleteDuplicatedEdges(Graph<V, E> baseGraph) { DefaultDirectedGraph<V, E> simpleGraph = new DefaultDirectedGraph<>(null, null, false); if (!edgeMap.containsKey(key)) { for (V v : baseGraph.vertexSet()) simpleGraph.addVertex(v); for (E edge : baseGraph.edgeSet()) { V src = baseGraph.getEdgeSource(edge); V tgt = baseGraph.getEdgeTarget(edge); if (!simpleGraph.containsEdge(src, tgt)) simpleGraph.addEdge(src, tgt, edge); edgeMap.put(key, edge); } } return simpleGraph; Loading Loading @@ -358,8 +378,9 @@ public class ICFG extends Graph implements Buildable<NodeList<CompilationUnit>> GraphNode<?> enterNode = cfgMap.get(callGraph.getEdgeTarget(call).getDeclaration()).getRootNode(); GraphNode<?> exitNode = cfgMap.get(callGraph.getEdgeTarget(call).getDeclaration()).getExitNode(); // Connections addControlFlowArc(callNode, enterNode); addControlFlowArc(exitNode, returnNode); ControlFlowArc call2enter = addControlFlowArc(callNode, enterNode); ControlFlowArc exit2return = addControlFlowArc(exitNode, returnNode); callGraphEdge2ICFGArcMap.put(call, List.of(call2enter, exit2return)); } } Loading
iacfg/src/test/java/es/upv/mist/slicing/graphs/icfg/GraphLogIntraSCR.java 0 → 100644 +153 −0 Original line number Diff line number Diff line package es.upv.mist.slicing.graphs.icfg; import es.upv.mist.slicing.arcs.Arc; import es.upv.mist.slicing.cli.DOTAttributes; import es.upv.mist.slicing.nodes.GraphNode; import es.upv.mist.slicing.utils.Logger; import org.jgrapht.Graph; import org.jgrapht.graph.DefaultEdge; import org.jgrapht.nio.dot.DOTExporter; import java.awt.*; import java.io.*; import java.util.stream.Collectors; public abstract class GraphLogIntraSCR<G extends Graph<Graph<GraphNode<?>, Arc>, DefaultEdge>> { protected G graph; protected String imageName; protected String format; protected boolean generated = false; protected File outputDir = new File("./out/"); public GraphLogIntraSCR() { this(null); } public GraphLogIntraSCR(G graph) { this.graph = graph; } public void setDirectory(File outputDir) { this.outputDir = outputDir; } public void log() throws IOException { Logger.log( "****************************\n" + "* GRAPH *\n" + "****************************" ); Logger.log(graph); Logger.log( "****************************\n" + "* GRAPHVIZ *\n" + "****************************" ); try (StringWriter stringWriter = new StringWriter()) { getDOTExporter().exportGraph(graph, stringWriter); stringWriter.append('\n'); Logger.log(stringWriter.toString()); } } public void generateImages() throws IOException { generateImages("graph"); } public void generateImages(String imageName) throws IOException { generateImages(imageName, "pdf"); } public void generateImages(String imageName, String format) throws IOException { this.format = format; generated = true; File tmpDot = getDotFile(imageName); // Graph -> DOT -> file try (Writer w = new FileWriter(tmpDot)) { getDOTExporter().exportGraph(graph, w); } // Execute dot ProcessBuilder pb = new ProcessBuilder("dot", tmpDot.getAbsolutePath(), "-T" + format, "-o", getImageFile().getAbsolutePath()); try { int result = pb.start().waitFor(); if (result == 0) tmpDot.deleteOnExit(); else Logger.log("Image generation failed, try running \"" + pb.toString() + "\" on your terminal."); } catch (InterruptedException e) { Logger.log("Image generation failed\n" + e.getMessage()); } } public File getDotFile(String imageName) throws IOException { this.imageName = imageName + "-" + graph.getClass().getSimpleName(); File tmpDot = File.createTempFile("graph-source-", ".dot"); tmpDot.getParentFile().mkdirs(); getImageFile().getParentFile().mkdirs(); // Graph -> DOT -> file try (Writer w = new FileWriter(tmpDot)) { getDOTExporter().exportGraph(graph, w); } return tmpDot; } public void openVisualRepresentation() throws IOException { if (!generated) generateImages(); openFileForUser(getImageFile()); } protected static void openFileForUser(File file) throws IOException { if (Desktop.isDesktopSupported()) { Desktop.getDesktop().open(file); return; } // Alternative manual opening of the file String os = System.getProperty("os.name").toLowerCase(); String cmd = null; if (os.contains("win")) { cmd = ""; } else if (os.contains("mac")) { cmd = "open"; } else if (os.contains("nix") || os.contains("nux") || os.contains("aix")) { cmd = "xdg-open"; } if (cmd != null) { new ProcessBuilder(cmd, file.getAbsolutePath()).start(); } else { Logger.format("Warning: cannot open file %s in your system (%s)", file.getName(), os); } } public File getImageFile() { return new File(outputDir, imageName + "." + format); } protected DOTExporter<Graph<GraphNode<?>, Arc>, DefaultEdge> getDOTExporter() { DOTExporter<Graph<GraphNode<?>, Arc>, DefaultEdge> exporter = new DOTExporter<>(); exporter.setVertexIdProvider(node -> String.valueOf(node.vertexSet().stream().map(GraphNode::getId).findFirst().orElse(-1L))); exporter.setVertexAttributeProvider(v -> vertexAttributes(v).build()); exporter.setEdgeAttributeProvider(v -> edgeAttributes(v).build()); return exporter; } protected DOTAttributes vertexAttributes(Graph<GraphNode<?>, Arc> vertex) { DOTAttributes res = new DOTAttributes(); res.set("label", vertex.vertexSet().stream() .map(graphNode -> "%04d: %s".formatted(graphNode.getId(), graphNode.getLabel())) .sorted() .collect(Collectors.joining("\n"))); return res; } protected DOTAttributes edgeAttributes(DefaultEdge arc) { return new DOTAttributes(); } }
iacfg/src/test/java/es/upv/mist/slicing/graphs/icfg/ICFGTest.java +4 −1 Original line number Diff line number Diff line Loading @@ -26,8 +26,11 @@ public class ICFGTest { createGraph("TestInlineFunctions.java", "grafoInlineVariables"); System.out.println("Grafo 4 generado..."); createGraph("TestExamplePaper.java", "grafoInlineVariables"); createGraph("TestExamplePaper.java", "grafoPaper"); System.out.println("Grafo 5 generado..."); createGraph("TestExamplePaperSimple.java", "grafoPaperSimple"); System.out.println("Grafo 6 generado..."); } private static void createGraph(String fileName, String graphName) throws IOException { Loading
iacfg/src/test/resources/TestExamplePaperSimple.java 0 → 100644 +78 −0 Original line number Diff line number Diff line public class TestExamplePaperSimple { public static void main(String[] args) { System.out.println("LLAMAMOS P"); while (1 > 2) { System.out.println("S1"); p1(); System.out.println("S2"); p1(); System.out.println("S3"); } if (1 > 2) { System.out.println("S4"); r1(); System.out.println("S5"); } else { System.out.println("S6"); r1(); System.out.println("S7"); } if (20 < 10) { while (10 > 0) { r1(); System.out.println("S9"); } } else { while (10 > 0) { r1(); System.out.println("S10"); } } System.out.println("S11"); l(); System.out.println("S12"); } public static void p1() { p2(); } public static void p2() { p3(); } public static void p3() { while (1 > 2) { System.out.println("P3!"); } } public static void r1() { System.out.println("S20"); if (21 > 0) { r1(); } System.out.println("S23"); System.out.println("S24"); } public static void l() { if (1 > 0) { m(); System.out.println("L3"); } } public static void m() { if (1 > 0) { n(); System.out.println("M3"); } } public static void n() { if (1 > 0) { l(); System.out.println("N3"); } } } No newline at end of file