Loading src/main/java/tfm/exec/Main.java +2 −2 Original line number Diff line number Diff line Loading @@ -19,8 +19,8 @@ import java.util.Optional; public class Main { public static final String PROGRAM = Utils.PROGRAMS_FOLDER + "sdg/Example1.java"; public static final String GRAPH = GraphLog.SDG; public static final String METHOD = "main"; public static final String GRAPH = GraphLog.PDG; public static final String METHOD = "sum"; public static void main(String[] args) throws IOException { JavaParser.getStaticConfiguration().setAttributeComments(false); Loading src/main/java/tfm/graphs/Graph.java +9 −4 Original line number Diff line number Diff line package tfm.graphs; import com.github.javaparser.ast.Node; import org.jetbrains.annotations.NotNull; import org.jgrapht.graph.DirectedPseudograph; import org.jgrapht.io.DOTExporter; import tfm.arcs.Arc; import tfm.nodes.GraphNode; import tfm.nodes.NodeFactory; import tfm.nodes.factories.NodeFactory; import tfm.utils.ASTUtils; import java.util.*; Loading @@ -25,12 +26,16 @@ public abstract class Graph extends DirectedPseudograph<GraphNode<?>, Arc> { * * @param node the node to add to the graph */ public <ASTNode extends Node> void addNode(GraphNode<ASTNode> node) { public <ASTNode extends Node> void addNode(@NotNull GraphNode<ASTNode> node) { this.addVertex(node); } public <ASTNode extends Node> GraphNode<ASTNode> addNode(String instruction, ASTNode node) { GraphNode<ASTNode> newNode = NodeFactory.graphNode(instruction, node); public <ASTNode extends Node> GraphNode<ASTNode> addNode(@NotNull String instruction, @NotNull ASTNode node) { return this.addNode(instruction, node, GraphNode.DEFAULT_FACTORY); } public <ASTNode extends Node> GraphNode<ASTNode> addNode(@NotNull String instruction, @NotNull ASTNode node, @NotNull NodeFactory nodeFactory) { GraphNode<ASTNode> newNode = nodeFactory.graphNode(instruction, node); this.addNode(newNode); Loading src/main/java/tfm/graphs/GraphWithRootNode.java +4 −3 Original line number Diff line number Diff line Loading @@ -2,8 +2,9 @@ package tfm.graphs; import com.github.javaparser.ast.Node; import com.github.javaparser.ast.body.MethodDeclaration; import org.jetbrains.annotations.NotNull; import tfm.nodes.GraphNode; import tfm.nodes.NodeFactory; import tfm.nodes.factories.NodeFactory; import java.util.Objects; import java.util.Optional; Loading @@ -24,12 +25,12 @@ public abstract class GraphWithRootNode<ASTRootNode extends Node> extends Graph * @param rootNodeAst the AST node * @return true if the root node is created, false otherwise */ public boolean buildRootNode(String instruction, ASTRootNode rootNodeAst) { public boolean buildRootNode(@NotNull String instruction, @NotNull ASTRootNode rootNodeAst, @NotNull NodeFactory nodeFactory) { if (rootNode != null) { return false; } GraphNode<ASTRootNode> root = NodeFactory.graphNode(instruction, rootNodeAst); GraphNode<ASTRootNode> root = nodeFactory.graphNode(instruction, rootNodeAst); this.rootNode = root; this.addVertex(root); Loading src/main/java/tfm/graphs/augmented/ACFGBuilder.java +2 −1 Original line number Diff line number Diff line Loading @@ -8,6 +8,7 @@ import com.github.javaparser.ast.stmt.*; import com.github.javaparser.ast.visitor.VoidVisitor; import tfm.graphs.cfg.CFGBuilder; import tfm.nodes.GraphNode; import tfm.nodes.factories.MethodNodeFactory; import tfm.utils.ASTUtils; import java.util.LinkedList; Loading Loading @@ -237,7 +238,7 @@ public class ACFGBuilder extends CFGBuilder { if (!methodDeclaration.getBody().isPresent()) throw new IllegalStateException("The method must have a body!"); graph.buildRootNode("ENTER " + methodDeclaration.getNameAsString(), methodDeclaration); graph.buildRootNode("ENTER " + methodDeclaration.getNameAsString(), methodDeclaration, new MethodNodeFactory()); hangingNodes.add(graph.getRootNode().get()); methodDeclaration.getBody().get().accept(this, arg); Loading src/main/java/tfm/graphs/cfg/CFGBuilder.java +82 −14 Original line number Diff line number Diff line Loading @@ -2,13 +2,16 @@ package tfm.graphs.cfg; import com.github.javaparser.ast.Node; import com.github.javaparser.ast.body.MethodDeclaration; import com.github.javaparser.ast.expr.BooleanLiteralExpr; import com.github.javaparser.ast.expr.Expression; import com.github.javaparser.ast.expr.SimpleName; import com.github.javaparser.ast.body.Parameter; import com.github.javaparser.ast.body.VariableDeclarator; import com.github.javaparser.ast.expr.*; import com.github.javaparser.ast.stmt.*; import com.github.javaparser.ast.visitor.VoidVisitor; import com.github.javaparser.ast.visitor.VoidVisitorAdapter; import tfm.nodes.GraphNode; import tfm.nodes.factories.InVariableNodeFactory; import tfm.nodes.factories.MethodNodeFactory; import tfm.nodes.factories.OutVariableNodeFactory; import tfm.utils.ASTUtils; import java.util.*; Loading @@ -30,22 +33,38 @@ import java.util.*; * </ol> */ public class CFGBuilder extends VoidVisitorAdapter<Void> { /** Stores the CFG representing the method analyzed. */ /** * Stores the CFG representing the method analyzed. */ protected final CFG graph; /** Nodes that haven't yet been connected to another one. * The next node will be the destination, they are the source. */ /** * Nodes that haven't yet been connected to another one. * The next node will be the destination, they are the source. */ protected final List<GraphNode<?>> hangingNodes = new LinkedList<>(); /** Stack of break statements collected in various (nestable) breakable blocks. */ /** * Stack of break statements collected in various (nestable) breakable blocks. */ protected final Deque<List<GraphNode<BreakStmt>>> breakStack = new LinkedList<>(); /** Stack of continue statements collected in various (nestable) continuable blocks. */ /** * Stack of continue statements collected in various (nestable) continuable blocks. */ protected final Deque<List<GraphNode<ContinueStmt>>> continueStack = new LinkedList<>(); /** Lists of labelled break statements, mapped according to their label. */ /** * Lists of labelled break statements, mapped according to their label. */ protected final Map<SimpleName, List<GraphNode<BreakStmt>>> breakMap = new HashMap<>(); /** Lists of labelled continue statements, mapped according to their label. */ /** * Lists of labelled continue statements, mapped according to their label. */ protected final Map<SimpleName, List<GraphNode<ContinueStmt>>> continueMap = new HashMap<>(); /** Return statements that should be connected to the final node, if it is created at the end of the */ /** * Return statements that should be connected to the final node, if it is created at the end of the */ protected final List<GraphNode<ReturnStmt>> returnList = new LinkedList<>(); /** Stack of lists of hanging cases on switch statements */ /** * Stack of lists of hanging cases on switch statements */ protected final Deque<List<GraphNode<SwitchEntryStmt>>> switchEntriesStack = new LinkedList<>(); protected CFGBuilder(CFG graph) { Loading Loading @@ -197,7 +216,9 @@ public class CFGBuilder extends VoidVisitorAdapter<Void> { hangingNodes.addAll(breakStack.pop()); } /** Switch entry, considered part of the condition of the switch. */ /** * Switch entry, considered part of the condition of the switch. */ @Override public void visit(SwitchEntryStmt entryStmt, Void arg) { // Case header (prev -> case EXPR) Loading Loading @@ -270,11 +291,58 @@ public class CFGBuilder extends VoidVisitorAdapter<Void> { if (!methodDeclaration.getBody().isPresent()) throw new IllegalStateException("The method must have a body!"); graph.buildRootNode("ENTER " + methodDeclaration.getNameAsString(), methodDeclaration); graph.buildRootNode("ENTER " + methodDeclaration.getNameAsString(), methodDeclaration, new MethodNodeFactory()); // Compute variable in and out expressions (necessary to compute data dependence in SDG) List<ExpressionStmt> inVariableExpressions = new ArrayList<>(); List<ExpressionStmt> outVariableExpressions = new ArrayList<>(); for (Parameter parameter : methodDeclaration.getParameters()) { // In expression VariableDeclarationExpr inVariableDeclarationExpr = new VariableDeclarationExpr( new VariableDeclarator( parameter.getType(), parameter.getNameAsString(), new NameExpr(parameter.getNameAsString() + "_in") ) ); ExpressionStmt inExprStmt = new ExpressionStmt(inVariableDeclarationExpr); inVariableExpressions.add(inExprStmt); // Out expression VariableDeclarationExpr outVariableDeclarationExpr = new VariableDeclarationExpr( new VariableDeclarator( parameter.getType(), parameter.getNameAsString() + "_out", new NameExpr(parameter.getNameAsString()) ) ); ExpressionStmt outExprStmt = new ExpressionStmt(outVariableDeclarationExpr); outVariableExpressions.add(outExprStmt); } hangingNodes.add(graph.getRootNode().get()); // Add in variable nodes for (ExpressionStmt expressionStmt : inVariableExpressions) { GraphNode<ExpressionStmt> node = this.graph.addNode(expressionStmt.toString(), expressionStmt, new InVariableNodeFactory()); connectTo(node); } methodDeclaration.getBody().get().accept(this, arg); returnList.stream().filter(node -> !hangingNodes.contains(node)).forEach(hangingNodes::add); // Add out variable nodes for (ExpressionStmt expressionStmt : outVariableExpressions) { GraphNode<ExpressionStmt> node = this.graph.addNode(expressionStmt.toString(), expressionStmt, new OutVariableNodeFactory()); connectTo(node); } GraphNode<EmptyStmt> exitNode = connectTo(new EmptyStmt(), "Exit"); graph.setExitNode(exitNode); } Loading Loading
src/main/java/tfm/exec/Main.java +2 −2 Original line number Diff line number Diff line Loading @@ -19,8 +19,8 @@ import java.util.Optional; public class Main { public static final String PROGRAM = Utils.PROGRAMS_FOLDER + "sdg/Example1.java"; public static final String GRAPH = GraphLog.SDG; public static final String METHOD = "main"; public static final String GRAPH = GraphLog.PDG; public static final String METHOD = "sum"; public static void main(String[] args) throws IOException { JavaParser.getStaticConfiguration().setAttributeComments(false); Loading
src/main/java/tfm/graphs/Graph.java +9 −4 Original line number Diff line number Diff line package tfm.graphs; import com.github.javaparser.ast.Node; import org.jetbrains.annotations.NotNull; import org.jgrapht.graph.DirectedPseudograph; import org.jgrapht.io.DOTExporter; import tfm.arcs.Arc; import tfm.nodes.GraphNode; import tfm.nodes.NodeFactory; import tfm.nodes.factories.NodeFactory; import tfm.utils.ASTUtils; import java.util.*; Loading @@ -25,12 +26,16 @@ public abstract class Graph extends DirectedPseudograph<GraphNode<?>, Arc> { * * @param node the node to add to the graph */ public <ASTNode extends Node> void addNode(GraphNode<ASTNode> node) { public <ASTNode extends Node> void addNode(@NotNull GraphNode<ASTNode> node) { this.addVertex(node); } public <ASTNode extends Node> GraphNode<ASTNode> addNode(String instruction, ASTNode node) { GraphNode<ASTNode> newNode = NodeFactory.graphNode(instruction, node); public <ASTNode extends Node> GraphNode<ASTNode> addNode(@NotNull String instruction, @NotNull ASTNode node) { return this.addNode(instruction, node, GraphNode.DEFAULT_FACTORY); } public <ASTNode extends Node> GraphNode<ASTNode> addNode(@NotNull String instruction, @NotNull ASTNode node, @NotNull NodeFactory nodeFactory) { GraphNode<ASTNode> newNode = nodeFactory.graphNode(instruction, node); this.addNode(newNode); Loading
src/main/java/tfm/graphs/GraphWithRootNode.java +4 −3 Original line number Diff line number Diff line Loading @@ -2,8 +2,9 @@ package tfm.graphs; import com.github.javaparser.ast.Node; import com.github.javaparser.ast.body.MethodDeclaration; import org.jetbrains.annotations.NotNull; import tfm.nodes.GraphNode; import tfm.nodes.NodeFactory; import tfm.nodes.factories.NodeFactory; import java.util.Objects; import java.util.Optional; Loading @@ -24,12 +25,12 @@ public abstract class GraphWithRootNode<ASTRootNode extends Node> extends Graph * @param rootNodeAst the AST node * @return true if the root node is created, false otherwise */ public boolean buildRootNode(String instruction, ASTRootNode rootNodeAst) { public boolean buildRootNode(@NotNull String instruction, @NotNull ASTRootNode rootNodeAst, @NotNull NodeFactory nodeFactory) { if (rootNode != null) { return false; } GraphNode<ASTRootNode> root = NodeFactory.graphNode(instruction, rootNodeAst); GraphNode<ASTRootNode> root = nodeFactory.graphNode(instruction, rootNodeAst); this.rootNode = root; this.addVertex(root); Loading
src/main/java/tfm/graphs/augmented/ACFGBuilder.java +2 −1 Original line number Diff line number Diff line Loading @@ -8,6 +8,7 @@ import com.github.javaparser.ast.stmt.*; import com.github.javaparser.ast.visitor.VoidVisitor; import tfm.graphs.cfg.CFGBuilder; import tfm.nodes.GraphNode; import tfm.nodes.factories.MethodNodeFactory; import tfm.utils.ASTUtils; import java.util.LinkedList; Loading Loading @@ -237,7 +238,7 @@ public class ACFGBuilder extends CFGBuilder { if (!methodDeclaration.getBody().isPresent()) throw new IllegalStateException("The method must have a body!"); graph.buildRootNode("ENTER " + methodDeclaration.getNameAsString(), methodDeclaration); graph.buildRootNode("ENTER " + methodDeclaration.getNameAsString(), methodDeclaration, new MethodNodeFactory()); hangingNodes.add(graph.getRootNode().get()); methodDeclaration.getBody().get().accept(this, arg); Loading
src/main/java/tfm/graphs/cfg/CFGBuilder.java +82 −14 Original line number Diff line number Diff line Loading @@ -2,13 +2,16 @@ package tfm.graphs.cfg; import com.github.javaparser.ast.Node; import com.github.javaparser.ast.body.MethodDeclaration; import com.github.javaparser.ast.expr.BooleanLiteralExpr; import com.github.javaparser.ast.expr.Expression; import com.github.javaparser.ast.expr.SimpleName; import com.github.javaparser.ast.body.Parameter; import com.github.javaparser.ast.body.VariableDeclarator; import com.github.javaparser.ast.expr.*; import com.github.javaparser.ast.stmt.*; import com.github.javaparser.ast.visitor.VoidVisitor; import com.github.javaparser.ast.visitor.VoidVisitorAdapter; import tfm.nodes.GraphNode; import tfm.nodes.factories.InVariableNodeFactory; import tfm.nodes.factories.MethodNodeFactory; import tfm.nodes.factories.OutVariableNodeFactory; import tfm.utils.ASTUtils; import java.util.*; Loading @@ -30,22 +33,38 @@ import java.util.*; * </ol> */ public class CFGBuilder extends VoidVisitorAdapter<Void> { /** Stores the CFG representing the method analyzed. */ /** * Stores the CFG representing the method analyzed. */ protected final CFG graph; /** Nodes that haven't yet been connected to another one. * The next node will be the destination, they are the source. */ /** * Nodes that haven't yet been connected to another one. * The next node will be the destination, they are the source. */ protected final List<GraphNode<?>> hangingNodes = new LinkedList<>(); /** Stack of break statements collected in various (nestable) breakable blocks. */ /** * Stack of break statements collected in various (nestable) breakable blocks. */ protected final Deque<List<GraphNode<BreakStmt>>> breakStack = new LinkedList<>(); /** Stack of continue statements collected in various (nestable) continuable blocks. */ /** * Stack of continue statements collected in various (nestable) continuable blocks. */ protected final Deque<List<GraphNode<ContinueStmt>>> continueStack = new LinkedList<>(); /** Lists of labelled break statements, mapped according to their label. */ /** * Lists of labelled break statements, mapped according to their label. */ protected final Map<SimpleName, List<GraphNode<BreakStmt>>> breakMap = new HashMap<>(); /** Lists of labelled continue statements, mapped according to their label. */ /** * Lists of labelled continue statements, mapped according to their label. */ protected final Map<SimpleName, List<GraphNode<ContinueStmt>>> continueMap = new HashMap<>(); /** Return statements that should be connected to the final node, if it is created at the end of the */ /** * Return statements that should be connected to the final node, if it is created at the end of the */ protected final List<GraphNode<ReturnStmt>> returnList = new LinkedList<>(); /** Stack of lists of hanging cases on switch statements */ /** * Stack of lists of hanging cases on switch statements */ protected final Deque<List<GraphNode<SwitchEntryStmt>>> switchEntriesStack = new LinkedList<>(); protected CFGBuilder(CFG graph) { Loading Loading @@ -197,7 +216,9 @@ public class CFGBuilder extends VoidVisitorAdapter<Void> { hangingNodes.addAll(breakStack.pop()); } /** Switch entry, considered part of the condition of the switch. */ /** * Switch entry, considered part of the condition of the switch. */ @Override public void visit(SwitchEntryStmt entryStmt, Void arg) { // Case header (prev -> case EXPR) Loading Loading @@ -270,11 +291,58 @@ public class CFGBuilder extends VoidVisitorAdapter<Void> { if (!methodDeclaration.getBody().isPresent()) throw new IllegalStateException("The method must have a body!"); graph.buildRootNode("ENTER " + methodDeclaration.getNameAsString(), methodDeclaration); graph.buildRootNode("ENTER " + methodDeclaration.getNameAsString(), methodDeclaration, new MethodNodeFactory()); // Compute variable in and out expressions (necessary to compute data dependence in SDG) List<ExpressionStmt> inVariableExpressions = new ArrayList<>(); List<ExpressionStmt> outVariableExpressions = new ArrayList<>(); for (Parameter parameter : methodDeclaration.getParameters()) { // In expression VariableDeclarationExpr inVariableDeclarationExpr = new VariableDeclarationExpr( new VariableDeclarator( parameter.getType(), parameter.getNameAsString(), new NameExpr(parameter.getNameAsString() + "_in") ) ); ExpressionStmt inExprStmt = new ExpressionStmt(inVariableDeclarationExpr); inVariableExpressions.add(inExprStmt); // Out expression VariableDeclarationExpr outVariableDeclarationExpr = new VariableDeclarationExpr( new VariableDeclarator( parameter.getType(), parameter.getNameAsString() + "_out", new NameExpr(parameter.getNameAsString()) ) ); ExpressionStmt outExprStmt = new ExpressionStmt(outVariableDeclarationExpr); outVariableExpressions.add(outExprStmt); } hangingNodes.add(graph.getRootNode().get()); // Add in variable nodes for (ExpressionStmt expressionStmt : inVariableExpressions) { GraphNode<ExpressionStmt> node = this.graph.addNode(expressionStmt.toString(), expressionStmt, new InVariableNodeFactory()); connectTo(node); } methodDeclaration.getBody().get().accept(this, arg); returnList.stream().filter(node -> !hangingNodes.contains(node)).forEach(hangingNodes::add); // Add out variable nodes for (ExpressionStmt expressionStmt : outVariableExpressions) { GraphNode<ExpressionStmt> node = this.graph.addNode(expressionStmt.toString(), expressionStmt, new OutVariableNodeFactory()); connectTo(node); } GraphNode<EmptyStmt> exitNode = connectTo(new EmptyStmt(), "Exit"); graph.setExitNode(exitNode); } Loading