Skip to content

Commit c09c9b7

Browse files
SONARPY-1819 Improve testing to compare types
1 parent 2fa533c commit c09c9b7

File tree

9 files changed

+28
-14
lines changed

9 files changed

+28
-14
lines changed

python-frontend/src/main/java/org/sonar/python/types/v2/ObjectType.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,11 @@ public boolean isCompatibleWith(PythonType another) {
4141
return this.type.isCompatibleWith(another);
4242
}
4343

44+
@Override
45+
public PythonType unwrappedType() {
46+
return this.type;
47+
}
48+
4449
@Override
4550
public Optional<PythonType> resolveMember(String memberName) {
4651
return members().stream()

python-frontend/src/main/java/org/sonar/python/types/v2/PythonType.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,4 +59,8 @@ default TriBool hasMember(String memberName) {
5959
default Optional<LocationInFile> definitionLocation() {
6060
return Optional.empty();
6161
}
62+
63+
default PythonType unwrappedType() {
64+
return this;
65+
}
6266
}

python-frontend/src/test/java/org/sonar/python/semantic/v2/TypeInferenceV2Test.java

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -58,14 +58,15 @@
5858

5959
import static org.assertj.core.api.Assertions.assertThat;
6060
import static org.sonar.python.PythonTestUtils.parseWithoutSymbols;
61+
import static org.sonar.python.types.v2.TypesTestUtils.INT_TYPE;
62+
import static org.sonar.python.types.v2.TypesTestUtils.LIST_TYPE;
63+
import static org.sonar.python.types.v2.TypesTestUtils.STR_TYPE;
6164

6265
class TypeInferenceV2Test {
6366
private static FileInput fileInput;
6467

6568
static PythonFile pythonFile = PythonTestUtils.pythonFile("");
6669

67-
static ModuleType BUILTINS = new ProjectLevelTypeTable(ProjectLevelSymbolTable.empty()).getModule();
68-
6970
@BeforeAll
7071
static void init() {
7172
var context = TestPythonVisitorRunner.createContext(new File("src/test/resources/semantic/v2/script.py"));
@@ -299,20 +300,17 @@ void inferTypeForReassignedVariables() {
299300
var aSymbol = aName.symbolV2();
300301
Assertions.assertThat(aSymbol.usages()).hasSize(6);
301302

302-
var typeNames = aSymbol.usages()
303+
var types = aSymbol.usages()
303304
.stream()
304305
.map(UsageV2::tree)
305306
.map(Name.class::cast)
306307
.sorted(Comparator.comparing(n -> n.firstToken().line()))
307308
.map(Expression::typeV2)
308-
.filter(ObjectType.class::isInstance)
309-
.map(ObjectType.class::cast)
310-
.map(ObjectType::type)
311-
.map(PythonType::name)
309+
.map(PythonType::unwrappedType)
312310
.toList();
313311

314-
Assertions.assertThat(typeNames).hasSize(6)
315-
.containsExactly("int", "int", "str", "str", "str", "str");
312+
Assertions.assertThat(types).hasSize(6)
313+
.containsExactly(INT_TYPE, INT_TYPE, STR_TYPE, STR_TYPE, STR_TYPE, STR_TYPE);
316314
}
317315

318316
@Test
@@ -408,7 +406,7 @@ void compoundAssignmentStr() {
408406
a = 42
409407
a += 1
410408
a
411-
""").typeV2().displayName()).contains("int");
409+
""").typeV2().unwrappedType()).isEqualTo(INT_TYPE);
412410
}
413411

414412
@Test
@@ -418,7 +416,7 @@ void compoundAssignmentList() {
418416
b = 'world'
419417
a += b
420418
a
421-
""").typeV2().displayName()).contains("list");
419+
""").typeV2().unwrappedType()).isEqualTo(LIST_TYPE);
422420
}
423421

424422
@Test
@@ -427,7 +425,7 @@ void annotation_with_reassignment() {
427425
a = "foo"
428426
b: int = a
429427
b
430-
""").typeV2().displayName()).contains("str");
428+
""").typeV2().unwrappedType()).isEqualTo(STR_TYPE);
431429
}
432430

433431
@Test
@@ -450,7 +448,7 @@ class A: pass
450448

