Skip to content
DataDependencyBuilder.java 4.11 KiB
Newer Older

import com.github.javaparser.ast.stmt.*;
import com.github.javaparser.ast.visitor.VoidVisitorAdapter;
import tfm.graphs.cfg.CFG;
import tfm.graphs.pdg.PDG;
Javier Costa's avatar
Javier Costa committed
import tfm.nodes.GraphNode;
import tfm.variables.VariableExtractor;

import java.util.Optional;
import java.util.Set;

class DataDependencyBuilder extends VoidVisitorAdapter<Void> {
    private CFG cfg;
    private PDG pdg;
    public DataDependencyBuilder(PDG pdg, CFG cfg) {
        this.pdg = pdg;
        this.cfg = cfg;
    public void visit(ExpressionStmt expressionStmt, Void ignored) {
        buildDataDependency(expressionStmt);
    }

    @Override
    public void visit(IfStmt ifStmt, Void ignored) {
        buildDataDependency(ifStmt);

        ifStmt.getThenStmt().accept(this, null);

        ifStmt.getElseStmt().ifPresent(statement -> statement.accept(this, null));
    }

    @Override
    public void visit(WhileStmt whileStmt, Void ignored) {
        buildDataDependency(whileStmt);

        whileStmt.getBody().accept(this, null);
    }

    @Override
    public void visit(ForStmt forStmt, Void ignored) {
        GraphNode<ForStmt> forNode = pdg.findNodeByASTNode(forStmt).get();
Javier Costa's avatar
Javier Costa committed
        forStmt.getInitialization().stream()
                .map(ExpressionStmt::new)
                .forEach(expressionStmt -> buildDataDependency(forNode, expressionStmt));
Javier Costa's avatar
Javier Costa committed
        buildDataDependency(forStmt); // Only for comparison

        forStmt.getUpdate().stream()
                .map(ExpressionStmt::new)
                .forEach(expressionStmt -> buildDataDependency(forNode, expressionStmt));
Javier Costa's avatar
Javier Costa committed
        forStmt.getBody().accept(this, null);
    public void visit(ForEachStmt forEachStmt, Void ignored) {
        buildDataDependency(forEachStmt);

        forEachStmt.getBody().accept(this, null);
    }

    @Override
    public void visit(SwitchStmt switchStmt, Void ignored) {
        buildDataDependency(switchStmt);

        switchStmt.getEntries().accept(this, null);
    }

    @Override
    public void visit(SwitchEntryStmt switchEntryStmt, Void ignored) {
        buildDataDependency(switchEntryStmt);

        switchEntryStmt.getStatements().accept(this, null);
    }

    private void buildDataDependency(Statement statement) {
        buildDataDependency(pdg.findNodeByASTNode(statement).get());
Javier Costa's avatar
Javier Costa committed
    private void buildDataDependency(GraphNode<?> node) {
        new VariableExtractor()
                .setOnVariableUseListener(variable -> {
                    node.addUsedVariable(variable);

                    Optional<? extends GraphNode<?>> nodeOptional = cfg.findNodeByASTNode(node.getAstNode());

                    if (!nodeOptional.isPresent()) {
                        return;
                    }

Javier Costa's avatar
Javier Costa committed
                    GraphNode<?> cfgNode = nodeOptional.get();
                    Set<GraphNode<?>> lastDefinitions = cfg.findLastDefinitionsFrom(cfgNode, variable);
Javier Costa's avatar
Javier Costa committed
                    for (GraphNode<?> definitionNode : lastDefinitions) {
                        pdg.findNodeByASTNode(definitionNode.getAstNode())
                                .ifPresent(pdgNode -> pdg.addDataDependencyArc(pdgNode, node, variable));
                    }
                })
                .setOnVariableDefinitionListener(node::addDefinedVariable)
                .setOnVariableDeclarationListener(node::addDeclaredVariable)
                .visit(node.getAstNode());
Javier Costa's avatar
Javier Costa committed

    // For statement special case
Javier Costa's avatar
Javier Costa committed
    private void buildDataDependency(GraphNode<?> forNode, Statement statement) {
Javier Costa's avatar
Javier Costa committed
        new VariableExtractor()
                .setOnVariableUseListener(variable -> {
                    forNode.addUsedVariable(variable);

                    Optional<? extends GraphNode<?>> nodeOptional = cfg.findNodeByASTNode(statement);
Javier Costa's avatar
Javier Costa committed

                    if (!nodeOptional.isPresent()) {
                        return;
                    }

                    pdg.addDataDependencyArc(forNode, forNode, variable);
Javier Costa's avatar
Javier Costa committed
                })
                .setOnVariableDefinitionListener(forNode::addDefinedVariable)
                .setOnVariableDeclarationListener(forNode::addDeclaredVariable)
                .visit(statement);
    }