2323import javax .annotation .Nullable ;
2424import org .sonar .check .Rule ;
2525import org .sonar .plugins .python .api .LocationInFile ;
26+ import org .sonar .plugins .python .api .SubscriptionContext ;
2627import org .sonar .plugins .python .api .symbols .ClassSymbol ;
2728import org .sonar .plugins .python .api .symbols .FunctionSymbol ;
2829import org .sonar .plugins .python .api .symbols .Symbol ;
4344import org .sonar .plugins .python .api .types .v2 .FullyQualifiedNameHelper ;
4445import org .sonar .plugins .python .api .types .InferredType ;
4546import org .sonar .plugins .python .api .types .v2 .ClassType ;
47+ import org .sonar .plugins .python .api .types .v2 .UnknownType ;
48+ import org .sonar .plugins .python .api .types .v2 .matchers .TypeMatcher ;
4649import org .sonar .python .tree .TreeUtils ;
4750import org .sonar .python .types .InferredTypes ;
51+ import org .sonar .python .types .v2 .matchers .InternalTypeMatchers ;
4852
4953import static org .sonar .plugins .python .api .symbols .Symbol .Kind .CLASS ;
5054import static org .sonar .plugins .python .api .symbols .Symbol .Kind .FUNCTION ;
5357@ Rule (key = "S5644" )
5458public class ItemOperationsTypeCheck extends ItemOperationsType {
5559
60+ private static final TypeMatcher KNOWN_DECORATOR_EFFECTS = InternalTypeMatchers .hasKnownClassDecoratorEffectsInHierarchy ();
61+
5662 private static final Set <String > TYPING_LITERAL = Set .of ("typing.Literal" , "typing_extensions.Literal" );
5763 private static final Set <String > TYPING_ANNOTATED = Set .of ("typing.Annotated" , "typing_extensions.Annotated" );
5864
5965 @ Override
6066 public boolean isValidSubscription (Expression subscriptionObject , String requiredMethod , @ Nullable String classRequiredMethod ,
61- Map <LocationInFile , String > secondaries ) {
67+ Map <LocationInFile , String > secondaries , SubscriptionContext context ) {
6268
6369 if (subscriptionObject .is (Tree .Kind .GENERATOR_EXPR )) {
6470 return false ;
@@ -75,10 +81,16 @@ public boolean isValidSubscription(Expression subscriptionObject, String require
7581 return true ;
7682 }
7783 if (symbol .is (FUNCTION , CLASS )) {
78- return isValidSubscriptionSymbol (symbol , subscriptionObject , secondaries , requiredMethod , classRequiredMethod );
84+ return isValidSubscriptionSymbol (symbol , subscriptionObject , secondaries , requiredMethod , classRequiredMethod , context );
7985 }
8086 }
8187
88+ // Preserve the existing V1 check when V2 has no type information at all.
89+ if (!(subscriptionObject .typeV2 () instanceof UnknownType )
90+ && !KNOWN_DECORATOR_EFFECTS .isTrueFor (subscriptionObject , context )) {
91+ return true ;
92+ }
93+
8294 InferredType type = subscriptionObject .type ();
8395 String typeName = InferredTypes .typeName (type );
8496 String secondaryMessage = typeName != null ? String .format (SECONDARY_MESSAGE , typeName ) : DEFAULT_SECONDARY_MESSAGE ;
@@ -87,10 +99,11 @@ public boolean isValidSubscription(Expression subscriptionObject, String require
8799 }
88100
89101 private static boolean isValidSubscriptionSymbol (Symbol symbol , Expression subscriptionObject , Map <LocationInFile , String > secondaries , String requiredMethod ,
90- @ Nullable String classRequiredMethod ) {
102+ @ Nullable String classRequiredMethod , SubscriptionContext context ) {
91103 LocationInFile locationInFile = symbol .is (FUNCTION ) ? ((FunctionSymbol ) symbol ).definitionLocation () : ((ClassSymbol ) symbol ).definitionLocation ();
92104 secondaries .put (locationInFile , SECONDARY_MESSAGE .formatted (symbol .name ()));
93105 return isSubscriptionInClassArg (subscriptionObject )
106+ || (symbol .is (CLASS ) && !KNOWN_DECORATOR_EFFECTS .isTrueFor (subscriptionObject , context ))
94107 || canHaveMethod (symbol , requiredMethod , classRequiredMethod )
95108 || isValidGenericUsage (symbol , subscriptionObject , requiredMethod );
96109 }
@@ -207,7 +220,6 @@ private static boolean canHaveMethod(Symbol symbol, String requiredMethod, @Null
207220 }
208221 ClassSymbol classSymbol = (ClassSymbol ) symbol ;
209222 return classSymbol .canHaveMember (requiredMethod )
210- || (classRequiredMethod != null && classSymbol .canHaveMember (classRequiredMethod ))
211- || classSymbol .hasDecorators ();
223+ || (classRequiredMethod != null && classSymbol .canHaveMember (classRequiredMethod ));
212224 }
213225}
0 commit comments