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

fix! JSysCFGBuilder now extends ESCFG.Builder

parent d1ccdf38
Loading
Loading
Loading
Loading
+7 −6
Original line number Diff line number Diff line
@@ -34,7 +34,7 @@ public class ESCFG extends ACFG {

    @Override
    protected CFGBuilder newCFGBuilder() {
        return new Builder();
        return new Builder(this);
    }

    protected ExceptionExitNode addExceptionExitNode(CallableDeclaration<?> method, ResolvedType type) {
@@ -103,8 +103,9 @@ public class ESCFG extends ACFG {
        /** Map of return nodes from each method call, mapped by the normal return node of said call. */
        protected Map<NormalReturnNode, Set<ReturnNode>> pendingNormalReturnNodes = new HashMap<>();

        protected Builder() {
        protected Builder(ESCFG escfg) {
            super(ESCFG.this);
            assert escfg == ESCFG.this;
        }

        @Override
@@ -248,23 +249,23 @@ public class ESCFG extends ACFG {

        @Override
        public void visit(MethodCallExpr n, Void arg) {
            visitCall(n);
            visitCallForExceptions(n);
        }

        @Override
        public void visit(ObjectCreationExpr n, Void arg) {
            visitCall(n);
            visitCallForExceptions(n);
        }

        @Override
        public void visit(ExplicitConstructorInvocationStmt n, Void arg) {
            connectTo(n);
            visitCall(n);
            visitCallForExceptions(n);
        }

        /** Process a call that may throw exceptions. Generates normal and return nodes, and
         * registers the appropriate exception source. */
        protected void visitCall(Resolvable<? extends ResolvedMethodLikeDeclaration> call) {
        protected void visitCallForExceptions(Resolvable<? extends ResolvedMethodLikeDeclaration> call) {
            ResolvedMethodLikeDeclaration resolved = call.resolve();
            if (resolved.getNumberOfSpecifiedExceptions() == 0)
                return;
+62 −2
Original line number Diff line number Diff line
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.BodyDeclaration;
import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
import com.github.javaparser.ast.body.ConstructorDeclaration;
import com.github.javaparser.ast.body.FieldDeclaration;
import com.github.javaparser.ast.stmt.ExplicitConstructorInvocationStmt;
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.utils.ASTUtils;

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

public class JSysCFG extends ESCFG {

@@ -20,10 +30,9 @@ public class JSysCFG extends ESCFG {
    }

    protected CFGBuilder newCFGBuilder() {
        return new JSysCFGBuilder(this);
        return new Builder(this);
    }


    /** Obtains the Javaparser Node corresponding to the class where the CFG is contained */
    public ClassOrInterfaceDeclaration getDeclarationClass() {
        assert rootNode != null;
@@ -31,4 +40,55 @@ public class JSysCFG extends ESCFG {
            throw new IllegalStateException("The Method declaration is not directly inside a Class Declaration");
        return (ClassOrInterfaceDeclaration) rootNode.getAstNode().getParentNode().get();
    }

    public class Builder extends ESCFG.Builder {

        /** List of inserted super calls in Javaparser AST to process them as Implicit Nodes (@ImplicitNode)*/
        protected List<Node> methodInsertedInstructions = new LinkedList<>();

        protected Builder(JSysCFG jSysCFG) {
            super(JSysCFG.this);
            assert jSysCFG == JSysCFG.this;
        }

        /** Esto se llama porque lo hemos insertado fantasma o porque existe. A continuacion se inserta el codigo dynInit */
        @Override
        public void visit(ExplicitConstructorInvocationStmt n, Void arg) {

            // 1. Create new super call if not present
            if (methodInsertedInstructions.contains(n)){
                ImplicitNode node = new ImplicitNode(n.toString(), n);
                graph.addVertex(node);
                connectTo(node);
            }
            else {
                connectTo(n);
            }
            // 2. Insert dynamic class code
            ClassOrInterfaceDeclaration containerClass = ((JSysCFG) graph).getDeclarationClass();
            List<BodyDeclaration<?>> dynInitList = ((JSysCFG) graph).getClassGraph().getDynInit(containerClass.getNameAsString());
            dynInitList.forEach(node -> node.accept(this, arg));

            // 3. Handle exceptions
            super.visitCallForExceptions(n);
        }

        @Override
        public void visit(FieldDeclaration n, Void arg){
            connectTo(n);
            super.visit(n,arg);
        }

        @Override
        public void visit(ConstructorDeclaration n, Void arg) {
            // Insert call to super() if it is implicit.
            if (!ASTUtils.constructorHasExplicitConstructorInvocation(n)){
                var superCall = new ExplicitConstructorInvocationStmt(null, null, false, null, new NodeList<>());
                methodInsertedInstructions.add(superCall);
                n.getBody().addStatement(0, superCall);
            }
            // Perform the same task as previous graphs.
            super.visit(n, arg);
        }
    }
}
+0 −73
Original line number Diff line number Diff line
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.*;
import com.github.javaparser.ast.stmt.ExplicitConstructorInvocationStmt;
import es.upv.mist.slicing.graphs.augmented.ACFGBuilder;
import es.upv.mist.slicing.nodes.io.MethodExitNode;
import es.upv.mist.slicing.utils.ASTUtils;

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

public class JSysCFGBuilder extends ACFGBuilder {

    /** List of inserted super calls in Javaparser AST to process them as Implicit Nodes (@ImplicitNode)*/
    protected List<Node> methodInsertedInstructions = new LinkedList<>();

    protected JSysCFGBuilder(JSysCFG graph) {
        super(graph);
    }

    /** Esto se llama porque lo hemos insertado fantasma o porque existe. A continuacion se inserta el codigo dynInit */
    @Override
    public void visit(ExplicitConstructorInvocationStmt n, Void arg) {

        // 1. Create new super call if not present
        if (methodInsertedInstructions.contains(n)){
            ImplicitNode node = new ImplicitNode(n.toString(), n);
            graph.addVertex(node);
            connectTo(node);
        }
        else {
            connectTo(n);
        }
        // 2. Insert dynamic class code
        ClassOrInterfaceDeclaration containerClass = ((JSysCFG) graph).getDeclarationClass();
        List<BodyDeclaration<?>> dynInitList = ((JSysCFG) graph).getClassGraph().getDynInit(containerClass.getNameAsString());
        dynInitList.forEach(node -> node.accept(this, arg));
    }

    @Override
    public void visit(FieldDeclaration n, Void arg){
        connectTo(n);
        super.visit(n,arg);
    }

    @Override
    protected void visitCallableDeclaration(CallableDeclaration<?> callableDeclaration, Void arg) {
        graph.buildRootNode(callableDeclaration);
        hangingNodes.add(graph.getRootNode());

        // 1. Check if first is super (only if constructor)
        //      then, create and build super()
        if (callableDeclaration instanceof ConstructorDeclaration){
            ConstructorDeclaration declaration = (ConstructorDeclaration) callableDeclaration;
            if (!ASTUtils.constructorHasExplicitConstructorInvocation(declaration)){
                ExplicitConstructorInvocationStmt superCall =
                        new ExplicitConstructorInvocationStmt(null, null, false, null, new NodeList<>());
                methodInsertedInstructions.add(superCall);
                declaration.getBody().addStatement(0, superCall);
            }
        }

        ASTUtils.getCallableBody(callableDeclaration).accept(this, arg);
        returnList.stream().filter(node -> !hangingNodes.contains(node)).forEach(hangingNodes::add);

        MethodExitNode exit = new MethodExitNode(callableDeclaration);
        graph.addVertex(exit);
        addMethodOutput(callableDeclaration, exit);
        connectTo(exit);
    }
}