mirror of
https://github.com/jlengrand/kotlin.git
synced 2026-03-10 08:31:29 +00:00
[Commonizer] Re-introduce node builders 'parentCommonDeclaration' context
This commit is contained in:
@@ -19,7 +19,7 @@ internal object ClassConstructorMerger {
|
||||
) = with(context) {
|
||||
val approximationKey = ConstructorApproximationKey(constructor, context.typeResolver)
|
||||
val constructorNode: CirClassConstructorNode = classNode.constructors.getOrPut(approximationKey) {
|
||||
buildClassConstructorNode(storageManager, targets, classifiers)
|
||||
buildClassConstructorNode(storageManager, targets, classifiers, classNode.commonDeclaration)
|
||||
}
|
||||
constructorNode.targetDeclarations[context.targetIndex] = CirDeserializers.constructor(
|
||||
source = constructor,
|
||||
|
||||
@@ -26,8 +26,9 @@ internal class ClassMerger(
|
||||
val classId = classEntry.classId
|
||||
val className = classId.relativeNameSegments.last()
|
||||
|
||||
val maybeClassOwnerNode: CirClassNode? = ownerNode as? CirClassNode
|
||||
val classNode: CirClassNode = ownerNode.classes.getOrPut(className) {
|
||||
buildClassNode(storageManager, targets, classifiers, classId)
|
||||
buildClassNode(storageManager, targets, classifiers, maybeClassOwnerNode?.commonDeclaration, classId)
|
||||
}
|
||||
|
||||
val clazz: KmClass?
|
||||
|
||||
@@ -27,14 +27,16 @@ internal object FunctionMerger {
|
||||
return
|
||||
}
|
||||
|
||||
val maybeClassOwnerNode: CirClassNode? = ownerNode as? CirClassNode
|
||||
|
||||
val approximationKey = FunctionApproximationKey(function, context.typeResolver)
|
||||
val functionNode: CirFunctionNode = ownerNode.functions.getOrPut(approximationKey) {
|
||||
buildFunctionNode(storageManager, targets, classifiers)
|
||||
buildFunctionNode(storageManager, targets, classifiers, maybeClassOwnerNode?.commonDeclaration)
|
||||
}
|
||||
functionNode.targetDeclarations[context.targetIndex] = CirDeserializers.function(
|
||||
name = approximationKey.name,
|
||||
source = function,
|
||||
containingClass = ownerNode.run { this as? CirClassNode }?.targetDeclarations?.get(context.targetIndex),
|
||||
containingClass = maybeClassOwnerNode?.targetDeclarations?.get(context.targetIndex),
|
||||
typeResolver = context.typeResolver
|
||||
)
|
||||
}
|
||||
|
||||
@@ -21,14 +21,16 @@ internal object PropertyMerger {
|
||||
if (property.isFakeOverride())
|
||||
return
|
||||
|
||||
val maybeClassOwnerNode: CirClassNode? = ownerNode as? CirClassNode
|
||||
|
||||
val approximationKey = PropertyApproximationKey(property, context.typeResolver)
|
||||
val propertyNode: CirPropertyNode = ownerNode.properties.getOrPut(approximationKey) {
|
||||
buildPropertyNode(storageManager, targets, classifiers)
|
||||
buildPropertyNode(storageManager, targets, classifiers, maybeClassOwnerNode?.commonDeclaration)
|
||||
}
|
||||
propertyNode.targetDeclarations[context.targetIndex] = CirDeserializers.property(
|
||||
name = approximationKey.name,
|
||||
source = property,
|
||||
containingClass = ownerNode.run { this as? CirClassNode }?.targetDeclarations?.get(context.targetIndex),
|
||||
containingClass = maybeClassOwnerNode?.targetDeclarations?.get(context.targetIndex),
|
||||
typeResolver = context.typeResolver
|
||||
)
|
||||
}
|
||||
|
||||
@@ -48,9 +48,11 @@ internal fun buildPropertyNode(
|
||||
storageManager: StorageManager,
|
||||
size: Int,
|
||||
classifiers: CirKnownClassifiers,
|
||||
parentCommonDeclaration: NullableLazyValue<*>?
|
||||
): CirPropertyNode = buildNode(
|
||||
storageManager = storageManager,
|
||||
size = size,
|
||||
parentCommonDeclaration = parentCommonDeclaration,
|
||||
commonizerProducer = { PropertyCommonizer(classifiers) },
|
||||
nodeProducer = ::CirPropertyNode
|
||||
)
|
||||
@@ -59,9 +61,11 @@ internal fun buildFunctionNode(
|
||||
storageManager: StorageManager,
|
||||
size: Int,
|
||||
classifiers: CirKnownClassifiers,
|
||||
parentCommonDeclaration: NullableLazyValue<*>?
|
||||
): CirFunctionNode = buildNode(
|
||||
storageManager = storageManager,
|
||||
size = size,
|
||||
parentCommonDeclaration = parentCommonDeclaration,
|
||||
commonizerProducer = { FunctionCommonizer(classifiers) },
|
||||
nodeProducer = ::CirFunctionNode
|
||||
)
|
||||
@@ -70,10 +74,12 @@ internal fun buildClassNode(
|
||||
storageManager: StorageManager,
|
||||
size: Int,
|
||||
classifiers: CirKnownClassifiers,
|
||||
parentCommonDeclaration: NullableLazyValue<*>?,
|
||||
classId: CirEntityId
|
||||
): CirClassNode = buildNode(
|
||||
storageManager = storageManager,
|
||||
size = size,
|
||||
parentCommonDeclaration = parentCommonDeclaration,
|
||||
commonizerProducer = { ClassCommonizer(classifiers) },
|
||||
recursionMarker = CirClassRecursionMarker,
|
||||
nodeProducer = { targetDeclarations, commonDeclaration ->
|
||||
@@ -87,9 +93,11 @@ internal fun buildClassConstructorNode(
|
||||
storageManager: StorageManager,
|
||||
size: Int,
|
||||
classifiers: CirKnownClassifiers,
|
||||
parentCommonDeclaration: NullableLazyValue<*>?
|
||||
): CirClassConstructorNode = buildNode(
|
||||
storageManager = storageManager,
|
||||
size = size,
|
||||
parentCommonDeclaration = parentCommonDeclaration,
|
||||
commonizerProducer = { ClassConstructorCommonizer(classifiers) },
|
||||
nodeProducer = ::CirClassConstructorNode
|
||||
)
|
||||
@@ -114,13 +122,14 @@ internal fun buildTypeAliasNode(
|
||||
private fun <T : CirDeclaration, R : CirDeclaration, N : CirNode<T, R>> buildNode(
|
||||
storageManager: StorageManager,
|
||||
size: Int,
|
||||
parentCommonDeclaration: NullableLazyValue<*>? = null,
|
||||
commonizerProducer: () -> Commonizer<T, R>,
|
||||
recursionMarker: R? = null,
|
||||
nodeProducer: (CommonizedGroup<T>, NullableLazyValue<R>) -> N
|
||||
): N {
|
||||
val targetDeclarations = CommonizedGroup<T>(size)
|
||||
|
||||
val commonComputable = { commonize(targetDeclarations, commonizerProducer()) }
|
||||
val commonComputable = { commonize(parentCommonDeclaration, targetDeclarations, commonizerProducer()) }
|
||||
|
||||
val commonLazyValue = if (recursionMarker != null)
|
||||
storageManager.createRecursionTolerantNullableLazyValue(commonComputable, recursionMarker)
|
||||
@@ -141,3 +150,17 @@ internal fun <T : Any, R> commonize(
|
||||
|
||||
return commonizer.result
|
||||
}
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
private inline fun <T : Any, R> commonize(
|
||||
parentCommonDeclaration: NullableLazyValue<*>?,
|
||||
targetDeclarations: CommonizedGroup<T>,
|
||||
commonizer: Commonizer<T, R>
|
||||
): R? {
|
||||
if (parentCommonDeclaration != null && parentCommonDeclaration.invoke() == null) {
|
||||
// don't commonize declaration if it's parent failed to commonize
|
||||
return null
|
||||
}
|
||||
|
||||
return commonize(targetDeclarations, commonizer)
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ package org.jetbrains.kotlin.commonizer.tree
|
||||
import org.jetbrains.kotlin.commonizer.TargetDependent
|
||||
import org.jetbrains.kotlin.commonizer.cir.CirRoot
|
||||
import org.jetbrains.kotlin.commonizer.mergedtree.*
|
||||
import org.jetbrains.kotlin.commonizer.tree.*
|
||||
import org.jetbrains.kotlin.storage.StorageManager
|
||||
|
||||
internal data class TargetBuildingContext(
|
||||
@@ -49,34 +48,41 @@ internal fun CirModuleNode.buildPackage(context: TargetBuildingContext, treePack
|
||||
treePackage.classes.forEach { clazz -> packageNode.buildClass(context, clazz) }
|
||||
}
|
||||
|
||||
internal fun CirNodeWithMembers<*, *>.buildClass(context: TargetBuildingContext, treeClass: CirTreeClass) {
|
||||
internal fun CirNodeWithMembers<*, *>.buildClass(
|
||||
context: TargetBuildingContext, treeClass: CirTreeClass, parent: CirNode<*, *>? = null
|
||||
) {
|
||||
val classNode = classes.getOrPut(treeClass.clazz.name) {
|
||||
buildClassNode(context.storageManager, context.targets, context.classifiers, treeClass.id)
|
||||
buildClassNode(context.storageManager, context.targets, context.classifiers, parent?.commonDeclaration, treeClass.id)
|
||||
}
|
||||
classNode.targetDeclarations[context.targetIndex] = treeClass.clazz
|
||||
treeClass.functions.forEach { function -> classNode.buildFunction(context, function) }
|
||||
treeClass.properties.forEach { property -> classNode.buildProperty(context, property) }
|
||||
treeClass.constructors.forEach { constructor -> classNode.buildConstructor(context, constructor) }
|
||||
treeClass.classes.forEach { clazz -> classNode.buildClass(context, clazz) }
|
||||
treeClass.functions.forEach { function -> classNode.buildFunction(context, function, classNode) }
|
||||
treeClass.properties.forEach { property -> classNode.buildProperty(context, property, classNode) }
|
||||
treeClass.constructors.forEach { constructor -> classNode.buildConstructor(context, constructor, classNode) }
|
||||
treeClass.classes.forEach { clazz -> classNode.buildClass(context, clazz, classNode) }
|
||||
}
|
||||
|
||||
internal fun CirNodeWithMembers<*, *>.buildFunction(context: TargetBuildingContext, treeFunction: CirTreeFunction) {
|
||||
internal fun CirNodeWithMembers<*, *>.buildFunction(
|
||||
context: TargetBuildingContext, treeFunction: CirTreeFunction, parent: CirNode<*, *>? = null
|
||||
) {
|
||||
val functionNode = functions.getOrPut(treeFunction.approximationKey) {
|
||||
buildFunctionNode(context.storageManager, context.targets, context.classifiers)
|
||||
buildFunctionNode(context.storageManager, context.targets, context.classifiers, parent?.commonDeclaration)
|
||||
}
|
||||
functionNode.targetDeclarations[context.targetIndex] = treeFunction.function
|
||||
}
|
||||
|
||||
internal fun CirNodeWithMembers<*, *>.buildProperty(context: TargetBuildingContext, treeProperty: CirTreeProperty) {
|
||||
internal fun CirNodeWithMembers<*, *>.buildProperty(
|
||||
context: TargetBuildingContext, treeProperty: CirTreeProperty, parent: CirNode<*, *>? = null) {
|
||||
val propertyNode = properties.getOrPut(treeProperty.approximationKey) {
|
||||
buildPropertyNode(context.storageManager, context.targets, context.classifiers)
|
||||
buildPropertyNode(context.storageManager, context.targets, context.classifiers, parent?.commonDeclaration)
|
||||
}
|
||||
propertyNode.targetDeclarations[context.targetIndex] = treeProperty.property
|
||||
}
|
||||
|
||||
internal fun CirClassNode.buildConstructor(context: TargetBuildingContext, treeConstructor: CirTreeClassConstructor) {
|
||||
internal fun CirClassNode.buildConstructor(
|
||||
context: TargetBuildingContext, treeConstructor: CirTreeClassConstructor, parent: CirNode<*, *>?
|
||||
) {
|
||||
val constructorNode = constructors.getOrPut(treeConstructor.approximationKey) {
|
||||
buildClassConstructorNode(context.storageManager, context.targets, context.classifiers)
|
||||
buildClassConstructorNode(context.storageManager, context.targets, context.classifiers, parent?.commonDeclaration)
|
||||
}
|
||||
constructorNode.targetDeclarations[context.targetIndex] = treeConstructor.constructor
|
||||
}
|
||||
|
||||
@@ -469,6 +469,7 @@ class TypeCommonizerTest : AbstractCommonizerTest<CirType, CirType>() {
|
||||
storageManager = LockBasedStorageManager.NO_LOCKS,
|
||||
size = variants.size,
|
||||
classifiers = classifiers,
|
||||
parentCommonDeclaration = null,
|
||||
classId = type.classifierId
|
||||
)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* 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.hierarchical
|
||||
|
||||
import org.jetbrains.kotlin.commonizer.AbstractInlineSourcesCommonizationTest
|
||||
import org.jetbrains.kotlin.commonizer.assertCommonized
|
||||
|
||||
class FunctionReturnTypeCommonizationTest : AbstractInlineSourcesCommonizationTest() {
|
||||
|
||||
fun `test non-commonized return type of top level function`() {
|
||||
val result = commonize {
|
||||
outputTarget("(a,b)")
|
||||
simpleSingleSourceTarget(
|
||||
"a", """
|
||||
class A { // NOTE: Class
|
||||
class B
|
||||
}
|
||||
fun x(): A.B = TODO()
|
||||
"""
|
||||
)
|
||||
|
||||
simpleSingleSourceTarget(
|
||||
"b", """
|
||||
interface A { // NOTE: Interface
|
||||
class B
|
||||
}
|
||||
fun x(): A.B = TODO()
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* -> A is not commonized (interface vs class)
|
||||
* -> B is not commonized
|
||||
* -> fun x can't be commonized
|
||||
* -> Empty commonization
|
||||
*/
|
||||
result.assertCommonized(
|
||||
"(a,b)", ""
|
||||
)
|
||||
|
||||
result.assertCommonized(
|
||||
"a", """
|
||||
class A {
|
||||
class B
|
||||
}
|
||||
fun x(): A.B = TODO()
|
||||
"""
|
||||
)
|
||||
|
||||
result.assertCommonized(
|
||||
"b", """
|
||||
interface A {
|
||||
class B
|
||||
}
|
||||
fun x(): A.B = TODO()
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
fun `test commonized return type of top level function`() {
|
||||
val result = commonize {
|
||||
outputTarget("(a,b)")
|
||||
simpleSingleSourceTarget(
|
||||
"a", """
|
||||
interface A {
|
||||
class B
|
||||
}
|
||||
fun x(): A.B = TODO()
|
||||
"""
|
||||
)
|
||||
|
||||
simpleSingleSourceTarget(
|
||||
"b", """
|
||||
interface A {
|
||||
class B
|
||||
}
|
||||
fun x(): A.B = TODO()
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* -> A is not commonized (interface vs class)
|
||||
* -> B is not commonized
|
||||
* -> fun x can't be commonized
|
||||
* -> Empty commonization
|
||||
*/
|
||||
result.assertCommonized(
|
||||
"(a,b)", """
|
||||
expect interface A {
|
||||
expect class B expect constructor()
|
||||
}
|
||||
expect fun x(): A.B
|
||||
"""
|
||||
)
|
||||
|
||||
result.assertCommonized(
|
||||
"a", """
|
||||
interface A {
|
||||
class B
|
||||
}
|
||||
fun x(): A.B = TODO()
|
||||
"""
|
||||
)
|
||||
|
||||
result.assertCommonized(
|
||||
"b", """
|
||||
interface A {
|
||||
class B
|
||||
}
|
||||
fun x(): A.B = TODO()
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user