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

Merge branch 'dynamic-type-search' into 'develop'

Add DynamicTypeResolver to solve dynamic types intraprocedurally

See merge request !48
parents 324cb72a 128a2ef1
Loading
Loading
Loading
Loading
Loading
+2 −6
Original line number Diff line number Diff line
@@ -4,9 +4,6 @@ import com.github.javaparser.StaticJavaParser;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.NodeList;
import com.github.javaparser.ast.comments.BlockComment;
import com.github.javaparser.symbolsolver.JavaSymbolSolver;
import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
import es.upv.mist.slicing.graphs.augmented.ASDG;
import es.upv.mist.slicing.graphs.augmented.PSDG;
import es.upv.mist.slicing.graphs.cfg.CFG;
@@ -16,6 +13,7 @@ import es.upv.mist.slicing.slicing.FileLineSlicingCriterion;
import es.upv.mist.slicing.slicing.NodeIdSlicingCriterion;
import es.upv.mist.slicing.slicing.Slice;
import es.upv.mist.slicing.slicing.SlicingCriterion;
import es.upv.mist.slicing.utils.StaticTypeSolver;
import org.apache.commons.cli.*;

import java.io.File;
@@ -88,9 +86,7 @@ public class PHPSlice {

    public void slice() throws ParseException, IOException {
        // Configure JavaParser
        CombinedTypeSolver combinedTypeSolver = new CombinedTypeSolver();
        combinedTypeSolver.add(new ReflectionTypeSolver(true));
        StaticJavaParser.getConfiguration().setSymbolResolver(new JavaSymbolSolver(combinedTypeSolver));
        StaticTypeSolver.addTypeSolverJRE();
        StaticJavaParser.getConfiguration().setAttributeComments(false);

        // Build the SDG
+3 −7
Original line number Diff line number Diff line
@@ -5,10 +5,7 @@ import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.NodeList;
import com.github.javaparser.ast.comments.BlockComment;
import com.github.javaparser.ast.nodeTypes.NodeWithName;
import com.github.javaparser.symbolsolver.JavaSymbolSolver;
import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver;
import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
import es.upv.mist.slicing.graphs.augmented.ASDG;
import es.upv.mist.slicing.graphs.augmented.PSDG;
import es.upv.mist.slicing.graphs.exceptionsensitive.ESSDG;
@@ -16,6 +13,7 @@ import es.upv.mist.slicing.graphs.sdg.SDG;
import es.upv.mist.slicing.slicing.FileLineSlicingCriterion;
import es.upv.mist.slicing.slicing.Slice;
import es.upv.mist.slicing.slicing.SlicingCriterion;
import es.upv.mist.slicing.utils.StaticTypeSolver;
import org.apache.commons.cli.*;

import java.io.File;
@@ -211,11 +209,9 @@ public class Slicer {

    public void slice() throws ParseException {
        // Configure JavaParser
        CombinedTypeSolver combinedTypeSolver = new CombinedTypeSolver();
        combinedTypeSolver.add(new ReflectionTypeSolver(true));
        StaticTypeSolver.addTypeSolverJRE();
        for (File directory : dirIncludeSet)
            combinedTypeSolver.add(new JavaParserTypeSolver(directory));
        StaticJavaParser.getConfiguration().setSymbolResolver(new JavaSymbolSolver(combinedTypeSolver));
            StaticTypeSolver.addTypeSolver(new JavaParserTypeSolver(directory));
        StaticJavaParser.getConfiguration().setAttributeComments(false);

        // Build the SDG
+40 −44
Original line number Diff line number Diff line
@@ -4,18 +4,18 @@ import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.NodeList;
import com.github.javaparser.ast.body.*;
import com.github.javaparser.ast.visitor.VoidVisitorAdapter;
import com.github.javaparser.resolution.declarations.ResolvedClassDeclaration;
import es.upv.mist.slicing.arcs.Arc;
import es.upv.mist.slicing.utils.ASTUtils;
import es.upv.mist.slicing.utils.Utils;
import org.jgrapht.graph.DefaultEdge;
import org.jgrapht.graph.DirectedPseudograph;
import org.jgrapht.nio.Attribute;
import org.jgrapht.nio.DefaultAttribute;
import org.jgrapht.nio.dot.DOTExporter;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class ClassGraph extends DirectedPseudograph<ClassGraph.Vertex, DefaultEdge> implements Buildable<NodeList<CompilationUnit>> {
public class ClassGraph extends DirectedPseudograph<ClassGraph.Vertex, ClassGraph.ClassArc> implements Buildable<NodeList<CompilationUnit>> {

    /** The key of the vertex map needs to be a String because extendedTypes represent extended classes
     * as ClassOrInterfaceType objects while class declarations define classes as ClassOrInterfaceDeclaration
@@ -28,6 +28,29 @@ public class ClassGraph extends DirectedPseudograph<ClassGraph.Vertex, DefaultEd
        super(null, null, false);
    }

    /** Locates the vertex that represents a given class or interface declaration.
     *  The vertex must exist, or an exception will be thrown. */
    protected Vertex findVertex(ResolvedClassDeclaration declaration) {
        Optional<Vertex> vertex = vertexSet().stream()
                .filter(v -> v.declaration instanceof ClassOrInterfaceDeclaration)
                .filter(v -> v.declaration.asClassOrInterfaceDeclaration().resolve().asClass().equals(declaration))
                .findFirst();
        return vertex.orElseThrow();
    }

    public Set<ClassOrInterfaceDeclaration> subclassesOf(ResolvedClassDeclaration clazz) {
        return subclassesStreamOf(findVertex(clazz))
                .map(ClassOrInterfaceDeclaration.class::cast)
                .collect(Collectors.toSet());
    }

    protected Stream<Vertex> subclassesStreamOf(Vertex classVertex) {
        return Stream.concat(Stream.of(classVertex), outgoingEdgesOf(classVertex).stream()
                .filter(ClassArc.Extends.class::isInstance)
                .map(this::getEdgeTarget)
                .flatMap(this::subclassesStreamOf));
    }

    @Override
    public void build(NodeList<CompilationUnit> arg) {
        if (isBuilt())
@@ -121,7 +144,7 @@ public class ClassGraph extends DirectedPseudograph<ClassGraph.Vertex, DefaultEd
                ClassOrInterfaceDeclaration clazz = classStack.peek();
                Vertex c = vertexDeclarationMap.get(clazz.getNameAsString());
                Vertex v = vertexDeclarationMap.get(clazz.getFullyQualifiedName().get()+ "." + n.toString());
                addEdge(c, v, new MemberArc());
                addEdge(c, v, new ClassArc.Member());
            }

            @Override
@@ -129,7 +152,7 @@ public class ClassGraph extends DirectedPseudograph<ClassGraph.Vertex, DefaultEd
                ClassOrInterfaceDeclaration clazz = classStack.peek();
                Vertex c = vertexDeclarationMap.get(clazz.getNameAsString());
                Vertex v = vertexDeclarationMap.get(clazz.getFullyQualifiedName().get()+ "." + n.getSignature().toString());
                addEdge(c, v, new MemberArc());
                addEdge(c, v, new ClassArc.Member());
            }

            @Override
@@ -137,7 +160,7 @@ public class ClassGraph extends DirectedPseudograph<ClassGraph.Vertex, DefaultEd
                ClassOrInterfaceDeclaration clazz = classStack.peek();
                Vertex c = vertexDeclarationMap.get(clazz.getNameAsString());
                Vertex v = vertexDeclarationMap.get(clazz.getFullyQualifiedName().get()+ "." + n.getSignature().toString());
                addEdge(c, v, new MemberArc());
                addEdge(c, v, new ClassArc.Member());
            }
        }, null);
    }
@@ -148,12 +171,12 @@ public class ClassGraph extends DirectedPseudograph<ClassGraph.Vertex, DefaultEd
        dv.getExtendedTypes().forEach(p -> {
            Vertex source = vertexDeclarationMap.get(p.getNameAsString());
            if (source != null && containsVertex(v))
                addEdge(source, v, new ExtendsArc());
                addEdge(source, v, new ClassArc.Extends());
        });
        dv.getImplementedTypes().forEach(p -> {
            Vertex source = vertexDeclarationMap.get(p.getNameAsString());
            if (source != null && containsVertex(v))
                addEdge(source, v, new ImplementsArc());
                addEdge(source, v, new ClassArc.Implements());
        });
    }

