18
18
19
19
import java .util .Arrays ;
20
20
import java .util .HashSet ;
21
+ import java .util .Map ;
21
22
import java .util .Set ;
23
+ import java .util .stream .Collectors ;
22
24
import org .sonar .check .Rule ;
23
25
import org .sonar .plugins .python .api .PythonSubscriptionCheck ;
24
26
import org .sonar .plugins .python .api .SubscriptionContext ;
31
33
import org .sonar .python .tree .TreeUtils ;
32
34
import org .sonar .python .types .v2 .PythonType ;
33
35
import org .sonar .python .types .v2 .TriBool ;
34
- import org .sonar .python .types .v2 .TypeChecker ;
36
+ import org .sonar .python .types .v2 .TypeCheckBuilder ;
35
37
36
38
@ Rule (key = "S2201" )
37
39
public class IgnoredPureOperationsCheck extends PythonSubscriptionCheck {
@@ -278,8 +280,13 @@ public class IgnoredPureOperationsCheck extends PythonSubscriptionCheck {
278
280
));
279
281
}
280
282
283
+ private static Map <String , TypeCheckBuilder > pureFunctionsCheckers = null ;
284
+ private static Set <TypeCheckBuilder > pureGetitemTypesCheckers = null ;
285
+ private static Set <TypeCheckBuilder > pureContainsTypesCheckers = null ;
286
+
281
287
@ Override
282
288
public void initialize (Context context ) {
289
+ context .registerSyntaxNodeConsumer (Tree .Kind .FILE_INPUT , IgnoredPureOperationsCheck ::resetTypeCheckers );
283
290
context .registerSyntaxNodeConsumer (Tree .Kind .EXPRESSION_STMT , ctx -> {
284
291
ExpressionStatement expressionStatement = (ExpressionStatement ) ctx .syntaxNode ();
285
292
if (TreeUtils .firstAncestor (expressionStatement , IgnoredPureOperationsCheck ::isInTryBlock ) != null ) {
@@ -290,26 +297,31 @@ public void initialize(Context context) {
290
297
});
291
298
}
292
299
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
+
293
306
private static void checkExpression (SubscriptionContext ctx , Expression expression ) {
294
- TypeChecker typeChecker = ctx .typeChecker ();
295
307
if (expression .is (Tree .Kind .CALL_EXPR )) {
296
308
CallExpression callExpression = (CallExpression ) expression ;
297
309
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 ))
300
312
.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 () )));
302
314
} else if (expression .is (Tree .Kind .SUBSCRIPTION )) {
303
315
SubscriptionExpression subscriptionExpression = (SubscriptionExpression ) expression ;
304
316
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 ));
306
318
if (isPureGetitemType ) {
307
319
ctx .addIssue (subscriptionExpression , String .format (MESSAGE_FORMAT , "__getitem__" ));
308
320
}
309
321
} else if (expression .is (Tree .Kind .IN )) {
310
322
InExpression inExpression = (InExpression ) expression ;
311
323
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 ));
313
325
if (isPureContainsType ) {
314
326
ctx .addIssue (inExpression , String .format (MESSAGE_FORMAT , "__contains__" ));
315
327
}
0 commit comments