Skip to content

Commit

Permalink
SONARPY-1510 Address the missing TODO fields, and enhance the corresp…
Browse files Browse the repository at this point in the history
…onding tests.
  • Loading branch information
Jeremi Do Dinh authored Oct 20, 2023
1 parent b8423a1 commit 777a113
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@
@Rule(key = "S6792")
public class GenericClassTypeParameterCheck extends PythonSubscriptionCheck {

private static final String MESSAGE = "Use the type parameter syntax to declare this generic class.";
private static final String MESSAGE = "Use the \"type\" parameter syntax to declare this generic class.";
private static final String SECONDARY_MESSAGE_PARENT = "\"Generic\" parent.";
private static final String SECONDARY_MESSAGE_ASSIGNMENT = "\"Generic\" is assigned here.";

@Override
public void initialize(Context context) {
Expand Down Expand Up @@ -74,15 +76,15 @@ private static List<IssueLocation> checkGenericValue(Argument argument) {
Expression expression = ((RegularArgument) argument).expression();

if (isTypingGeneric(expression)) {
return List.of(IssueLocation.preciseLocation(argument, "TODO"));
return List.of(IssueLocation.preciseLocation(argument, SECONDARY_MESSAGE_PARENT));
}
if (expression.is(Tree.Kind.NAME)) {
Name name = (Name) expression;
Expression assignedValue = Expressions.singleAssignedValue(name);
if (assignedValue != null && isTypingGeneric(assignedValue)) {
return List.of(
IssueLocation.preciseLocation(argument, "TODO"),
IssueLocation.preciseLocation(assignedValue, "TODO"));
IssueLocation.preciseLocation(argument, SECONDARY_MESSAGE_PARENT),
IssueLocation.preciseLocation(assignedValue, SECONDARY_MESSAGE_ASSIGNMENT));
}
}
return Collections.emptyList();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,38 +2,38 @@
def class_with_generic_in_declaration():
from typing import Generic, TypeVar
_T_co = TypeVar("_T_co", covariant=True, bound=str)
class ClassA(Generic[_T_co]): # Noncompliant {{Use the type parameter syntax to declare this generic class.}}
# ^^^^^^ ^^^^^^^^^^^^^^<
class ClassA(Generic[_T_co]): # Noncompliant {{Use the "type" parameter syntax to declare this generic class.}}
# ^^^^^^ ^^^^^^^^^^^^^^< {{"Generic" parent.}}
...

def class_with_typing_generic_in_declaration():
import typing
_T_co = typing.TypeVar("_T_co", covariant=True, bound=str)
class ClassA(typing.Generic[_T_co]): # Noncompliant {{Use the type parameter syntax to declare this generic class.}}
# ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^<
class ClassA(typing.Generic[_T_co]): # Noncompliant {{Use the "type" parameter syntax to declare this generic class.}}
# ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^< {{"Generic" parent.}}
...


def class_with_generic_from_variable():
from typing import Generic, TypeVar
_T_co = TypeVar("_T_co", covariant=True, bound=str)
generic = Generic[_T_co]
# ^^^^^^^^^^^^^^>
class ClassA(generic): # Noncompliant {{Use the type parameter syntax to declare this generic class.}}
# ^^^^^^ ^^^^^^^<
# ^^^^^^^^^^^^^^> {{"Generic" is assigned here.}}
class ClassA(generic): # Noncompliant {{Use the "type" parameter syntax to declare this generic class.}}
# ^^^^^^ ^^^^^^^< {{"Generic" parent.}}
...

def class_with_generic_without_subscription():
from typing import Generic
class ClassA(Generic): # Noncompliant {{Use the type parameter syntax to declare this generic class.}}
# ^^^^^^ ^^^^^^^<
class ClassA(Generic): # Noncompliant {{Use the "type" parameter syntax to declare this generic class.}}
# ^^^^^^ ^^^^^^^< {{"Generic" parent.}}
...

def class_with_generic_multiple_parents(xx):
from typing import Generic, TypeVar
_T_co = TypeVar("_T_co", covariant=True, bound=str)
class ClassA(xx, Generic[_T_co]): # Noncompliant {{Use the type parameter syntax to declare this generic class.}}
# ^^^^^^ ^^^^^^^^^^^^^^<
class ClassA(xx, Generic[_T_co]): # Noncompliant {{Use the "type" parameter syntax to declare this generic class.}}
# ^^^^^^ ^^^^^^^^^^^^^^< {{"Generic" parent.}}
...

def compliants(xx):
Expand All @@ -56,16 +56,9 @@ class ClassWithFunctionCallParent(foo()):
class ClassWithUnrelatedAssignedValueParent(generic):
...

class Generic:
...

def compliant_3(xx):
# Test case where we create a class called Generic, which coincidentally is a subscription expression,
# but is not the Generic class that we are interested in.
pass


def compliant_4(xx):
# Test case where we try to instantiate Generic without the subscription check.
pass

class ClassWithDifferentGenericParent(Generic):
...

# Define a class called Generic from a separate module.

0 comments on commit 777a113

Please sign in to comment.