@@ -167,7 +190,7 @@ public class ClassGraph extends DirectedPseudograph<ClassGraph.Vertex, DefaultEd

    /** A vertex containing the declaration it represents. It only exists because
     *  JGraphT relies heavily on equals comparison, which may not be correct in declarations. */
    public static class Vertex {
    protected static class Vertex {
        // First ancestor common class in the JavaParser hierarchy for
        // ClassOrInterfaceDeclaration, FieldDeclaration and CallableDeclaration
        protected final BodyDeclaration<?> declaration;
@@ -197,40 +220,13 @@ public class ClassGraph extends DirectedPseudograph<ClassGraph.Vertex, DefaultEd
        }
    }

    /**
     * An edge of the {@link ClassGraph}. Represents the inheritance relationship in Java.
     * It goes from the base class to the derived class
     */
    public static class ExtendsArc extends Arc {
        public Map<String, Attribute> getDotAttributes() {
            Map<String, Attribute> map = super.getDotAttributes();
            map.put("style", DefaultAttribute.createAttribute("dashed"));
            return map;
        }
    }

    /**
     * An edge of the {@link ClassGraph}. Represents the implements relationship in Java.
     * It goes from the interface to the class that implements it.
     */
    public static class ImplementsArc extends Arc {
        public Map<String, Attribute> getDotAttributes() {
            Map<String, Attribute> map = super.getDotAttributes();
            map.put("style", DefaultAttribute.createAttribute("dashed"));
            return map;
        }
    }

    /**
     * An edge of the {@link ClassGraph}. It represents the membership of a class node.
     * It links the class node and its inner data members/function definitions.
     */
    public static class MemberArc extends Arc {
        public Map<String, Attribute> getDotAttributes() {
            Map<String, Attribute> map = super.getDotAttributes();
            map.put("style", DefaultAttribute.createAttribute("dashed"));
            return map;
        }
    protected static class ClassArc extends Arc {
        /** An arc that connects a class with another one that inherits from it. */
        protected static class Extends extends ClassArc {}
        /** An arc that connects an interface to a class that implements it. */
        protected static class Implements extends ClassArc {}
        /** An arc that connects a class with a field or method contained in it. */
        protected static class Member extends ClassArc {}
    }
}

