Commit f8b7a13a authored by Carlos Galindo's avatar Carlos Galindo
Browse files

Add implicit constructors

* Small regression: only the last field declared in a constructor is included. This is expected, and will be solved with the new object dependencies.
* Integrate ImplicitNode as boolean in GraphNode.
* Updated tests
* Slice now allows the insertion of implicit instructions, but does not output them when generating the AST.
* Removed list of nodes from slice, as the map contains a superset of the information of the list.
parent a81337d6
Loading
Loading
Loading
Loading
+0 −15
Original line number Diff line number Diff line
package es.upv.mist.slicing.graphs.jsysdg;

import com.github.javaparser.ast.Node;
import es.upv.mist.slicing.nodes.SyntheticNode;

/**
 * A graph node that does not exist in the original program, but represents
 * implicit code constructs such as 'super()' at the start of a constructor.
 * @param <T> The type of the AST node contained in this graph node.
 */
public class ImplicitNode<T extends Node> extends SyntheticNode<T> {
    protected ImplicitNode(String instruction, T astNode) {
        super(instruction, astNode);
    }
}
+27 −6
Original line number Diff line number Diff line
@@ -2,6 +2,7 @@ package es.upv.mist.slicing.graphs.jsysdg;

import com.github.javaparser.ast.Node;
import com.github.javaparser.ast.NodeList;
import com.github.javaparser.ast.body.CallableDeclaration;
import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
import com.github.javaparser.ast.body.ConstructorDeclaration;
import com.github.javaparser.ast.body.FieldDeclaration;
@@ -12,10 +13,12 @@ import es.upv.mist.slicing.graphs.ClassGraph;
import es.upv.mist.slicing.graphs.cfg.CFGBuilder;
import es.upv.mist.slicing.graphs.exceptionsensitive.ESCFG;
import es.upv.mist.slicing.nodes.GraphNode;
import es.upv.mist.slicing.nodes.io.MethodExitNode;
import es.upv.mist.slicing.utils.ASTUtils;

import java.util.LinkedList;
import java.util.List;
import java.util.Set;

