Commit 1fc0ed0c authored by Javier Costa's avatar Javier Costa
Browse files

Merge branch 'develop' into cli

parents e3feee19 b3e32945
Loading
Loading
Loading
Loading
+7 −1
Original line number Diff line number Diff line
@@ -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)));
    }
+2 −34
Original line number Diff line number Diff line
@@ -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);
@@ -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;
            }

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

+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;
    }
}