Commit 21139d4b authored by Carlos Galindo's avatar Carlos Galindo
Browse files

fix! VariableVisitor no longer creates new NameExpr

parent f5aa3726
Loading
Loading
Loading
Loading
+31 −54
Original line number Diff line number Diff line
@@ -6,13 +6,14 @@ import com.github.javaparser.ast.body.FieldDeclaration;
import com.github.javaparser.ast.body.Parameter;
import com.github.javaparser.ast.body.VariableDeclarator;
import com.github.javaparser.ast.expr.*;
import com.github.javaparser.ast.nodeTypes.NodeWithVariables;
import com.github.javaparser.ast.stmt.CatchClause;
import com.github.javaparser.ast.stmt.ExplicitConstructorInvocationStmt;
import com.github.javaparser.ast.stmt.ExpressionStmt;
import com.github.javaparser.ast.stmt.ForEachStmt;
import com.github.javaparser.resolution.Resolvable;
import com.github.javaparser.resolution.UnsolvedSymbolException;
import com.github.javaparser.resolution.declarations.ResolvedMethodLikeDeclaration;
import com.github.javaparser.resolution.declarations.ResolvedValueDeclaration;
import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserFieldDeclaration;
import es.upv.mist.slicing.graphs.GraphNodeContentVisitor;
import es.upv.mist.slicing.utils.ASTUtils;
@@ -79,10 +80,6 @@ public class VariableVisitor extends GraphNodeContentVisitor<VariableVisitor.Act
        this.useConsumer = Objects.requireNonNullElse(useConsumer, BLANK_TRICONSUMER);
    }

    public void visitAsDefinition(Node node, Expression value) {
        visitAsDefinition(node, value, Action.DEFINITION);
    }

    public void visitAsDefinition(Node node, Expression value, Action action) {
        definitionStack.push(value);
        node.accept(this, action.or(Action.DEFINITION));
@@ -150,8 +147,9 @@ public class VariableVisitor extends GraphNodeContentVisitor<VariableVisitor.Act
    public void visit(ForEachStmt n, Action action) {
        n.getIterable().accept(this, Action.USE);
        for (VariableDeclarator variable : n.getVariable().getVariables()) {
            variable.getNameAsExpression().accept(this, Action.DECLARATION);
            visitAsDefinition(variable.getNameAsExpression(), null); // TODO: add a better initializer
            declConsumer.accept(graphNode, null, variable.getNameAsString());
            // ForEach initializes to each value of the iterable, but that expression is not available.
            defConsumer.accept(graphNode, null, variable.getNameAsString(), null);
        }
    }

@@ -214,22 +212,20 @@ public class VariableVisitor extends GraphNodeContentVisitor<VariableVisitor.Act

    @Override
    public void visit(VariableDeclarationExpr n, Action action) {
        for (VariableDeclarator v : n.getVariables()) {
            v.getNameAsExpression().accept(this, action.or(Action.DECLARATION));
            v.getInitializer().ifPresent(init -> {
                init.accept(this, action);
                visitAsDefinition(v.getNameAsExpression(), init);
            });
        }
        visitVarDeclaration(n, action);
    }

    @Override
    public void visit(FieldDeclaration n, Action action) {
        for (VariableDeclarator v : n.getVariables()) {
            v.getNameAsExpression().accept(this, action.or(Action.DECLARATION));
        visitVarDeclaration(n, action);
    }

    protected void visitVarDeclaration(NodeWithVariables<?> declaration, Action action) {
        for (VariableDeclarator v : declaration.getVariables()) {
            declConsumer.accept(graphNode, null, v.getNameAsString());
            v.getInitializer().ifPresent(init -> {
                init.accept(this, action);
                visitAsDefinition(v.getNameAsExpression(), init);
                defConsumer.accept(graphNode, null, v.getNameAsString(), init);
            });
        }
    }
@@ -281,13 +277,12 @@ public class VariableVisitor extends GraphNodeContentVisitor<VariableVisitor.Act
        return false;
    }

    /** Obtain the prefixed name of a variable, to improve matching of variables
     *  that point to the same object, such as 'x' and 'this.x'. */
    protected String getRealName(Expression n) {
        if (n.isNameExpr()) { // Add a prefix to the name ("this." or "CLASS.this.") when "n" is a NameExpr
            NameExpr en = n.asNameExpr();
        if (n.isNameExpr()) {
            try {
                String prefix = this.getNamePrefix(en); // Add a prefix to the name ("this." or "CLASS.this.")
                if (!prefix.isEmpty())
                    return prefix + n.toString();
                return getNamePrefix(n.asNameExpr()) + n.toString();
            } catch (UnsolvedSymbolException e) {
                Logger.log("Unable to resolve symbol " + e.getName());
            }
@@ -295,38 +290,20 @@ public class VariableVisitor extends GraphNodeContentVisitor<VariableVisitor.Act
        return n.toString();
    }

    /** Checks whether a NameExpr representing a variable
     * is a Field and returns the correct prefix to reference it */
    /** Generate the correct prefix for a NameExpr. Only works for non-static fields. */
    protected String getNamePrefix(NameExpr n) {
        // There are three constructs whose variable cannot be resolved due to: getNameAsExpression() function
        // FieldDeclaration, VariableDeclarationExpr, and ForEachStmt. They must be treated separately

        // 1. FieldDeclaration
        if (graphNode.getAstNode() instanceof FieldDeclaration)
            return "this.";
        // 2. VariableDeclarationExpr
        if (graphNode.getAstNode() instanceof ExpressionStmt) {
            Expression expr = ((ExpressionStmt) graphNode.getAstNode()).getExpression();
            if (expr instanceof VariableDeclarationExpr)
        // We only care about non-static fields
        ResolvedValueDeclaration resolved = n.resolve();
        if (!resolved.isField() || resolved.asField().isStatic())
            return "";
        }
        // 3. ForEachStmt
        if (graphNode.getAstNode() instanceof ForEachStmt)
            throw new RuntimeException("ForEachStmt internal structure is still a mystery for me");// TODO: Execute and see the internal structure

        // The rest of nodes can be resolved properly
        if (n.resolve().isField() && !n.resolve().asField().isStatic()){
            JavaParserFieldDeclaration fieldDeclaration = (JavaParserFieldDeclaration) n.resolve();
            Node decClass = ASTUtils.getClassNode(fieldDeclaration.getVariableDeclarator());
        // Obtain the class where the field is declared and the current class
        JavaParserFieldDeclaration field = (JavaParserFieldDeclaration) resolved.asField();
        Node decClass = ASTUtils.getClassNode(field.getVariableDeclarator());
        Node nClass = ASTUtils.getClassNode(n);

            assert (nClass instanceof ClassOrInterfaceDeclaration &&
                    decClass instanceof ClassOrInterfaceDeclaration);

        // If the classes match, the prefix can be simplified
        if (decClass.equals(nClass))
            return "this.";
        // Full prefix
        return ((ClassOrInterfaceDeclaration) decClass).getNameAsString() + ".this.";
    }
        return "";
    }
}
+1 −2
Original line number Diff line number Diff line
@@ -185,8 +185,7 @@ public class ASTUtils {
    public static Node getClassNode(Node n){
        Node upperNode = n;
        while (!(upperNode instanceof ClassOrInterfaceDeclaration))
            upperNode = upperNode.getParentNode().get();

            upperNode = upperNode.getParentNode().orElseThrow();
        return upperNode;
    }
}