/**
 * An SDG that is tailored for Java, including a class graph, inheritance,
@@ -24,10 +27,20 @@ import java.util.List;
public class JSysCFG extends ESCFG {
    /** ClassGraph associated to the Method represented by the CFG */
    protected ClassGraph classGraph;
    /** Set of constructors that must be built with implicit nodes. */
    protected Set<ConstructorDeclaration> implicitConstructors;

    public JSysCFG(ClassGraph classGraph){
    public JSysCFG(ClassGraph classGraph, Set<ConstructorDeclaration> implicitConstructors) {
        super();
        this.classGraph = classGraph;
        this.implicitConstructors = implicitConstructors;
    }

    @Override
    public void buildRootNode(CallableDeclaration<?> rootNodeAst) {
        super.buildRootNode(rootNodeAst);
        if (implicitConstructors.contains(rootNodeAst))
            rootNode.markAsImplicit();
    }

    @Override
@@ -39,6 +52,8 @@ public class JSysCFG extends ESCFG {
        /** List of implicit instructions inserted explicitly in this CFG.
         *  They should be included in the graph as ImplicitNodes. */
        protected List<Node> methodInsertedInstructions = new LinkedList<>();
        /** Whether we are building a CFG for an implicit method or not. */
        protected boolean implicitDeclaration = false;

        protected Builder(JSysCFG jSysCFG) {
            super(JSysCFG.this);
@@ -48,11 +63,10 @@ public class JSysCFG extends ESCFG {
        @Override
        protected <T extends Node> GraphNode<T> connectTo(T n, String text) {
            GraphNode<T> dest;
            if (methodInsertedInstructions.contains(n)) {
                dest = new ImplicitNode<>(n.toString(), n);
            } else {
            dest = new GraphNode<>(text, n);
            }
            if (methodInsertedInstructions.contains(n) ||
                    (implicitDeclaration && !(n instanceof FieldDeclaration)))
                dest.markAsImplicit();
            addVertex(dest);
            connectTo(dest);
            return dest;
@@ -79,6 +93,8 @@ public class JSysCFG extends ESCFG {

        @Override
        public void visit(ConstructorDeclaration n, Void arg) {
            if (implicitConstructors.contains(n))
                implicitDeclaration = true;
            // Insert call to super() if it is implicit.
            if (!ASTUtils.constructorHasExplicitConstructorInvocation(n)){
                var superCall = new ExplicitConstructorInvocationStmt(null, null, false, null, new NodeList<>());
@@ -90,6 +106,11 @@ public class JSysCFG extends ESCFG {
            }
            // Perform the same task as previous graphs.
            super.visit(n, arg);
            // Convert the exit nodes to implicit if appropriate
            if (implicitDeclaration)
                vertexSet().stream()
                        .filter(MethodExitNode.class::isInstance)
                        .forEach(GraphNode::markAsImplicit);
        }
    }
}
+29 −1
Original line number Diff line number Diff line
package es.upv.mist.slicing.graphs.jsysdg;

import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.Modifier;
import com.github.javaparser.ast.NodeList;
import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
import com.github.javaparser.ast.body.ConstructorDeclaration;
import com.github.javaparser.ast.visitor.ModifierVisitor;
import com.github.javaparser.ast.visitor.Visitable;
import es.upv.mist.slicing.graphs.augmented.PSDG;
import es.upv.mist.slicing.graphs.cfg.CFG;
import es.upv.mist.slicing.graphs.exceptionsensitive.ESSDG;
import es.upv.mist.slicing.graphs.exceptionsensitive.ExceptionSensitiveCallConnector;
import es.upv.mist.slicing.graphs.pdg.PDG;
import es.upv.mist.slicing.utils.NodeHashSet;

public class JSysDG extends ESSDG {

@@ -17,9 +25,29 @@ public class JSysDG extends ESSDG {
     * @see PSDG.Builder
     * @see ExceptionSensitiveCallConnector */
    class Builder extends ESSDG.Builder {
        protected NodeHashSet<ConstructorDeclaration> newlyInsertedConstructors = new NodeHashSet<>();

        @Override
        public void build(NodeList<CompilationUnit> nodeList) {
            insertImplicitConstructors(nodeList);
            super.build(nodeList);
        }

        /** Create implicit constructors, and store them in a set so that they may be built with implicit nodes. */
        protected void insertImplicitConstructors(NodeList<CompilationUnit> nodeList) {
            nodeList.accept(new ModifierVisitor<>() {
                @Override
                public Visitable visit(ClassOrInterfaceDeclaration n, Object arg) {
                    if (n.getConstructors().isEmpty())
                        newlyInsertedConstructors.add(n.addConstructor(Modifier.Keyword.PUBLIC));
                    return super.visit(n, arg);
                }
            }, null);
        }

        @Override
        protected CFG createCFG() {
            return new JSysCFG(classGraph);
            return new JSysCFG(classGraph, newlyInsertedConstructors);
        }

        @Override
+5 −2
Original line number Diff line number Diff line
package es.upv.mist.slicing.graphs.jsysdg;

import com.github.javaparser.ast.body.ConstructorDeclaration;
import es.upv.mist.slicing.graphs.ClassGraph;
import es.upv.mist.slicing.graphs.exceptionsensitive.ESPDG;

import java.util.Set;

public class JSysPDG extends ESPDG {
    public JSysPDG(ClassGraph clg) {
        this(new JSysCFG(clg));
    public JSysPDG(ClassGraph classGraph, Set<ConstructorDeclaration> implicitConstructors) {
        this(new JSysCFG(classGraph, implicitConstructors));
    }

    public JSysPDG(JSysCFG cfg) {
+2 −0
Original line number Diff line number Diff line
@@ -122,6 +122,8 @@ public class PDG extends GraphWithRootNode<CallableDeclaration<?>> {
                            callNodeStack.pop();
                        } else {
                            CallNode callNode = CallNode.create(((VariableAction.CallMarker) action).getCall());
                            if (graphNode.isImplicitInstruction())
                                callNode.markAsImplicit();
                            addVertex(callNode);
                            addControlDependencyArc(graphNode, callNode);
                            callNodeStack.push(callNode);
Loading