Skip to content

Commit 75023f9

Browse files
SONARPY-584 Rule S5719: Updated issue message and removed some FPs (SonarSource#650)
* SONARPY-584 Rule S5719: Updated issue message and removed some FPs * Small refactoring on usage search
1 parent a5c9299 commit 75023f9

3 files changed

Lines changed: 21 additions & 6 deletions

File tree

its/ruling/src/test/resources/expected/python-S5719.json

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,4 @@
2929
'project:twisted-12.1.0/twisted/protocols/ftp.py':[
3030
2063,
3131
],
32-
'project:twisted-12.1.0/twisted/trial/test/test_runner.py':[
33-
893,
34-
],
3532
}

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

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import org.sonar.plugins.python.api.SubscriptionContext;
2828
import org.sonar.plugins.python.api.symbols.ClassSymbol;
2929
import org.sonar.plugins.python.api.symbols.FunctionSymbol;
30+
import org.sonar.plugins.python.api.symbols.Usage;
3031
import org.sonar.plugins.python.api.tree.ClassDef;
3132
import org.sonar.plugins.python.api.tree.FunctionDef;
3233
import org.sonar.plugins.python.api.tree.Name;
@@ -39,6 +40,12 @@ public class InstanceAndClassMethodsAtLeastOnePositionalCheck extends PythonSubs
3940

4041
private static final List<String> KNOWN_CLASS_METHODS = Arrays.asList("__new__", "__init_subclass__");
4142

43+
private static boolean isUsageInClassBody(Usage usage, ClassDef classDef) {
44+
// We want all usages that are not function declarations and their closes parent is the class definition
45+
return usage.kind() != Usage.Kind.FUNC_DECLARATION
46+
&& classDef.equals(TreeUtils.firstAncestorOfKind(usage.tree(), Tree.Kind.CLASSDEF, Tree.Kind.FUNCDEF));
47+
}
48+
4249
private static void handleFunctionDef(SubscriptionContext ctx, ClassDef classDef, FunctionDef functionDef) {
4350
List<Parameter> parameters = TreeUtils.positionalParameters(functionDef);
4451
if (!parameters.isEmpty()) {
@@ -51,7 +58,7 @@ private static void handleFunctionDef(SubscriptionContext ctx, ClassDef classDef
5158
}
5259

5360
FunctionSymbol functionSymbol = TreeUtils.getFunctionSymbolFromDef(functionDef);
54-
if (functionSymbol == null || CheckUtils.isCalledInClassBody(functionSymbol, classDef)) {
61+
if (functionSymbol == null || functionSymbol.usages().stream().anyMatch(usage -> isUsageInClassBody(usage, classDef))) {
5562
return;
5663
}
5764

@@ -69,7 +76,7 @@ private static void handleFunctionDef(SubscriptionContext ctx, ClassDef classDef
6976
if (KNOWN_CLASS_METHODS.contains(name) || decoratorNames.contains("classmethod")) {
7077
ctx.addIssue(functionDef.defKeyword(), functionDef.rightPar(), "Add a class parameter");
7178
} else {
72-
ctx.addIssue(functionDef.defKeyword(), functionDef.rightPar(), "Add a \"self\" parameter");
79+
ctx.addIssue(functionDef.defKeyword(), functionDef.rightPar(), "Add a \"self\" or class parameter\"");
7380
}
7481
}
7582

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

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
class Foo:
2-
def instance_method(): # Noncompliant {{Add a "self" parameter}}
2+
def instance_method(): # Noncompliant {{Add a "self" or class parameter"}}
33
# ^^^^^^^^^^^^^^^^^^^^^
44
pass
55

@@ -31,12 +31,23 @@ def _called_in_cls_body(): # OK, this is called in the class body
3131

3232
x = _called_in_cls_body()
3333

34+
def referenced_in_cls_body():
35+
return 1
36+
37+
options = [referenced_in_cls_body]
38+
39+
# FP
40+
def referenced_outside(): # Noncompliant
41+
return 2
42+
3443
def no_pos_args(*, kw): # Noncompliant
3544
pass
3645

3746
def varargs(*args, kwarg): # OK, unlimited number of positional args
3847
pass
3948

49+
outside = [Foo.referenced_outside]
50+
4051
import zope.interface as zi
4152
class MyInterface(zi.Interface):
4253
def do_something(): # OK, it is a zope interface

0 commit comments

Comments
 (0)