451449
@Test
452450
void variable_outside_function() {
453-
assertThat(lastExpression("a = 42; a").typeV2().displayName()).contains("int");
451+
assertThat(lastExpression("a = 42; a").typeV2().unwrappedType()).isEqualTo(INT_TYPE);
454452
}
455453

456454
@Test
@@ -482,7 +480,7 @@ void variable_outside_function_4() {
482480
def foo():
483481
a = 'hello'
484482
a
485-
""").typeV2().displayName()).contains("int");
483+
""").typeV2().unwrappedType()).isEqualTo(INT_TYPE);
486484
}
487485

488486
private static FileInput inferTypes(String lines) {

python-frontend/src/test/java/org/sonar/python/types/v2/ClassTypeTest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ void no_parents() {
6565

6666
assertThat(classType.displayName()).contains("type");
6767
assertThat(classType.instanceDisplayName()).contains("C");
68+
assertThat(classType.unwrappedType()).isEqualTo(classType);
6869

6970
String fileId = SymbolUtils.pathOf(pythonFile).toString();
7071
assertThat(classType.definitionLocation()).contains(new LocationInFile(fileId, 1, 6, 1, 7));

python-frontend/src/test/java/org/sonar/python/types/v2/FunctionTypeTest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ void arity() {
4646
assertThat(functionType.isAsynchronous()).isFalse();
4747
assertThat(functionType.parameters()).isEmpty();
4848
assertThat(functionType.displayName()).contains("Callable");
49+
assertThat(functionType.unwrappedType()).isEqualTo(functionType);
4950
assertThat(functionType.instanceDisplayName()).isEmpty();
5051
String fileId = SymbolUtils.pathOf(pythonFile).toString();
5152
assertThat(functionType.definitionLocation()).contains(new LocationInFile(fileId, 1, 4, 1, 6));

python-frontend/src/test/java/org/sonar/python/types/v2/ModuleTypeTest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ void resolveMemberTest() {
3333

3434
Assertions.assertThat(b.resolveMember("a")).containsSame(a);
3535
Assertions.assertThat(b.resolveMember("b")).isNotPresent();
36+
Assertions.assertThat(b.unwrappedType()).isEqualTo(b);
3637
}
3738

3839
@Test

python-frontend/src/test/java/org/sonar/python/types/v2/ObjectTypeTest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ class A: ...
5656
);
5757
ClassType classType = (ClassType) ((ClassDef) fileInput.statements().statements().get(0)).name().typeV2();
5858
ObjectType objectType = (ObjectType) ((ExpressionStatement) fileInput.statements().statements().get(2)).expressions().get(0).typeV2();
59+
assertThat(objectType.unwrappedType()).isEqualTo(classType);
5960

6061
assertThat(objectType.displayName()).contains("A");
6162
assertThat(objectType.isCompatibleWith(classType)).isTrue();

python-frontend/src/test/java/org/sonar/python/types/v2/TypesTestUtils.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,11 @@
3030
public class TypesTestUtils {
3131

3232
public static final ModuleType BUILTINS = new ProjectLevelTypeTable(ProjectLevelSymbolTable.empty()).getModule();
33+
3334
public static final PythonType INT_TYPE = BUILTINS.resolveMember("int").get();
3435
public static final PythonType BOOL_TYPE = BUILTINS.resolveMember("bool").get();
3536
public static final PythonType STR_TYPE = BUILTINS.resolveMember("str").get();
37+
public static final PythonType LIST_TYPE = BUILTINS.resolveMember("list").get();
3638

3739
public static FileInput parseAndInferTypes(String... code) {
3840
return parseAndInferTypes(PythonTestUtils.pythonFile(""), code);

python-frontend/src/test/java/org/sonar/python/types/v2/UnionTypeTest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ void basicUnion() {
4545
assertThat(unionType.isCompatibleWith(strType)).isTrue();
4646

4747
assertThat(unionType.displayName()).contains("Union[int, str]");
48+
assertThat(unionType.unwrappedType()).isEqualTo(unionType);
4849
assertThat(unionType.instanceDisplayName()).isEmpty();
4950
assertThat(unionType.definitionLocation()).isEmpty();
5051
}

0 commit comments

Comments
 (0)