From 1e95717b8d2860fc39d3ee9a2531ad8b47942f9a Mon Sep 17 00:00:00 2001 From: "sebastian.sellmair" Date: Fri, 13 Aug 2021 11:26:05 +0200 Subject: [PATCH] [Commonizer] Implement SimpleCirSupertypesResolverTest ^KT-47430 --- .../cir/SimpleCirSupertypesResolverTest.kt | 170 ++++++++++++++++++ .../CirTreeClassDeserializerTest.kt | 22 +++ .../kotlin/commonizer/utils/mocks.kt | 2 +- 3 files changed, 193 insertions(+), 1 deletion(-) create mode 100644 native/commonizer/tests/org/jetbrains/kotlin/commonizer/cir/SimpleCirSupertypesResolverTest.kt diff --git a/native/commonizer/tests/org/jetbrains/kotlin/commonizer/cir/SimpleCirSupertypesResolverTest.kt b/native/commonizer/tests/org/jetbrains/kotlin/commonizer/cir/SimpleCirSupertypesResolverTest.kt new file mode 100644 index 00000000000..319ac1cecc6 --- /dev/null +++ b/native/commonizer/tests/org/jetbrains/kotlin/commonizer/cir/SimpleCirSupertypesResolverTest.kt @@ -0,0 +1,170 @@ +/* + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.commonizer.cir + +import org.jetbrains.kotlin.commonizer.mergedtree.CirClassifierIndex +import org.jetbrains.kotlin.commonizer.mergedtree.CirProvided +import org.jetbrains.kotlin.commonizer.mergedtree.CirProvidedClassifiers +import org.jetbrains.kotlin.commonizer.mergedtree.CirProvidedClassifiersByModules +import org.jetbrains.kotlin.commonizer.tree.CirTreeRoot +import org.jetbrains.kotlin.commonizer.utils.KtInlineSourceCommonizerTestCase +import org.jetbrains.kotlin.commonizer.utils.createCirTree +import org.jetbrains.kotlin.commonizer.utils.mockClassType +import org.jetbrains.kotlin.descriptors.ClassKind +import org.jetbrains.kotlin.descriptors.Visibilities +import org.jetbrains.kotlin.utils.addToStdlib.safeAs + +class SimpleCirSupertypesResolverTest : KtInlineSourceCommonizerTestCase() { + + fun `test single supertype from module`() { + val module = createCirTreeFromSourceCode( + """ + interface A + class X: A + """.trimIndent() + ) + + val root = CirTreeRoot(listOf(module)) + val index = CirClassifierIndex(root) + val resolver = SimpleCirSupertypesResolver(index, CirProvidedClassifiers.EMPTY) + val supertypes = resolver.supertypes(mockClassType("X")) + kotlin.test.assertEquals(1, supertypes.size, "Expected single supertype. Found $supertypes") + val supertype = supertypes.single() + kotlin.test.assertEquals(CirEntityId.create("A"), supertype.classifierId) + kotlin.test.assertNull(supertype.outerType, "Expected no outerType") + kotlin.test.assertTrue(supertype.arguments.isEmpty(), "Expected no arguments. Found ${supertype.arguments}") + kotlin.test.assertFalse(supertype.isMarkedNullable, "Expected supertype to be marked *not* nullable") + } + + fun `test outerType`() { + val module = createCirTreeFromSourceCode( + """ + class Outer { + open inner class Inner + class X: Inner() + } + """.trimIndent() + ) + + val root = CirTreeRoot(listOf(module)) + val index = CirClassifierIndex(root) + val resolver = SimpleCirSupertypesResolver(index, CirProvidedClassifiers.EMPTY) + val supertypes = resolver.supertypes(mockClassType("/Outer.X")) + kotlin.test.assertEquals(1, supertypes.size, "Expected single supertype. Found $supertypes") + val supertype = supertypes.single() + kotlin.test.assertEquals(CirEntityId.create("Outer.Inner"), supertype.classifierId) + val outerType = kotlin.test.assertNotNull(supertype.outerType, "Expected outerType") + kotlin.test.assertEquals(CirEntityId.create("Outer"), outerType.classifierId) + } + + fun `test hierarchy supertype from module`() { + val module = createCirTreeFromSourceCode( + """ + interface A + interface B: A + interface C: A + class X: B, C + """.trimIndent() + ) + + val root = CirTreeRoot(listOf(module)) + val index = CirClassifierIndex(root) + val resolver = SimpleCirSupertypesResolver(index, CirProvidedClassifiers.EMPTY) + val supertypes = resolver.supertypes(mockClassType("X")) + + assertEquals( + setOf("/B", "/C"), supertypes.map { it.safeAs()?.classifierId.toString() }.toSet() + ) + + supertypes.forEach { supertype -> + kotlin.test.assertNull(supertype.outerType, "Expected no outerType") + kotlin.test.assertTrue(supertype.arguments.isEmpty(), "Expected no arguments. Found ${supertype.arguments}") + kotlin.test.assertFalse(supertype.isMarkedNullable, "Expected supertype to be marked *not* nullable") + } + } + + fun `test single nullable supertype from module`() { + val module = createCirTreeFromSourceCode( + """ + interface A + class X: A + """.trimIndent() + ) + + val root = CirTreeRoot(listOf(module)) + val index = CirClassifierIndex(root) + val resolver = SimpleCirSupertypesResolver(index, CirProvidedClassifiers.EMPTY) + val supertypes = resolver.supertypes(mockClassType("X", nullable = true)) + kotlin.test.assertEquals(1, supertypes.size, "Expected single supertype. Found $supertypes") + val supertype = supertypes.single() + kotlin.test.assertEquals(CirEntityId.create("A"), supertype.classifierId) + kotlin.test.assertTrue(supertype.isMarkedNullable, "Expected supertype to be marked nullable") + } + + fun `test single supertype from dependencies`() { + val module = createCirTree { + dependency { source("""interface A""") } + source("""class X: A""") + } + + val root = CirTreeRoot(listOf(module)) + val index = CirClassifierIndex(root) + val resolver = SimpleCirSupertypesResolver( + index, CirProvidedClassifiersByModules( + false, mapOf( + CirEntityId.create("A") to CirProvided.RegularClass( + typeParameters = emptyList(), + supertypes = emptyList(), + visibility = Visibilities.Public, + kind = ClassKind.INTERFACE + ) + ) + ) + ) + val supertypes = resolver.supertypes(mockClassType("X")) + kotlin.test.assertEquals(1, supertypes.size, "Expected single supertype. Found $supertypes") + val supertype = supertypes.single() + kotlin.test.assertEquals(CirEntityId.create("A"), supertype.classifierId) + kotlin.test.assertNull(supertype.outerType, "Expected no outerType") + kotlin.test.assertTrue(supertype.arguments.isEmpty(), "Expected no arguments. Found ${supertype.arguments}") + kotlin.test.assertFalse(supertype.isMarkedNullable, "Expected supertype to be marked *not* nullable") + } + + fun `test single supertype from module and dependencies`() { + val module = createCirTree { + dependency { source("""interface A""") } + source( + """ + interface B + class X: A, B + """.trimIndent() + ) + } + + val root = CirTreeRoot(listOf(module)) + val index = CirClassifierIndex(root) + val resolver = SimpleCirSupertypesResolver( + index, CirProvidedClassifiersByModules( + false, mapOf( + CirEntityId.create("A") to CirProvided.RegularClass( + typeParameters = emptyList(), + supertypes = emptyList(), + visibility = Visibilities.Public, + kind = ClassKind.INTERFACE + ) + ) + ) + ) + val supertypes = resolver.supertypes(mockClassType("X")) + kotlin.test.assertEquals(setOf("/A", "/B"), supertypes.map { it.safeAs()?.classifierId.toString() }.toSet()) + + supertypes.forEach { supertype -> + kotlin.test.assertNull(supertype.outerType, "Expected no outerType") + kotlin.test.assertTrue(supertype.arguments.isEmpty(), "Expected no arguments. Found ${supertype.arguments}") + kotlin.test.assertFalse(supertype.isMarkedNullable, "Expected supertype to be marked *not* nullable") + } + } +} diff --git a/native/commonizer/tests/org/jetbrains/kotlin/commonizer/tree/deserializer/CirTreeClassDeserializerTest.kt b/native/commonizer/tests/org/jetbrains/kotlin/commonizer/tree/deserializer/CirTreeClassDeserializerTest.kt index cea5efbfe47..2a113d6189d 100644 --- a/native/commonizer/tests/org/jetbrains/kotlin/commonizer/tree/deserializer/CirTreeClassDeserializerTest.kt +++ b/native/commonizer/tests/org/jetbrains/kotlin/commonizer/tree/deserializer/CirTreeClassDeserializerTest.kt @@ -6,6 +6,8 @@ package org.jetbrains.kotlin.commonizer.tree.deserializer import org.jetbrains.kotlin.commonizer.cir.CirClassType +import org.jetbrains.kotlin.commonizer.tree.CirTreeClass +import org.jetbrains.kotlin.commonizer.util.transitiveClosure import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Visibilities @@ -117,6 +119,26 @@ class CirTreeClassDeserializerTest : AbstractCirTreeDeserializerTest() { } + fun `test supertypes - supertype being nested`() { + val module = createCirTreeFromSourceCode( + """ + class Outer { + open inner class Inner + inner class X: Outer.Inner() + } + """.trimIndent() + ) + + val pkg = module.assertSinglePackage() + val xClass = pkg.classes.flatMap { transitiveClosure(it, CirTreeClass::classes) + it } + .singleOrNull { it.clazz.name.toStrippedString() == "X" } ?: kotlin.test.fail("Missing class 'X'") + val xSuperType = xClass.clazz.supertypes.singleOrNull() + ?: kotlin.test.fail("Expected single supertype for 'X'. Found ${xClass.clazz.supertypes}") + val xClassSuperType = assertIs(xSuperType, "Expected xSuperType to be class type") + assertEquals("/Outer.Inner", xClassSuperType.classifierId.toString()) + assertEquals("/Outer", xClassSuperType.outerType?.classifierId.toString()) + } + fun `test abstract class`() { val module = createCirTreeFromSourceCode("abstract class X") val clazz = module.assertSingleClass() diff --git a/native/commonizer/tests/org/jetbrains/kotlin/commonizer/utils/mocks.kt b/native/commonizer/tests/org/jetbrains/kotlin/commonizer/utils/mocks.kt index 9aefe2fd41f..3d2123c5b14 100644 --- a/native/commonizer/tests/org/jetbrains/kotlin/commonizer/utils/mocks.kt +++ b/native/commonizer/tests/org/jetbrains/kotlin/commonizer/utils/mocks.kt @@ -47,7 +47,7 @@ internal fun mockClassType( ) private fun createValidClassifierId(classifierId: String): CirEntityId { - check(classifierId.none { it == '.' || it == '\\' || it == '?' }) { "Malformed classifier ID: $classifierId" } + check(classifierId.none { it == '\\' || it == '?' }) { "Malformed classifier ID: $classifierId" } return CirEntityId.create(classifierId) }