diff --git a/sdg-core/src/main/java/es/upv/mist/slicing/graphs/CallGraph.java b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/CallGraph.java index f0cdb2ce4ebc7cbb1402921f31ecac0af74342a6..3d1a880f6ce70fb837c46a9885890c7a7bf9e547 100644 --- a/sdg-core/src/main/java/es/upv/mist/slicing/graphs/CallGraph.java +++ b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/CallGraph.java @@ -217,7 +217,7 @@ public class CallGraph extends DirectedPseudograph classGraph.findMethodByTypeAndSignature(t, decl.getSignature())) + .map(t -> classGraph.findMethodByTypeAndSignature(t, decl)) .collect(Collectors.toCollection(NodeHashSet::new)) .forEach(methodDecl -> { edgesCreated.getAndIncrement(); 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 5dc4c886ebc664fe7c9dca5d72c6480e5d106f79..bc5bcc998325b6f7a3bd61a12bf0477372be1ab3 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 @@ -1,7 +1,6 @@ package es.upv.mist.slicing.graphs; import com.github.javaparser.ast.CompilationUnit; -import com.github.javaparser.ast.Modifier; import com.github.javaparser.ast.NodeList; import com.github.javaparser.ast.body.*; import com.github.javaparser.ast.visitor.VoidVisitorAdapter; @@ -33,33 +32,11 @@ public class ClassGraph extends DirectedPseudograph 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 overriddenSetOf(MethodDeclaration method) { @@ -90,11 +67,11 @@ public class ClassGraph extends DirectedPseudograph subclassesOf(ResolvedClassDeclaration clazz) { - return subclassesOf(findClassVertex(clazz)); + return subclassesOf(vertexDeclarationMap.get(mapKey(clazz))); } public Set subclassesOf(ResolvedReferenceType type) { - return subclassesOf(findClassVertex(type)); + return subclassesOf(vertexDeclarationMap.get(mapKey(type))); } /** @see #subclassesOf(ClassOrInterfaceDeclaration) */ @@ -115,21 +92,14 @@ public class ClassGraph extends DirectedPseudograph 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 parentType = parentOf(type); if (parentType.isEmpty()) - throw new IllegalArgumentException("Cannot find the given signature: " + signature); - return findMethodByTypeAndSignature(parentType.get(), signature); + throw new IllegalArgumentException("Cannot find the given declaration: " + declaration); + return findMethodByTypeAndSignature(parentType.get(), declaration); } /** Find the parent class or interface of a given class. */ @@ -157,6 +127,26 @@ public class ClassGraph extends DirectedPseudograph 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 arg) { @@ -177,16 +167,19 @@ public class ClassGraph extends DirectedPseudograph n, ClassOrInterfaceDeclaration c){ assert n instanceof ConstructorDeclaration || n instanceof MethodDeclaration; ClassGraph.Vertex v = new ClassGraph.Vertex(n); - vertexDeclarationMap.put(c.getFullyQualifiedName().get()+ "." + n.getSignature().toString(), v); + vertexDeclarationMap.put(mapKey(n, c), v); addVertex(v); } @@ -224,7 +217,7 @@ public class ClassGraph extends DirectedPseudograph { - 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, 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())); + public DOTExporter getDOTExporter() { + DOTExporter dot = new DOTExporter<>(); + dot.setVertexAttributeProvider(vertex -> Utils.dotLabel(vertex.declaration.toString().replaceAll("\\{.*}", ""))); + dot.setEdgeAttributeProvider(edge -> Utils.dotLabel(edge.getClass().getSimpleName())); return dot; } @@ -306,40 +303,8 @@ public class ClassGraph extends DirectedPseudograph> getStaticInit(String className){ - return getClassInit(className,true); - } - - /** Returns a List with the dynamic FieldDeclarations and InitializerDeclarations of the given class */ - public List> getDynInit(String className){ - return getClassInit(className,false); - } - - /** Returns a List with FieldDeclarations and InitializerDeclarations static/dynamic items of the given class */ - private List> getClassInit(String className, Boolean isStatic){ - Vertex classNode = vertexDeclarationMap.get(className); - List> members = classNode.declaration.asClassOrInterfaceDeclaration().getMembers(); - List> 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 { diff --git a/sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/JSysCFG.java b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/JSysCFG.java index f43e32adc04d21340d191fa7491c2c0f26db1681..b184a5f7aec197487e95117c83174ca573f50a3d 100644 --- a/sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/JSysCFG.java +++ b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/JSysCFG.java @@ -3,13 +3,11 @@ package es.upv.mist.slicing.graphs.jsysdg; import com.github.javaparser.ast.Node; import com.github.javaparser.ast.NodeList; import com.github.javaparser.ast.body.CallableDeclaration; -import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration; import com.github.javaparser.ast.body.ConstructorDeclaration; import com.github.javaparser.ast.body.FieldDeclaration; import com.github.javaparser.ast.expr.ThisExpr; import com.github.javaparser.ast.stmt.ExplicitConstructorInvocationStmt; import com.github.javaparser.ast.stmt.ReturnStmt; -import es.upv.mist.slicing.graphs.ClassGraph; import es.upv.mist.slicing.graphs.cfg.CFGBuilder; import es.upv.mist.slicing.graphs.exceptionsensitive.ESCFG; import es.upv.mist.slicing.nodes.GraphNode; @@ -25,22 +23,19 @@ import java.util.Set; * polymorphism and other features. */ public class JSysCFG extends ESCFG { - /** ClassGraph associated to the Method represented by the CFG */ - protected ClassGraph classGraph; - /** Set of constructors that must be built with implicit nodes. */ - protected Set implicitConstructors; - - public JSysCFG(ClassGraph classGraph, Set implicitConstructors) { - super(); - this.classGraph = classGraph; - this.implicitConstructors = implicitConstructors; + @Override + public void build(CallableDeclaration declaration) { + throw new UnsupportedOperationException("Use build(CallableDeclaration, ClassGraph, Set)"); } - @Override - public void buildRootNode(CallableDeclaration rootNodeAst) { - super.buildRootNode(rootNodeAst); - if (implicitConstructors.contains(rootNodeAst)) - rootNode.markAsImplicit(); + public void build(CallableDeclaration declaration, Set implicitConstructors) { + Builder builder = (Builder) newCFGBuilder(); + builder.implicitDeclaration = implicitConstructors.contains(declaration); + declaration.accept(builder, null); + // Verify that it has been built + exitNode = vertexSet().stream().filter(MethodExitNode.class::isInstance).findFirst() + .orElseThrow(() -> new IllegalStateException("Built graph has no exit node!")); + built = true; } @Override @@ -77,10 +72,9 @@ public class JSysCFG extends ESCFG { // 1. Connect to the following statements connectTo(n); // 2. Insert dynamic class code (only for super()) - if (!n.isThis()) { - ClassOrInterfaceDeclaration containerClass = ASTUtils.getClassNode(rootNode.getAstNode()); - classGraph.getDynInit(containerClass.getNameAsString()).forEach(node -> node.accept(this, arg)); - } + if (!n.isThis()) + ASTUtils.getClassInit(ASTUtils.getClassNode(rootNode.getAstNode()), false) + .forEach(node -> node.accept(this, arg)); // 3. Handle exceptions super.visitCallForExceptions(n); } @@ -93,8 +87,6 @@ public class JSysCFG extends ESCFG { @Override public void visit(ConstructorDeclaration n, Void arg) { - if (implicitConstructors.contains(n)) - implicitDeclaration = true; // Insert call to super() if it is implicit. if (!ASTUtils.constructorHasExplicitConstructorInvocation(n)){ var superCall = new ExplicitConstructorInvocationStmt(null, null, false, null, new NodeList<>()); @@ -106,11 +98,13 @@ public class JSysCFG extends ESCFG { } // Perform the same task as previous graphs. super.visit(n, arg); - // Convert the exit nodes to implicit if appropriate - if (implicitDeclaration) + // Convert enter/exit nodes to implicit if appropriate + if (implicitDeclaration) { + getRootNode().markAsImplicit(); vertexSet().stream() .filter(MethodExitNode.class::isInstance) .forEach(GraphNode::markAsImplicit); + } } } } diff --git a/sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/JSysDG.java b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/JSysDG.java index eaf5a3652e7c5ea416b022ba78f10f54bc875919..809c0d663c2cfc8bc2e42470d868543a8ae3be7e 100644 --- a/sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/JSysDG.java +++ b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/JSysDG.java @@ -3,6 +3,7 @@ package es.upv.mist.slicing.graphs.jsysdg; import com.github.javaparser.ast.CompilationUnit; import com.github.javaparser.ast.Modifier; import com.github.javaparser.ast.NodeList; +import com.github.javaparser.ast.body.CallableDeclaration; import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration; import com.github.javaparser.ast.body.ConstructorDeclaration; import com.github.javaparser.ast.visitor.ModifierVisitor; @@ -45,9 +46,14 @@ public class JSysDG extends ESSDG { }, null); } + @Override + protected void buildCFG(CallableDeclaration declaration, CFG cfg) { + ((JSysCFG) cfg).build(declaration, newlyInsertedConstructors); + } + @Override protected CFG createCFG() { - return new JSysCFG(classGraph, newlyInsertedConstructors); + return new JSysCFG(); } @Override diff --git a/sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/JSysPDG.java b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/JSysPDG.java index abd225e4b1a66d09243c5b88eeb8a560a75cb5a0..487ed1d06cb7b59170c518f6b5ce51621e62ffa5 100644 --- a/sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/JSysPDG.java +++ b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/JSysPDG.java @@ -1,14 +1,10 @@ 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 implicitConstructors) { - this(new JSysCFG(classGraph, implicitConstructors)); + public JSysPDG() { + this(new JSysCFG()); } public JSysPDG(JSysCFG cfg) { diff --git a/sdg-core/src/main/java/es/upv/mist/slicing/graphs/sdg/InterproceduralDefinitionFinder.java b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/sdg/InterproceduralDefinitionFinder.java index 7ad47b30b21c3b36c8db770a015021ddc6972a02..b9ca7713f272b299bbadd6225da8d00c4de79c6c 100644 --- a/sdg-core/src/main/java/es/upv/mist/slicing/graphs/sdg/InterproceduralDefinitionFinder.java +++ b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/sdg/InterproceduralDefinitionFinder.java @@ -12,9 +12,7 @@ import es.upv.mist.slicing.nodes.VariableAction; import es.upv.mist.slicing.nodes.io.ActualIONode; import es.upv.mist.slicing.nodes.io.FormalIONode; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; +import java.util.*; import java.util.stream.Stream; /** An interprocedural definition finder, which adds the associated actions to formal and actual nodes in the CFGs. */ @@ -37,7 +35,7 @@ public class InterproceduralDefinitionFinder extends InterproceduralActionFinder @Override protected void handleActualAction(CallGraph.Edge edge, VariableAction.Definition def) { - Set movables = new HashSet<>(); + List movables = new LinkedList<>(); GraphNode graphNode = edge.getGraphNode(); ResolvedValueDeclaration resolved = def.getResolvedValueDeclaration(); if (resolved.isParameter()) { diff --git a/sdg-core/src/main/java/es/upv/mist/slicing/graphs/sdg/InterproceduralUsageFinder.java b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/sdg/InterproceduralUsageFinder.java index 20919e905722aeb1937a475fd915d9a53747c76a..979200fa12e0d87c6099d6849493687921a9e295 100644 --- a/sdg-core/src/main/java/es/upv/mist/slicing/graphs/sdg/InterproceduralUsageFinder.java +++ b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/sdg/InterproceduralUsageFinder.java @@ -12,9 +12,9 @@ import es.upv.mist.slicing.nodes.VariableVisitor; import es.upv.mist.slicing.nodes.io.ActualIONode; import es.upv.mist.slicing.nodes.io.FormalIONode; -import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; import java.util.Map; -import java.util.Set; import java.util.function.Predicate; import java.util.stream.Stream; @@ -34,7 +34,7 @@ public class InterproceduralUsageFinder extends InterproceduralActionFinder edge, VariableAction.Usage use) { - Set movables = new HashSet<>(); + List movables = new LinkedList<>(); GraphNode graphNode = edge.getGraphNode(); ResolvedValueDeclaration resolved = use.getResolvedValueDeclaration(); if (resolved.isParameter()) { 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 4e6209b07d56d8aa64b4e83f8559f2e8c03b184a..a5767b2bbc3f9734a209ec4fb310f978c650fea0 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 @@ -28,9 +28,9 @@ import es.upv.mist.slicing.slicing.*; import es.upv.mist.slicing.utils.ASTUtils; import java.util.Collection; +import java.util.List; import java.util.Map; import java.util.Optional; -import java.util.Set; import static es.upv.mist.slicing.graphs.cfg.CFGBuilder.VARIABLE_NAME_OUTPUT; @@ -129,19 +129,24 @@ public class SDG extends Graph implements Sliceable, Buildable declaration, CFG cfg) { + cfg.build(declaration); + } + /** Create call graph from the list of compilation units. */ protected CallGraph createCallGraph(NodeList nodeList) { CallGraph callGraph = new CallGraph(cfgMap, classGraph); @@ -176,7 +181,7 @@ public class SDG extends Graph implements Sliceable, Buildable implements Comparable> { } /** Append or prepend the given set of actions to the actions of the given call. */ - public void addActionsForCall(Set actions, Resolvable call, boolean prepend) { + public void addActionsForCall(List actions, Resolvable call, boolean prepend) { for (int i = 0; i < variableActions.size(); i++) { VariableAction var = variableActions.get(i); if (var instanceof VariableAction.CallMarker) { diff --git a/sdg-core/src/main/java/es/upv/mist/slicing/nodes/VariableVisitor.java b/sdg-core/src/main/java/es/upv/mist/slicing/nodes/VariableVisitor.java index fff957332d8278f2dc0b96d47c7ea18fe8bd94f9..276207cc015fd64f7807040a465de87311e5deb3 100644 --- a/sdg-core/src/main/java/es/upv/mist/slicing/nodes/VariableVisitor.java +++ b/sdg-core/src/main/java/es/upv/mist/slicing/nodes/VariableVisitor.java @@ -20,8 +20,8 @@ import es.upv.mist.slicing.utils.Logger; import java.util.Deque; import java.util.LinkedList; +import java.util.List; import java.util.Objects; -import java.util.Set; import static es.upv.mist.slicing.graphs.cfg.CFGBuilder.VARIABLE_NAME_OUTPUT; @@ -272,7 +272,7 @@ public class VariableVisitor extends GraphNodeContentVisitor> getClassInit(ClassOrInterfaceDeclaration clazz, boolean isStatic) { + List> classInit = new LinkedList<>(); + for (BodyDeclaration member : clazz.getMembers()) { + if (member.isFieldDeclaration() && + member.asFieldDeclaration().isStatic() == isStatic) + classInit.add(member); + if (member.isInitializerDeclaration() && + member.asInitializerDeclaration().isStatic() == isStatic) + classInit.add(member); + } + return classInit; + } }