From 3bf8f3bf336cc8d7c2347e3b6500ae601968d6c6 Mon Sep 17 00:00:00 2001 From: serperu Date: Wed, 16 Dec 2020 13:41:26 +0100 Subject: [PATCH 1/4] Create classGraph --- .../upv/mist/slicing/graphs/ClassGraph.java | 212 ++++++++++++++++++ 1 file changed, 212 insertions(+) create mode 100644 sdg-core/src/main/java/es/upv/mist/slicing/graphs/ClassGraph.java diff --git a/sdg-core/src/main/java/es/upv/mist/slicing/graphs/ClassGraph.java b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/ClassGraph.java new file mode 100644 index 0000000..7778a76 --- /dev/null +++ b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/ClassGraph.java @@ -0,0 +1,212 @@ +package es.upv.mist.slicing.graphs; + +import com.github.javaparser.ast.CompilationUnit; +import com.github.javaparser.ast.NodeList; +import com.github.javaparser.ast.body.CallableDeclaration; +import com.github.javaparser.ast.body.ConstructorDeclaration; +import com.github.javaparser.ast.body.MethodDeclaration; +import com.github.javaparser.ast.expr.MethodCallExpr; +import com.github.javaparser.ast.expr.ObjectCreationExpr; +import com.github.javaparser.ast.stmt.ExplicitConstructorInvocationStmt; +import com.github.javaparser.ast.visitor.VoidVisitorAdapter; +import com.github.javaparser.resolution.Resolvable; +import com.github.javaparser.resolution.declarations.ResolvedMethodLikeDeclaration; +import es.upv.mist.slicing.graphs.cfg.CFG; +import es.upv.mist.slicing.nodes.GraphNode; +import es.upv.mist.slicing.utils.ASTUtils; +import es.upv.mist.slicing.utils.NodeNotFoundException; +import es.upv.mist.slicing.utils.Utils; +import org.jgrapht.graph.DefaultEdge; +import org.jgrapht.graph.DirectedPseudograph; +import org.jgrapht.nio.dot.DOTExporter; + +import java.util.*; + +public class ClassGraph extends DirectedPseudograph> implements Buildable> { + private final Map, CFG> cfgMap; + private final Map, CallGraph.Vertex> vertexDeclarationMap = new IdentityHashMap<>(); + + private boolean built = false; + + public ClassGraph(Map, CFG> cfgMap) { + super(null, null, false); + this.cfgMap = cfgMap; + } + + /** Resolve a call to its declaration, by using the call AST nodes stored on the edges. */ + public CallableDeclaration getCallTarget(Resolvable call) { + return edgeSet().stream() + .filter(e -> e.getCall() == call) + .map(this::getEdgeTarget) + .map(CallGraph.Vertex::getDeclaration) + .map(CallableDeclaration.class::cast) + .findFirst() + .orElse(null); + } + + @Override + public void build(NodeList arg) { + if (isBuilt()) + return; + buildVertices(arg); + buildEdges(arg); + built = true; + } + + @Override + public boolean isBuilt() { + return built; + } + + /** Find the method and constructor declarations (vertices) in the given list of compilation units. */ + protected void buildVertices(NodeList arg) { + arg.accept(new VoidVisitorAdapter() { + @Override + public void visit(MethodDeclaration n, Void arg) { + addDeclaration(n); + super.visit(n, arg); + } + + @Override + public void visit(ConstructorDeclaration n, Void arg) { + addDeclaration(n); + super.visit(n, arg); + } + }, null); + } + + protected void addDeclaration(CallableDeclaration n) { + CallGraph.Vertex v = new CallGraph.Vertex(n); + vertexDeclarationMap.put(n, v); + addVertex(v); + } + + protected boolean addEdge(CallableDeclaration source, CallableDeclaration target, Resolvable call) { + CallGraph.Edge edge = new CallGraph.Edge<>(call, findGraphNode(call, source)); + return addEdge(vertexDeclarationMap.get(source), vertexDeclarationMap.get(target), edge); + } + + /** Find the calls to methods and constructors (edges) in the given list of compilation units. */ + protected void buildEdges(NodeList arg) { + arg.accept(new VoidVisitorAdapter() { + private final Deque> declStack = new LinkedList<>(); + + // ============ Method declarations =========== + // There are some locations not considered, which may lead to an error in the stack. + // 1. Method calls in non-static field initializations are assigned to all constructors of that class + // 2. Method calls in static field initializations are assigned to the static block of that class + + @Override + public void visit(MethodDeclaration n, Void arg) { + declStack.push(n); + super.visit(n, arg); + declStack.pop(); + } + + @Override + public void visit(ConstructorDeclaration n, Void arg) { + declStack.push(n); + super.visit(n, arg); + declStack.pop(); + } + + // =============== Method calls =============== + @Override + public void visit(MethodCallExpr n, Void arg) { + n.resolve().toAst().ifPresent(decl -> addEdge(declStack.peek(), decl, n)); + super.visit(n, arg); + } + + @Override + public void visit(ObjectCreationExpr n, Void arg) { + n.resolve().toAst().ifPresent(decl -> addEdge(declStack.peek(), decl, n)); + super.visit(n, arg); + } + + @Override + public void visit(ExplicitConstructorInvocationStmt n, Void arg) { + n.resolve().toAst().ifPresent(decl -> addEdge(declStack.peek(), decl, n)); + super.visit(n, arg); + } + }, null); + } + + /** Locates the node in the collection of CFGs that contains the given call. */ + protected GraphNode findGraphNode(Resolvable n, CallableDeclaration declaration) { + for (GraphNode node : cfgMap.get(declaration).vertexSet()) + if (node.containsCall(n)) + return node; + throw new NodeNotFoundException("call " + n + " could not be located!"); + } + + /** Creates a graph-appropriate DOT exporter. */ + public DOTExporter, CallGraph.Edge> getDOTExporter() { + DOTExporter, CallGraph.Edge> dot = new DOTExporter<>(); + dot.setVertexAttributeProvider(decl -> Utils.dotLabel(decl.getDeclarationAsString(false, false, false))); + dot.setEdgeAttributeProvider(edge -> Utils.dotLabel(edge.getCall().toString())); + return dot; + } + + /** 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 final CallableDeclaration declaration; + + public Vertex(CallableDeclaration declaration) { + assert declaration instanceof ConstructorDeclaration || declaration instanceof MethodDeclaration; + this.declaration = declaration; + } + + /** The declaration represented by this node. */ + public CallableDeclaration getDeclaration() { + return declaration; + } + + @Override + public int hashCode() { + return Objects.hash(declaration, declaration.getRange()); + } + + @Override + public boolean equals(Object obj) { + return obj instanceof CallGraph.Vertex && ASTUtils.equalsWithRangeInCU(((CallGraph.Vertex) obj).declaration, declaration); + } + + @Override + public String toString() { + return super.toString(); + } + } + + /** An edge containing the call it represents, and the graph node that contains it. */ + public static class Edge> extends DefaultEdge { + protected final T call; + protected final GraphNode graphNode; + + public Edge(T call, GraphNode graphNode) { + assert call instanceof MethodCallExpr || call instanceof ObjectCreationExpr || call instanceof ExplicitConstructorInvocationStmt; + this.call = call; + this.graphNode = graphNode; + } + + /** The call represented by this edge. Using the {@link CallGraph} it can be effortlessly resolved. */ + public T getCall() { + return call; + } + + /** The graph node that contains the call represented by this edge. */ + public GraphNode getGraphNode() { + return graphNode; + } + + @Override + public String toString() { + return String.format("%s -%d-> %s", + ((CallableDeclaration) getSource()).getDeclarationAsString(false, false, false), + graphNode.getId(), + ((CallableDeclaration) getTarget()).getDeclarationAsString(false, false, false)); + } + } +} + + -- GitLab From af7109421ff2f55ca946b14c1fbb3159799240f4 Mon Sep 17 00:00:00 2001 From: serperu Date: Tue, 22 Dec 2020 14:19:51 +0100 Subject: [PATCH 2/4] Class Graph with new arcs, members and inheritance relationship --- .../upv/mist/slicing/arcs/clg/ExtendsArc.java | 23 +++ .../mist/slicing/arcs/clg/ImplementsArc.java | 21 ++ .../upv/mist/slicing/arcs/clg/MemberArc.java | 21 ++ .../upv/mist/slicing/graphs/ClassGraph.java | 187 ++++++++---------- .../es/upv/mist/slicing/graphs/sdg/SDG.java | 10 + 5 files changed, 159 insertions(+), 103 deletions(-) create mode 100644 sdg-core/src/main/java/es/upv/mist/slicing/arcs/clg/ExtendsArc.java create mode 100644 sdg-core/src/main/java/es/upv/mist/slicing/arcs/clg/ImplementsArc.java create mode 100644 sdg-core/src/main/java/es/upv/mist/slicing/arcs/clg/MemberArc.java diff --git a/sdg-core/src/main/java/es/upv/mist/slicing/arcs/clg/ExtendsArc.java b/sdg-core/src/main/java/es/upv/mist/slicing/arcs/clg/ExtendsArc.java new file mode 100644 index 0000000..e4df0d9 --- /dev/null +++ b/sdg-core/src/main/java/es/upv/mist/slicing/arcs/clg/ExtendsArc.java @@ -0,0 +1,23 @@ +package es.upv.mist.slicing.arcs.clg; + +import es.upv.mist.slicing.arcs.Arc; +import es.upv.mist.slicing.graphs.ClassGraph; +import org.jgrapht.nio.Attribute; +import org.jgrapht.nio.DefaultAttribute; + + +import java.util.Map; + + +/** + * An edge of the {@link ClassGraph}. Represents the inheritance relationship in Java. + * It goes from the base class to the derived class + */ + +public class ExtendsArc extends Arc { + public Map getDotAttributes() { + Map map = super.getDotAttributes(); + map.put("style", DefaultAttribute.createAttribute("dashed")); + return map; + } +} diff --git a/sdg-core/src/main/java/es/upv/mist/slicing/arcs/clg/ImplementsArc.java b/sdg-core/src/main/java/es/upv/mist/slicing/arcs/clg/ImplementsArc.java new file mode 100644 index 0000000..4ec7251 --- /dev/null +++ b/sdg-core/src/main/java/es/upv/mist/slicing/arcs/clg/ImplementsArc.java @@ -0,0 +1,21 @@ +package es.upv.mist.slicing.arcs.clg; + +import es.upv.mist.slicing.arcs.Arc; +import es.upv.mist.slicing.graphs.ClassGraph; +import org.jgrapht.nio.Attribute; +import org.jgrapht.nio.DefaultAttribute; + +import java.util.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 class ImplementsArc extends Arc { + public Map getDotAttributes() { + Map map = super.getDotAttributes(); + map.put("style", DefaultAttribute.createAttribute("dashed")); + return map; + } +} diff --git a/sdg-core/src/main/java/es/upv/mist/slicing/arcs/clg/MemberArc.java b/sdg-core/src/main/java/es/upv/mist/slicing/arcs/clg/MemberArc.java new file mode 100644 index 0000000..8c5dbaa --- /dev/null +++ b/sdg-core/src/main/java/es/upv/mist/slicing/arcs/clg/MemberArc.java @@ -0,0 +1,21 @@ +package es.upv.mist.slicing.arcs.clg; + +import es.upv.mist.slicing.arcs.Arc; +import es.upv.mist.slicing.graphs.ClassGraph; +import org.jgrapht.nio.Attribute; +import org.jgrapht.nio.DefaultAttribute; + +import java.util.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 class MemberArc extends Arc { + public Map getDotAttributes() { + Map map = super.getDotAttributes(); + map.put("style", DefaultAttribute.createAttribute("dashed")); + return map; + } +} diff --git a/sdg-core/src/main/java/es/upv/mist/slicing/graphs/ClassGraph.java b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/ClassGraph.java index 7778a76..a718472 100644 --- a/sdg-core/src/main/java/es/upv/mist/slicing/graphs/ClassGraph.java +++ b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/ClassGraph.java @@ -2,19 +2,13 @@ package es.upv.mist.slicing.graphs; import com.github.javaparser.ast.CompilationUnit; import com.github.javaparser.ast.NodeList; -import com.github.javaparser.ast.body.CallableDeclaration; -import com.github.javaparser.ast.body.ConstructorDeclaration; -import com.github.javaparser.ast.body.MethodDeclaration; -import com.github.javaparser.ast.expr.MethodCallExpr; -import com.github.javaparser.ast.expr.ObjectCreationExpr; -import com.github.javaparser.ast.stmt.ExplicitConstructorInvocationStmt; +import com.github.javaparser.ast.body.*; import com.github.javaparser.ast.visitor.VoidVisitorAdapter; -import com.github.javaparser.resolution.Resolvable; -import com.github.javaparser.resolution.declarations.ResolvedMethodLikeDeclaration; +import es.upv.mist.slicing.arcs.clg.ExtendsArc; +import es.upv.mist.slicing.arcs.clg.ImplementsArc; +import es.upv.mist.slicing.arcs.clg.MemberArc; import es.upv.mist.slicing.graphs.cfg.CFG; -import es.upv.mist.slicing.nodes.GraphNode; import es.upv.mist.slicing.utils.ASTUtils; -import es.upv.mist.slicing.utils.NodeNotFoundException; import es.upv.mist.slicing.utils.Utils; import org.jgrapht.graph.DefaultEdge; import org.jgrapht.graph.DirectedPseudograph; @@ -22,27 +16,19 @@ import org.jgrapht.nio.dot.DOTExporter; import java.util.*; -public class ClassGraph extends DirectedPseudograph> implements Buildable> { - private final Map, CFG> cfgMap; - private final Map, CallGraph.Vertex> vertexDeclarationMap = new IdentityHashMap<>(); +public class ClassGraph extends DirectedPseudograph implements Buildable> { + + /** 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 + * objects and there is no relationship to match them */ + private final Map vertexDeclarationMap = new HashMap<>(); private boolean built = false; - public ClassGraph(Map, CFG> cfgMap) { + public ClassGraph() { super(null, null, false); - this.cfgMap = cfgMap; } - /** Resolve a call to its declaration, by using the call AST nodes stored on the edges. */ - public CallableDeclaration getCallTarget(Resolvable call) { - return edgeSet().stream() - .filter(e -> e.getCall() == call) - .map(this::getEdgeTarget) - .map(CallGraph.Vertex::getDeclaration) - .map(CallableDeclaration.class::cast) - .findFirst() - .orElse(null); - } @Override public void build(NodeList arg) { @@ -58,85 +44,109 @@ public class ClassGraph extends DirectedPseudograph arg) { arg.accept(new VoidVisitorAdapter() { + +// QUESTIONS & LACKS: +// 1) Is it necessary to include something apart from class vertices? +// 2) Private classes inside other classes? +// 3) Static declaration blocks not considered + @Override - public void visit(MethodDeclaration n, Void arg) { - addDeclaration(n); + public void visit(ClassOrInterfaceDeclaration n, Void arg) { + addClassDeclaration(n); super.visit(n, arg); } + @Override + public void visit(FieldDeclaration n, Void arg) { + addFieldDeclaration(n); + } + + @Override + public void visit(MethodDeclaration n, Void arg) { + addCallableDeclaration(n); + } + @Override public void visit(ConstructorDeclaration n, Void arg) { - addDeclaration(n); - super.visit(n, arg); + addCallableDeclaration(n); } }, null); } - protected void addDeclaration(CallableDeclaration n) { - CallGraph.Vertex v = new CallGraph.Vertex(n); - vertexDeclarationMap.put(n, v); + /** Add a class declaration vertex to the class graph */ + protected void addClassDeclaration(ClassOrInterfaceDeclaration n) { + ClassGraph.Vertex v = new ClassGraph.Vertex(n); + // Required string to match ClassOrInterfaceType and ClassOrInterfaceDeclaration + vertexDeclarationMap.put(n.getNameAsString(), v); + addVertex(v); + } + + /** Add a field declaration vertex to the class graph */ + protected void addFieldDeclaration(FieldDeclaration n){ + ClassGraph.Vertex v = new ClassGraph.Vertex(n); + // Key value: hashCode + toString() to avoid multiple field declarations with the same syntax in different classes + vertexDeclarationMap.put(n.hashCode() + n.toString(), v); addVertex(v); } - protected boolean addEdge(CallableDeclaration source, CallableDeclaration target, Resolvable call) { - CallGraph.Edge edge = new CallGraph.Edge<>(call, findGraphNode(call, source)); - return addEdge(vertexDeclarationMap.get(source), vertexDeclarationMap.get(target), edge); + /** Add a method/constructor declaration vertex to the class graph */ + protected void addCallableDeclaration(CallableDeclaration n){ + assert n instanceof ConstructorDeclaration || n instanceof MethodDeclaration; + ClassGraph.Vertex v = new ClassGraph.Vertex(n); + vertexDeclarationMap.put(n.hashCode() + n.getSignature().toString(), v); + addVertex(v); } - /** Find the calls to methods and constructors (edges) in the given list of compilation units. */ + /** Find the class declarations, field declarations, and method declarations and build the corresponding + * member/extends/implements relationships in the given list of compilation units. */ protected void buildEdges(NodeList arg) { arg.accept(new VoidVisitorAdapter() { - private final Deque> declStack = new LinkedList<>(); - - // ============ Method declarations =========== - // There are some locations not considered, which may lead to an error in the stack. - // 1. Method calls in non-static field initializations are assigned to all constructors of that class - // 2. Method calls in static field initializations are assigned to the static block of that class + private final Deque classStack = new LinkedList<>(); @Override - public void visit(MethodDeclaration n, Void arg) { - declStack.push(n); + public void visit(ClassOrInterfaceDeclaration n, Void arg) { + classStack.push(n); + Vertex v = vertexDeclarationMap.get(n.getNameAsString()); + addClassEdges(v); super.visit(n, arg); - declStack.pop(); + classStack.pop(); } @Override - public void visit(ConstructorDeclaration n, Void arg) { - declStack.push(n); - super.visit(n, arg); - declStack.pop(); + public void visit(FieldDeclaration n, Void arg) { + ClassOrInterfaceDeclaration clazz = classStack.peek(); + Vertex c = vertexDeclarationMap.get(clazz.getNameAsString()); + Vertex v = vertexDeclarationMap.get(n.hashCode() + n.toString()); + addEdge(c, v, new MemberArc()); } - // =============== Method calls =============== @Override - public void visit(MethodCallExpr n, Void arg) { - n.resolve().toAst().ifPresent(decl -> addEdge(declStack.peek(), decl, n)); - super.visit(n, arg); - } - - @Override - public void visit(ObjectCreationExpr n, Void arg) { - n.resolve().toAst().ifPresent(decl -> addEdge(declStack.peek(), decl, n)); - super.visit(n, arg); + public void visit(MethodDeclaration n, Void arg) { + ClassOrInterfaceDeclaration clazz = classStack.peek(); + Vertex c = vertexDeclarationMap.get(clazz.getNameAsString()); + Vertex v = vertexDeclarationMap.get(n.hashCode() + n.getSignature().toString()); + addEdge(c, v, new MemberArc()); } @Override - public void visit(ExplicitConstructorInvocationStmt n, Void arg) { - n.resolve().toAst().ifPresent(decl -> addEdge(declStack.peek(), decl, n)); - super.visit(n, arg); + public void visit(ConstructorDeclaration n, Void arg) { + ClassOrInterfaceDeclaration clazz = classStack.peek(); + Vertex c = vertexDeclarationMap.get(clazz.getNameAsString()); + Vertex v = vertexDeclarationMap.get(n.hashCode() + n.getSignature().toString()); + addEdge(c, v, new MemberArc()); } }, null); } - /** Locates the node in the collection of CFGs that contains the given call. */ - protected GraphNode findGraphNode(Resolvable n, CallableDeclaration declaration) { - for (GraphNode node : cfgMap.get(declaration).vertexSet()) - if (node.containsCall(n)) - return node; - throw new NodeNotFoundException("call " + n + " could not be located!"); + protected void addClassEdges(Vertex v){ + assert v.declaration instanceof ClassOrInterfaceDeclaration; + ClassOrInterfaceDeclaration dv = (ClassOrInterfaceDeclaration) v.declaration; + dv.getExtendedTypes().forEach(p -> addEdge(vertexDeclarationMap.get(p.getNameAsString()), v, new ExtendsArc())); + dv.getImplementedTypes().forEach(p -> addEdge(vertexDeclarationMap.get(p.getNameAsString()), v, new ImplementsArc())); } /** Creates a graph-appropriate DOT exporter. */ @@ -150,15 +160,16 @@ public class ClassGraph extends DirectedPseudograph declaration; + // First ancestor common class in the JavaParser hierarchy for + // ClassOrInterfaceDeclaration, FieldDeclaration and CallableDeclaration + protected final BodyDeclaration declaration; - public Vertex(CallableDeclaration declaration) { - assert declaration instanceof ConstructorDeclaration || declaration instanceof MethodDeclaration; + public Vertex(BodyDeclaration declaration) { this.declaration = declaration; } /** The declaration represented by this node. */ - public CallableDeclaration getDeclaration() { + public BodyDeclaration getDeclaration() { return declaration; } @@ -177,36 +188,6 @@ public class ClassGraph extends DirectedPseudograph> extends DefaultEdge { - protected final T call; - protected final GraphNode graphNode; - - public Edge(T call, GraphNode graphNode) { - assert call instanceof MethodCallExpr || call instanceof ObjectCreationExpr || call instanceof ExplicitConstructorInvocationStmt; - this.call = call; - this.graphNode = graphNode; - } - - /** The call represented by this edge. Using the {@link CallGraph} it can be effortlessly resolved. */ - public T getCall() { - return call; - } - - /** The graph node that contains the call represented by this edge. */ - public GraphNode getGraphNode() { - return graphNode; - } - - @Override - public String toString() { - return String.format("%s -%d-> %s", - ((CallableDeclaration) getSource()).getDeclarationAsString(false, false, false), - graphNode.getId(), - ((CallableDeclaration) getTarget()).getDeclarationAsString(false, false, false)); - } - } } diff --git a/sdg-core/src/main/java/es/upv/mist/slicing/graphs/sdg/SDG.java b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/sdg/SDG.java index c22cb79..aaf67c9 100644 --- a/sdg-core/src/main/java/es/upv/mist/slicing/graphs/sdg/SDG.java +++ b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/sdg/SDG.java @@ -15,6 +15,7 @@ import es.upv.mist.slicing.arcs.sdg.ParameterInOutArc; import es.upv.mist.slicing.arcs.sdg.SummaryArc; import es.upv.mist.slicing.graphs.Buildable; import es.upv.mist.slicing.graphs.CallGraph; +import es.upv.mist.slicing.graphs.ClassGraph; import es.upv.mist.slicing.graphs.Graph; import es.upv.mist.slicing.graphs.cfg.CFG; import es.upv.mist.slicing.graphs.cfg.CFGBuilder; @@ -107,6 +108,7 @@ public class SDG extends Graph implements Sliceable, Buildable nodeList){ + ClassGraph classGraph = new ClassGraph(); + classGraph.build(nodeList); + return classGraph; + } + + /** Perform interprocedural analyses to determine the actual, formal and call return nodes. */ protected void dataFlowAnalysis(CallGraph callGraph) { new InterproceduralDefinitionFinder(callGraph, cfgMap).save(); // 3.1 -- GitLab From 39bc794d5342bfa4fc672d506e950969625cfe7b Mon Sep 17 00:00:00 2001 From: serperu Date: Thu, 7 Jan 2021 14:06:40 +0100 Subject: [PATCH 3/4] Usage of FullyQualifiedName as vertexMap key --- .../upv/mist/slicing/graphs/ClassGraph.java | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/sdg-core/src/main/java/es/upv/mist/slicing/graphs/ClassGraph.java b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/ClassGraph.java index a718472..d9819bc 100644 --- a/sdg-core/src/main/java/es/upv/mist/slicing/graphs/ClassGraph.java +++ b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/ClassGraph.java @@ -48,7 +48,7 @@ public class ClassGraph extends DirectedPseudograph arg) { arg.accept(new VoidVisitorAdapter() { - + private final Deque classStack = new LinkedList<>(); // QUESTIONS & LACKS: // 1) Is it necessary to include something apart from class vertices? // 2) Private classes inside other classes? @@ -56,23 +56,25 @@ public class ClassGraph extends DirectedPseudograph n){ + protected void addCallableDeclaration(CallableDeclaration n, ClassOrInterfaceDeclaration c){ assert n instanceof ConstructorDeclaration || n instanceof MethodDeclaration; ClassGraph.Vertex v = new ClassGraph.Vertex(n); - vertexDeclarationMap.put(n.hashCode() + n.getSignature().toString(), v); + vertexDeclarationMap.put(c.getFullyQualifiedName().get()+ "." + n.getSignature().toString(), v); addVertex(v); } @@ -120,7 +122,7 @@ public class ClassGraph extends DirectedPseudograph Date: Thu, 7 Jan 2021 16:38:44 +0100 Subject: [PATCH 4/4] Merge arc classes into ClassGraph, fix null pointer --- .../upv/mist/slicing/arcs/clg/ExtendsArc.java | 23 -------- .../mist/slicing/arcs/clg/ImplementsArc.java | 21 ------- .../upv/mist/slicing/arcs/clg/MemberArc.java | 21 ------- .../upv/mist/slicing/graphs/ClassGraph.java | 56 ++++++++++++++++--- 4 files changed, 49 insertions(+), 72 deletions(-) delete mode 100644 sdg-core/src/main/java/es/upv/mist/slicing/arcs/clg/ExtendsArc.java delete mode 100644 sdg-core/src/main/java/es/upv/mist/slicing/arcs/clg/ImplementsArc.java delete mode 100644 sdg-core/src/main/java/es/upv/mist/slicing/arcs/clg/MemberArc.java diff --git a/sdg-core/src/main/java/es/upv/mist/slicing/arcs/clg/ExtendsArc.java b/sdg-core/src/main/java/es/upv/mist/slicing/arcs/clg/ExtendsArc.java deleted file mode 100644 index e4df0d9..0000000 --- a/sdg-core/src/main/java/es/upv/mist/slicing/arcs/clg/ExtendsArc.java +++ /dev/null @@ -1,23 +0,0 @@ -package es.upv.mist.slicing.arcs.clg; - -import es.upv.mist.slicing.arcs.Arc; -import es.upv.mist.slicing.graphs.ClassGraph; -import org.jgrapht.nio.Attribute; -import org.jgrapht.nio.DefaultAttribute; - - -import java.util.Map; - - -/** - * An edge of the {@link ClassGraph}. Represents the inheritance relationship in Java. - * It goes from the base class to the derived class - */ - -public class ExtendsArc extends Arc { - public Map getDotAttributes() { - Map map = super.getDotAttributes(); - map.put("style", DefaultAttribute.createAttribute("dashed")); - return map; - } -} diff --git a/sdg-core/src/main/java/es/upv/mist/slicing/arcs/clg/ImplementsArc.java b/sdg-core/src/main/java/es/upv/mist/slicing/arcs/clg/ImplementsArc.java deleted file mode 100644 index 4ec7251..0000000 --- a/sdg-core/src/main/java/es/upv/mist/slicing/arcs/clg/ImplementsArc.java +++ /dev/null @@ -1,21 +0,0 @@ -package es.upv.mist.slicing.arcs.clg; - -import es.upv.mist.slicing.arcs.Arc; -import es.upv.mist.slicing.graphs.ClassGraph; -import org.jgrapht.nio.Attribute; -import org.jgrapht.nio.DefaultAttribute; - -import java.util.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 class ImplementsArc extends Arc { - public Map getDotAttributes() { - Map map = super.getDotAttributes(); - map.put("style", DefaultAttribute.createAttribute("dashed")); - return map; - } -} diff --git a/sdg-core/src/main/java/es/upv/mist/slicing/arcs/clg/MemberArc.java b/sdg-core/src/main/java/es/upv/mist/slicing/arcs/clg/MemberArc.java deleted file mode 100644 index 8c5dbaa..0000000 --- a/sdg-core/src/main/java/es/upv/mist/slicing/arcs/clg/MemberArc.java +++ /dev/null @@ -1,21 +0,0 @@ -package es.upv.mist.slicing.arcs.clg; - -import es.upv.mist.slicing.arcs.Arc; -import es.upv.mist.slicing.graphs.ClassGraph; -import org.jgrapht.nio.Attribute; -import org.jgrapht.nio.DefaultAttribute; - -import java.util.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 class MemberArc extends Arc { - public Map getDotAttributes() { - Map map = super.getDotAttributes(); - map.put("style", DefaultAttribute.createAttribute("dashed")); - return map; - } -} diff --git a/sdg-core/src/main/java/es/upv/mist/slicing/graphs/ClassGraph.java b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/ClassGraph.java index d9819bc..0777a79 100644 --- a/sdg-core/src/main/java/es/upv/mist/slicing/graphs/ClassGraph.java +++ b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/ClassGraph.java @@ -4,14 +4,13 @@ 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 es.upv.mist.slicing.arcs.clg.ExtendsArc; -import es.upv.mist.slicing.arcs.clg.ImplementsArc; -import es.upv.mist.slicing.arcs.clg.MemberArc; -import es.upv.mist.slicing.graphs.cfg.CFG; +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.*; @@ -29,7 +28,6 @@ public class ClassGraph extends DirectedPseudograph arg) { if (isBuilt()) @@ -147,8 +145,16 @@ public class ClassGraph extends DirectedPseudograph addEdge(vertexDeclarationMap.get(p.getNameAsString()), v, new ExtendsArc())); - dv.getImplementedTypes().forEach(p -> addEdge(vertexDeclarationMap.get(p.getNameAsString()), v, new ImplementsArc())); + dv.getExtendedTypes().forEach(p -> { + Vertex source = vertexDeclarationMap.get(p.getNameAsString()); + if (source != null && containsVertex(v)) + addEdge(source, v, new ExtendsArc()); + }); + dv.getImplementedTypes().forEach(p -> { + Vertex source = vertexDeclarationMap.get(p.getNameAsString()); + if (source != null && containsVertex(v)) + addEdge(source, v, new ImplementsArc()); + }); } /** Creates a graph-appropriate DOT exporter. */ @@ -190,6 +196,42 @@ public class ClassGraph extends DirectedPseudograph getDotAttributes() { + Map 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 getDotAttributes() { + Map 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 getDotAttributes() { + Map map = super.getDotAttributes(); + map.put("style", DefaultAttribute.createAttribute("dashed")); + return map; + } + } } -- GitLab