[Commonizer] Implement SimpleCirSupertypesResolverTest

^KT-47430
This commit is contained in:
sebastian.sellmair
2021-08-13 11:26:05 +02:00
committed by Space
parent f64a0efa8b
commit 1e95717b8d
3 changed files with 193 additions and 1 deletions
@@ -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<CirClassType>()?.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<CirClassType>()?.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")
}
}
}
@@ -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<CirClassType>(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()
@@ -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)
}