Commit f8183adf authored by Javier Costa's avatar Javier Costa
Browse files

Replacing method calls

parent 2183fed1
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -2,3 +2,4 @@
.idea/
target/
out/
.settings/
 No newline at end of file
+1 −1
Original line number Diff line number Diff line
@@ -4,11 +4,11 @@ import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
import com.github.javaparser.ast.body.MethodDeclaration;
import com.github.javaparser.ast.visitor.VoidVisitorAdapter;
import javassist.expr.MethodCall;
import tfm.graphbuilding.Graphs;
import tfm.graphs.PDGGraph;
import tfm.graphs.SDGGraph;
import tfm.utils.Context;
import tfm.visitors.sdg.methodcall.MethodCallReplacer;

public class NewSDGBuilder extends VoidVisitorAdapter<Context> {

+1 −0
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import java.util.Optional;
 * Asumimos que procesamos 1 archivo con una o más clases donde el primer método de la primera clase es el main
 *
 */
@Deprecated
public class SDGBuilder extends VoidVisitorAdapter<Void> {

    SDGGraph sdgGraph;
+1 −4
Original line number Diff line number Diff line
package tfm.visitors.sdg;
package tfm.visitors.sdg.methodcall;

import com.github.javaparser.ast.body.MethodDeclaration;
import tfm.graphs.PDGGraph;
import tfm.graphs.SDGGraph;
import tfm.utils.Context;

public class MethodCallReplacer {

+76 −10
Original line number Diff line number Diff line
package tfm.visitors.sdg;
package tfm.visitors.sdg.methodcall;

import com.github.javaparser.ast.Node;
import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
import com.github.javaparser.ast.body.MethodDeclaration;
import com.github.javaparser.ast.body.VariableDeclarator;
import com.github.javaparser.ast.expr.AssignExpr;
import com.github.javaparser.ast.expr.MethodCallExpr;
import com.github.javaparser.ast.expr.StringLiteralExpr;
import com.github.javaparser.ast.expr.VariableDeclarationExpr;
import com.github.javaparser.ast.nodeTypes.NodeWithSimpleName;
import com.github.javaparser.ast.stmt.ExpressionStmt;
import com.github.javaparser.ast.type.Type;
import com.github.javaparser.ast.visitor.VoidVisitorAdapter;
@@ -13,10 +16,10 @@ import tfm.graphs.PDGGraph;
import tfm.nodes.GraphNode;
import tfm.utils.Context;
import tfm.utils.Logger;
import tfm.utils.Utils;
import tfm.variables.actions.VariableDeclaration;

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

public class MethodCallReplacerVisitor extends VoidVisitorAdapter<Context> {
@@ -38,19 +41,82 @@ public class MethodCallReplacerVisitor extends VoidVisitorAdapter<Context> {
            return;
        }

        // todo make call
        /* TODO

            1. Get parameters of the method declaration

            2. Parse arguments of the method call

            3. Build in and out assignment expressions

            4. Add in and out variable nodes

            5. Compute data dependency of new nodes

         */

        MethodDeclaration callingMethod = optionalCallingMethod.get();

        // 1
        List<String> parameterNames = callingMethod.getParameters().stream()
                .map(NodeWithSimpleName::getNameAsString)
                .collect(Collectors.toList());

        // todo: Add global variables

        // 2
        List<String> argumentNames = methodCallExpr.getArguments().stream()
                .map(Node::toString) // todo: argument can be a numeric, string, or method call expression. Must differentiate between them
                .collect(Collectors.toList());

        // todo: Add global variables

        // 3
        if (parameterNames.size() != argumentNames.size()) {
            // todo: The last parameter is varargs: wrap the last n arguments in an array
        }

        List<AssignExpr> assignExprs = Utils.emptyList();

        // IN assignments
        for (int i = 0; i < parameterNames.size(); i++) {
            AssignExpr assignExpr =
                    new AssignExpr(
                            new StringLiteralExpr(parameterNames.get(i) + "_in"),
                            new StringLiteralExpr(argumentNames.get(i)),
                            AssignExpr.Operator.ASSIGN
                    );

            assignExprs.add(assignExpr);
        }

        // OUT assignments
        // todo

        // 4
        int lastId = pdgGraph.getNodes().stream()
                .map(GraphNode::getId)
                .max(Integer::compareTo)
                .orElse(-1);

        for (AssignExpr assignExpr : assignExprs) {
            pdgGraph.addNode(new GraphNode<Node>(lastId + 1, assignExpr.toString(), assignExpr));
        }

        // 5
        // todo
        // For IN, get last defined variable
        // For OUT, get first used variable

        Logger.log(String.format("Method '%s' called", optionalCallingMethod.get().getNameAsString()));
    }

    private Optional<MethodDeclaration> shouldMakeCallWithScope(MethodCallExpr methodCallExpr, Context context) {
        assert methodCallExpr.getScope().isPresent();
        assert context.getCurrentClass().isPresent();

        String scopeName = methodCallExpr.getScope().get().toString();

        if (!context.getCurrentClass().isPresent()) {
            return Optional.empty();
        }

        ClassOrInterfaceDeclaration currentClass = context.getCurrentClass().get();

        // Check if it's a static method call of current class
@@ -60,7 +126,7 @@ public class MethodCallReplacerVisitor extends VoidVisitorAdapter<Context> {
            List<GraphNode<?>> declarations = pdgGraph.findDeclarationsOfVariable(scopeName);

            if (declarations.isEmpty()) {
                // It is a static method call of another class. We do nothing
                // It is a static method call of another class TODO: check other classes in the same file (compilation unit)
                return Optional.empty();
            }