Skip to content
DataDependencyVisitor.java 4.25 KiB
Newer Older
package tfm.visitors;

Javier Costa's avatar
Javier Costa committed
import com.github.javaparser.ast.Node;
import com.github.javaparser.ast.stmt.*;
import com.github.javaparser.ast.visitor.VoidVisitorAdapter;
import tfm.graphs.CFGGraph;
import tfm.graphs.PDGGraph;
import tfm.nodes.CFGNode;
import tfm.nodes.PDGNode;
Javier Costa's avatar
Javier Costa committed
import tfm.utils.Utils;
import tfm.variables.VariableExtractor;

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

public class DataDependencyVisitor extends VoidVisitorAdapter<Void> {

    private CFGGraph cfgGraph;
    private PDGGraph pdgGraph;

    public DataDependencyVisitor(PDGGraph pdgGraph, CFGGraph cfgGraph) {
        this.pdgGraph = pdgGraph;
        this.cfgGraph = cfgGraph;
    }

    @Override
    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) {
Javier Costa's avatar
Javier Costa committed
        PDGNode forNode = pdgGraph.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(pdgGraph.findNodeByASTNode(statement).get());
    }

    private void buildDataDependency(PDGNode node) {
        new VariableExtractor()
                .setOnVariableUseListener(variable -> {
                    node.addUsedVariable(variable);

Javier Costa's avatar
Javier Costa committed
                    Optional<CFGNode<?>> nodeOptional = cfgGraph.findNodeByASTNode(node.getAstNode());

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

                    CFGNode cfgNode = nodeOptional.get();

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

    // For statement special case
    private void buildDataDependency(PDGNode forNode, Statement statement) {
        new VariableExtractor()
                .setOnVariableUseListener(variable -> {
                    forNode.addUsedVariable(variable);

Javier Costa's avatar
Javier Costa committed
                    Optional<CFGNode<?>> nodeOptional = cfgGraph.findNodeByASTNode(statement);
Javier Costa's avatar
Javier Costa committed

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

                    pdgGraph.addDataDependencyArc(forNode, forNode, variable);
                })
                .setOnVariableDefinitionListener(forNode::addDefinedVariable)
                .setOnVariableDeclarationListener(forNode::addDeclaredVariable)
                .visit(statement);
    }