|
21 | 21 |
|
22 | 22 | import java.util.Comparator;
|
23 | 23 | import java.util.EnumSet;
|
| 24 | +import java.util.List; |
24 | 25 | import java.util.regex.Pattern;
|
25 | 26 | import org.sonar.check.Rule;
|
26 | 27 | import org.sonar.check.RuleProperty;
|
27 | 28 | import org.sonar.plugins.python.api.PythonSubscriptionCheck;
|
28 | 29 | import org.sonar.plugins.python.api.SubscriptionContext;
|
| 30 | +import org.sonar.plugins.python.api.symbols.Symbol; |
| 31 | +import org.sonar.plugins.python.api.symbols.Usage; |
| 32 | +import org.sonar.plugins.python.api.tree.AssignmentStatement; |
29 | 33 | import org.sonar.plugins.python.api.tree.Expression;
|
30 | 34 | import org.sonar.plugins.python.api.tree.FunctionDef;
|
| 35 | +import org.sonar.plugins.python.api.tree.Name; |
| 36 | +import org.sonar.plugins.python.api.tree.SubscriptionExpression; |
31 | 37 | import org.sonar.plugins.python.api.tree.Tree;
|
32 |
| -import org.sonar.plugins.python.api.symbols.Symbol; |
33 |
| -import org.sonar.plugins.python.api.symbols.Usage; |
34 | 38 |
|
35 | 39 | @Rule(key = "S117")
|
36 | 40 | public class LocalVariableAndParameterNameConventionCheck extends PythonSubscriptionCheck {
|
@@ -78,7 +82,42 @@ private void checkName(Symbol symbol, SubscriptionContext ctx) {
|
78 | 82 | }
|
79 | 83 |
|
80 | 84 | private static boolean isType(Symbol symbol) {
|
81 |
| - return symbol.usages().stream().map(Usage::tree).filter(Expression.class::isInstance).map(Expression.class::cast).anyMatch(e -> e.type().mustBeOrExtend("type")); |
| 85 | + return isExtendingType(symbol) || isAssignedFromTyping(symbol); |
| 86 | + } |
| 87 | + |
| 88 | + private static boolean isExtendingType(Symbol symbol) { |
| 89 | + return symbol.usages().stream().map(Usage::tree).filter(Expression.class::isInstance).map(Expression.class::cast).anyMatch(e -> e.type().mustBeOrExtend("type")) || |
| 90 | + (symbol.annotatedTypeName() != null && symbol.annotatedTypeName().startsWith("typing.")); |
| 91 | + } |
| 92 | + |
| 93 | + private static boolean isAssignedFromTyping(Symbol symbol) { |
| 94 | + List<Tree> assignmentNames = symbol.usages().stream().filter(u -> u.kind() == Usage.Kind.ASSIGNMENT_LHS).map(Usage::tree).toList(); |
| 95 | + for (Tree assignmentName : assignmentNames) { |
| 96 | + Expression assignedValue = getAssignedValue(assignmentName); |
| 97 | + if (assignedValue == null) { |
| 98 | + continue; |
| 99 | + } |
| 100 | + if (assignedValue.is(Tree.Kind.SUBSCRIPTION)) { |
| 101 | + SubscriptionExpression subscriptionExpression = (SubscriptionExpression) assignedValue; |
| 102 | + if (subscriptionExpression.object().is(Tree.Kind.NAME)) { |
| 103 | + Symbol assignedSymbol = ((Name) subscriptionExpression.object()).symbol(); |
| 104 | + if (assignedSymbol != null && isExtendingType(assignedSymbol)) { |
| 105 | + return true; |
| 106 | + } |
| 107 | + } |
| 108 | + } |
| 109 | + } |
| 110 | + return false; |
| 111 | + } |
| 112 | + |
| 113 | + private static Expression getAssignedValue(Tree assignmentName) { |
| 114 | + while (assignmentName != null && !assignmentName.is(Tree.Kind.ASSIGNMENT_STMT)) { |
| 115 | + assignmentName = assignmentName.parent(); |
| 116 | + } |
| 117 | + if (assignmentName == null) { |
| 118 | + return null; |
| 119 | + } |
| 120 | + return ((AssignmentStatement) assignmentName).assignedValue(); |
82 | 121 | }
|
83 | 122 |
|
84 | 123 | private void raiseIssueForNameAndUsage(SubscriptionContext ctx, String name, Usage usage) {
|
|
0 commit comments