Loading sdg-core/src/main/java/es/upv/mist/slicing/graphs/CallGraph.java +1 −1 Original line number Diff line number Diff line Loading @@ -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(); Loading sdg-core/src/main/java/es/upv/mist/slicing/graphs/ClassGraph.java +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; Loading Loading @@ -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) { Loading Loading @@ -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) */ Loading @@ -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. */ Loading Loading @@ -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) { Loading @@ -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); Loading @@ -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); } Loading @@ -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); } Loading @@ -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(); Loading @@ -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); Loading @@ -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; } Loading Loading @@ -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 { Loading sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/JSysCFG.java +18 −24 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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 Loading Loading @@ -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); } Loading @@ -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<>()); Loading @@ -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); } } } } sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/JSysDG.java +7 −1 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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 Loading sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/JSysPDG.java +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 Loading
sdg-core/src/main/java/es/upv/mist/slicing/graphs/CallGraph.java +1 −1 Original line number Diff line number Diff line Loading @@ -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(); Loading
sdg-core/src/main/java/es/upv/mist/slicing/graphs/ClassGraph.java +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; Loading Loading @@ -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) { Loading Loading @@ -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) */ Loading @@ -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. */ Loading Loading @@ -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) { Loading @@ -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); Loading @@ -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); } Loading @@ -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); } Loading @@ -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(); Loading @@ -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); Loading @@ -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; } Loading Loading @@ -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 { Loading
sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/JSysCFG.java +18 −24 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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 Loading Loading @@ -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); } Loading @@ -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<>()); Loading @@ -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); } } } }
sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/JSysDG.java +7 −1 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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 Loading
sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/JSysPDG.java +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