Loading sdg-core/src/main/java/tfm/graphs/cfg/CFGBuilder.java +10 −0 Original line number Diff line number Diff line Loading @@ -325,6 +325,16 @@ public class CFGBuilder extends VoidVisitorAdapter<Void> { returnList.stream().filter(node -> !hangingNodes.contains(node)).forEach(hangingNodes::add); createAndConnectFormalOutNodes(methodDeclaration); // Create and connect formal-out nodes sequentially 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 −0 Original line number Diff line number Diff line Loading @@ -59,10 +59,12 @@ public class MethodCallReplacerVisitor extends GraphNodeContentVisitor<Void> { for (int i = 0; i < parameters.size(); i++) { Parameter parameter = parameters.get(i); Expression argument; if (!parameter.isVarArgs()) { argument = arguments.get(i); } else { NodeList<Expression> varArgs = new NodeList<>(arguments.subList(i, arguments.size())); argument = new ArrayCreationExpr( parameter.getType(), new NodeList<>(new ArrayCreationLevel(varArgs.size())), 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 Loading @@ -34,19 +33,19 @@ public class NaiveSummaryArcsBuilder extends SummaryArcsBuilder { @Override public void visit() { for (GraphNode<MethodDeclaration> methodDeclarationNode : findAllMethodDeclarations()) { 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 @@ -56,17 +55,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 @@ -84,33 +83,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 @@ -33,5 +33,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 +10 −0 Original line number Diff line number Diff line Loading @@ -325,6 +325,16 @@ public class CFGBuilder extends VoidVisitorAdapter<Void> { returnList.stream().filter(node -> !hangingNodes.contains(node)).forEach(hangingNodes::add); createAndConnectFormalOutNodes(methodDeclaration); // Create and connect formal-out nodes sequentially 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 −0 Original line number Diff line number Diff line Loading @@ -59,10 +59,12 @@ public class MethodCallReplacerVisitor extends GraphNodeContentVisitor<Void> { for (int i = 0; i < parameters.size(); i++) { Parameter parameter = parameters.get(i); Expression argument; if (!parameter.isVarArgs()) { argument = arguments.get(i); } else { NodeList<Expression> varArgs = new NodeList<>(arguments.subList(i, arguments.size())); argument = new ArrayCreationExpr( parameter.getType(), new NodeList<>(new ArrayCreationLevel(varArgs.size())), 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 Loading @@ -34,19 +33,19 @@ public class NaiveSummaryArcsBuilder extends SummaryArcsBuilder { @Override public void visit() { for (GraphNode<MethodDeclaration> methodDeclarationNode : findAllMethodDeclarations()) { 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 @@ -56,17 +55,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 @@ -84,33 +83,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 @@ -33,5 +33,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; } }