Commit 2ff95c0c authored by jacosro's avatar jacosro
Browse files

Added support for node subtypes

parent 7c29ef7b
Loading
Loading
Loading
Loading
+0 −12
Original line number Diff line number Diff line
@@ -7,7 +7,6 @@ import tfm.arcs.pdg.ControlDependencyArc;
import tfm.arcs.pdg.DataDependencyArc;
import tfm.arcs.sdg.CallArc;
import tfm.arcs.sdg.ParameterInOutArc;
import tfm.arcs.sdg.ReturnArc;
import tfm.arcs.sdg.SummaryArc;
import tfm.nodes.GraphNode;

@@ -87,17 +86,6 @@ public abstract class Arc extends DefaultEdge {
        throw new UnsupportedOperationException("Not a ParameterInOutArc");
    }

    /** @see ReturnArc */
    public final boolean isReturnArc() {
        return this instanceof ReturnArc;
    }

    public final ReturnArc asReturnArc() {
        if (isReturnArc())
            return (ReturnArc) this;
        throw new UnsupportedOperationException("Not a ReturnArc");
    }

    /** @see SummaryArc */
    public final boolean isSummaryArc() {
        return this instanceof SummaryArc;
+1 −1
Original line number Diff line number Diff line
@@ -82,7 +82,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());
    }

+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;
@@ -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);
                        }
@@ -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);
@@ -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);
    }
}
+17 −1
Original line number Diff line number Diff line
@@ -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;
    }
}