Loading sdg-core/src/main/java/es/upv/mist/slicing/arcs/clg/ExtendsArc.java 0 → 100644 +23 −0 Original line number Diff line number Diff line 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<String, Attribute> getDotAttributes() { Map<String, Attribute> map = super.getDotAttributes(); map.put("style", DefaultAttribute.createAttribute("dashed")); return map; } } sdg-core/src/main/java/es/upv/mist/slicing/arcs/clg/ImplementsArc.java 0 → 100644 +21 −0 Original line number Diff line number Diff line 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<String, Attribute> getDotAttributes() { Map<String, Attribute> map = super.getDotAttributes(); map.put("style", DefaultAttribute.createAttribute("dashed")); return map; } } sdg-core/src/main/java/es/upv/mist/slicing/arcs/clg/MemberArc.java 0 → 100644 +21 −0 Original line number Diff line number Diff line 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<String, Attribute> getDotAttributes() { Map<String, Attribute> map = super.getDotAttributes(); map.put("style", DefaultAttribute.createAttribute("dashed")); return map; } } sdg-core/src/main/java/es/upv/mist/slicing/graphs/ClassGraph.java +84 −103 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -22,27 +16,19 @@ import org.jgrapht.nio.dot.DOTExporter; import java.util.*; public class ClassGraph extends DirectedPseudograph<CallGraph.Vertex, CallGraph.Edge<?>> implements Buildable<NodeList<CompilationUnit>> { private final Map<CallableDeclaration<?>, CFG> cfgMap; private final Map<CallableDeclaration<?>, CallGraph.Vertex> vertexDeclarationMap = new IdentityHashMap<>(); public class ClassGraph extends DirectedPseudograph<ClassGraph.Vertex, DefaultEdge> 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 * objects and there is no relationship to match them */ private final Map<String, ClassGraph.Vertex> vertexDeclarationMap = new HashMap<>(); private boolean built = false; public ClassGraph(Map<CallableDeclaration<?>, 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<? extends ResolvedMethodLikeDeclaration> 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<CompilationUnit> arg) { Loading @@ -58,85 +44,109 @@ public class ClassGraph extends DirectedPseudograph<CallGraph.Vertex, CallGraph. return built; } /** Find the method and constructor declarations (vertices) in the given list of compilation units. */ /** 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) { arg.accept(new VoidVisitorAdapter<Void>() { // 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<? extends ResolvedMethodLikeDeclaration> 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<CompilationUnit> arg) { arg.accept(new VoidVisitorAdapter<Void>() { private final Deque<CallableDeclaration<?>> 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<ClassOrInterfaceDeclaration> 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<? extends ResolvedMethodLikeDeclaration> 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. */ Loading @@ -150,15 +160,16 @@ public class ClassGraph extends DirectedPseudograph<CallGraph.Vertex, CallGraph. /** 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; // 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; } Loading @@ -177,36 +188,6 @@ public class ClassGraph extends DirectedPseudograph<CallGraph.Vertex, CallGraph. return super.toString(); } } /** An edge containing the call it represents, and the graph node that contains it. */ public static class Edge<T extends Resolvable<? extends ResolvedMethodLikeDeclaration>> 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)); } } } sdg-core/src/main/java/es/upv/mist/slicing/graphs/sdg/SDG.java +10 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -107,6 +108,7 @@ public class SDG extends Graph implements Sliceable, Buildable<NodeList<Compilat // See creation strategy at http://kaz2.dsic.upv.es:3000/Fzg46cQvT1GzHQG9hFnP1g#Using-data-flow-in-the-SDG buildCFGs(nodeList); // 1 CallGraph callGraph = createCallGraph(nodeList); // 2 ClassGraph classGraph = createClassGraph(nodeList); // TODO: Update order and creation strategy dataFlowAnalysis(callGraph); // 3 buildAndCopyPDGs(); // 4 connectCalls(callGraph); // 5 Loading Loading @@ -139,6 +141,14 @@ public class SDG extends Graph implements Sliceable, Buildable<NodeList<Compilat return callGraph; } /** Create class graph from the list of compilation units. */ protected ClassGraph createClassGraph(NodeList<CompilationUnit> 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 Loading Loading
sdg-core/src/main/java/es/upv/mist/slicing/arcs/clg/ExtendsArc.java 0 → 100644 +23 −0 Original line number Diff line number Diff line 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<String, Attribute> getDotAttributes() { Map<String, Attribute> map = super.getDotAttributes(); map.put("style", DefaultAttribute.createAttribute("dashed")); return map; } }
sdg-core/src/main/java/es/upv/mist/slicing/arcs/clg/ImplementsArc.java 0 → 100644 +21 −0 Original line number Diff line number Diff line 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<String, Attribute> getDotAttributes() { Map<String, Attribute> map = super.getDotAttributes(); map.put("style", DefaultAttribute.createAttribute("dashed")); return map; } }
sdg-core/src/main/java/es/upv/mist/slicing/arcs/clg/MemberArc.java 0 → 100644 +21 −0 Original line number Diff line number Diff line 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<String, Attribute> getDotAttributes() { Map<String, Attribute> map = super.getDotAttributes(); map.put("style", DefaultAttribute.createAttribute("dashed")); return map; } }
sdg-core/src/main/java/es/upv/mist/slicing/graphs/ClassGraph.java +84 −103 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -22,27 +16,19 @@ import org.jgrapht.nio.dot.DOTExporter; import java.util.*; public class ClassGraph extends DirectedPseudograph<CallGraph.Vertex, CallGraph.Edge<?>> implements Buildable<NodeList<CompilationUnit>> { private final Map<CallableDeclaration<?>, CFG> cfgMap; private final Map<CallableDeclaration<?>, CallGraph.Vertex> vertexDeclarationMap = new IdentityHashMap<>(); public class ClassGraph extends DirectedPseudograph<ClassGraph.Vertex, DefaultEdge> 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 * objects and there is no relationship to match them */ private final Map<String, ClassGraph.Vertex> vertexDeclarationMap = new HashMap<>(); private boolean built = false; public ClassGraph(Map<CallableDeclaration<?>, 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<? extends ResolvedMethodLikeDeclaration> 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<CompilationUnit> arg) { Loading @@ -58,85 +44,109 @@ public class ClassGraph extends DirectedPseudograph<CallGraph.Vertex, CallGraph. return built; } /** Find the method and constructor declarations (vertices) in the given list of compilation units. */ /** 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) { arg.accept(new VoidVisitorAdapter<Void>() { // 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<? extends ResolvedMethodLikeDeclaration> 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<CompilationUnit> arg) { arg.accept(new VoidVisitorAdapter<Void>() { private final Deque<CallableDeclaration<?>> 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<ClassOrInterfaceDeclaration> 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<? extends ResolvedMethodLikeDeclaration> 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. */ Loading @@ -150,15 +160,16 @@ public class ClassGraph extends DirectedPseudograph<CallGraph.Vertex, CallGraph. /** 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; // 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; } Loading @@ -177,36 +188,6 @@ public class ClassGraph extends DirectedPseudograph<CallGraph.Vertex, CallGraph. return super.toString(); } } /** An edge containing the call it represents, and the graph node that contains it. */ public static class Edge<T extends Resolvable<? extends ResolvedMethodLikeDeclaration>> 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)); } } }
sdg-core/src/main/java/es/upv/mist/slicing/graphs/sdg/SDG.java +10 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -107,6 +108,7 @@ public class SDG extends Graph implements Sliceable, Buildable<NodeList<Compilat // See creation strategy at http://kaz2.dsic.upv.es:3000/Fzg46cQvT1GzHQG9hFnP1g#Using-data-flow-in-the-SDG buildCFGs(nodeList); // 1 CallGraph callGraph = createCallGraph(nodeList); // 2 ClassGraph classGraph = createClassGraph(nodeList); // TODO: Update order and creation strategy dataFlowAnalysis(callGraph); // 3 buildAndCopyPDGs(); // 4 connectCalls(callGraph); // 5 Loading Loading @@ -139,6 +141,14 @@ public class SDG extends Graph implements Sliceable, Buildable<NodeList<Compilat return callGraph; } /** Create class graph from the list of compilation units. */ protected ClassGraph createClassGraph(NodeList<CompilationUnit> 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 Loading