@@ -156,21 +156,94 @@ void builtinGenericType() {
156
156
void userDefinedGenericType () {
157
157
FileInput fileInput = inferTypes (
158
158
"""
159
- from typing import Generic
159
+ from typing import Generic, TypeVar
160
+ T = TypeVar('T')
160
161
class MyClass(Generic[T]): ...
161
162
x = MyClass[str]()
162
163
x
163
164
"""
164
165
);
165
- PythonType classType = ((ClassDef ) fileInput .statements ().statements ().get (1 )).name ().typeV2 ();
166
- ObjectType xType = (ObjectType ) ((ExpressionStatement ) fileInput .statements ().statements ().get (3 )).expressions ().get (0 ).typeV2 ();
166
+ PythonType classType = ((ClassDef ) fileInput .statements ().statements ().get (2 )).name ().typeV2 ();
167
+ ObjectType xType = (ObjectType ) ((ExpressionStatement ) fileInput .statements ().statements ().get (4 )).expressions ().get (0 ).typeV2 ();
167
168
assertThat (xType .unwrappedType ()).isEqualTo (classType );
168
169
// SONARPY-2356: Instantiation of specialized classes
169
170
assertThat (xType .attributes ()).isEmpty ();
170
171
}
171
172
172
173
@ Test
173
174
void inheritedGenericType () {
175
+ FileInput fileInput = inferTypes (
176
+ """
177
+ from typing import Generic, TypeVar
178
+ T = TypeVar('T')
179
+ class MyClass(Generic[T]): ...
180
+ class MyOtherClass(MyClass[T]): ...
181
+ x = MyOtherClass[str]()
182
+ x
183
+ """
184
+ );
185
+ ClassType myOtherClassType = (ClassType ) ((ClassDef ) fileInput .statements ().statements ().get (3 )).name ().typeV2 ();
186
+ assertThat (myOtherClassType .isGeneric ()).isTrue ();
187
+ PythonType xType = ((ExpressionStatement ) fileInput .statements ().statements ().get (5 )).expressions ().get (0 ).typeV2 ();
188
+ assertThat (xType .unwrappedType ()).isEqualTo (myOtherClassType );
189
+ }
190
+
191
+ @ Test
192
+ void inheritedGenericTypeUnsupportedExpression () {
193
+ FileInput fileInput = inferTypes (
194
+ """
195
+ from typing import Generic, TypeVar
196
+ T = TypeVar('T')
197
+ class MyClass(Generic[T()]): ...
198
+ class MyOtherClass(MyClass[T]): ...
199
+ x = MyOtherClass[str]()
200
+ x
201
+ """
202
+ );
203
+ ClassType myOtherClassType = (ClassType ) ((ClassDef ) fileInput .statements ().statements ().get (3 )).name ().typeV2 ();
204
+ assertThat (myOtherClassType .isGeneric ()).isFalse ();
205
+ PythonType xType = ((ExpressionStatement ) fileInput .statements ().statements ().get (5 )).expressions ().get (0 ).typeV2 ();
206
+ assertThat (xType .unwrappedType ()).isInstanceOf (UnknownType .class );
207
+ }
208
+
209
+ @ Test
210
+ void inheritedGenericTypeVarAnnotatedAssignment () {
211
+ FileInput fileInput = inferTypes (
212
+ """
213
+ from typing import Generic, TypeVar
214
+ T: TypeVar = TypeVar('T')
215
+ class MyClass(Generic[T]): ...
216
+ class MyOtherClass(MyClass[T]): ...
217
+ x = MyOtherClass[str]()
218
+ x
219
+ """
220
+ );
221
+ ClassType myOtherClassType = (ClassType ) ((ClassDef ) fileInput .statements ().statements ().get (3 )).name ().typeV2 ();
222
+ assertThat (myOtherClassType .isGeneric ()).isTrue ();
223
+ PythonType xType = ((ExpressionStatement ) fileInput .statements ().statements ().get (5 )).expressions ().get (0 ).typeV2 ();
224
+ assertThat (xType .unwrappedType ()).isEqualTo (myOtherClassType );
225
+ }
226
+
227
+ @ Test
228
+ void inheritedGenericTypeVarAssignmentExpression () {
229
+ FileInput fileInput = inferTypes (
230
+ """
231
+ from typing import Generic, TypeVar
232
+ foo(T:=TypeVar('T'))
233
+ class MyClass(Generic[T]): ...
234
+ class MyOtherClass(MyClass[T]): ...
235
+ x = MyOtherClass[str]()
236
+ x
237
+ """
238
+ );
239
+ ClassType myOtherClassType = (ClassType ) ((ClassDef ) fileInput .statements ().statements ().get (3 )).name ().typeV2 ();
240
+ assertThat (myOtherClassType .isGeneric ()).isTrue ();
241
+ PythonType xType = ((ExpressionStatement ) fileInput .statements ().statements ().get (5 )).expressions ().get (0 ).typeV2 ();
242
+ assertThat (xType .unwrappedType ()).isEqualTo (myOtherClassType );
243
+ }
244
+
245
+ @ Test
246
+ void inheritedGenericTypeUndefinedTypeVar () {
174
247
FileInput fileInput = inferTypes (
175
248
"""
176
249
from typing import Generic
@@ -181,9 +254,10 @@ class MyOtherClass(MyClass[T]): ...
181
254
"""
182
255
);
183
256
ClassType myOtherClassType = (ClassType ) ((ClassDef ) fileInput .statements ().statements ().get (2 )).name ().typeV2 ();
184
- assertThat (myOtherClassType .isGeneric ()).isTrue ();
257
+ // TypeVar is undefined: not a proper generic
258
+ assertThat (myOtherClassType .isGeneric ()).isFalse ();
185
259
PythonType xType = ((ExpressionStatement ) fileInput .statements ().statements ().get (4 )).expressions ().get (0 ).typeV2 ();
186
- assertThat (xType .unwrappedType ()).isEqualTo ( myOtherClassType );
260
+ assertThat (xType .unwrappedType ()).isInstanceOf ( UnknownType . class );
187
261
}
188
262
189
263
@ Test
@@ -219,9 +293,9 @@ class MyOtherClass(MyClass[str]): ...
219
293
);
220
294
ClassType myOtherClassType = (ClassType ) ((ClassDef ) fileInput .statements ().statements ().get (2 )).name ().typeV2 ();
221
295
// SONARPY-2356: MyOtherClass can no longer be considered generic (specialized version of MyClass)
222
- assertThat (myOtherClassType .isGeneric ()).isTrue ();
296
+ assertThat (myOtherClassType .isGeneric ()).isFalse ();
223
297
PythonType xType = ((ExpressionStatement ) fileInput .statements ().statements ().get (4 )).expressions ().get (0 ).typeV2 ();
224
- assertThat (xType .unwrappedType ()).isEqualTo ( myOtherClassType );
298
+ assertThat (xType .unwrappedType ()).isInstanceOf ( UnknownType . class );
225
299
}
226
300
227
301
@ Test
0 commit comments