Unverified Commit 8c87900a authored by Javier Costa's avatar Javier Costa Committed by GitHub
Browse files

Merge pull request #31 from jacosro/organize-nodetypes

Organize NodeType enum
parents af64d37d 35a9f6e6
Loading
Loading
Loading
Loading
+0 −5
Original line number Diff line number Diff line
@@ -10,11 +10,6 @@ public class ACFG extends CFG {
        addControlFlowEdge(from, to, new ControlFlowArc.NonExecutable());
    }

    @Override
    protected void setExitNode(GraphNode<?> exitNode) {
        super.setExitNode(exitNode);
    }

    @Override
    protected CFGBuilder newCFGBuilder() {
        return new ACFGBuilder(this);
+7 −3
Original line number Diff line number Diff line
@@ -2,6 +2,7 @@ package tfm.graphs.augmented;

import com.github.javaparser.ast.Node;
import com.github.javaparser.ast.body.MethodDeclaration;
import com.github.javaparser.ast.body.Parameter;
import com.github.javaparser.ast.expr.BooleanLiteralExpr;
import com.github.javaparser.ast.expr.Expression;
import com.github.javaparser.ast.stmt.*;
@@ -239,13 +240,16 @@ public class ACFGBuilder extends CFGBuilder {
        if (!methodDeclaration.getBody().isPresent())
            throw new IllegalStateException("The method must have a body!");

        graph.buildRootNode("ENTER " + methodDeclaration.getNameAsString(), methodDeclaration, TypeNodeFactory.fromType(NodeType.METHOD));
        graph.buildRootNode("ENTER " + methodDeclaration.getNameAsString(), methodDeclaration, TypeNodeFactory.fromType(NodeType.METHOD_ENTER));

        hangingNodes.add(graph.getRootNode().get());
        for (Parameter param : methodDeclaration.getParameters())
            connectTo(addFormalInGraphNode(param));
        methodDeclaration.getBody().get().accept(this, arg);
        returnList.stream().filter(node -> !hangingNodes.contains(node)).forEach(hangingNodes::add);
        for (Parameter param : methodDeclaration.getParameters())
            connectTo(addFormalOutGraphNode(param));
        nonExecHangingNodes.add(graph.getRootNode().get());
        GraphNode<EmptyStmt> exitNode = connectTo(new EmptyStmt(), "Exit");
        ((ACFG) graph).setExitNode(exitNode);
        connectTo(graph.addNode("Exit", new EmptyStmt(), TypeNodeFactory.fromType(NodeType.METHOD_EXIT)));
    }
}
+7 −16
Original line number Diff line number Diff line
@@ -3,9 +3,9 @@ package tfm.graphs.cfg;
import com.github.javaparser.ast.body.MethodDeclaration;
import tfm.arcs.Arc;
import tfm.arcs.cfg.ControlFlowArc;
import tfm.graphs.Graph;
import tfm.graphs.GraphWithRootNode;
import tfm.nodes.GraphNode;
import tfm.nodes.type.NodeType;
import tfm.utils.NodeNotFoundException;

import java.util.HashSet;
@@ -21,7 +21,6 @@ import java.util.Set;
 */
public class CFG extends GraphWithRootNode<MethodDeclaration> {
    private boolean built = false;
    protected GraphNode<?> exitNode;

