[Commonizer] Implement CirUnderscoredTypeAliasSubstitutor

Try substituting TypeAlias types that start with `__` in favour
of TypeAlias without the underscored prefix

^KT-48287 Verification Pending
^KT-48286 Verification Pending
This commit is contained in:
sebastian.sellmair
2021-08-17 17:24:47 +02:00
committed by Space
parent 7d3830ba7d
commit 8aceff3641
4 changed files with 202 additions and 8 deletions

View File

@@ -14,6 +14,8 @@ import org.jetbrains.kotlin.commonizer.mergedtree.CirKnownClassifiers
import org.jetbrains.kotlin.commonizer.mergedtree.CirNode.Companion.indexOfCommon
import org.jetbrains.kotlin.commonizer.mergedtree.CirRootNode
import org.jetbrains.kotlin.commonizer.metadata.CirTreeSerializer
import org.jetbrains.kotlin.commonizer.transformer.CirAliasTypeSubstitutor
import org.jetbrains.kotlin.commonizer.transformer.CirUnderscoredTypeAliasSubstitutor
import org.jetbrains.kotlin.commonizer.transformer.InlineTypeAliasCirNodeTransformer
import org.jetbrains.kotlin.commonizer.transformer.TypeSubstitutionCirNodeTransformer
import org.jetbrains.kotlin.commonizer.tree.CirTreeRoot
@@ -62,7 +64,16 @@ internal fun commonizeTarget(
val mergedTree = mergeCirTree(parameters.storageManager, classifiers, availableTrees)
InlineTypeAliasCirNodeTransformer(parameters.storageManager, classifiers).invoke(mergedTree)
TypeSubstitutionCirNodeTransformer(parameters.storageManager, classifiers).invoke(mergedTree)
TypeSubstitutionCirNodeTransformer(
parameters.storageManager, classifiers,
CirAliasTypeSubstitutor(classifiers.commonDependencies, classifiers.classifierIndices)
).invoke(mergedTree)
TypeSubstitutionCirNodeTransformer(
parameters.storageManager, classifiers,
CirUnderscoredTypeAliasSubstitutor(classifiers.classifierIndices)
).invoke(mergedTree)
mergedTree.accept(CommonizationVisitor(classifiers, mergedTree), Unit)

View File

@@ -0,0 +1,63 @@
/*
* 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.transformer
import org.jetbrains.kotlin.commonizer.TargetDependent
import org.jetbrains.kotlin.commonizer.cir.CirEntityId
import org.jetbrains.kotlin.commonizer.cir.CirName
import org.jetbrains.kotlin.commonizer.cir.CirType
import org.jetbrains.kotlin.commonizer.cir.CirTypeAliasType
import org.jetbrains.kotlin.commonizer.core.expandedType
import org.jetbrains.kotlin.commonizer.mergedtree.CirClassifierIndex
import org.jetbrains.kotlin.commonizer.mergedtree.CirTypeSubstitutor
import org.jetbrains.kotlin.commonizer.mergedtree.findTypeAlias
/**
* Explicitly substitute [CirTypeAliasType]s whose classifier name is prefixed with a double underscore: "__"
* with a type using a classifier without the prefix if
* 1) Such a TypeAlias exists on the platform
* 2) Such a TypeAlias expands to the same type
*
* Example from platform.posix.mkdir:
* This function uses the following parameter:
* linux: `platform/posix/__mode_t -> kotlin/UInt`
* apple: `platform/posix/mode_t -> platform/posix/__darwin_mode_t -> platform/posix/__uint16_t -> kotlin/UShort`
*
* However, on linux a corresponding type alias
* `platform/posix/mode_t -> platform/posix/__mode_t -> kotlin/UInt`
* exists which is preferable
*/
internal class CirUnderscoredTypeAliasSubstitutor(
private val classifierIndices: TargetDependent<CirClassifierIndex>
) : CirTypeSubstitutor {
override fun substitute(targetIndex: Int, type: CirType): CirType {
if (type !is CirTypeAliasType) return type
/* TypeAliases cannot be nested and therefore are expected to have only a single name segment */
val name = type.classifierId.relativeNameSegments.singleOrNull() ?: return type
if (!name.name.startsWith("__")) return type
/* Argument substitution not implemented. No real world cases known that would benefit */
if (type.arguments.isNotEmpty()) return type
val preferredClassifierId = CirEntityId.create(
type.classifierId.packageName,
CirName.create(name.name.removePrefix("__"))
)
val preferredTypeAlias = classifierIndices[targetIndex].findTypeAlias(preferredClassifierId) ?: return type
val expandedType = type.expandedType()
if (preferredTypeAlias.expandedType != expandedType) return type
return CirTypeAliasType.createInterned(
typeAliasId = preferredClassifierId,
underlyingType = preferredTypeAlias.underlyingType,
arguments = emptyList(),
isMarkedNullable = expandedType.isMarkedNullable
)
}
}

View File

@@ -7,7 +7,6 @@ package org.jetbrains.kotlin.commonizer.transformer
import org.jetbrains.kotlin.commonizer.mergedtree.*
import org.jetbrains.kotlin.commonizer.mergedtree.CirNodeRelationship.ParentNode
import org.jetbrains.kotlin.commonizer.tree.CirTreeRoot
import org.jetbrains.kotlin.storage.StorageManager
internal class TypeSubstitutionCirNodeTransformer(
@@ -16,12 +15,6 @@ internal class TypeSubstitutionCirNodeTransformer(
private val typeSubstitutor: CirTypeSubstitutor
) : CirNodeTransformer {
constructor(storageManager: StorageManager, classifiers: CirKnownClassifiers) : this(
storageManager = storageManager,
classifiers = classifiers,
typeSubstitutor = CirAliasTypeSubstitutor(classifiers.commonDependencies, classifiers.classifierIndices)
)
override fun invoke(root: CirRootNode) {
for (index in 0 until root.targetDeclarations.size) {
root.modules.forEach { (_, module) -> this(module, index) }

View File

@@ -0,0 +1,127 @@
/*
* 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.transformer
import org.jetbrains.kotlin.commonizer.AbstractInlineSourcesCommonizationTest
import org.jetbrains.kotlin.commonizer.assertCommonized
class CirUnderscoredTypeAliasSubstitutorTest : AbstractInlineSourcesCommonizationTest() {
fun `test inlined underscored typealias - single platform`() {
val result = commonize {
outputTarget("(a, b)")
simpleSingleSourceTarget(
"a", """
typealias X = Int
typealias __X = X
fun x(x: __X)
""".trimIndent()
)
simpleSingleSourceTarget(
"b", """
typealias X = Int
fun x(x: X)
""".trimIndent()
)
}
result.assertCommonized(
"(a, b)", """
typealias X = Int
expect fun x(x: X)
""".trimIndent()
)
}
fun `test inlined underscored typealias - both platforms`() {
val result = commonize {
outputTarget("(a, b)")
simpleSingleSourceTarget(
"a", """
typealias X = Int
typealias __X = X
fun x(x: __X)
""".trimIndent()
)
simpleSingleSourceTarget(
"b", """
typealias X = Int
typealias __X = X
fun x(x: X)
""".trimIndent()
)
}
result.assertCommonized(
"(a, b)", """
typealias X = Int
typealias __X = X
expect fun x(x: X)
""".trimIndent()
)
}
fun `test inlined underscored typealias - both platforms - not used in signature`() {
val result = commonize {
outputTarget("(a, b)")
simpleSingleSourceTarget(
"a", """
typealias X = Int
typealias __X = X
fun x(x: X)
""".trimIndent()
)
simpleSingleSourceTarget(
"b", """
typealias X = Int
typealias __X = X
fun x(x: X)
""".trimIndent()
)
}
result.assertCommonized(
"(a, b)", """
typealias X = Int
typealias __X = X
expect fun x(x: X)
""".trimIndent()
)
}
fun `test inlined underscored typealias - both platforms - underscore used in both signatures`() {
val result = commonize {
outputTarget("(a, b)")
simpleSingleSourceTarget(
"a", """
typealias X = Int
typealias __X = X
fun x(x: __X)
""".trimIndent()
)
simpleSingleSourceTarget(
"b", """
typealias X = Int
typealias __X = X
fun x(x: __X)
""".trimIndent()
)
}
result.assertCommonized(
"(a, b)", """
typealias X = Int
typealias __X = X
expect fun x(x: __X)
""".trimIndent()
)
}
}