Loading sdg-core/src/main/java/tfm/slicing/Slice.java +36 −1 Original line number Diff line number Diff line package tfm.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.MethodDeclaration; import com.github.javaparser.ast.visitor.CloneVisitor; import com.github.javaparser.ast.visitor.Visitable; Loading Loading @@ -43,6 +45,39 @@ public class Slice { return Set.copyOf(map.values()); } /** * 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<CompilationUnit> toAst() { Map<CompilationUnit, Set<Node>> cuMap = new HashMap<>(); // Build key set nodes.stream().filter(n -> n instanceof CompilationUnit) .forEach(cu -> cuMap.put((CompilationUnit) cu, new HashSet<>())); // 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) node.findCompilationUnit() .flatMap(n -> Optional.ofNullable(cuMap.get(n))) .ifPresent(set -> set.add(node)); // Traverse the AST of each compilation unit, creating a copy and // removing any element not present in the slice. NodeList<CompilationUnit> cus = new NodeList<>(); SlicePruneVisitor sliceVisitor = new SlicePruneVisitor(); CloneVisitor cloneVisitor = new CloneVisitor(); for (Map.Entry<CompilationUnit, Set<Node>> entry : cuMap.entrySet()) { CompilationUnit clone = (CompilationUnit) entry.getKey().accept(cloneVisitor, null); assert entry.getKey().getStorage().isPresent(); clone.setStorage(entry.getKey().getStorage().get().getPath()); Visitable sliced = clone.accept(sliceVisitor, entry.getValue()); assert sliced instanceof CompilationUnit; cus.add((CompilationUnit) sliced); } return cus; } @Deprecated public Node getAst() { List<GraphNode<?>> methods = map.values().stream().filter(e -> e.getAstNode() instanceof MethodDeclaration).collect(Collectors.toList()); if (methods.size() == 1) { Loading @@ -63,7 +98,7 @@ public class Slice { private MethodDeclaration getMethodAst(Node node) { Visitable clone = node.accept(new CloneVisitor(), null); assert clone instanceof MethodDeclaration; clone.accept(new SliceAstVisitor(), this); clone.accept(new SlicePruneVisitor(), nodes); return ((MethodDeclaration) clone); } } sdg-core/src/main/java/tfm/slicing/SliceAstVisitor.java→sdg-core/src/main/java/tfm/slicing/SlicePruneVisitor.java +171 −0 Original line number Diff line number Diff line package tfm.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.expr.BooleanLiteralExpr; 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 java.util.Set; import java.util.stream.Collectors; public class SliceAstVisitor extends ModifierVisitor<Slice> { public class SlicePruneVisitor extends ModifierVisitor<Set<Node>> { // ========== Utility methods ========== protected void fillBody(Node n) { if (!(n instanceof NodeWithBody)) return; NodeWithBody<?> nb = ((NodeWithBody<?>) n); if (nb.getBody() == null) nb.setBody(new EmptyStmt()); } // ========== File visitors ========== @Override public Visitable visit(CompilationUnit n, Set<Node> arg) { boolean keep = arg.contains(n); Visitable v = super.visit(n, arg); return keep ? v : null; } @Override public Visitable visit(ClassOrInterfaceDeclaration n, Set<Node> arg) { boolean keep = arg.contains(n); Visitable v = super.visit(n, arg); return keep ? v : null; } // ========== Class body visitors ========== @Override public Visitable visit(MethodDeclaration n, Set<Node> arg) { boolean keep = arg.contains(n); Visitable v = super.visit(n, arg); return keep ? v : null; } @Override public Visitable visit(ConstructorDeclaration n, Set<Node> arg) { boolean keep = arg.contains(n); Visitable v = super.visit(n, arg); return keep ? v : null; } @Override public Visitable visit(BreakStmt n, Slice arg) { public Visitable visit(FieldDeclaration n, Set<Node> arg) { boolean keep = arg.contains(n); Visitable v = super.visit(n, arg); return keep ? v : null; } // ========== Method body visitors ========== // 3 alternatives: // a. Without relevant children and included if on the slice or not (e.g. ExpressionStmt) // b. With relevant children and included if of the slice or not, children are discarded if not included (e.g. WhileStmt) // 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<Node> arg) { return arg.contains(n) ? n : null; } @Override public Visitable visit(ContinueStmt n, Slice arg) { public Visitable visit(ContinueStmt n, Set<Node> arg) { return arg.contains(n) ? n : null; } @Override public Visitable visit(DoStmt n, Slice arg) { public Visitable visit(DoStmt n, Set<Node> arg) { boolean keep = arg.contains(n); super.visit(n, arg); fillBody(n); Loading @@ -30,7 +91,7 @@ public class SliceAstVisitor extends ModifierVisitor<Slice> { } @Override public Visitable visit(ForEachStmt n, Slice arg) { public Visitable visit(ForEachStmt n, Set<Node> arg) { boolean keep = arg.contains(n); super.visit(n, arg); fillBody(n); Loading @@ -38,7 +99,7 @@ public class SliceAstVisitor extends ModifierVisitor<Slice> { } @Override public Visitable visit(ForStmt n, Slice arg) { public Visitable visit(ForStmt n, Set<Node> arg) { boolean keep = arg.contains(n); super.visit(n, arg); n.setInitialization(new NodeList<>(n.getInitialization().stream() Loading @@ -55,7 +116,7 @@ public class SliceAstVisitor extends ModifierVisitor<Slice> { } @Override public Visitable visit(WhileStmt n, Slice arg) { public Visitable visit(WhileStmt n, Set<Node> arg) { boolean keep = arg.contains(n); super.visit(n, arg); fillBody(n); Loading @@ -63,7 +124,7 @@ public class SliceAstVisitor extends ModifierVisitor<Slice> { } @Override public Visitable visit(IfStmt n, Slice arg) { public Visitable visit(IfStmt n, Set<Node> arg) { boolean keep = arg.contains(n); super.visit(n, arg); if (n.getThenStmt() == null) Loading @@ -72,23 +133,23 @@ public class SliceAstVisitor extends ModifierVisitor<Slice> { } @Override public Visitable visit(LabeledStmt n, Slice arg) { public Visitable visit(LabeledStmt n, Set<Node> arg) { super.visit(n, arg); return n.getStatement() != null ? n : null; } @Override public Visitable visit(ReturnStmt n, Slice arg) { public Visitable visit(ReturnStmt n, Set<Node> arg) { return arg.contains(n) ? n : null; } @Override public Visitable visit(ThrowStmt n, Slice arg) { public Visitable visit(ThrowStmt n, Set<Node> arg) { return arg.contains(n) ? n : null; } @Override public Visitable visit(SwitchEntryStmt n, Slice arg) { public Visitable visit(SwitchEntryStmt n, Set<Node> arg) { boolean keep = arg.contains(n); super.visit(n, arg); if (!n.getStatements().isEmpty()) Loading @@ -97,22 +158,14 @@ public class SliceAstVisitor extends ModifierVisitor<Slice> { } @Override public Visitable visit(SwitchStmt n, Slice arg) { public Visitable visit(SwitchStmt n, Set<Node> arg) { boolean keep = arg.contains(n); super.visit(n, arg); return keep ? n : null; } @Override public Visitable visit(ExpressionStmt n, Slice arg) { public Visitable visit(ExpressionStmt n, Set<Node> arg) { return arg.contains(n) ? n : null; } private void fillBody(Node n) { if (!(n instanceof NodeWithBody)) return; NodeWithBody<?> nb = ((NodeWithBody<?>) n); if (nb.getBody() == null) nb.setBody(new EmptyStmt()); } } Loading
sdg-core/src/main/java/tfm/slicing/Slice.java +36 −1 Original line number Diff line number Diff line package tfm.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.MethodDeclaration; import com.github.javaparser.ast.visitor.CloneVisitor; import com.github.javaparser.ast.visitor.Visitable; Loading Loading @@ -43,6 +45,39 @@ public class Slice { return Set.copyOf(map.values()); } /** * 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<CompilationUnit> toAst() { Map<CompilationUnit, Set<Node>> cuMap = new HashMap<>(); // Build key set nodes.stream().filter(n -> n instanceof CompilationUnit) .forEach(cu -> cuMap.put((CompilationUnit) cu, new HashSet<>())); // 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) node.findCompilationUnit() .flatMap(n -> Optional.ofNullable(cuMap.get(n))) .ifPresent(set -> set.add(node)); // Traverse the AST of each compilation unit, creating a copy and // removing any element not present in the slice. NodeList<CompilationUnit> cus = new NodeList<>(); SlicePruneVisitor sliceVisitor = new SlicePruneVisitor(); CloneVisitor cloneVisitor = new CloneVisitor(); for (Map.Entry<CompilationUnit, Set<Node>> entry : cuMap.entrySet()) { CompilationUnit clone = (CompilationUnit) entry.getKey().accept(cloneVisitor, null); assert entry.getKey().getStorage().isPresent(); clone.setStorage(entry.getKey().getStorage().get().getPath()); Visitable sliced = clone.accept(sliceVisitor, entry.getValue()); assert sliced instanceof CompilationUnit; cus.add((CompilationUnit) sliced); } return cus; } @Deprecated public Node getAst() { List<GraphNode<?>> methods = map.values().stream().filter(e -> e.getAstNode() instanceof MethodDeclaration).collect(Collectors.toList()); if (methods.size() == 1) { Loading @@ -63,7 +98,7 @@ public class Slice { private MethodDeclaration getMethodAst(Node node) { Visitable clone = node.accept(new CloneVisitor(), null); assert clone instanceof MethodDeclaration; clone.accept(new SliceAstVisitor(), this); clone.accept(new SlicePruneVisitor(), nodes); return ((MethodDeclaration) clone); } }
sdg-core/src/main/java/tfm/slicing/SliceAstVisitor.java→sdg-core/src/main/java/tfm/slicing/SlicePruneVisitor.java +171 −0 Original line number Diff line number Diff line package tfm.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.expr.BooleanLiteralExpr; 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 java.util.Set; import java.util.stream.Collectors; public class SliceAstVisitor extends ModifierVisitor<Slice> { public class SlicePruneVisitor extends ModifierVisitor<Set<Node>> { // ========== Utility methods ========== protected void fillBody(Node n) { if (!(n instanceof NodeWithBody)) return; NodeWithBody<?> nb = ((NodeWithBody<?>) n); if (nb.getBody() == null) nb.setBody(new EmptyStmt()); } // ========== File visitors ========== @Override public Visitable visit(CompilationUnit n, Set<Node> arg) { boolean keep = arg.contains(n); Visitable v = super.visit(n, arg); return keep ? v : null; } @Override public Visitable visit(ClassOrInterfaceDeclaration n, Set<Node> arg) { boolean keep = arg.contains(n); Visitable v = super.visit(n, arg); return keep ? v : null; } // ========== Class body visitors ========== @Override public Visitable visit(MethodDeclaration n, Set<Node> arg) { boolean keep = arg.contains(n); Visitable v = super.visit(n, arg); return keep ? v : null; } @Override public Visitable visit(ConstructorDeclaration n, Set<Node> arg) { boolean keep = arg.contains(n); Visitable v = super.visit(n, arg); return keep ? v : null; } @Override public Visitable visit(BreakStmt n, Slice arg) { public Visitable visit(FieldDeclaration n, Set<Node> arg) { boolean keep = arg.contains(n); Visitable v = super.visit(n, arg); return keep ? v : null; } // ========== Method body visitors ========== // 3 alternatives: // a. Without relevant children and included if on the slice or not (e.g. ExpressionStmt) // b. With relevant children and included if of the slice or not, children are discarded if not included (e.g. WhileStmt) // 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<Node> arg) { return arg.contains(n) ? n : null; } @Override public Visitable visit(ContinueStmt n, Slice arg) { public Visitable visit(ContinueStmt n, Set<Node> arg) { return arg.contains(n) ? n : null; } @Override public Visitable visit(DoStmt n, Slice arg) { public Visitable visit(DoStmt n, Set<Node> arg) { boolean keep = arg.contains(n); super.visit(n, arg); fillBody(n); Loading @@ -30,7 +91,7 @@ public class SliceAstVisitor extends ModifierVisitor<Slice> { } @Override public Visitable visit(ForEachStmt n, Slice arg) { public Visitable visit(ForEachStmt n, Set<Node> arg) { boolean keep = arg.contains(n); super.visit(n, arg); fillBody(n); Loading @@ -38,7 +99,7 @@ public class SliceAstVisitor extends ModifierVisitor<Slice> { } @Override public Visitable visit(ForStmt n, Slice arg) { public Visitable visit(ForStmt n, Set<Node> arg) { boolean keep = arg.contains(n); super.visit(n, arg); n.setInitialization(new NodeList<>(n.getInitialization().stream() Loading @@ -55,7 +116,7 @@ public class SliceAstVisitor extends ModifierVisitor<Slice> { } @Override public Visitable visit(WhileStmt n, Slice arg) { public Visitable visit(WhileStmt n, Set<Node> arg) { boolean keep = arg.contains(n); super.visit(n, arg); fillBody(n); Loading @@ -63,7 +124,7 @@ public class SliceAstVisitor extends ModifierVisitor<Slice> { } @Override public Visitable visit(IfStmt n, Slice arg) { public Visitable visit(IfStmt n, Set<Node> arg) { boolean keep = arg.contains(n); super.visit(n, arg); if (n.getThenStmt() == null) Loading @@ -72,23 +133,23 @@ public class SliceAstVisitor extends ModifierVisitor<Slice> { } @Override public Visitable visit(LabeledStmt n, Slice arg) { public Visitable visit(LabeledStmt n, Set<Node> arg) { super.visit(n, arg); return n.getStatement() != null ? n : null; } @Override public Visitable visit(ReturnStmt n, Slice arg) { public Visitable visit(ReturnStmt n, Set<Node> arg) { return arg.contains(n) ? n : null; } @Override public Visitable visit(ThrowStmt n, Slice arg) { public Visitable visit(ThrowStmt n, Set<Node> arg) { return arg.contains(n) ? n : null; } @Override public Visitable visit(SwitchEntryStmt n, Slice arg) { public Visitable visit(SwitchEntryStmt n, Set<Node> arg) { boolean keep = arg.contains(n); super.visit(n, arg); if (!n.getStatements().isEmpty()) Loading @@ -97,22 +158,14 @@ public class SliceAstVisitor extends ModifierVisitor<Slice> { } @Override public Visitable visit(SwitchStmt n, Slice arg) { public Visitable visit(SwitchStmt n, Set<Node> arg) { boolean keep = arg.contains(n); super.visit(n, arg); return keep ? n : null; } @Override public Visitable visit(ExpressionStmt n, Slice arg) { public Visitable visit(ExpressionStmt n, Set<Node> arg) { return arg.contains(n) ? n : null; } private void fillBody(Node n) { if (!(n instanceof NodeWithBody)) return; NodeWithBody<?> nb = ((NodeWithBody<?>) n); if (nb.getBody() == null) nb.setBody(new EmptyStmt()); } }