    public CFG() {
        super();
@@ -66,28 +65,20 @@ public class CFG extends GraphWithRootNode<MethodDeclaration> {

    @Override
    public boolean removeVertex(GraphNode<?> graphNode) {
        if (Objects.equals(graphNode, exitNode))
        // Cannot remove exit node
        // Enter node's removal is checked in super#removeVertex(GraphNode)
        if (graphNode.getNodeType() == NodeType.METHOD_EXIT)
            return false;
        return super.removeVertex(graphNode);
    }

    public GraphNode<?> getExitNode() {
        return exitNode;
    }

    protected void setExitNode(GraphNode<?> exitNode) {
        if (this.exitNode != null)
            throw new IllegalStateException("Exit node already set!");
        this.exitNode = exitNode;
    }

    @Override
    public void build(MethodDeclaration method) {
        method.accept(newCFGBuilder(), null);
        if (exitNode == null)
            throw new IllegalStateException("Exit node missing!");
        if (vertexSet().stream().noneMatch(n -> n.getNodeType() == NodeType.METHOD_EXIT))
            throw new IllegalStateException("There is no exit node after building the graph");
        built = true;
    }
    }/**/

    @Override
    public boolean isBuilt() {
+35 −51
Original line number Diff line number Diff line
@@ -9,13 +9,15 @@ import com.github.javaparser.ast.stmt.*;
import com.github.javaparser.ast.visitor.VoidVisitor;
import com.github.javaparser.ast.visitor.VoidVisitorAdapter;
import tfm.nodes.GraphNode;
import tfm.nodes.NodeFactory;
import tfm.nodes.TypeNodeFactory;
import tfm.nodes.type.NodeType;
import tfm.utils.ASTUtils;

import java.util.*;

import static tfm.nodes.type.NodeType.FORMAL_IN;
import static tfm.nodes.type.NodeType.FORMAL_OUT;

/**
 * Populates a {@link CFG}, given one and an AST root node.
 * For now it only accepts {@link MethodDeclaration} as roots, as it disallows
@@ -286,64 +288,46 @@ public class CFGBuilder extends VoidVisitorAdapter<Void> {

    @Override
    public void visit(MethodDeclaration methodDeclaration, Void arg) {
        // Sanity checks
        if (graph.getRootNode().isPresent())
            throw new IllegalStateException("CFG is only allowed for one method, not multiple!");
        if (!methodDeclaration.getBody().isPresent())
            throw new IllegalStateException("The method must have a body!");

        graph.buildRootNode("ENTER " + methodDeclaration.getNameAsString(), methodDeclaration, TypeNodeFactory.fromType(NodeType.METHOD));

        // Compute variable in and out expressions (necessary to compute data dependence in SDG)
        List<ExpressionStmt> inVariableExpressions = new ArrayList<>();
        List<ExpressionStmt> outVariableExpressions = new ArrayList<>();

        for (Parameter parameter : methodDeclaration.getParameters()) {
            // In expression
            VariableDeclarationExpr inVariableDeclarationExpr = new VariableDeclarationExpr(
                new VariableDeclarator(
                    parameter.getType(),
                    parameter.getNameAsString(),
                    new NameExpr(parameter.getNameAsString() + "_in")
                )
            );

            ExpressionStmt inExprStmt = new ExpressionStmt(inVariableDeclarationExpr);

            inVariableExpressions.add(inExprStmt);

            // Out expression
            VariableDeclarationExpr outVariableDeclarationExpr = new VariableDeclarationExpr(
                    new VariableDeclarator(
                            parameter.getType(),
                            parameter.getNameAsString() + "_out",
                            new NameExpr(parameter.getNameAsString())
                    )
            );

            ExpressionStmt outExprStmt = new ExpressionStmt(outVariableDeclarationExpr);

            outVariableExpressions.add(outExprStmt);
        }
            throw new IllegalStateException("The method must have a body! Abstract methods have no CFG");

        // Create the root node
        graph.buildRootNode(
                "ENTER " + methodDeclaration.getNameAsString(),
                methodDeclaration,
                TypeNodeFactory.fromType(NodeType.METHOD_ENTER));
        hangingNodes.add(graph.getRootNode().get());

        // Add in variable nodes
        for (ExpressionStmt expressionStmt : inVariableExpressions) {
            GraphNode<ExpressionStmt> node = this.graph.addNode(expressionStmt.toString(), expressionStmt, TypeNodeFactory.fromType(NodeType.VARIABLE_IN));
            connectTo(node);
        }

        // Create and connect formal-in nodes sequentially
        for (Parameter param : methodDeclaration.getParameters())
            connectTo(addFormalInGraphNode(param));
        // Visit the body of the method
        methodDeclaration.getBody().get().accept(this, arg);

        // Append all return statements (without repetition)
        returnList.stream().filter(node -> !hangingNodes.contains(node)).forEach(hangingNodes::add);

        // Add out variable nodes
        for (ExpressionStmt expressionStmt : outVariableExpressions) {
            GraphNode<ExpressionStmt> node = this.graph.addNode(expressionStmt.toString(), expressionStmt, TypeNodeFactory.fromType(NodeType.VARIABLE_OUT));
            connectTo(node);
        // Create and connect formal-out nodes sequentially
        for (Parameter param : methodDeclaration.getParameters())
            connectTo(addFormalOutGraphNode(param));
        // Create and connect the exit node
        connectTo(graph.addNode("Exit", new EmptyStmt(), TypeNodeFactory.fromType(NodeType.METHOD_EXIT)));
    }

    protected GraphNode<ExpressionStmt> addFormalInGraphNode(Parameter param) {
        ExpressionStmt exprStmt = new ExpressionStmt(new VariableDeclarationExpr(new VariableDeclarator(
                param.getType(),
                param.getNameAsString(),
                new NameExpr(param.getNameAsString() + "_in"))));
        return graph.addNode(exprStmt.toString(), exprStmt, TypeNodeFactory.fromType(FORMAL_IN));
    }

        GraphNode<EmptyStmt> exitNode = connectTo(new EmptyStmt(), "Exit");
        graph.setExitNode(exitNode);
    protected GraphNode<ExpressionStmt> addFormalOutGraphNode(Parameter param) {
        ExpressionStmt exprStmt = new ExpressionStmt(new VariableDeclarationExpr(new VariableDeclarator(
                param.getType(),
                param.getNameAsString() + "_out",
                new NameExpr(param.getNameAsString()))));
        return graph.addNode(exprStmt.toString(), exprStmt, TypeNodeFactory.fromType(FORMAL_OUT));
    }
}
+4 −2
Original line number Diff line number Diff line
@@ -4,8 +4,10 @@ import tfm.arcs.Arc;
import tfm.graphs.augmented.PPDG;
import tfm.graphs.cfg.CFG;
import tfm.nodes.GraphNode;
import tfm.nodes.type.NodeType;

import java.util.*;
import java.util.HashSet;
import java.util.Set;
import java.util.stream.Collectors;

/**
@@ -41,7 +43,7 @@ class ControlDependencyBuilder {
        roots.remove(cfg.getRootNode().get());

        Set<GraphNode<?>> cfgNodes = new HashSet<>(cfg.vertexSet());
        cfgNodes.remove(cfg.getExitNode());
        cfgNodes.removeIf(node -> node.getNodeType() == NodeType.METHOD_EXIT);

        for (GraphNode<?> node : cfgNodes)
            registerNode(node);
Loading