Loading sdg-core/src/main/java/tfm/graphs/cfg/CFGBuilder.java +7 −1 Original line number Diff line number Diff line Loading @@ -309,8 +309,14 @@ public class CFGBuilder extends VoidVisitorAdapter<Void> { returnList.stream().filter(node -> !hangingNodes.contains(node)).forEach(hangingNodes::add); // Create and connect formal-out nodes sequentially for (Parameter param : methodDeclaration.getParameters()) for (Parameter param : methodDeclaration.getParameters()) { // Do not generate out for primitives if (param.getType().isPrimitiveType()) { continue; } connectTo(addFormalOutGraphNode(param)); } // Create and connect the exit node connectTo(graph.addNode("Exit", new EmptyStmt(), TypeNodeFactory.fromType(NodeType.METHOD_EXIT))); } Loading sdg-core/src/main/java/tfm/graphs/sdg/MethodCallReplacerVisitor.java +2 −34 Original line number Diff line number Diff line Loading @@ -105,10 +105,6 @@ class MethodCallReplacerVisitor extends VoidVisitorAdapter<Context> { MethodDeclaration methodDeclaration = methodDeclarationNode.getAstNode(); Optional<CFG> optionalCFG = sdg.getMethodCFG(methodDeclaration); assert optionalCFG.isPresent(); CFG methodCFG = optionalCFG.get(); GraphNode<MethodCallExpr> methodCallNode = sdg.addNode("CALL " + methodCallExpr.toString(), methodCallExpr, TypeNodeFactory.fromType(NodeType.METHOD_CALL)); sdg.addControlDependencyArc(originalMethodCallNode, methodCallNode); Loading Loading @@ -171,32 +167,8 @@ class MethodCallReplacerVisitor extends VoidVisitorAdapter<Context> { // Out expression OutNodeVariableVisitor shouldHaveOutNodeVisitor = new OutNodeVariableVisitor(); Set<String> variablesForOutNode = new HashSet<>(); argument.accept(shouldHaveOutNodeVisitor, variablesForOutNode); // Here, variablesForOutNode may have 1 variable or more depending on the expression Logger.log("MethodCallReplacerVisitor", String.format("Variables for out node: %s", variablesForOutNode)); if (variablesForOutNode.isEmpty()) { /* If the argument is not a variable or it is not declared in the scope, then there is no OUT node */ Logger.log("MethodCallReplacerVisitor", String.format("Expression '%s' should not have out node", argument.toString())); continue; } else if (variablesForOutNode.size() == 1) { String variable = variablesForOutNode.iterator().next(); List<GraphNode<?>> declarations = sdg.findDeclarationsOfVariable(variable, originalMethodCallNode); Logger.log("MethodCallReplacerVisitor", String.format("Declarations of variable: '%s': %s", variable, declarations)); if (declarations.isEmpty()) { Logger.log("MethodCallReplacerVisitor", String.format("Expression '%s' should not have out node", argument.toString())); continue; } } else { // If argument is primitive or not a variable, do not generate out nodes if (parameter.getType().isPrimitiveType() || !argument.isNameExpr()) { continue; } Loading Loading @@ -267,10 +239,6 @@ class MethodCallReplacerVisitor extends VoidVisitorAdapter<Context> { Logger.log("MethodCallReplacerVisitor", String.format("%s | Method '%s' called", methodCallExpr, methodDeclaration.getNameAsString())); } private void argumentAsNameExpr(GraphNode<ExpressionStmt> methodCallNode) { } @Override public void visit(MethodDeclaration n, Context arg) { arg.setCurrentMethod(n); Loading sdg-core/src/main/java/tfm/graphs/sdg/SDG.java +1 −1 Original line number Diff line number Diff line Loading @@ -93,7 +93,7 @@ public class SDG extends Graph implements Sliceable, Buildable<NodeList<Compilat this.addEdge(from, to, new ParameterInOutArc()); } public void addSummaryArc(GraphNode<ExpressionStmt> from, GraphNode<ExpressionStmt> to) { public void addSummaryArc(GraphNode<?> from, GraphNode<?> to) { this.addEdge(from, to, new SummaryArc()); } Loading sdg-core/src/main/java/tfm/graphs/sdg/sumarcs/NaiveSummaryArcsBuilder.java +28 −28 Original line number Diff line number Diff line package tfm.graphs.sdg.sumarcs; import com.github.javaparser.ast.body.MethodDeclaration; import com.github.javaparser.ast.stmt.ExpressionStmt; import tfm.arcs.Arc; import tfm.graphs.sdg.SDG; import tfm.nodes.GraphNode; Loading @@ -27,19 +26,19 @@ public class NaiveSummaryArcsBuilder extends SummaryArcsBuilder { GraphNode<MethodDeclaration> methodDeclarationNode = optionalMethodDeclarationNode.get(); Set<GraphNode<ExpressionStmt>> formalOutNodes = sdg.outgoingEdgesOf(methodDeclarationNode).stream() .filter(arc -> sdg.getEdgeTarget(arc).getNodeType() == NodeType.FORMAL_OUT) .map(arc -> (GraphNode<ExpressionStmt>) sdg.getEdgeTarget(arc)) Set<GraphNode<?>> formalOutNodes = sdg.outgoingEdgesOf(methodDeclarationNode).stream() .filter(arc -> sdg.getEdgeTarget(arc).getNodeType().is(NodeType.FORMAL_OUT)) .map(arc -> (GraphNode<?>) sdg.getEdgeTarget(arc)) .collect(Collectors.toSet()); for (GraphNode<ExpressionStmt> formalOutNode : formalOutNodes) { Set<GraphNode<ExpressionStmt>> reachableFormalInNodes = this.findReachableFormalInNodes(formalOutNode); for (GraphNode<?> formalOutNode : formalOutNodes) { Set<GraphNode<?>> reachableFormalInNodes = this.findReachableFormalInNodes(formalOutNode); Set<GraphNode<ExpressionStmt>> actualInNodes = reachableFormalInNodes.stream().flatMap(this::getActualInsStream).collect(Collectors.toSet()); Set<GraphNode<ExpressionStmt>> actualOutNodes = this.getActualOuts(formalOutNode); Set<GraphNode<?>> actualInNodes = reachableFormalInNodes.stream().flatMap(this::getActualInsStream).collect(Collectors.toSet()); Set<GraphNode<?>> actualOutNodes = this.getActualOuts(formalOutNode); for (GraphNode<ExpressionStmt> actualOutNode : actualOutNodes) { for (GraphNode<ExpressionStmt> actualInNode : actualInNodes) { for (GraphNode<?> actualOutNode : actualOutNodes) { for (GraphNode<?> actualInNode : actualInNodes) { if (this.belongToSameMethodCall(actualInNode, actualOutNode)) { sdg.addSummaryArc(actualInNode, actualOutNode); } Loading @@ -49,17 +48,17 @@ public class NaiveSummaryArcsBuilder extends SummaryArcsBuilder { } } private Set<GraphNode<ExpressionStmt>> findReachableFormalInNodes(GraphNode<ExpressionStmt> formalOutNode) { private Set<GraphNode<?>> findReachableFormalInNodes(GraphNode<?> formalOutNode) { return this.doFindReachableFormalInNodes(formalOutNode, Utils.emptySet()); } private Set<GraphNode<ExpressionStmt>> doFindReachableFormalInNodes(GraphNode<?> root, Set<Long> visited) { private Set<GraphNode<?>> doFindReachableFormalInNodes(GraphNode<?> root, Set<Long> visited) { visited.add(root.getId()); Set<GraphNode<ExpressionStmt>> res = Utils.emptySet(); Set<GraphNode<?>> res = Utils.emptySet(); if (root.getNodeType() == NodeType.FORMAL_IN) { res.add((GraphNode<ExpressionStmt>) root); if (root.getNodeType().is(NodeType.FORMAL_IN)) { res.add(root); } else { for (Arc arc : sdg.incomingEdgesOf(root)) { GraphNode<?> nextNode = sdg.getEdgeSource(arc); Loading @@ -77,33 +76,34 @@ public class NaiveSummaryArcsBuilder extends SummaryArcsBuilder { return res; } private Stream<GraphNode<ExpressionStmt>> getActualInsStream(GraphNode<ExpressionStmt> formalIn) { private Stream<GraphNode<?>> getActualInsStream(GraphNode<?> formalIn) { return sdg.incomingEdgesOf(formalIn).stream() .filter(Arc::isParameterInOutArc) .filter(arc -> sdg.getEdgeSource(arc).getNodeType() == NodeType.ACTUAL_IN) .map(arc -> (GraphNode<ExpressionStmt>) sdg.getEdgeSource(arc)); .filter(arc -> sdg.getEdgeSource(arc).getNodeType().is(NodeType.ACTUAL_IN)) .map(arc -> sdg.getEdgeSource(arc)); } private Set<GraphNode<ExpressionStmt>> getActualOuts(GraphNode<ExpressionStmt> formalOut) { private Set<GraphNode<?>> getActualOuts(GraphNode<?> formalOut) { return sdg.outgoingEdgesOf(formalOut).stream() .filter(Arc::isParameterInOutArc) .filter(arc -> sdg.getEdgeTarget(arc).getNodeType() == NodeType.ACTUAL_OUT) .map(arc -> (GraphNode<ExpressionStmt>) sdg.getEdgeTarget(arc)) .filter(arc -> sdg.getEdgeTarget(arc).getNodeType().is(NodeType.ACTUAL_OUT)) .map(arc -> (GraphNode<?>) sdg.getEdgeTarget(arc)) .collect(Collectors.toSet()); } private boolean belongToSameMethodCall(GraphNode<ExpressionStmt> actualIn, GraphNode<ExpressionStmt> actualOut) { Optional<GraphNode<ExpressionStmt>> optionalInCallNode = this.getCallNode(actualIn); Optional<GraphNode<ExpressionStmt>> optionalOutCallNode = this.getCallNode(actualOut); private boolean belongToSameMethodCall(GraphNode<?> actualIn, GraphNode<?> actualOut) { Optional<GraphNode<?>> optionalInCallNode = this.getCallNode(actualIn); Optional<GraphNode<?>> optionalOutCallNode = this.getCallNode(actualOut); return optionalInCallNode.isPresent() && optionalOutCallNode.isPresent() && optionalInCallNode.get() == optionalOutCallNode.get(); } private Optional<GraphNode<ExpressionStmt>> getCallNode(GraphNode<ExpressionStmt> actualInOrOut) { private Optional<GraphNode<?>> getCallNode(GraphNode<?> actualInOrOut) { return sdg.incomingEdgesOf(actualInOrOut).stream() .filter(arc -> sdg.getEdgeSource(arc).getNodeType() == NodeType.METHOD_CALL) .map(arc -> (GraphNode<ExpressionStmt>) sdg.getEdgeSource(arc)) .findFirst(); .filter(arc -> sdg.getEdgeSource(arc).getNodeType().is(NodeType.METHOD_CALL)) .map(arc -> sdg.getEdgeSource(arc)) .findFirst() .map(node -> (GraphNode<?>) node); } } sdg-core/src/main/java/tfm/nodes/type/NodeType.java +17 −1 Original line number Diff line number Diff line Loading @@ -25,5 +25,21 @@ public enum NodeType { /** A node representing the return value of a non-void method call. */ METHOD_CALL_RETURN, /** A node representing the return value of a non-void method declaration. */ METHOD_OUTPUT METHOD_OUTPUT; public boolean is(NodeType type) { if (this == type) { return true; } if (this == METHOD_CALL_RETURN) { return type == ACTUAL_OUT; } if (this == METHOD_OUTPUT) { return type == FORMAL_OUT; } return false; } } Loading
sdg-core/src/main/java/tfm/graphs/cfg/CFGBuilder.java +7 −1 Original line number Diff line number Diff line Loading @@ -309,8 +309,14 @@ public class CFGBuilder extends VoidVisitorAdapter<Void> { returnList.stream().filter(node -> !hangingNodes.contains(node)).forEach(hangingNodes::add); // Create and connect formal-out nodes sequentially for (Parameter param : methodDeclaration.getParameters()) for (Parameter param : methodDeclaration.getParameters()) { // Do not generate out for primitives if (param.getType().isPrimitiveType()) { continue; } connectTo(addFormalOutGraphNode(param)); } // Create and connect the exit node connectTo(graph.addNode("Exit", new EmptyStmt(), TypeNodeFactory.fromType(NodeType.METHOD_EXIT))); } Loading
sdg-core/src/main/java/tfm/graphs/sdg/MethodCallReplacerVisitor.java +2 −34 Original line number Diff line number Diff line Loading @@ -105,10 +105,6 @@ class MethodCallReplacerVisitor extends VoidVisitorAdapter<Context> { MethodDeclaration methodDeclaration = methodDeclarationNode.getAstNode(); Optional<CFG> optionalCFG = sdg.getMethodCFG(methodDeclaration); assert optionalCFG.isPresent(); CFG methodCFG = optionalCFG.get(); GraphNode<MethodCallExpr> methodCallNode = sdg.addNode("CALL " + methodCallExpr.toString(), methodCallExpr, TypeNodeFactory.fromType(NodeType.METHOD_CALL)); sdg.addControlDependencyArc(originalMethodCallNode, methodCallNode); Loading Loading @@ -171,32 +167,8 @@ class MethodCallReplacerVisitor extends VoidVisitorAdapter<Context> { // Out expression OutNodeVariableVisitor shouldHaveOutNodeVisitor = new OutNodeVariableVisitor(); Set<String> variablesForOutNode = new HashSet<>(); argument.accept(shouldHaveOutNodeVisitor, variablesForOutNode); // Here, variablesForOutNode may have 1 variable or more depending on the expression Logger.log("MethodCallReplacerVisitor", String.format("Variables for out node: %s", variablesForOutNode)); if (variablesForOutNode.isEmpty()) { /* If the argument is not a variable or it is not declared in the scope, then there is no OUT node */ Logger.log("MethodCallReplacerVisitor", String.format("Expression '%s' should not have out node", argument.toString())); continue; } else if (variablesForOutNode.size() == 1) { String variable = variablesForOutNode.iterator().next(); List<GraphNode<?>> declarations = sdg.findDeclarationsOfVariable(variable, originalMethodCallNode); Logger.log("MethodCallReplacerVisitor", String.format("Declarations of variable: '%s': %s", variable, declarations)); if (declarations.isEmpty()) { Logger.log("MethodCallReplacerVisitor", String.format("Expression '%s' should not have out node", argument.toString())); continue; } } else { // If argument is primitive or not a variable, do not generate out nodes if (parameter.getType().isPrimitiveType() || !argument.isNameExpr()) { continue; } Loading Loading @@ -267,10 +239,6 @@ class MethodCallReplacerVisitor extends VoidVisitorAdapter<Context> { Logger.log("MethodCallReplacerVisitor", String.format("%s | Method '%s' called", methodCallExpr, methodDeclaration.getNameAsString())); } private void argumentAsNameExpr(GraphNode<ExpressionStmt> methodCallNode) { } @Override public void visit(MethodDeclaration n, Context arg) { arg.setCurrentMethod(n); Loading
sdg-core/src/main/java/tfm/graphs/sdg/SDG.java +1 −1 Original line number Diff line number Diff line Loading @@ -93,7 +93,7 @@ public class SDG extends Graph implements Sliceable, Buildable<NodeList<Compilat this.addEdge(from, to, new ParameterInOutArc()); } public void addSummaryArc(GraphNode<ExpressionStmt> from, GraphNode<ExpressionStmt> to) { public void addSummaryArc(GraphNode<?> from, GraphNode<?> to) { this.addEdge(from, to, new SummaryArc()); } Loading
sdg-core/src/main/java/tfm/graphs/sdg/sumarcs/NaiveSummaryArcsBuilder.java +28 −28 Original line number Diff line number Diff line package tfm.graphs.sdg.sumarcs; import com.github.javaparser.ast.body.MethodDeclaration; import com.github.javaparser.ast.stmt.ExpressionStmt; import tfm.arcs.Arc; import tfm.graphs.sdg.SDG; import tfm.nodes.GraphNode; Loading @@ -27,19 +26,19 @@ public class NaiveSummaryArcsBuilder extends SummaryArcsBuilder { GraphNode<MethodDeclaration> methodDeclarationNode = optionalMethodDeclarationNode.get(); Set<GraphNode<ExpressionStmt>> formalOutNodes = sdg.outgoingEdgesOf(methodDeclarationNode).stream() .filter(arc -> sdg.getEdgeTarget(arc).getNodeType() == NodeType.FORMAL_OUT) .map(arc -> (GraphNode<ExpressionStmt>) sdg.getEdgeTarget(arc)) Set<GraphNode<?>> formalOutNodes = sdg.outgoingEdgesOf(methodDeclarationNode).stream() .filter(arc -> sdg.getEdgeTarget(arc).getNodeType().is(NodeType.FORMAL_OUT)) .map(arc -> (GraphNode<?>) sdg.getEdgeTarget(arc)) .collect(Collectors.toSet()); for (GraphNode<ExpressionStmt> formalOutNode : formalOutNodes) { Set<GraphNode<ExpressionStmt>> reachableFormalInNodes = this.findReachableFormalInNodes(formalOutNode); for (GraphNode<?> formalOutNode : formalOutNodes) { Set<GraphNode<?>> reachableFormalInNodes = this.findReachableFormalInNodes(formalOutNode); Set<GraphNode<ExpressionStmt>> actualInNodes = reachableFormalInNodes.stream().flatMap(this::getActualInsStream).collect(Collectors.toSet()); Set<GraphNode<ExpressionStmt>> actualOutNodes = this.getActualOuts(formalOutNode); Set<GraphNode<?>> actualInNodes = reachableFormalInNodes.stream().flatMap(this::getActualInsStream).collect(Collectors.toSet()); Set<GraphNode<?>> actualOutNodes = this.getActualOuts(formalOutNode); for (GraphNode<ExpressionStmt> actualOutNode : actualOutNodes) { for (GraphNode<ExpressionStmt> actualInNode : actualInNodes) { for (GraphNode<?> actualOutNode : actualOutNodes) { for (GraphNode<?> actualInNode : actualInNodes) { if (this.belongToSameMethodCall(actualInNode, actualOutNode)) { sdg.addSummaryArc(actualInNode, actualOutNode); } Loading @@ -49,17 +48,17 @@ public class NaiveSummaryArcsBuilder extends SummaryArcsBuilder { } } private Set<GraphNode<ExpressionStmt>> findReachableFormalInNodes(GraphNode<ExpressionStmt> formalOutNode) { private Set<GraphNode<?>> findReachableFormalInNodes(GraphNode<?> formalOutNode) { return this.doFindReachableFormalInNodes(formalOutNode, Utils.emptySet()); } private Set<GraphNode<ExpressionStmt>> doFindReachableFormalInNodes(GraphNode<?> root, Set<Long> visited) { private Set<GraphNode<?>> doFindReachableFormalInNodes(GraphNode<?> root, Set<Long> visited) { visited.add(root.getId()); Set<GraphNode<ExpressionStmt>> res = Utils.emptySet(); Set<GraphNode<?>> res = Utils.emptySet(); if (root.getNodeType() == NodeType.FORMAL_IN) { res.add((GraphNode<ExpressionStmt>) root); if (root.getNodeType().is(NodeType.FORMAL_IN)) { res.add(root); } else { for (Arc arc : sdg.incomingEdgesOf(root)) { GraphNode<?> nextNode = sdg.getEdgeSource(arc); Loading @@ -77,33 +76,34 @@ public class NaiveSummaryArcsBuilder extends SummaryArcsBuilder { return res; } private Stream<GraphNode<ExpressionStmt>> getActualInsStream(GraphNode<ExpressionStmt> formalIn) { private Stream<GraphNode<?>> getActualInsStream(GraphNode<?> formalIn) { return sdg.incomingEdgesOf(formalIn).stream() .filter(Arc::isParameterInOutArc) .filter(arc -> sdg.getEdgeSource(arc).getNodeType() == NodeType.ACTUAL_IN) .map(arc -> (GraphNode<ExpressionStmt>) sdg.getEdgeSource(arc)); .filter(arc -> sdg.getEdgeSource(arc).getNodeType().is(NodeType.ACTUAL_IN)) .map(arc -> sdg.getEdgeSource(arc)); } private Set<GraphNode<ExpressionStmt>> getActualOuts(GraphNode<ExpressionStmt> formalOut) { private Set<GraphNode<?>> getActualOuts(GraphNode<?> formalOut) { return sdg.outgoingEdgesOf(formalOut).stream() .filter(Arc::isParameterInOutArc) .filter(arc -> sdg.getEdgeTarget(arc).getNodeType() == NodeType.ACTUAL_OUT) .map(arc -> (GraphNode<ExpressionStmt>) sdg.getEdgeTarget(arc)) .filter(arc -> sdg.getEdgeTarget(arc).getNodeType().is(NodeType.ACTUAL_OUT)) .map(arc -> (GraphNode<?>) sdg.getEdgeTarget(arc)) .collect(Collectors.toSet()); } private boolean belongToSameMethodCall(GraphNode<ExpressionStmt> actualIn, GraphNode<ExpressionStmt> actualOut) { Optional<GraphNode<ExpressionStmt>> optionalInCallNode = this.getCallNode(actualIn); Optional<GraphNode<ExpressionStmt>> optionalOutCallNode = this.getCallNode(actualOut); private boolean belongToSameMethodCall(GraphNode<?> actualIn, GraphNode<?> actualOut) { Optional<GraphNode<?>> optionalInCallNode = this.getCallNode(actualIn); Optional<GraphNode<?>> optionalOutCallNode = this.getCallNode(actualOut); return optionalInCallNode.isPresent() && optionalOutCallNode.isPresent() && optionalInCallNode.get() == optionalOutCallNode.get(); } private Optional<GraphNode<ExpressionStmt>> getCallNode(GraphNode<ExpressionStmt> actualInOrOut) { private Optional<GraphNode<?>> getCallNode(GraphNode<?> actualInOrOut) { return sdg.incomingEdgesOf(actualInOrOut).stream() .filter(arc -> sdg.getEdgeSource(arc).getNodeType() == NodeType.METHOD_CALL) .map(arc -> (GraphNode<ExpressionStmt>) sdg.getEdgeSource(arc)) .findFirst(); .filter(arc -> sdg.getEdgeSource(arc).getNodeType().is(NodeType.METHOD_CALL)) .map(arc -> sdg.getEdgeSource(arc)) .findFirst() .map(node -> (GraphNode<?>) node); } }
sdg-core/src/main/java/tfm/nodes/type/NodeType.java +17 −1 Original line number Diff line number Diff line Loading @@ -25,5 +25,21 @@ public enum NodeType { /** A node representing the return value of a non-void method call. */ METHOD_CALL_RETURN, /** A node representing the return value of a non-void method declaration. */ METHOD_OUTPUT METHOD_OUTPUT; public boolean is(NodeType type) { if (this == type) { return true; } if (this == METHOD_CALL_RETURN) { return type == ACTUAL_OUT; } if (this == METHOD_OUTPUT) { return type == FORMAL_OUT; } return false; } }