Commit c19c0a41 authored by Carlos Galindo's avatar Carlos Galindo
Browse files

Add interprocedural object arcs between formal/actual-out.

Redesigned JSysCallConnector, to rely more on CallConnector.
parent edd157c6
Loading
Loading
Loading
Loading
+27 −31
Original line number Diff line number Diff line
package es.upv.mist.slicing.graphs.jsysdg;

import com.github.javaparser.ast.body.CallableDeclaration;
import es.upv.mist.slicing.graphs.CallGraph;
import es.upv.mist.slicing.graphs.cfg.CFGBuilder;
import es.upv.mist.slicing.graphs.exceptionsensitive.ExceptionSensitiveCallConnector;
import es.upv.mist.slicing.nodes.GraphNode;
import es.upv.mist.slicing.nodes.VariableAction;
import es.upv.mist.slicing.nodes.io.ActualIONode;
import es.upv.mist.slicing.nodes.io.CallNode;
import es.upv.mist.slicing.nodes.io.FormalIONode;
import es.upv.mist.slicing.nodes.io.OutputNode;
import es.upv.mist.slicing.utils.ASTUtils;

import java.util.List;
import java.util.function.Consumer;

public class JSysCallConnector extends ExceptionSensitiveCallConnector {
    public JSysCallConnector(JSysDG sdg) {
@@ -25,41 +24,38 @@ public class JSysCallConnector extends ExceptionSensitiveCallConnector {
    }

    @Override
    protected void connectActualIn(GraphNode<? extends CallableDeclaration<?>> declaration, ActualIONode actualIn) {
        sdg.outgoingEdgesOf(declaration).stream()
                .map(sdg::getEdgeTarget)
                .filter(FormalIONode.class::isInstance)
                .map(FormalIONode.class::cast)
                .filter(actualIn::matchesFormalIO)
                .forEach(formalIn -> {
                    boolean primitive = !formalIn.getVariableName().equals("this")
                            && declaration.getAstNode().getParameterByName(formalIn.getVariableName())
    protected void createActualInConnection(ActualIONode actualIn, FormalIONode formalIn) {
        super.createActualInConnection(actualIn, formalIn);
        if (formalIsObject(formalIn))
            connectObjectInterprocedurally(actualIn, formalIn);
    }

    @Override
    protected void createActualOutConnection(FormalIONode formalOut, ActualIONode actualOut) {
        super.createActualOutConnection(formalOut, actualOut);
        if (formalIsObject(formalOut))
            connectObjectInterprocedurally(formalOut, actualOut);
    }

    protected boolean formalIsObject(FormalIONode formalNode) {
        return formalNode.getVariableName().equals("this")
                || !formalNode.getAstNode().getParameterByName(formalNode.getVariableName())
                .orElseThrow().getType().isPrimitiveType();
                    sdg.addParameterInOutArc(actualIn, formalIn);
                    if (!primitive)
                        connectObjectActualIn(actualIn, formalIn);
                });
    }

    protected void connectObjectActualIn(GraphNode<?> actualIn, GraphNode<?> formalIn) {
        List<VariableAction> formalList = formalIn.getVariableActions();
        assert formalList.size() == 1;
        VariableAction actualVar = actualIn.getLastVariableAction();
        VariableAction formalVar = formalList.get(0);
        actualVar.applySDGTreeConnection((JSysDG) sdg, formalVar);
    protected void connectObjectInterprocedurally(GraphNode<?> source, GraphNode<?> target) {
        assert !target.getVariableActions().isEmpty();
        assert !source.getVariableActions().isEmpty();
        for (VariableAction targetVar : target.getVariableActions())
            source.getLastVariableAction().applySDGTreeConnection((JSysDG) sdg, targetVar);
    }

    @Override
    protected void connectOutput(GraphNode<? extends CallableDeclaration<?>> methodDeclaration, GraphNode<?> callReturnNode) {
        Consumer<GraphNode<?>> action;
        if (ASTUtils.declarationReturnIsObject(methodDeclaration.getAstNode()))
            action = node -> connectObjectOutput(node, callReturnNode);
    protected void createOutputReturnConnection(OutputNode<?> outputNode, CallNode.Return callReturnNode) {
        if (ASTUtils.declarationReturnIsObject(outputNode.getAstNode()))
            connectObjectOutput(outputNode, callReturnNode);
        else
            action = node -> sdg.addParameterInOutArc(node, callReturnNode);
        sdg.outgoingEdgesOf(methodDeclaration).stream()
                .map(sdg::getEdgeTarget)
                .filter(OutputNode.class::isInstance)
                .forEach(action);
            super.createOutputReturnConnection(outputNode, callReturnNode);
    }

    protected void connectObjectOutput(GraphNode<?> methodOutputNode, GraphNode<?> callReturnNode) {
+18 −4
Original line number Diff line number Diff line
@@ -67,6 +67,7 @@ public class CallConnector {
        sdg.outgoingEdgesOf(callNode).stream()
                .map(sdg::getEdgeTarget)
                .filter(CallNode.Return.class::isInstance)
                .map(CallNode.Return.class::cast)
                .forEach(n -> connectOutput(declarationNode, n));
    }

@@ -77,7 +78,11 @@ public class CallConnector {
                .filter(FormalIONode.class::isInstance)
                .map(FormalIONode.class::cast)
                .filter(actualIn::matchesFormalIO)
                .forEach(formalIn -> sdg.addParameterInOutArc(actualIn, formalIn));
                .forEach(formalIn -> createActualInConnection(actualIn, formalIn));
    }

    protected void createActualInConnection(ActualIONode actualIn, FormalIONode formalIn) {
        sdg.addParameterInOutArc(actualIn, formalIn);
    }

    /** Connects an actual-out node to its formal-out counterpart. Arc in reverse direction. */
@@ -87,14 +92,23 @@ public class CallConnector {
                .filter(FormalIONode.class::isInstance)
                .map(FormalIONode.class::cast)
                .filter(actualOut::matchesFormalIO)
                .forEach(formalOut -> sdg.addParameterInOutArc(formalOut, actualOut));
                .forEach(formalOut -> createActualOutConnection(formalOut, actualOut));
    }

    protected void createActualOutConnection(FormalIONode formalOut, ActualIONode actualOut) {
        sdg.addParameterInOutArc(formalOut, actualOut);
    }

    /** Connects a method call return node to its method output counterpart. Arc in reverse direction. */
    protected void connectOutput(GraphNode<? extends CallableDeclaration<?>> methodDeclaration, GraphNode<?> callReturnNode) {
    protected void connectOutput(GraphNode<? extends CallableDeclaration<?>> methodDeclaration, CallNode.Return callReturnNode) {
        sdg.outgoingEdgesOf(methodDeclaration).stream()
                .map(sdg::getEdgeTarget)
                .filter(OutputNode.class::isInstance)
                .forEach(n -> sdg.addParameterInOutArc(n, callReturnNode));
                .map(OutputNode.class::cast)
                .forEach(n -> createOutputReturnConnection(n, callReturnNode));
    }

    protected void createOutputReturnConnection(OutputNode<?> outputNode, CallNode.Return callReturnNode) {
        sdg.addParameterInOutArc(outputNode, callReturnNode);
    }
}