2222import org .junit .jupiter .params .ParameterizedTest ;
2323import org .junit .jupiter .params .provider .Arguments ;
2424import org .junit .jupiter .params .provider .MethodSource ;
25+ import org .sonar .python .tree .TokenImpl ;
26+ import org .sonar .python .tree .UnaryExpressionImpl ;
2527import org .sonar .python .types .v2 .ObjectType ;
2628import org .sonar .python .types .v2 .PythonType ;
2729import org .sonar .python .types .v2 .TypesTestUtils ;
2830
2931import static org .assertj .core .api .Assertions .assertThat ;
32+ import static org .mockito .Mockito .mock ;
33+ import static org .mockito .Mockito .when ;
3034import static org .sonar .python .PythonTestUtils .lastExpression ;
3135import static org .sonar .python .PythonTestUtils .pythonFile ;
3236import static org .sonar .python .types .v2 .TypesTestUtils .PROJECT_LEVEL_TYPE_TABLE ;
@@ -54,15 +58,13 @@ static Stream<Arguments> testSources() {
5458 Arguments .of ("+(True)" , TypesTestUtils .INT_TYPE ),
5559
5660 Arguments .of ("~1" , TypesTestUtils .INT_TYPE ),
57- Arguments .of ("~1.0" , TypesTestUtils .INT_TYPE ),
58- Arguments .of ("~(3+2j)" , TypesTestUtils .INT_TYPE ),
59- Arguments .of ("~(1j)" , TypesTestUtils .INT_TYPE ),
6061 Arguments .of ("~(True)" , TypesTestUtils .INT_TYPE ),
6162
6263 Arguments .of ("not 1" , TypesTestUtils .BOOL_TYPE ),
6364 Arguments .of ("not 1.0" , TypesTestUtils .BOOL_TYPE ),
6465 Arguments .of ("not (2j)" , TypesTestUtils .BOOL_TYPE ),
65- Arguments .of ("not (True)" , TypesTestUtils .BOOL_TYPE )
66+ Arguments .of ("not (True)" , TypesTestUtils .BOOL_TYPE ),
67+ Arguments .of ("not x" , TypesTestUtils .BOOL_TYPE )
6668 );
6769 }
6870
@@ -77,12 +79,32 @@ void test(String code, PythonType expectedType) {
7779 assertThat (objectType .type ()).isEqualTo (expectedType ));
7880 }
7981
82+ static Stream <Arguments > testUnknownReturnSources () {
83+ return Stream .of (
84+ Arguments .of ("~x" ),
85+ Arguments .of ("~1.0" ),
86+ Arguments .of ("~(1j)" ),
87+ Arguments .of ("~(3+2j)" ),
88+ Arguments .of ("-x" ),
89+ Arguments .of ("+x" )
90+ );
91+ }
92+
93+ @ ParameterizedTest
94+ @ MethodSource ("testUnknownReturnSources" )
95+ void testUnknownReturn (String code ) {
96+ var expr = lastExpression (code );
97+ expr .accept (trivialTypeInferenceVisitor );
98+ expr .accept (trivialTypePropagationVisitor );
99+ assertThat (expr .typeV2 ()).isEqualTo (PythonType .UNKNOWN );
100+ }
101+
80102 static Stream <Arguments > customNumberClassTestSource () {
81103 return Stream .of (
82104 Arguments .of ("+(MyNum())" , PythonType .UNKNOWN ),
83105 Arguments .of ("-(MyNum())" , PythonType .UNKNOWN ),
84106 Arguments .of ("not (MyNum())" , new ObjectType (TypesTestUtils .BOOL_TYPE )),
85- Arguments .of ("~(MyNum())" , new ObjectType ( TypesTestUtils . INT_TYPE ) )
107+ Arguments .of ("~(MyNum())" , PythonType . UNKNOWN )
86108 );
87109 }
88110
@@ -105,4 +127,16 @@ void testNotOfCustomClass() {
105127 assertThat (expr .typeV2 ()).isInstanceOfSatisfying (ObjectType .class , objectType ->
106128 assertThat (objectType .type ()).isEqualTo (TypesTestUtils .BOOL_TYPE ));
107129 }
130+
131+ @ Test
132+ void testUnknownOperator () {
133+ var operator = mock (TokenImpl .class );
134+ when (operator .value ()).thenReturn ("invalid_operator" );
135+ UnaryExpressionImpl expr = new UnaryExpressionImpl (operator , lastExpression ("1" ));
136+ expr .typeV2 (TypesTestUtils .INT_TYPE );
137+
138+ expr .accept (trivialTypePropagationVisitor );
139+ assertThat (expr .typeV2 ()).isEqualTo (PythonType .UNKNOWN );
140+ }
141+
108142}
0 commit comments