[Commonizer] Adapt TypeCommonizerTest
^KT-48288
This commit is contained in:
committed by
Space
parent
36a5b53398
commit
9d2553bd18
+1
-1
@@ -28,7 +28,7 @@ internal class ClassOrTypeAliasTypeCommonizer(
|
|||||||
val arguments = TypeArgumentListCommonizer(typeCommonizer).commonize(values.map { it.arguments }) ?: return null
|
val arguments = TypeArgumentListCommonizer(typeCommonizer).commonize(values.map { it.arguments }) ?: return null
|
||||||
val classifierId = selectClassifierId(values)
|
val classifierId = selectClassifierId(values)
|
||||||
?: typeCommonizer.options.enableOptimisticNumberTypeCommonization.ifTrue {
|
?: typeCommonizer.options.enableOptimisticNumberTypeCommonization.ifTrue {
|
||||||
return OptimisticNumbersTypeCommonizer.commonize(values.map { it.expandedType() })
|
return OptimisticNumbersTypeCommonizer.commonize(expansions)
|
||||||
} ?: return null
|
} ?: return null
|
||||||
|
|
||||||
val outerTypes = values.safeCastValues<CirClassOrTypeAliasType, CirClassType>()?.map { it.outerType }
|
val outerTypes = values.safeCastValues<CirClassOrTypeAliasType, CirClassType>()?.map { it.outerType }
|
||||||
|
|||||||
+18
-8
@@ -15,9 +15,10 @@ import org.jetbrains.kotlin.commonizer.cir.CirTypeAlias
|
|||||||
|
|
||||||
internal fun CirCommonClassifierIdResolver(
|
internal fun CirCommonClassifierIdResolver(
|
||||||
classifierIndices: TargetDependent<CirClassifierIndex>,
|
classifierIndices: TargetDependent<CirClassifierIndex>,
|
||||||
dependencies: CirProvidedClassifiers = CirProvidedClassifiers.EMPTY
|
targetDependencies: TargetDependent<CirProvidedClassifiers>,
|
||||||
|
commonDependencies: CirProvidedClassifiers = CirProvidedClassifiers.EMPTY
|
||||||
): CirCommonClassifierIdResolver {
|
): CirCommonClassifierIdResolver {
|
||||||
return CirCommonClassifierIdResolverImpl(classifierIndices, dependencies)
|
return CirCommonClassifierIdResolverImpl(classifierIndices, targetDependencies, commonDependencies)
|
||||||
}
|
}
|
||||||
|
|
||||||
interface CirCommonClassifierIdResolver {
|
interface CirCommonClassifierIdResolver {
|
||||||
@@ -26,7 +27,8 @@ interface CirCommonClassifierIdResolver {
|
|||||||
|
|
||||||
private class CirCommonClassifierIdResolverImpl(
|
private class CirCommonClassifierIdResolverImpl(
|
||||||
private val classifierIndices: TargetDependent<CirClassifierIndex>,
|
private val classifierIndices: TargetDependent<CirClassifierIndex>,
|
||||||
private val dependencies: CirProvidedClassifiers
|
private val targetDependencies: TargetDependent<CirProvidedClassifiers>,
|
||||||
|
private val commonDependencies: CirProvidedClassifiers
|
||||||
) : CirCommonClassifierIdResolver {
|
) : CirCommonClassifierIdResolver {
|
||||||
|
|
||||||
private val cachedResults = THashMap<CirEntityId, CirCommonClassifierId>()
|
private val cachedResults = THashMap<CirEntityId, CirCommonClassifierId>()
|
||||||
@@ -54,8 +56,10 @@ private class CirCommonClassifierIdResolverImpl(
|
|||||||
val nextClassifierId = queue.removeFirst()
|
val nextClassifierId = queue.removeFirst()
|
||||||
|
|
||||||
/* Either CirClassifier or CirProvided.Classifier or null */
|
/* Either CirClassifier or CirProvided.Classifier or null */
|
||||||
val foundClassifiers = classifierIndices.associateWith { index ->
|
val foundClassifiers = classifierIndices.targets.associateWith { index ->
|
||||||
index.findClassifier(nextClassifierId) ?: dependencies.classifier(nextClassifierId)
|
classifierIndices[index].findClassifier(nextClassifierId)
|
||||||
|
?: targetDependencies[index].classifier(nextClassifierId)
|
||||||
|
?: commonDependencies.classifier(nextClassifierId)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Classifier is available for all targets */
|
/* Classifier is available for all targets */
|
||||||
@@ -63,17 +67,23 @@ private class CirCommonClassifierIdResolverImpl(
|
|||||||
results.add(nextClassifierId)
|
results.add(nextClassifierId)
|
||||||
}
|
}
|
||||||
|
|
||||||
foundClassifiers.forEach { (index, classifier) ->
|
foundClassifiers.forEach { (target, classifier) ->
|
||||||
if (classifier == null) return@forEach
|
if (classifier == null) return@forEach
|
||||||
|
|
||||||
// Propagate to the left (towards typealias)
|
// Propagate to the left (towards typealias)
|
||||||
index.findTypeAliasesWithUnderlyingType(nextClassifierId).forEach { alias ->
|
classifierIndices[target].findTypeAliasesWithUnderlyingType(nextClassifierId).forEach { alias ->
|
||||||
if (visited.add(alias.id)) {
|
if (visited.add(alias.id)) {
|
||||||
queue.add(alias.id)
|
queue.add(alias.id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies.findTypeAliasesWithUnderlyingType(nextClassifierId).forEach { aliasId ->
|
targetDependencies[target].findTypeAliasesWithUnderlyingType(nextClassifierId).forEach { aliasId ->
|
||||||
|
if (visited.add(aliasId)) {
|
||||||
|
queue.add(aliasId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
commonDependencies.findTypeAliasesWithUnderlyingType(nextClassifierId).forEach { aliasId ->
|
||||||
if (visited.add(aliasId)) {
|
if (visited.add(aliasId)) {
|
||||||
queue.add(aliasId)
|
queue.add(aliasId)
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -14,7 +14,8 @@ class CirKnownClassifiers(
|
|||||||
val targetDependencies: TargetDependent<CirProvidedClassifiers>,
|
val targetDependencies: TargetDependent<CirProvidedClassifiers>,
|
||||||
val commonizedNodes: CirCommonizedClassifierNodes,
|
val commonizedNodes: CirCommonizedClassifierNodes,
|
||||||
val commonDependencies: CirProvidedClassifiers,
|
val commonDependencies: CirProvidedClassifiers,
|
||||||
val commonClassifierIdResolver: CirCommonClassifierIdResolver = CirCommonClassifierIdResolver(classifierIndices, commonDependencies),
|
val commonClassifierIdResolver: CirCommonClassifierIdResolver =
|
||||||
|
CirCommonClassifierIdResolver(classifierIndices, targetDependencies, commonDependencies),
|
||||||
)
|
)
|
||||||
|
|
||||||
/** A set of all CIR nodes built for commonized classes and type aliases. */
|
/** A set of all CIR nodes built for commonized classes and type aliases. */
|
||||||
|
|||||||
+3
-1
@@ -277,7 +277,9 @@ private fun createCommonClassifierIdResolver(
|
|||||||
return CirCommonClassifierIdResolver(
|
return CirCommonClassifierIdResolver(
|
||||||
TargetDependent(root.withIndex().associate { (index, root) -> LeafCommonizerTarget(index.toString()) to root })
|
TargetDependent(root.withIndex().associate { (index, root) -> LeafCommonizerTarget(index.toString()) to root })
|
||||||
.mapValue(::CirClassifierIndex),
|
.mapValue(::CirClassifierIndex),
|
||||||
dependencies = dependencies
|
targetDependencies = root.withIndex()
|
||||||
|
.associate { (index, _) -> LeafCommonizerTarget(index.toString()) to CirProvidedClassifiers.EMPTY }.toTargetDependent(),
|
||||||
|
commonDependencies = dependencies
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+460
-332
@@ -5,243 +5,454 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.commonizer.core
|
package org.jetbrains.kotlin.commonizer.core
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.commonizer.AbstractInlineSourcesCommonizationTest
|
||||||
|
import org.jetbrains.kotlin.commonizer.LeafCommonizerTarget
|
||||||
import org.jetbrains.kotlin.commonizer.TargetDependent
|
import org.jetbrains.kotlin.commonizer.TargetDependent
|
||||||
import org.jetbrains.kotlin.commonizer.cir.*
|
import org.jetbrains.kotlin.commonizer.cir.CirType
|
||||||
import org.jetbrains.kotlin.commonizer.mergedtree.*
|
import org.jetbrains.kotlin.commonizer.mapValue
|
||||||
import org.jetbrains.kotlin.commonizer.utils.isUnderStandardKotlinPackages
|
import org.jetbrains.kotlin.commonizer.mergedtree.CirClassifierIndex
|
||||||
import org.jetbrains.kotlin.commonizer.utils.mockClassType
|
import org.jetbrains.kotlin.commonizer.mergedtree.CirCommonizedClassifierNodes
|
||||||
import org.jetbrains.kotlin.commonizer.utils.mockTAType
|
import org.jetbrains.kotlin.commonizer.mergedtree.CirKnownClassifiers
|
||||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
import org.jetbrains.kotlin.commonizer.mergedtree.CirProvidedClassifiers
|
||||||
import org.jetbrains.kotlin.descriptors.Modality
|
import org.jetbrains.kotlin.commonizer.tree.mergeCirTree
|
||||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
import org.jetbrains.kotlin.commonizer.utils.*
|
||||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||||
import org.junit.Before
|
|
||||||
import org.junit.Test
|
|
||||||
|
|
||||||
class TypeCommonizerTest : AbstractCommonizerTest<CirType, CirType?>() {
|
class TypeCommonizerTest : AbstractInlineSourcesCommonizationTest() {
|
||||||
|
|
||||||
private lateinit var classifiers: CirKnownClassifiers
|
fun createCommonizer(
|
||||||
|
commonTargetSources: InlineSourceBuilder.ModuleBuilder.() -> Unit = {
|
||||||
@Before
|
source(
|
||||||
fun initialize() {
|
"""
|
||||||
// reset cache
|
package org.sample
|
||||||
classifiers = CirKnownClassifiers(
|
class Foo
|
||||||
classifierIndices = TargetDependent.empty(),
|
class Bar
|
||||||
targetDependencies = TargetDependent.empty(),
|
""".trimIndent(), "commonTargetSource.kt"
|
||||||
commonizedNodes = CirCommonizedClassifierNodes.default(),
|
|
||||||
commonDependencies = object : CirProvidedClassifiers {
|
|
||||||
override fun hasClassifier(classifierId: CirEntityId) = classifierId.packageName.isUnderStandardKotlinPackages
|
|
||||||
override fun classifier(classifierId: CirEntityId) = error("This method should not be called")
|
|
||||||
override fun findTypeAliasesWithUnderlyingType(underlyingClassifier: CirEntityId): List<CirEntityId> = emptyList()
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
source(
|
||||||
|
"""
|
||||||
|
package org.fictitiousPackageName
|
||||||
|
class Foo
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
},
|
||||||
|
commonDependencySources: InlineSourceBuilder.ModuleBuilder.() -> Unit = {
|
||||||
|
source(
|
||||||
|
"""
|
||||||
|
package kotlin.collections
|
||||||
|
class List
|
||||||
|
class Set
|
||||||
|
""".trimIndent(), "collections.kt"
|
||||||
|
)
|
||||||
|
|
||||||
|
source(
|
||||||
|
"""
|
||||||
|
package kotlinx.cinterop
|
||||||
|
class CPointer
|
||||||
|
""".trimIndent(), "cinterop.kt"
|
||||||
|
)
|
||||||
|
|
||||||
|
source(
|
||||||
|
"""
|
||||||
|
package kotlin.fictitiousPackageName
|
||||||
|
class List
|
||||||
|
class CPointer
|
||||||
|
""".trimIndent(), "fictitiousPackageName.kt"
|
||||||
|
)
|
||||||
|
},
|
||||||
|
targetASpecificSources: (InlineSourceBuilder.ModuleBuilder.() -> Unit)? = null,
|
||||||
|
targetBSpecificSources: (InlineSourceBuilder.ModuleBuilder.() -> Unit)? = null,
|
||||||
|
targetCSpecificSources: (InlineSourceBuilder.ModuleBuilder.() -> Unit)? = null,
|
||||||
|
targetADependencySources: (InlineSourceBuilder.ModuleBuilder.() -> Unit)? = null,
|
||||||
|
targetBDependencySources: (InlineSourceBuilder.ModuleBuilder.() -> Unit)? = null,
|
||||||
|
targetCDependencySources: (InlineSourceBuilder.ModuleBuilder.() -> Unit)? = null
|
||||||
|
): TypeCommonizer {
|
||||||
|
|
||||||
|
val targetARoot = createCirTreeRoot {
|
||||||
|
commonTargetSources()
|
||||||
|
if (targetASpecificSources != null) targetASpecificSources()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
val targetBRoot = createCirTreeRoot {
|
||||||
fun classTypesInKotlinPackageWithSameName() = doTestSuccess(
|
commonTargetSources()
|
||||||
expected = mockClassType("kotlin/collections/List"),
|
if (targetBSpecificSources != null) targetBSpecificSources()
|
||||||
|
}
|
||||||
|
|
||||||
|
val targetCRoot = createCirTreeRoot {
|
||||||
|
commonTargetSources()
|
||||||
|
if (targetCSpecificSources != null) targetCSpecificSources()
|
||||||
|
}
|
||||||
|
|
||||||
|
val commonDependencies = createCirProvidedClassifiers { commonDependencySources() }
|
||||||
|
|
||||||
|
val targetADependencies = targetADependencySources?.let { createCirProvidedClassifiers { it() } } ?: CirProvidedClassifiers.EMPTY
|
||||||
|
val targetBDependencies = targetBDependencySources?.let { createCirProvidedClassifiers { it() } } ?: CirProvidedClassifiers.EMPTY
|
||||||
|
val targetCDependencies = targetCDependencySources?.let { createCirProvidedClassifiers { it() } } ?: CirProvidedClassifiers.EMPTY
|
||||||
|
|
||||||
|
val targetDependencies = TargetDependent(
|
||||||
|
LeafCommonizerTarget("a") to targetADependencies,
|
||||||
|
LeafCommonizerTarget("b") to targetBDependencies,
|
||||||
|
LeafCommonizerTarget("c") to targetCDependencies
|
||||||
|
)
|
||||||
|
|
||||||
|
val roots = TargetDependent(
|
||||||
|
LeafCommonizerTarget("a") to targetARoot,
|
||||||
|
LeafCommonizerTarget("b") to targetBRoot,
|
||||||
|
LeafCommonizerTarget("c") to targetCRoot
|
||||||
|
)
|
||||||
|
|
||||||
|
val classifiers = CirKnownClassifiers(
|
||||||
|
classifierIndices = roots.mapValue(::CirClassifierIndex),
|
||||||
|
targetDependencies = targetDependencies,
|
||||||
|
commonizedNodes = CirCommonizedClassifierNodes.default(),
|
||||||
|
commonDependencies = commonDependencies
|
||||||
|
).also { classifiers ->
|
||||||
|
mergeCirTree(LockBasedStorageManager.NO_LOCKS, classifiers, roots)
|
||||||
|
}
|
||||||
|
|
||||||
|
return TypeCommonizer(classifiers)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun `test class types in Kotlin package with same name`() {
|
||||||
|
assertEquals(
|
||||||
|
mockClassType("kotlin/collections/List"), createCommonizer().invoke(
|
||||||
|
listOf(
|
||||||
mockClassType("kotlin/collections/List"),
|
mockClassType("kotlin/collections/List"),
|
||||||
mockClassType("kotlin/collections/List"),
|
mockClassType("kotlin/collections/List"),
|
||||||
mockClassType("kotlin/collections/List")
|
mockClassType("kotlin/collections/List")
|
||||||
)
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalCommonizerStateException::class)
|
fun `test class types in Kotlin package with different names - 1`() {
|
||||||
fun classTypesInKotlinPackageWithDifferentNames1() = doTestFailure(
|
assertEquals(
|
||||||
|
null, createCommonizer().invoke(
|
||||||
|
listOf(
|
||||||
mockClassType("kotlin/collections/List"),
|
mockClassType("kotlin/collections/List"),
|
||||||
mockClassType("kotlin/collections/List"),
|
mockClassType("kotlin/collections/List"),
|
||||||
mockClassType("kotlin/fictitiousPackageName/List")
|
mockClassType("kotlin/fictitiousPackageName/List")
|
||||||
)
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalCommonizerStateException::class)
|
fun `test class types in Kotlin package with different names - 2`() {
|
||||||
fun classTypesInKotlinPackageWithDifferentNames2() = doTestFailure(
|
assertEquals(
|
||||||
|
null, createCommonizer().invoke(
|
||||||
|
listOf(
|
||||||
mockClassType("kotlin/collections/List"),
|
mockClassType("kotlin/collections/List"),
|
||||||
mockClassType("kotlin/collections/List"),
|
mockClassType("kotlin/collections/List"),
|
||||||
mockClassType("kotlin/collections/Set")
|
mockClassType("kotlin/collections/Set")
|
||||||
)
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalCommonizerStateException::class)
|
fun `test class types in Kotlin package with different names - 3`() {
|
||||||
fun classTypesInKotlinPackageWithDifferentNames3() = doTestFailure(
|
assertEquals(
|
||||||
|
null, createCommonizer().invoke(
|
||||||
|
listOf(
|
||||||
mockClassType("kotlin/collections/List"),
|
mockClassType("kotlin/collections/List"),
|
||||||
mockClassType("kotlin/collections/List"),
|
mockClassType("kotlin/collections/List"),
|
||||||
mockClassType("org/sample/Foo")
|
mockClassType("org/sample/Foo")
|
||||||
)
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
fun `test class types in Kotlinx package with same name`() {
|
||||||
fun classTypesInKotlinxPackageWithSameName() = doTestSuccess(
|
assertEquals(
|
||||||
expected = mockClassType("kotlinx/cinterop/CPointer"),
|
mockClassType("kotlinx/cinterop/CPointer"), createCommonizer().invoke(
|
||||||
|
listOf(
|
||||||
mockClassType("kotlinx/cinterop/CPointer"),
|
mockClassType("kotlinx/cinterop/CPointer"),
|
||||||
mockClassType("kotlinx/cinterop/CPointer"),
|
mockClassType("kotlinx/cinterop/CPointer"),
|
||||||
mockClassType("kotlinx/cinterop/CPointer")
|
mockClassType("kotlinx/cinterop/CPointer")
|
||||||
)
|
)
|
||||||
|
|
||||||
@Test(expected = IllegalCommonizerStateException::class)
|
|
||||||
fun classTypesInKotlinxPackageWithDifferentNames1() = doTestFailure(
|
|
||||||
mockClassType("kotlinx/cinterop/CPointer"),
|
|
||||||
mockClassType("kotlinx/cinterop/CPointer"),
|
|
||||||
mockClassType("kotlinx/fictitiousPackageName/CPointer")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
@Test(expected = IllegalCommonizerStateException::class)
|
|
||||||
fun classTypesInKotlinxPackageWithDifferentNames2() = doTestFailure(
|
|
||||||
mockClassType("kotlinx/cinterop/CPointer"),
|
|
||||||
mockClassType("kotlinx/cinterop/CPointer"),
|
|
||||||
mockClassType("kotlinx/cinterop/ObjCObject")
|
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalCommonizerStateException::class)
|
fun `test class types in Kotlinx package with different names - 1`() {
|
||||||
fun classTypesInKotlinxPackageWithDifferentNames3() = doTestFailure(
|
assertEquals(
|
||||||
|
null, createCommonizer().invoke(
|
||||||
|
listOf(
|
||||||
mockClassType("kotlinx/cinterop/CPointer"),
|
mockClassType("kotlinx/cinterop/CPointer"),
|
||||||
mockClassType("kotlinx/cinterop/CPointer"),
|
mockClassType("kotlinx/cinterop/CPointer"),
|
||||||
mockClassType("org/sample/Foo")
|
mockClassType("kotlin/fictitiousPackageName/CPointer")
|
||||||
)
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
fun `test class types in user package with same name`() {
|
||||||
fun classTypesInUserPackageWithSameName() = doTestSuccess(
|
assertEquals(
|
||||||
expected = mockClassType("org/sample/Foo"),
|
mockClassType("org/sample/Foo"), createCommonizer().invoke(
|
||||||
|
listOf(
|
||||||
mockClassType("org/sample/Foo"),
|
mockClassType("org/sample/Foo"),
|
||||||
mockClassType("org/sample/Foo"),
|
mockClassType("org/sample/Foo"),
|
||||||
mockClassType("org/sample/Foo")
|
mockClassType("org/sample/Foo")
|
||||||
)
|
)
|
||||||
|
|
||||||
@Test(expected = IllegalCommonizerStateException::class)
|
|
||||||
fun classTypesInUserPackageWithDifferentNames1() = doTestFailure(
|
|
||||||
mockClassType("org/sample/Foo"),
|
|
||||||
mockClassType("org/fictitiousPackageName/Foo"),
|
|
||||||
shouldFailOnFirstVariant = false
|
|
||||||
)
|
)
|
||||||
|
|
||||||
@Test(expected = IllegalCommonizerStateException::class)
|
|
||||||
fun classTypesInUserPackageWithDifferentNames2() = doTestFailure(
|
|
||||||
mockClassType("org/sample/Foo"),
|
|
||||||
mockClassType("org/sample/Bar"),
|
|
||||||
shouldFailOnFirstVariant = false
|
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalCommonizerStateException::class)
|
fun `test class types in user package with different names - 1`() {
|
||||||
fun classTypesInUserPackageWithDifferentNames3() = doTestFailure(
|
assertEquals(
|
||||||
|
null, createCommonizer().invoke(
|
||||||
|
listOf(
|
||||||
mockClassType("org/sample/Foo"),
|
mockClassType("org/sample/Foo"),
|
||||||
mockClassType("kotlin/String"),
|
mockClassType("org/fictitiousPackageName/Foo")
|
||||||
shouldFailOnFirstVariant = false
|
|
||||||
)
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
fun `test class types in user package with different names - 2`() {
|
||||||
fun classTypesInKotlinPackageWithSameNullability1() = doTestSuccess(
|
assertEquals(
|
||||||
expected = mockClassType("kotlin/collections/List", nullable = false),
|
null, createCommonizer().invoke(
|
||||||
|
listOf(
|
||||||
|
mockClassType("org/sample/Foo"),
|
||||||
|
mockClassType("org/sample/Bar")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun `test class types in user package with different names - 3`() {
|
||||||
|
assertEquals(
|
||||||
|
null, createCommonizer().invoke(
|
||||||
|
listOf(
|
||||||
|
mockClassType("org/sample/Foo"),
|
||||||
|
mockClassType("kotlin/String")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun `test class types in Kotlin package with same nullability - 1`() {
|
||||||
|
assertEquals(
|
||||||
|
mockClassType("kotlin/collections/List", nullable = false), createCommonizer().invoke(
|
||||||
|
listOf(
|
||||||
mockClassType("kotlin/collections/List", nullable = false),
|
mockClassType("kotlin/collections/List", nullable = false),
|
||||||
mockClassType("kotlin/collections/List", nullable = false),
|
mockClassType("kotlin/collections/List", nullable = false),
|
||||||
mockClassType("kotlin/collections/List", nullable = false)
|
mockClassType("kotlin/collections/List", nullable = false)
|
||||||
)
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
fun `test class types in Kotlin package with same nullability - 2`() {
|
||||||
fun classTypesInKotlinPackageWithSameNullability2() = doTestSuccess(
|
assertEquals(
|
||||||
expected = mockClassType("kotlin/collections/List", nullable = true),
|
mockClassType("kotlin/collections/List", nullable = true), createCommonizer().invoke(
|
||||||
|
listOf(
|
||||||
mockClassType("kotlin/collections/List", nullable = true),
|
mockClassType("kotlin/collections/List", nullable = true),
|
||||||
mockClassType("kotlin/collections/List", nullable = true),
|
mockClassType("kotlin/collections/List", nullable = true),
|
||||||
mockClassType("kotlin/collections/List", nullable = true)
|
mockClassType("kotlin/collections/List", nullable = true)
|
||||||
)
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalCommonizerStateException::class)
|
fun `test class types in Kotlin package with different nullability - 1`() {
|
||||||
fun classTypesInKotlinPackageWithDifferentNullability1() = doTestFailure(
|
assertEquals(
|
||||||
|
null, createCommonizer().invoke(
|
||||||
|
listOf(
|
||||||
mockClassType("kotlin/collections/List", nullable = false),
|
mockClassType("kotlin/collections/List", nullable = false),
|
||||||
mockClassType("kotlin/collections/List", nullable = false),
|
mockClassType("kotlin/collections/List", nullable = false),
|
||||||
mockClassType("kotlin/collections/List", nullable = true)
|
mockClassType("kotlin/collections/List", nullable = true)
|
||||||
)
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalCommonizerStateException::class)
|
fun `test class types in Kotlin package with different nullability - 2`() {
|
||||||
fun classTypesInKotlinPackageWithDifferentNullability2() = doTestFailure(
|
assertEquals(
|
||||||
|
null, createCommonizer().invoke(
|
||||||
|
listOf(
|
||||||
mockClassType("kotlin/collections/List", nullable = true),
|
mockClassType("kotlin/collections/List", nullable = true),
|
||||||
mockClassType("kotlin/collections/List", nullable = true),
|
mockClassType("kotlin/collections/List", nullable = true),
|
||||||
mockClassType("kotlin/collections/List", nullable = false)
|
mockClassType("kotlin/collections/List", nullable = false)
|
||||||
)
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
fun `test class types in user package with same nullability - 1`() {
|
||||||
fun classTypesInUserPackageWithSameNullability1() = doTestSuccess(
|
assertEquals(
|
||||||
expected = mockClassType("org/sample/Foo", nullable = false),
|
mockClassType("org/sample/Foo", nullable = false), createCommonizer().invoke(
|
||||||
|
listOf(
|
||||||
mockClassType("org/sample/Foo", nullable = false),
|
mockClassType("org/sample/Foo", nullable = false),
|
||||||
mockClassType("org/sample/Foo", nullable = false),
|
mockClassType("org/sample/Foo", nullable = false),
|
||||||
mockClassType("org/sample/Foo", nullable = false)
|
mockClassType("org/sample/Foo", nullable = false)
|
||||||
)
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
fun `test class types in user package with same nullability - 2`() {
|
||||||
fun classTypesInUserPackageWithSameNullability2() = doTestSuccess(
|
assertEquals(
|
||||||
expected = mockClassType("org/sample/Foo", nullable = true),
|
mockClassType("org/sample/Foo", nullable = true), createCommonizer().invoke(
|
||||||
|
listOf(
|
||||||
mockClassType("org/sample/Foo", nullable = true),
|
mockClassType("org/sample/Foo", nullable = true),
|
||||||
mockClassType("org/sample/Foo", nullable = true),
|
mockClassType("org/sample/Foo", nullable = true),
|
||||||
mockClassType("org/sample/Foo", nullable = true)
|
mockClassType("org/sample/Foo", nullable = true)
|
||||||
)
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalCommonizerStateException::class)
|
fun `test class types in user package with different nullability - 1`() {
|
||||||
fun classTypesInUserPackageWithDifferentNullability1() = doTestFailure(
|
assertEquals(
|
||||||
|
null, createCommonizer().invoke(
|
||||||
|
listOf(
|
||||||
mockClassType("org/sample/Foo", nullable = false),
|
mockClassType("org/sample/Foo", nullable = false),
|
||||||
mockClassType("org/sample/Foo", nullable = false),
|
mockClassType("org/sample/Foo", nullable = false),
|
||||||
mockClassType("org/sample/Foo", nullable = true)
|
mockClassType("org/sample/Foo", nullable = true)
|
||||||
)
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalCommonizerStateException::class)
|
fun `test class types in user package with different nullability - 2`() {
|
||||||
fun classTypesInUserPackageWithDifferentNullability2() = doTestFailure(
|
assertEquals(
|
||||||
|
null, createCommonizer().invoke(
|
||||||
|
listOf(
|
||||||
mockClassType("org/sample/Foo", nullable = true),
|
mockClassType("org/sample/Foo", nullable = true),
|
||||||
mockClassType("org/sample/Foo", nullable = true),
|
mockClassType("org/sample/Foo", nullable = true),
|
||||||
mockClassType("org/sample/Foo", nullable = false)
|
mockClassType("org/sample/Foo", nullable = false)
|
||||||
)
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
fun `test ta types in Kotlin package with same name and class`() {
|
||||||
// why success: matching FQNs from the standard Kotlin packages
|
val commonizer = createCommonizer(
|
||||||
fun taTypesInKotlinPackageWithSameNameAndClass() = doTestSuccess(
|
commonDependencySources = {
|
||||||
expected = mockTAType("kotlin/sequences/SequenceBuilder") { mockClassType("kotlin/sequences/SequenceScope") },
|
source(
|
||||||
|
"""
|
||||||
|
package kotlin.sequences
|
||||||
|
class SequenceScope
|
||||||
|
typealias SequenceBuilder = SequenceScope
|
||||||
|
""".trimIndent(), "sequences.kt"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
assertEquals(mockTAType("kotlin/sequences/SequenceBuilder") { mockClassType("kotlin/sequences/SequenceScope") }, commonizer(
|
||||||
|
listOf(
|
||||||
mockTAType("kotlin/sequences/SequenceBuilder") { mockClassType("kotlin/sequences/SequenceScope") },
|
mockTAType("kotlin/sequences/SequenceBuilder") { mockClassType("kotlin/sequences/SequenceScope") },
|
||||||
mockTAType("kotlin/sequences/SequenceBuilder") { mockClassType("kotlin/sequences/SequenceScope") },
|
mockTAType("kotlin/sequences/SequenceBuilder") { mockClassType("kotlin/sequences/SequenceScope") },
|
||||||
mockTAType("kotlin/sequences/SequenceBuilder") { mockClassType("kotlin/sequences/SequenceScope") }
|
mockTAType("kotlin/sequences/SequenceBuilder") { mockClassType("kotlin/sequences/SequenceScope") }
|
||||||
)
|
)))
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
fun `test ta types in Kotlin package with different names`() {
|
||||||
fun taTypesInKotlinPackageWithDifferentNames() = doTestSuccess(
|
val commonizer = createCommonizer(
|
||||||
expected = mockClassType("kotlin/sequences/SequenceScope"),
|
commonDependencySources = {
|
||||||
|
source(
|
||||||
|
"""
|
||||||
|
package kotlin.sequences
|
||||||
|
class SequenceScope
|
||||||
|
typealias SequenceBuilder = SequenceScope
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
},
|
||||||
|
|
||||||
|
targetCDependencySources = {
|
||||||
|
source(
|
||||||
|
"""
|
||||||
|
package kotlin.sequences
|
||||||
|
class SequenceScope
|
||||||
|
typealias FictitiousTypeAlias = SequenceScope
|
||||||
|
""".trimIndent(), "fictitious.kt"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
mockTAType("kotlin/sequences/SequenceBuilder") { mockClassType("kotlin/sequences/SequenceScope") }, commonizer(
|
||||||
|
listOf(
|
||||||
mockTAType("kotlin/sequences/SequenceBuilder") { mockClassType("kotlin/sequences/SequenceScope") },
|
mockTAType("kotlin/sequences/SequenceBuilder") { mockClassType("kotlin/sequences/SequenceScope") },
|
||||||
mockTAType("kotlin/sequences/SequenceBuilder") { mockClassType("kotlin/sequences/SequenceScope") },
|
mockTAType("kotlin/sequences/SequenceBuilder") { mockClassType("kotlin/sequences/SequenceScope") },
|
||||||
mockTAType("kotlin/sequences/FictitiousTypeAlias") { mockClassType("kotlin/sequences/SequenceScope") }
|
mockTAType("kotlin/sequences/FictitiousTypeAlias") { mockClassType("kotlin/sequences/SequenceScope") }
|
||||||
)
|
)))
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
fun `test ta types in Kotlin package with different classes`() {
|
||||||
// why success: matching FQNs from the standard Kotlin packages
|
val commonizer = createCommonizer(
|
||||||
fun taTypesInKotlinPackageWithDifferentClasses() = doTestSuccess(
|
targetADependencySources = {
|
||||||
expected = mockTAType("kotlin/sequences/SequenceBuilder") { mockClassType("kotlin/sequences/SequenceScope") },
|
source(
|
||||||
|
"""
|
||||||
|
package kotlin.sequences
|
||||||
|
class SequenceScope
|
||||||
|
typealias SequenceBuilder = SequenceScope
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
},
|
||||||
|
targetBDependencySources = {
|
||||||
|
source(
|
||||||
|
"""
|
||||||
|
package kotlin.sequences
|
||||||
|
class SequenceScope
|
||||||
|
typealias SequenceBuilder = SequenceScope
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
},
|
||||||
|
targetCDependencySources = {
|
||||||
|
source(
|
||||||
|
"""
|
||||||
|
package kotlin.sequences
|
||||||
|
class FictitiousClass
|
||||||
|
typealias SequenceBuilder = FictitiousClass
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
assertEquals(null, commonizer(
|
||||||
|
listOf(
|
||||||
mockTAType("kotlin/sequences/SequenceBuilder") { mockClassType("kotlin/sequences/SequenceScope") },
|
mockTAType("kotlin/sequences/SequenceBuilder") { mockClassType("kotlin/sequences/SequenceScope") },
|
||||||
mockTAType("kotlin/sequences/SequenceBuilder") { mockClassType("kotlin/sequences/SequenceScope") },
|
mockTAType("kotlin/sequences/SequenceBuilder") { mockClassType("kotlin/sequences/SequenceScope") },
|
||||||
mockTAType("kotlin/sequences/SequenceBuilder") { mockClassType("kotlin/sequences/FictitiousClass") }
|
mockTAType("kotlin/sequences/SequenceBuilder") { mockClassType("kotlin/sequences/FictitiousClass") }
|
||||||
)
|
)))
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
fun `test multilevel ta types in Kotlin package with same name and right hand side class`() {
|
||||||
// why success: matching FQNs from the standard Kotlin packages
|
val commonizer = createCommonizer(
|
||||||
fun taTypesInKotlinxPackageWithSameNameAndClass() = doTestSuccess(
|
targetASpecificSources = {
|
||||||
expected = mockTAType("kotlinx/cinterop/CArrayPointer") { mockClassType("kotlinx/cinterop/CPointer") },
|
source(
|
||||||
mockTAType("kotlinx/cinterop/CArrayPointer") { mockClassType("kotlinx/cinterop/CPointer") },
|
"""
|
||||||
mockTAType("kotlinx/cinterop/CArrayPointer") { mockClassType("kotlinx/cinterop/CPointer") },
|
package kotlin
|
||||||
mockTAType("kotlinx/cinterop/CArrayPointer") { mockClassType("kotlinx/cinterop/CPointer") }
|
class FictitiousClass
|
||||||
|
typealias FictitiousTypeAlias = FictitiousClass
|
||||||
|
""".trimIndent()
|
||||||
)
|
)
|
||||||
|
|
||||||
@Test()
|
|
||||||
fun taTypesInKotlinxPackageWithDifferentNames() = doTestSuccess(
|
|
||||||
expected = mockClassType("kotlinx/cinterop/CPointer"),
|
|
||||||
mockTAType("kotlinx/cinterop/CArrayPointer") { mockClassType("kotlinx/cinterop/CPointer") },
|
|
||||||
mockTAType("kotlinx/cinterop/CArrayPointer") { mockClassType("kotlinx/cinterop/CPointer") },
|
|
||||||
mockTAType("kotlinx/cinterop/FictitiousTypeAlias") { mockClassType("kotlinx/cinterop/CPointer") }
|
|
||||||
)
|
|
||||||
|
|
||||||
@Test
|
|
||||||
// why success: matching FQNs from the standard Kotlin packages
|
|
||||||
fun taTypesInKotlinxPackageWithDifferentClasses() = doTestSuccess(
|
|
||||||
expected = mockTAType("kotlinx/cinterop/CArrayPointer") { mockClassType("kotlinx/cinterop/CPointer") },
|
|
||||||
mockTAType("kotlinx/cinterop/CArrayPointer") { mockClassType("kotlinx/cinterop/CPointer") },
|
|
||||||
mockTAType("kotlinx/cinterop/CArrayPointer") { mockClassType("kotlinx/cinterop/CPointer") },
|
|
||||||
mockTAType("kotlinx/cinterop/CArrayPointer") { mockClassType("kotlinx/cinterop/FictitiousClass") }
|
|
||||||
)
|
|
||||||
|
|
||||||
@Test
|
|
||||||
// why success: matching FQNs from the standard Kotlin packages
|
|
||||||
fun multilevelTATypesInKotlinPackageWithSameNameAndRightHandSideClass() = doTestSuccess(
|
|
||||||
expected = mockTAType("kotlin/FictitiousTypeAlias") {
|
|
||||||
mockClassType("kotlin/FictitiousClass")
|
|
||||||
},
|
},
|
||||||
|
targetBSpecificSources = {
|
||||||
|
source(
|
||||||
|
"""
|
||||||
|
package kotlin
|
||||||
|
class FictitiousClass
|
||||||
|
typealias FictitiousTypeAliasL2 = FictitiousClass
|
||||||
|
typealias FictitiousTypeAlias = FictitiousTypeAliasL2
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
},
|
||||||
|
targetCSpecificSources = {
|
||||||
|
source(
|
||||||
|
"""
|
||||||
|
package kotlin
|
||||||
|
class FictitiousClass
|
||||||
|
typealias FictitiousTypeAliasL2 = FictitiousClass
|
||||||
|
typealias FictitiousTypeAliasL3 = FictitiousTypeAliasL2
|
||||||
|
typealias FictitiousTypeAlias = FictitiousTypeAliasL3
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
assertEquals(mockTAType("kotlin/FictitiousTypeAlias") {
|
||||||
|
mockClassType("kotlin/FictitiousClass")
|
||||||
|
}, commonizer(listOf(
|
||||||
|
|
||||||
mockTAType("kotlin/FictitiousTypeAlias") {
|
mockTAType("kotlin/FictitiousTypeAlias") {
|
||||||
mockClassType("kotlin/FictitiousClass")
|
mockClassType("kotlin/FictitiousClass")
|
||||||
@@ -260,64 +471,86 @@ class TypeCommonizerTest : AbstractCommonizerTest<CirType, CirType?>() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)))
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
fun `test multilevel ta types in user package with same name and right hand side class - 1`() {
|
||||||
// why success: lifting up
|
val commonizer = createCommonizer(
|
||||||
fun taTypesInUserPackageWithSameNameAndClass() = doTestSuccess(
|
targetASpecificSources = {
|
||||||
expected = mockTAType("org/sample/FooAlias") { mockClassType("org/sample/Foo") },
|
source(
|
||||||
mockTAType("org/sample/FooAlias") { mockClassType("org/sample/Foo") },
|
"""
|
||||||
mockTAType("org/sample/FooAlias") { mockClassType("org/sample/Foo") },
|
package org.sample
|
||||||
mockTAType("org/sample/FooAlias") { mockClassType("org/sample/Foo") }
|
class F
|
||||||
|
typealias FAlias = F
|
||||||
|
""".trimIndent()
|
||||||
)
|
)
|
||||||
|
|
||||||
@Test
|
|
||||||
fun taTypesInUserPackageWithDifferentNames() = doTestSuccess(
|
|
||||||
expected = mockClassType("org/sample/Foo"),
|
|
||||||
mockTAType("org/sample/FooAlias") { mockClassType("org/sample/Foo") },
|
|
||||||
mockTAType("org/sample/BarAlias") { mockClassType("org/sample/Foo") },
|
|
||||||
)
|
|
||||||
|
|
||||||
@Test
|
|
||||||
// why success: short-circuiting & lifting up
|
|
||||||
fun multilevelTATypesInUserPackageWithSameNameAndRightHandSideClass1() = doTestSuccess(
|
|
||||||
expected = mockTAType("org/sample/FooAlias") {
|
|
||||||
mockClassType("org/sample/Foo")
|
|
||||||
},
|
},
|
||||||
|
targetBSpecificSources = {
|
||||||
mockTAType("org/sample/FooAlias") {
|
source(
|
||||||
mockClassType("org/sample/Foo")
|
"""
|
||||||
|
package org.sample
|
||||||
|
class F
|
||||||
|
typealias FAlias = F
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
},
|
},
|
||||||
|
targetCSpecificSources = {
|
||||||
|
source(
|
||||||
|
"""
|
||||||
|
package org.sample
|
||||||
|
class F
|
||||||
|
typealias FAliasL2 = F
|
||||||
|
typealias FAlias = FAliasL2
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
mockTAType("org/sample/FAlias") {
|
||||||
|
mockClassType("org/sample/F")
|
||||||
|
}, commonizer(
|
||||||
|
listOf(
|
||||||
|
mockTAType("org/sample/FAlias") {
|
||||||
|
mockClassType("org/sample/F")
|
||||||
|
},
|
||||||
|
mockTAType("org/sample/FAlias") {
|
||||||
|
mockClassType("org/sample/F")
|
||||||
|
},
|
||||||
|
mockTAType("org/sample/FAlias") {
|
||||||
|
mockTAType("org/sample/FAliasL2") {
|
||||||
|
mockClassType("org/sample/F")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun `test multilevel ta types in user package with same name and right hand side class - 3`() {
|
||||||
|
val commonizer = createCommonizer(
|
||||||
|
commonTargetSources = {
|
||||||
|
source(
|
||||||
|
"""
|
||||||
|
package org.sample
|
||||||
|
class Foo
|
||||||
|
typealias FooAliasL2 = Foo
|
||||||
|
typealias FooAlias = FooAliasL2
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
mockTAType("org/sample/FooAlias") {
|
mockTAType("org/sample/FooAlias") {
|
||||||
mockTAType("org/sample/FooAliasL2") {
|
mockTAType("org/sample/FooAliasL2") {
|
||||||
mockClassType("org/sample/Foo")
|
mockClassType("org/sample/Foo")
|
||||||
}
|
}
|
||||||
}
|
}, commonizer(
|
||||||
)
|
listOf(
|
||||||
|
|
||||||
@Test
|
|
||||||
// why success: short-circuiting & lifting up
|
|
||||||
fun multilevelTATypesInUserPackageWithSameNameAndRightHandSideClass2() = doTestSuccess(
|
|
||||||
expected = mockTAType("org/sample/FooAlias") {
|
|
||||||
mockClassType("org/sample/Foo")
|
|
||||||
},
|
|
||||||
|
|
||||||
mockTAType("org/sample/FooAlias") {
|
mockTAType("org/sample/FooAlias") {
|
||||||
mockTAType("org/sample/FooAliasL2") {
|
mockTAType("org/sample/FooAliasL2") {
|
||||||
mockClassType("org/sample/Foo")
|
mockClassType("org/sample/Foo")
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
mockTAType("org/sample/FooAlias") {
|
mockTAType("org/sample/FooAlias") {
|
||||||
mockClassType("org/sample/Foo")
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
@Test
|
|
||||||
// why success: lifting up (inner and outer TAs)
|
|
||||||
fun multilevelTATypesInUserPackageWithSameNameAndRightHandSideClass3() = doTestSuccess(
|
|
||||||
expected = mockTAType("org/sample/FooAlias") {
|
|
||||||
mockTAType("org/sample/FooAliasL2") {
|
mockTAType("org/sample/FooAliasL2") {
|
||||||
mockClassType("org/sample/Foo")
|
mockClassType("org/sample/Foo")
|
||||||
}
|
}
|
||||||
@@ -327,176 +560,71 @@ class TypeCommonizerTest : AbstractCommonizerTest<CirType, CirType?>() {
|
|||||||
mockTAType("org/sample/FooAliasL2") {
|
mockTAType("org/sample/FooAliasL2") {
|
||||||
mockClassType("org/sample/Foo")
|
mockClassType("org/sample/Foo")
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun `test ta types in Kotlin package with different nullability`() {
|
||||||
|
val commonizer = createCommonizer(
|
||||||
|
targetADependencySources = {
|
||||||
|
source(
|
||||||
|
"""
|
||||||
|
package kotlin.sequences
|
||||||
|
class SequenceScope
|
||||||
|
typealias SequenceBuilder = SequenceScope
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
},
|
},
|
||||||
|
targetBDependencySources = {
|
||||||
mockTAType("org/sample/FooAlias") {
|
source(
|
||||||
mockTAType("org/sample/FooAliasL2") {
|
"""
|
||||||
mockClassType("org/sample/Foo")
|
package kotlin.sequences
|
||||||
}
|
class SequenceScope
|
||||||
|
typealias SequenceBuilder = SequenceScope
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
},
|
||||||
|
targetCDependencySources = {
|
||||||
|
source(
|
||||||
|
"""
|
||||||
|
package kotlin.sequences
|
||||||
|
class SequenceScope
|
||||||
|
typealias SequenceBuilder = SequenceScope?
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
assertEquals(null, commonizer(listOf(
|
||||||
@Test
|
|
||||||
// why success: types with the same nullability are treated as equal
|
|
||||||
fun taTypesInKotlinPackageWithSameNullability1() = doTestSuccess(
|
|
||||||
expected = mockTAType("kotlin/sequences/SequenceBuilder", nullable = false) { mockClassType("kotlin/sequences/SequenceScope") },
|
|
||||||
mockTAType("kotlin/sequences/SequenceBuilder", nullable = false) { mockClassType("kotlin/sequences/SequenceScope") },
|
|
||||||
mockTAType("kotlin/sequences/SequenceBuilder", nullable = false) { mockClassType("kotlin/sequences/SequenceScope") },
|
|
||||||
mockTAType("kotlin/sequences/SequenceBuilder", nullable = false) { mockClassType("kotlin/sequences/SequenceScope") }
|
|
||||||
)
|
|
||||||
|
|
||||||
@Test
|
|
||||||
// why success: types with the same nullability are treated as equal
|
|
||||||
fun taTypesInKotlinPackageWithSameNullability2() = doTestSuccess(
|
|
||||||
expected = mockTAType("kotlin/sequences/SequenceBuilder", nullable = true) { mockClassType("kotlin/sequences/SequenceScope") },
|
|
||||||
mockTAType("kotlin/sequences/SequenceBuilder", nullable = true) { mockClassType("kotlin/sequences/SequenceScope") },
|
|
||||||
mockTAType("kotlin/sequences/SequenceBuilder", nullable = true) { mockClassType("kotlin/sequences/SequenceScope") },
|
|
||||||
mockTAType("kotlin/sequences/SequenceBuilder", nullable = true) { mockClassType("kotlin/sequences/SequenceScope") }
|
|
||||||
)
|
|
||||||
|
|
||||||
@Test(expected = IllegalCommonizerStateException::class)
|
|
||||||
fun taTypesInKotlinPackageWithDifferentNullability1() = doTestFailure(
|
|
||||||
mockTAType("kotlin/sequences/SequenceBuilder", nullable = false) { mockClassType("kotlin/sequences/SequenceScope") },
|
|
||||||
mockTAType("kotlin/sequences/SequenceBuilder", nullable = false) { mockClassType("kotlin/sequences/SequenceScope") },
|
|
||||||
mockTAType("kotlin/sequences/SequenceBuilder", nullable = true) { mockClassType("kotlin/sequences/SequenceScope") }
|
|
||||||
)
|
|
||||||
|
|
||||||
@Test(expected = IllegalCommonizerStateException::class)
|
|
||||||
fun taTypesInKotlinPackageWithDifferentNullability2() = doTestFailure(
|
|
||||||
mockTAType("kotlin/sequences/SequenceBuilder", nullable = true) { mockClassType("kotlin/sequences/SequenceScope") },
|
|
||||||
mockTAType("kotlin/sequences/SequenceBuilder", nullable = true) { mockClassType("kotlin/sequences/SequenceScope") },
|
|
||||||
mockTAType("kotlin/sequences/SequenceBuilder", nullable = false) { mockClassType("kotlin/sequences/SequenceScope") }
|
|
||||||
)
|
|
||||||
|
|
||||||
@Test(expected = IllegalCommonizerStateException::class)
|
|
||||||
// why failure: Different nullability in type-expansion can't be commonized by now
|
|
||||||
fun taTypesInKotlinPackageWithDifferentNullability3() = doTestFailure(
|
|
||||||
mockTAType("kotlin/sequences/SequenceBuilder") { mockClassType("kotlin/sequences/SequenceScope", nullable = false) },
|
mockTAType("kotlin/sequences/SequenceBuilder") { mockClassType("kotlin/sequences/SequenceScope", nullable = false) },
|
||||||
mockTAType("kotlin/sequences/SequenceBuilder") { mockClassType("kotlin/sequences/SequenceScope", nullable = false) },
|
mockTAType("kotlin/sequences/SequenceBuilder") { mockClassType("kotlin/sequences/SequenceScope", nullable = false) },
|
||||||
mockTAType("kotlin/sequences/SequenceBuilder") { mockClassType("kotlin/sequences/SequenceScope", nullable = true) }
|
mockTAType("kotlin/sequences/SequenceBuilder") { mockClassType("kotlin/sequences/SequenceScope", nullable = true) }
|
||||||
)
|
)))
|
||||||
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalCommonizerStateException::class)
|
fun `test ta types in user package with same nullability`() {
|
||||||
// why failure: Different nullability in type-expansion can't be commonized by now
|
val commonizer = createCommonizer(
|
||||||
fun taTypesInKotlinPackageWithDifferentNullability4() = doTestFailure(
|
commonTargetSources = {
|
||||||
mockTAType("kotlin/sequences/SequenceBuilder") { mockClassType("kotlin/sequences/SequenceScope", nullable = true) },
|
source(
|
||||||
mockTAType("kotlin/sequences/SequenceBuilder") { mockClassType("kotlin/sequences/SequenceScope", nullable = true) },
|
"""
|
||||||
mockTAType("kotlin/sequences/SequenceBuilder") { mockClassType("kotlin/sequences/SequenceScope", nullable = false) }
|
package org.sample
|
||||||
|
class Foo
|
||||||
|
typealias FooAlias = Foo?
|
||||||
|
""".trimIndent()
|
||||||
)
|
)
|
||||||
|
}
|
||||||
@Test
|
|
||||||
// why success: types with the same nullability are treated as equal
|
|
||||||
fun taTypesInUserPackageWithSameNullability1() = doTestSuccess(
|
|
||||||
expected = mockTAType("org/sample/FooAlias", nullable = false) { mockClassType("org/sample/Foo") },
|
|
||||||
mockTAType("org/sample/FooAlias", nullable = false) { mockClassType("org/sample/Foo") },
|
|
||||||
mockTAType("org/sample/FooAlias", nullable = false) { mockClassType("org/sample/Foo") },
|
|
||||||
mockTAType("org/sample/FooAlias", nullable = false) { mockClassType("org/sample/Foo") }
|
|
||||||
)
|
)
|
||||||
|
assertEquals(mockTAType("org/sample/FooAlias", nullable = true) { mockClassType("org/sample/Foo") }, commonizer(listOf(
|
||||||
@Test
|
|
||||||
// why success: types with the same nullability are treated as equal
|
|
||||||
fun taTypesInUserPackageWithSameNullability2() = doTestSuccess(
|
|
||||||
expected = mockTAType("org/sample/FooAlias", nullable = true) { mockClassType("org/sample/Foo") },
|
|
||||||
mockTAType("org/sample/FooAlias", nullable = true) { mockClassType("org/sample/Foo") },
|
mockTAType("org/sample/FooAlias", nullable = true) { mockClassType("org/sample/Foo") },
|
||||||
mockTAType("org/sample/FooAlias", nullable = true) { mockClassType("org/sample/Foo") },
|
mockTAType("org/sample/FooAlias", nullable = true) { mockClassType("org/sample/Foo") },
|
||||||
mockTAType("org/sample/FooAlias", nullable = true) { mockClassType("org/sample/Foo") }
|
mockTAType("org/sample/FooAlias", nullable = true) { mockClassType("org/sample/Foo") }
|
||||||
)
|
)))
|
||||||
|
|
||||||
@Test(expected = IllegalCommonizerStateException::class)
|
|
||||||
fun taTypesInUserPackageWithDifferentNullability1() = doTestFailure(
|
|
||||||
mockTAType("org/sample/FooAlias", nullable = false) { mockClassType("org/sample/Foo") },
|
|
||||||
mockTAType("org/sample/FooAlias", nullable = false) { mockClassType("org/sample/Foo") },
|
|
||||||
mockTAType("org/sample/FooAlias", nullable = true) { mockClassType("org/sample/Foo") }
|
|
||||||
)
|
|
||||||
|
|
||||||
@Test(expected = IllegalCommonizerStateException::class)
|
|
||||||
fun taTypesInUserPackageWithDifferentNullability2() = doTestFailure(
|
|
||||||
mockTAType("org/sample/FooAlias", nullable = true) { mockClassType("org/sample/Foo") },
|
|
||||||
mockTAType("org/sample/FooAlias", nullable = true) { mockClassType("org/sample/Foo") },
|
|
||||||
mockTAType("org/sample/FooAlias", nullable = false) { mockClassType("org/sample/Foo") },
|
|
||||||
)
|
|
||||||
|
|
||||||
private fun prepareCache(variants: Array<out CirClassOrTypeAliasType>) {
|
|
||||||
check(variants.isNotEmpty())
|
|
||||||
|
|
||||||
fun recurse(type: CirClassOrTypeAliasType, index: Int) {
|
|
||||||
when (type) {
|
|
||||||
is CirClassType -> {
|
|
||||||
val node = classifiers.classNode(type.classifierId) {
|
|
||||||
buildClassNode(
|
|
||||||
storageManager = LockBasedStorageManager.NO_LOCKS,
|
|
||||||
size = variants.size,
|
|
||||||
classifiers = classifiers,
|
|
||||||
nodeRelationship = null,
|
|
||||||
classId = type.classifierId
|
|
||||||
)
|
|
||||||
}
|
|
||||||
node.targetDeclarations[index] = CirClass.create(
|
|
||||||
annotations = emptyList(),
|
|
||||||
name = type.classifierId.relativeNameSegments.last(),
|
|
||||||
typeParameters = emptyList(),
|
|
||||||
supertypes = emptyList(),
|
|
||||||
visibility = Visibilities.Public,
|
|
||||||
modality = Modality.FINAL,
|
|
||||||
kind = ClassKind.CLASS,
|
|
||||||
companion = null,
|
|
||||||
isCompanion = false,
|
|
||||||
isData = false,
|
|
||||||
isValue = false,
|
|
||||||
isInner = false,
|
|
||||||
isExternal = false
|
|
||||||
)
|
|
||||||
}
|
|
||||||
is CirTypeAliasType -> {
|
|
||||||
val node = classifiers.typeAliasNode(type.classifierId) {
|
|
||||||
buildTypeAliasNode(
|
|
||||||
storageManager = LockBasedStorageManager.NO_LOCKS,
|
|
||||||
size = variants.size,
|
|
||||||
classifiers = classifiers,
|
|
||||||
typeAliasId = type.classifierId
|
|
||||||
)
|
|
||||||
}
|
|
||||||
node.targetDeclarations[index] = CirTypeAlias.create(
|
|
||||||
annotations = emptyList(),
|
|
||||||
name = type.classifierId.relativeNameSegments.last(),
|
|
||||||
typeParameters = emptyList(),
|
|
||||||
visibility = Visibilities.Public,
|
|
||||||
underlyingType = type.underlyingType,
|
|
||||||
expandedType = computeExpandedType(type.underlyingType)
|
|
||||||
)
|
|
||||||
|
|
||||||
recurse(type.underlyingType, index) // expand underlying types recursively
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
variants.forEachIndexed { index, type ->
|
|
||||||
recurse(type, index)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun doTestSuccess(expected: CirClassOrTypeAliasType, vararg variants: CirClassOrTypeAliasType) {
|
|
||||||
prepareCache(variants)
|
|
||||||
super.doTestSuccess(expected, *variants)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun doTestFailure(vararg variants: CirClassOrTypeAliasType, shouldFailOnFirstVariant: Boolean = false) {
|
|
||||||
prepareCache(variants)
|
|
||||||
super.doTestFailure(*variants, shouldFailOnFirstVariant = shouldFailOnFirstVariant)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun createCommonizer() = TypeCommonizer(classifiers).asCommonizer()
|
|
||||||
|
|
||||||
override fun areEqual(a: CirType?, b: CirType?) = (a === b) || (a != null && b != null && areEqual(classifiers, a, b))
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun areEqual(classifiers: CirKnownClassifiers, a: CirType, b: CirType): Boolean =
|
fun areEqual(classifiers: CirKnownClassifiers, a: CirType, b: CirType): Boolean =
|
||||||
TypeCommonizer(classifiers).asCommonizer().run { commonizeWith(a) && commonizeWith(b) }
|
TypeCommonizer(classifiers).invoke(listOf(a, b)) != null
|
||||||
|
|
||||||
private fun CirKnownClassifiers.classNode(classId: CirEntityId, computation: () -> CirClassNode) =
|
|
||||||
commonizedNodes.classNode(classId) ?: computation()
|
|
||||||
|
|
||||||
private fun CirKnownClassifiers.typeAliasNode(typeAliasId: CirEntityId, computation: () -> CirTypeAliasNode) =
|
|
||||||
commonizedNodes.typeAliasNode(typeAliasId) ?: computation()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -114,3 +114,12 @@ fun InlineSourceBuilder.createCirProvidedClassifiers(module: InlineSourceBuilder
|
|||||||
return CirProvidedClassifiersByModules.load(modulesProvider)
|
return CirProvidedClassifiersByModules.load(modulesProvider)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@InlineSourceBuilder.ModuleBuilderDsl
|
||||||
|
fun InlineSourceBuilder.createCirProvidedClassifiers(builder: InlineSourceBuilder.ModuleBuilder.() -> Unit): CirProvidedClassifiers {
|
||||||
|
return createCirProvidedClassifiers(createModule { builder() })
|
||||||
|
}
|
||||||
|
|
||||||
|
@InlineSourceBuilder.ModuleBuilderDsl
|
||||||
|
fun InlineSourceBuilder.createCirProvidedClassifiersFromSourceCode(@Language("kotlin") sourceCode: String): CirProvidedClassifiers {
|
||||||
|
return createCirProvidedClassifiers(createModule { source(sourceCode) })
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user