Commit 30e4766a authored by Carlos Galindo's avatar Carlos Galindo
Browse files

Merge branch 'fix-bad-smells' into 'develop'

Fix bad smells

Closes #53, #52, and #54

See merge request !57
parents 47cc94ec 5f2ef1f1
Loading
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -217,7 +217,7 @@ public class CallGraph extends DirectedPseudograph<CallGraph.Vertex, CallGraph.E
                // Connect to each declaration
                AtomicInteger edgesCreated = new AtomicInteger();
                dynamicTypes.stream()
                        .map(t -> classGraph.findMethodByTypeAndSignature(t, decl.getSignature()))
                        .map(t -> classGraph.findMethodByTypeAndSignature(t, decl))
                        .collect(Collectors.toCollection(NodeHashSet::new))
                        .forEach(methodDecl -> {
                            edgesCreated.getAndIncrement();
+54 −89
Original line number Diff line number Diff line
package es.upv.mist.slicing.graphs;

import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.Modifier;
import com.github.javaparser.ast.NodeList;
import com.github.javaparser.ast.body.*;
import com.github.javaparser.ast.visitor.VoidVisitorAdapter;
@@ -33,33 +32,11 @@ public class ClassGraph extends DirectedPseudograph<ClassGraph.Vertex, ClassGrap
    /** Locates the vertex that represents a given class or interface declaration.
     *  The vertex must exist, or an exception will be thrown. */
    protected Vertex findClassVertex(ClassOrInterfaceDeclaration declaration) {
        return vertexSet().stream()
                .filter(v -> v.declaration.isClassOrInterfaceDeclaration())
                .filter(v -> ASTUtils.equalsWithRangeInCU(v.declaration, declaration))
                .findFirst().orElseThrow();
    }

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

    protected Vertex findClassVertex(ResolvedReferenceType type) {
        return vertexSet().stream()
                .filter(v -> v.declaration.isClassOrInterfaceDeclaration())
                .filter(v -> ASTUtils.resolvedTypeDeclarationToResolvedType(v.declaration.asClassOrInterfaceDeclaration().resolve()).equals(type))
                .findFirst().orElseThrow();
        return vertexDeclarationMap.get(mapKey(declaration));
    }

    protected Vertex findMethodVertex(CallableDeclaration<?> declaration) {
        return vertexSet().stream()
                .filter(v -> v.declaration.isCallableDeclaration())
                .filter(v -> ASTUtils.equalsWithRangeInCU(v.declaration, declaration))
                .findFirst().orElseThrow();
        return vertexDeclarationMap.get(mapKey(declaration, ASTUtils.getClassNode(declaration)));
    }

    public Set<MethodDeclaration> overriddenSetOf(MethodDeclaration method) {
@@ -90,11 +67,11 @@ public class ClassGraph extends DirectedPseudograph<ClassGraph.Vertex, ClassGrap

    /** Returns all child classes of the given class, including itself. */
    public Set<ClassOrInterfaceDeclaration> subclassesOf(ResolvedClassDeclaration clazz) {
        return subclassesOf(findClassVertex(clazz));
        return subclassesOf(vertexDeclarationMap.get(mapKey(clazz)));
    }

    public Set<ClassOrInterfaceDeclaration> subclassesOf(ResolvedReferenceType type) {
        return subclassesOf(findClassVertex(type));
        return subclassesOf(vertexDeclarationMap.get(mapKey(type)));
    }

    /** @see #subclassesOf(ClassOrInterfaceDeclaration) */
@@ -115,21 +92,14 @@ public class ClassGraph extends DirectedPseudograph<ClassGraph.Vertex, ClassGrap
    // TODO: this method ignores default method implementations in interfaces, as can be overridden.
    /** Looks up a method in the graph, going up the class inheritance tree to locate a
     *  matching method. If no match can be found, throws an {@link IllegalArgumentException}. */
    public MethodDeclaration findMethodByTypeAndSignature(ClassOrInterfaceDeclaration type, CallableDeclaration.Signature signature) {
        Optional<MethodDeclaration> result = outgoingEdgesOf(findClassVertex(type)).stream()
                .filter(ClassArc.Member.class::isInstance)
                .map(this::getEdgeTarget)
                .map(Vertex::getDeclaration)
                .filter(BodyDeclaration::isMethodDeclaration)
                .map(BodyDeclaration::asMethodDeclaration)
                .filter(decl -> signature.equals(decl.getSignature()))
                .findFirst();
        if (result.isPresent())
            return result.get();
    public MethodDeclaration findMethodByTypeAndSignature(ClassOrInterfaceDeclaration type, CallableDeclaration<?> declaration) {
        Vertex v = vertexDeclarationMap.get(mapKey(declaration, type));
        if (v != null && v.declaration.isMethodDeclaration())
            return v.declaration.asMethodDeclaration();
        Optional<ClassOrInterfaceDeclaration> parentType = parentOf(type);
        if (parentType.isEmpty())
            throw new IllegalArgumentException("Cannot find the given signature: " + signature);
        return findMethodByTypeAndSignature(parentType.get(), signature);
            throw new IllegalArgumentException("Cannot find the given declaration: " + declaration);
        return findMethodByTypeAndSignature(parentType.get(), declaration);
    }

    /** Find the parent class or interface of a given class. */
@@ -157,6 +127,26 @@ public class ClassGraph extends DirectedPseudograph<ClassGraph.Vertex, ClassGrap
        return built;
    }

    protected String mapKey(ClassOrInterfaceDeclaration n) {
        return n.getFullyQualifiedName().orElseThrow();
    }

    protected String mapKey(ResolvedClassDeclaration n) {
        return n.getQualifiedName();
    }

    protected String mapKey(ResolvedReferenceType n) {
        return n.getQualifiedName();
    }

    protected String mapKey(CallableDeclaration<?> declaration, ClassOrInterfaceDeclaration clazz) {
        return clazz.getFullyQualifiedName().orElseThrow() + "." + declaration.getSignature();
    }

    protected String mapKey(FieldDeclaration declaration, ClassOrInterfaceDeclaration clazz) {
        return clazz.getFullyQualifiedName().orElseThrow() + "." + declaration;
    }

    /** Find the class declarations, the field declaration, and method and constructor declarations (vertices)
     * in the given list of compilation units. */
    protected void buildVertices(NodeList<CompilationUnit> arg) {
@@ -177,16 +167,19 @@ public class ClassGraph extends DirectedPseudograph<ClassGraph.Vertex, ClassGrap

            @Override
            public void visit(FieldDeclaration n, Void arg) {
                assert classStack.peek() != null;
                addFieldDeclaration(n, classStack.peek());
            }

            @Override
            public void visit(MethodDeclaration n, Void arg) {
                assert classStack.peek() != null;
                addCallableDeclaration(n, classStack.peek());
            }

            @Override
            public void visit(ConstructorDeclaration n, Void arg) {
                assert classStack.peek() != null;
                addCallableDeclaration(n, classStack.peek());
            }
        }, null);
@@ -196,14 +189,14 @@ public class ClassGraph extends DirectedPseudograph<ClassGraph.Vertex, ClassGrap
    protected void addClassDeclaration(ClassOrInterfaceDeclaration n) {
        ClassGraph.Vertex v = new ClassGraph.Vertex(n);
        // Required string to match ClassOrInterfaceType and ClassOrInterfaceDeclaration. QualifiedName Not Valid
        vertexDeclarationMap.put(n.getNameAsString(), v);
        vertexDeclarationMap.put(mapKey(n), v);
        addVertex(v);
    }

    /** Add a field declaration vertex to the class graph */
    protected void addFieldDeclaration(FieldDeclaration n, ClassOrInterfaceDeclaration c){
        ClassGraph.Vertex v = new ClassGraph.Vertex(n);
        vertexDeclarationMap.put(c.getFullyQualifiedName().get()+ "." + n.toString(), v);
        vertexDeclarationMap.put(mapKey(n, c), v);
        addVertex(v);
    }

@@ -211,7 +204,7 @@ public class ClassGraph extends DirectedPseudograph<ClassGraph.Vertex, ClassGrap
    protected void addCallableDeclaration(CallableDeclaration<?> n, ClassOrInterfaceDeclaration c){
        assert n instanceof ConstructorDeclaration || n instanceof MethodDeclaration;
        ClassGraph.Vertex v = new ClassGraph.Vertex(n);
        vertexDeclarationMap.put(c.getFullyQualifiedName().get()+ "." + n.getSignature().toString(), v);
        vertexDeclarationMap.put(mapKey(n, c), v);
        addVertex(v);
    }

@@ -224,7 +217,7 @@ public class ClassGraph extends DirectedPseudograph<ClassGraph.Vertex, ClassGrap
            @Override
            public void visit(ClassOrInterfaceDeclaration n, Void arg) {
                classStack.push(n);
                Vertex v = vertexDeclarationMap.get(n.getNameAsString());
                Vertex v = vertexDeclarationMap.get(mapKey(n));
                addClassEdges(v);
                super.visit(n, arg);
                classStack.pop();
@@ -233,24 +226,27 @@ public class ClassGraph extends DirectedPseudograph<ClassGraph.Vertex, ClassGrap
            @Override
            public void visit(FieldDeclaration n, Void arg) {
                ClassOrInterfaceDeclaration clazz = classStack.peek();
                Vertex c = vertexDeclarationMap.get(clazz.getNameAsString());
                Vertex v = vertexDeclarationMap.get(clazz.getFullyQualifiedName().get()+ "." + n.toString());
                assert clazz != null;
                Vertex c = vertexDeclarationMap.get(mapKey(clazz));
                Vertex v = vertexDeclarationMap.get(mapKey(n, clazz));
                addEdge(c, v, new ClassArc.Member());
            }

            @Override
            public void visit(MethodDeclaration n, Void arg) {
                ClassOrInterfaceDeclaration clazz = classStack.peek();
                Vertex c = vertexDeclarationMap.get(clazz.getNameAsString());
                Vertex v = vertexDeclarationMap.get(clazz.getFullyQualifiedName().get()+ "." + n.getSignature().toString());
                assert clazz != null;
                Vertex c = vertexDeclarationMap.get(mapKey(clazz));
                Vertex v = vertexDeclarationMap.get(mapKey(n, clazz));
                addEdge(c, v, new ClassArc.Member());
            }

            @Override
            public void visit(ConstructorDeclaration n, Void arg) {
                ClassOrInterfaceDeclaration clazz = classStack.peek();
                Vertex c = vertexDeclarationMap.get(clazz.getNameAsString());
                Vertex v = vertexDeclarationMap.get(clazz.getFullyQualifiedName().get()+ "." + n.getSignature().toString());
                assert clazz != null;
                Vertex c = vertexDeclarationMap.get(mapKey(clazz));
                Vertex v = vertexDeclarationMap.get(mapKey(n, clazz));
                addEdge(c, v, new ClassArc.Member());
            }
        }, null);
@@ -260,21 +256,22 @@ public class ClassGraph extends DirectedPseudograph<ClassGraph.Vertex, ClassGrap
        assert v.declaration instanceof ClassOrInterfaceDeclaration;
        ClassOrInterfaceDeclaration dv = (ClassOrInterfaceDeclaration) v.declaration;
        dv.getExtendedTypes().forEach(p -> {
            Vertex source = vertexDeclarationMap.get(p.getNameAsString());
            Vertex source = vertexDeclarationMap.get(mapKey(p.resolve()));
            if (source != null && containsVertex(v))
                addEdge(source, v, new ClassArc.Extends());
        });
        dv.getImplementedTypes().forEach(p -> {
            Vertex source = vertexDeclarationMap.get(p.getNameAsString());
            Vertex source = vertexDeclarationMap.get(mapKey(p.resolve()));
            if (source != null && containsVertex(v))
                addEdge(source, v, new ClassArc.Implements());
        });
    }

    /** Creates a graph-appropriate DOT exporter. */
    public DOTExporter<CallableDeclaration<?>, CallGraph.Edge<?>> getDOTExporter() {
        DOTExporter<CallableDeclaration<?>, CallGraph.Edge<?>> dot = new DOTExporter<>();
        dot.setVertexAttributeProvider(decl -> Utils.dotLabel(decl.getDeclarationAsString(false, false, false)));
        dot.setEdgeAttributeProvider(edge -> Utils.dotLabel(edge.getCall().toString()));
    public DOTExporter<ClassGraph.Vertex, ClassGraph.ClassArc> getDOTExporter() {
        DOTExporter<ClassGraph.Vertex, ClassGraph.ClassArc> dot = new DOTExporter<>();
        dot.setVertexAttributeProvider(vertex -> Utils.dotLabel(vertex.declaration.toString().replaceAll("\\{.*}", "")));
        dot.setEdgeAttributeProvider(edge -> Utils.dotLabel(edge.getClass().getSimpleName()));
        return dot;
    }

@@ -306,40 +303,8 @@ public class ClassGraph extends DirectedPseudograph<ClassGraph.Vertex, ClassGrap

        @Override
        public String toString() {
            return super.toString();
        }
    }

    /** Returns a List with the static FieldDeclarations and InitializerDeclarations of the given class */
    public List<BodyDeclaration<?>> getStaticInit(String className){
        return getClassInit(className,true);
    }

    /** Returns a List with the dynamic FieldDeclarations and InitializerDeclarations of the given class */
    public List<BodyDeclaration<?>> getDynInit(String className){
        return getClassInit(className,false);
    }

    /** Returns a List with FieldDeclarations and InitializerDeclarations static/dynamic items of the given class */
    private List<BodyDeclaration<?>> getClassInit(String className, Boolean isStatic){
        Vertex classNode = vertexDeclarationMap.get(className);
        List<BodyDeclaration<?>> members = classNode.declaration.asClassOrInterfaceDeclaration().getMembers();
        List<BodyDeclaration<?>> classInit = new LinkedList<>();
        for (BodyDeclaration<?> member : members) {
            if (member instanceof CallableDeclaration<?>)
                continue;

            if (member.isFieldDeclaration()) {
                if (isStatic == member.asFieldDeclaration().hasModifier(Modifier.Keyword.STATIC))
                    classInit.add(member);
                continue;
            }

            if (member.isInitializerDeclaration())
                if (isStatic == member.asInitializerDeclaration().isStatic())
                    classInit.add(member);
            return declaration.toString();
        }
        return classInit;
    }

    protected static class ClassArc extends Arc {
+18 −24
Original line number Diff line number Diff line
@@ -3,13 +3,11 @@ 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;
import com.github.javaparser.ast.expr.ThisExpr;
import com.github.javaparser.ast.stmt.ExplicitConstructorInvocationStmt;
import com.github.javaparser.ast.stmt.ReturnStmt;
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;
@@ -25,22 +23,19 @@ import java.util.Set;
 * polymorphism and other features.
 */
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, Set<ConstructorDeclaration> implicitConstructors) {
        super();
        this.classGraph = classGraph;
        this.implicitConstructors = implicitConstructors;
    @Override
    public void build(CallableDeclaration<?> declaration) {
        throw new UnsupportedOperationException("Use build(CallableDeclaration, ClassGraph, Set<ConstructorDeclaration>)");
    }

    @Override
    public void buildRootNode(CallableDeclaration<?> rootNodeAst) {
        super.buildRootNode(rootNodeAst);
        if (implicitConstructors.contains(rootNodeAst))
            rootNode.markAsImplicit();
    public void build(CallableDeclaration<?> declaration, Set<ConstructorDeclaration> implicitConstructors) {
        Builder builder = (Builder) newCFGBuilder();
        builder.implicitDeclaration = implicitConstructors.contains(declaration);
        declaration.accept(builder, null);
        // Verify that it has been built
        exitNode = vertexSet().stream().filter(MethodExitNode.class::isInstance).findFirst()
                .orElseThrow(() -> new IllegalStateException("Built graph has no exit node!"));
        built = true;
    }

    @Override
@@ -77,10 +72,9 @@ public class JSysCFG extends ESCFG {
            // 1. Connect to the following statements
            connectTo(n);
            // 2. Insert dynamic class code (only for super())
            if (!n.isThis()) {
                ClassOrInterfaceDeclaration containerClass = ASTUtils.getClassNode(rootNode.getAstNode());
                classGraph.getDynInit(containerClass.getNameAsString()).forEach(node -> node.accept(this, arg));
            }
            if (!n.isThis())
                ASTUtils.getClassInit(ASTUtils.getClassNode(rootNode.getAstNode()), false)
                        .forEach(node -> node.accept(this, arg));
            // 3. Handle exceptions
            super.visitCallForExceptions(n);
        }
@@ -93,8 +87,6 @@ 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<>());
@@ -106,11 +98,13 @@ 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)
            // Convert enter/exit nodes to implicit if appropriate
            if (implicitDeclaration) {
                getRootNode().markAsImplicit();
                vertexSet().stream()
                        .filter(MethodExitNode.class::isInstance)
                        .forEach(GraphNode::markAsImplicit);
            }
        }
    }
}
+7 −1
Original line number Diff line number Diff line
@@ -3,6 +3,7 @@ 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.CallableDeclaration;
import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
import com.github.javaparser.ast.body.ConstructorDeclaration;
import com.github.javaparser.ast.visitor.ModifierVisitor;
@@ -45,9 +46,14 @@ public class JSysDG extends ESSDG {
            }, null);
        }

        @Override
        protected void buildCFG(CallableDeclaration<?> declaration, CFG cfg) {
            ((JSysCFG) cfg).build(declaration, newlyInsertedConstructors);
        }

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

        @Override
+2 −6
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 classGraph, Set<ConstructorDeclaration> implicitConstructors) {
        this(new JSysCFG(classGraph, implicitConstructors));
    public JSysPDG() {
        this(new JSysCFG());
    }

    public JSysPDG(JSysCFG cfg) {
Loading