+4 −2
Original line number Diff line number Diff line
@@ -132,8 +132,10 @@ public class ACFGBuilder extends CFGBuilder {
    @Override
    public void visit(ReturnStmt returnStmt, Void arg) {
        GraphNode<ReturnStmt> node = connectTo(returnStmt);
        node.addDefinedVariable(new NameExpr(VARIABLE_NAME_OUTPUT));
        returnStmt.getExpression().ifPresent(n -> n.accept(this, arg));
        returnStmt.getExpression().ifPresent(n -> {
            n.accept(this, arg);
            node.addDefinedVariable(new NameExpr(VARIABLE_NAME_OUTPUT), n);
        });
        returnList.add(node);
        clearHanging();
        nonExecHangingNodes.add(node); // NEW vs CFG
+1 −1
Original line number Diff line number Diff line
@@ -331,7 +331,7 @@ public class CFGBuilder extends VoidVisitorAdapter<Void> {
        GraphNode<ReturnStmt> node = connectTo(returnStmt);
        returnStmt.getExpression().ifPresent(n -> {
            n.accept(this, arg);
            node.addDefinedVariable(new NameExpr(VARIABLE_NAME_OUTPUT));
            node.addDefinedVariable(new NameExpr(VARIABLE_NAME_OUTPUT), n);
        });
        returnList.add(node);
        clearHanging();
Loading