Loading sdg-core/src/main/java/es/upv/mist/slicing/graphs/CallGraph.java +1 −1 Original line number Diff line number Diff line Loading @@ -167,7 +167,7 @@ public class CallGraph extends DirectedPseudograph<CallGraph.Vertex, CallGraph.E // =============== Method calls =============== @Override public void visit(MethodCallExpr n, Void arg) { n.resolve().toAst().ifPresent(decl -> createNormalEdge(decl, n)); n.resolve().toAst().ifPresent(decl -> createPolyEdges(decl, n)); super.visit(n, arg); } Loading sdg-core/src/main/java/es/upv/mist/slicing/graphs/ExpressionObjectTreeFinder.java +1 −2 Original line number Diff line number Diff line package es.upv.mist.slicing.graphs; import com.github.javaparser.ast.Node; import com.github.javaparser.ast.body.VariableDeclarator; import com.github.javaparser.ast.expr.*; import com.github.javaparser.ast.visitor.VoidVisitorAdapter; Loading Loading @@ -203,7 +202,7 @@ public class ExpressionObjectTreeFinder { for (VariableAction variableAction : graphNode.getVariableActions()) { if (variableAction instanceof VariableAction.CallMarker) { VariableAction.CallMarker marker = (VariableAction.CallMarker) variableAction; if (ASTUtils.equalsWithRange((Node) marker.getCall(), (Node) call) && !marker.isEnter()) { if (ASTUtils.equalsWithRange(marker.getCall(), call) && !marker.isEnter()) { assert lastUseOut != null; list.add(new Pair<>(lastUseOut, arg)); return; Loading sdg-core/src/main/java/es/upv/mist/slicing/graphs/sdg/InterproceduralDefinitionFinder.java +40 −9 Original line number Diff line number Diff line Loading @@ -44,23 +44,30 @@ public class InterproceduralDefinitionFinder extends InterproceduralActionFinder Optional<Expression> arg = extractArgument(def, edge, false); if (arg.isEmpty()) return; ActualIONode actualOut = ActualIONode.createActualOut(edge.getCall(), def.getName(), arg.get()); ActualIONode actualOut = locateActualOutNode(edge, def.getName()) .orElseGet(() -> ActualIONode.createActualOut(edge.getCall(), def.getName(), arg.get())); extractOutputVariablesAsMovables(arg.get(), movables, graphNode, actualOut, def); } else if (def.isField()) { if (def.isStatic()) { // Known limitation: static fields } else { assert !(edge.getCall() instanceof ObjectCreationExpr); ActualIONode actualOut = ActualIONode.createActualOut(edge.getCall(), def.getName(), null); ActualIONode actualOut = locateActualOutNode(edge, def.getName()) .orElseGet(() -> ActualIONode.createActualOut(edge.getCall(), def.getName(), null)); Optional<Expression> scope = ASTUtils.getResolvableScope(edge.getCall()); if (scope.isPresent()) { extractOutputVariablesAsMovables(scope.get(), movables, graphNode, actualOut, def); } else { assert def.hasObjectTree(); Optional<VariableAction> optVA = locateDefinition(graphNode, "this"); if (optVA.isPresent()) optVA.get().getObjectTree().addAll(def.getObjectTree()); else { var movableDef = new Definition(DeclarationType.FIELD, "this", graphNode, (ObjectTree) def.getObjectTree().clone()); movables.add(new Movable(movableDef, actualOut)); } } } } else { throw new IllegalStateException("Definition must be either from a parameter or a field!"); } Loading @@ -75,6 +82,10 @@ public class InterproceduralDefinitionFinder extends InterproceduralActionFinder e.accept(new OutNodeVariableVisitor(), defExpressions); for (Expression expression : defExpressions) { assert def.hasObjectTree(); Optional<VariableAction> optVa = locateDefinition(graphNode, expression.toString()); if (optVa.isPresent()) { optVa.get().getObjectTree().addAll(def.getObjectTree()); } else { DeclarationType type = DeclarationType.valueOf(expression); Definition inner = new Definition(type, expression.toString(), graphNode, (ObjectTree) def.getObjectTree().clone()); if (defExpressions.size() > 1) Loading @@ -82,6 +93,26 @@ public class InterproceduralDefinitionFinder extends InterproceduralActionFinder movables.add(new Movable(inner, actualOut)); } } } /** Find the actual out node in the given edge call that corresponds to the given variable name. */ protected Optional<ActualIONode> locateActualOutNode(CallGraph.Edge<?> edge, String name) { return edge.getGraphNode().getSyntheticNodesInMovables().stream() .filter(ActualIONode.class::isInstance) .map(ActualIONode.class::cast) .filter(ActualIONode::isOutput) .filter(actual -> actual.getVariableName().equals(name)) .filter(actual -> ASTUtils.equalsWithRange(actual.getAstNode(), edge.getCall())) .findFirst(); } /** Try to locate the definition for the given variable name in the given node. */ protected Optional<VariableAction> locateDefinition(GraphNode<?> graphNode, String name) { return graphNode.getVariableActions().stream() .filter(va -> va.getName().equals(name)) .filter(VariableAction::isDefinition) .findAny(); } @Override protected Stream<Definition> mapAndFilterActionStream(Stream<VariableAction> stream, CFG cfg) { Loading sdg-core/src/main/java/es/upv/mist/slicing/graphs/sdg/InterproceduralUsageFinder.java +69 −22 Original line number Diff line number Diff line package es.upv.mist.slicing.graphs.sdg; import com.github.javaparser.ast.Node; 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.ast.expr.ThisExpr; import com.github.javaparser.resolution.Resolvable; import com.github.javaparser.resolution.declarations.ResolvedMethodLikeDeclaration; import es.upv.mist.slicing.graphs.CallGraph; import es.upv.mist.slicing.graphs.ExpressionObjectTreeFinder; import es.upv.mist.slicing.graphs.cfg.CFG; import es.upv.mist.slicing.nodes.GraphNode; import es.upv.mist.slicing.nodes.ObjectTree; import es.upv.mist.slicing.nodes.VariableAction; import es.upv.mist.slicing.nodes.VariableAction.Definition; import es.upv.mist.slicing.nodes.VariableAction.Movable; import es.upv.mist.slicing.nodes.VariableAction.Usage; import es.upv.mist.slicing.nodes.io.ActualIONode; Loading @@ -20,7 +19,9 @@ import es.upv.mist.slicing.utils.ASTUtils; import java.util.Map; import java.util.Objects; 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. */ Loading @@ -29,6 +30,32 @@ public class InterproceduralUsageFinder extends InterproceduralActionFinder<Usag super(callGraph, cfgMap); } @Override public void save() { super.save(); markTransferenceToRoot(); } /** For every variable action -scope-in- or -arg-in- in the graph, * runs {@link ExpressionObjectTreeFinder#locateAndMarkTransferenceToRoot(Expression, VariableAction)}. */ protected void markTransferenceToRoot() { for (CallGraph.Edge<?> edge : graph.edgeSet()) { for (ActualIONode actualIn : locateActualInNode(edge)) { for (VariableAction va : edge.getGraphNode().getVariableActions()) { if (va instanceof Movable && ((Movable) va).getRealNode().equals(actualIn)) { ExpressionObjectTreeFinder finder = new ExpressionObjectTreeFinder(edge.getGraphNode()); if (va.getName().equals("-scope-in-")) { Expression scope = Objects.requireNonNullElseGet(actualIn.getArgument(), ThisExpr::new); finder.locateAndMarkTransferenceToRoot(scope, va); } else if (va.getName().equals("-arg-in-")) { finder.locateAndMarkTransferenceToRoot(actualIn.getArgument(), va); } } } } } } @Override protected void handleFormalAction(CallGraph.Vertex vertex, Usage use) { CFG cfg = cfgMap.get(vertex.getDeclaration()); Loading @@ -43,12 +70,9 @@ public class InterproceduralUsageFinder extends InterproceduralActionFinder<Usag if (use.isParameter()) { if (!use.isPrimitive()) { assert use.hasObjectTree(); ActualIONode actualIn = locateActualInNode(edge, use.getName()); Definition def = new Definition(VariableAction.DeclarationType.SYNTHETIC, "-arg-in-", graphNode, (ObjectTree) use.getObjectTree().clone()); Movable movDef = new Movable(def, actualIn); graphNode.addVariableActionAfterLastMatchingRealNode(movDef, actualIn); ExpressionObjectTreeFinder finder = new ExpressionObjectTreeFinder(graphNode); finder.locateAndMarkTransferenceToRoot(actualIn.getArgument(), def); int index = ASTUtils.getMatchingParameterIndex(graph.getEdgeTarget(edge).getDeclaration(), use.getName()); VariableAction argIn = locateArgIn(graphNode, edge.getCall(), index); argIn.getObjectTree().addAll(use.getObjectTree()); } } else if (use.isField()) { if (use.isStatic()) { Loading @@ -56,29 +80,52 @@ public class InterproceduralUsageFinder extends InterproceduralActionFinder<Usag } else { // An object creation expression input an existing object via actual-in because it creates it. assert !(edge.getCall() instanceof ObjectCreationExpr); ActualIONode actualIn = locateActualInNode(edge, use.getName()); Definition def = new Definition(VariableAction.DeclarationType.SYNTHETIC, "-scope-in-", graphNode, (ObjectTree) use.getObjectTree().clone()); Movable movDef = new Movable(def, actualIn); Expression scope = Objects.requireNonNullElseGet(actualIn.getArgument(), ThisExpr::new); graphNode.addVariableActionAfterLastMatchingRealNode(movDef, actualIn); ExpressionObjectTreeFinder finder = new ExpressionObjectTreeFinder(graphNode); finder.locateAndMarkTransferenceToRoot(scope, def); VariableAction scopeIn = locateScopeIn(graphNode, edge.getCall()); scopeIn.getObjectTree().addAll(use.getObjectTree()); } } else { throw new IllegalStateException("Definition must be either from a parameter or a field!"); } } /** Locates the actual-in node associated with the given variable name and call edge. */ protected ActualIONode locateActualInNode(CallGraph.Edge<?> edge, String name) { /** Find all actual in nodes in the given call. */ protected Set<ActualIONode> locateActualInNode(CallGraph.Edge<?> edge) { return edge.getGraphNode().getSyntheticNodesInMovables().stream() .filter(ActualIONode.class::isInstance) .map(ActualIONode.class::cast) .filter(ActualIONode::isInput) .filter(actual -> actual.getVariableName().equals(name)) .filter(actual -> ASTUtils.equalsWithRange(actual.getAstNode(), (Node) edge.getCall())) .findFirst() .orElseThrow(() -> new IllegalStateException("can't locate actual-in node")); .filter(actual -> ASTUtils.equalsWithRange(actual.getAstNode(), edge.getCall())) .collect(Collectors.toSet()); } /** Find the -arg-in- variable action that corresponds to the given node, call and index. */ protected VariableAction locateArgIn(GraphNode<?> graphNode, Resolvable<? extends ResolvedMethodLikeDeclaration> call, int index) { return locateActionIn(graphNode, call, index, "-arg-in-"); } /** Find the -scope-in- variable action that corresponds to the given node and call. */ protected VariableAction locateScopeIn(GraphNode<?> graphNode, Resolvable<? extends ResolvedMethodLikeDeclaration> call) { return locateActionIn(graphNode, call, 0, "-scope-in-"); } /** Find the nth variable action from the given node and call that matches the given name. 0 represents the first occurrence. */ protected VariableAction locateActionIn(GraphNode<?> graphNode, Resolvable<? extends ResolvedMethodLikeDeclaration> call, int index, String actionName) { boolean inCall = false; for (VariableAction va : graphNode.getVariableActions()) { if (va instanceof VariableAction.CallMarker && ASTUtils.equalsWithRange(((VariableAction.CallMarker) va).getCall(), call)) { if (((VariableAction.CallMarker) va).isEnter()) inCall = true; else break; // The call has ended, can't find the action now } if (inCall && va.isDefinition() && va.getName().equals(actionName)) { if (index == 0) return va; else index--; } } throw new IllegalStateException("Could not locate " + actionName + " for call " + call + " in node " + graphNode); } @Override Loading sdg-core/src/main/java/es/upv/mist/slicing/nodes/ObjectTree.java +1 −4 Original line number Diff line number Diff line Loading @@ -11,9 +11,6 @@ import java.util.regex.Pattern; import java.util.stream.Collectors; import java.util.stream.Stream; import static es.upv.mist.slicing.graphs.cfg.CFGBuilder.VARIABLE_NAME_OUTPUT; import static es.upv.mist.slicing.graphs.exceptionsensitive.ESCFG.ACTIVE_EXCEPTION_VARIABLE; /** * A tree data structure that mimics the tree found in an object's fields. * Each tree contains a MemberNode that represents its, including a name. Loading @@ -29,7 +26,7 @@ public class ObjectTree implements Cloneable { public static final String ROOT_NAME = "-root-"; /** Regex pattern to split the root from the fields of a field access expression. */ private static final Pattern FIELD_SPLIT = Pattern.compile("^(?<root>(([_0-9A-Za-z]+\\.)*this)|([_0-9A-Za-z]+)|(" + ROOT_NAME + ")|(" + VARIABLE_NAME_OUTPUT + ")|(" + ACTIVE_EXCEPTION_VARIABLE + "))(\\.(?<fields>.+))?$"); private static final Pattern FIELD_SPLIT = Pattern.compile("^(?<root>(([_0-9A-Za-z]+\\.)*this)|(?<dash>(-?))([_0-9A-Za-z]+\\k<dash>)+)(\\.(?<fields>.+))?$"); /** Direct children of this tree node, mapped by field name. */ private final Map<String, ObjectTree> childrenMap = new HashMap<>(); Loading Loading
sdg-core/src/main/java/es/upv/mist/slicing/graphs/CallGraph.java +1 −1 Original line number Diff line number Diff line Loading @@ -167,7 +167,7 @@ public class CallGraph extends DirectedPseudograph<CallGraph.Vertex, CallGraph.E // =============== Method calls =============== @Override public void visit(MethodCallExpr n, Void arg) { n.resolve().toAst().ifPresent(decl -> createNormalEdge(decl, n)); n.resolve().toAst().ifPresent(decl -> createPolyEdges(decl, n)); super.visit(n, arg); } Loading
sdg-core/src/main/java/es/upv/mist/slicing/graphs/ExpressionObjectTreeFinder.java +1 −2 Original line number Diff line number Diff line package es.upv.mist.slicing.graphs; import com.github.javaparser.ast.Node; import com.github.javaparser.ast.body.VariableDeclarator; import com.github.javaparser.ast.expr.*; import com.github.javaparser.ast.visitor.VoidVisitorAdapter; Loading Loading @@ -203,7 +202,7 @@ public class ExpressionObjectTreeFinder { for (VariableAction variableAction : graphNode.getVariableActions()) { if (variableAction instanceof VariableAction.CallMarker) { VariableAction.CallMarker marker = (VariableAction.CallMarker) variableAction; if (ASTUtils.equalsWithRange((Node) marker.getCall(), (Node) call) && !marker.isEnter()) { if (ASTUtils.equalsWithRange(marker.getCall(), call) && !marker.isEnter()) { assert lastUseOut != null; list.add(new Pair<>(lastUseOut, arg)); return; Loading
sdg-core/src/main/java/es/upv/mist/slicing/graphs/sdg/InterproceduralDefinitionFinder.java +40 −9 Original line number Diff line number Diff line Loading @@ -44,23 +44,30 @@ public class InterproceduralDefinitionFinder extends InterproceduralActionFinder Optional<Expression> arg = extractArgument(def, edge, false); if (arg.isEmpty()) return; ActualIONode actualOut = ActualIONode.createActualOut(edge.getCall(), def.getName(), arg.get()); ActualIONode actualOut = locateActualOutNode(edge, def.getName()) .orElseGet(() -> ActualIONode.createActualOut(edge.getCall(), def.getName(), arg.get())); extractOutputVariablesAsMovables(arg.get(), movables, graphNode, actualOut, def); } else if (def.isField()) { if (def.isStatic()) { // Known limitation: static fields } else { assert !(edge.getCall() instanceof ObjectCreationExpr); ActualIONode actualOut = ActualIONode.createActualOut(edge.getCall(), def.getName(), null); ActualIONode actualOut = locateActualOutNode(edge, def.getName()) .orElseGet(() -> ActualIONode.createActualOut(edge.getCall(), def.getName(), null)); Optional<Expression> scope = ASTUtils.getResolvableScope(edge.getCall()); if (scope.isPresent()) { extractOutputVariablesAsMovables(scope.get(), movables, graphNode, actualOut, def); } else { assert def.hasObjectTree(); Optional<VariableAction> optVA = locateDefinition(graphNode, "this"); if (optVA.isPresent()) optVA.get().getObjectTree().addAll(def.getObjectTree()); else { var movableDef = new Definition(DeclarationType.FIELD, "this", graphNode, (ObjectTree) def.getObjectTree().clone()); movables.add(new Movable(movableDef, actualOut)); } } } } else { throw new IllegalStateException("Definition must be either from a parameter or a field!"); } Loading @@ -75,6 +82,10 @@ public class InterproceduralDefinitionFinder extends InterproceduralActionFinder e.accept(new OutNodeVariableVisitor(), defExpressions); for (Expression expression : defExpressions) { assert def.hasObjectTree(); Optional<VariableAction> optVa = locateDefinition(graphNode, expression.toString()); if (optVa.isPresent()) { optVa.get().getObjectTree().addAll(def.getObjectTree()); } else { DeclarationType type = DeclarationType.valueOf(expression); Definition inner = new Definition(type, expression.toString(), graphNode, (ObjectTree) def.getObjectTree().clone()); if (defExpressions.size() > 1) Loading @@ -82,6 +93,26 @@ public class InterproceduralDefinitionFinder extends InterproceduralActionFinder movables.add(new Movable(inner, actualOut)); } } } /** Find the actual out node in the given edge call that corresponds to the given variable name. */ protected Optional<ActualIONode> locateActualOutNode(CallGraph.Edge<?> edge, String name) { return edge.getGraphNode().getSyntheticNodesInMovables().stream() .filter(ActualIONode.class::isInstance) .map(ActualIONode.class::cast) .filter(ActualIONode::isOutput) .filter(actual -> actual.getVariableName().equals(name)) .filter(actual -> ASTUtils.equalsWithRange(actual.getAstNode(), edge.getCall())) .findFirst(); } /** Try to locate the definition for the given variable name in the given node. */ protected Optional<VariableAction> locateDefinition(GraphNode<?> graphNode, String name) { return graphNode.getVariableActions().stream() .filter(va -> va.getName().equals(name)) .filter(VariableAction::isDefinition) .findAny(); } @Override protected Stream<Definition> mapAndFilterActionStream(Stream<VariableAction> stream, CFG cfg) { Loading
sdg-core/src/main/java/es/upv/mist/slicing/graphs/sdg/InterproceduralUsageFinder.java +69 −22 Original line number Diff line number Diff line package es.upv.mist.slicing.graphs.sdg; import com.github.javaparser.ast.Node; 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.ast.expr.ThisExpr; import com.github.javaparser.resolution.Resolvable; import com.github.javaparser.resolution.declarations.ResolvedMethodLikeDeclaration; import es.upv.mist.slicing.graphs.CallGraph; import es.upv.mist.slicing.graphs.ExpressionObjectTreeFinder; import es.upv.mist.slicing.graphs.cfg.CFG; import es.upv.mist.slicing.nodes.GraphNode; import es.upv.mist.slicing.nodes.ObjectTree; import es.upv.mist.slicing.nodes.VariableAction; import es.upv.mist.slicing.nodes.VariableAction.Definition; import es.upv.mist.slicing.nodes.VariableAction.Movable; import es.upv.mist.slicing.nodes.VariableAction.Usage; import es.upv.mist.slicing.nodes.io.ActualIONode; Loading @@ -20,7 +19,9 @@ import es.upv.mist.slicing.utils.ASTUtils; import java.util.Map; import java.util.Objects; 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. */ Loading @@ -29,6 +30,32 @@ public class InterproceduralUsageFinder extends InterproceduralActionFinder<Usag super(callGraph, cfgMap); } @Override public void save() { super.save(); markTransferenceToRoot(); } /** For every variable action -scope-in- or -arg-in- in the graph, * runs {@link ExpressionObjectTreeFinder#locateAndMarkTransferenceToRoot(Expression, VariableAction)}. */ protected void markTransferenceToRoot() { for (CallGraph.Edge<?> edge : graph.edgeSet()) { for (ActualIONode actualIn : locateActualInNode(edge)) { for (VariableAction va : edge.getGraphNode().getVariableActions()) { if (va instanceof Movable && ((Movable) va).getRealNode().equals(actualIn)) { ExpressionObjectTreeFinder finder = new ExpressionObjectTreeFinder(edge.getGraphNode()); if (va.getName().equals("-scope-in-")) { Expression scope = Objects.requireNonNullElseGet(actualIn.getArgument(), ThisExpr::new); finder.locateAndMarkTransferenceToRoot(scope, va); } else if (va.getName().equals("-arg-in-")) { finder.locateAndMarkTransferenceToRoot(actualIn.getArgument(), va); } } } } } } @Override protected void handleFormalAction(CallGraph.Vertex vertex, Usage use) { CFG cfg = cfgMap.get(vertex.getDeclaration()); Loading @@ -43,12 +70,9 @@ public class InterproceduralUsageFinder extends InterproceduralActionFinder<Usag if (use.isParameter()) { if (!use.isPrimitive()) { assert use.hasObjectTree(); ActualIONode actualIn = locateActualInNode(edge, use.getName()); Definition def = new Definition(VariableAction.DeclarationType.SYNTHETIC, "-arg-in-", graphNode, (ObjectTree) use.getObjectTree().clone()); Movable movDef = new Movable(def, actualIn); graphNode.addVariableActionAfterLastMatchingRealNode(movDef, actualIn); ExpressionObjectTreeFinder finder = new ExpressionObjectTreeFinder(graphNode); finder.locateAndMarkTransferenceToRoot(actualIn.getArgument(), def); int index = ASTUtils.getMatchingParameterIndex(graph.getEdgeTarget(edge).getDeclaration(), use.getName()); VariableAction argIn = locateArgIn(graphNode, edge.getCall(), index); argIn.getObjectTree().addAll(use.getObjectTree()); } } else if (use.isField()) { if (use.isStatic()) { Loading @@ -56,29 +80,52 @@ public class InterproceduralUsageFinder extends InterproceduralActionFinder<Usag } else { // An object creation expression input an existing object via actual-in because it creates it. assert !(edge.getCall() instanceof ObjectCreationExpr); ActualIONode actualIn = locateActualInNode(edge, use.getName()); Definition def = new Definition(VariableAction.DeclarationType.SYNTHETIC, "-scope-in-", graphNode, (ObjectTree) use.getObjectTree().clone()); Movable movDef = new Movable(def, actualIn); Expression scope = Objects.requireNonNullElseGet(actualIn.getArgument(), ThisExpr::new); graphNode.addVariableActionAfterLastMatchingRealNode(movDef, actualIn); ExpressionObjectTreeFinder finder = new ExpressionObjectTreeFinder(graphNode); finder.locateAndMarkTransferenceToRoot(scope, def); VariableAction scopeIn = locateScopeIn(graphNode, edge.getCall()); scopeIn.getObjectTree().addAll(use.getObjectTree()); } } else { throw new IllegalStateException("Definition must be either from a parameter or a field!"); } } /** Locates the actual-in node associated with the given variable name and call edge. */ protected ActualIONode locateActualInNode(CallGraph.Edge<?> edge, String name) { /** Find all actual in nodes in the given call. */ protected Set<ActualIONode> locateActualInNode(CallGraph.Edge<?> edge) { return edge.getGraphNode().getSyntheticNodesInMovables().stream() .filter(ActualIONode.class::isInstance) .map(ActualIONode.class::cast) .filter(ActualIONode::isInput) .filter(actual -> actual.getVariableName().equals(name)) .filter(actual -> ASTUtils.equalsWithRange(actual.getAstNode(), (Node) edge.getCall())) .findFirst() .orElseThrow(() -> new IllegalStateException("can't locate actual-in node")); .filter(actual -> ASTUtils.equalsWithRange(actual.getAstNode(), edge.getCall())) .collect(Collectors.toSet()); } /** Find the -arg-in- variable action that corresponds to the given node, call and index. */ protected VariableAction locateArgIn(GraphNode<?> graphNode, Resolvable<? extends ResolvedMethodLikeDeclaration> call, int index) { return locateActionIn(graphNode, call, index, "-arg-in-"); } /** Find the -scope-in- variable action that corresponds to the given node and call. */ protected VariableAction locateScopeIn(GraphNode<?> graphNode, Resolvable<? extends ResolvedMethodLikeDeclaration> call) { return locateActionIn(graphNode, call, 0, "-scope-in-"); } /** Find the nth variable action from the given node and call that matches the given name. 0 represents the first occurrence. */ protected VariableAction locateActionIn(GraphNode<?> graphNode, Resolvable<? extends ResolvedMethodLikeDeclaration> call, int index, String actionName) { boolean inCall = false; for (VariableAction va : graphNode.getVariableActions()) { if (va instanceof VariableAction.CallMarker && ASTUtils.equalsWithRange(((VariableAction.CallMarker) va).getCall(), call)) { if (((VariableAction.CallMarker) va).isEnter()) inCall = true; else break; // The call has ended, can't find the action now } if (inCall && va.isDefinition() && va.getName().equals(actionName)) { if (index == 0) return va; else index--; } } throw new IllegalStateException("Could not locate " + actionName + " for call " + call + " in node " + graphNode); } @Override Loading
sdg-core/src/main/java/es/upv/mist/slicing/nodes/ObjectTree.java +1 −4 Original line number Diff line number Diff line Loading @@ -11,9 +11,6 @@ import java.util.regex.Pattern; import java.util.stream.Collectors; import java.util.stream.Stream; import static es.upv.mist.slicing.graphs.cfg.CFGBuilder.VARIABLE_NAME_OUTPUT; import static es.upv.mist.slicing.graphs.exceptionsensitive.ESCFG.ACTIVE_EXCEPTION_VARIABLE; /** * A tree data structure that mimics the tree found in an object's fields. * Each tree contains a MemberNode that represents its, including a name. Loading @@ -29,7 +26,7 @@ public class ObjectTree implements Cloneable { public static final String ROOT_NAME = "-root-"; /** Regex pattern to split the root from the fields of a field access expression. */ private static final Pattern FIELD_SPLIT = Pattern.compile("^(?<root>(([_0-9A-Za-z]+\\.)*this)|([_0-9A-Za-z]+)|(" + ROOT_NAME + ")|(" + VARIABLE_NAME_OUTPUT + ")|(" + ACTIVE_EXCEPTION_VARIABLE + "))(\\.(?<fields>.+))?$"); private static final Pattern FIELD_SPLIT = Pattern.compile("^(?<root>(([_0-9A-Za-z]+\\.)*this)|(?<dash>(-?))([_0-9A-Za-z]+\\k<dash>)+)(\\.(?<fields>.+))?$"); /** Direct children of this tree node, mapped by field name. */ private final Map<String, ObjectTree> childrenMap = new HashMap<>(); Loading