Skip to content

Commit c9fb601

Browse files
SONARPY-814 S1481 should not raise on annotated assignments without RHS (SonarSource#884)
1 parent 6f91096 commit c9fb601

2 files changed

Lines changed: 20 additions & 0 deletions

File tree

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import org.sonar.check.Rule;
2525
import org.sonar.plugins.python.api.PythonSubscriptionCheck;
2626
import org.sonar.plugins.python.api.SubscriptionContext;
27+
import org.sonar.plugins.python.api.tree.AnnotatedAssignment;
2728
import org.sonar.plugins.python.api.tree.CallExpression;
2829
import org.sonar.plugins.python.api.tree.ComprehensionExpression;
2930
import org.sonar.plugins.python.api.tree.DictCompExpression;
@@ -72,10 +73,18 @@ private static void checkLocalVars(SubscriptionContext ctx, Tree functionTree, S
7273

7374
private static boolean hasOnlyBindingUsages(Symbol symbol) {
7475
List<Usage> usages = symbol.usages();
76+
if (isOnlyTypeAnnotation(usages)) {
77+
return false;
78+
}
7579
return usages.stream().noneMatch(usage -> usage.kind() == Usage.Kind.IMPORT)
7680
&& usages.stream().allMatch(Usage::isBindingUsage);
7781
}
7882

83+
private static boolean isOnlyTypeAnnotation(List<Usage> usages) {
84+
return usages.size() == 1 && usages.get(0).isBindingUsage() &&
85+
TreeUtils.firstAncestor(usages.get(0).tree(), t -> t.is(Kind.ANNOTATED_ASSIGNMENT) && ((AnnotatedAssignment) t).assignedValue() == null) != null;
86+
}
87+
7988
private static boolean isTupleDeclaration(Tree tree) {
8089
return TreeUtils.firstAncestor(tree, t -> t.is(Kind.TUPLE)
8190
|| (t.is(Kind.EXPRESSION_LIST) && ((ExpressionList) t).expressions().size() > 1)

python-checks/src/test/resources/checks/unusedLocalVariable.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,3 +66,14 @@ def for_loops():
6666
def unused_import():
6767
import foo # OK, should be handled in a dedicated rule
6868
from x import y # OK, should be handled in a dedicated rule
69+
70+
def no_fp_type_annotation():
71+
value: str # OK
72+
73+
def no_fp_type_annotation_2():
74+
value: str # OK
75+
return [int(value) for value in something()]
76+
77+
def no_fn_type_annotation_with_assignment():
78+
value: str = "hello" # Noncompliant
79+
return [int(value) for value in something()]

0 commit comments

Comments
 (0)