1818
1919import java .util .Arrays ;
2020import java .util .HashSet ;
21+ import java .util .Map ;
2122import java .util .Set ;
23+ import java .util .stream .Collectors ;
2224import org .sonar .check .Rule ;
2325import org .sonar .plugins .python .api .PythonSubscriptionCheck ;
2426import org .sonar .plugins .python .api .SubscriptionContext ;
3133import org .sonar .python .tree .TreeUtils ;
3234import org .sonar .python .types .v2 .PythonType ;
3335import org .sonar .python .types .v2 .TriBool ;
34- import org .sonar .python .types .v2 .TypeChecker ;
36+ import org .sonar .python .types .v2 .TypeCheckBuilder ;
3537
3638@ Rule (key = "S2201" )
3739public class IgnoredPureOperationsCheck extends PythonSubscriptionCheck {
@@ -278,8 +280,13 @@ public class IgnoredPureOperationsCheck extends PythonSubscriptionCheck {
278280 ));
279281 }
280282
283+ private static Map <String , TypeCheckBuilder > pureFunctionsCheckers = null ;
284+ private static Set <TypeCheckBuilder > pureGetitemTypesCheckers = null ;
285+ private static Set <TypeCheckBuilder > pureContainsTypesCheckers = null ;
286+
281287 @ Override
282288 public void initialize (Context context ) {
289+ context .registerSyntaxNodeConsumer (Tree .Kind .FILE_INPUT , IgnoredPureOperationsCheck ::resetTypeCheckers );
283290 context .registerSyntaxNodeConsumer (Tree .Kind .EXPRESSION_STMT , ctx -> {
284291 ExpressionStatement expressionStatement = (ExpressionStatement ) ctx .syntaxNode ();
285292 if (TreeUtils .firstAncestor (expressionStatement , IgnoredPureOperationsCheck ::isInTryBlock ) != null ) {
@@ -290,26 +297,31 @@ public void initialize(Context context) {
290297 });
291298 }
292299
300+ private static void resetTypeCheckers (SubscriptionContext ctx ) {
301+ pureFunctionsCheckers = PURE_FUNCTIONS .stream ().collect (Collectors .toMap (f -> f , f -> ctx .typeChecker ().typeCheckBuilder ().isTypeWithName (f )));
302+ pureGetitemTypesCheckers = PURE_GETITEM_TYPES .stream ().map (f -> ctx .typeChecker ().typeCheckBuilder ().isTypeOrInstanceWithName (f )).collect (Collectors .toSet ());
303+ pureContainsTypesCheckers = PURE_CONTAINS_TYPES .stream ().map (f -> ctx .typeChecker ().typeCheckBuilder ().isTypeOrInstanceWithName (f )).collect (Collectors .toSet ());
304+ }
305+
293306 private static void checkExpression (SubscriptionContext ctx , Expression expression ) {
294- TypeChecker typeChecker = ctx .typeChecker ();
295307 if (expression .is (Tree .Kind .CALL_EXPR )) {
296308 CallExpression callExpression = (CallExpression ) expression ;
297309 PythonType pythonType = callExpression .callee ().typeV2 ();
298- PURE_FUNCTIONS .stream ()
299- .filter (f -> typeChecker . typeCheckBuilder (). isTypeWithName ( f ).check (pythonType ).equals (TriBool .TRUE ))
310+ pureFunctionsCheckers . entrySet () .stream ()
311+ .filter (c -> c . getValue ( ).check (pythonType ).equals (TriBool .TRUE ))
300312 .findFirst ()
301- .ifPresent (result -> ctx .addIssue (callExpression .callee (), String .format (MESSAGE_FORMAT , result )));
313+ .ifPresent (result -> ctx .addIssue (callExpression .callee (), String .format (MESSAGE_FORMAT , result . getKey () )));
302314 } else if (expression .is (Tree .Kind .SUBSCRIPTION )) {
303315 SubscriptionExpression subscriptionExpression = (SubscriptionExpression ) expression ;
304316 PythonType pythonType = subscriptionExpression .object ().typeV2 ();
305- boolean isPureGetitemType = PURE_GETITEM_TYPES .stream ().anyMatch (t -> typeChecker . typeCheckBuilder (). isTypeOrInstanceWithName ( t ) .check (pythonType ).equals (TriBool .TRUE ));
317+ boolean isPureGetitemType = pureGetitemTypesCheckers .stream ().anyMatch (c -> c .check (pythonType ).equals (TriBool .TRUE ));
306318 if (isPureGetitemType ) {
307319 ctx .addIssue (subscriptionExpression , String .format (MESSAGE_FORMAT , "__getitem__" ));
308320 }
309321 } else if (expression .is (Tree .Kind .IN )) {
310322 InExpression inExpression = (InExpression ) expression ;
311323 PythonType pythonType = inExpression .rightOperand ().typeV2 ();
312- boolean isPureContainsType = PURE_CONTAINS_TYPES .stream ().anyMatch (t -> typeChecker . typeCheckBuilder (). isTypeOrInstanceWithName ( t ) .check (pythonType ).equals (TriBool .TRUE ));
324+ boolean isPureContainsType = pureContainsTypesCheckers .stream ().anyMatch (c -> c .check (pythonType ).equals (TriBool .TRUE ));
313325 if (isPureContainsType ) {
314326 ctx .addIssue (inExpression , String .format (MESSAGE_FORMAT , "__contains__" ));
315327 }
0 commit comments