From d9c2084d7b12c4612e4549e38d769a73538b2c21 Mon Sep 17 00:00:00 2001 From: Carlos Galindo Date: Mon, 18 Jan 2021 23:40:55 +0100 Subject: [PATCH 1/5] Replace Set with IdentityHashSet or NodeHashSet --- .../graphs/BackwardDataFlowAnalysis.java | 3 +- .../es/upv/mist/slicing/graphs/CallGraph.java | 7 +- .../ConditionalControlDependencyBuilder.java | 17 ++-- .../es/upv/mist/slicing/graphs/sdg/SDG.java | 7 +- .../es/upv/mist/slicing/slicing/Slice.java | 8 +- .../slicing/slicing/SlicePruneVisitor.java | 46 +++++----- .../es/upv/mist/slicing/utils/ASTUtils.java | 34 +++++-- .../slicing/utils/CustomEqualityHashSet.java | 92 +++++++++++++++++++ .../upv/mist/slicing/utils/NodeHashSet.java | 32 +++++++ 9 files changed, 200 insertions(+), 46 deletions(-) create mode 100644 sdg-core/src/main/java/es/upv/mist/slicing/utils/CustomEqualityHashSet.java create mode 100644 sdg-core/src/main/java/es/upv/mist/slicing/utils/NodeHashSet.java diff --git a/sdg-core/src/main/java/es/upv/mist/slicing/graphs/BackwardDataFlowAnalysis.java b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/BackwardDataFlowAnalysis.java index 6c7e7b7..0f64648 100644 --- a/sdg-core/src/main/java/es/upv/mist/slicing/graphs/BackwardDataFlowAnalysis.java +++ b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/BackwardDataFlowAnalysis.java @@ -1,5 +1,6 @@ package es.upv.mist.slicing.graphs; +import es.upv.mist.slicing.utils.ASTUtils; import org.jgrapht.graph.AbstractGraph; import java.util.*; @@ -34,7 +35,7 @@ public abstract class BackwardDataFlowAnalysis { List newWorkList = new LinkedList<>(); for (V vertex : workList) { Set mayAffectVertex = graph.outgoingEdgesOf(vertex).stream() - .map(graph::getEdgeTarget).collect(Collectors.toCollection(() -> Collections.newSetFromMap(new IdentityHashMap<>()))); + .map(graph::getEdgeTarget).collect(Collectors.toCollection(ASTUtils::newIdentityHashSet)); D newValue = compute(vertex, mayAffectVertex); if (!Objects.equals(vertexDataMap.get(vertex), newValue)) { vertexDataMap.put(vertex, newValue); diff --git a/sdg-core/src/main/java/es/upv/mist/slicing/graphs/CallGraph.java b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/CallGraph.java index 75c407b..ea738c4 100644 --- a/sdg-core/src/main/java/es/upv/mist/slicing/graphs/CallGraph.java +++ b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/CallGraph.java @@ -21,7 +21,10 @@ import org.jgrapht.graph.DefaultEdge; import org.jgrapht.graph.DirectedPseudograph; import org.jgrapht.nio.dot.DOTExporter; -import java.util.*; +import java.util.Deque; +import java.util.LinkedList; +import java.util.Map; +import java.util.Objects; /** * A directed graph which displays the available method declarations as nodes and their @@ -37,7 +40,7 @@ import java.util.*; */ public class CallGraph extends DirectedPseudograph> implements Buildable> { private final Map, CFG> cfgMap; - private final Map, Vertex> vertexDeclarationMap = new IdentityHashMap<>(); + private final Map, Vertex> vertexDeclarationMap = ASTUtils.newIdentityHashMap(); private boolean built = false; diff --git a/sdg-core/src/main/java/es/upv/mist/slicing/graphs/exceptionsensitive/ConditionalControlDependencyBuilder.java b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/exceptionsensitive/ConditionalControlDependencyBuilder.java index ad33155..a035ba5 100644 --- a/sdg-core/src/main/java/es/upv/mist/slicing/graphs/exceptionsensitive/ConditionalControlDependencyBuilder.java +++ b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/exceptionsensitive/ConditionalControlDependencyBuilder.java @@ -14,6 +14,7 @@ import es.upv.mist.slicing.nodes.exceptionsensitive.NormalReturnNode; import es.upv.mist.slicing.nodes.exceptionsensitive.ReturnNode; import es.upv.mist.slicing.slicing.PseudoPredicateSlicingAlgorithm; import es.upv.mist.slicing.utils.ASTUtils; +import es.upv.mist.slicing.utils.NodeHashSet; import es.upv.mist.slicing.utils.Utils; import java.util.HashSet; @@ -70,7 +71,7 @@ public class ConditionalControlDependencyBuilder { /** Create the {@link ConditionalControlDependencyArc.CC2 CC2} * arcs associated to a given {@link CatchClause}. */ protected void buildCC2(GraphNode cc) { - Set tryBlockInstructs = getTryBlockInstructs(cc.getAstNode()); + NodeHashSet tryBlockInstructs = getTryBlockInstructs(cc.getAstNode()); for (Node node : tryBlockInstructs) for (GraphNode dst : pdg.findAllNodes(n -> ASTUtils.equalsWithRangeInCU(n.getAstNode(), node))) if (isExceptionSource(dst) && hasControlDependencePath(dst, cc, tryBlockInstructs)) @@ -78,13 +79,13 @@ public class ConditionalControlDependencyBuilder { } /** Obtains the set of AST nodes found within a given {@link CatchClause}. */ - protected static Set getBlockInstructs(CatchClause cc) { + protected static NodeHashSet getBlockInstructs(CatchClause cc) { return childNodesOf(cc); } /** Obtains the set of AST nodes found within the {@link com.github.javaparser.ast.stmt.TryStmt try} * associated with the given {@link CatchClause}. */ - protected static Set getTryBlockInstructs(CatchClause cc) { + protected static NodeHashSet getTryBlockInstructs(CatchClause cc) { Optional parent = cc.getParentNode(); assert parent.isPresent(); return childNodesOf(parent.get()); @@ -107,7 +108,7 @@ public class ConditionalControlDependencyBuilder { * following the rules of the PPDG traversal. * @see PseudoPredicateSlicingAlgorithm */ - protected boolean hasControlDependencePath(GraphNode a, GraphNode b, Set universe) { + protected boolean hasControlDependencePath(GraphNode a, GraphNode b, NodeHashSet universe) { Set> visited = new HashSet<>(); Set> pending = new HashSet<>(); pending.add(b); @@ -134,13 +135,13 @@ public class ConditionalControlDependencyBuilder { } /** Internal method to find all possible AST nodes that descend from the given argument. */ - protected static Set childNodesOf(Node parent) { - Set result = new HashSet<>(); - Set pending = new HashSet<>(); + protected static NodeHashSet childNodesOf(Node parent) { + NodeHashSet result = new NodeHashSet<>(); + Set pending = new NodeHashSet<>(); pending.add(parent); while (!pending.isEmpty()) { - Set newPending = new HashSet<>(); + Set newPending = new NodeHashSet<>(); for (Node n : pending) { newPending.addAll(n.getChildNodes()); result.add(n); 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..2f0cb03 100644 --- a/sdg-core/src/main/java/es/upv/mist/slicing/graphs/sdg/SDG.java +++ b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/sdg/SDG.java @@ -28,7 +28,10 @@ import es.upv.mist.slicing.nodes.io.CallNode; import es.upv.mist.slicing.slicing.*; import es.upv.mist.slicing.utils.ASTUtils; -import java.util.*; +import java.util.Collection; +import java.util.Map; +import java.util.Optional; +import java.util.Set; /** * The System Dependence Graph represents the statements of a program in @@ -43,7 +46,7 @@ import java.util.*; * */ public class SDG extends Graph implements Sliceable, Buildable> { - protected final Map, CFG> cfgMap = new IdentityHashMap<>(); + protected final Map, CFG> cfgMap = ASTUtils.newIdentityHashMap(); protected boolean built = false; protected NodeList compilationUnits; 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..92e273b 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 @@ -5,6 +5,8 @@ import com.github.javaparser.ast.Node; import com.github.javaparser.ast.NodeList; import com.github.javaparser.ast.visitor.CloneVisitor; import es.upv.mist.slicing.nodes.GraphNode; +import es.upv.mist.slicing.utils.ASTUtils; +import es.upv.mist.slicing.utils.NodeHashSet; import java.util.*; @@ -57,13 +59,13 @@ public class Slice { /** Organize all nodes pertaining to this slice in one or more CompilationUnits. CompilationUnits * themselves need not be part of the slice to be included if any of their components are present. */ public NodeList toAst() { - Map> cuMap = new IdentityHashMap<>(); + 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(); if (cu.isEmpty()) continue; - cuMap.putIfAbsent(cu.get(), new HashSet<>()); + cuMap.putIfAbsent(cu.get(), new NodeHashSet<>()); cuMap.get(cu.get()).add(node); } // Traverse the AST of each compilation unit, creating a copy and @@ -71,7 +73,7 @@ public class Slice { NodeList cus = new NodeList<>(); SlicePruneVisitor sliceVisitor = new SlicePruneVisitor(); CloneVisitor cloneVisitor = new CloneVisitor(); - for (Map.Entry> entry : cuMap.entrySet()) { + for (Map.Entry> entry : cuMap.entrySet()) { CompilationUnit clone = (CompilationUnit) entry.getKey().accept(cloneVisitor, null); if (entry.getKey().getStorage().isPresent()) clone.setStorage(entry.getKey().getStorage().get().getPath(), 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 4ffd20c..6381413 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 @@ -12,14 +12,14 @@ import com.github.javaparser.ast.nodeTypes.NodeWithBody; import com.github.javaparser.ast.stmt.*; import com.github.javaparser.ast.visitor.ModifierVisitor; import com.github.javaparser.ast.visitor.Visitable; +import es.upv.mist.slicing.utils.NodeHashSet; -import java.util.Set; import java.util.stream.Collectors; /** Given an AST tree and a slice, removes or prunes all nodes that are not * included in the slice. Some nodes are included if they are present in the slice * or of any of their children are (as is the case with {@link CompilationUnit}s). */ -public class SlicePruneVisitor extends ModifierVisitor> { +public class SlicePruneVisitor extends ModifierVisitor> { // ========== Utility methods ========== /** Place a valid placeholder in this node's body, if any. */ @@ -34,14 +34,14 @@ public class SlicePruneVisitor extends ModifierVisitor> { // ========== File visitors ========== @Override - public Visitable visit(CompilationUnit n, Set arg) { + public Visitable visit(CompilationUnit n, NodeHashSet arg) { boolean keep = arg.contains(n); Visitable v = super.visit(n, arg); return keep || !((Node) v).getChildNodes().isEmpty() ? v : null; } @Override - public Visitable visit(ClassOrInterfaceDeclaration n, Set arg) { + 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; @@ -50,21 +50,21 @@ public class SlicePruneVisitor extends ModifierVisitor> { // ========== Class body visitors ========== @Override - public Visitable visit(MethodDeclaration n, Set arg) { + public Visitable visit(MethodDeclaration n, NodeHashSet arg) { boolean keep = arg.contains(n); Visitable v = super.visit(n, arg); return keep ? v : null; } @Override - public Visitable visit(ConstructorDeclaration n, Set arg) { + public Visitable visit(ConstructorDeclaration n, NodeHashSet arg) { boolean keep = arg.contains(n); Visitable v = super.visit(n, arg); return keep ? v : null; } @Override - public Visitable visit(FieldDeclaration n, Set arg) { + public Visitable visit(FieldDeclaration n, NodeHashSet arg) { boolean keep = arg.contains(n); Visitable v = super.visit(n, arg); return keep ? v : null; @@ -77,17 +77,17 @@ public class SlicePruneVisitor extends ModifierVisitor> { // c. With relevant children and included if any children is included OR if on the slice (e.g. SwitchEntryStmt, LabeledStmt) @Override - public Visitable visit(BreakStmt n, Set arg) { + public Visitable visit(BreakStmt n, NodeHashSet arg) { return arg.contains(n) ? n : null; } @Override - public Visitable visit(ContinueStmt n, Set arg) { + public Visitable visit(ContinueStmt n, NodeHashSet arg) { return arg.contains(n) ? n : null; } @Override - public Visitable visit(DoStmt n, Set arg) { + public Visitable visit(DoStmt n, NodeHashSet arg) { boolean keep = arg.contains(n); super.visit(n, arg); fillBody(n); @@ -95,7 +95,7 @@ public class SlicePruneVisitor extends ModifierVisitor> { } @Override - public Visitable visit(ForEachStmt n, Set arg) { + public Visitable visit(ForEachStmt n, NodeHashSet arg) { boolean keep = arg.contains(n); super.visit(n, arg); fillBody(n); @@ -103,7 +103,7 @@ public class SlicePruneVisitor extends ModifierVisitor> { } @Override - public Visitable visit(ForStmt n, Set arg) { + public Visitable visit(ForStmt n, NodeHashSet arg) { boolean keep = arg.contains(n); super.visit(n, arg); n.setInitialization(new NodeList<>(n.getInitialization().stream() @@ -120,7 +120,7 @@ public class SlicePruneVisitor extends ModifierVisitor> { } @Override - public Visitable visit(WhileStmt n, Set arg) { + public Visitable visit(WhileStmt n, NodeHashSet arg) { boolean keep = arg.contains(n); super.visit(n, arg); fillBody(n); @@ -128,7 +128,7 @@ public class SlicePruneVisitor extends ModifierVisitor> { } @Override - public Visitable visit(IfStmt n, Set arg) { + public Visitable visit(IfStmt n, NodeHashSet arg) { boolean keep = arg.contains(n); super.visit(n, arg); if (n.getThenStmt() == null) @@ -137,23 +137,23 @@ public class SlicePruneVisitor extends ModifierVisitor> { } @Override - public Visitable visit(LabeledStmt n, Set arg) { + public Visitable visit(LabeledStmt n, NodeHashSet arg) { super.visit(n, arg); return n.getStatement() != null ? n : null; } @Override - public Visitable visit(ReturnStmt n, Set arg) { + public Visitable visit(ReturnStmt n, NodeHashSet arg) { return arg.contains(n) ? n : null; } @Override - public Visitable visit(ThrowStmt n, Set arg) { + public Visitable visit(ThrowStmt n, NodeHashSet arg) { return arg.contains(n) ? n : null; } @Override - public Visitable visit(SwitchEntry n, Set arg) { + public Visitable visit(SwitchEntry n, NodeHashSet arg) { boolean keep = arg.contains(n); super.visit(n, arg); if (!n.getStatements().isEmpty()) @@ -162,31 +162,31 @@ public class SlicePruneVisitor extends ModifierVisitor> { } @Override - public Visitable visit(SwitchStmt n, Set arg) { + public Visitable visit(SwitchStmt n, NodeHashSet arg) { boolean keep = arg.contains(n); super.visit(n, arg); return keep ? n : null; } @Override - public Visitable visit(ExpressionStmt n, Set arg) { + public Visitable visit(ExpressionStmt n, NodeHashSet arg) { return arg.contains(n) ? n : null; } @Override - public Visitable visit(ExplicitConstructorInvocationStmt n, Set arg) { + public Visitable visit(ExplicitConstructorInvocationStmt n, NodeHashSet arg) { return arg.contains(n) ? n : null; } @Override - public Visitable visit(TryStmt n, Set arg) { + public Visitable visit(TryStmt n, NodeHashSet arg) { boolean keep = arg.contains(n); super.visit(n, arg); return keep ? n : null; } @Override - public Visitable visit(CatchClause n, Set arg) { + public Visitable visit(CatchClause n, NodeHashSet arg) { boolean keep = arg.contains(n); super.visit(n, arg); return keep ? n : null; 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 ba9ed55..b36705a 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 @@ -4,7 +4,6 @@ import com.github.javaparser.ast.Node; import com.github.javaparser.ast.body.CallableDeclaration; import com.github.javaparser.ast.body.ConstructorDeclaration; import com.github.javaparser.ast.body.MethodDeclaration; -import com.github.javaparser.ast.expr.CastExpr; import com.github.javaparser.ast.expr.Expression; import com.github.javaparser.ast.expr.MethodCallExpr; import com.github.javaparser.ast.expr.ObjectCreationExpr; @@ -13,14 +12,13 @@ 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.resolution.Resolvable; -import com.github.javaparser.resolution.declarations.*; -import com.github.javaparser.resolution.types.ResolvedType; -import com.github.javaparser.symbolsolver.model.typesystem.ReferenceTypeImpl; +import com.github.javaparser.resolution.declarations.ResolvedConstructorDeclaration; +import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration; +import com.github.javaparser.resolution.declarations.ResolvedMethodLikeDeclaration; +import com.github.javaparser.resolution.declarations.ResolvedParameterDeclaration; import es.upv.mist.slicing.nodes.GraphNode; -import java.util.List; -import java.util.Objects; -import java.util.Optional; +import java.util.*; /** JavaParser-related utility functions. */ public class ASTUtils { @@ -127,6 +125,27 @@ public class ASTUtils { return shouldVisitArgumentsForMethodCalls(call) || graphNode == null; } + /** + * Creates a new set that is suitable for JavaParser nodes. This + * set behaves by comparing by identity (==) instead of equality (equals()). + * Thus, multiple objects representing the same node will not be identified as + * equal, and duplicates will be inserted. For this use-case, you may use + * {@link NodeHashSet}. + */ + public static Set newIdentityHashSet() { + return Collections.newSetFromMap(new IdentityHashMap<>()); + } + + /** + * Creates a new map that is suitable for JavaParser nodes as keys. This + * map behaves by comparing by identity (==) instead of equality (equals()). + * Thus, multiple objects representing the same node will not be identified as + * equal, and duplicates will be inserted. + */ + public static Map newIdentityHashMap() { + return new IdentityHashMap<>(); + } + /** Converts a type declaration into just a type. */ public static ResolvedType resolvedTypeDeclarationToResolvedType(ResolvedReferenceTypeDeclaration decl) { return new ReferenceTypeImpl(decl, StaticTypeSolver.getTypeSolver()); @@ -155,4 +174,5 @@ public class ASTUtils { } throw new IllegalArgumentException("This operation is only valid for reference type cast operations."); } + } diff --git a/sdg-core/src/main/java/es/upv/mist/slicing/utils/CustomEqualityHashSet.java b/sdg-core/src/main/java/es/upv/mist/slicing/utils/CustomEqualityHashSet.java new file mode 100644 index 0000000..1a55f65 --- /dev/null +++ b/sdg-core/src/main/java/es/upv/mist/slicing/utils/CustomEqualityHashSet.java @@ -0,0 +1,92 @@ +package es.upv.mist.slicing.utils; + +import java.util.*; + +/** + * A customized abstract HashSet, which allows for customization of the equality + * method used to compare objects. To create a child class, just implement the + * abstract methods. + */ +public abstract class CustomEqualityHashSet extends AbstractSet { + /** The underlying collection of objects, each list acts as bucket for colliding hash codes. */ + protected final Map> map; + + protected int size = 0; + + public CustomEqualityHashSet() { + map = new HashMap<>(); + } + + public CustomEqualityHashSet(int initialCapacity) { + map = new HashMap<>(initialCapacity); + } + + public CustomEqualityHashSet(int initialCapacity, float loadFactor) { + map = new HashMap<>(initialCapacity, loadFactor); + } + + /** Compares two objects to determine equality. The objects are assumed to be of type {@link T}. */ + protected abstract boolean objEquals(T a, Object b); + + /** Checks whether the argument is of a compatible class with the set. A + * default implementation could check against {@link Object}. */ + protected abstract boolean objInstanceOf(Object o); + + @Override + public boolean add(T t) { + Objects.requireNonNull(t); + List bucket = map.computeIfAbsent(t.hashCode(), i -> new LinkedList<>()); + if (contains(t, bucket)) + return false; + bucket.add(t); + size++; + return true; + } + + @Override + public boolean remove(Object o) { + if (!objInstanceOf(o)) + return false; + List bucket = map.get(o.hashCode()); + if (bucket == null) + return false; + Iterator it = bucket.iterator(); + while (it.hasNext()) { + T t = it.next(); + if (objEquals(t, o)) { + it.remove(); + size--; + return true; + } + } + return false; // matching element not found + } + + @Override + public boolean contains(Object o) { + List bucket = map.get(o.hashCode()); + if (bucket == null) + return false; + return contains(o, bucket); + } + + /** Whether the given bucket contains the given object. */ + protected boolean contains(Object o, List bucket) { + if (!objInstanceOf(o)) + return false; + for (T element : bucket) + if (objEquals(element, o)) + return true; + return false; + } + + @Override + public Iterator iterator() { + return map.values().stream().flatMap(Collection::stream).iterator(); + } + + @Override + public int size() { + return size; + } +} diff --git a/sdg-core/src/main/java/es/upv/mist/slicing/utils/NodeHashSet.java b/sdg-core/src/main/java/es/upv/mist/slicing/utils/NodeHashSet.java new file mode 100644 index 0000000..ee99525 --- /dev/null +++ b/sdg-core/src/main/java/es/upv/mist/slicing/utils/NodeHashSet.java @@ -0,0 +1,32 @@ +package es.upv.mist.slicing.utils; + +import com.github.javaparser.ast.Node; + +/** + * A HashSet that implements an appropriate equals method ({@link ASTUtils#equalsWithRangeInCU(Node, Node)}). + * For a set that relies on object identity (==), use {@link ASTUtils#newIdentityHashSet()}. + * @param The specific subclass of Node. + */ +public class NodeHashSet extends CustomEqualityHashSet { + public NodeHashSet() { + super(); + } + + public NodeHashSet(int initialCapacity) { + super(initialCapacity); + } + + public NodeHashSet(int initialCapacity, float loadFactor) { + super(initialCapacity, loadFactor); + } + + @Override + protected boolean objEquals(T a, Object b) { + return ASTUtils.equalsWithRangeInCU(a, (Node) b); + } + + @Override + protected boolean objInstanceOf(Object o) { + return o instanceof Node; + } +} -- GitLab From c020ce1c5480abdc89d404d53905fed6048a18e2 Mon Sep 17 00:00:00 2001 From: Carlos Galindo Date: Tue, 19 Jan 2021 10:23:02 +0100 Subject: [PATCH 2/5] Fix: create sets on demand --- sdg-core/src/main/java/es/upv/mist/slicing/slicing/Slice.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 92e273b..b79d439 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 @@ -65,7 +65,7 @@ public class Slice { for (Node node : nodes) { Optional cu = node.findCompilationUnit(); if (cu.isEmpty()) continue; - cuMap.putIfAbsent(cu.get(), new NodeHashSet<>()); + cuMap.computeIfAbsent(cu.get(), compilationUnit -> new NodeHashSet<>()); cuMap.get(cu.get()).add(node); } // Traverse the AST of each compilation unit, creating a copy and -- GitLab From 3143e5859972b52a79ab7b14c42d0fbf7a2bf3c2 Mon Sep 17 00:00:00 2001 From: Carlos Galindo Date: Tue, 19 Jan 2021 10:23:35 +0100 Subject: [PATCH 3/5] Fix NodeHashSet: changed equality criterion and added removal capabilities to iterator. --- .../slicing/utils/CustomEqualityHashSet.java | 27 ++++++++++++++++++- .../upv/mist/slicing/utils/NodeHashSet.java | 2 +- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/sdg-core/src/main/java/es/upv/mist/slicing/utils/CustomEqualityHashSet.java b/sdg-core/src/main/java/es/upv/mist/slicing/utils/CustomEqualityHashSet.java index 1a55f65..5940e14 100644 --- a/sdg-core/src/main/java/es/upv/mist/slicing/utils/CustomEqualityHashSet.java +++ b/sdg-core/src/main/java/es/upv/mist/slicing/utils/CustomEqualityHashSet.java @@ -80,9 +80,34 @@ public abstract class CustomEqualityHashSet extends AbstractSet { return false; } + @Override + public void clear() { + map.clear(); + size = 0; + } + @Override public Iterator iterator() { - return map.values().stream().flatMap(Collection::stream).iterator(); + Iterator it = map.values().stream().flatMap(Collection::stream).iterator(); + return new Iterator<>() { + T last = null; + + @Override + public boolean hasNext() { + return it.hasNext(); + } + + @Override + public T next() { + return last = it.next(); + } + + @Override + public void remove() { + if (last != null) + CustomEqualityHashSet.this.remove(last); + } + }; } @Override diff --git a/sdg-core/src/main/java/es/upv/mist/slicing/utils/NodeHashSet.java b/sdg-core/src/main/java/es/upv/mist/slicing/utils/NodeHashSet.java index ee99525..bb61e99 100644 --- a/sdg-core/src/main/java/es/upv/mist/slicing/utils/NodeHashSet.java +++ b/sdg-core/src/main/java/es/upv/mist/slicing/utils/NodeHashSet.java @@ -22,7 +22,7 @@ public class NodeHashSet extends CustomEqualityHashSet { @Override protected boolean objEquals(T a, Object b) { - return ASTUtils.equalsWithRangeInCU(a, (Node) b); + return ASTUtils.equalsWithRange(a, (Node) b); } @Override -- GitLab From 5f5562eaa358e57e5d78048967fed8642ca4878b Mon Sep 17 00:00:00 2001 From: Carlos Galindo Date: Tue, 19 Jan 2021 10:50:55 +0100 Subject: [PATCH 4/5] Update expected test results. Expected removal of repeated statements that were incorrectly included in the slice by SlicePruneVisitor without being marked as such by the algorithm. --- .../test/res/regression/dinsa-tests/Josep2.java.sdg.sliced | 4 ---- .../test/res/regression/dinsa-tests/Josep5.java.sdg.sliced | 1 - .../regression/ltd-samples/BasicSwitchDefault.java.sdg.sliced | 1 - .../test/res/regression/ltd-samples/Bucles_3.java.sdg.sliced | 1 - .../test/res/regression/ltd-samples/Bucles_5.java.sdg.sliced | 1 - .../test/res/regression/ltd-samples/Test_9.java.sdg.sliced | 2 -- .../test/res/regression/programs/cfg/Eval_1.java.sdg.sliced | 1 - .../test/res/regression/programs/pdg/Example1.java.sdg.sliced | 1 - .../src/test/res/regression/review-07-2020/P5.java.sdg.sliced | 4 ---- 9 files changed, 16 deletions(-) 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 a22b18d..d9ca3aa 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 @@ -31,8 +31,4 @@ class GrandesNumeros extends Numeros { GrandesNumeros(double x) { haceFalta = 0; } - - int random() { - return haceFalta; - } } 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 f854b69..641233c 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,7 +1,6 @@ class A { A(int newx) { - xA = newx; } int getx() { diff --git a/sdg-core/src/test/res/regression/ltd-samples/BasicSwitchDefault.java.sdg.sliced b/sdg-core/src/test/res/regression/ltd-samples/BasicSwitchDefault.java.sdg.sliced index 66b717c..426f97d 100644 --- a/sdg-core/src/test/res/regression/ltd-samples/BasicSwitchDefault.java.sdg.sliced +++ b/sdg-core/src/test/res/regression/ltd-samples/BasicSwitchDefault.java.sdg.sliced @@ -17,7 +17,6 @@ public class BasicSwitchDefault { break; default: y = -1; - break; } System.out.println(y); } diff --git a/sdg-core/src/test/res/regression/ltd-samples/Bucles_3.java.sdg.sliced b/sdg-core/src/test/res/regression/ltd-samples/Bucles_3.java.sdg.sliced index b269ac3..58160a4 100644 --- a/sdg-core/src/test/res/regression/ltd-samples/Bucles_3.java.sdg.sliced +++ b/sdg-core/src/test/res/regression/ltd-samples/Bucles_3.java.sdg.sliced @@ -5,7 +5,6 @@ public class Bucles_3 { public static void main(String[] args) { int x; x = 1; - x = 1; do { x++; } while (x <= 10); diff --git a/sdg-core/src/test/res/regression/ltd-samples/Bucles_5.java.sdg.sliced b/sdg-core/src/test/res/regression/ltd-samples/Bucles_5.java.sdg.sliced index 7fac87e..6be659b 100644 --- a/sdg-core/src/test/res/regression/ltd-samples/Bucles_5.java.sdg.sliced +++ b/sdg-core/src/test/res/regression/ltd-samples/Bucles_5.java.sdg.sliced @@ -5,7 +5,6 @@ public class Bucles_5 { public static void main(String[] args) { int x = 0; x = 1; - x = 1; do { x++; } while (x <= 10); diff --git a/sdg-core/src/test/res/regression/ltd-samples/Test_9.java.sdg.sliced b/sdg-core/src/test/res/regression/ltd-samples/Test_9.java.sdg.sliced index 54c5660..ed949eb 100644 --- a/sdg-core/src/test/res/regression/ltd-samples/Test_9.java.sdg.sliced +++ b/sdg-core/src/test/res/regression/ltd-samples/Test_9.java.sdg.sliced @@ -21,8 +21,6 @@ public class Test_9 { } x--; } - x--; } - x--; } } 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 3b67b2f..e26a9e4 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 @@ -31,7 +31,6 @@ public class Eval_1 { break; default: x = 5; - break; } System.out.println(x); } diff --git a/sdg-core/src/test/res/regression/programs/pdg/Example1.java.sdg.sliced b/sdg-core/src/test/res/regression/programs/pdg/Example1.java.sdg.sliced index 511bb68..02c4ff4 100644 --- a/sdg-core/src/test/res/regression/programs/pdg/Example1.java.sdg.sliced +++ b/sdg-core/src/test/res/regression/programs/pdg/Example1.java.sdg.sliced @@ -29,7 +29,6 @@ public class Example1 { case 2: case 3: e = 4; - break; } System.out.println(e); } 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 a22b18d..d9ca3aa 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 @@ -31,8 +31,4 @@ class GrandesNumeros extends Numeros { GrandesNumeros(double x) { haceFalta = 0; } - - int random() { - return haceFalta; - } } -- GitLab From c51cc77b3dfc0aa84f1067f826ab8264d5d9ec17 Mon Sep 17 00:00:00 2001 From: Carlos Galindo Date: Tue, 19 Jan 2021 23:46:20 +0100 Subject: [PATCH 5/5] fixup! Replace Set with IdentityHashSet or NodeHashSet --- .../src/main/java/es/upv/mist/slicing/utils/ASTUtils.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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 b36705a..436742d 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 @@ -4,6 +4,7 @@ import com.github.javaparser.ast.Node; import com.github.javaparser.ast.body.CallableDeclaration; import com.github.javaparser.ast.body.ConstructorDeclaration; import com.github.javaparser.ast.body.MethodDeclaration; +import com.github.javaparser.ast.expr.CastExpr; import com.github.javaparser.ast.expr.Expression; import com.github.javaparser.ast.expr.MethodCallExpr; import com.github.javaparser.ast.expr.ObjectCreationExpr; @@ -12,10 +13,9 @@ 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.resolution.Resolvable; -import com.github.javaparser.resolution.declarations.ResolvedConstructorDeclaration; -import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration; -import com.github.javaparser.resolution.declarations.ResolvedMethodLikeDeclaration; -import com.github.javaparser.resolution.declarations.ResolvedParameterDeclaration; +import com.github.javaparser.resolution.declarations.*; +import com.github.javaparser.resolution.types.ResolvedType; +import com.github.javaparser.symbolsolver.model.typesystem.ReferenceTypeImpl; import es.upv.mist.slicing.nodes.GraphNode; import java.util.*; -- GitLab