Loading src/main/java/tfm/graphs/sdg/MethodCallReplacerVisitor.java +18 −8 Original line number Diff line number Diff line Loading @@ -252,17 +252,27 @@ class MethodCallReplacerVisitor extends VoidVisitorAdapter<Context> { } } // 'Return' node GraphNode<EmptyStmt> returnNode = sdg.addNode("return", new EmptyStmt(), TypeNodeFactory.fromType(NodeType.METHOD_CALL_RETURN)); sdg.addControlDependencyArc(methodCallNode, returnNode); // Add 'output' node of the call sdg.addReturnArc(returnNode, originalMethodCallNode); // First, check if method has an output node Optional<GraphNode<EmptyStmt>> optionalDeclarationOutputNode = sdg.outgoingEdgesOf(methodDeclarationNode).stream() .filter(arc -> sdg.getEdgeTarget(arc).getNodeType() == NodeType.METHOD_OUTPUT) .map(arc -> (GraphNode<EmptyStmt>) sdg.getEdgeTarget(arc)) .findFirst(); if (!optionalDeclarationOutputNode.isPresent()) { // Method return type is void, do nothing return; } GraphNode<EmptyStmt> declarationOutputNode = optionalDeclarationOutputNode.get(); methodCFG.vertexSet().stream() .filter(node -> node.getAstNode() instanceof ReturnStmt) .map(node -> (GraphNode<ReturnStmt>) node) .forEach(node -> sdg.addReturnArc(node, returnNode)); // If method has output node, then create output call node and link them GraphNode<EmptyStmt> callReturnNode = sdg.addNode("output", new EmptyStmt(), TypeNodeFactory.fromType(NodeType.METHOD_CALL_RETURN)); sdg.addControlDependencyArc(methodCallNode, callReturnNode); sdg.addReturnArc(callReturnNode, originalMethodCallNode); sdg.addReturnArc(declarationOutputNode, callReturnNode); Logger.log("MethodCallReplacerVisitor", String.format("%s | Method '%s' called", methodCallExpr, methodDeclaration.getNameAsString())); } Loading src/main/java/tfm/graphs/sdg/SDGBuilder.java +22 −0 Original line number Diff line number Diff line Loading @@ -5,13 +5,19 @@ import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration; import com.github.javaparser.ast.body.MethodDeclaration; import com.github.javaparser.ast.body.Parameter; import com.github.javaparser.ast.expr.*; import com.github.javaparser.ast.stmt.EmptyStmt; import com.github.javaparser.ast.stmt.ExpressionStmt; import com.github.javaparser.ast.stmt.ReturnStmt; import com.github.javaparser.ast.visitor.VoidVisitorAdapter; import tfm.arcs.Arc; import tfm.graphs.pdg.PDG; import tfm.nodes.GraphNode; import tfm.nodes.TypeNodeFactory; import tfm.nodes.type.NodeType; import tfm.utils.Context; import java.lang.reflect.Type; class SDGBuilder extends VoidVisitorAdapter<Context> { SDG sdg; Loading Loading @@ -53,6 +59,22 @@ class SDGBuilder extends VoidVisitorAdapter<Context> { // Add CFG sdg.setMethodCFG(methodDeclaration, pdg.getCfg()); // Add output node if (methodDeclaration.getType().isVoidType()) { // If method return type is void, do nothing return; } GraphNode<EmptyStmt> outputNode = sdg.addNode("output", new EmptyStmt(), TypeNodeFactory.fromType(NodeType.METHOD_OUTPUT)); sdg.addControlDependencyArc(methodDeclarationNode, outputNode); // Add return arc from all return statements to the output node pdg.getCfg().vertexSet().stream() .filter(node -> node.getAstNode() instanceof ReturnStmt) .map(node -> (GraphNode<ReturnStmt>) node) .forEach(node -> sdg.addReturnArc(node, outputNode)); } @Override Loading src/main/java/tfm/nodes/type/NodeType.java +2 −0 Original line number Diff line number Diff line Loading @@ -22,6 +22,8 @@ public enum NodeType { /** An argument or globally accessible variable that * has been modified in a method declaration. */ FORMAL_OUT, /** A node representing the return value of a non-void method declaration. */ METHOD_OUTPUT, /** A node representing the return value of a non-void method call. */ METHOD_CALL_RETURN, } Loading
src/main/java/tfm/graphs/sdg/MethodCallReplacerVisitor.java +18 −8 Original line number Diff line number Diff line Loading @@ -252,17 +252,27 @@ class MethodCallReplacerVisitor extends VoidVisitorAdapter<Context> { } } // 'Return' node GraphNode<EmptyStmt> returnNode = sdg.addNode("return", new EmptyStmt(), TypeNodeFactory.fromType(NodeType.METHOD_CALL_RETURN)); sdg.addControlDependencyArc(methodCallNode, returnNode); // Add 'output' node of the call sdg.addReturnArc(returnNode, originalMethodCallNode); // First, check if method has an output node Optional<GraphNode<EmptyStmt>> optionalDeclarationOutputNode = sdg.outgoingEdgesOf(methodDeclarationNode).stream() .filter(arc -> sdg.getEdgeTarget(arc).getNodeType() == NodeType.METHOD_OUTPUT) .map(arc -> (GraphNode<EmptyStmt>) sdg.getEdgeTarget(arc)) .findFirst(); if (!optionalDeclarationOutputNode.isPresent()) { // Method return type is void, do nothing return; } GraphNode<EmptyStmt> declarationOutputNode = optionalDeclarationOutputNode.get(); methodCFG.vertexSet().stream() .filter(node -> node.getAstNode() instanceof ReturnStmt) .map(node -> (GraphNode<ReturnStmt>) node) .forEach(node -> sdg.addReturnArc(node, returnNode)); // If method has output node, then create output call node and link them GraphNode<EmptyStmt> callReturnNode = sdg.addNode("output", new EmptyStmt(), TypeNodeFactory.fromType(NodeType.METHOD_CALL_RETURN)); sdg.addControlDependencyArc(methodCallNode, callReturnNode); sdg.addReturnArc(callReturnNode, originalMethodCallNode); sdg.addReturnArc(declarationOutputNode, callReturnNode); Logger.log("MethodCallReplacerVisitor", String.format("%s | Method '%s' called", methodCallExpr, methodDeclaration.getNameAsString())); } Loading
src/main/java/tfm/graphs/sdg/SDGBuilder.java +22 −0 Original line number Diff line number Diff line Loading @@ -5,13 +5,19 @@ import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration; import com.github.javaparser.ast.body.MethodDeclaration; import com.github.javaparser.ast.body.Parameter; import com.github.javaparser.ast.expr.*; import com.github.javaparser.ast.stmt.EmptyStmt; import com.github.javaparser.ast.stmt.ExpressionStmt; import com.github.javaparser.ast.stmt.ReturnStmt; import com.github.javaparser.ast.visitor.VoidVisitorAdapter; import tfm.arcs.Arc; import tfm.graphs.pdg.PDG; import tfm.nodes.GraphNode; import tfm.nodes.TypeNodeFactory; import tfm.nodes.type.NodeType; import tfm.utils.Context; import java.lang.reflect.Type; class SDGBuilder extends VoidVisitorAdapter<Context> { SDG sdg; Loading Loading @@ -53,6 +59,22 @@ class SDGBuilder extends VoidVisitorAdapter<Context> { // Add CFG sdg.setMethodCFG(methodDeclaration, pdg.getCfg()); // Add output node if (methodDeclaration.getType().isVoidType()) { // If method return type is void, do nothing return; } GraphNode<EmptyStmt> outputNode = sdg.addNode("output", new EmptyStmt(), TypeNodeFactory.fromType(NodeType.METHOD_OUTPUT)); sdg.addControlDependencyArc(methodDeclarationNode, outputNode); // Add return arc from all return statements to the output node pdg.getCfg().vertexSet().stream() .filter(node -> node.getAstNode() instanceof ReturnStmt) .map(node -> (GraphNode<ReturnStmt>) node) .forEach(node -> sdg.addReturnArc(node, outputNode)); } @Override Loading
src/main/java/tfm/nodes/type/NodeType.java +2 −0 Original line number Diff line number Diff line Loading @@ -22,6 +22,8 @@ public enum NodeType { /** An argument or globally accessible variable that * has been modified in a method declaration. */ FORMAL_OUT, /** A node representing the return value of a non-void method declaration. */ METHOD_OUTPUT, /** A node representing the return value of a non-void method call. */ METHOD_CALL_RETURN, }