Loading sdg-cli/pom.xml +2 −2 Original line number Diff line number Diff line Loading @@ -6,7 +6,7 @@ <groupId>tfm</groupId> <artifactId>sdg-cli</artifactId> <version>1.0.3</version> <version>1.0.4</version> <properties> <maven.compiler.source>11</maven.compiler.source> Loading @@ -27,7 +27,7 @@ <dependency> <groupId>tfm</groupId> <artifactId>sdg-core</artifactId> <version>1.2.3</version> <version>1.2.4</version> </dependency> </dependencies> </project> sdg-core/pom.xml +1 −1 Original line number Diff line number Diff line Loading @@ -6,7 +6,7 @@ <groupId>tfm</groupId> <artifactId>sdg-core</artifactId> <version>1.2.3</version> <version>1.2.4</version> <properties> <maven.compiler.source>11</maven.compiler.source> Loading sdg-core/src/main/java/tfm/graphs/sdg/InterproceduralUsageFinder.java +3 −3 Original line number Diff line number Diff line Loading @@ -40,9 +40,9 @@ public class InterproceduralUsageFinder extends InterproceduralActionFinder<Vari Expression argument = extractArgument(use, edge, true); ActualIONode actualIn = ActualIONode.createActualIn(edge.getCall(), resolved, argument); argument.accept(new VariableVisitor( (name, n) -> movables.add(new VariableAction.Movable(new VariableAction.Declaration(name, graphNode), actualIn)), (name, n) -> movables.add(new VariableAction.Movable(new VariableAction.Definition(name, graphNode), actualIn)), (name, n) -> movables.add(new VariableAction.Movable(new VariableAction.Usage(name, graphNode), actualIn)) (n, name) -> movables.add(new VariableAction.Movable(new VariableAction.Declaration(name, graphNode), actualIn)), (n, name) -> movables.add(new VariableAction.Movable(new VariableAction.Definition(name, graphNode), actualIn)), (n, name) -> movables.add(new VariableAction.Movable(new VariableAction.Usage(name, graphNode), actualIn)) ), VariableVisitor.Action.USE); graphNode.addActionsForCall(movables, edge.getCall(), true); } Loading sdg-core/src/main/java/tfm/nodes/VariableVisitor.java +53 −21 Original line number Diff line number Diff line Loading @@ -22,6 +22,9 @@ public class VariableVisitor extends GraphNodeContentVisitor<VariableVisitor.Act public enum Action { DECLARATION, DEFINITION, USE; /** Whether the action is performed in all executions of the node. */ private boolean always = true; /** Join multiple actions into one. */ public Action or(Action action) { if (action == DECLARATION || this == DECLARATION) Loading @@ -30,30 +33,32 @@ public class VariableVisitor extends GraphNodeContentVisitor<VariableVisitor.Act return DEFINITION; return USE; } public void setAlways(boolean always) { this.always = always; } } /** A default action to be used as a placeholder when a {@code null} action is received. */ protected static final BiConsumer<NameExpr, GraphNode<?>> BLANK_CONSUMER = (a, b) -> {}; protected static final BiConsumer<GraphNode<?>, NameExpr> BLANK_CONSUMER = (a, b) -> {}; /** The action to perform when a declaration is found. */ protected final BiConsumer<NameExpr, GraphNode<?>> declConsumer; protected final BiConsumer<GraphNode<?>, NameExpr> declConsumer; /** The action to perform when a definition is found. */ protected final BiConsumer<NameExpr, GraphNode<?>> defConsumer; protected final BiConsumer<GraphNode<?>, NameExpr> defConsumer; /** The action to perform when a usage is found. */ protected final BiConsumer<NameExpr, GraphNode<?>> useConsumer; protected final BiConsumer<GraphNode<?>, NameExpr> useConsumer; /** A variable visitor that will add each action to the list of actions of the graph node. * The entry-point for this graph MUST be {@link #startVisit(GraphNode)} or {@link #startVisit(GraphNode, Action)} */ public VariableVisitor() { this((name, node) -> node.addDeclaredVariable(name), (name, node) -> node.addDefinedVariable(name), (name, node) -> node.addUsedVariable(name)); this(GraphNode::addDeclaredVariable, GraphNode::addDefinedVariable, GraphNode::addUsedVariable); } /** A variable visitor that will perform the given actions when a variable is found. * A node can accept this visitor, but calls will be ignored if the entry-point is * not {@link #startVisit(GraphNode)} or {@link #startVisit(GraphNode, Action)} */ public VariableVisitor(BiConsumer<NameExpr, GraphNode<?>> declConsumer, BiConsumer<NameExpr, GraphNode<?>> defConsumer, BiConsumer<NameExpr, GraphNode<?>> useConsumer) { /** A variable visitor that will perform the given actions when a variable is found. A node can accept this visitor, * but calls will be ignored if the entry-point is not {@link #startVisit(GraphNode)} or {@link #startVisit(GraphNode, Action)}. * The arguments are the actions to be performed when an action is found in the corresponding node. */ public VariableVisitor(BiConsumer<GraphNode<?>, NameExpr> declConsumer, BiConsumer<GraphNode<?>, NameExpr> defConsumer, BiConsumer<GraphNode<?>, NameExpr> useConsumer) { this.declConsumer = Objects.requireNonNullElse(declConsumer, BLANK_CONSUMER); this.defConsumer = Objects.requireNonNullElse(defConsumer, BLANK_CONSUMER); this.useConsumer = Objects.requireNonNullElse(useConsumer, BLANK_CONSUMER); Loading @@ -68,13 +73,13 @@ public class VariableVisitor extends GraphNodeContentVisitor<VariableVisitor.Act public void visit(NameExpr n, Action action) { switch (action) { case DECLARATION: declConsumer.accept(n, graphNode); declConsumer.accept(graphNode, n); break; case DEFINITION: defConsumer.accept(n, graphNode); defConsumer.accept(graphNode, n); break; case USE: useConsumer.accept(n, graphNode); useConsumer.accept(graphNode, n); break; default: throw new UnsupportedOperationException(); Loading Loading @@ -102,6 +107,32 @@ public class VariableVisitor extends GraphNodeContentVisitor<VariableVisitor.Act } } @Override public void visit(ConditionalExpr n, Action arg) { n.getCondition().accept(this, arg); boolean always = arg.always; arg.setAlways(false); n.getThenExpr().accept(this, arg); n.getElseExpr().accept(this, arg); arg.setAlways(always); } @Override public void visit(BinaryExpr n, Action arg) { n.getLeft().accept(this, arg); switch (n.getOperator()) { case OR: case AND: boolean always = arg.always; arg.setAlways(false); n.getRight().accept(this, arg); arg.setAlways(always); default: n.getRight().accept(this, arg); } super.visit(n, arg); } @Override public void visit(AssignExpr n, Action action) { // Target will be used if operator is not '=' Loading Loading @@ -150,8 +181,8 @@ public class VariableVisitor extends GraphNodeContentVisitor<VariableVisitor.Act @Override public void visit(Parameter n, Action arg) { declConsumer.accept(new NameExpr(n.getName().getId()), graphNode); defConsumer.accept(new NameExpr(n.getName().getId()), graphNode); declConsumer.accept(graphNode, new NameExpr(n.getName().getId())); defConsumer.accept(graphNode, new NameExpr(n.getName().getId())); } // ======================================================================= // ================================ CALLS ================================ Loading @@ -162,28 +193,29 @@ public class VariableVisitor extends GraphNodeContentVisitor<VariableVisitor.Act @Override public void visit(ObjectCreationExpr n, Action arg) { if (!visitCall(n, arg)) if (visitCall(n, arg)) super.visit(n, arg); } @Override public void visit(ExplicitConstructorInvocationStmt n, Action arg) { if (!visitCall(n, arg)) if (visitCall(n, arg)) super.visit(n, arg); } @Override public void visit(MethodCallExpr n, Action arg) { if (!visitCall(n, arg)) if (visitCall(n, arg)) super.visit(n, arg); } /** Tries to resolve and add the corresponding call markers. */ protected boolean visitCall(Resolvable<? extends ResolvedMethodLikeDeclaration> call, Action arg) { if (ASTUtils.getResolvedAST(call.resolve()).isEmpty() || graphNode == null) return false; return true; graphNode.addCallMarker(call, true); ASTUtils.getResolvableScope(call).ifPresent(s -> s.accept(this, arg)); graphNode.addCallMarker(call, false); return true; return false; } } Loading
sdg-cli/pom.xml +2 −2 Original line number Diff line number Diff line Loading @@ -6,7 +6,7 @@ <groupId>tfm</groupId> <artifactId>sdg-cli</artifactId> <version>1.0.3</version> <version>1.0.4</version> <properties> <maven.compiler.source>11</maven.compiler.source> Loading @@ -27,7 +27,7 @@ <dependency> <groupId>tfm</groupId> <artifactId>sdg-core</artifactId> <version>1.2.3</version> <version>1.2.4</version> </dependency> </dependencies> </project>
sdg-core/pom.xml +1 −1 Original line number Diff line number Diff line Loading @@ -6,7 +6,7 @@ <groupId>tfm</groupId> <artifactId>sdg-core</artifactId> <version>1.2.3</version> <version>1.2.4</version> <properties> <maven.compiler.source>11</maven.compiler.source> Loading
sdg-core/src/main/java/tfm/graphs/sdg/InterproceduralUsageFinder.java +3 −3 Original line number Diff line number Diff line Loading @@ -40,9 +40,9 @@ public class InterproceduralUsageFinder extends InterproceduralActionFinder<Vari Expression argument = extractArgument(use, edge, true); ActualIONode actualIn = ActualIONode.createActualIn(edge.getCall(), resolved, argument); argument.accept(new VariableVisitor( (name, n) -> movables.add(new VariableAction.Movable(new VariableAction.Declaration(name, graphNode), actualIn)), (name, n) -> movables.add(new VariableAction.Movable(new VariableAction.Definition(name, graphNode), actualIn)), (name, n) -> movables.add(new VariableAction.Movable(new VariableAction.Usage(name, graphNode), actualIn)) (n, name) -> movables.add(new VariableAction.Movable(new VariableAction.Declaration(name, graphNode), actualIn)), (n, name) -> movables.add(new VariableAction.Movable(new VariableAction.Definition(name, graphNode), actualIn)), (n, name) -> movables.add(new VariableAction.Movable(new VariableAction.Usage(name, graphNode), actualIn)) ), VariableVisitor.Action.USE); graphNode.addActionsForCall(movables, edge.getCall(), true); } Loading
sdg-core/src/main/java/tfm/nodes/VariableVisitor.java +53 −21 Original line number Diff line number Diff line Loading @@ -22,6 +22,9 @@ public class VariableVisitor extends GraphNodeContentVisitor<VariableVisitor.Act public enum Action { DECLARATION, DEFINITION, USE; /** Whether the action is performed in all executions of the node. */ private boolean always = true; /** Join multiple actions into one. */ public Action or(Action action) { if (action == DECLARATION || this == DECLARATION) Loading @@ -30,30 +33,32 @@ public class VariableVisitor extends GraphNodeContentVisitor<VariableVisitor.Act return DEFINITION; return USE; } public void setAlways(boolean always) { this.always = always; } } /** A default action to be used as a placeholder when a {@code null} action is received. */ protected static final BiConsumer<NameExpr, GraphNode<?>> BLANK_CONSUMER = (a, b) -> {}; protected static final BiConsumer<GraphNode<?>, NameExpr> BLANK_CONSUMER = (a, b) -> {}; /** The action to perform when a declaration is found. */ protected final BiConsumer<NameExpr, GraphNode<?>> declConsumer; protected final BiConsumer<GraphNode<?>, NameExpr> declConsumer; /** The action to perform when a definition is found. */ protected final BiConsumer<NameExpr, GraphNode<?>> defConsumer; protected final BiConsumer<GraphNode<?>, NameExpr> defConsumer; /** The action to perform when a usage is found. */ protected final BiConsumer<NameExpr, GraphNode<?>> useConsumer; protected final BiConsumer<GraphNode<?>, NameExpr> useConsumer; /** A variable visitor that will add each action to the list of actions of the graph node. * The entry-point for this graph MUST be {@link #startVisit(GraphNode)} or {@link #startVisit(GraphNode, Action)} */ public VariableVisitor() { this((name, node) -> node.addDeclaredVariable(name), (name, node) -> node.addDefinedVariable(name), (name, node) -> node.addUsedVariable(name)); this(GraphNode::addDeclaredVariable, GraphNode::addDefinedVariable, GraphNode::addUsedVariable); } /** A variable visitor that will perform the given actions when a variable is found. * A node can accept this visitor, but calls will be ignored if the entry-point is * not {@link #startVisit(GraphNode)} or {@link #startVisit(GraphNode, Action)} */ public VariableVisitor(BiConsumer<NameExpr, GraphNode<?>> declConsumer, BiConsumer<NameExpr, GraphNode<?>> defConsumer, BiConsumer<NameExpr, GraphNode<?>> useConsumer) { /** A variable visitor that will perform the given actions when a variable is found. A node can accept this visitor, * but calls will be ignored if the entry-point is not {@link #startVisit(GraphNode)} or {@link #startVisit(GraphNode, Action)}. * The arguments are the actions to be performed when an action is found in the corresponding node. */ public VariableVisitor(BiConsumer<GraphNode<?>, NameExpr> declConsumer, BiConsumer<GraphNode<?>, NameExpr> defConsumer, BiConsumer<GraphNode<?>, NameExpr> useConsumer) { this.declConsumer = Objects.requireNonNullElse(declConsumer, BLANK_CONSUMER); this.defConsumer = Objects.requireNonNullElse(defConsumer, BLANK_CONSUMER); this.useConsumer = Objects.requireNonNullElse(useConsumer, BLANK_CONSUMER); Loading @@ -68,13 +73,13 @@ public class VariableVisitor extends GraphNodeContentVisitor<VariableVisitor.Act public void visit(NameExpr n, Action action) { switch (action) { case DECLARATION: declConsumer.accept(n, graphNode); declConsumer.accept(graphNode, n); break; case DEFINITION: defConsumer.accept(n, graphNode); defConsumer.accept(graphNode, n); break; case USE: useConsumer.accept(n, graphNode); useConsumer.accept(graphNode, n); break; default: throw new UnsupportedOperationException(); Loading Loading @@ -102,6 +107,32 @@ public class VariableVisitor extends GraphNodeContentVisitor<VariableVisitor.Act } } @Override public void visit(ConditionalExpr n, Action arg) { n.getCondition().accept(this, arg); boolean always = arg.always; arg.setAlways(false); n.getThenExpr().accept(this, arg); n.getElseExpr().accept(this, arg); arg.setAlways(always); } @Override public void visit(BinaryExpr n, Action arg) { n.getLeft().accept(this, arg); switch (n.getOperator()) { case OR: case AND: boolean always = arg.always; arg.setAlways(false); n.getRight().accept(this, arg); arg.setAlways(always); default: n.getRight().accept(this, arg); } super.visit(n, arg); } @Override public void visit(AssignExpr n, Action action) { // Target will be used if operator is not '=' Loading Loading @@ -150,8 +181,8 @@ public class VariableVisitor extends GraphNodeContentVisitor<VariableVisitor.Act @Override public void visit(Parameter n, Action arg) { declConsumer.accept(new NameExpr(n.getName().getId()), graphNode); defConsumer.accept(new NameExpr(n.getName().getId()), graphNode); declConsumer.accept(graphNode, new NameExpr(n.getName().getId())); defConsumer.accept(graphNode, new NameExpr(n.getName().getId())); } // ======================================================================= // ================================ CALLS ================================ Loading @@ -162,28 +193,29 @@ public class VariableVisitor extends GraphNodeContentVisitor<VariableVisitor.Act @Override public void visit(ObjectCreationExpr n, Action arg) { if (!visitCall(n, arg)) if (visitCall(n, arg)) super.visit(n, arg); } @Override public void visit(ExplicitConstructorInvocationStmt n, Action arg) { if (!visitCall(n, arg)) if (visitCall(n, arg)) super.visit(n, arg); } @Override public void visit(MethodCallExpr n, Action arg) { if (!visitCall(n, arg)) if (visitCall(n, arg)) super.visit(n, arg); } /** Tries to resolve and add the corresponding call markers. */ protected boolean visitCall(Resolvable<? extends ResolvedMethodLikeDeclaration> call, Action arg) { if (ASTUtils.getResolvedAST(call.resolve()).isEmpty() || graphNode == null) return false; return true; graphNode.addCallMarker(call, true); ASTUtils.getResolvableScope(call).ifPresent(s -> s.accept(this, arg)); graphNode.addCallMarker(call, false); return true; return false; } }