|
27 | 27 | import org.sonar.check.RuleProperty; |
28 | 28 | import org.sonar.plugins.python.api.PythonSubscriptionCheck; |
29 | 29 | import org.sonar.plugins.python.api.SubscriptionContext; |
| 30 | +import org.sonar.plugins.python.api.symbols.FunctionSymbol; |
30 | 31 | import org.sonar.plugins.python.api.symbols.Symbol; |
31 | 32 | import org.sonar.plugins.python.api.symbols.Usage; |
32 | 33 | import org.sonar.plugins.python.api.tree.AssignmentStatement; |
33 | 34 | import org.sonar.plugins.python.api.tree.Expression; |
34 | 35 | import org.sonar.plugins.python.api.tree.FunctionDef; |
35 | 36 | import org.sonar.plugins.python.api.tree.Name; |
| 37 | +import org.sonar.plugins.python.api.tree.Parameter; |
36 | 38 | import org.sonar.plugins.python.api.tree.SubscriptionExpression; |
37 | 39 | import org.sonar.plugins.python.api.tree.Tree; |
38 | 40 | import org.sonar.plugins.python.api.types.v2.PythonType; |
@@ -168,7 +170,52 @@ private void raiseIssueForNameAndUsage(SubscriptionContext ctx, String name, Usa |
168 | 170 | if (name.length() <= 1) { |
169 | 171 | return; |
170 | 172 | } |
| 173 | + } else if (kind == UsageV2.Kind.PARAMETER && isParameterNameFromOverriddenMethod(usage, name)) { |
| 174 | + return; |
171 | 175 | } |
172 | 176 | ctx.addIssue(usage.tree(), String.format(MESSAGE, type, name, format)); |
173 | 177 | } |
| 178 | + |
| 179 | + private static boolean isParameterNameFromOverriddenMethod(UsageV2 usage, String parameterName) { |
| 180 | + Tree functionLikeAncestor = TreeUtils.firstAncestorOfKind(usage.tree(), Tree.Kind.FUNCDEF, Tree.Kind.LAMBDA); |
| 181 | + if (functionLikeAncestor == null || functionLikeAncestor.is(Tree.Kind.LAMBDA)) { |
| 182 | + return false; |
| 183 | + } |
| 184 | + FunctionDef functionDef = (FunctionDef) functionLikeAncestor; |
| 185 | + |
| 186 | + int parameterIndex = getParameterIndex(functionDef, parameterName); |
| 187 | + if (parameterIndex < 0) { |
| 188 | + return false; |
| 189 | + } |
| 190 | + |
| 191 | + FunctionSymbol functionSymbol = TreeUtils.getFunctionSymbolFromDef(functionDef); |
| 192 | + if (functionSymbol == null) { |
| 193 | + return false; |
| 194 | + } |
| 195 | + |
| 196 | + List<FunctionSymbol> overriddenMethods = SymbolUtils.getOverriddenMethods(functionSymbol); |
| 197 | + for (FunctionSymbol overriddenMethod : overriddenMethods) { |
| 198 | + List<FunctionSymbol.Parameter> overriddenParams = overriddenMethod.parameters(); |
| 199 | + // parameterIndex is based on positional parameters only, while overriddenParams contains all parameters. |
| 200 | + // This comparison works because positional parameters are always a prefix of the full parameter list. |
| 201 | + if (parameterIndex < overriddenParams.size()) { |
| 202 | + String overriddenParamName = overriddenParams.get(parameterIndex).name(); |
| 203 | + if (parameterName.equals(overriddenParamName)) { |
| 204 | + return true; |
| 205 | + } |
| 206 | + } |
| 207 | + } |
| 208 | + return false; |
| 209 | + } |
| 210 | + |
| 211 | + private static int getParameterIndex(FunctionDef functionDef, String parameterName) { |
| 212 | + List<Parameter> parameters = TreeUtils.positionalParameters(functionDef); |
| 213 | + for (int i = 0; i < parameters.size(); i++) { |
| 214 | + Name paramName = parameters.get(i).name(); |
| 215 | + if (paramName != null && parameterName.equals(paramName.name())) { |
| 216 | + return i; |
| 217 | + } |
| 218 | + } |
| 219 | + return -1; |
| 220 | + } |
174 | 221 | } |
0 commit comments