Commit 7101ed4f authored by jacosro's avatar jacosro
Browse files

Changed sdg data structure from pdgs to root nodes

parent cbbd7a65
Loading
Loading
Loading
Loading
+0 −6
Original line number Diff line number Diff line
@@ -58,12 +58,6 @@ public abstract class Graph extends DirectedPseudograph<GraphNode<?>, Arc> {
                .collect(Collectors.joining(System.lineSeparator()));
    }

    public List<GraphNode<?>> findDeclarationsOfVariable(String variable) {
        return vertexSet().stream()
                .filter(node -> node.getDeclaredVariables().contains(variable))
                .collect(Collectors.toList());
    }

    public boolean isEmpty() {
        return this.vertexSet().isEmpty();
    }
+8 −0
Original line number Diff line number Diff line
@@ -12,7 +12,9 @@ import tfm.slicing.Slice;
import tfm.slicing.SlicingCriterion;
import tfm.utils.NodeNotFoundException;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * The <b>Program Dependence Graph</b> represents the statements of a method in
@@ -77,4 +79,10 @@ public class PDG extends GraphWithRootNode<MethodDeclaration> implements Sliceab
    public boolean isBuilt() {
        return built;
    }

    public List<GraphNode<?>> findDeclarationsOfVariable(String variable) {
        return vertexSet().stream()
                .filter(node -> node.getDeclaredVariables().contains(variable))
                .collect(Collectors.toList());
    }
}
+3 −1
Original line number Diff line number Diff line
package tfm.graphs.sdg;

