[Commonizer] Re-introduce node builders 'parentCommonDeclaration' context

This commit is contained in:
sebastian.sellmair
2021-04-06 10:32:17 +02:00
parent 947dc71bda
commit bbe499c1b6
8 changed files with 175 additions and 20 deletions
@@ -19,7 +19,7 @@ internal object ClassConstructorMerger {
) = with(context) { ) = with(context) {
val approximationKey = ConstructorApproximationKey(constructor, context.typeResolver) val approximationKey = ConstructorApproximationKey(constructor, context.typeResolver)
val constructorNode: CirClassConstructorNode = classNode.constructors.getOrPut(approximationKey) { val constructorNode: CirClassConstructorNode = classNode.constructors.getOrPut(approximationKey) {
buildClassConstructorNode(storageManager, targets, classifiers) buildClassConstructorNode(storageManager, targets, classifiers, classNode.commonDeclaration)
} }
constructorNode.targetDeclarations[context.targetIndex] = CirDeserializers.constructor( constructorNode.targetDeclarations[context.targetIndex] = CirDeserializers.constructor(
source = constructor, source = constructor,
@@ -26,8 +26,9 @@ internal class ClassMerger(
val classId = classEntry.classId val classId = classEntry.classId
val className = classId.relativeNameSegments.last() val className = classId.relativeNameSegments.last()
val maybeClassOwnerNode: CirClassNode? = ownerNode as? CirClassNode
val classNode: CirClassNode = ownerNode.classes.getOrPut(className) { val classNode: CirClassNode = ownerNode.classes.getOrPut(className) {
buildClassNode(storageManager, targets, classifiers, classId) buildClassNode(storageManager, targets, classifiers, maybeClassOwnerNode?.commonDeclaration, classId)
} }
val clazz: KmClass? val clazz: KmClass?
@@ -27,14 +27,16 @@ internal object FunctionMerger {
return return
} }
val maybeClassOwnerNode: CirClassNode? = ownerNode as? CirClassNode
val approximationKey = FunctionApproximationKey(function, context.typeResolver) val approximationKey = FunctionApproximationKey(function, context.typeResolver)
val functionNode: CirFunctionNode = ownerNode.functions.getOrPut(approximationKey) { val functionNode: CirFunctionNode = ownerNode.functions.getOrPut(approximationKey) {
buildFunctionNode(storageManager, targets, classifiers) buildFunctionNode(storageManager, targets, classifiers, maybeClassOwnerNode?.commonDeclaration)
} }
functionNode.targetDeclarations[context.targetIndex] = CirDeserializers.function( functionNode.targetDeclarations[context.targetIndex] = CirDeserializers.function(
name = approximationKey.name, name = approximationKey.name,
source = function, source = function,
containingClass = ownerNode.run { this as? CirClassNode }?.targetDeclarations?.get(context.targetIndex), containingClass = maybeClassOwnerNode?.targetDeclarations?.get(context.targetIndex),
typeResolver = context.typeResolver typeResolver = context.typeResolver
) )
} }
@@ -21,14 +21,16 @@ internal object PropertyMerger {
if (property.isFakeOverride()) if (property.isFakeOverride())
return return
val maybeClassOwnerNode: CirClassNode? = ownerNode as? CirClassNode
val approximationKey = PropertyApproximationKey(property, context.typeResolver) val approximationKey = PropertyApproximationKey(property, context.typeResolver)
val propertyNode: CirPropertyNode = ownerNode.properties.getOrPut(approximationKey) { val propertyNode: CirPropertyNode = ownerNode.properties.getOrPut(approximationKey) {
buildPropertyNode(storageManager, targets, classifiers) buildPropertyNode(storageManager, targets, classifiers, maybeClassOwnerNode?.commonDeclaration)
} }
propertyNode.targetDeclarations[context.targetIndex] = CirDeserializers.property( propertyNode.targetDeclarations[context.targetIndex] = CirDeserializers.property(
name = approximationKey.name, name = approximationKey.name,
source = property, source = property,
containingClass = ownerNode.run { this as? CirClassNode }?.targetDeclarations?.get(context.targetIndex), containingClass = maybeClassOwnerNode?.targetDeclarations?.get(context.targetIndex),
typeResolver = context.typeResolver typeResolver = context.typeResolver
) )
} }
@@ -48,9 +48,11 @@ internal fun buildPropertyNode(
storageManager: StorageManager, storageManager: StorageManager,
size: Int, size: Int,
classifiers: CirKnownClassifiers, classifiers: CirKnownClassifiers,
parentCommonDeclaration: NullableLazyValue<*>?
): CirPropertyNode = buildNode( ): CirPropertyNode = buildNode(
storageManager = storageManager, storageManager = storageManager,
size = size, size = size,
parentCommonDeclaration = parentCommonDeclaration,
commonizerProducer = { PropertyCommonizer(classifiers) }, commonizerProducer = { PropertyCommonizer(classifiers) },
nodeProducer = ::CirPropertyNode nodeProducer = ::CirPropertyNode
) )
@@ -59,9 +61,11 @@ internal fun buildFunctionNode(
storageManager: StorageManager, storageManager: StorageManager,
size: Int, size: Int,
classifiers: CirKnownClassifiers, classifiers: CirKnownClassifiers,
parentCommonDeclaration: NullableLazyValue<*>?
): CirFunctionNode = buildNode( ): CirFunctionNode = buildNode(
storageManager = storageManager, storageManager = storageManager,
size = size, size = size,
parentCommonDeclaration = parentCommonDeclaration,
commonizerProducer = { FunctionCommonizer(classifiers) }, commonizerProducer = { FunctionCommonizer(classifiers) },
nodeProducer = ::CirFunctionNode nodeProducer = ::CirFunctionNode
) )
@@ -70,10 +74,12 @@ internal fun buildClassNode(
storageManager: StorageManager, storageManager: StorageManager,
size: Int, size: Int,
classifiers: CirKnownClassifiers, classifiers: CirKnownClassifiers,
parentCommonDeclaration: NullableLazyValue<*>?,
classId: CirEntityId classId: CirEntityId
): CirClassNode = buildNode( ): CirClassNode = buildNode(
storageManager = storageManager, storageManager = storageManager,
size = size, size = size,
parentCommonDeclaration = parentCommonDeclaration,
commonizerProducer = { ClassCommonizer(classifiers) }, commonizerProducer = { ClassCommonizer(classifiers) },
recursionMarker = CirClassRecursionMarker, recursionMarker = CirClassRecursionMarker,
nodeProducer = { targetDeclarations, commonDeclaration -> nodeProducer = { targetDeclarations, commonDeclaration ->
@@ -87,9 +93,11 @@ internal fun buildClassConstructorNode(
storageManager: StorageManager, storageManager: StorageManager,
size: Int, size: Int,
classifiers: CirKnownClassifiers, classifiers: CirKnownClassifiers,
parentCommonDeclaration: NullableLazyValue<*>?
): CirClassConstructorNode = buildNode( ): CirClassConstructorNode = buildNode(
storageManager = storageManager, storageManager = storageManager,
size = size, size = size,
parentCommonDeclaration = parentCommonDeclaration,
commonizerProducer = { ClassConstructorCommonizer(classifiers) }, commonizerProducer = { ClassConstructorCommonizer(classifiers) },
nodeProducer = ::CirClassConstructorNode nodeProducer = ::CirClassConstructorNode
) )
@@ -114,13 +122,14 @@ internal fun buildTypeAliasNode(
private fun <T : CirDeclaration, R : CirDeclaration, N : CirNode<T, R>> buildNode( private fun <T : CirDeclaration, R : CirDeclaration, N : CirNode<T, R>> buildNode(
storageManager: StorageManager, storageManager: StorageManager,
size: Int, size: Int,
parentCommonDeclaration: NullableLazyValue<*>? = null,
commonizerProducer: () -> Commonizer<T, R>, commonizerProducer: () -> Commonizer<T, R>,
recursionMarker: R? = null, recursionMarker: R? = null,
nodeProducer: (CommonizedGroup<T>, NullableLazyValue<R>) -> N nodeProducer: (CommonizedGroup<T>, NullableLazyValue<R>) -> N
): N { ): N {
val targetDeclarations = CommonizedGroup<T>(size) val targetDeclarations = CommonizedGroup<T>(size)
val commonComputable = { commonize(targetDeclarations, commonizerProducer()) } val commonComputable = { commonize(parentCommonDeclaration, targetDeclarations, commonizerProducer()) }
val commonLazyValue = if (recursionMarker != null) val commonLazyValue = if (recursionMarker != null)
storageManager.createRecursionTolerantNullableLazyValue(commonComputable, recursionMarker) storageManager.createRecursionTolerantNullableLazyValue(commonComputable, recursionMarker)
@@ -141,3 +150,17 @@ internal fun <T : Any, R> commonize(
return commonizer.result 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.TargetDependent
import org.jetbrains.kotlin.commonizer.cir.CirRoot import org.jetbrains.kotlin.commonizer.cir.CirRoot
import org.jetbrains.kotlin.commonizer.mergedtree.* import org.jetbrains.kotlin.commonizer.mergedtree.*
import org.jetbrains.kotlin.commonizer.tree.*
import org.jetbrains.kotlin.storage.StorageManager import org.jetbrains.kotlin.storage.StorageManager
internal data class TargetBuildingContext( internal data class TargetBuildingContext(
@@ -49,34 +48,41 @@ internal fun CirModuleNode.buildPackage(context: TargetBuildingContext, treePack
treePackage.classes.forEach { clazz -> packageNode.buildClass(context, clazz) } 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) { 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 classNode.targetDeclarations[context.targetIndex] = treeClass.clazz
treeClass.functions.forEach { function -> classNode.buildFunction(context, function) } treeClass.functions.forEach { function -> classNode.buildFunction(context, function, classNode) }
treeClass.properties.forEach { property -> classNode.buildProperty(context, property) } treeClass.properties.forEach { property -> classNode.buildProperty(context, property, classNode) }
treeClass.constructors.forEach { constructor -> classNode.buildConstructor(context, constructor) } treeClass.constructors.forEach { constructor -> classNode.buildConstructor(context, constructor, classNode) }
treeClass.classes.forEach { clazz -> classNode.buildClass(context, clazz) } 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) { 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 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) { 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 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) { 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 constructorNode.targetDeclarations[context.targetIndex] = treeConstructor.constructor
} }
@@ -469,6 +469,7 @@ class TypeCommonizerTest : AbstractCommonizerTest<CirType, CirType>() {
storageManager = LockBasedStorageManager.NO_LOCKS, storageManager = LockBasedStorageManager.NO_LOCKS,
size = variants.size, size = variants.size,
classifiers = classifiers, classifiers = classifiers,
parentCommonDeclaration = null,
classId = type.classifierId 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()
"""
)
}
}