[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

View File

@@ -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,

View File

@@ -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?

View File

@@ -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
)
}

View File

@@ -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
)
}

View File

@@ -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)
}

View File

@@ -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
}

View File

@@ -469,6 +469,7 @@ class TypeCommonizerTest : AbstractCommonizerTest<CirType, CirType>() {
storageManager = LockBasedStorageManager.NO_LOCKS,
size = variants.size,
classifiers = classifiers,
parentCommonDeclaration = null,
classId = type.classifierId
)
}

View File

@@ -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()
"""
)
}
}