import com.github.javaparser.ast.body.MethodDeclaration;
import tfm.graphs.GraphWithRootNode;
import tfm.nodes.GraphNode;
import tfm.utils.Context;
import tfm.utils.Logger;
@@ -20,7 +22,7 @@ class MethodCallReplacer {
            .forEach(context -> {
                Logger.log("MethodCallReplacer", context);

                Optional<GraphNode<?>> optionalRootNode = this.sdg.getRootNode(context);
                Optional<GraphNode<MethodDeclaration>> optionalRootNode = this.sdg.getRootNode(context);

                if (!optionalRootNode.isPresent()) {
                    return; // We don't have visited the code (e.g. the MethodDeclaration for a method call)
+16 −4
Original line number Diff line number Diff line
@@ -24,14 +24,26 @@ import java.util.stream.Collectors;

class MethodCallReplacerVisitor extends VoidVisitorAdapter<Context> {

    private PDG pdg;
    private SDG sdg;
    private GraphNode<ExpressionStmt> methodCallNode;

    public MethodCallReplacerVisitor() {

    }

    public MethodCallReplacerVisitor(PDG pdg) {
        this.pdg = pdg;
    public MethodCallReplacerVisitor(SDG sdg) {
        this.sdg = sdg;
    }

    @Override
    public void visit(ExpressionStmt n, Context arg) {
        Optional<GraphNode<ExpressionStmt>> optionalNode = sdg.findNodeByASTNode(n);

        assert optionalNode.isPresent();

        methodCallNode = optionalNode.get();

        super.visit(n, arg);
    }

    @Override
@@ -66,7 +78,7 @@ class MethodCallReplacerVisitor extends VoidVisitorAdapter<Context> {
        if (!Objects.equals(scopeName, currentClass.getNameAsString())) {

            // Check if 'scopeName' is a variable
            List<GraphNode<?>> declarations = pdg.findDeclarationsOfVariable(scopeName);
            List<GraphNode<?>> declarations = sdg.findDeclarationsOfVariable(scopeName, methodCallNode);

            if (declarations.isEmpty()) {
                // It is a static method call of another class. We do nothing
+57 −10
Original line number Diff line number Diff line
@@ -4,12 +4,14 @@ import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.NodeList;
import com.github.javaparser.ast.body.MethodDeclaration;
import com.github.javaparser.ast.stmt.ExpressionStmt;
import tfm.arcs.Arc;
import tfm.arcs.pdg.ControlDependencyArc;
import tfm.arcs.pdg.DataDependencyArc;
import tfm.arcs.sdg.CallArc;
import tfm.arcs.sdg.ParameterInOutArc;
import tfm.graphs.Buildable;
import tfm.graphs.Graph;
import tfm.graphs.pdg.PDG;
import tfm.nodes.*;
import tfm.slicing.Slice;
import tfm.slicing.Sliceable;
@@ -17,14 +19,16 @@ import tfm.slicing.SlicingCriterion;
import tfm.utils.Context;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

public class SDG extends Graph implements Sliceable, Buildable<NodeList<CompilationUnit>> {
    private boolean built = false;

    private Map<Context, Long> contextToRootNodeId;
    private Map<Context, Long> contextToMethodRoot;

    public SDG() {
        this.contextToRootNodeId = new HashMap<>();
        this.contextToMethodRoot = new HashMap<>();
    }

    @Override
@@ -43,21 +47,45 @@ public class SDG extends Graph implements Sliceable, Buildable<NodeList<Compilat
    }

    public Set<Context> getContexts() {
        return contextToRootNodeId.keySet();
        return contextToMethodRoot.keySet();
    }

    public Optional<GraphNode<?>> getRootNode(Context context) {
        Long id = this.contextToRootNodeId.get(context);
    @SuppressWarnings("unchecked")
    public List<GraphNode<MethodDeclaration>> getMethodRoots() {
        return contextToMethodRoot.values().stream()
                .map(id -> findNodeById(id))
                .filter(Optional::isPresent)
                .map(optional -> (GraphNode<MethodDeclaration>) optional.get())
                .collect(Collectors.toList());
    }

    @SuppressWarnings("unchecked")
    public Optional<GraphNode<MethodDeclaration>> getRootNode(Context context) {
        Long id = this.contextToMethodRoot.get(context);

        if (id == null) {
            return Optional.empty();
        }

        return id != null ? findNodeById(id) : Optional.empty();
        return findNodeById(id).map(node -> (GraphNode<MethodDeclaration>) node);
    }

    public void addRootNode(Context context, long id) {
        if (!findNodeById(id).isPresent()) {
            throw new IllegalArgumentException("Cannot add root node to SDG: " + id + " is not in graph!");
        if (!findNodeById(id).isPresent())
            throw new IllegalArgumentException("Root node with id " + id + " is not contained in graph!");

        this.contextToMethodRoot.put(new Context(context), id);
    }

    public void addRootNode(Context context, GraphNode<MethodDeclaration> node) {
        addRootNode(context, node.getId());
    }

        this.contextToRootNodeId.put(new Context(context), id);
    public Optional<Context> getContext(long id) {
        return contextToMethodRoot.entrySet().stream()
                .filter(entry -> Objects.equals(entry.getValue(), id))
                .findFirst()
                .map(Map.Entry::getKey);
    }

    public void addControlDependencyArc(GraphNode<?> from, GraphNode<?> to) {
@@ -75,4 +103,23 @@ public class SDG extends Graph implements Sliceable, Buildable<NodeList<Compilat
    public void addParameterInOutArc(GraphNode<ExpressionStmt> from, GraphNode<ExpressionStmt> to) {
        this.addEdge(from, to, new ParameterInOutArc());
    }

    public List<GraphNode<?>> findDeclarationsOfVariable(String variable, GraphNode<?> root) {
        List<GraphNode<?>> res = new ArrayList<>();

        // First, expand the node
        for (Arc arc : incomingEdgesOf(root)) {
            if (arc.isDataDependencyArc() || arc.isControlDependencyArc()) {
                res.addAll(findDeclarationsOfVariable(variable, getEdgeSource(arc)));
            }
        }

        // Finally, the current node
        // This way, the last element of the list is the most recent declaration
        if (root.getDeclaredVariables().contains(variable)) {
            res.add(root);
        }

        return res;
    }
}
Loading