Commit 1f9911ff authored by jacosro's avatar jacosro
Browse files

Implemented out nodes

parent 7cb05e5d
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
@@ -4,6 +4,10 @@ import com.github.javaparser.JavaParser;
import com.github.javaparser.ast.Node;
import com.github.javaparser.ast.NodeList;
import com.github.javaparser.ast.body.MethodDeclaration;
import com.github.javaparser.ast.type.Type;
import com.github.javaparser.ast.visitor.GenericVisitor;
import com.github.javaparser.ast.visitor.VoidVisitor;
import com.github.javaparser.resolution.types.ResolvedType;
import tfm.graphs.cfg.CFG;
import tfm.graphs.Graph;
import tfm.graphs.pdg.PDG;
@@ -20,7 +24,7 @@ public class Main {

    public static final String PROGRAM = Utils.PROGRAMS_FOLDER + "sdg/Example1.java";
    public static final String GRAPH = GraphLog.PDG;
    public static final String METHOD = "sum";
    public static final String METHOD = "main";

    public static void main(String[] args) throws IOException {
        JavaParser.getStaticConfiguration().setAttributeComments(false);
+29 −14
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ import tfm.nodes.TypeNodeFactory;
import tfm.nodes.type.NodeType;
import tfm.utils.Context;
import tfm.utils.Logger;
import tfm.utils.MethodDeclarationSolver;

import java.nio.file.Path;
import java.util.List;
@@ -114,7 +115,10 @@ class MethodCallReplacerVisitor extends VoidVisitorAdapter<Context> {

        Logger.log("MethodCallReplacerVisitor", context);

        Optional<GraphNode<MethodDeclaration>> optionalNethodDeclarationNode = getMethodDeclarationNodeWithJavaParser(methodCallExpr);
        Optional<GraphNode<MethodDeclaration>> optionalNethodDeclarationNode =
                MethodDeclarationSolver.getInstance()
                    .findDeclarationFrom(methodCallExpr)
                    .flatMap(methodDeclaration -> sdg.findNodeByASTNode(methodDeclaration));

        if (!optionalNethodDeclarationNode.isPresent()) {
            Logger.format("Not found: '%s'. Discarding", methodCallExpr);
@@ -191,6 +195,15 @@ class MethodCallReplacerVisitor extends VoidVisitorAdapter<Context> {
            }

            // Out expression

            if (!argument.isNameExpr() && !sdg.findDeclarationsOfVariable(argument.toString(), methodCallNode).isEmpty()) {
                /*
                    If the argument is not a variable (is a name expression and it is declared in the scope),
                    then there is no OUT node
                 */
                continue;
            }

            VariableDeclarationExpr outVariableDeclarationExpr = new VariableDeclarationExpr(
                    new VariableDeclarator(
                            parameter.getType(),
@@ -205,13 +218,26 @@ class MethodCallReplacerVisitor extends VoidVisitorAdapter<Context> {

            sdg.addControlDependencyArc(methodCallNode, argumentOutNode);

            // Now, find the corresponding method declaration's out node and link argument node with it
            // Now, find the corresponding method call's out node and link argument node with it

            Optional<GraphNode<ExpressionStmt>> optionalParameterOutNode = sdg.outgoingEdgesOf(methodDeclarationNode).stream()
                    .map(arc -> (GraphNode<ExpressionStmt>) sdg.getEdgeTarget(arc))
                    .filter(node -> node.getNodeType() == NodeType.VARIABLE_OUT && node.getInstruction().contains(parameter.getNameAsString() + "_out"))
                    .findFirst();

            // Handle data dependency: remove arc from method call node and add it to OUT node

            List<DataDependencyArc> outDataDependencies = sdg.outgoingEdgesOf(methodCallNode).stream()
                    .filter(arc -> arc.isDataDependencyArc() && Objects.equals(arc.getLabel(), argument.toString()))
                    .map(Arc::asDataDependencyArc)
                    .collect(Collectors.toList());

            for (DataDependencyArc arc : outDataDependencies) {
                GraphNode<?> dataDependencyTarget = sdg.getEdgeTarget(arc);
                sdg.removeEdge(arc);
                sdg.addDataDependencyArc(argumentOutNode, dataDependencyTarget, argument.toString());
            }

            if (optionalParameterOutNode.isPresent()) {
                sdg.addParameterInOutArc(optionalParameterOutNode.get(), argumentOutNode);
            } else {
@@ -224,19 +250,8 @@ class MethodCallReplacerVisitor extends VoidVisitorAdapter<Context> {
        Logger.log("MethodCallReplacerVisitor", String.format("%s | Method '%s' called", methodCallExpr, methodDeclaration.getNameAsString()));
    }

    private Optional<GraphNode<MethodDeclaration>> getMethodDeclarationNodeWithJavaParser(MethodCallExpr methodCallExpr) {
        TypeSolver typeSolver = new ReflectionTypeSolver();

        try {
            SymbolReference<ResolvedMethodDeclaration> solver = JavaParserFacade.get(typeSolver).solve(methodCallExpr);
    private void argumentAsNameExpr(GraphNode<ExpressionStmt> methodCallNode) {

            return solver.isSolved()
                    ? solver.getCorrespondingDeclaration().toAst()
                        .flatMap(methodDeclaration -> sdg.findNodeByASTNode(methodDeclaration))
                    : Optional.empty();
        } catch (UnsolvedSymbolException e) {
            return Optional.empty();
        }
    }

    @Override
+15 −17
Original line number Diff line number Diff line
package tfm.utils;

import com.github.javaparser.ast.Node;
import com.github.javaparser.ast.body.MethodDeclaration;
import com.github.javaparser.ast.expr.MethodCallExpr;
import com.github.javaparser.resolution.UnsolvedSymbolException;
@@ -9,39 +8,38 @@ import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
import tfm.nodes.GraphNode;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.*;

public class SymbolSolverWrapper {
public class MethodDeclarationSolver {

    private static final SymbolSolverWrapper instance = new SymbolSolverWrapper();
    private static final List<TypeSolver> typeSolvers = new ArrayList<>();
    private static final MethodDeclarationSolver instance = new MethodDeclarationSolver();
    private static final List<TypeSolver> usedTypeSolvers = new ArrayList<>();

    private SymbolSolverWrapper() {
    private MethodDeclarationSolver() {

    }

    public static void addTypeSolver(TypeSolver typeSolver) {
        typeSolvers.add(typeSolver);
    public static void addTypeSolvers(TypeSolver... typeSolvers) {
        usedTypeSolvers.addAll(Arrays.asList(typeSolvers));
    }

    public static SymbolSolverWrapper getInstance() {
    public static MethodDeclarationSolver getInstance() {
        return instance;
    }

    private <N extends Node> Optional<N> findNodeFrom(MethodCallExpr methodCallExpr) {
        CombinedTypeSolver combinedTypeSolver = new CombinedTypeSolver();
    public Optional<MethodDeclaration> findDeclarationFrom(MethodCallExpr methodCallExpr) {
        return this.findDeclarationFrom(methodCallExpr, usedTypeSolvers);
    }

    public Optional<MethodDeclaration> findDeclarationFrom(MethodCallExpr methodCallExpr, Collection<? extends TypeSolver> customTypeSolvers) {
        CombinedTypeSolver combinedTypeSolver = new CombinedTypeSolver(customTypeSolvers.toArray(new TypeSolver[0]));

        try {
            SymbolReference<ResolvedMethodDeclaration> solver = JavaParserFacade.get(typeSolver).solve(methodCallExpr);
            SymbolReference<ResolvedMethodDeclaration> solver = JavaParserFacade.get(combinedTypeSolver).solve(methodCallExpr);

            return solver.isSolved()
                    ? solver.getCorrespondingDeclaration().toAst()
                    .flatMap(methodDeclaration -> sdg.findNodeByASTNode(methodDeclaration))
                    : Optional.empty();
        } catch (UnsolvedSymbolException e) {
            return Optional.empty();
+10 −1
Original line number Diff line number Diff line
@@ -7,6 +7,8 @@ import com.github.javaparser.ast.visitor.VoidVisitorAdapter;
import org.checkerframework.checker.nullness.qual.NonNull;
import tfm.variables.actions.VariableAction;

import java.awt.*;

abstract class VariableVisitor extends VoidVisitorAdapter<VariableAction.Actions> {

    @Override
@@ -101,7 +103,14 @@ abstract class VariableVisitor extends VoidVisitorAdapter<VariableAction.Actions
    public void visit(MethodCallExpr n, VariableAction.Actions action) {
        // // Logger.log("On MethodCallExpr: [" + n + "]");
        n.getScope().ifPresent(expression -> expression.accept(this, action.or(VariableAction.Actions.USE)));
        n.getArguments().forEach(expression -> expression.accept(this, action.or(VariableAction.Actions.USE)));
        n.getArguments().forEach(expression -> {
            expression.accept(this, action.or(VariableAction.Actions.USE));


            if (expression.isNameExpr() || expression.isFieldAccessExpr()) {
                expression.accept(this, action.or(VariableAction.Actions.DEFINITION));
            }
        });
    }

    @Override
+11 −2
Original line number Diff line number Diff line
@@ -11,16 +11,25 @@ public class Example1 {

     */

    int num;

    public static void main(String[] args) {
        int x = 1;
        int y = 2;

        int f = sum(x, y);
        Example1 example1 = new Example1();
        Example1 example2 = new Example1();

        int f = sum(example1.getNum(), example2.num);

        Logger.log(x);
        Logger.log(example1.num);
        Logger.log(f);
    }

    public int getNum() {
        return num;
    }

    private static int sum(int x, int y) {
        int res = x + y;
        return res;