From 15575d4a59ef3b9c4c018cfff0bfab89114a80d7 Mon Sep 17 00:00:00 2001 From: Carlos Galindo Date: Thu, 6 May 2021 22:44:43 +0200 Subject: [PATCH] Store associated expressions in each VA, to avoid confusion between them ExpressionObjectTreeFinder will now locate the correct VA, by searching for the matching call or expression. --- .../graphs/ExpressionObjectTreeFinder.java | 60 ++++-- .../sdg/InterproceduralUsageFinder.java | 8 +- .../mist/slicing/nodes/VariableAction.java | 27 +++ .../mist/slicing/nodes/VariableVisitor.java | 180 +++++++++--------- .../es/upv/mist/slicing/utils/ASTUtils.java | 5 + 5 files changed, 173 insertions(+), 107 deletions(-) diff --git a/sdg-core/src/main/java/es/upv/mist/slicing/graphs/ExpressionObjectTreeFinder.java b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/ExpressionObjectTreeFinder.java index f5b063d..baefca7 100644 --- a/sdg-core/src/main/java/es/upv/mist/slicing/graphs/ExpressionObjectTreeFinder.java +++ b/sdg-core/src/main/java/es/upv/mist/slicing/graphs/ExpressionObjectTreeFinder.java @@ -14,6 +14,8 @@ import es.upv.mist.slicing.utils.ASTUtils; import java.util.LinkedList; import java.util.List; +import java.util.Optional; +import java.util.function.Predicate; import static es.upv.mist.slicing.graphs.cfg.CFGBuilder.VARIABLE_NAME_OUTPUT; @@ -124,6 +126,26 @@ public class ExpressionObjectTreeFinder { .forEach(pair -> markTransference(pair, targetAction, "")); } + public void locateAndMarkTransferenceToRoot(Resolvable call, VariableAction targetAction) { + boolean enteredCall = false; + for (VariableAction va : graphNode.getVariableActions()) { + if (va instanceof VariableAction.CallMarker && + ASTUtils.equalsWithRange(((VariableAction.CallMarker) va).getCall(), call)) { + if (((VariableAction.CallMarker) va).isEnter()) + enteredCall = true; + else + break; + } + if (enteredCall && va.isDefinition() && va.getName().equals("-scope-in-")) + break; + if (enteredCall && va.isUsage() && va.getName().equals("this")) { + markTransference(new Pair<>(va, ""), targetAction, ""); + return; + } + } + throw new IllegalStateException("Can't locate USE(this)--scope--for call " + call); + } + /** * Finds object trees that correspond to the output of the given expression. * @param expression An expression that outputs an object. @@ -155,27 +177,25 @@ public class ExpressionObjectTreeFinder { if (resolved.isType()) return; if (resolved.isField() && !resolved.asField().isStatic()) { - new FieldAccessExpr(new ThisExpr(), n.getNameAsString()).accept(this, arg); - return; + String newArg = n.getNameAsString() + (!arg.isEmpty() ? "." : "") + arg; + var optVa = locateVariableAction(n, va -> va.getName().matches("^.*this$")); + if (optVa.isEmpty()) + throw new IllegalStateException("Could not find USE action for var " + newArg); + list.add(new Pair<>(optVa.get(), newArg)); + } else { + var optVa = locateVariableAction(n, va -> va.getName().equals(n.getNameAsString())); + if (optVa.isEmpty()) + throw new IllegalStateException("Cannot find USE action for var " + n); + list.add(new Pair<>(optVa.get(), arg)); } - for (VariableAction action : graphNode.getVariableActions()) { - if (action.isUsage() && action.getName().equals(n.getNameAsString())) { - list.add(new Pair<>(action, arg)); - return; - } - } - throw new IllegalStateException("Cannot find USE action for var " + n); } @Override public void visit(ThisExpr n, String arg) { - for (VariableAction action : graphNode.getVariableActions()) { - if (action.isUsage() && action.getName().matches("^.*this$")) { - list.add(new Pair<>(action, arg)); - return; - } - } - throw new IllegalStateException("Could not find USE(this)"); + var vaOpt = locateVariableAction(n, va -> va.getName().matches("^.*this$")); + if (vaOpt.isEmpty()) + throw new IllegalStateException("Could not find USE(this)"); + list.add(new Pair<>(vaOpt.get(), arg)); } @Override @@ -247,6 +267,14 @@ public class ExpressionObjectTreeFinder { @Override public void visit(PatternExpr n, String arg) {} + + protected Optional locateVariableAction(Expression expression, Predicate predicate) { + return graphNode.getVariableActions().stream() + .filter(VariableAction::isUsage) + .filter(predicate) + .filter(va -> va.matches(expression)) + .findAny(); + } }, ""); return list; } 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 ad1e384..d3a49a1 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 @@ -3,7 +3,6 @@ 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.ast.expr.ThisExpr; import com.github.javaparser.resolution.Resolvable; import com.github.javaparser.resolution.declarations.ResolvedMethodLikeDeclaration; import es.upv.mist.slicing.graphs.CallGraph; @@ -18,7 +17,6 @@ import es.upv.mist.slicing.nodes.io.FormalIONode; 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; @@ -45,8 +43,10 @@ public class InterproceduralUsageFinder extends InterproceduralActionFinder dynamicTypes = new HashSet<>(); + protected final Set expressions = new NodeHashSet<>(); protected ResolvedType staticType; protected GraphNode graphNode; @@ -176,6 +178,21 @@ public abstract class VariableAction { return dynamicTypes; } + public void addExpression(Expression expression) { + expressions.add(expression); + } + + public void copyExpressions(VariableAction variableAction) { + if (variableAction instanceof Movable) + variableAction = ((Movable) variableAction).inner; + variableAction.expressions.forEach(this::addExpression); + } + + /** Whether this variable action represents the given expression. */ + public boolean matches(Expression expression) { + return expressions.contains(expression); + } + // ====================================================== // =================== OBJECT TREE ====================== // ====================================================== @@ -521,6 +538,16 @@ public abstract class VariableAction { inner.applySDGTreeConnection(sdg, targetAction); } + @Override + public void addExpression(Expression expression) { + inner.addExpression(expression); + } + + @Override + public boolean matches(Expression expression) { + return inner.matches(expression); + } + @Override public void setStaticType(ResolvedType staticType) { inner.setStaticType(staticType); 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 370649b..6228adb 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,6 +11,7 @@ import com.github.javaparser.resolution.UnsolvedSymbolException; import com.github.javaparser.resolution.declarations.AssociableToAST; import com.github.javaparser.resolution.declarations.ResolvedMethodLikeDeclaration; import com.github.javaparser.resolution.declarations.ResolvedValueDeclaration; +import com.github.javaparser.resolution.types.ResolvedReferenceType; import com.github.javaparser.resolution.types.ResolvedType; import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserMethodDeclaration; import es.upv.mist.slicing.graphs.ClassGraph; @@ -81,8 +82,9 @@ public class VariableVisitor extends GraphNodeContentVisitor l.accept(this, arg)); } @Override @@ -265,16 +275,16 @@ public class VariableVisitor extends GraphNodeContentVisitor { init.accept(this, action); definitionStack.push(init); - acceptAction(LOCAL_VARIABLE, v.getNameAsString(), DEFINITION); - graphNode.getLastVariableAction().setStaticType(v.getType().resolve()); + VariableAction vaDef = acceptAction(LOCAL_VARIABLE, v.getNameAsString(), DEFINITION); + vaDef.addExpression(n); + vaDef.setStaticType(v.getType().resolve()); definitionStack.pop(); if (v.getType().isClassOrInterfaceType()) - getLastDefinition().setTotallyDefinedMember(v.getNameAsString()); + vaDef.asDefinition().setTotallyDefinedMember(v.getNameAsString()); v.accept(this, action); }); } @@ -369,19 +384,19 @@ public class VariableVisitor extends GraphNodeContentVisitor ASTUtils.initializerForField(n)); init.accept(this, action); definitionStack.push(init); - acceptAction(FIELD, realName, DEFINITION); - graphNode.getLastVariableAction().setStaticType(staticType); + VariableAction vaDef = acceptAction(FIELD, realName, DEFINITION); + vaDef.setStaticType(staticType); definitionStack.pop(); if (v.getType().isClassOrInterfaceType()) - getLastDefinition().setTotallyDefinedMember(realName); + vaDef.asDefinition().setTotallyDefinedMember(realName); v.accept(this, action); } } @@ -405,10 +420,10 @@ public class VariableVisitor extends GraphNodeContentVisitor vaList = graphNode.getVariableActions(); - if (vaList.size() >= 5) { // call-super, DEC(this), USE(-output-), ret-super, DEF(this) + if (!visitCall) { // call-super, DEC(this), USE(-output-), ret-super, DEF(this) + assert vaList.size() >= 5; VariableAction useOutput = vaList.get(vaList.size() - 3); - VariableAction defThis = graphNode.getLastVariableAction(); assert useOutput.isUsage() && useOutput.getName().equals(VARIABLE_NAME_OUTPUT); - assert defThis.isDefinition() && defThis.getName().equals("this"); defThis.asDefinition().setTotallyDefinedMember("this"); ObjectTree.copyTargetTreeToSource(defThis.getObjectTree(), useOutput.getObjectTree(), "", ""); useOutput.setPDGTreeConnectionTo(defThis, "", ""); @@ -462,8 +477,8 @@ public class VariableVisitor extends GraphNodeContentVisitor scope.accept(this, action), () -> { - acceptAction(FIELD, "this", USE); - graphNode.getLastVariableAction().setStaticType(ASTUtils.resolvedTypeDeclarationToResolvedType(((MethodCallExpr) call).findAncestor(ClassOrInterfaceDeclaration.class).orElseThrow().resolve())); + VariableAction va = acceptAction(FIELD, "this", USE); + va.setStaticType(ASTUtils.resolvedTypeOfCurrentClass((MethodCallExpr) call)); }); // Generate -scope-in- action, so that InterproceduralUsageFinder does not need to do so. VariableAction.Definition def = new VariableAction.Definition(VariableAction.DeclarationType.SYNTHETIC, "-scope-in-", graphNode); @@ -516,9 +531,10 @@ public class VariableVisitor extends GraphNodeContentVisitor parentNode = ((Node) call).getParentNode(); if (parentNode.isEmpty() || !(parentNode.get() instanceof ExpressionStmt)) { - graphNode.addVariableAction(new VariableAction.Usage(SYNTHETIC, VARIABLE_NAME_OUTPUT, graphNode, - fields.map(tree -> (ObjectTree) tree.clone()).orElse(null))); - graphNode.getLastVariableAction().setStaticType(ASTUtils.getCallResolvedType(call)); + VariableAction use = new VariableAction.Usage(SYNTHETIC, VARIABLE_NAME_OUTPUT, graphNode, + fields.map(tree -> (ObjectTree) tree.clone()).orElse(null)); + graphNode.addVariableAction(use); + use.setStaticType(ASTUtils.getCallResolvedType(call)); } } @@ -542,7 +558,7 @@ public class VariableVisitor extends GraphNodeContentVisitor 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 b84f838..94004bf 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 @@ -250,4 +250,9 @@ public class ASTUtils { } return classInit; } + + public static ResolvedType resolvedTypeOfCurrentClass(Node n) { + return ASTUtils.resolvedTypeDeclarationToResolvedType( + n.findAncestor(ClassOrInterfaceDeclaration.class).orElseThrow().resolve()); + } } -- GitLab