19
19
*/
20
20
package org .sonar .python .semantic .v2 ;
21
21
22
- import java .io .File ;
23
22
import java .util .Comparator ;
24
23
import java .util .HashMap ;
25
24
import java .util .HashSet ;
26
25
import java .util .List ;
27
26
import java .util .Map ;
28
27
import java .util .Set ;
29
28
import org .assertj .core .api .Assertions ;
30
- import org .junit .jupiter .api .BeforeAll ;
31
29
import org .junit .jupiter .api .Disabled ;
32
30
import org .junit .jupiter .api .Test ;
33
31
import org .sonar .plugins .python .api .PythonFile ;
45
43
import org .sonar .plugins .python .api .tree .StatementList ;
46
44
import org .sonar .plugins .python .api .tree .Tree ;
47
45
import org .sonar .python .PythonTestUtils ;
48
- import org .sonar .python .TestPythonVisitorRunner ;
49
46
import org .sonar .python .semantic .ClassSymbolImpl ;
50
47
import org .sonar .python .semantic .ProjectLevelSymbolTable ;
51
48
import org .sonar .python .tree .TreeUtils ;
63
60
import static org .sonar .python .types .v2 .TypesTestUtils .STR_TYPE ;
64
61
65
62
class TypeInferenceV2Test {
66
- private static FileInput fileInput ;
67
63
68
64
static PythonFile pythonFile = PythonTestUtils .pythonFile ("" );
69
65
70
- @ BeforeAll
71
- static void init () {
72
- var context = TestPythonVisitorRunner .createContext (new File ("src/test/resources/semantic/v2/script.py" ));
73
- fileInput = context .rootTree ();
74
- }
75
-
76
- @ Test
77
- void test () {
78
- var pythonFile = PythonTestUtils .pythonFile ("script.py" );
79
- var symbolTable = new SymbolTableBuilderV2 (fileInput )
80
- .build ();
81
- new TypeInferenceV2 (new ProjectLevelTypeTable (ProjectLevelSymbolTable .empty ()), pythonFile , symbolTable ).inferTypes (fileInput );
82
-
83
- System .out .println ("hello" );
84
- }
85
-
86
66
@ Test
87
67
void testTypeshedImports () {
88
68
FileInput root = inferTypes ("""
@@ -263,7 +243,114 @@ void inferTypeForBuiltins() {
263
243
}
264
244
265
245
@ Test
266
- void inferTypeForReassignedBuiltins () {
246
+ @ Disabled ("Single assigned is approximated for now" )
247
+ void inferTypesInsideFunction1 () {
248
+ FileInput root = inferTypes ("""
249
+ x = 42
250
+ def foo():
251
+ x
252
+ """ );
253
+
254
+ var functionDef = (FunctionDef ) root .statements ().statements ().get (1 );
255
+ var lastExpressionStatement = (ExpressionStatement ) functionDef .body ().statements ().get (functionDef .body ().statements ().size () -1 );
256
+ Assertions .assertThat (lastExpressionStatement .expressions ().get (0 ).typeV2 ().unwrappedType ()).isEqualTo (PythonType .UNKNOWN );
257
+ }
258
+
259
+ @ Test
260
+ void inferTypesInsideFunction2 () {
261
+ FileInput root = inferTypes ("""
262
+ x = 42
263
+ def foo():
264
+ x
265
+ x = "hello"
266
+ """ );
267
+
268
+ var functionDef = (FunctionDef ) root .statements ().statements ().get (1 );
269
+ var lastExpressionStatement = (ExpressionStatement ) functionDef .body ().statements ().get (functionDef .body ().statements ().size () -1 );
270
+ Assertions .assertThat (lastExpressionStatement .expressions ().get (0 ).typeV2 ().unwrappedType ()).isEqualTo (PythonType .UNKNOWN );
271
+ }
272
+
273
+ @ Test
274
+ void inferTypesInsideFunction3 () {
275
+ FileInput root = inferTypes ("""
276
+ x = "hello"
277
+ def foo():
278
+ x = 42
279
+ x
280
+ x = "world"
281
+ """ );
282
+
283
+ var functionDef = (FunctionDef ) root .statements ().statements ().get (1 );
284
+ var lastExpressionStatement = (ExpressionStatement ) functionDef .body ().statements ().get (functionDef .body ().statements ().size () -1 );
285
+ Assertions .assertThat (lastExpressionStatement .expressions ().get (0 ).typeV2 ().unwrappedType ()).isEqualTo (INT_TYPE );
286
+ }
287
+
288
+ @ Test
289
+ void inferTypesInsideFunction4 () {
290
+ FileInput root = inferTypes ("""
291
+ def foo():
292
+ x = 42
293
+ x
294
+ """ );
295
+
296
+ var lastExpressionStatement = (ExpressionStatement ) root .statements ().statements ().get (root .statements ().statements ().size () -1 );
297
+ Assertions .assertThat (lastExpressionStatement .expressions ().get (0 ).typeV2 ().unwrappedType ()).isEqualTo (PythonType .UNKNOWN );
298
+ }
299
+
300
+ @ Test
301
+ void inferTypesInsideFunction5 () {
302
+ FileInput root = inferTypes ("""
303
+ def foo(param: int):
304
+ param
305
+ """ );
306
+
307
+ var functionDef = (FunctionDef ) root .statements ().statements ().get (0 );
308
+ var lastExpressionStatement = (ExpressionStatement ) functionDef .body ().statements ().get (functionDef .body ().statements ().size () -1 );
309
+ // TODO: should be declared int
310
+ Assertions .assertThat (lastExpressionStatement .expressions ().get (0 ).typeV2 ().unwrappedType ()).isEqualTo (PythonType .UNKNOWN );
311
+ }
312
+
313
+ @ Test
314
+ void inferTypesInsideFunction6 () {
315
+ FileInput root = inferTypes ("""
316
+ def foo(param: int):
317
+ param = "hello"
318
+ param
319
+ """ );
320
+
321
+ var functionDef = (FunctionDef ) root .statements ().statements ().get (0 );
322
+ var lastExpressionStatement = (ExpressionStatement ) functionDef .body ().statements ().get (functionDef .body ().statements ().size () -1 );
323
+ Assertions .assertThat (lastExpressionStatement .expressions ().get (0 ).typeV2 ().unwrappedType ()).isEqualTo (STR_TYPE );
324
+ }
325
+
326
+ @ Test
327
+ void inferTypesInsideFunction7 () {
328
+ FileInput root = inferTypes ("""
329
+ def foo(param):
330
+ param = "hello"
331
+ param
332
+ """ );
333
+
334
+ var functionDef = (FunctionDef ) root .statements ().statements ().get (0 );
335
+ var lastExpressionStatement = (ExpressionStatement ) functionDef .body ().statements ().get (functionDef .body ().statements ().size () -1 );
336
+ Assertions .assertThat (lastExpressionStatement .expressions ().get (0 ).typeV2 ().unwrappedType ()).isEqualTo (PythonType .UNKNOWN );
337
+ }
338
+
339
+ @ Test
340
+ void inferTypesInsideFunction8 () {
341
+ FileInput root = inferTypes ("""
342
+ def foo(param: int):
343
+ x = param
344
+ x
345
+ """ );
346
+
347
+ var functionDef = (FunctionDef ) root .statements ().statements ().get (0 );
348
+ var lastExpressionStatement = (ExpressionStatement ) functionDef .body ().statements ().get (functionDef .body ().statements ().size () -1 );
349
+ Assertions .assertThat (lastExpressionStatement .expressions ().get (0 ).typeV2 ().unwrappedType ()).isEqualTo (PythonType .UNKNOWN );
350
+ }
351
+
352
+ @ Test
353
+ void inferTypeForReassignedBuiltinsInsideFunction () {
267
354
FileInput root = inferTypes ("""
268
355
def foo():
269
356
global list
@@ -274,7 +361,55 @@ def foo():
274
361
275
362
var functionDef = (FunctionDef ) root .statements ().statements ().get (0 );
276
363
var expressionStatement = (ExpressionStatement ) functionDef .body ().statements ().get (3 );
277
- Assertions .assertThat (expressionStatement .expressions ().get (0 ).typeV2 ()).isEqualTo (PythonType .UNKNOWN );
364
+ // TODO: Shouldn't this be UNKNOWN due to glboal?
365
+ assertThat (expressionStatement .expressions ().get (0 ).typeV2 ().unwrappedType ()).isEqualTo (STR_TYPE );
366
+ }
367
+
368
+ @ Test
369
+ void global_variable () {
370
+ assertThat (lastExpression ("""
371
+ global a
372
+ a = 42
373
+ a
374
+ """ ).typeV2 ().unwrappedType ()).isEqualTo (PythonType .UNKNOWN );
375
+ }
376
+
377
+ @ Test
378
+ void global_variable_builtin () {
379
+ assertThat (lastExpression ("""
380
+ global list
381
+ list = 42
382
+ list
383
+ """ ).typeV2 ().unwrappedType ()).isEqualTo (PythonType .UNKNOWN );
384
+ }
385
+
386
+ @ Test
387
+ void conditional_assignment () {
388
+ PythonType type = lastExpression ("""
389
+ if p:
390
+ x = 42
391
+ else:
392
+ x = 'str'
393
+ x
394
+ """ ).typeV2 ().unwrappedType ();
395
+ assertThat (type ).isInstanceOf (UnionType .class );
396
+ assertThat (((UnionType ) type ).candidates ()).extracting (PythonType ::unwrappedType ).containsExactlyInAnyOrder (INT_TYPE , STR_TYPE );
397
+ }
398
+
399
+ @ Test
400
+ void conditional_assignment_in_function () {
401
+ FileInput fileInput = inferTypes ("""
402
+ def foo():
403
+ if p:
404
+ x = 42
405
+ else:
406
+ x = 'str'
407
+ x
408
+ """ );
409
+ var functionDef = (FunctionDef ) fileInput .statements ().statements ().get (0 );
410
+ var lastExpressionStatement = (ExpressionStatement ) functionDef .body ().statements ().get (functionDef .body ().statements ().size () -1 );
411
+ assertThat (lastExpressionStatement .expressions ().get (0 ).typeV2 ()).isInstanceOf (UnionType .class );
412
+ assertThat (((UnionType ) lastExpressionStatement .expressions ().get (0 ).typeV2 ()).candidates ()).extracting (PythonType ::unwrappedType ).containsExactlyInAnyOrder (INT_TYPE , STR_TYPE );
278
413
}
279
414
280
415
@ Test
@@ -428,6 +563,14 @@ void annotation_with_reassignment() {
428
563
""" ).typeV2 ().unwrappedType ()).isEqualTo (STR_TYPE );
429
564
}
430
565
566
+ @ Test
567
+ void annotation_without_reassignment () {
568
+ assertThat (lastExpression ("""
569
+ a: int
570
+ a
571
+ """ ).typeV2 ().unwrappedType ()).isEqualTo (PythonType .UNKNOWN );
572
+ }
573
+
431
574
@ Test
432
575
@ Disabled ("ObjectType[PythonType.UNKNOWN] should just be PythonType.UNKNOWN" )
433
576
void call_expression () {
0 commit comments