Skip to content

Commit 529b9f3

Browse files
SONARPY-744 Avoid FP when subscription object is used inside 'in expressions' (SonarSource#861)
1 parent 3bbbd8e commit 529b9f3

2 files changed

Lines changed: 29 additions & 1 deletion

File tree

python-checks/src/main/java/org/sonar/python/checks/ConfusingTypeCheckingCheck.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,13 @@
3030
import org.sonar.plugins.python.api.symbols.ClassSymbol;
3131
import org.sonar.plugins.python.api.symbols.Symbol;
3232
import org.sonar.plugins.python.api.tree.Expression;
33+
import org.sonar.plugins.python.api.tree.InExpression;
3334
import org.sonar.plugins.python.api.tree.IsExpression;
3435
import org.sonar.plugins.python.api.tree.RaiseStatement;
3536
import org.sonar.plugins.python.api.tree.Token;
3637
import org.sonar.plugins.python.api.tree.Tree;
3738
import org.sonar.plugins.python.api.types.InferredType;
39+
import org.sonar.python.tree.TreeUtils;
3840
import org.sonar.python.types.InferredTypes;
3941
import org.sonar.python.types.TypeShed;
4042

@@ -110,7 +112,21 @@ public boolean isValidSubscription(Expression subscriptionObject, String require
110112
// handled by S5644
111113
return true;
112114
}
113-
return type.declaresMember(requiredMethod);
115+
return isUsedInsideInExpression(subscriptionObject) || type.declaresMember(requiredMethod);
116+
}
117+
118+
private static boolean isUsedInsideInExpression(Expression subscriptionObject) {
119+
return TreeUtils.getSymbolFromTree(subscriptionObject)
120+
.filter(symbol -> symbol.usages().stream().anyMatch(usage -> isRightOperandInExpression(usage.tree())))
121+
.isPresent();
122+
}
123+
124+
private static boolean isRightOperandInExpression(Tree tree) {
125+
Tree parent = tree.parent();
126+
if (parent instanceof InExpression) {
127+
return ((InExpression) parent).rightOperand() == tree;
128+
}
129+
return false;
114130
}
115131

116132
@Override

python-checks/src/test/resources/checks/confusingTypeChecking/itemOperations.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,15 @@ def f(val: object):
2020
if not isinstance(val, tuple):
2121
...
2222
val[0]
23+
24+
def checked_with_in(obj: object, other: object, prop):
25+
if prop in obj:
26+
obj[prop]
27+
if other in obj:
28+
other[prop] # Noncompliant
29+
30+
def checked_with_not_in(obj: object, prop):
31+
if prop not in obj:
32+
return
33+
obj[prop]
34+

0 commit comments

Comments
 (0)