19
19
*/
20
20
package org .sonar .python .checks ;
21
21
22
- import java .util .Arrays ;
23
- import java .util .HashSet ;
24
- import java .util .Set ;
25
22
import java .util .function .Predicate ;
26
23
import javax .annotation .Nullable ;
27
24
import org .sonar .check .Rule ;
37
34
import org .sonar .plugins .python .api .tree .Expression ;
38
35
import org .sonar .plugins .python .api .tree .Token ;
39
36
import org .sonar .plugins .python .api .tree .Tree ;
40
- import org .sonar .plugins .python .api .types .InferredType ;
41
37
import org .sonar .python .quickfix .TextEditUtils ;
42
38
import org .sonar .python .tree .TreeUtils ;
39
+ import org .sonar .python .types .v2 .PythonType ;
40
+ import org .sonar .python .types .v2 .TriBool ;
43
41
44
42
import static org .sonar .plugins .python .api .symbols .Symbol .Kind .CLASS ;
45
43
import static org .sonar .plugins .python .api .tree .Tree .Kind .EXCEPT_CLAUSE ;
46
44
import static org .sonar .plugins .python .api .tree .Tree .Kind .EXCEPT_GROUP_CLAUSE ;
47
45
import static org .sonar .plugins .python .api .types .BuiltinTypes .BASE_EXCEPTION ;
48
- import static org .sonar .plugins .python .api .types .BuiltinTypes .DICT ;
49
- import static org .sonar .plugins .python .api .types .BuiltinTypes .LIST ;
50
- import static org .sonar .plugins .python .api .types .BuiltinTypes .SET ;
51
- import static org .sonar .plugins .python .api .types .BuiltinTypes .TUPLE ;
52
46
53
47
@ Rule (key = "S5708" )
54
48
public class CaughtExceptionsCheck extends PythonSubscriptionCheck {
55
49
56
50
private static final String MESSAGE = "Change this expression to be a class deriving from BaseException or a tuple of such classes." ;
57
- private static final Set <String > NON_COMPLIANT_TYPES = new HashSet <>(Arrays .asList (LIST , SET , DICT ));
58
51
public static final String QUICK_FIX_MESSAGE_FORMAT = "Make \" %s\" deriving from \" Exception\" " ;
59
52
60
53
@ Override
@@ -74,7 +67,7 @@ private static void checkExceptClause(SubscriptionContext ctx) {
74
67
var notInheritsFromBaseException = expressionSymbolOpt
75
68
.filter (Predicate .not (CaughtExceptionsCheck ::inheritsFromBaseException ))
76
69
.isPresent ();
77
- if (!canBeOrExtendBaseException (expression . type () ) || notInheritsFromBaseException ) {
70
+ if (!canBeOrExtendBaseException (expression , ctx ) || notInheritsFromBaseException ) {
78
71
var issue = ctx .addIssue (expression , MESSAGE );
79
72
expressionSymbolOpt .ifPresent (symbol -> addQuickFix (issue , symbol ));
80
73
}
@@ -111,21 +104,11 @@ private static void addQuickFix(PreciseIssue issue, Symbol symbol) {
111
104
});
112
105
}
113
106
114
- private static boolean canBeOrExtendBaseException (InferredType type ) {
115
- if (NON_COMPLIANT_TYPES .stream ().anyMatch (type ::canOnlyBe )) {
116
- // due to some limitations in type inference engine,
117
- // type.canBeOrExtend("list" | "set" | "dict") returns true
118
- return false ;
119
- }
120
- if (type .canBeOrExtend (TUPLE )) {
121
- // avoid FP on variables holding a tuple: SONARPY-713
122
- return true ;
123
- }
124
- if (type .canBeOrExtend ("type" )) {
125
- // SONARPY-1666: Here we should only exclude type objects that represent Exception types
126
- return true ;
127
- }
128
- return type .canBeOrExtend (BASE_EXCEPTION );
107
+ private static boolean canBeOrExtendBaseException (Expression expression , SubscriptionContext ctx ) {
108
+ PythonType pythonType = expression .typeV2 ();
109
+ TriBool isBaseException = ctx .typeChecker ().typeCheckBuilder ().isInstanceOf ("BaseException" ).check (pythonType );
110
+ TriBool isTuple = ctx .typeChecker ().typeCheckBuilder ().isBuiltinWithName ("tuple" ).check (pythonType );
111
+ return isBaseException != TriBool .FALSE || isTuple != TriBool .FALSE ;
129
112
}
130
113
131
114
private static boolean inheritsFromBaseException (@ Nullable Symbol symbol ) {
0 commit comments