From 955981f3df3b1ed989344d816603016db1a0fcd5 Mon Sep 17 00:00:00 2001 From: serperu Date: Wed, 20 Jan 2021 12:30:07 +0100 Subject: [PATCH 01/33] Super call added & JSysDG --- .../java/es/upv/mist/slicing/cli/Slicer.java | 2 + .../slicing/graphs/jsysdg/ImplicitNode.java | 11 +++ .../mist/slicing/graphs/jsysdg/JSysCFG.java | 34 +++++++++ .../slicing/graphs/jsysdg/JSysCFGBuilder.java | 76 +++++++++++++++++++ .../mist/slicing/graphs/jsysdg/JSysDG.java | 6 ++ .../mist/slicing/graphs/jsysdg/JSysPDG.java | 14 ++++ .../es/upv/mist/slicing/graphs/sdg/SDG.java | 6 +- .../es/upv/mist/slicing/slicing/Slice.java | 12 ++- 8 files changed, 156 insertions(+), 5 deletions(-) create mode 100644 sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/ImplicitNode.java create mode 100644 sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/JSysCFG.java create mode 100644 sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/JSysCFGBuilder.java create mode 100644 sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/JSysDG.java create mode 100644 sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/JSysPDG.java diff --git a/sdg-cli/src/main/java/es/upv/mist/slicing/cli/Slicer.java b/sdg-cli/src/main/java/es/upv/mist/slicing/cli/Slicer.java index b8893f0..e55a284 100644 --- a/sdg-cli/src/main/java/es/upv/mist/slicing/cli/Slicer.java +++ b/sdg-cli/src/main/java/es/upv/mist/slicing/cli/Slicer.java @@ -10,6 +10,7 @@ import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSol import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver; import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver; import es.upv.mist.slicing.graphs.augmented.ASDG; +import es.upv.mist.slicing.graphs.jsysdg.JSysDG; import es.upv.mist.slicing.graphs.augmented.PSDG; import es.upv.mist.slicing.graphs.exceptionsensitive.ESSDG; import es.upv.mist.slicing.graphs.sdg.SDG; @@ -236,6 +237,7 @@ public class Slicer { case "ASDG": sdg = new ASDG(); break; case "PSDG": sdg = new PSDG(); break; case "ESSDG": sdg = new ESSDG(); break; + case "JSysDG": sdg = new JSysDG(); break; default: throw new IllegalArgumentException("Unknown type of graph. Available graphs are SDG, ASDG, PSDG, ESSDG"); } diff --git a/sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/ImplicitNode.java b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/ImplicitNode.java new file mode 100644 index 0000000..8b70d65 --- /dev/null +++ b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/ImplicitNode.java @@ -0,0 +1,11 @@ +package es.upv.mist.slicing.graphs.jsysdg; + +import com.github.javaparser.ast.Node; +import es.upv.mist.slicing.nodes.SyntheticNode; + +// TODO: Concretar más el tipo T del nodo (Node es muy general). Por ahora seria solo ExplicitConstructorInvocationStmt +public class ImplicitNode extends SyntheticNode { + protected ImplicitNode(String instruction, Node astNode) { + super(instruction, astNode); + } +} 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 new file mode 100644 index 0000000..0d011ba --- /dev/null +++ b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/JSysCFG.java @@ -0,0 +1,34 @@ +package es.upv.mist.slicing.graphs.jsysdg; + +import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration; +import es.upv.mist.slicing.graphs.ClassGraph; +import es.upv.mist.slicing.graphs.cfg.CFGBuilder; +import es.upv.mist.slicing.graphs.exceptionsensitive.ESCFG; + +public class JSysCFG extends ESCFG { + + /** ClassGraph associated to the Method represented by the CFG */ + protected ClassGraph clg; + + public JSysCFG(ClassGraph clg){ + super(); + this.clg = clg; + } + + public ClassGraph getClassGraph(){ + return this.clg; + } + + protected CFGBuilder newCFGBuilder() { + return new JSysCFGBuilder(this); + } + + + /** Obtains the Javaparser Node corresponding to the class where the CFG is contained */ + public ClassOrInterfaceDeclaration getDeclarationClass() { + assert rootNode != null; + if (!(rootNode.getAstNode().getParentNode().get() instanceof ClassOrInterfaceDeclaration)) + throw new IllegalStateException("The Method declaration is not directly inside a Class Declaration"); + return (ClassOrInterfaceDeclaration) rootNode.getAstNode().getParentNode().get(); + } +} diff --git a/sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/JSysCFGBuilder.java b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/JSysCFGBuilder.java new file mode 100644 index 0000000..3ff40ca --- /dev/null +++ b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/JSysCFGBuilder.java @@ -0,0 +1,76 @@ +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.*; +import com.github.javaparser.ast.stmt.ExplicitConstructorInvocationStmt; +import es.upv.mist.slicing.graphs.augmented.ACFGBuilder; +import es.upv.mist.slicing.nodes.io.MethodExitNode; +import es.upv.mist.slicing.utils.ASTUtils; + +import java.util.LinkedList; +import java.util.List; + +public class JSysCFGBuilder extends ACFGBuilder { + + /** List of inserted super calls in Javaparser AST to process them as Implicit Nodes (@ImplicitNode)*/ + protected List methodInsertedInstructions = new LinkedList<>(); + + protected JSysCFGBuilder(JSysCFG graph) { + super(graph); + } + + /** Esto se llama porque lo hemos insertado fantasma o porque existe. A continuacion se inserta el codigo dynInit */ + @Override + public void visit(ExplicitConstructorInvocationStmt n, Void arg) { + + // 1. Create new super call if not present + if (methodInsertedInstructions.contains(n)){ + ImplicitNode node = new ImplicitNode(n.toString(), n); // TODO: implementar + connectTo(node); + } + else { + connectTo(n); + } + // 2. Insert dynamic class code + // TODO + + } + + @Override + public void visit(FieldDeclaration n, Void arg){ + connectTo(n); + } + + @Override + public void visit(InitializerDeclaration n, Void arg){ + // TODO + } + + + @Override + protected void visitCallableDeclaration(CallableDeclaration callableDeclaration, Void arg) { + graph.buildRootNode(callableDeclaration); + hangingNodes.add(graph.getRootNode()); + + // 1. Check if first is super (only if constructor) + // then, create and build super() + if (callableDeclaration instanceof ConstructorDeclaration){ + ConstructorDeclaration declaration = (ConstructorDeclaration) callableDeclaration; + if (!ASTUtils.constructorHasExplicitConstructorInvocation(declaration)){ + ExplicitConstructorInvocationStmt superCall = + new ExplicitConstructorInvocationStmt(null, null, false, null, new NodeList<>()); + methodInsertedInstructions.add(superCall); + declaration.getBody().addStatement(0, superCall); + } + } + + ASTUtils.getCallableBody(callableDeclaration).accept(this, arg); + returnList.stream().filter(node -> !hangingNodes.contains(node)).forEach(hangingNodes::add); + + MethodExitNode exit = new MethodExitNode(callableDeclaration); + graph.addVertex(exit); + addMethodOutput(callableDeclaration, exit); + connectTo(exit); + } +} 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 new file mode 100644 index 0000000..f02b7dd --- /dev/null +++ b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/JSysDG.java @@ -0,0 +1,6 @@ +package es.upv.mist.slicing.graphs.jsysdg; + +import es.upv.mist.slicing.graphs.exceptionsensitive.ESSDG; + +public class JSysDG extends ESSDG { +} 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 new file mode 100644 index 0000000..509675d --- /dev/null +++ b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/JSysPDG.java @@ -0,0 +1,14 @@ +package es.upv.mist.slicing.graphs.jsysdg; + +import es.upv.mist.slicing.graphs.ClassGraph; +import es.upv.mist.slicing.graphs.exceptionsensitive.ESPDG; + +public class JSysPDG extends ESPDG { + public JSysPDG(ClassGraph clg) { + this(new JSysCFG(clg)); + } + + public JSysPDG(JSysCFG oocfg) { + super(oocfg); + } +} 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 aaf67c9..f8c7c78 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 @@ -106,9 +106,9 @@ public class SDG extends Graph implements Sliceable, Buildable nodeList) { // 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 + buildCFGs(nodeList, classGraph); // 1 + CallGraph callGraph = createCallGraph(nodeList); // 2 dataFlowAnalysis(callGraph); // 3 buildAndCopyPDGs(); // 4 connectCalls(callGraph); // 5 @@ -116,7 +116,7 @@ public class SDG extends Graph implements Sliceable, Buildable nodeList) { + protected void buildCFGs(NodeList nodeList, ClassGraph clg) { nodeList.accept(new VoidVisitorAdapter() { @Override public void visit(MethodDeclaration n, Void arg) { diff --git a/sdg-core/src/main/java/es/upv/mist/slicing/slicing/Slice.java b/sdg-core/src/main/java/es/upv/mist/slicing/slicing/Slice.java index 4dc751a..5be96c2 100644 --- a/sdg-core/src/main/java/es/upv/mist/slicing/slicing/Slice.java +++ b/sdg-core/src/main/java/es/upv/mist/slicing/slicing/Slice.java @@ -4,6 +4,7 @@ import com.github.javaparser.ast.CompilationUnit; import com.github.javaparser.ast.Node; import com.github.javaparser.ast.NodeList; import com.github.javaparser.ast.visitor.CloneVisitor; +import es.upv.mist.slicing.graphs.jsysdg.ImplicitNode; import es.upv.mist.slicing.nodes.GraphNode; import java.util.*; @@ -20,8 +21,10 @@ public class Slice { /** Add a node to this slice. */ public void add(GraphNode node) { assert !map.containsKey(node.getId()); - map.put(node.getId(), node); - nodes.add(node.getAstNode()); + if (this.isASTOriginalNode(node)) { + map.put(node.getId(), node); + nodes.add(node.getAstNode()); + } } /** Add multiple nodes to this slice. */ @@ -81,4 +84,9 @@ public class Slice { } return cus; } + + /** Returns whether a node was in the original AST or was added by instrumentation. */ + private boolean isASTOriginalNode(GraphNode node){ + return !(node instanceof ImplicitNode); + } } -- GitLab From 83db387653bde30312a9ebf781f77a12e0dd8be2 Mon Sep 17 00:00:00 2001 From: serperu Date: Wed, 20 Jan 2021 12:31:37 +0100 Subject: [PATCH 02/33] Added dynamic init & VariableActions for field declarations --- .../upv/mist/slicing/graphs/ClassGraph.java | 35 +++++++++++++++++-- .../graphs/GraphNodeContentVisitor.java | 4 +-- .../slicing/graphs/jsysdg/JSysCFGBuilder.java | 4 ++- .../mist/slicing/nodes/VariableVisitor.java | 17 +++++++++ .../es/upv/mist/slicing/utils/ASTUtils.java | 5 +++ 5 files changed, 59 insertions(+), 6 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 d9819bc..beeeba7 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,13 +1,13 @@ 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; 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.utils.ASTUtils; import es.upv.mist.slicing.utils.Utils; import org.jgrapht.graph.DefaultEdge; @@ -90,7 +90,6 @@ public class ClassGraph extends DirectedPseudograph> getStaticInit(String className){ + return getClassInit(className,true); + } + + /** Returns a NodeList with the dynamic FieldDeclarations and InitializerDeclarations of the given class */ + public NodeList> getDynInit(String className){ + return getClassInit(className,false); + } + + /** Returns a NodeList with FieldDeclarations and InitializerDeclarations static/dynamic items of the given class */ + private NodeList> getClassInit(String className, Boolean isStatic){ + Vertex classNode = vertexDeclarationMap.get(className); + NodeList> members = classNode.declaration.asClassOrInterfaceDeclaration().getMembers(); + NodeList> classInit = new NodeList<>(); + 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 classInit; + } } diff --git a/sdg-core/src/main/java/es/upv/mist/slicing/graphs/GraphNodeContentVisitor.java b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/GraphNodeContentVisitor.java index fa0e685..282f733 100644 --- a/sdg-core/src/main/java/es/upv/mist/slicing/graphs/GraphNodeContentVisitor.java +++ b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/GraphNodeContentVisitor.java @@ -87,9 +87,7 @@ public class GraphNodeContentVisitor extends VoidVisitorAdapter { } @Override - public void visit(FieldDeclaration n, A arg) { - throw new UnsupportedOperationException(); - } + public void visit(FieldDeclaration n, A arg) { super.visit(n, arg); } @Override public void visit(ForEachStmt n, A arg) { diff --git a/sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/JSysCFGBuilder.java b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/JSysCFGBuilder.java index 3ff40ca..05755fc 100644 --- a/sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/JSysCFGBuilder.java +++ b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/JSysCFGBuilder.java @@ -33,7 +33,9 @@ public class JSysCFGBuilder extends ACFGBuilder { connectTo(n); } // 2. Insert dynamic class code - // TODO + ClassOrInterfaceDeclaration containerClass = ((JSysCFG) graph).getDeclarationClass(); + NodeList> dynInitList = ((JSysCFG) graph).getClassGraph().getDynInit(containerClass.getNameAsString()); + dynInitList.accept(this, arg); } 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 fffef92..49415de 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 @@ -1,5 +1,6 @@ package es.upv.mist.slicing.nodes; +import com.github.javaparser.ast.body.FieldDeclaration; import com.github.javaparser.ast.body.Parameter; import com.github.javaparser.ast.body.VariableDeclarator; import com.github.javaparser.ast.expr.*; @@ -174,6 +175,22 @@ public class VariableVisitor extends GraphNodeContentVisitor call, GraphNode graphNode) { return shouldVisitArgumentsForMethodCalls(call) || graphNode == null; } + + public static boolean constructorHasExplicitConstructorInvocation(ConstructorDeclaration declaration) { + return !getCallableBody(declaration).getStatements().isEmpty() && + getCallableBody(declaration).getStatements().getFirst().get() instanceof ExplicitConstructorInvocationStmt; + } } -- GitLab From 1442240ac531b460412cabb34cd3c57acef127d4 Mon Sep 17 00:00:00 2001 From: serperu Date: Wed, 20 Jan 2021 16:06:36 +0100 Subject: [PATCH 03/33] Change nodeList into List & CFG Arcs generation fix --- .../java/es/upv/mist/slicing/cli/Slicer.java | 2 +- .../upv/mist/slicing/graphs/ClassGraph.java | 16 ++--- .../graphs/exceptionsensitive/ESSDG.java | 2 +- .../slicing/graphs/jsysdg/JSysCFGBuilder.java | 14 ++--- .../mist/slicing/graphs/jsysdg/JSysDG.java | 58 +++++++++++++++++++ .../mist/slicing/graphs/jsysdg/JSysPDG.java | 4 +- .../es/upv/mist/slicing/graphs/sdg/SDG.java | 8 ++- 7 files changed, 79 insertions(+), 25 deletions(-) diff --git a/sdg-cli/src/main/java/es/upv/mist/slicing/cli/Slicer.java b/sdg-cli/src/main/java/es/upv/mist/slicing/cli/Slicer.java index 7157a5b..8215f24 100644 --- a/sdg-cli/src/main/java/es/upv/mist/slicing/cli/Slicer.java +++ b/sdg-cli/src/main/java/es/upv/mist/slicing/cli/Slicer.java @@ -228,7 +228,7 @@ public class Slicer { } SDG sdg; - switch (cliOpts.getOptionValue("type", "ESSDG")) { + switch (cliOpts.getOptionValue("type", "JSysDG")) { case "SDG": sdg = new SDG(); break; case "ASDG": sdg = new ASDG(); break; case "PSDG": sdg = new PSDG(); break; 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 04c91b8..a242eb7 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 @@ -180,21 +180,21 @@ public class ClassGraph extends DirectedPseudograph> getStaticInit(String className){ + /** Returns a List with the static FieldDeclarations and InitializerDeclarations of the given class */ + public List> getStaticInit(String className){ return getClassInit(className,true); } - /** Returns a NodeList with the dynamic FieldDeclarations and InitializerDeclarations of the given class */ - public NodeList> getDynInit(String className){ + /** Returns a List with the dynamic FieldDeclarations and InitializerDeclarations of the given class */ + public List> getDynInit(String className){ return getClassInit(className,false); } - /** Returns a NodeList with FieldDeclarations and InitializerDeclarations static/dynamic items of the given class */ - private NodeList> getClassInit(String className, Boolean isStatic){ + /** 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); - NodeList> members = classNode.declaration.asClassOrInterfaceDeclaration().getMembers(); - NodeList> classInit = new NodeList<>(); + List> members = classNode.declaration.asClassOrInterfaceDeclaration().getMembers(); + List> classInit = new LinkedList<>(); for (BodyDeclaration member : members) { if (member instanceof CallableDeclaration) continue; diff --git a/sdg-core/src/main/java/es/upv/mist/slicing/graphs/exceptionsensitive/ESSDG.java b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/exceptionsensitive/ESSDG.java index 02d1214..aa21e52 100644 --- a/sdg-core/src/main/java/es/upv/mist/slicing/graphs/exceptionsensitive/ESSDG.java +++ b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/exceptionsensitive/ESSDG.java @@ -32,7 +32,7 @@ public class ESSDG extends PSDG { /** Populates an ESSDG, using ESPDG and ESCFG as default graphs. * @see PSDG.Builder * @see ExceptionSensitiveCallConnector */ - class Builder extends PSDG.Builder { + protected class Builder extends PSDG.Builder { @Override protected CFG createCFG() { return new ESCFG(); diff --git a/sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/JSysCFGBuilder.java b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/JSysCFGBuilder.java index 05755fc..204bc10 100644 --- a/sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/JSysCFGBuilder.java +++ b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/JSysCFGBuilder.java @@ -26,7 +26,8 @@ public class JSysCFGBuilder extends ACFGBuilder { // 1. Create new super call if not present if (methodInsertedInstructions.contains(n)){ - ImplicitNode node = new ImplicitNode(n.toString(), n); // TODO: implementar + ImplicitNode node = new ImplicitNode(n.toString(), n); + graph.addVertex(node); connectTo(node); } else { @@ -34,9 +35,8 @@ public class JSysCFGBuilder extends ACFGBuilder { } // 2. Insert dynamic class code ClassOrInterfaceDeclaration containerClass = ((JSysCFG) graph).getDeclarationClass(); - NodeList> dynInitList = ((JSysCFG) graph).getClassGraph().getDynInit(containerClass.getNameAsString()); - dynInitList.accept(this, arg); - + List> dynInitList = ((JSysCFG) graph).getClassGraph().getDynInit(containerClass.getNameAsString()); + dynInitList.forEach(node -> node.accept(this, arg)); } @Override @@ -44,12 +44,6 @@ public class JSysCFGBuilder extends ACFGBuilder { connectTo(n); } - @Override - public void visit(InitializerDeclaration n, Void arg){ - // TODO - } - - @Override protected void visitCallableDeclaration(CallableDeclaration callableDeclaration, Void arg) { graph.buildRootNode(callableDeclaration); 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 f02b7dd..0f838f4 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 @@ -1,6 +1,64 @@ package es.upv.mist.slicing.graphs.jsysdg; +import com.github.javaparser.ast.CompilationUnit; +import com.github.javaparser.ast.NodeList; +import es.upv.mist.slicing.arcs.sdg.ReturnArc; +import es.upv.mist.slicing.graphs.CallGraph; +import es.upv.mist.slicing.graphs.ClassGraph; +import es.upv.mist.slicing.graphs.augmented.PSDG; +import es.upv.mist.slicing.graphs.cfg.CFG; import es.upv.mist.slicing.graphs.exceptionsensitive.ESSDG; +import es.upv.mist.slicing.graphs.exceptionsensitive.ExceptionSensitiveCallConnector; +import es.upv.mist.slicing.graphs.pdg.PDG; +import es.upv.mist.slicing.nodes.exceptionsensitive.ExitNode; +import es.upv.mist.slicing.nodes.exceptionsensitive.ReturnNode; +import es.upv.mist.slicing.slicing.ExceptionSensitiveSlicingAlgorithm; +import es.upv.mist.slicing.slicing.SlicingAlgorithm; public class JSysDG extends ESSDG { + + @Override + protected JSysDG.Builder createBuilder() { + return new JSysDG.Builder(); + } + + @Override + protected SlicingAlgorithm createSlicingAlgorithm() { + return new ExceptionSensitiveSlicingAlgorithm(this); + } + + public void addReturnArc(ExitNode source, ReturnNode target) { + addEdge(source, target, new ReturnArc()); + } + + /** Populates an ESSDG, using ESPDG and ESCFG as default graphs. + * @see PSDG.Builder + * @see ExceptionSensitiveCallConnector */ + class Builder extends ESSDG.Builder { + + private ClassGraph classGraph; + + @Override + public void build(NodeList nodeList) { + // See creation strategy at http://kaz2.dsic.upv.es:3000/Fzg46cQvT1GzHQG9hFnP1g#Using-data-flow-in-the-SDG + classGraph = createClassGraph(nodeList); + buildCFGs(nodeList); // 1 + CallGraph callGraph = createCallGraph(nodeList); // 2 + dataFlowAnalysis(callGraph); // 3 + buildAndCopyPDGs(); // 4 + connectCalls(callGraph); // 5 + createSummaryArcs(callGraph); // 6 + } + + @Override + protected CFG createCFG() { + return new JSysCFG(classGraph); + } + + @Override + protected PDG createPDG(CFG cfg) { + assert cfg instanceof JSysCFG; + return new JSysPDG((JSysCFG) cfg); + } + } } 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 509675d..f86f92d 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 @@ -8,7 +8,7 @@ public class JSysPDG extends ESPDG { this(new JSysCFG(clg)); } - public JSysPDG(JSysCFG oocfg) { - super(oocfg); + public JSysPDG(JSysCFG cfg) { + super(cfg); } } 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 3dbd94a..7284f3d 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 @@ -109,8 +109,7 @@ public class SDG extends Graph implements Sliceable, Buildable nodeList) { // See creation strategy at http://kaz2.dsic.upv.es:3000/Fzg46cQvT1GzHQG9hFnP1g#Using-data-flow-in-the-SDG - ClassGraph classGraph = createClassGraph(nodeList); // TODO: Update order and creation strategy - buildCFGs(nodeList, classGraph); // 1 + buildCFGs(nodeList); // 1 CallGraph callGraph = createCallGraph(nodeList); // 2 dataFlowAnalysis(callGraph); // 3 buildAndCopyPDGs(); // 4 @@ -119,7 +118,7 @@ public class SDG extends Graph implements Sliceable, Buildable nodeList, ClassGraph clg) { + protected void buildCFGs(NodeList nodeList) { nodeList.accept(new VoidVisitorAdapter() { @Override public void visit(MethodDeclaration n, Void arg) { @@ -132,6 +131,9 @@ public class SDG extends Graph implements Sliceable, Buildable nod : cfg.vertexSet()){ + System.out.println(); + } cfgMap.put(n, cfg); } }, null); -- GitLab From dcb6221634b784b0e54aa49186e73c2e9925f415 Mon Sep 17 00:00:00 2001 From: serperu Date: Wed, 20 Jan 2021 12:30:07 +0100 Subject: [PATCH 04/33] Super call added & JSysDG --- .../java/es/upv/mist/slicing/cli/Slicer.java | 2 + .../slicing/graphs/jsysdg/ImplicitNode.java | 11 +++ .../mist/slicing/graphs/jsysdg/JSysCFG.java | 34 +++++++++ .../slicing/graphs/jsysdg/JSysCFGBuilder.java | 76 +++++++++++++++++++ .../mist/slicing/graphs/jsysdg/JSysDG.java | 6 ++ .../mist/slicing/graphs/jsysdg/JSysPDG.java | 14 ++++ .../es/upv/mist/slicing/graphs/sdg/SDG.java | 4 +- .../es/upv/mist/slicing/slicing/Slice.java | 12 ++- 8 files changed, 155 insertions(+), 4 deletions(-) create mode 100644 sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/ImplicitNode.java create mode 100644 sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/JSysCFG.java create mode 100644 sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/JSysCFGBuilder.java create mode 100644 sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/JSysDG.java create mode 100644 sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/JSysPDG.java diff --git a/sdg-cli/src/main/java/es/upv/mist/slicing/cli/Slicer.java b/sdg-cli/src/main/java/es/upv/mist/slicing/cli/Slicer.java index 460161a..a39c064 100644 --- a/sdg-cli/src/main/java/es/upv/mist/slicing/cli/Slicer.java +++ b/sdg-cli/src/main/java/es/upv/mist/slicing/cli/Slicer.java @@ -7,6 +7,7 @@ import com.github.javaparser.ast.comments.BlockComment; import com.github.javaparser.ast.nodeTypes.NodeWithName; import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver; import es.upv.mist.slicing.graphs.augmented.ASDG; +import es.upv.mist.slicing.graphs.jsysdg.JSysDG; import es.upv.mist.slicing.graphs.augmented.PSDG; import es.upv.mist.slicing.graphs.exceptionsensitive.ESSDG; import es.upv.mist.slicing.graphs.sdg.SDG; @@ -237,6 +238,7 @@ public class Slicer { case "ASDG": sdg = new ASDG(); break; case "PSDG": sdg = new PSDG(); break; case "ESSDG": sdg = new ESSDG(); break; + case "JSysDG": sdg = new JSysDG(); break; default: throw new IllegalArgumentException("Unknown type of graph. Available graphs are SDG, ASDG, PSDG, ESSDG"); } diff --git a/sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/ImplicitNode.java b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/ImplicitNode.java new file mode 100644 index 0000000..8b70d65 --- /dev/null +++ b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/ImplicitNode.java @@ -0,0 +1,11 @@ +package es.upv.mist.slicing.graphs.jsysdg; + +import com.github.javaparser.ast.Node; +import es.upv.mist.slicing.nodes.SyntheticNode; + +// TODO: Concretar más el tipo T del nodo (Node es muy general). Por ahora seria solo ExplicitConstructorInvocationStmt +public class ImplicitNode extends SyntheticNode { + protected ImplicitNode(String instruction, Node astNode) { + super(instruction, astNode); + } +} 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 new file mode 100644 index 0000000..0d011ba --- /dev/null +++ b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/JSysCFG.java @@ -0,0 +1,34 @@ +package es.upv.mist.slicing.graphs.jsysdg; + +import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration; +import es.upv.mist.slicing.graphs.ClassGraph; +import es.upv.mist.slicing.graphs.cfg.CFGBuilder; +import es.upv.mist.slicing.graphs.exceptionsensitive.ESCFG; + +public class JSysCFG extends ESCFG { + + /** ClassGraph associated to the Method represented by the CFG */ + protected ClassGraph clg; + + public JSysCFG(ClassGraph clg){ + super(); + this.clg = clg; + } + + public ClassGraph getClassGraph(){ + return this.clg; + } + + protected CFGBuilder newCFGBuilder() { + return new JSysCFGBuilder(this); + } + + + /** Obtains the Javaparser Node corresponding to the class where the CFG is contained */ + public ClassOrInterfaceDeclaration getDeclarationClass() { + assert rootNode != null; + if (!(rootNode.getAstNode().getParentNode().get() instanceof ClassOrInterfaceDeclaration)) + throw new IllegalStateException("The Method declaration is not directly inside a Class Declaration"); + return (ClassOrInterfaceDeclaration) rootNode.getAstNode().getParentNode().get(); + } +} diff --git a/sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/JSysCFGBuilder.java b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/JSysCFGBuilder.java new file mode 100644 index 0000000..3ff40ca --- /dev/null +++ b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/JSysCFGBuilder.java @@ -0,0 +1,76 @@ +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.*; +import com.github.javaparser.ast.stmt.ExplicitConstructorInvocationStmt; +import es.upv.mist.slicing.graphs.augmented.ACFGBuilder; +import es.upv.mist.slicing.nodes.io.MethodExitNode; +import es.upv.mist.slicing.utils.ASTUtils; + +import java.util.LinkedList; +import java.util.List; + +public class JSysCFGBuilder extends ACFGBuilder { + + /** List of inserted super calls in Javaparser AST to process them as Implicit Nodes (@ImplicitNode)*/ + protected List methodInsertedInstructions = new LinkedList<>(); + + protected JSysCFGBuilder(JSysCFG graph) { + super(graph); + } + + /** Esto se llama porque lo hemos insertado fantasma o porque existe. A continuacion se inserta el codigo dynInit */ + @Override + public void visit(ExplicitConstructorInvocationStmt n, Void arg) { + + // 1. Create new super call if not present + if (methodInsertedInstructions.contains(n)){ + ImplicitNode node = new ImplicitNode(n.toString(), n); // TODO: implementar + connectTo(node); + } + else { + connectTo(n); + } + // 2. Insert dynamic class code + // TODO + + } + + @Override + public void visit(FieldDeclaration n, Void arg){ + connectTo(n); + } + + @Override + public void visit(InitializerDeclaration n, Void arg){ + // TODO + } + + + @Override + protected void visitCallableDeclaration(CallableDeclaration callableDeclaration, Void arg) { + graph.buildRootNode(callableDeclaration); + hangingNodes.add(graph.getRootNode()); + + // 1. Check if first is super (only if constructor) + // then, create and build super() + if (callableDeclaration instanceof ConstructorDeclaration){ + ConstructorDeclaration declaration = (ConstructorDeclaration) callableDeclaration; + if (!ASTUtils.constructorHasExplicitConstructorInvocation(declaration)){ + ExplicitConstructorInvocationStmt superCall = + new ExplicitConstructorInvocationStmt(null, null, false, null, new NodeList<>()); + methodInsertedInstructions.add(superCall); + declaration.getBody().addStatement(0, superCall); + } + } + + ASTUtils.getCallableBody(callableDeclaration).accept(this, arg); + returnList.stream().filter(node -> !hangingNodes.contains(node)).forEach(hangingNodes::add); + + MethodExitNode exit = new MethodExitNode(callableDeclaration); + graph.addVertex(exit); + addMethodOutput(callableDeclaration, exit); + connectTo(exit); + } +} 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 new file mode 100644 index 0000000..f02b7dd --- /dev/null +++ b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/JSysDG.java @@ -0,0 +1,6 @@ +package es.upv.mist.slicing.graphs.jsysdg; + +import es.upv.mist.slicing.graphs.exceptionsensitive.ESSDG; + +public class JSysDG extends ESSDG { +} 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 new file mode 100644 index 0000000..509675d --- /dev/null +++ b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/JSysPDG.java @@ -0,0 +1,14 @@ +package es.upv.mist.slicing.graphs.jsysdg; + +import es.upv.mist.slicing.graphs.ClassGraph; +import es.upv.mist.slicing.graphs.exceptionsensitive.ESPDG; + +public class JSysPDG extends ESPDG { + public JSysPDG(ClassGraph clg) { + this(new JSysCFG(clg)); + } + + public JSysPDG(JSysCFG oocfg) { + super(oocfg); + } +} 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 35d6cee..fcedcb7 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 @@ -109,8 +109,8 @@ public class SDG extends Graph implements Sliceable, Buildable nodeList) { // See creation strategy at http://kaz2.dsic.upv.es:3000/Fzg46cQvT1GzHQG9hFnP1g#Using-data-flow-in-the-SDG - buildCFGs(nodeList); // 1 ClassGraph classGraph = createClassGraph(nodeList); // TODO: Update order and creation strategy + buildCFGs(nodeList, classGraph); // 1 CallGraph callGraph = createCallGraph(nodeList, classGraph); // 2 dataFlowAnalysis(callGraph); // 3 buildAndCopyPDGs(); // 4 @@ -119,7 +119,7 @@ public class SDG extends Graph implements Sliceable, Buildable nodeList) { + protected void buildCFGs(NodeList nodeList, ClassGraph clg) { nodeList.accept(new VoidVisitorAdapter() { @Override public void visit(MethodDeclaration n, Void arg) { diff --git a/sdg-core/src/main/java/es/upv/mist/slicing/slicing/Slice.java b/sdg-core/src/main/java/es/upv/mist/slicing/slicing/Slice.java index b79d439..b28d9d8 100644 --- a/sdg-core/src/main/java/es/upv/mist/slicing/slicing/Slice.java +++ b/sdg-core/src/main/java/es/upv/mist/slicing/slicing/Slice.java @@ -4,6 +4,7 @@ import com.github.javaparser.ast.CompilationUnit; import com.github.javaparser.ast.Node; import com.github.javaparser.ast.NodeList; import com.github.javaparser.ast.visitor.CloneVisitor; +import es.upv.mist.slicing.graphs.jsysdg.ImplicitNode; import es.upv.mist.slicing.nodes.GraphNode; import es.upv.mist.slicing.utils.ASTUtils; import es.upv.mist.slicing.utils.NodeHashSet; @@ -22,8 +23,10 @@ public class Slice { /** Add a node to this slice. */ public void add(GraphNode node) { assert !map.containsKey(node.getId()); - map.put(node.getId(), node); - nodes.add(node.getAstNode()); + if (this.isASTOriginalNode(node)) { + map.put(node.getId(), node); + nodes.add(node.getAstNode()); + } } /** Add multiple nodes to this slice. */ @@ -83,4 +86,9 @@ public class Slice { } return cus; } + + /** Returns whether a node was in the original AST or was added by instrumentation. */ + private boolean isASTOriginalNode(GraphNode node){ + return !(node instanceof ImplicitNode); + } } -- GitLab From 37ec554b81e2752d3f5bfa83ee11af6a8015b9f3 Mon Sep 17 00:00:00 2001 From: serperu Date: Wed, 20 Jan 2021 12:31:37 +0100 Subject: [PATCH 05/33] Added dynamic init & VariableActions for field declarations --- .../upv/mist/slicing/graphs/ClassGraph.java | 34 ++++++++++++++++++- .../graphs/GraphNodeContentVisitor.java | 4 +-- .../slicing/graphs/jsysdg/JSysCFGBuilder.java | 4 ++- .../mist/slicing/nodes/VariableVisitor.java | 17 ++++++++++ .../es/upv/mist/slicing/utils/ASTUtils.java | 5 +++ 5 files changed, 59 insertions(+), 5 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 bd11813..bb07f44 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,6 +1,7 @@ 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; @@ -202,7 +203,6 @@ public class ClassGraph extends DirectedPseudograph> getStaticInit(String className){ + return getClassInit(className,true); + } + + /** Returns a NodeList with the dynamic FieldDeclarations and InitializerDeclarations of the given class */ + public NodeList> getDynInit(String className){ + return getClassInit(className,false); + } + + /** Returns a NodeList with FieldDeclarations and InitializerDeclarations static/dynamic items of the given class */ + private NodeList> getClassInit(String className, Boolean isStatic){ + Vertex classNode = vertexDeclarationMap.get(className); + NodeList> members = classNode.declaration.asClassOrInterfaceDeclaration().getMembers(); + NodeList> classInit = new NodeList<>(); + 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 classInit; + } + protected static class ClassArc extends Arc { /** An arc that connects a class with another one that inherits from it. */ protected static class Extends extends ClassArc {} diff --git a/sdg-core/src/main/java/es/upv/mist/slicing/graphs/GraphNodeContentVisitor.java b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/GraphNodeContentVisitor.java index fa0e685..282f733 100644 --- a/sdg-core/src/main/java/es/upv/mist/slicing/graphs/GraphNodeContentVisitor.java +++ b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/GraphNodeContentVisitor.java @@ -87,9 +87,7 @@ public class GraphNodeContentVisitor extends VoidVisitorAdapter { } @Override - public void visit(FieldDeclaration n, A arg) { - throw new UnsupportedOperationException(); - } + public void visit(FieldDeclaration n, A arg) { super.visit(n, arg); } @Override public void visit(ForEachStmt n, A arg) { diff --git a/sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/JSysCFGBuilder.java b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/JSysCFGBuilder.java index 3ff40ca..05755fc 100644 --- a/sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/JSysCFGBuilder.java +++ b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/JSysCFGBuilder.java @@ -33,7 +33,9 @@ public class JSysCFGBuilder extends ACFGBuilder { connectTo(n); } // 2. Insert dynamic class code - // TODO + ClassOrInterfaceDeclaration containerClass = ((JSysCFG) graph).getDeclarationClass(); + NodeList> dynInitList = ((JSysCFG) graph).getClassGraph().getDynInit(containerClass.getNameAsString()); + dynInitList.accept(this, arg); } 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 dd407e5..8faa522 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 @@ -1,6 +1,7 @@ package es.upv.mist.slicing.nodes; import com.github.javaparser.ast.Node; +import com.github.javaparser.ast.body.FieldDeclaration; import com.github.javaparser.ast.body.Parameter; import com.github.javaparser.ast.body.VariableDeclarator; import com.github.javaparser.ast.expr.*; @@ -213,6 +214,22 @@ public class VariableVisitor extends GraphNodeContentVisitor Date: Wed, 20 Jan 2021 16:06:36 +0100 Subject: [PATCH 06/33] Change nodeList into List & CFG Arcs generation fix --- .../java/es/upv/mist/slicing/cli/Slicer.java | 2 +- .../upv/mist/slicing/graphs/ClassGraph.java | 1 - .../graphs/exceptionsensitive/ESSDG.java | 2 +- .../slicing/graphs/jsysdg/JSysCFGBuilder.java | 14 ++--- .../mist/slicing/graphs/jsysdg/JSysDG.java | 58 +++++++++++++++++++ .../mist/slicing/graphs/jsysdg/JSysPDG.java | 4 +- .../es/upv/mist/slicing/graphs/sdg/SDG.java | 6 +- 7 files changed, 69 insertions(+), 18 deletions(-) diff --git a/sdg-cli/src/main/java/es/upv/mist/slicing/cli/Slicer.java b/sdg-cli/src/main/java/es/upv/mist/slicing/cli/Slicer.java index a39c064..1ad2452 100644 --- a/sdg-cli/src/main/java/es/upv/mist/slicing/cli/Slicer.java +++ b/sdg-cli/src/main/java/es/upv/mist/slicing/cli/Slicer.java @@ -233,7 +233,7 @@ public class Slicer { } SDG sdg; - switch (cliOpts.getOptionValue("type", "ESSDG")) { + switch (cliOpts.getOptionValue("type", "JSysDG")) { case "SDG": sdg = new SDG(); break; case "ASDG": sdg = new ASDG(); break; case "PSDG": sdg = new PSDG(); break; 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 bb07f44..1ac7dc6 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 @@ -270,7 +270,6 @@ public class ClassGraph extends DirectedPseudograph, CallGraph.Edge> getDOTExporter() { DOTExporter, CallGraph.Edge> dot = new DOTExporter<>(); diff --git a/sdg-core/src/main/java/es/upv/mist/slicing/graphs/exceptionsensitive/ESSDG.java b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/exceptionsensitive/ESSDG.java index 02d1214..aa21e52 100644 --- a/sdg-core/src/main/java/es/upv/mist/slicing/graphs/exceptionsensitive/ESSDG.java +++ b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/exceptionsensitive/ESSDG.java @@ -32,7 +32,7 @@ public class ESSDG extends PSDG { /** Populates an ESSDG, using ESPDG and ESCFG as default graphs. * @see PSDG.Builder * @see ExceptionSensitiveCallConnector */ - class Builder extends PSDG.Builder { + protected class Builder extends PSDG.Builder { @Override protected CFG createCFG() { return new ESCFG(); diff --git a/sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/JSysCFGBuilder.java b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/JSysCFGBuilder.java index 05755fc..204bc10 100644 --- a/sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/JSysCFGBuilder.java +++ b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/JSysCFGBuilder.java @@ -26,7 +26,8 @@ public class JSysCFGBuilder extends ACFGBuilder { // 1. Create new super call if not present if (methodInsertedInstructions.contains(n)){ - ImplicitNode node = new ImplicitNode(n.toString(), n); // TODO: implementar + ImplicitNode node = new ImplicitNode(n.toString(), n); + graph.addVertex(node); connectTo(node); } else { @@ -34,9 +35,8 @@ public class JSysCFGBuilder extends ACFGBuilder { } // 2. Insert dynamic class code ClassOrInterfaceDeclaration containerClass = ((JSysCFG) graph).getDeclarationClass(); - NodeList> dynInitList = ((JSysCFG) graph).getClassGraph().getDynInit(containerClass.getNameAsString()); - dynInitList.accept(this, arg); - + List> dynInitList = ((JSysCFG) graph).getClassGraph().getDynInit(containerClass.getNameAsString()); + dynInitList.forEach(node -> node.accept(this, arg)); } @Override @@ -44,12 +44,6 @@ public class JSysCFGBuilder extends ACFGBuilder { connectTo(n); } - @Override - public void visit(InitializerDeclaration n, Void arg){ - // TODO - } - - @Override protected void visitCallableDeclaration(CallableDeclaration callableDeclaration, Void arg) { graph.buildRootNode(callableDeclaration); 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 f02b7dd..0f838f4 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 @@ -1,6 +1,64 @@ package es.upv.mist.slicing.graphs.jsysdg; +import com.github.javaparser.ast.CompilationUnit; +import com.github.javaparser.ast.NodeList; +import es.upv.mist.slicing.arcs.sdg.ReturnArc; +import es.upv.mist.slicing.graphs.CallGraph; +import es.upv.mist.slicing.graphs.ClassGraph; +import es.upv.mist.slicing.graphs.augmented.PSDG; +import es.upv.mist.slicing.graphs.cfg.CFG; import es.upv.mist.slicing.graphs.exceptionsensitive.ESSDG; +import es.upv.mist.slicing.graphs.exceptionsensitive.ExceptionSensitiveCallConnector; +import es.upv.mist.slicing.graphs.pdg.PDG; +import es.upv.mist.slicing.nodes.exceptionsensitive.ExitNode; +import es.upv.mist.slicing.nodes.exceptionsensitive.ReturnNode; +import es.upv.mist.slicing.slicing.ExceptionSensitiveSlicingAlgorithm; +import es.upv.mist.slicing.slicing.SlicingAlgorithm; public class JSysDG extends ESSDG { + + @Override + protected JSysDG.Builder createBuilder() { + return new JSysDG.Builder(); + } + + @Override + protected SlicingAlgorithm createSlicingAlgorithm() { + return new ExceptionSensitiveSlicingAlgorithm(this); + } + + public void addReturnArc(ExitNode source, ReturnNode target) { + addEdge(source, target, new ReturnArc()); + } + + /** Populates an ESSDG, using ESPDG and ESCFG as default graphs. + * @see PSDG.Builder + * @see ExceptionSensitiveCallConnector */ + class Builder extends ESSDG.Builder { + + private ClassGraph classGraph; + + @Override + public void build(NodeList nodeList) { + // See creation strategy at http://kaz2.dsic.upv.es:3000/Fzg46cQvT1GzHQG9hFnP1g#Using-data-flow-in-the-SDG + classGraph = createClassGraph(nodeList); + buildCFGs(nodeList); // 1 + CallGraph callGraph = createCallGraph(nodeList); // 2 + dataFlowAnalysis(callGraph); // 3 + buildAndCopyPDGs(); // 4 + connectCalls(callGraph); // 5 + createSummaryArcs(callGraph); // 6 + } + + @Override + protected CFG createCFG() { + return new JSysCFG(classGraph); + } + + @Override + protected PDG createPDG(CFG cfg) { + assert cfg instanceof JSysCFG; + return new JSysPDG((JSysCFG) cfg); + } + } } 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 509675d..f86f92d 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 @@ -8,7 +8,7 @@ public class JSysPDG extends ESPDG { this(new JSysCFG(clg)); } - public JSysPDG(JSysCFG oocfg) { - super(oocfg); + public JSysPDG(JSysCFG cfg) { + super(cfg); } } 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 fcedcb7..509c017 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 @@ -109,8 +109,8 @@ public class SDG extends Graph implements Sliceable, Buildable nodeList) { // See creation strategy at http://kaz2.dsic.upv.es:3000/Fzg46cQvT1GzHQG9hFnP1g#Using-data-flow-in-the-SDG - ClassGraph classGraph = createClassGraph(nodeList); // TODO: Update order and creation strategy - buildCFGs(nodeList, classGraph); // 1 + buildCFGs(nodeList); // 1 + ClassGraph classGraph = createClassGraph(nodeList); // TODO: Update order and creation strategy // 1 CallGraph callGraph = createCallGraph(nodeList, classGraph); // 2 dataFlowAnalysis(callGraph); // 3 buildAndCopyPDGs(); // 4 @@ -119,7 +119,7 @@ public class SDG extends Graph implements Sliceable, Buildable nodeList, ClassGraph clg) { + protected void buildCFGs(NodeList nodeList) { nodeList.accept(new VoidVisitorAdapter() { @Override public void visit(MethodDeclaration n, Void arg) { -- GitLab From df2be717c5cb8ee9930f5969145cab1029b6c1e3 Mon Sep 17 00:00:00 2001 From: serperu Date: Tue, 2 Feb 2021 11:27:49 +0100 Subject: [PATCH 07/33] Duplicated VariableAction USEs fixed --- .../main/java/es/upv/mist/slicing/nodes/VariableVisitor.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 8faa522..f08ecea 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 @@ -7,6 +7,7 @@ import com.github.javaparser.ast.body.VariableDeclarator; import com.github.javaparser.ast.expr.*; import com.github.javaparser.ast.stmt.CatchClause; import com.github.javaparser.ast.stmt.ExplicitConstructorInvocationStmt; +import com.github.javaparser.ast.stmt.ExpressionStmt; import com.github.javaparser.ast.stmt.ForEachStmt; import com.github.javaparser.resolution.Resolvable; import com.github.javaparser.resolution.declarations.ResolvedMethodLikeDeclaration; @@ -170,7 +171,7 @@ public class VariableVisitor extends GraphNodeContentVisitor l.accept(this, arg)); } @Override -- GitLab From 1f73ff3f1f73ff1d4469e2b868e451b11712a617 Mon Sep 17 00:00:00 2001 From: serperu Date: Wed, 3 Feb 2021 11:13:50 +0100 Subject: [PATCH 08/33] Rename Field Variables in VariableActions --- .../slicing/graphs/jsysdg/JSysCFGBuilder.java | 1 + .../mist/slicing/nodes/VariableVisitor.java | 45 ++++++++++++++----- .../es/upv/mist/slicing/utils/ASTUtils.java | 9 ++++ 3 files changed, 44 insertions(+), 11 deletions(-) diff --git a/sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/JSysCFGBuilder.java b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/JSysCFGBuilder.java index 204bc10..0fd8597 100644 --- a/sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/JSysCFGBuilder.java +++ b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/JSysCFGBuilder.java @@ -42,6 +42,7 @@ public class JSysCFGBuilder extends ACFGBuilder { @Override public void visit(FieldDeclaration n, Void arg){ connectTo(n); + super.visit(n,arg); } @Override 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 f08ecea..d886d94 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 @@ -1,7 +1,8 @@ package es.upv.mist.slicing.nodes; -import com.github.javaparser.ast.Node; +import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration; import com.github.javaparser.ast.body.FieldDeclaration; +import com.github.javaparser.ast.Node; import com.github.javaparser.ast.body.Parameter; import com.github.javaparser.ast.body.VariableDeclarator; import com.github.javaparser.ast.expr.*; @@ -11,6 +12,7 @@ import com.github.javaparser.ast.stmt.ExpressionStmt; import com.github.javaparser.ast.stmt.ForEachStmt; import com.github.javaparser.resolution.Resolvable; import com.github.javaparser.resolution.declarations.ResolvedMethodLikeDeclaration; +import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserFieldDeclaration; import es.upv.mist.slicing.graphs.GraphNodeContentVisitor; import es.upv.mist.slicing.utils.ASTUtils; import es.upv.mist.slicing.utils.TriConsumer; @@ -90,6 +92,8 @@ public class VariableVisitor extends GraphNodeContentVisitor { + init.accept(this, action); + visitAsDefinition(v.getNameAsExpression(), init); + }); } } @@ -277,4 +276,28 @@ public class VariableVisitor extends GraphNodeContentVisitor Date: Fri, 12 Feb 2021 11:58:01 +0100 Subject: [PATCH 09/33] VariableNamePrefix computed for VariableActions --- .../mist/slicing/nodes/VariableVisitor.java | 46 +++++++++++-------- 1 file changed, 27 insertions(+), 19 deletions(-) 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 d886d94..948f74c 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 @@ -6,10 +6,7 @@ import com.github.javaparser.ast.Node; import com.github.javaparser.ast.body.Parameter; import com.github.javaparser.ast.body.VariableDeclarator; import com.github.javaparser.ast.expr.*; -import com.github.javaparser.ast.stmt.CatchClause; -import com.github.javaparser.ast.stmt.ExplicitConstructorInvocationStmt; -import com.github.javaparser.ast.stmt.ExpressionStmt; -import com.github.javaparser.ast.stmt.ForEachStmt; +import com.github.javaparser.ast.stmt.*; import com.github.javaparser.resolution.Resolvable; import com.github.javaparser.resolution.declarations.ResolvedMethodLikeDeclaration; import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserFieldDeclaration; @@ -92,7 +89,7 @@ public class VariableVisitor extends GraphNodeContentVisitor Date: Tue, 16 Feb 2021 14:40:37 +0100 Subject: [PATCH 10/33] NodeList into List to access CompilationUnit --- .../es/upv/mist/slicing/graphs/ClassGraph.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 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 1ac7dc6..5dc4c88 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 @@ -310,21 +310,21 @@ public class ClassGraph extends DirectedPseudograph> getStaticInit(String className){ + /** Returns a List with the static FieldDeclarations and InitializerDeclarations of the given class */ + public List> getStaticInit(String className){ return getClassInit(className,true); } - /** Returns a NodeList with the dynamic FieldDeclarations and InitializerDeclarations of the given class */ - public NodeList> getDynInit(String className){ + /** Returns a List with the dynamic FieldDeclarations and InitializerDeclarations of the given class */ + public List> getDynInit(String className){ return getClassInit(className,false); } - /** Returns a NodeList with FieldDeclarations and InitializerDeclarations static/dynamic items of the given class */ - private NodeList> getClassInit(String className, Boolean isStatic){ + /** 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); - NodeList> members = classNode.declaration.asClassOrInterfaceDeclaration().getMembers(); - NodeList> classInit = new NodeList<>(); + List> members = classNode.declaration.asClassOrInterfaceDeclaration().getMembers(); + List> classInit = new LinkedList<>(); for (BodyDeclaration member : members) { if (member instanceof CallableDeclaration) continue; -- GitLab From f81411ec98bd5a6619f2e6a6b25684da962cf426 Mon Sep 17 00:00:00 2001 From: serperu Date: Tue, 23 Feb 2021 14:17:37 +0100 Subject: [PATCH 11/33] Updated variable_pattern_regex to match VariableActions regarding object fields accessed in different ways --- .../java/es/upv/mist/slicing/nodes/VariableAction.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/sdg-core/src/main/java/es/upv/mist/slicing/nodes/VariableAction.java b/sdg-core/src/main/java/es/upv/mist/slicing/nodes/VariableAction.java index 385076e..17afb00 100644 --- a/sdg-core/src/main/java/es/upv/mist/slicing/nodes/VariableAction.java +++ b/sdg-core/src/main/java/es/upv/mist/slicing/nodes/VariableAction.java @@ -17,7 +17,8 @@ import java.util.stream.Collectors; /** An action upon a variable (e.g. usage, definition, declaration) */ public abstract class VariableAction { - protected static final String VARIABLE_PATTERN = "^([a-zA-Z][a-zA-Z0-9_]*|[_a-zA-Z][a-zA-Z0-9_]+)$"; + protected static final String VARIABLE_PATTERN = "^([a-zA-Z][a-zA-Z0-9_]*|[_a-zA-Z][a-zA-Z0-9_]+" + + "|([a-zA-Z][a-zA-Z0-9_]*)([\\.][a-zA-Z][a-zA-Z]*)+)$"; protected final Expression variable; protected final GraphNode graphNode; @@ -68,7 +69,9 @@ public abstract class VariableAction { /** Whether the argument is performed upon the same variable as this action. */ public boolean matches(VariableAction action) { - return Objects.equals(action.variable, variable); + return Objects.equals(action.variable, variable) + // Needed to link FieldAccessExpr with NameExpr in case they refer to the same Field Variable (this.x = x + 1) + || action.variable.toString().equals(variable.toString()); } public boolean isUsage() { -- GitLab From 53fdb7dbc8f97ade5f083182c96540921dc3982c Mon Sep 17 00:00:00 2001 From: serperu Date: Tue, 23 Feb 2021 14:19:54 +0100 Subject: [PATCH 12/33] Add prefix to VariableActions names when necessary and reorder sequence of assign VariableActions --- .../es/upv/mist/slicing/graphs/jsysdg/JSysDG.java | 2 +- .../es/upv/mist/slicing/nodes/VariableVisitor.java | 12 ++++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) 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 0f838f4..745730e 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 @@ -43,7 +43,7 @@ public class JSysDG extends ESSDG { // See creation strategy at http://kaz2.dsic.upv.es:3000/Fzg46cQvT1GzHQG9hFnP1g#Using-data-flow-in-the-SDG classGraph = createClassGraph(nodeList); buildCFGs(nodeList); // 1 - CallGraph callGraph = createCallGraph(nodeList); // 2 + CallGraph callGraph = createCallGraph(nodeList, classGraph); // 2 dataFlowAnalysis(callGraph); // 3 buildAndCopyPDGs(); // 4 connectCalls(callGraph); // 5 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 948f74c..1be475e 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 @@ -76,7 +76,7 @@ public class VariableVisitor extends GraphNodeContentVisitor, Expression> BLANK_BICONSUMER = (a, b) -> {}; - protected static final TriConsumer, Expression, Expression> BLANK_TRICONSUMER = (a, b, c) -> {}; + protected static final TriConsumer, Expression, String> BLANK_TRICONSUMER = (a, b, c) -> {}; + protected static final QuadConsumer, Expression, String, Expression> BLANK_QUADCONSUMER = (a, b, c, d) -> {}; /** The action to perform when a declaration is found. */ - protected final BiConsumer, Expression> declConsumer; + protected final TriConsumer, Expression, String> declConsumer; /** The action to perform when a definition is found. */ - protected final TriConsumer, Expression, Expression> defConsumer; + protected final QuadConsumer, Expression, String, Expression> defConsumer; /** The action to perform when a usage is found. */ - protected final BiConsumer, Expression> useConsumer; + protected final TriConsumer, Expression, String> useConsumer; /** A stack with the last definition expression, to provide it when a variable definition is found. */ protected final Deque definitionStack = new LinkedList<>(); @@ -66,10 +69,12 @@ public class VariableVisitor extends GraphNodeContentVisitor, Expression> declConsumer, TriConsumer, Expression, Expression> defConsumer, BiConsumer, Expression> useConsumer) { - this.declConsumer = Objects.requireNonNullElse(declConsumer, BLANK_BICONSUMER); - this.defConsumer = Objects.requireNonNullElse(defConsumer, BLANK_TRICONSUMER); - this.useConsumer = Objects.requireNonNullElse(useConsumer, BLANK_BICONSUMER); + public VariableVisitor(TriConsumer, Expression, String> declConsumer, + QuadConsumer, Expression, String, Expression> defConsumer, + TriConsumer, Expression, String> useConsumer) { + this.declConsumer = Objects.requireNonNullElse(declConsumer, BLANK_TRICONSUMER); + this.defConsumer = Objects.requireNonNullElse(defConsumer, BLANK_QUADCONSUMER); + this.useConsumer = Objects.requireNonNullElse(useConsumer, BLANK_TRICONSUMER); } public void visitAsDefinition(Node node, Expression value) { @@ -115,21 +120,17 @@ public class VariableVisitor extends GraphNodeContentVisitor { + void accept(T arg1, U arg2, V arg3, W arg4); +} -- GitLab From 6ad07f6de466390ec056bcc3a7ac6f34b40c3e19 Mon Sep 17 00:00:00 2001 From: Carlos Galindo Date: Thu, 25 Feb 2021 11:11:54 +0100 Subject: [PATCH 14/33] fix! VariableAction#equals --- .../src/main/java/es/upv/mist/slicing/nodes/VariableAction.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdg-core/src/main/java/es/upv/mist/slicing/nodes/VariableAction.java b/sdg-core/src/main/java/es/upv/mist/slicing/nodes/VariableAction.java index dbdde05..acf1c81 100644 --- a/sdg-core/src/main/java/es/upv/mist/slicing/nodes/VariableAction.java +++ b/sdg-core/src/main/java/es/upv/mist/slicing/nodes/VariableAction.java @@ -125,7 +125,7 @@ public abstract class VariableAction { public boolean equals(Object obj) { return obj instanceof VariableAction && obj.getClass().equals(getClass()) && - variable.equals(((VariableAction) obj).variable) && + Objects.equals(variable, ((VariableAction) obj).variable) && realName.equals(((VariableAction) obj).realName); } -- GitLab From d1ccdf384852b141eea2d4779fa6beb047e435a5 Mon Sep 17 00:00:00 2001 From: Carlos Galindo Date: Thu, 25 Feb 2021 10:02:16 +0100 Subject: [PATCH 15/33] fix! nameExpr prefixing now catches UnsolvedSymbolException --- .../graphs/sdg/InterproceduralActionFinder.java | 1 - .../es/upv/mist/slicing/nodes/VariableVisitor.java | 14 ++++++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/sdg-core/src/main/java/es/upv/mist/slicing/graphs/sdg/InterproceduralActionFinder.java b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/sdg/InterproceduralActionFinder.java index 30e3aae..9eececc 100644 --- a/sdg-core/src/main/java/es/upv/mist/slicing/graphs/sdg/InterproceduralActionFinder.java +++ b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/sdg/InterproceduralActionFinder.java @@ -128,7 +128,6 @@ public abstract class InterproceduralActionFinder exte else if (r1.isField() && r2.isParameter()) return 1; } catch (UnsolvedSymbolException e) { - Logger.log("Could not resolve a given name expression, it may be a type: " + e.getName()); if (r1 == null) return 1; else if (r2 == null) 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 334041c..82f1545 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 @@ -11,10 +11,12 @@ import com.github.javaparser.ast.stmt.ExplicitConstructorInvocationStmt; import com.github.javaparser.ast.stmt.ExpressionStmt; import com.github.javaparser.ast.stmt.ForEachStmt; import com.github.javaparser.resolution.Resolvable; +import com.github.javaparser.resolution.UnsolvedSymbolException; import com.github.javaparser.resolution.declarations.ResolvedMethodLikeDeclaration; import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserFieldDeclaration; import es.upv.mist.slicing.graphs.GraphNodeContentVisitor; import es.upv.mist.slicing.utils.ASTUtils; +import es.upv.mist.slicing.utils.Logger; import es.upv.mist.slicing.utils.QuadConsumer; import es.upv.mist.slicing.utils.TriConsumer; @@ -282,16 +284,20 @@ public class VariableVisitor extends GraphNodeContentVisitor Date: Thu, 25 Feb 2021 10:27:56 +0100 Subject: [PATCH 16/33] fix! JSysCFGBuilder now extends ESCFG.Builder --- .../graphs/exceptionsensitive/ESCFG.java | 13 ++-- .../mist/slicing/graphs/jsysdg/JSysCFG.java | 64 +++++++++++++++- .../slicing/graphs/jsysdg/JSysCFGBuilder.java | 73 ------------------- 3 files changed, 69 insertions(+), 81 deletions(-) delete mode 100644 sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/JSysCFGBuilder.java diff --git a/sdg-core/src/main/java/es/upv/mist/slicing/graphs/exceptionsensitive/ESCFG.java b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/exceptionsensitive/ESCFG.java index f57e40d..cbde73c 100644 --- a/sdg-core/src/main/java/es/upv/mist/slicing/graphs/exceptionsensitive/ESCFG.java +++ b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/exceptionsensitive/ESCFG.java @@ -34,7 +34,7 @@ public class ESCFG extends ACFG { @Override protected CFGBuilder newCFGBuilder() { - return new Builder(); + return new Builder(this); } protected ExceptionExitNode addExceptionExitNode(CallableDeclaration method, ResolvedType type) { @@ -103,8 +103,9 @@ public class ESCFG extends ACFG { /** Map of return nodes from each method call, mapped by the normal return node of said call. */ protected Map> pendingNormalReturnNodes = new HashMap<>(); - protected Builder() { + protected Builder(ESCFG escfg) { super(ESCFG.this); + assert escfg == ESCFG.this; } @Override @@ -248,23 +249,23 @@ public class ESCFG extends ACFG { @Override public void visit(MethodCallExpr n, Void arg) { - visitCall(n); + visitCallForExceptions(n); } @Override public void visit(ObjectCreationExpr n, Void arg) { - visitCall(n); + visitCallForExceptions(n); } @Override public void visit(ExplicitConstructorInvocationStmt n, Void arg) { connectTo(n); - visitCall(n); + visitCallForExceptions(n); } /** Process a call that may throw exceptions. Generates normal and return nodes, and * registers the appropriate exception source. */ - protected void visitCall(Resolvable call) { + protected void visitCallForExceptions(Resolvable call) { ResolvedMethodLikeDeclaration resolved = call.resolve(); if (resolved.getNumberOfSpecifiedExceptions() == 0) return; 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 0d011ba..cfd48c5 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 @@ -1,9 +1,19 @@ 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.BodyDeclaration; 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.stmt.ExplicitConstructorInvocationStmt; 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.utils.ASTUtils; + +import java.util.LinkedList; +import java.util.List; public class JSysCFG extends ESCFG { @@ -20,10 +30,9 @@ public class JSysCFG extends ESCFG { } protected CFGBuilder newCFGBuilder() { - return new JSysCFGBuilder(this); + return new Builder(this); } - /** Obtains the Javaparser Node corresponding to the class where the CFG is contained */ public ClassOrInterfaceDeclaration getDeclarationClass() { assert rootNode != null; @@ -31,4 +40,55 @@ public class JSysCFG extends ESCFG { throw new IllegalStateException("The Method declaration is not directly inside a Class Declaration"); return (ClassOrInterfaceDeclaration) rootNode.getAstNode().getParentNode().get(); } + + public class Builder extends ESCFG.Builder { + + /** List of inserted super calls in Javaparser AST to process them as Implicit Nodes (@ImplicitNode)*/ + protected List methodInsertedInstructions = new LinkedList<>(); + + protected Builder(JSysCFG jSysCFG) { + super(JSysCFG.this); + assert jSysCFG == JSysCFG.this; + } + + /** Esto se llama porque lo hemos insertado fantasma o porque existe. A continuacion se inserta el codigo dynInit */ + @Override + public void visit(ExplicitConstructorInvocationStmt n, Void arg) { + + // 1. Create new super call if not present + if (methodInsertedInstructions.contains(n)){ + ImplicitNode node = new ImplicitNode(n.toString(), n); + graph.addVertex(node); + connectTo(node); + } + else { + connectTo(n); + } + // 2. Insert dynamic class code + ClassOrInterfaceDeclaration containerClass = ((JSysCFG) graph).getDeclarationClass(); + List> dynInitList = ((JSysCFG) graph).getClassGraph().getDynInit(containerClass.getNameAsString()); + dynInitList.forEach(node -> node.accept(this, arg)); + + // 3. Handle exceptions + super.visitCallForExceptions(n); + } + + @Override + public void visit(FieldDeclaration n, Void arg){ + connectTo(n); + super.visit(n,arg); + } + + @Override + public void visit(ConstructorDeclaration n, Void arg) { + // Insert call to super() if it is implicit. + if (!ASTUtils.constructorHasExplicitConstructorInvocation(n)){ + var superCall = new ExplicitConstructorInvocationStmt(null, null, false, null, new NodeList<>()); + methodInsertedInstructions.add(superCall); + n.getBody().addStatement(0, superCall); + } + // Perform the same task as previous graphs. + super.visit(n, arg); + } + } } diff --git a/sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/JSysCFGBuilder.java b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/JSysCFGBuilder.java deleted file mode 100644 index 0fd8597..0000000 --- a/sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/JSysCFGBuilder.java +++ /dev/null @@ -1,73 +0,0 @@ -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.*; -import com.github.javaparser.ast.stmt.ExplicitConstructorInvocationStmt; -import es.upv.mist.slicing.graphs.augmented.ACFGBuilder; -import es.upv.mist.slicing.nodes.io.MethodExitNode; -import es.upv.mist.slicing.utils.ASTUtils; - -import java.util.LinkedList; -import java.util.List; - -public class JSysCFGBuilder extends ACFGBuilder { - - /** List of inserted super calls in Javaparser AST to process them as Implicit Nodes (@ImplicitNode)*/ - protected List methodInsertedInstructions = new LinkedList<>(); - - protected JSysCFGBuilder(JSysCFG graph) { - super(graph); - } - - /** Esto se llama porque lo hemos insertado fantasma o porque existe. A continuacion se inserta el codigo dynInit */ - @Override - public void visit(ExplicitConstructorInvocationStmt n, Void arg) { - - // 1. Create new super call if not present - if (methodInsertedInstructions.contains(n)){ - ImplicitNode node = new ImplicitNode(n.toString(), n); - graph.addVertex(node); - connectTo(node); - } - else { - connectTo(n); - } - // 2. Insert dynamic class code - ClassOrInterfaceDeclaration containerClass = ((JSysCFG) graph).getDeclarationClass(); - List> dynInitList = ((JSysCFG) graph).getClassGraph().getDynInit(containerClass.getNameAsString()); - dynInitList.forEach(node -> node.accept(this, arg)); - } - - @Override - public void visit(FieldDeclaration n, Void arg){ - connectTo(n); - super.visit(n,arg); - } - - @Override - protected void visitCallableDeclaration(CallableDeclaration callableDeclaration, Void arg) { - graph.buildRootNode(callableDeclaration); - hangingNodes.add(graph.getRootNode()); - - // 1. Check if first is super (only if constructor) - // then, create and build super() - if (callableDeclaration instanceof ConstructorDeclaration){ - ConstructorDeclaration declaration = (ConstructorDeclaration) callableDeclaration; - if (!ASTUtils.constructorHasExplicitConstructorInvocation(declaration)){ - ExplicitConstructorInvocationStmt superCall = - new ExplicitConstructorInvocationStmt(null, null, false, null, new NodeList<>()); - methodInsertedInstructions.add(superCall); - declaration.getBody().addStatement(0, superCall); - } - } - - ASTUtils.getCallableBody(callableDeclaration).accept(this, arg); - returnList.stream().filter(node -> !hangingNodes.contains(node)).forEach(hangingNodes::add); - - MethodExitNode exit = new MethodExitNode(callableDeclaration); - graph.addVertex(exit); - addMethodOutput(callableDeclaration, exit); - connectTo(exit); - } -} -- GitLab From 21139d4b24f2ef04cac59a76f712b3faca9bb133 Mon Sep 17 00:00:00 2001 From: Carlos Galindo Date: Thu, 25 Feb 2021 11:00:17 +0100 Subject: [PATCH 17/33] fix! VariableVisitor no longer creates new NameExpr --- .../mist/slicing/nodes/VariableVisitor.java | 85 +++++++------------ .../es/upv/mist/slicing/utils/ASTUtils.java | 3 +- 2 files changed, 32 insertions(+), 56 deletions(-) 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 82f1545..73bce31 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 @@ -6,13 +6,14 @@ import com.github.javaparser.ast.body.FieldDeclaration; import com.github.javaparser.ast.body.Parameter; import com.github.javaparser.ast.body.VariableDeclarator; import com.github.javaparser.ast.expr.*; +import com.github.javaparser.ast.nodeTypes.NodeWithVariables; import com.github.javaparser.ast.stmt.CatchClause; import com.github.javaparser.ast.stmt.ExplicitConstructorInvocationStmt; -import com.github.javaparser.ast.stmt.ExpressionStmt; import com.github.javaparser.ast.stmt.ForEachStmt; import com.github.javaparser.resolution.Resolvable; import com.github.javaparser.resolution.UnsolvedSymbolException; import com.github.javaparser.resolution.declarations.ResolvedMethodLikeDeclaration; +import com.github.javaparser.resolution.declarations.ResolvedValueDeclaration; import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserFieldDeclaration; import es.upv.mist.slicing.graphs.GraphNodeContentVisitor; import es.upv.mist.slicing.utils.ASTUtils; @@ -79,11 +80,7 @@ public class VariableVisitor extends GraphNodeContentVisitor { - init.accept(this, action); - visitAsDefinition(v.getNameAsExpression(), init); - }); - } + visitVarDeclaration(n, action); } @Override public void visit(FieldDeclaration n, Action action) { - for (VariableDeclarator v : n.getVariables()) { - v.getNameAsExpression().accept(this, action.or(Action.DECLARATION)); + visitVarDeclaration(n, action); + } + + protected void visitVarDeclaration(NodeWithVariables declaration, Action action) { + for (VariableDeclarator v : declaration.getVariables()) { + declConsumer.accept(graphNode, null, v.getNameAsString()); v.getInitializer().ifPresent(init -> { init.accept(this, action); - visitAsDefinition(v.getNameAsExpression(), init); + defConsumer.accept(graphNode, null, v.getNameAsString(), init); }); } } @@ -281,13 +277,12 @@ public class VariableVisitor extends GraphNodeContentVisitor Date: Thu, 25 Feb 2021 11:23:16 +0100 Subject: [PATCH 18/33] fix! improve getNamePrefix to avoid cast errors --- .../es/upv/mist/slicing/nodes/VariableVisitor.java | 12 +++++------- .../java/es/upv/mist/slicing/utils/ASTUtils.java | 4 ++-- 2 files changed, 7 insertions(+), 9 deletions(-) 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 73bce31..6f45b9c 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 @@ -1,7 +1,6 @@ package es.upv.mist.slicing.nodes; import com.github.javaparser.ast.Node; -import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration; import com.github.javaparser.ast.body.FieldDeclaration; import com.github.javaparser.ast.body.Parameter; import com.github.javaparser.ast.body.VariableDeclarator; @@ -13,8 +12,8 @@ import com.github.javaparser.ast.stmt.ForEachStmt; import com.github.javaparser.resolution.Resolvable; import com.github.javaparser.resolution.UnsolvedSymbolException; import com.github.javaparser.resolution.declarations.ResolvedMethodLikeDeclaration; +import com.github.javaparser.resolution.declarations.ResolvedTypeDeclaration; import com.github.javaparser.resolution.declarations.ResolvedValueDeclaration; -import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserFieldDeclaration; import es.upv.mist.slicing.graphs.GraphNodeContentVisitor; import es.upv.mist.slicing.utils.ASTUtils; import es.upv.mist.slicing.utils.Logger; @@ -297,13 +296,12 @@ public class VariableVisitor extends GraphNodeContentVisitor Date: Thu, 25 Feb 2021 11:38:07 +0100 Subject: [PATCH 19/33] fix! UsageFinder should visit the argument, not the node --- .../mist/slicing/graphs/sdg/InterproceduralUsageFinder.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 d567911..a6c4d9d 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 @@ -39,11 +39,11 @@ public class InterproceduralUsageFinder extends InterproceduralActionFinder movables.add(new VariableAction.Movable(new VariableAction.Declaration(exp, name, graphNode), actualIn)), (n, exp, name, expression) -> movables.add(new VariableAction.Movable(new VariableAction.Definition(exp, name, graphNode, expression), actualIn)), (n, exp, name) -> movables.add(new VariableAction.Movable(new VariableAction.Usage(exp, name, graphNode), actualIn)) - ).startVisit(graphNode, VariableVisitor.Action.USE); + ), VariableVisitor.Action.USE); graphNode.addActionsForCall(movables, edge.getCall(), true); } -- GitLab From 6df2fff791b1a909c0f4d2896319358943f6b0c4 Mon Sep 17 00:00:00 2001 From: Carlos Galindo Date: Thu, 25 Feb 2021 12:54:25 +0100 Subject: [PATCH 20/33] fix! better matching of calls (== instead of equals) --- .../src/main/java/es/upv/mist/slicing/nodes/GraphNode.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sdg-core/src/main/java/es/upv/mist/slicing/nodes/GraphNode.java b/sdg-core/src/main/java/es/upv/mist/slicing/nodes/GraphNode.java index 3a0cb7e..33ff1df 100644 --- a/sdg-core/src/main/java/es/upv/mist/slicing/nodes/GraphNode.java +++ b/sdg-core/src/main/java/es/upv/mist/slicing/nodes/GraphNode.java @@ -7,6 +7,7 @@ import com.github.javaparser.resolution.declarations.ResolvedMethodLikeDeclarati import es.upv.mist.slicing.graphs.cfg.CFG; import es.upv.mist.slicing.graphs.pdg.PDG; import es.upv.mist.slicing.graphs.sdg.SDG; +import es.upv.mist.slicing.utils.ASTUtils; import java.util.*; @@ -92,7 +93,8 @@ public class GraphNode implements Comparable> { /** Whether this node contains the given call AST node. */ public boolean containsCall(Resolvable call) { - return methodCalls.contains(call); + return methodCalls.stream() + .anyMatch(callInMethod -> ASTUtils.equalsWithRangeInCU((Node) callInMethod, (Node) call)); } /** Append or prepend the given set of actions to the actions of the given call. */ -- GitLab From ffe2b3dd4edc15b1c4f6c3a01aa5abaa16340bf4 Mon Sep 17 00:00:00 2001 From: Carlos Galindo Date: Thu, 25 Feb 2021 12:54:48 +0100 Subject: [PATCH 21/33] fix! ppdg condition didn't check for pseudopredicate status --- .../mist/slicing/slicing/ExceptionSensitiveSlicingAlgorithm.java | 1 + 1 file changed, 1 insertion(+) diff --git a/sdg-core/src/main/java/es/upv/mist/slicing/slicing/ExceptionSensitiveSlicingAlgorithm.java b/sdg-core/src/main/java/es/upv/mist/slicing/slicing/ExceptionSensitiveSlicingAlgorithm.java index d888ce2..0aa3a3e 100644 --- a/sdg-core/src/main/java/es/upv/mist/slicing/slicing/ExceptionSensitiveSlicingAlgorithm.java +++ b/sdg-core/src/main/java/es/upv/mist/slicing/slicing/ExceptionSensitiveSlicingAlgorithm.java @@ -115,6 +115,7 @@ public class ExceptionSensitiveSlicingAlgorithm implements SlicingAlgorithm { protected boolean ppdgIgnore(Arc arc) { GraphNode target = graph.getEdgeTarget(arc); return arc.isUnconditionalControlDependencyArc() && + graph.isPseudoPredicate(target) && reachedStream(target).allMatch(Arc::isUnconditionalControlDependencyArc) && !target.equals(slicingCriterion); } -- GitLab From b753697d58b444a4ceee986824c12c87f070a74b Mon Sep 17 00:00:00 2001 From: Carlos Galindo Date: Thu, 25 Feb 2021 12:55:01 +0100 Subject: [PATCH 22/33] fix! remove unnecessary overrides --- .../es/upv/mist/slicing/graphs/jsysdg/JSysDG.java | 14 -------------- 1 file changed, 14 deletions(-) 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 745730e..f4e0db5 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 @@ -2,7 +2,6 @@ package es.upv.mist.slicing.graphs.jsysdg; import com.github.javaparser.ast.CompilationUnit; import com.github.javaparser.ast.NodeList; -import es.upv.mist.slicing.arcs.sdg.ReturnArc; import es.upv.mist.slicing.graphs.CallGraph; import es.upv.mist.slicing.graphs.ClassGraph; import es.upv.mist.slicing.graphs.augmented.PSDG; @@ -10,10 +9,6 @@ import es.upv.mist.slicing.graphs.cfg.CFG; import es.upv.mist.slicing.graphs.exceptionsensitive.ESSDG; import es.upv.mist.slicing.graphs.exceptionsensitive.ExceptionSensitiveCallConnector; import es.upv.mist.slicing.graphs.pdg.PDG; -import es.upv.mist.slicing.nodes.exceptionsensitive.ExitNode; -import es.upv.mist.slicing.nodes.exceptionsensitive.ReturnNode; -import es.upv.mist.slicing.slicing.ExceptionSensitiveSlicingAlgorithm; -import es.upv.mist.slicing.slicing.SlicingAlgorithm; public class JSysDG extends ESSDG { @@ -22,15 +17,6 @@ public class JSysDG extends ESSDG { return new JSysDG.Builder(); } - @Override - protected SlicingAlgorithm createSlicingAlgorithm() { - return new ExceptionSensitiveSlicingAlgorithm(this); - } - - public void addReturnArc(ExitNode source, ReturnNode target) { - addEdge(source, target, new ReturnArc()); - } - /** Populates an ESSDG, using ESPDG and ESCFG as default graphs. * @see PSDG.Builder * @see ExceptionSensitiveCallConnector */ -- GitLab From 230192c031e512e09409e3945a30a610ab8c1f0a Mon Sep 17 00:00:00 2001 From: Carlos Galindo Date: Thu, 25 Feb 2021 12:55:26 +0100 Subject: [PATCH 23/33] fix! SlicePruneVisitor doesn't need to go into members of FieldDeclaration --- .../java/es/upv/mist/slicing/slicing/SlicePruneVisitor.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sdg-core/src/main/java/es/upv/mist/slicing/slicing/SlicePruneVisitor.java b/sdg-core/src/main/java/es/upv/mist/slicing/slicing/SlicePruneVisitor.java index 6381413..460c43f 100644 --- a/sdg-core/src/main/java/es/upv/mist/slicing/slicing/SlicePruneVisitor.java +++ b/sdg-core/src/main/java/es/upv/mist/slicing/slicing/SlicePruneVisitor.java @@ -65,9 +65,7 @@ public class SlicePruneVisitor extends ModifierVisitor> { @Override public Visitable visit(FieldDeclaration n, NodeHashSet arg) { - boolean keep = arg.contains(n); - Visitable v = super.visit(n, arg); - return keep ? v : null; + return arg.contains(n) ? n : null; } // ========== Method body visitors ========== -- GitLab From 0b11fa734d5ac2f50ea4c47c9dd326916c8fb67a Mon Sep 17 00:00:00 2001 From: Carlos Galindo Date: Thu, 25 Feb 2021 12:55:50 +0100 Subject: [PATCH 24/33] test against JSysDG --- sdg-core/src/test/java/es/upv/mist/slicing/SlicerTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sdg-core/src/test/java/es/upv/mist/slicing/SlicerTest.java b/sdg-core/src/test/java/es/upv/mist/slicing/SlicerTest.java index 21f0224..f111440 100644 --- a/sdg-core/src/test/java/es/upv/mist/slicing/SlicerTest.java +++ b/sdg-core/src/test/java/es/upv/mist/slicing/SlicerTest.java @@ -3,7 +3,7 @@ package es.upv.mist.slicing; import com.github.javaparser.StaticJavaParser; import com.github.javaparser.ast.CompilationUnit; import com.github.javaparser.ast.NodeList; -import es.upv.mist.slicing.graphs.exceptionsensitive.ESSDG; +import es.upv.mist.slicing.graphs.jsysdg.JSysDG; import es.upv.mist.slicing.graphs.sdg.SDG; import es.upv.mist.slicing.slicing.FileLineSlicingCriterion; import es.upv.mist.slicing.slicing.Slice; @@ -127,7 +127,7 @@ public class SlicerTest { } private static Slice slice(File javaFile, SlicingCriterion sc) throws FileNotFoundException { - SDG sdg = new ESSDG(); + SDG sdg = new JSysDG(); sdg.build(new NodeList<>(StaticJavaParser.parse(javaFile))); return sdg.slice(sc); } -- GitLab From a25d1ec8e22539446d11d407245e44a71d9466f5 Mon Sep 17 00:00:00 2001 From: Carlos Galindo Date: Thu, 25 Feb 2021 12:56:00 +0100 Subject: [PATCH 25/33] updated regression tests --- .../res/regression/carlos/Problem3.java.sdg.sliced | 5 +++++ .../regression/dinsa-tests/Josep4.java.sdg.sliced | 3 +++ .../regression/ltd-samples/Test_2.java.sdg.sliced | 2 ++ .../regression/review-07-2020/P6.java.sdg.sliced | 13 +++++++++++++ 4 files changed, 23 insertions(+) diff --git a/sdg-core/src/test/res/regression/carlos/Problem3.java.sdg.sliced b/sdg-core/src/test/res/regression/carlos/Problem3.java.sdg.sliced index 4fadd2b..f181758 100644 --- a/sdg-core/src/test/res/regression/carlos/Problem3.java.sdg.sliced +++ b/sdg-core/src/test/res/regression/carlos/Problem3.java.sdg.sliced @@ -2,6 +2,11 @@ public class Problem3 { public static void main() throws Exception { x = 0; + try { + f(); + } catch (Exception e) { + } + x = 1; f(); } diff --git a/sdg-core/src/test/res/regression/dinsa-tests/Josep4.java.sdg.sliced b/sdg-core/src/test/res/regression/dinsa-tests/Josep4.java.sdg.sliced index d9e3a79..071079b 100644 --- a/sdg-core/src/test/res/regression/dinsa-tests/Josep4.java.sdg.sliced +++ b/sdg-core/src/test/res/regression/dinsa-tests/Josep4.java.sdg.sliced @@ -1,6 +1,9 @@ class A { + int x = 0; + A(int x) { + this.x = x; } int getx() { diff --git a/sdg-core/src/test/res/regression/ltd-samples/Test_2.java.sdg.sliced b/sdg-core/src/test/res/regression/ltd-samples/Test_2.java.sdg.sliced index b61c5b7..1621799 100644 --- a/sdg-core/src/test/res/regression/ltd-samples/Test_2.java.sdg.sliced +++ b/sdg-core/src/test/res/regression/ltd-samples/Test_2.java.sdg.sliced @@ -4,6 +4,8 @@ public class Test_2 { public static void main(String[] args) { int x = 1; + x++; + ++x; int y = 0; x = x + y; System.out.println(x); diff --git a/sdg-core/src/test/res/regression/review-07-2020/P6.java.sdg.sliced b/sdg-core/src/test/res/regression/review-07-2020/P6.java.sdg.sliced index 7e9046d..c8e0f9f 100644 --- a/sdg-core/src/test/res/regression/review-07-2020/P6.java.sdg.sliced +++ b/sdg-core/src/test/res/regression/review-07-2020/P6.java.sdg.sliced @@ -1,5 +1,18 @@ public class Bucles { + public static void main(String[] args) { + int x = 2; + try { + for (int i = 0; i <= 12; i++) { + metodoGeneradorExcepciones(x); + } + } catch (ExceptionB a) { + } catch (ExceptionA a) { + } catch (Exception a) { + System.out.println("Se lanza Exception"); + } + } + static void metodoGeneradorExcepciones(int x) throws Exception { if (x == 0) throw new ExceptionA(); -- GitLab From f88013c0ae6f9cf18c026a1529a822d5077a362e Mon Sep 17 00:00:00 2001 From: Carlos Galindo Date: Thu, 25 Feb 2021 15:56:35 +0100 Subject: [PATCH 26/33] simplify JSysDG by reordering the creation order in SDG --- .../graphs/exceptionsensitive/ESSDG.java | 3 +- .../mist/slicing/graphs/jsysdg/JSysDG.java | 19 ------------ .../es/upv/mist/slicing/graphs/sdg/SDG.java | 30 +++++++++++-------- 3 files changed, 18 insertions(+), 34 deletions(-) diff --git a/sdg-core/src/main/java/es/upv/mist/slicing/graphs/exceptionsensitive/ESSDG.java b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/exceptionsensitive/ESSDG.java index aa21e52..2e57468 100644 --- a/sdg-core/src/main/java/es/upv/mist/slicing/graphs/exceptionsensitive/ESSDG.java +++ b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/exceptionsensitive/ESSDG.java @@ -1,7 +1,6 @@ package es.upv.mist.slicing.graphs.exceptionsensitive; import es.upv.mist.slicing.arcs.sdg.ReturnArc; -import es.upv.mist.slicing.graphs.CallGraph; import es.upv.mist.slicing.graphs.augmented.PPDG; import es.upv.mist.slicing.graphs.augmented.PSDG; import es.upv.mist.slicing.graphs.cfg.CFG; @@ -45,7 +44,7 @@ public class ESSDG extends PSDG { } @Override - protected void connectCalls(CallGraph callGraph) { + protected void connectCalls() { new ExceptionSensitiveCallConnector(ESSDG.this).connectAllCalls(callGraph); } } 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 f4e0db5..9d5ecee 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 @@ -1,9 +1,5 @@ package es.upv.mist.slicing.graphs.jsysdg; -import com.github.javaparser.ast.CompilationUnit; -import com.github.javaparser.ast.NodeList; -import es.upv.mist.slicing.graphs.CallGraph; -import es.upv.mist.slicing.graphs.ClassGraph; import es.upv.mist.slicing.graphs.augmented.PSDG; import es.upv.mist.slicing.graphs.cfg.CFG; import es.upv.mist.slicing.graphs.exceptionsensitive.ESSDG; @@ -21,21 +17,6 @@ public class JSysDG extends ESSDG { * @see PSDG.Builder * @see ExceptionSensitiveCallConnector */ class Builder extends ESSDG.Builder { - - private ClassGraph classGraph; - - @Override - public void build(NodeList nodeList) { - // See creation strategy at http://kaz2.dsic.upv.es:3000/Fzg46cQvT1GzHQG9hFnP1g#Using-data-flow-in-the-SDG - classGraph = createClassGraph(nodeList); - buildCFGs(nodeList); // 1 - CallGraph callGraph = createCallGraph(nodeList, classGraph); // 2 - dataFlowAnalysis(callGraph); // 3 - buildAndCopyPDGs(); // 4 - connectCalls(callGraph); // 5 - createSummaryArcs(callGraph); // 6 - } - @Override protected CFG createCFG() { return new JSysCFG(classGraph); 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 59502b2..4a8901c 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 @@ -107,15 +107,19 @@ public class SDG extends Graph implements Sliceable, Buildable nodeList) { // See creation strategy at http://kaz2.dsic.upv.es:3000/Fzg46cQvT1GzHQG9hFnP1g#Using-data-flow-in-the-SDG - buildCFGs(nodeList); // 1 - ClassGraph classGraph = createClassGraph(nodeList); // TODO: Update order and creation strategy // 1 - CallGraph callGraph = createCallGraph(nodeList, classGraph); // 2 - dataFlowAnalysis(callGraph); // 3 - buildAndCopyPDGs(); // 4 - connectCalls(callGraph); // 5 - createSummaryArcs(callGraph); // 6 + // This ordering cannot be altered, as each step requires elements from the previous one. + classGraph = createClassGraph(nodeList); // 0 + buildCFGs(nodeList); // 1 + callGraph = createCallGraph(nodeList); // 2 + dataFlowAnalysis(); // 3 + buildAndCopyPDGs(); // 4 + connectCalls(); // 5 + createSummaryArcs(); // 6 } /** Build a CFG per declaration found in the list of compilation units. */ @@ -138,7 +142,7 @@ public class SDG extends Graph implements Sliceable, Buildable nodeList, ClassGraph classGraph) { + protected CallGraph createCallGraph(NodeList nodeList) { CallGraph callGraph = new CallGraph(cfgMap, classGraph); callGraph.build(nodeList); return callGraph; @@ -153,14 +157,14 @@ public class SDG extends Graph implements Sliceable, Buildable edge : callGraph.edgeSet()) { if (ASTUtils.resolvableIsVoid(edge.getCall())) continue; @@ -188,12 +192,12 @@ public class SDG extends Graph implements Sliceable, Buildable Date: Thu, 25 Feb 2021 16:22:50 +0100 Subject: [PATCH 27/33] Simplify variable and field regexes --- .../main/java/es/upv/mist/slicing/nodes/VariableAction.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sdg-core/src/main/java/es/upv/mist/slicing/nodes/VariableAction.java b/sdg-core/src/main/java/es/upv/mist/slicing/nodes/VariableAction.java index acf1c81..2bbe684 100644 --- a/sdg-core/src/main/java/es/upv/mist/slicing/nodes/VariableAction.java +++ b/sdg-core/src/main/java/es/upv/mist/slicing/nodes/VariableAction.java @@ -16,8 +16,8 @@ import java.util.stream.Collectors; /** An action upon a variable (e.g. usage, definition, declaration) */ public abstract class VariableAction { - protected static final String VARIABLE_PATTERN = "^([a-zA-Z][a-zA-Z0-9_]*|[_a-zA-Z][a-zA-Z0-9_]+" + - "|([a-zA-Z][a-zA-Z0-9_]*)([\\.][a-zA-Z][a-zA-Z]*)+)$"; + protected static final String VARIABLE_PATTERN = "([a-zA-Z][a-zA-Z0-9_]*|_[a-zA-Z0-9_]+)"; + protected static final String FIELD_PATTERN = "^" + VARIABLE_PATTERN + "(\\." + VARIABLE_PATTERN + ")*" + "$"; protected final Expression variable; protected final String realName; @@ -37,7 +37,7 @@ public abstract class VariableAction { /** Whether this action is performed upon an invented variable, * introduced by this library (e.g. the active exception or the returned value). */ public boolean isSynthetic() { - return !getVariable().matches(VARIABLE_PATTERN); + return !getVariable().matches(FIELD_PATTERN); } public String getVariable() { -- GitLab From 07f6e99f107b50a95e57cc7d9bda7abc9c9b09ad Mon Sep 17 00:00:00 2001 From: Carlos Galindo Date: Fri, 26 Feb 2021 09:59:55 +0100 Subject: [PATCH 28/33] Only include classes if they contain a BodyDeclaration --- .../es/upv/mist/slicing/slicing/SlicePruneVisitor.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/sdg-core/src/main/java/es/upv/mist/slicing/slicing/SlicePruneVisitor.java b/sdg-core/src/main/java/es/upv/mist/slicing/slicing/SlicePruneVisitor.java index 460c43f..f5569b0 100644 --- a/sdg-core/src/main/java/es/upv/mist/slicing/slicing/SlicePruneVisitor.java +++ b/sdg-core/src/main/java/es/upv/mist/slicing/slicing/SlicePruneVisitor.java @@ -3,10 +3,7 @@ package es.upv.mist.slicing.slicing; import com.github.javaparser.ast.CompilationUnit; import com.github.javaparser.ast.Node; import com.github.javaparser.ast.NodeList; -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.body.MethodDeclaration; +import com.github.javaparser.ast.body.*; import com.github.javaparser.ast.expr.BooleanLiteralExpr; import com.github.javaparser.ast.nodeTypes.NodeWithBody; import com.github.javaparser.ast.stmt.*; @@ -44,7 +41,8 @@ public class SlicePruneVisitor extends ModifierVisitor> { public Visitable visit(ClassOrInterfaceDeclaration n, NodeHashSet arg) { boolean keep = arg.contains(n); Visitable v = super.visit(n, arg); - return keep || !((Node) v).getChildNodes().isEmpty() ? v : null; + boolean containsDeclarations = ((Node) v).getChildNodes().stream().anyMatch(BodyDeclaration.class::isInstance); + return keep || containsDeclarations ? v : null; } // ========== Class body visitors ========== -- GitLab From a2dc36c5c2549cac88bc4f97ab8701bc2a638696 Mon Sep 17 00:00:00 2001 From: Carlos Galindo Date: Fri, 26 Feb 2021 11:04:49 +0100 Subject: [PATCH 29/33] Stop printing null in graphs --- sdg-core/src/main/java/es/upv/mist/slicing/utils/Utils.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sdg-core/src/main/java/es/upv/mist/slicing/utils/Utils.java b/sdg-core/src/main/java/es/upv/mist/slicing/utils/Utils.java index 6e823b8..d5f2dc8 100644 --- a/sdg-core/src/main/java/es/upv/mist/slicing/utils/Utils.java +++ b/sdg-core/src/main/java/es/upv/mist/slicing/utils/Utils.java @@ -25,7 +25,8 @@ public class Utils { public static Map dotLabel(String label) { Map map = new HashMap<>(); - map.put("label", DefaultAttribute.createAttribute(label)); + if (label != null) + map.put("label", DefaultAttribute.createAttribute(label)); return map; } } -- GitLab From a81337d61b2af1a23eadc3631f881fd92c8d22ef Mon Sep 17 00:00:00 2001 From: Carlos Galindo Date: Sat, 27 Feb 2021 00:57:27 +0100 Subject: [PATCH 30/33] Tree handling of objects, multiple fixes and improvements * Update tests with better slices. * GraphNode#addActionsAfterCall uses varargs instead of a set. * Improved handling of super() and this() calls. * ImplicitNode is now generic * Improved interface in JSysCFG to insert new instructions ad-hoc. * Constructors now have an implicit "return this". * Removed JSysCFG#getDeclarationClass, ASTUtils has a similar method. * VariableActions can now store (but don't propagate) a tree of fields acted upon. * VariableActions can now take null as variable, or any possible expression. * Automatic generation of the actions for fields (USE(a.x) generates USE(a)). * Conversely, fields now either traverse their scope or declare an action. * Handling of ThisExpr. * Better initialization naming for fields. * Implemented default initialization of fields if none is present. * InterproceduralActionFinders: * Unified the behaviour of #initialValue() * Improved generation of actual-in/out for fields. Caveats: * InterproceduralActionFinders cannot process VariableActions that don't resolve into a ResolvedValueDeclaration. Thus, 'this' must be declared when entering a method or constructor declaration. * Removed type from IO nodes, as it required resolving expressions and was unnecessary for the slicer. --- .../slicing/graphs/jsysdg/ImplicitNode.java | 10 +- .../mist/slicing/graphs/jsysdg/JSysCFG.java | 69 ++++----- .../sdg/InterproceduralActionFinder.java | 106 ++++++++++++-- .../sdg/InterproceduralDefinitionFinder.java | 52 +++---- .../sdg/InterproceduralUsageFinder.java | 46 +++--- .../es/upv/mist/slicing/graphs/sdg/SDG.java | 6 +- .../es/upv/mist/slicing/nodes/GraphNode.java | 6 +- .../mist/slicing/nodes/VariableAction.java | 116 +++++++++++++-- .../mist/slicing/nodes/VariableVisitor.java | 135 ++++++++++++++---- .../mist/slicing/nodes/io/ActualIONode.java | 10 +- .../mist/slicing/nodes/io/FormalIONode.java | 22 ++- .../es/upv/mist/slicing/nodes/io/IONode.java | 8 +- .../es/upv/mist/slicing/utils/ASTUtils.java | 28 ++-- .../carlos/Problem2.java.sdg.sliced | 5 + .../dinsa-tests/Carlos1.java.sdg.sliced | 6 - .../dinsa-tests/Carlos2.java.sdg.sliced | 6 - .../dinsa-tests/Josep3.java.sdg.sliced | 2 + .../dinsa-tests/Josep4.java.sdg.sliced | 1 - .../dinsa-tests/Josep5.java.sdg.sliced | 7 +- .../dinsa-tests/Josep6.java.sdg.sliced | 4 + .../dinsa-tests/Josep7.java.sdg.sliced | 13 +- .../res/regression/dinsa-tests/Josep8.java | 45 +++++- .../dinsa-tests/Josep8.java.sdg.sliced | 13 +- .../dinsa-tests/Josep9.java.sdg.sliced | 2 + .../ltd-samples/BasicBreak.java.sdg.sliced | 6 + .../ltd-samples/BasicContinue.java.sdg.sliced | 6 + .../ltd-samples/Bucles_Josep.java.sdg.sliced | 7 + .../programs/cfg/Eval_1.java.sdg.sliced | 6 + .../programs/cfg/Eval_2.java.sdg.sliced | 9 ++ .../programs/cfg/Eval_3.java.sdg.sliced | 14 ++ .../programs/pdg/Test.java.sdg.sliced | 5 + .../review-07-2020/P3.java.sdg.sliced | 17 ++- .../review-07-2020/P4.java.sdg.sliced | 25 +++- .../review-07-2020/P6.java.sdg.sliced | 8 -- 34 files changed, 599 insertions(+), 222 deletions(-) diff --git a/sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/ImplicitNode.java b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/ImplicitNode.java index 8b70d65..1bb2a29 100644 --- a/sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/ImplicitNode.java +++ b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/ImplicitNode.java @@ -3,9 +3,13 @@ package es.upv.mist.slicing.graphs.jsysdg; import com.github.javaparser.ast.Node; import es.upv.mist.slicing.nodes.SyntheticNode; -// TODO: Concretar más el tipo T del nodo (Node es muy general). Por ahora seria solo ExplicitConstructorInvocationStmt -public class ImplicitNode extends SyntheticNode { - protected ImplicitNode(String instruction, Node astNode) { +/** + * A graph node that does not exist in the original program, but represents + * implicit code constructs such as 'super()' at the start of a constructor. + * @param The type of the AST node contained in this graph node. + */ +public class ImplicitNode extends SyntheticNode { + protected ImplicitNode(String instruction, T astNode) { super(instruction, astNode); } } 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 cfd48c5..f11d49d 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 @@ -2,48 +2,42 @@ 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.BodyDeclaration; 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; import es.upv.mist.slicing.utils.ASTUtils; import java.util.LinkedList; import java.util.List; +/** + * An SDG that is tailored for Java, including a class graph, inheritance, + * polymorphism and other features. + */ public class JSysCFG extends ESCFG { - /** ClassGraph associated to the Method represented by the CFG */ - protected ClassGraph clg; + protected ClassGraph classGraph; - public JSysCFG(ClassGraph clg){ + public JSysCFG(ClassGraph classGraph){ super(); - this.clg = clg; - } - - public ClassGraph getClassGraph(){ - return this.clg; + this.classGraph = classGraph; } + @Override protected CFGBuilder newCFGBuilder() { return new Builder(this); } - /** Obtains the Javaparser Node corresponding to the class where the CFG is contained */ - public ClassOrInterfaceDeclaration getDeclarationClass() { - assert rootNode != null; - if (!(rootNode.getAstNode().getParentNode().get() instanceof ClassOrInterfaceDeclaration)) - throw new IllegalStateException("The Method declaration is not directly inside a Class Declaration"); - return (ClassOrInterfaceDeclaration) rootNode.getAstNode().getParentNode().get(); - } - public class Builder extends ESCFG.Builder { - - /** List of inserted super calls in Javaparser AST to process them as Implicit Nodes (@ImplicitNode)*/ + /** List of implicit instructions inserted explicitly in this CFG. + * They should be included in the graph as ImplicitNodes. */ protected List methodInsertedInstructions = new LinkedList<>(); protected Builder(JSysCFG jSysCFG) { @@ -51,24 +45,28 @@ public class JSysCFG extends ESCFG { assert jSysCFG == JSysCFG.this; } - /** Esto se llama porque lo hemos insertado fantasma o porque existe. A continuacion se inserta el codigo dynInit */ @Override - public void visit(ExplicitConstructorInvocationStmt n, Void arg) { - - // 1. Create new super call if not present - if (methodInsertedInstructions.contains(n)){ - ImplicitNode node = new ImplicitNode(n.toString(), n); - graph.addVertex(node); - connectTo(node); - } - else { - connectTo(n); + protected GraphNode connectTo(T n, String text) { + GraphNode dest; + if (methodInsertedInstructions.contains(n)) { + dest = new ImplicitNode<>(n.toString(), n); + } else { + dest = new GraphNode<>(text, n); } - // 2. Insert dynamic class code - ClassOrInterfaceDeclaration containerClass = ((JSysCFG) graph).getDeclarationClass(); - List> dynInitList = ((JSysCFG) graph).getClassGraph().getDynInit(containerClass.getNameAsString()); - dynInitList.forEach(node -> node.accept(this, arg)); + addVertex(dest); + connectTo(dest); + return dest; + } + @Override + public void visit(ExplicitConstructorInvocationStmt n, Void arg) { + // 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)); + } // 3. Handle exceptions super.visitCallForExceptions(n); } @@ -84,8 +82,11 @@ public class JSysCFG extends ESCFG { // Insert call to super() if it is implicit. if (!ASTUtils.constructorHasExplicitConstructorInvocation(n)){ var superCall = new ExplicitConstructorInvocationStmt(null, null, false, null, new NodeList<>()); + var returnThis = new ReturnStmt(new ThisExpr()); methodInsertedInstructions.add(superCall); + methodInsertedInstructions.add(returnThis); n.getBody().addStatement(0, superCall); + n.getBody().addStatement(returnThis); } // Perform the same task as previous graphs. super.visit(n, arg); diff --git a/sdg-core/src/main/java/es/upv/mist/slicing/graphs/sdg/InterproceduralActionFinder.java b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/sdg/InterproceduralActionFinder.java index 9eececc..92e8289 100644 --- a/sdg-core/src/main/java/es/upv/mist/slicing/graphs/sdg/InterproceduralActionFinder.java +++ b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/sdg/InterproceduralActionFinder.java @@ -2,7 +2,12 @@ package es.upv.mist.slicing.graphs.sdg; import com.github.javaparser.ast.body.CallableDeclaration; import com.github.javaparser.ast.expr.Expression; +import com.github.javaparser.ast.expr.MethodCallExpr; +import com.github.javaparser.ast.expr.ThisExpr; +import com.github.javaparser.ast.stmt.ExplicitConstructorInvocationStmt; +import com.github.javaparser.resolution.Resolvable; import com.github.javaparser.resolution.UnsolvedSymbolException; +import com.github.javaparser.resolution.declarations.ResolvedMethodLikeDeclaration; import com.github.javaparser.resolution.declarations.ResolvedParameterDeclaration; import com.github.javaparser.resolution.declarations.ResolvedValueDeclaration; import es.upv.mist.slicing.graphs.BackwardDataFlowAnalysis; @@ -15,6 +20,9 @@ import es.upv.mist.slicing.utils.Logger; import java.util.*; import java.util.function.BiConsumer; import java.util.function.Consumer; +import java.util.function.Predicate; +import java.util.stream.Collectors; +import java.util.stream.Stream; // TODO: this approach of generating actual nodes may skip an argument; this is only a problem if there is a definition // TODO: update placement of actual and formal outputs for ESSDG (see if the definition/usage reaches all/any exits). @@ -71,24 +79,73 @@ public abstract class InterproceduralActionFinder exte /** Generate the actual node(s) related to this action and call. */ protected abstract void handleActualAction(CallGraph.Edge edge, A action); + // =========================================================== + // ============== AUXILIARY METHODS FOR CHILDREN ============= + // =========================================================== + + /** Given a call, obtains the scope. If none is present it may return null. + * ExpressionConstructorInvocations result in a this expression, as they + * may be seen as dynamic method calls that can modify 'this'. */ + protected static Expression obtainScope(Resolvable call) { + if (call instanceof MethodCallExpr) { + var methodCall = (MethodCallExpr) call; + return methodCall.getScope().orElse(null); + } else if (call instanceof ExplicitConstructorInvocationStmt) { + return new ThisExpr(); + } else { + throw new IllegalArgumentException("The given call is not of a valid type"); + } + } + /** Obtains the expression passed as argument for the given action at the given call. If {@code input} * is false, primitive parameters will be skipped, as their value cannot be redefined.*/ - protected Expression extractArgument(VariableAction action, CallGraph.Edge edge, boolean input) { - ResolvedValueDeclaration resolved = action.getResolvedValueDeclaration(); + protected Expression extractArgument(ResolvedParameterDeclaration p, CallGraph.Edge edge, boolean input) { CallableDeclaration callTarget = graph.getEdgeTarget(edge).getDeclaration(); - if (resolved.isParameter()) { - ResolvedParameterDeclaration p = resolved.asParameter(); - if (!input && p.getType().isPrimitive()) - return null; // primitives do not have actual-out! - int paramIndex = ASTUtils.getMatchingParameterIndex(callTarget, p); - return ASTUtils.getResolvableArgs(edge.getCall()).get(paramIndex); - } else if (resolved.isField()) { - return action.getVariableExpression(); + if (!input && p.getType().isPrimitive()) + return null; // primitives do not have actual-out! + int paramIndex = ASTUtils.getMatchingParameterIndex(callTarget, p); + return ASTUtils.getResolvableArgs(edge.getCall()).get(paramIndex); + } + + /** Generate the name that should be given to an object in a caller method, given an action + * in the callee method. This is used to transform a reference to 'this' into the scope + * of a method. */ + protected static String obtainAliasedFieldName(VariableAction action, CallGraph.Edge edge) { + if (edge.getCall() instanceof MethodCallExpr) { + Optional optScope = ((MethodCallExpr) edge.getCall()).getScope(); + return obtainAliasedFieldName(action, edge, optScope.isPresent() ? optScope.get().toString() : ""); + } else if (edge.getCall() instanceof ExplicitConstructorInvocationStmt) { + // The only possibility is 'this' or its fields, so we return empty scope and 'type.this.' is generated + return obtainAliasedFieldName(action, edge, ""); + } else { + throw new IllegalArgumentException("The given call is not of a valid type"); + } + } + + /** To be used by {@link #obtainAliasedFieldName(VariableAction, CallGraph.Edge)} exclusively.
+ * Given a scope, name inside a method and call, translates the name of a variable, such that 'this' becomes + * the scope of the method. */ + protected static String obtainAliasedFieldName(VariableAction action, CallGraph.Edge edge, String scope) { + if (scope.isEmpty()) { + return action.getVariable(); } else { - throw new IllegalArgumentException("Variable should be either param or field!"); + String newPrefix = scope; + newPrefix = newPrefix.replaceAll("((\\.)super|^super)(\\.)?", "$2this$3"); + if (newPrefix.equals("this")) { + String fqName = ASTUtils.getClassNode(edge.getGraphNode().getAstNode()).getFullyQualifiedName().orElseThrow(); + newPrefix = fqName + ".this"; + } + String withPrefix = action.getVariable(); + String withoutPrefix = withPrefix.replaceFirst("^((.*\\.)?this\\.?)", ""); + String result = newPrefix + withoutPrefix; + return result.replaceFirst("this(\\.this)+", "this"); } } + // =========================================================== + // =============== COMPUTE DATA FOR FIXED POINT ============== + // =========================================================== + @Override protected Set> compute(CallGraph.Vertex vertex, Set predecessors) { saveDeclaration(vertex); @@ -97,11 +154,32 @@ public abstract class InterproceduralActionFinder
exte return newValue; } - /** Wrap a variable action in a {@link StoredAction}, to track whether it has been applied to the graph or not. */ - protected StoredAction wrapAction(A action) { - return new StoredAction<>(action); + @Override + protected Set> initialValue(CallGraph.Vertex vertex) { + CFG cfg = cfgMap.get(vertex.getDeclaration()); + if (cfg == null) + return Collections.emptySet(); + Stream stream = cfg.vertexSet().stream() + // Ignore root node, it is literally the entrypoint for interprocedural actions. + .filter(n -> n != cfg.getRootNode()) + .flatMap(n -> n.getVariableActions().stream()) + // We never analyze synthetic variables (all intraprocedural) + .filter(Predicate.not(VariableAction::isSynthetic)) + // We skip over non-root variables (for each 'x.a' action we'll find 'x' later) + .filter(VariableAction::isRootAction); + return mapAndFilterActionStream(stream, cfg) + .map(StoredAction::new) + .collect(Collectors.toSet()); } + /** Given a stream of VariableAction objects, map it to the finders' type and + * filter unwanted items (only if the filter is specific to that type). */ + protected abstract Stream mapAndFilterActionStream(Stream stream, CFG cfg); + + // =========================================================== + // ========================= SUBCLASSES ====================== + // =========================================================== + /** A comparator to sort parameters and fields in the generation of actual nodes. It will sort * {@link StoredAction}s in the following order: fields, then parameters by descending index number. * The actual nodes will be generated in that order and inserted in reverse order in the graph node. */ 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 7f95e57..7ad47b3 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 @@ -3,6 +3,7 @@ package es.upv.mist.slicing.graphs.sdg; import com.github.javaparser.ast.body.CallableDeclaration; import com.github.javaparser.ast.expr.Expression; import com.github.javaparser.ast.expr.NameExpr; +import com.github.javaparser.ast.expr.ObjectCreationExpr; import com.github.javaparser.resolution.declarations.ResolvedValueDeclaration; import es.upv.mist.slicing.graphs.CallGraph; import es.upv.mist.slicing.graphs.cfg.CFG; @@ -11,12 +12,10 @@ 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.Collections; import java.util.HashSet; import java.util.Map; import java.util.Set; -import java.util.function.Predicate; -import java.util.stream.Collectors; +import java.util.stream.Stream; /** An interprocedural definition finder, which adds the associated actions to formal and actual nodes in the CFGs. */ public class InterproceduralDefinitionFinder extends InterproceduralActionFinder { @@ -41,34 +40,39 @@ public class InterproceduralDefinitionFinder extends InterproceduralActionFinder Set movables = new HashSet<>(); GraphNode graphNode = edge.getGraphNode(); ResolvedValueDeclaration resolved = def.getResolvedValueDeclaration(); - Expression arg = extractArgument(def, edge, false); - if (arg == null) - return; - ActualIONode actualOut = ActualIONode.createActualOut(edge.getCall(), resolved, arg); if (resolved.isParameter()) { - Set exprSet = new HashSet<>(); - arg.accept(new OutNodeVariableVisitor(), exprSet); - for (NameExpr nameExpr : exprSet) - movables.add(new VariableAction.Movable(new VariableAction.Definition(nameExpr, nameExpr.toString(), graphNode), actualOut)); + Expression arg = extractArgument(resolved.asParameter(), edge, false); + if (arg == null) + return; + ActualIONode actualOut = ActualIONode.createActualOut(edge.getCall(), resolved, arg); + if (resolved.isParameter()) { + Set exprSet = new HashSet<>(); + arg.accept(new OutNodeVariableVisitor(), exprSet); + for (NameExpr nameExpr : exprSet) + movables.add(new VariableAction.Movable(new VariableAction.Definition(nameExpr, nameExpr.toString(), graphNode), actualOut)); + } else { + movables.add(new VariableAction.Movable(def.toDefinition(graphNode), actualOut)); + } + } else if (resolved.isField()) { + // Known limitation: static fields + // An object creation expression doesn't alter an existing object via actual-out + // it is returned and assigned via -output-. + if (edge.getCall() instanceof ObjectCreationExpr) + return; + String aliasedName = obtainAliasedFieldName(def, edge); + ActualIONode actualOut = ActualIONode.createActualOut(edge.getCall(), resolved, null); + var movableDef = new VariableAction.Definition(obtainScope(edge.getCall()), aliasedName, graphNode, null); + movables.add(new VariableAction.Movable(movableDef, actualOut)); } else { - movables.add(new VariableAction.Movable(def.toDefinition(graphNode), actualOut)); + throw new IllegalStateException("Definition must be either from a parameter or a field!"); } graphNode.addActionsForCall(movables, edge.getCall(), false); } @Override - protected Set> initialValue(CallGraph.Vertex vertex) { - CFG cfg = cfgMap.get(vertex.getDeclaration()); - if (cfg == null) - return Collections.emptySet(); - return cfg.vertexSet().stream() - .filter(n -> n != cfg.getRootNode()) - .flatMap(n -> n.getVariableActions().stream()) - .filter(VariableAction::isDefinition) - .filter(Predicate.not(VariableAction::isSynthetic)) + protected Stream mapAndFilterActionStream(Stream stream, CFG cfg) { + return stream.filter(VariableAction::isDefinition) .map(VariableAction::asDefinition) - .filter(def -> cfg.findDeclarationFor(def).isEmpty()) - .map(this::wrapAction) - .collect(Collectors.toSet()); + .filter(def -> cfg.findDeclarationFor(def).isEmpty()); } } 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 a6c4d9d..20919e9 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 @@ -2,6 +2,7 @@ package es.upv.mist.slicing.graphs.sdg; import com.github.javaparser.ast.body.CallableDeclaration; import com.github.javaparser.ast.expr.Expression; +import com.github.javaparser.ast.expr.ObjectCreationExpr; import com.github.javaparser.resolution.declarations.ResolvedValueDeclaration; import es.upv.mist.slicing.graphs.CallGraph; import es.upv.mist.slicing.graphs.cfg.CFG; @@ -11,12 +12,11 @@ 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.Collections; import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.function.Predicate; -import java.util.stream.Collectors; +import java.util.stream.Stream; /** An interprocedural usage finder, which adds the associated actions to formal and actual nodes in the CFGs. */ public class InterproceduralUsageFinder extends InterproceduralActionFinder { @@ -37,29 +37,33 @@ public class InterproceduralUsageFinder extends InterproceduralActionFinder movables = new HashSet<>(); GraphNode graphNode = edge.getGraphNode(); ResolvedValueDeclaration resolved = use.getResolvedValueDeclaration(); - Expression argument = extractArgument(use, edge, true); - ActualIONode actualIn = ActualIONode.createActualIn(edge.getCall(), resolved, argument); - argument.accept(new VariableVisitor( - (n, exp, name) -> movables.add(new VariableAction.Movable(new VariableAction.Declaration(exp, name, graphNode), actualIn)), - (n, exp, name, expression) -> movables.add(new VariableAction.Movable(new VariableAction.Definition(exp, name, graphNode, expression), actualIn)), - (n, exp, name) -> movables.add(new VariableAction.Movable(new VariableAction.Usage(exp, name, graphNode), actualIn)) - ), VariableVisitor.Action.USE); + if (resolved.isParameter()) { + Expression argument = extractArgument(resolved.asParameter(), edge, true); + ActualIONode actualIn = ActualIONode.createActualIn(edge.getCall(), resolved, argument); + argument.accept(new VariableVisitor( + (n, exp, name) -> movables.add(new VariableAction.Movable(new VariableAction.Declaration(exp, name, graphNode), actualIn)), + (n, exp, name, expression) -> movables.add(new VariableAction.Movable(new VariableAction.Definition(exp, name, graphNode, expression), actualIn)), + (n, exp, name) -> movables.add(new VariableAction.Movable(new VariableAction.Usage(exp, name, graphNode), actualIn)) + ), VariableVisitor.Action.USE); + } else if (resolved.isField()) { + // Known limitation: static fields + // An object creation expression input an existing object via actual-in because it creates it. + if (edge.getCall() instanceof ObjectCreationExpr) + return; + String aliasedName = obtainAliasedFieldName(use, edge); + ActualIONode actualIn = ActualIONode.createActualIn(edge.getCall(), resolved, null); + var movableUse = new VariableAction.Usage(obtainScope(edge.getCall()), aliasedName, graphNode); + movables.add(new VariableAction.Movable(movableUse, actualIn)); + } else { + throw new IllegalStateException("Definition must be either from a parameter or a field!"); + } graphNode.addActionsForCall(movables, edge.getCall(), true); } @Override - protected Set> initialValue(CallGraph.Vertex vertex) { - CFG cfg = cfgMap.get(vertex.getDeclaration()); - if (cfg == null) - return Collections.emptySet(); - return cfg.vertexSet().stream() - .filter(n -> n != cfg.getRootNode()) - .flatMap(n -> n.getVariableActions().stream()) - .filter(VariableAction::isUsage) - .filter(Predicate.not(VariableAction::isSynthetic)) + protected Stream mapAndFilterActionStream(Stream stream, CFG cfg) { + return stream.filter(VariableAction::isUsage) .map(VariableAction::asUsage) - .filter(Predicate.not(cfg::isCompletelyDefined)) - .map(this::wrapAction) - .collect(Collectors.toSet()); + .filter(Predicate.not(cfg::isCompletelyDefined)); } } 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 4a8901c..4e6209b 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 @@ -5,6 +5,7 @@ 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.stmt.ExplicitConstructorInvocationStmt; import com.github.javaparser.ast.visitor.VoidVisitorAdapter; import es.upv.mist.slicing.arcs.pdg.ControlDependencyArc; import es.upv.mist.slicing.arcs.pdg.DataDependencyArc; @@ -168,6 +169,9 @@ public class SDG extends Graph implements Sliceable, Buildable edge : callGraph.edgeSet()) { if (ASTUtils.resolvableIsVoid(edge.getCall())) continue; + // We handle super()/this() in VariableVisitor + if (edge.getCall() instanceof ExplicitConstructorInvocationStmt) + continue; GraphNode graphNode = edge.getGraphNode(); // A node defines -output- var def = new VariableAction.Definition(null, VARIABLE_NAME_OUTPUT, graphNode); @@ -175,7 +179,7 @@ public class SDG extends Graph implements Sliceable, Buildable implements Comparable> { throw new IllegalArgumentException("Could not find markers for " + call.resolve().getSignature() + " in " + this); } - /** Append the given set of actions to after the actions of the given call. */ - public void addActionsAfterCall(Set actions, Resolvable call) { + /** Append the given actions to after the actions of the given call. */ + public void addActionsAfterCall(Resolvable call, VariableAction... actions) { for (int i = 0; i < variableActions.size(); i++) { VariableAction var = variableActions.get(i); if (var instanceof VariableAction.CallMarker) { VariableAction.CallMarker marker = (VariableAction.CallMarker) var; if (marker.getCall().equals(call) && !marker.isEnter()) { - variableActions.addAll(i + 1, actions); + variableActions.addAll(i + 1, List.of(actions)); return; } } diff --git a/sdg-core/src/main/java/es/upv/mist/slicing/nodes/VariableAction.java b/sdg-core/src/main/java/es/upv/mist/slicing/nodes/VariableAction.java index 2bbe684..556b12f 100644 --- a/sdg-core/src/main/java/es/upv/mist/slicing/nodes/VariableAction.java +++ b/sdg-core/src/main/java/es/upv/mist/slicing/nodes/VariableAction.java @@ -1,17 +1,23 @@ package es.upv.mist.slicing.nodes; import com.github.javaparser.ast.expr.Expression; +import com.github.javaparser.ast.expr.FieldAccessExpr; import com.github.javaparser.resolution.Resolvable; import com.github.javaparser.resolution.declarations.ResolvedMethodLikeDeclaration; import com.github.javaparser.resolution.declarations.ResolvedValueDeclaration; +import com.github.javaparser.resolution.types.ResolvedType; import es.upv.mist.slicing.arcs.Arc; import es.upv.mist.slicing.arcs.pdg.DataDependencyArc; import es.upv.mist.slicing.graphs.Graph; import es.upv.mist.slicing.graphs.pdg.PDG; +import org.jgrapht.graph.DefaultEdge; +import org.jgrapht.graph.SimpleDirectedGraph; import java.lang.reflect.InvocationTargetException; import java.util.Objects; import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import java.util.stream.Collectors; /** An action upon a variable (e.g. usage, definition, declaration) */ @@ -22,16 +28,85 @@ public abstract class VariableAction { protected final Expression variable; protected final String realName; protected final GraphNode graphNode; + protected final SimpleDirectedGraph objectTree = new SimpleDirectedGraph<>(null, DefaultEdge::new, false); protected boolean optional = false; protected ResolvedValueDeclaration resolvedVariableCache; public VariableAction(Expression variable, String realName, GraphNode graphNode) { - assert variable == null || variable.isNameExpr() || variable.isFieldAccessExpr(); assert realName != null && !realName.isEmpty(); this.variable = variable; this.realName = realName; this.graphNode = graphNode; + this.objectTree.addVertex(realName); + } + + /** Add a field of this object, such that the same action performed on the object + * is applied to this field too. Fields of fields may be specified separated by dots. */ + public void addObjectField(String fieldName) { + String parent = null; + for (String element : fieldName.split("\\.")) { + objectTree.addVertex(element); + if (parent != null) + objectTree.addEdge(parent, element); + parent = element; + } + } + + public VariableAction getRootAction() { + assert !isRootAction(); + assert variable == null || variable.isNameExpr() || variable.isFieldAccessExpr() || variable.isThisExpr(); + if (this instanceof Movable) { + Movable movable = (Movable) this; + return new Movable(movable.inner.getRootAction(), (SyntheticNode) graphNode); + } + Expression nVar; + String nRealName = getRootVariable(); + GraphNode nNode = graphNode; + Expression nExpr = isDefinition() ? asDefinition().expression : null; + if (variable == null || !(variable instanceof FieldAccessExpr)) { + // This appears only when generated from a field: just set the variable to null + assert realName.contains(".this."); + nVar = null; + } else { // We are in a FieldAccessExpr + nVar = variable; + while (nVar.isFieldAccessExpr()) + nVar = variable.asFieldAccessExpr().getScope(); + } + if (this instanceof Usage) + return new Usage(nVar, nRealName, nNode); + if (this instanceof Definition) + return new Definition(nVar, nRealName, nNode, nExpr); + if (this instanceof Declaration) + throw new UnsupportedOperationException("Can't create a root node for a declaration!"); + throw new IllegalStateException("Invalid action type"); + } + + public String getRootVariable() { + Pattern rootVariable = Pattern.compile("^(?(([_0-9A-Za-z]+\\.)*this)|([_0-9A-Za-z]+)).*$"); + Matcher matcher = rootVariable.matcher(realName); + if (matcher.matches()) { + if (matcher.group("root") != null) + return matcher.group("root"); // [type.this] or [this] + else + throw new IllegalStateException("Invalid real name: " + realName); + } else { + return null; + } + } + + public boolean isRootAction() { + return isSynthetic() || Objects.equals(getRootVariable(), realName); + } + + public static boolean typeMatches(VariableAction a, VariableAction b) { + return (a.isDeclaration() && b.isDeclaration()) || + (a.isDefinition() && b.isDefinition()) || + (a.isUsage() && b.isUsage()); + } + + public static boolean rootMatches(VariableAction a, VariableAction b) { + return a.getRootVariable().equals(b.getRootVariable()); } /** Whether this action is performed upon an invented variable, @@ -52,16 +127,39 @@ public abstract class VariableAction { return variable; } + /** + * Returns the resolved value declaration. When the action being performed + * is done so on a ThisExpr, the resulting declaration has the following properties: + *
    + *
  • Can return type and name
  • + *
  • Is not a parameter, it's a field.
  • + *
  • All other methods are left to their default implementations.
  • + *
+ */ public ResolvedValueDeclaration getResolvedValueDeclaration() { - if (variable == null) - throw new IllegalStateException("There was no variable to resolve"); if (resolvedVariableCache == null) { - if (variable.isFieldAccessExpr()) - resolvedVariableCache = variable.asFieldAccessExpr().resolve(); - else if (variable.isNameExpr()) - resolvedVariableCache = variable.asNameExpr().resolve(); - else - throw new IllegalStateException("the variable is of an unsupported type"); + if (variable instanceof Resolvable) { + var resolved = ((Resolvable) variable).resolve(); + if (resolved instanceof ResolvedValueDeclaration) + resolvedVariableCache = (ResolvedValueDeclaration) resolved; + } + if (resolvedVariableCache == null) + resolvedVariableCache = new ResolvedValueDeclaration() { + @Override + public ResolvedType getType() { + return null; + } + + @Override + public String getName() { + return realName; + } + + @Override + public boolean isField() { + return true; + } + }; } return resolvedVariableCache; } 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 6f45b9c..1d06a7f 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 @@ -5,7 +5,6 @@ import com.github.javaparser.ast.body.FieldDeclaration; import com.github.javaparser.ast.body.Parameter; import com.github.javaparser.ast.body.VariableDeclarator; import com.github.javaparser.ast.expr.*; -import com.github.javaparser.ast.nodeTypes.NodeWithVariables; import com.github.javaparser.ast.stmt.CatchClause; import com.github.javaparser.ast.stmt.ExplicitConstructorInvocationStmt; import com.github.javaparser.ast.stmt.ForEachStmt; @@ -15,6 +14,7 @@ import com.github.javaparser.resolution.declarations.ResolvedMethodLikeDeclarati import com.github.javaparser.resolution.declarations.ResolvedTypeDeclaration; import com.github.javaparser.resolution.declarations.ResolvedValueDeclaration; import es.upv.mist.slicing.graphs.GraphNodeContentVisitor; +import es.upv.mist.slicing.nodes.io.CallNode; import es.upv.mist.slicing.utils.ASTUtils; import es.upv.mist.slicing.utils.Logger; import es.upv.mist.slicing.utils.QuadConsumer; @@ -23,6 +23,9 @@ import es.upv.mist.slicing.utils.TriConsumer; import java.util.Deque; import java.util.LinkedList; import java.util.Objects; +import java.util.Set; + +import static es.upv.mist.slicing.graphs.cfg.CFGBuilder.VARIABLE_NAME_OUTPUT; /** A graph node visitor that extracts the actions performed in a given GraphNode. An initial action mode can * be set, to consider variables found a declaration, definition or usage (default). @@ -88,6 +91,7 @@ public class VariableVisitor extends GraphNodeContentVisitor node) { startVisit(node, Action.USE); + groupActionsByRoot(node); } @Override @@ -95,10 +99,13 @@ public class VariableVisitor extends GraphNodeContentVisitor { + init.accept(this, action); + defConsumer.accept(graphNode, null, realName, init); + }); + } } @Override public void visit(FieldDeclaration n, Action action) { - visitVarDeclaration(n, action); - } - - protected void visitVarDeclaration(NodeWithVariables declaration, Action action) { - for (VariableDeclarator v : declaration.getVariables()) { - declConsumer.accept(graphNode, null, v.getNameAsString()); - v.getInitializer().ifPresent(init -> { - init.accept(this, action); - defConsumer.accept(graphNode, null, v.getNameAsString(), init); - }); + for (VariableDeclarator v : n.getVariables()) { + String realName; + realName = getRealNameForFieldDeclaration(v); + declConsumer.accept(graphNode, null, realName); + Expression init = v.getInitializer().orElseGet(() -> ASTUtils.initializerForField(n)); + init.accept(this, action); + defConsumer.accept(graphNode, null, realName, init); } } @@ -256,8 +270,22 @@ public class VariableVisitor extends GraphNodeContentVisitor s.accept(this, arg)); graphNode.addCallMarker(call, false); return false; } + /** Adds a declaration for the variable 'this'. */ + protected void declareThis(ExplicitConstructorInvocationStmt call) { + String variableName = getFQClassName(call) + ".this"; + declConsumer.accept(graphNode, null, variableName); + } + + /** Obtains the fully qualified class name of the class that contains an AST node. */ + protected String getFQClassName(Node node) { + // Known limitation: anonymous classes do not have a FQ class name. + return ASTUtils.getClassNode(node).getFullyQualifiedName().orElseThrow(); + } + + /** Prepends [declaring class name].this. to the name of the given variable declarator. */ + protected String getRealNameForFieldDeclaration(VariableDeclarator decl) { + return ASTUtils.getClassNode(decl).getFullyQualifiedName().orElseThrow() + ".this." + decl.getNameAsString(); + } + /** Obtain the prefixed name of a variable, to improve matching of variables * that point to the same object, such as 'x' and 'this.x'. */ protected String getRealName(Expression n) { @@ -285,6 +333,9 @@ public class VariableVisitor extends GraphNodeContentVisitor graphNode) { + VariableAction lastRootAction = null; + for (int i = 0; i < graphNode.variableActions.size(); i++) { + VariableAction action = graphNode.variableActions.get(i); + if (action.isRootAction() || action.isDeclaration() || + action instanceof VariableAction.CallMarker) { + if (lastRootAction != null) { + graphNode.variableActions.add(i, lastRootAction); + i++; + lastRootAction = null; + } + continue; + } + if (lastRootAction == null) { + // generate our own root action + lastRootAction = action.getRootAction(); + // It can be representing a fieldAccessExpr or a fieldDeclaration + // in the first, we can use the expression to obtain the 'type.this' or 'object_name' + // in the second, the expression is null but we can extract 'type.this' from realName + } else { + // Check if action matches the previously generated root action + if (VariableAction.rootMatches(action, lastRootAction) + && VariableAction.typeMatches(action, lastRootAction)) { + lastRootAction.addObjectField(action.getVariable()); + } else { + // No match: add the root before the current element and update counter + graphNode.variableActions.add(i, lastRootAction); + i++; + // generate our own root action + lastRootAction = action.getRootAction(); + } + } + } + // Append the last root action if there is any! + if (lastRootAction != null) + graphNode.variableActions.add(lastRootAction); } } diff --git a/sdg-core/src/main/java/es/upv/mist/slicing/nodes/io/ActualIONode.java b/sdg-core/src/main/java/es/upv/mist/slicing/nodes/io/ActualIONode.java index d7704a0..e074556 100644 --- a/sdg-core/src/main/java/es/upv/mist/slicing/nodes/io/ActualIONode.java +++ b/sdg-core/src/main/java/es/upv/mist/slicing/nodes/io/ActualIONode.java @@ -8,7 +8,6 @@ import com.github.javaparser.resolution.declarations.ResolvedConstructorDeclarat import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration; import com.github.javaparser.resolution.declarations.ResolvedMethodLikeDeclaration; import com.github.javaparser.resolution.declarations.ResolvedValueDeclaration; -import com.github.javaparser.resolution.types.ResolvedType; import java.util.Objects; @@ -17,8 +16,8 @@ public class ActualIONode extends IONode { protected final Expression argument; protected ActualIONode(Resolvable astNode, ResolvedValueDeclaration variable, Expression argument, boolean isInput) { - super(createLabel(isInput, variable.getType(), variable.getName(), argument), (Node) astNode, variable.getType(), variable.getName(), isInput); - this.argument = Objects.requireNonNull(argument); + super(createLabel(isInput, variable.getName(), argument), (Node) astNode, variable.getName(), isInput); + this.argument = argument; } public Expression getArgument() { @@ -30,7 +29,6 @@ public class ActualIONode extends IONode { return getClass().equals(ActualIONode.class) && o.getClass().equals(FormalIONode.class) // 2. Our variables must match (type + name) && Objects.equals(variableName, o.variableName) - && Objects.equals(variableType, o.variableType) // 3. in matches in, out matches out && isInput() == o.isInput() // 4. The method call must resolve to the method declaration of the argument. @@ -58,9 +56,9 @@ public class ActualIONode extends IONode { return Objects.hash(super.hashCode(), argument); } - protected static String createLabel(boolean isInput, ResolvedType paramType, String paramName, Expression arg) { + protected static String createLabel(boolean isInput, String paramName, Expression arg) { if (isInput) - return String.format("%s %s_in = %s", paramType.describe(), paramName, arg.toString()); + return String.format("%s_in = %s", paramName, arg); else return String.format("%s = %s_out", arg, paramName); } diff --git a/sdg-core/src/main/java/es/upv/mist/slicing/nodes/io/FormalIONode.java b/sdg-core/src/main/java/es/upv/mist/slicing/nodes/io/FormalIONode.java index fe4a0da..4b3864e 100644 --- a/sdg-core/src/main/java/es/upv/mist/slicing/nodes/io/FormalIONode.java +++ b/sdg-core/src/main/java/es/upv/mist/slicing/nodes/io/FormalIONode.java @@ -2,36 +2,34 @@ package es.upv.mist.slicing.nodes.io; import com.github.javaparser.ast.body.CallableDeclaration; import com.github.javaparser.resolution.declarations.ResolvedValueDeclaration; -import com.github.javaparser.resolution.types.ResolvedType; /** A formal-in or formal-out node, displaying interprocedural data dependencies. */ public class FormalIONode extends IONode> { - protected FormalIONode(CallableDeclaration astNode, ResolvedType varType, String varName, boolean isInput) { - this(createLabel(isInput, varType, varName), astNode, varType, varName, isInput); + protected FormalIONode(CallableDeclaration astNode, String varName, boolean isInput) { + this(createLabel(isInput, varName), astNode, varName, isInput); } - protected FormalIONode(String text, CallableDeclaration astNode, ResolvedType varType, String varName, boolean isInput) { - super(text, astNode, varType, varName, isInput); + protected FormalIONode(String text, CallableDeclaration astNode, String varName, boolean isInput) { + super(text, astNode, varName, isInput); } - protected static String createLabel(boolean isInput, ResolvedType varType, String varName) { + protected static String createLabel(boolean isInput, String varName) { if (isInput) - return String.format("%s %s = %2$s_in", varType.describe(), varName); + return String.format("%s = %1$s_in", varName); else - return String.format("%s %s_out = %2$s", varType.describe(), varName); + return String.format("%s_out = %1$s", varName); } public static FormalIONode createFormalIn(CallableDeclaration declaration, ResolvedValueDeclaration resolvedValue) { - return new FormalIONode(declaration, resolvedValue.getType(), resolvedValue.getName(), true); + return new FormalIONode(declaration, resolvedValue.getName(), true); } public static FormalIONode createFormalOut(CallableDeclaration declaration, ResolvedValueDeclaration resolvedValue) { - return new FormalIONode(declaration, resolvedValue.getType(), resolvedValue.getName(), false); + return new FormalIONode(declaration, resolvedValue.getName(), false); } public static FormalIONode createFormalInDecl(CallableDeclaration declaration, ResolvedValueDeclaration resolvedValue) { - ResolvedType type = resolvedValue.getType(); String name = resolvedValue.getName(); - return new FormalIONode(type.describe() + " " + name, declaration, type, name, true); + return new FormalIONode(name, declaration, name, true); } } diff --git a/sdg-core/src/main/java/es/upv/mist/slicing/nodes/io/IONode.java b/sdg-core/src/main/java/es/upv/mist/slicing/nodes/io/IONode.java index 09e0d33..d6ee384 100644 --- a/sdg-core/src/main/java/es/upv/mist/slicing/nodes/io/IONode.java +++ b/sdg-core/src/main/java/es/upv/mist/slicing/nodes/io/IONode.java @@ -1,7 +1,6 @@ package es.upv.mist.slicing.nodes.io; import com.github.javaparser.ast.Node; -import com.github.javaparser.resolution.types.ResolvedType; import es.upv.mist.slicing.nodes.SyntheticNode; import java.util.LinkedList; @@ -10,12 +9,10 @@ import java.util.Objects; /** A node representing an input or output from a declaration or call (formal or actual). */ public abstract class IONode extends SyntheticNode { protected final boolean isInput; - protected final ResolvedType variableType; protected final String variableName; - protected IONode(String instruction, T astNode, ResolvedType variableType, String variableName, boolean isInput) { + protected IONode(String instruction, T astNode, String variableName, boolean isInput) { super(instruction, astNode, new LinkedList<>()); - this.variableType = variableType; this.variableName = variableName; this.isInput = isInput; } @@ -32,12 +29,11 @@ public abstract class IONode extends SyntheticNode { public boolean equals(Object o) { return super.equals(o) && o instanceof IONode && ((IONode) o).isInput == isInput - && Objects.equals(((IONode) o).variableType, variableType) && Objects.equals(((IONode) o).variableName, variableName); } @Override public int hashCode() { - return Objects.hash(super.hashCode(), isInput, variableType, variableName); + return Objects.hash(super.hashCode(), isInput, variableName); } } diff --git a/sdg-core/src/main/java/es/upv/mist/slicing/utils/ASTUtils.java b/sdg-core/src/main/java/es/upv/mist/slicing/utils/ASTUtils.java index 993046a..0d8629c 100644 --- a/sdg-core/src/main/java/es/upv/mist/slicing/utils/ASTUtils.java +++ b/sdg-core/src/main/java/es/upv/mist/slicing/utils/ASTUtils.java @@ -1,18 +1,14 @@ package es.upv.mist.slicing.utils; import com.github.javaparser.ast.Node; -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.MethodDeclaration; -import com.github.javaparser.ast.expr.CastExpr; -import com.github.javaparser.ast.expr.Expression; -import com.github.javaparser.ast.expr.MethodCallExpr; -import com.github.javaparser.ast.expr.ObjectCreationExpr; +import com.github.javaparser.ast.body.*; +import com.github.javaparser.ast.expr.*; import com.github.javaparser.ast.stmt.BlockStmt; import com.github.javaparser.ast.stmt.ExplicitConstructorInvocationStmt; import com.github.javaparser.ast.stmt.SwitchEntry; import com.github.javaparser.ast.stmt.SwitchStmt; +import com.github.javaparser.ast.type.PrimitiveType; +import com.github.javaparser.ast.type.Type; import com.github.javaparser.resolution.Resolvable; import com.github.javaparser.resolution.declarations.*; import com.github.javaparser.resolution.types.ResolvedType; @@ -188,4 +184,20 @@ public class ASTUtils { upperNode = upperNode.getParentNode().orElseThrow(); return (ClassOrInterfaceDeclaration) upperNode; } + + /** Generates the default initializer, given a field. In Java, reference types + * default to null, booleans to false and all other primitives to 0. */ + public static Expression initializerForField(FieldDeclaration field) { + Type type = field.getVariables().getFirst().orElseThrow().getType(); + if (type.isReferenceType()) + return new NullLiteralExpr(); + if (type.isPrimitiveType()) { + PrimitiveType primitive = type.asPrimitiveType(); + if (primitive.equals(PrimitiveType.booleanType())) + return new BooleanLiteralExpr(); + else + return new IntegerLiteralExpr(); + } + throw new IllegalArgumentException("Invalid typing for a field"); + } } diff --git a/sdg-core/src/test/res/regression/carlos/Problem2.java.sdg.sliced b/sdg-core/src/test/res/regression/carlos/Problem2.java.sdg.sliced index 369ed03..a27fe67 100644 --- a/sdg-core/src/test/res/regression/carlos/Problem2.java.sdg.sliced +++ b/sdg-core/src/test/res/regression/carlos/Problem2.java.sdg.sliced @@ -2,6 +2,11 @@ public class Problem2 { public static void main(String[] args) { int a = 0; + while (a >= 0) { + if (a > 10) + break; + a++; + } System.out.println(a); } } diff --git a/sdg-core/src/test/res/regression/dinsa-tests/Carlos1.java.sdg.sliced b/sdg-core/src/test/res/regression/dinsa-tests/Carlos1.java.sdg.sliced index 18cd2cc..b284c03 100644 --- a/sdg-core/src/test/res/regression/dinsa-tests/Carlos1.java.sdg.sliced +++ b/sdg-core/src/test/res/regression/dinsa-tests/Carlos1.java.sdg.sliced @@ -4,9 +4,3 @@ class A { int SC = 42; } } - -class Exception2 extends Exception { -} - -class Exception3 extends Exception2 { -} diff --git a/sdg-core/src/test/res/regression/dinsa-tests/Carlos2.java.sdg.sliced b/sdg-core/src/test/res/regression/dinsa-tests/Carlos2.java.sdg.sliced index 0df3d83..f6c39ff 100644 --- a/sdg-core/src/test/res/regression/dinsa-tests/Carlos2.java.sdg.sliced +++ b/sdg-core/src/test/res/regression/dinsa-tests/Carlos2.java.sdg.sliced @@ -26,9 +26,3 @@ class A { return e1; } } - -class Exception2 extends Exception { -} - -class Exception3 extends Exception2 { -} diff --git a/sdg-core/src/test/res/regression/dinsa-tests/Josep3.java.sdg.sliced b/sdg-core/src/test/res/regression/dinsa-tests/Josep3.java.sdg.sliced index bb7aeb2..739b3a4 100644 --- a/sdg-core/src/test/res/regression/dinsa-tests/Josep3.java.sdg.sliced +++ b/sdg-core/src/test/res/regression/dinsa-tests/Josep3.java.sdg.sliced @@ -1,5 +1,7 @@ class A { + int x = 0; + A(int x) { } diff --git a/sdg-core/src/test/res/regression/dinsa-tests/Josep4.java.sdg.sliced b/sdg-core/src/test/res/regression/dinsa-tests/Josep4.java.sdg.sliced index 071079b..6551a9e 100644 --- a/sdg-core/src/test/res/regression/dinsa-tests/Josep4.java.sdg.sliced +++ b/sdg-core/src/test/res/regression/dinsa-tests/Josep4.java.sdg.sliced @@ -3,7 +3,6 @@ class A { int x = 0; A(int x) { - this.x = x; } int getx() { diff --git a/sdg-core/src/test/res/regression/dinsa-tests/Josep5.java.sdg.sliced b/sdg-core/src/test/res/regression/dinsa-tests/Josep5.java.sdg.sliced index 641233c..7df4908 100644 --- a/sdg-core/src/test/res/regression/dinsa-tests/Josep5.java.sdg.sliced +++ b/sdg-core/src/test/res/regression/dinsa-tests/Josep5.java.sdg.sliced @@ -1,16 +1,15 @@ class A { + int xA = 0; + A(int newx) { + xA = newx; } int getx() { return xA; } - void setx(int newx) { - xA = newx; - } - public static void main(String[] args) { B b1 = new B(5.6); int z = b1.getx(); diff --git a/sdg-core/src/test/res/regression/dinsa-tests/Josep6.java.sdg.sliced b/sdg-core/src/test/res/regression/dinsa-tests/Josep6.java.sdg.sliced index 332b824..90e514e 100644 --- a/sdg-core/src/test/res/regression/dinsa-tests/Josep6.java.sdg.sliced +++ b/sdg-core/src/test/res/regression/dinsa-tests/Josep6.java.sdg.sliced @@ -1,10 +1,14 @@ class A { + int xA = 0; + A(int newx) { + xA = newx; } public static void main(String[] args) { B b1 = new B(5.6); + b1.modificarxB(b1); int z = b1.getxB(); System.out.println(z); } diff --git a/sdg-core/src/test/res/regression/dinsa-tests/Josep7.java.sdg.sliced b/sdg-core/src/test/res/regression/dinsa-tests/Josep7.java.sdg.sliced index 6bc5db6..a42669b 100644 --- a/sdg-core/src/test/res/regression/dinsa-tests/Josep7.java.sdg.sliced +++ b/sdg-core/src/test/res/regression/dinsa-tests/Josep7.java.sdg.sliced @@ -1,25 +1,18 @@ class A { + int xA = 0; + A(int newx) { + xA = newx; } int getx() { return xA; } - void siModificaxA(int v) { - xA++; - } - public static void main(String[] args) { A a1 = new A(1); int z = a1.getx(); System.out.println(z); } } - -class B extends A { - - void siModificaxA(int v) { - } -} diff --git a/sdg-core/src/test/res/regression/dinsa-tests/Josep8.java b/sdg-core/src/test/res/regression/dinsa-tests/Josep8.java index 539cb1c..e6cfcfe 100644 --- a/sdg-core/src/test/res/regression/dinsa-tests/Josep8.java +++ b/sdg-core/src/test/res/regression/dinsa-tests/Josep8.java @@ -43,4 +43,47 @@ class B extends A{ void noModificaxA() {System.out.println("useless");} void siModificaxA(int v) {super.siModificaxA(v);} -} \ No newline at end of file +} + +// 1. :D Definir this como -output- al final de los constructores. +// 2. Hay que copiar el arbol al usar un Movable para generar un nodo. +// 3. Hay que utilizar el arbol para generar el arbol de nodos correspondiente +// 4. En las llamadas a super que se resuelven a Object.super(), hay que definir 'this'. +// Por tanto todos los constructores empezaran [in]directamente por una definciion de this, +// y 'this' nunca se buscara en Interprocedural*Finder + + +// PARA RESOLVER problemas con this +/* +2. Cada vez que se define/usa un miembro, se realiza la misma accion para todos +los padres en el arbol (use(a.x) es tambien use(a)): podemos utilizar el arbol de ayer +3. siempre conectemos una actual/formal a un uso/def tenemos que copiar el arbol +(en actual cambiando el nombre de la raiz -- cambiar raiz y todos sus arcos). + */ +/* +Interprocedural*Finder: cuando se define this en un constructor hay qeu pasarlo de vuelta +a) es una creacion de obj normal: se traduce como retorno de la llamada. +b) es una creacion de obj con super()/this(): se traduce a 'this': se copia el arbol + */ +/* +cuando super() defina x, y, z, la salida DEF(this) que contendra las variables definidas. +buscara un DEC(this) y lo encontrara justo antes (INTRA) +el DEF(this) servira como elemento INTRA para enlazar el resto de statements del constr. + */ + +/* +Preservar el orden de acciones al usar arboles: +Cuando se encuentra una accion repetida (e.g. USE(a.x), DEF(a.x), **USE(a.x)**), +tenemos que quitar del Factory la accion vieja (el primer USE(a.x), que sea un USE(a) +y contendra en su arbol (a.x)). + +Ejemplo: +print(a.x++ + a.x); USE(a.x), DEF(a.x), USE(a.x) +Y despues de la visita se tratan las definiciones, pasando a ser: +USE(a.x), USE(a), DEF(a.x), DEF(a), USE(a.x), USE(a) +Modificamos el Interprocedural*Finder para solo tratar los elementos raiz. +Incluso podemos incluir una referencia al hijo en el raiz (USE(a) contiene USE(a.x)) + +Problema: +print(a.y++ + a.x + a.x++): + */ \ No newline at end of file diff --git a/sdg-core/src/test/res/regression/dinsa-tests/Josep8.java.sdg.sliced b/sdg-core/src/test/res/regression/dinsa-tests/Josep8.java.sdg.sliced index 6bc5db6..a42669b 100644 --- a/sdg-core/src/test/res/regression/dinsa-tests/Josep8.java.sdg.sliced +++ b/sdg-core/src/test/res/regression/dinsa-tests/Josep8.java.sdg.sliced @@ -1,25 +1,18 @@ class A { + int xA = 0; + A(int newx) { + xA = newx; } int getx() { return xA; } - void siModificaxA(int v) { - xA++; - } - public static void main(String[] args) { A a1 = new A(1); int z = a1.getx(); System.out.println(z); } } - -class B extends A { - - void siModificaxA(int v) { - } -} diff --git a/sdg-core/src/test/res/regression/dinsa-tests/Josep9.java.sdg.sliced b/sdg-core/src/test/res/regression/dinsa-tests/Josep9.java.sdg.sliced index 3a6b6c2..fc8b83a 100644 --- a/sdg-core/src/test/res/regression/dinsa-tests/Josep9.java.sdg.sliced +++ b/sdg-core/src/test/res/regression/dinsa-tests/Josep9.java.sdg.sliced @@ -14,6 +14,8 @@ class A { public static void main(String[] args) { A a1 = new A(); + a1.setx(5); + a1.siModificaxA(5); int z = a1.getx(); System.out.println(z); } diff --git a/sdg-core/src/test/res/regression/ltd-samples/BasicBreak.java.sdg.sliced b/sdg-core/src/test/res/regression/ltd-samples/BasicBreak.java.sdg.sliced index 79eb720..403a692 100644 --- a/sdg-core/src/test/res/regression/ltd-samples/BasicBreak.java.sdg.sliced +++ b/sdg-core/src/test/res/regression/ltd-samples/BasicBreak.java.sdg.sliced @@ -6,6 +6,12 @@ public class BasicBreak { int x = 0; bucle: while (true) { x++; + for (int y = 0; y < 10; y++) { + if (y == x) + break; + if (y * 2 == x) + break bucle; + } if (x > 10) break; x++; diff --git a/sdg-core/src/test/res/regression/ltd-samples/BasicContinue.java.sdg.sliced b/sdg-core/src/test/res/regression/ltd-samples/BasicContinue.java.sdg.sliced index c00796b..f001b24 100644 --- a/sdg-core/src/test/res/regression/ltd-samples/BasicContinue.java.sdg.sliced +++ b/sdg-core/src/test/res/regression/ltd-samples/BasicContinue.java.sdg.sliced @@ -6,6 +6,12 @@ public class BasicContinue { int x = 0; bucle: while (x < 20) { x++; + for (int y = 0; y < 10; y++) { + if (y == x) + continue; + if (y * 2 == x) + continue bucle; + } if (x > 10) continue; x++; diff --git a/sdg-core/src/test/res/regression/ltd-samples/Bucles_Josep.java.sdg.sliced b/sdg-core/src/test/res/regression/ltd-samples/Bucles_Josep.java.sdg.sliced index 7883a00..3ac6ff8 100644 --- a/sdg-core/src/test/res/regression/ltd-samples/Bucles_Josep.java.sdg.sliced +++ b/sdg-core/src/test/res/regression/ltd-samples/Bucles_Josep.java.sdg.sliced @@ -6,5 +6,12 @@ public class Bucles_Josep { int x = 0; int y = 0, z = 0; z = x + y; + while (z == 0) { + if (z == 0) { + z++; + } else { + z--; + } + } } } diff --git a/sdg-core/src/test/res/regression/programs/cfg/Eval_1.java.sdg.sliced b/sdg-core/src/test/res/regression/programs/cfg/Eval_1.java.sdg.sliced index e26a9e4..a77113e 100644 --- a/sdg-core/src/test/res/regression/programs/cfg/Eval_1.java.sdg.sliced +++ b/sdg-core/src/test/res/regression/programs/cfg/Eval_1.java.sdg.sliced @@ -8,6 +8,12 @@ public class Eval_1 { int x = 1; one: while (x <= 10) { x++; + while (x <= 10) { + if (x > 0) { + continue one; + } else + x++; + } } do { x--; diff --git a/sdg-core/src/test/res/regression/programs/cfg/Eval_2.java.sdg.sliced b/sdg-core/src/test/res/regression/programs/cfg/Eval_2.java.sdg.sliced index ee31854..1efef45 100644 --- a/sdg-core/src/test/res/regression/programs/cfg/Eval_2.java.sdg.sliced +++ b/sdg-core/src/test/res/regression/programs/cfg/Eval_2.java.sdg.sliced @@ -4,6 +4,15 @@ public class Eval_2 { public static void main(String[] args) { int x = 1; + if (x <= 1) { + if (x <= 2) { + if (x <= 3) { + x++; + } else + x--; + } else + x--; + } System.out.println(x); } } diff --git a/sdg-core/src/test/res/regression/programs/cfg/Eval_3.java.sdg.sliced b/sdg-core/src/test/res/regression/programs/cfg/Eval_3.java.sdg.sliced index 05636d5..87b30f4 100644 --- a/sdg-core/src/test/res/regression/programs/cfg/Eval_3.java.sdg.sliced +++ b/sdg-core/src/test/res/regression/programs/cfg/Eval_3.java.sdg.sliced @@ -4,5 +4,19 @@ public class Eval_3 { public static void main(String[] args) { int x = 1; + while (x > 0) { + if (x <= 1) { + x--; + } else if (x <= 2) { + if (x <= 3) { + x++; + } else { + x--; + while (x > 1) { + x--; + } + } + } + } } } diff --git a/sdg-core/src/test/res/regression/programs/pdg/Test.java.sdg.sliced b/sdg-core/src/test/res/regression/programs/pdg/Test.java.sdg.sliced index 883158f..84cf2b1 100644 --- a/sdg-core/src/test/res/regression/programs/pdg/Test.java.sdg.sliced +++ b/sdg-core/src/test/res/regression/programs/pdg/Test.java.sdg.sliced @@ -4,6 +4,11 @@ public class Test { public static void main(String[] args) { int a = 0; + while (a > 0) { + if (a > 100) + continue; + a++; + } System.out.println(a); } } diff --git a/sdg-core/src/test/res/regression/review-07-2020/P3.java.sdg.sliced b/sdg-core/src/test/res/regression/review-07-2020/P3.java.sdg.sliced index d722393..29d44d2 100644 --- a/sdg-core/src/test/res/regression/review-07-2020/P3.java.sdg.sliced +++ b/sdg-core/src/test/res/regression/review-07-2020/P3.java.sdg.sliced @@ -2,11 +2,16 @@ public class Bucles { public static void main(String[] args) { int x = 2; + try { + if (x == 0) + throw new ExceptionA(); + if (x == 1) + throw new ExceptionB(); + if (x == 2) + throw new Exception(); + } catch (ExceptionA a) { + } catch (Exception a) { + System.out.println("Se lanza Exception"); + } } } - -class ExceptionA extends Exception { -} - -class ExceptionB extends ExceptionA { -} diff --git a/sdg-core/src/test/res/regression/review-07-2020/P4.java.sdg.sliced b/sdg-core/src/test/res/regression/review-07-2020/P4.java.sdg.sliced index 1c388f1..6907e2e 100644 --- a/sdg-core/src/test/res/regression/review-07-2020/P4.java.sdg.sliced +++ b/sdg-core/src/test/res/regression/review-07-2020/P4.java.sdg.sliced @@ -1,12 +1,27 @@ public class Bucles { public static void main(String[] args) { + try { + metodoGeneradorExcepciones(); + } catch (ExceptionB a) { + main(args); + } catch (ExceptionA a) { + main(args); + } catch (Exception a) { + main(args); + } System.out.println("No se lanza ninguna excepcion"); } -} - -class ExceptionA extends Exception { -} -class ExceptionB extends ExceptionA { + static void metodoGeneradorExcepciones() throws Exception { + if (x == 0) { + throw new ExceptionA(); + } + if (x == 1) { + throw new ExceptionB(); + } + if (x == 2) { + throw new Exception(); + } + } } diff --git a/sdg-core/src/test/res/regression/review-07-2020/P6.java.sdg.sliced b/sdg-core/src/test/res/regression/review-07-2020/P6.java.sdg.sliced index c8e0f9f..b2595e2 100644 --- a/sdg-core/src/test/res/regression/review-07-2020/P6.java.sdg.sliced +++ b/sdg-core/src/test/res/regression/review-07-2020/P6.java.sdg.sliced @@ -1,12 +1,10 @@ public class Bucles { public static void main(String[] args) { - int x = 2; try { for (int i = 0; i <= 12; i++) { metodoGeneradorExcepciones(x); } - } catch (ExceptionB a) { } catch (ExceptionA a) { } catch (Exception a) { System.out.println("Se lanza Exception"); @@ -22,9 +20,3 @@ public class Bucles { throw new Exception(); } } - -class ExceptionA extends Exception { -} - -class ExceptionB extends ExceptionA { -} -- GitLab From f8b7a13a711adb2fc2594e77808b895ac27cf75b Mon Sep 17 00:00:00 2001 From: Carlos Galindo Date: Sat, 27 Feb 2021 02:30:22 +0100 Subject: [PATCH 31/33] Add implicit constructors * Small regression: only the last field declared in a constructor is included. This is expected, and will be solved with the new object dependencies. * Integrate ImplicitNode as boolean in GraphNode. * Updated tests * Slice now allows the insertion of implicit instructions, but does not output them when generating the AST. * Removed list of nodes from slice, as the map contains a superset of the information of the list. --- .../slicing/graphs/jsysdg/ImplicitNode.java | 15 --------- .../mist/slicing/graphs/jsysdg/JSysCFG.java | 33 +++++++++++++++---- .../mist/slicing/graphs/jsysdg/JSysDG.java | 30 ++++++++++++++++- .../mist/slicing/graphs/jsysdg/JSysPDG.java | 7 ++-- .../es/upv/mist/slicing/graphs/pdg/PDG.java | 2 ++ .../es/upv/mist/slicing/nodes/GraphNode.java | 19 +++++++++++ .../es/upv/mist/slicing/slicing/Slice.java | 23 ++++--------- .../dinsa-tests/Josep2.java.sdg.sliced | 2 ++ .../dinsa-tests/Josep9.java.sdg.sliced | 2 ++ .../review-07-2020/P5.java.sdg.sliced | 2 ++ 10 files changed, 95 insertions(+), 40 deletions(-) delete mode 100644 sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/ImplicitNode.java diff --git a/sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/ImplicitNode.java b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/ImplicitNode.java deleted file mode 100644 index 1bb2a29..0000000 --- a/sdg-core/src/main/java/es/upv/mist/slicing/graphs/jsysdg/ImplicitNode.java +++ /dev/null @@ -1,15 +0,0 @@ -package es.upv.mist.slicing.graphs.jsysdg; - -import com.github.javaparser.ast.Node; -import es.upv.mist.slicing.nodes.SyntheticNode; - -/** - * A graph node that does not exist in the original program, but represents - * implicit code constructs such as 'super()' at the start of a constructor. - * @param The type of the AST node contained in this graph node. - */ -public class ImplicitNode extends SyntheticNode { - protected ImplicitNode(String instruction, T astNode) { - super(instruction, astNode); - } -} 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 f11d49d..f43e32a 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 @@ -2,6 +2,7 @@ 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; @@ -12,10 +13,12 @@ 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; +import es.upv.mist.slicing.nodes.io.MethodExitNode; import es.upv.mist.slicing.utils.ASTUtils; import java.util.LinkedList; import java.util.List; +import java.util.Set; /** * An SDG that is tailored for Java, including a class graph, inheritance, @@ -24,10 +27,20 @@ import java.util.List; 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){ + public JSysCFG(ClassGraph classGraph, Set implicitConstructors) { super(); this.classGraph = classGraph; + this.implicitConstructors = implicitConstructors; + } + + @Override + public void buildRootNode(CallableDeclaration rootNodeAst) { + super.buildRootNode(rootNodeAst); + if (implicitConstructors.contains(rootNodeAst)) + rootNode.markAsImplicit(); } @Override @@ -39,6 +52,8 @@ public class JSysCFG extends ESCFG { /** List of implicit instructions inserted explicitly in this CFG. * They should be included in the graph as ImplicitNodes. */ protected List methodInsertedInstructions = new LinkedList<>(); + /** Whether we are building a CFG for an implicit method or not. */ + protected boolean implicitDeclaration = false; protected Builder(JSysCFG jSysCFG) { super(JSysCFG.this); @@ -48,11 +63,10 @@ public class JSysCFG extends ESCFG { @Override protected GraphNode connectTo(T n, String text) { GraphNode dest; - if (methodInsertedInstructions.contains(n)) { - dest = new ImplicitNode<>(n.toString(), n); - } else { - dest = new GraphNode<>(text, n); - } + dest = new GraphNode<>(text, n); + if (methodInsertedInstructions.contains(n) || + (implicitDeclaration && !(n instanceof FieldDeclaration))) + dest.markAsImplicit(); addVertex(dest); connectTo(dest); return dest; @@ -79,6 +93,8 @@ 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<>()); @@ -90,6 +106,11 @@ 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) + 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 9d5ecee..eaf5a36 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 @@ -1,10 +1,18 @@ 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.ClassOrInterfaceDeclaration; +import com.github.javaparser.ast.body.ConstructorDeclaration; +import com.github.javaparser.ast.visitor.ModifierVisitor; +import com.github.javaparser.ast.visitor.Visitable; import es.upv.mist.slicing.graphs.augmented.PSDG; import es.upv.mist.slicing.graphs.cfg.CFG; import es.upv.mist.slicing.graphs.exceptionsensitive.ESSDG; import es.upv.mist.slicing.graphs.exceptionsensitive.ExceptionSensitiveCallConnector; import es.upv.mist.slicing.graphs.pdg.PDG; +import es.upv.mist.slicing.utils.NodeHashSet; public class JSysDG extends ESSDG { @@ -17,9 +25,29 @@ public class JSysDG extends ESSDG { * @see PSDG.Builder * @see ExceptionSensitiveCallConnector */ class Builder extends ESSDG.Builder { + protected NodeHashSet newlyInsertedConstructors = new NodeHashSet<>(); + + @Override + public void build(NodeList nodeList) { + insertImplicitConstructors(nodeList); + super.build(nodeList); + } + + /** Create implicit constructors, and store them in a set so that they may be built with implicit nodes. */ + protected void insertImplicitConstructors(NodeList nodeList) { + nodeList.accept(new ModifierVisitor<>() { + @Override + public Visitable visit(ClassOrInterfaceDeclaration n, Object arg) { + if (n.getConstructors().isEmpty()) + newlyInsertedConstructors.add(n.addConstructor(Modifier.Keyword.PUBLIC)); + return super.visit(n, arg); + } + }, null); + } + @Override protected CFG createCFG() { - return new JSysCFG(classGraph); + return new JSysCFG(classGraph, newlyInsertedConstructors); } @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 f86f92d..abd225e 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,11 +1,14 @@ 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 clg) { - this(new JSysCFG(clg)); + public JSysPDG(ClassGraph classGraph, Set implicitConstructors) { + this(new JSysCFG(classGraph, implicitConstructors)); } public JSysPDG(JSysCFG cfg) { diff --git a/sdg-core/src/main/java/es/upv/mist/slicing/graphs/pdg/PDG.java b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/pdg/PDG.java index d361b90..1014998 100644 --- a/sdg-core/src/main/java/es/upv/mist/slicing/graphs/pdg/PDG.java +++ b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/pdg/PDG.java @@ -122,6 +122,8 @@ public class PDG extends GraphWithRootNode> { callNodeStack.pop(); } else { CallNode callNode = CallNode.create(((VariableAction.CallMarker) action).getCall()); + if (graphNode.isImplicitInstruction()) + callNode.markAsImplicit(); addVertex(callNode); addControlDependencyArc(graphNode, callNode); callNodeStack.push(callNode); diff --git a/sdg-core/src/main/java/es/upv/mist/slicing/nodes/GraphNode.java b/sdg-core/src/main/java/es/upv/mist/slicing/nodes/GraphNode.java index 0527f09..faa1e5a 100644 --- a/sdg-core/src/main/java/es/upv/mist/slicing/nodes/GraphNode.java +++ b/sdg-core/src/main/java/es/upv/mist/slicing/nodes/GraphNode.java @@ -30,6 +30,9 @@ public class GraphNode implements Comparable> { /** The method calls contained */ protected final List> methodCalls = new LinkedList<>(); + /** @see #isImplicitInstruction() */ + protected boolean isImplicit = false; + /** Create a graph node, with id and variable actions generated automatically. */ public GraphNode(String label, N astNode) { this(IdHelper.getInstance().getNextId(), label, astNode); @@ -87,6 +90,22 @@ public class GraphNode implements Comparable> { return label; } + /** Marks the current node as implicit. + * @see #isImplicitInstruction() */ + public void markAsImplicit() { + this.isImplicit = true; + variableActions.stream() + .filter(VariableAction.Movable.class::isInstance) + .map(VariableAction.Movable.class::cast) + .map(VariableAction.Movable::getRealNode) + .forEach(GraphNode::markAsImplicit); + } + + /** Whether this graph node represents an AST node that didn't exist explicitly, such as 'super()'. */ + public boolean isImplicitInstruction() { + return isImplicit; + } + // ============================================================= // =================== Variables and Calls =================== // ============================================================= diff --git a/sdg-core/src/main/java/es/upv/mist/slicing/slicing/Slice.java b/sdg-core/src/main/java/es/upv/mist/slicing/slicing/Slice.java index b28d9d8..22ef03f 100644 --- a/sdg-core/src/main/java/es/upv/mist/slicing/slicing/Slice.java +++ b/sdg-core/src/main/java/es/upv/mist/slicing/slicing/Slice.java @@ -4,7 +4,6 @@ import com.github.javaparser.ast.CompilationUnit; import com.github.javaparser.ast.Node; import com.github.javaparser.ast.NodeList; import com.github.javaparser.ast.visitor.CloneVisitor; -import es.upv.mist.slicing.graphs.jsysdg.ImplicitNode; import es.upv.mist.slicing.nodes.GraphNode; import es.upv.mist.slicing.utils.ASTUtils; import es.upv.mist.slicing.utils.NodeHashSet; @@ -17,16 +16,11 @@ import java.util.*; public class Slice { /** Nodes contained in this slice, mapped by id. */ private final Map> map = new HashMap<>(); - /** The AST nodes contained in this slice. */ - private final List nodes = new LinkedList<>(); /** Add a node to this slice. */ public void add(GraphNode node) { assert !map.containsKey(node.getId()); - if (this.isASTOriginalNode(node)) { - map.put(node.getId(), node); - nodes.add(node.getAstNode()); - } + map.put(node.getId(), node); } /** Add multiple nodes to this slice. */ @@ -41,7 +35,7 @@ public class Slice { /** Whether the slice contains the given AST node. */ public boolean contains(Node node) { - return nodes.stream().anyMatch(n -> n == node); + return map.values().stream().anyMatch(gn -> gn.getAstNode() == node); } @Override @@ -65,11 +59,13 @@ public class Slice { Map> cuMap = ASTUtils.newIdentityHashMap(); // Add each node to the corresponding bucket of the map // Nodes may not belong to a compilation unit (fictional nodes), and they are skipped for the slice. - for (Node node : nodes) { - Optional cu = node.findCompilationUnit(); + for (GraphNode graphNode : map.values()) { + if (graphNode.isImplicitInstruction()) + continue; + Optional cu = graphNode.getAstNode().findCompilationUnit(); if (cu.isEmpty()) continue; cuMap.computeIfAbsent(cu.get(), compilationUnit -> new NodeHashSet<>()); - cuMap.get(cu.get()).add(node); + cuMap.get(cu.get()).add(graphNode.getAstNode()); } // Traverse the AST of each compilation unit, creating a copy and // removing any element not present in the slice. @@ -86,9 +82,4 @@ public class Slice { } return cus; } - - /** Returns whether a node was in the original AST or was added by instrumentation. */ - private boolean isASTOriginalNode(GraphNode node){ - return !(node instanceof ImplicitNode); - } } diff --git a/sdg-core/src/test/res/regression/dinsa-tests/Josep2.java.sdg.sliced b/sdg-core/src/test/res/regression/dinsa-tests/Josep2.java.sdg.sliced index 49c80ed..0740208 100644 --- a/sdg-core/src/test/res/regression/dinsa-tests/Josep2.java.sdg.sliced +++ b/sdg-core/src/test/res/regression/dinsa-tests/Josep2.java.sdg.sliced @@ -21,6 +21,8 @@ public class Josep2 { class Numeros { + int noHaceFalta = 1; + int random() { return haceFalta; } diff --git a/sdg-core/src/test/res/regression/dinsa-tests/Josep9.java.sdg.sliced b/sdg-core/src/test/res/regression/dinsa-tests/Josep9.java.sdg.sliced index fc8b83a..d20b0aa 100644 --- a/sdg-core/src/test/res/regression/dinsa-tests/Josep9.java.sdg.sliced +++ b/sdg-core/src/test/res/regression/dinsa-tests/Josep9.java.sdg.sliced @@ -1,5 +1,7 @@ class A { + int xA = 0; + int getx() { return xA; } diff --git a/sdg-core/src/test/res/regression/review-07-2020/P5.java.sdg.sliced b/sdg-core/src/test/res/regression/review-07-2020/P5.java.sdg.sliced index 49c80ed..0740208 100644 --- a/sdg-core/src/test/res/regression/review-07-2020/P5.java.sdg.sliced +++ b/sdg-core/src/test/res/regression/review-07-2020/P5.java.sdg.sliced @@ -21,6 +21,8 @@ public class Josep2 { class Numeros { + int noHaceFalta = 1; + int random() { return haceFalta; } -- GitLab From 20b60fed91b61856b330062b7ddb21b23800bc03 Mon Sep 17 00:00:00 2001 From: Carlos Galindo Date: Sat, 27 Feb 2021 12:21:42 +0100 Subject: [PATCH 32/33] remove unrelated comments from test case --- .../res/regression/dinsa-tests/Josep8.java | 43 ------------------- 1 file changed, 43 deletions(-) diff --git a/sdg-core/src/test/res/regression/dinsa-tests/Josep8.java b/sdg-core/src/test/res/regression/dinsa-tests/Josep8.java index e6cfcfe..8a6cef7 100644 --- a/sdg-core/src/test/res/regression/dinsa-tests/Josep8.java +++ b/sdg-core/src/test/res/regression/dinsa-tests/Josep8.java @@ -44,46 +44,3 @@ class B extends A{ void noModificaxA() {System.out.println("useless");} void siModificaxA(int v) {super.siModificaxA(v);} } - -// 1. :D Definir this como -output- al final de los constructores. -// 2. Hay que copiar el arbol al usar un Movable para generar un nodo. -// 3. Hay que utilizar el arbol para generar el arbol de nodos correspondiente -// 4. En las llamadas a super que se resuelven a Object.super(), hay que definir 'this'. -// Por tanto todos los constructores empezaran [in]directamente por una definciion de this, -// y 'this' nunca se buscara en Interprocedural*Finder - - -// PARA RESOLVER problemas con this -/* -2. Cada vez que se define/usa un miembro, se realiza la misma accion para todos -los padres en el arbol (use(a.x) es tambien use(a)): podemos utilizar el arbol de ayer -3. siempre conectemos una actual/formal a un uso/def tenemos que copiar el arbol -(en actual cambiando el nombre de la raiz -- cambiar raiz y todos sus arcos). - */ -/* -Interprocedural*Finder: cuando se define this en un constructor hay qeu pasarlo de vuelta -a) es una creacion de obj normal: se traduce como retorno de la llamada. -b) es una creacion de obj con super()/this(): se traduce a 'this': se copia el arbol - */ -/* -cuando super() defina x, y, z, la salida DEF(this) que contendra las variables definidas. -buscara un DEC(this) y lo encontrara justo antes (INTRA) -el DEF(this) servira como elemento INTRA para enlazar el resto de statements del constr. - */ - -/* -Preservar el orden de acciones al usar arboles: -Cuando se encuentra una accion repetida (e.g. USE(a.x), DEF(a.x), **USE(a.x)**), -tenemos que quitar del Factory la accion vieja (el primer USE(a.x), que sea un USE(a) -y contendra en su arbol (a.x)). - -Ejemplo: -print(a.x++ + a.x); USE(a.x), DEF(a.x), USE(a.x) -Y despues de la visita se tratan las definiciones, pasando a ser: -USE(a.x), USE(a), DEF(a.x), DEF(a), USE(a.x), USE(a) -Modificamos el Interprocedural*Finder para solo tratar los elementos raiz. -Incluso podemos incluir una referencia al hijo en el raiz (USE(a) contiene USE(a.x)) - -Problema: -print(a.y++ + a.x + a.x++): - */ \ No newline at end of file -- GitLab From 639bd5b6ba2630fecba75b912564eb6d2e00353b Mon Sep 17 00:00:00 2001 From: Carlos Galindo Date: Mon, 1 Mar 2021 11:20:03 +0100 Subject: [PATCH 33/33] Remove {Tri,Quad}Consumer classes --- .../mist/slicing/nodes/VariableVisitor.java | 73 ++++++++++++------- .../upv/mist/slicing/utils/QuadConsumer.java | 5 -- .../upv/mist/slicing/utils/TriConsumer.java | 5 -- 3 files changed, 46 insertions(+), 37 deletions(-) delete mode 100644 sdg-core/src/main/java/es/upv/mist/slicing/utils/QuadConsumer.java delete mode 100644 sdg-core/src/main/java/es/upv/mist/slicing/utils/TriConsumer.java 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 1d06a7f..fff9573 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 @@ -17,8 +17,6 @@ import es.upv.mist.slicing.graphs.GraphNodeContentVisitor; import es.upv.mist.slicing.nodes.io.CallNode; import es.upv.mist.slicing.utils.ASTUtils; import es.upv.mist.slicing.utils.Logger; -import es.upv.mist.slicing.utils.QuadConsumer; -import es.upv.mist.slicing.utils.TriConsumer; import java.util.Deque; import java.util.LinkedList; @@ -52,16 +50,12 @@ public class VariableVisitor extends GraphNodeContentVisitor, Expression, String> BLANK_TRICONSUMER = (a, b, c) -> {}; - protected static final QuadConsumer, Expression, String, Expression> BLANK_QUADCONSUMER = (a, b, c, d) -> {}; - /** The action to perform when a declaration is found. */ - protected final TriConsumer, Expression, String> declConsumer; + protected final DeclarationConsumer declConsumer; /** The action to perform when a definition is found. */ - protected final QuadConsumer, Expression, String, Expression> defConsumer; + protected final DefinitionConsumer defConsumer; /** The action to perform when a usage is found. */ - protected final TriConsumer, Expression, String> useConsumer; + protected final UsageConsumer useConsumer; /** A stack with the last definition expression, to provide it when a variable definition is found. */ protected final Deque definitionStack = new LinkedList<>(); @@ -74,12 +68,10 @@ public class VariableVisitor extends GraphNodeContentVisitor, Expression, String> declConsumer, - QuadConsumer, Expression, String, Expression> defConsumer, - TriConsumer, Expression, String> useConsumer) { - this.declConsumer = Objects.requireNonNullElse(declConsumer, BLANK_TRICONSUMER); - this.defConsumer = Objects.requireNonNullElse(defConsumer, BLANK_QUADCONSUMER); - this.useConsumer = Objects.requireNonNullElse(useConsumer, BLANK_TRICONSUMER); + public VariableVisitor(DeclarationConsumer declConsumer, DefinitionConsumer defConsumer, UsageConsumer useConsumer) { + this.declConsumer = Objects.requireNonNullElse(declConsumer, DeclarationConsumer.defaultConsumer()); + this.defConsumer = Objects.requireNonNullElse(defConsumer, DefinitionConsumer.defaultConsumer()); + this.useConsumer = Objects.requireNonNullElse(useConsumer, UsageConsumer.defaultConsumer()); } public void visitAsDefinition(Node node, Expression value, Action action) { @@ -130,14 +122,14 @@ public class VariableVisitor extends GraphNodeContentVisitor { init.accept(this, action); - defConsumer.accept(graphNode, null, realName, init); + defConsumer.acceptDefinition(graphNode, null, realName, init); }); } } @@ -236,10 +228,10 @@ public class VariableVisitor extends GraphNodeContentVisitor ASTUtils.initializerForField(n)); init.accept(this, action); - defConsumer.accept(graphNode, null, realName, init); + defConsumer.acceptDefinition(graphNode, null, realName, init); } } @@ -251,8 +243,8 @@ public class VariableVisitor extends GraphNodeContentVisitor graphNode, Expression variable, String realName); + + static DeclarationConsumer defaultConsumer() { + return (a, b, c) -> {}; + } + } + + @FunctionalInterface + public interface DefinitionConsumer { + void acceptDefinition(GraphNode graphNode, Expression variable, String realName, Expression valueAssigned); + + static DefinitionConsumer defaultConsumer() { + return (a, b, c, d) -> {}; + } + } + + @FunctionalInterface + public interface UsageConsumer { + void acceptUsage(GraphNode graphNode, Expression variable, String realName); + + static UsageConsumer defaultConsumer() { + return (a, b, c) -> {}; + } + } } diff --git a/sdg-core/src/main/java/es/upv/mist/slicing/utils/QuadConsumer.java b/sdg-core/src/main/java/es/upv/mist/slicing/utils/QuadConsumer.java deleted file mode 100644 index 8335256..0000000 --- a/sdg-core/src/main/java/es/upv/mist/slicing/utils/QuadConsumer.java +++ /dev/null @@ -1,5 +0,0 @@ -package es.upv.mist.slicing.utils; - -public interface QuadConsumer { - void accept(T arg1, U arg2, V arg3, W arg4); -} diff --git a/sdg-core/src/main/java/es/upv/mist/slicing/utils/TriConsumer.java b/sdg-core/src/main/java/es/upv/mist/slicing/utils/TriConsumer.java deleted file mode 100644 index fe933c2..0000000 --- a/sdg-core/src/main/java/es/upv/mist/slicing/utils/TriConsumer.java +++ /dev/null @@ -1,5 +0,0 @@ -package es.upv.mist.slicing.utils; - -public interface TriConsumer { - void accept(T arg1, U arg2, V arg3); -} -- GitLab