[Commonizer] Initial implementation for nullable return type commonization

^KT-48567
This commit is contained in:
sebastian.sellmair
2021-09-04 14:11:22 +02:00
committed by Space
parent f56419cbf8
commit b13f3599cf
6 changed files with 72 additions and 10 deletions
@@ -5,21 +5,21 @@
package org.jetbrains.kotlin.commonizer.core
import org.jetbrains.kotlin.commonizer.cir.CirFunctionOrProperty
import org.jetbrains.kotlin.commonizer.cir.CirName
import org.jetbrains.kotlin.commonizer.cir.*
import org.jetbrains.kotlin.commonizer.mergedtree.CirKnownClassifiers
import org.jetbrains.kotlin.commonizer.utils.safeCastValues
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.DELEGATION
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.SYNTHESIZED
abstract class AbstractFunctionOrPropertyCommonizer<T : CirFunctionOrProperty>(
classifiers: CirKnownClassifiers
) : AbstractStandardCommonizer<T, T>() {
) : AbstractStandardCommonizer<T, T?>() {
protected lateinit var name: CirName
protected val modality = ModalityCommonizer()
protected val visibility = VisibilityCommonizer.lowering()
protected val extensionReceiver = ExtensionReceiverCommonizer(classifiers)
protected val returnType = TypeCommonizer(classifiers).asCommonizer()
protected val returnType = ReturnTypeCommonizer(classifiers).asCommonizer()
protected lateinit var kind: CallableMemberDescriptor.Kind
protected val typeParameters = TypeParameterListCommonizer(classifiers)
@@ -35,6 +35,29 @@ abstract class AbstractFunctionOrPropertyCommonizer<T : CirFunctionOrProperty>(
&& modality.commonizeWith(next.modality)
&& visibility.commonizeWith(next)
&& extensionReceiver.commonizeWith(next.extensionReceiver)
&& returnType.commonizeWith(next.returnType)
&& returnType.commonizeWith(next)
&& typeParameters.commonizeWith(next.typeParameters)
}
private class ReturnTypeCommonizer(
private val classifiers: CirKnownClassifiers,
) : NullableContextualSingleInvocationCommonizer<CirFunctionOrProperty, CirType> {
override fun invoke(values: List<CirFunctionOrProperty>): CirType? {
if (values.isEmpty()) return null
val isTopLevel = values.all { it.containingClass == null }
val returnTypes = if (isTopLevel) makeNullableIfNecessary(values.map { it.returnType }) else values.map { it.returnType }
return TypeCommonizer(classifiers).asCommonizer().commonize(returnTypes)
}
private fun makeNullableIfNecessary(types: List<CirType>): List<CirType> {
val simpleTypes = types.safeCastValues<CirType, CirSimpleType>() ?: return types
if (
simpleTypes.all { type -> type.isMarkedNullable } ||
simpleTypes.none { type -> type.isMarkedNullable }
) return types
return simpleTypes.map { type -> type.makeNullable() }
}
}
@@ -13,7 +13,7 @@ class FunctionCommonizer(classifiers: CirKnownClassifiers) : AbstractFunctionOrP
private val modifiers = FunctionModifiersCommonizer()
private val valueParameters = CallableValueParametersCommonizer(classifiers)
override fun commonizationResult(): CirFunction {
override fun commonizationResult(): CirFunction? {
val valueParameters = valueParameters.result
valueParameters.patchCallables()
@@ -27,7 +27,7 @@ class FunctionCommonizer(classifiers: CirKnownClassifiers) : AbstractFunctionOrP
valueParameters = valueParameters.valueParameters,
hasStableParameterNames = valueParameters.hasStableParameterNames,
extensionReceiver = extensionReceiver.result,
returnType = returnType.result,
returnType = returnType.result ?: return null,
kind = kind,
modifiers = modifiers.result
)
@@ -19,4 +19,21 @@ fun <T : Any> NullableSingleInvocationCommonizer<T>.asCommonizer(): Commonizer<T
collectedValues.add(next)
return true
}
}
}
interface NullableContextualSingleInvocationCommonizer<T : Any, R : Any> {
operator fun invoke(values: List<T>): R?
}
fun <T : Any, R: Any> NullableContextualSingleInvocationCommonizer<T, R>.asCommonizer(): Commonizer<T, R?> = object : Commonizer<T, R?> {
private val collectedValues = mutableListOf<T>()
override val result: R?
get() = this@asCommonizer.invoke(collectedValues)
override fun commonizeWith(next: T): Boolean {
collectedValues.add(next)
return true
}
}
@@ -17,7 +17,7 @@ class PropertyCommonizer(classifiers: CirKnownClassifiers) : AbstractFunctionOrP
private var isExternal = true
private lateinit var constCommonizationState: ConstCommonizationState
override fun commonizationResult(): CirProperty {
override fun commonizationResult(): CirProperty? {
val modality = modality.result
val setter = setter.result?.takeIf { setter ->
@@ -36,7 +36,7 @@ class PropertyCommonizer(classifiers: CirKnownClassifiers) : AbstractFunctionOrP
containingClass = null, // does not matter
isExternal = isExternal,
extensionReceiver = extensionReceiver.result,
returnType = returnType.result,
returnType = returnType.result ?: return null,
kind = kind,
isVar = setter != null,
isLateInit = false,
@@ -122,3 +122,21 @@ inline fun <T> Array<T>.fastForEach(action: (T) -> Unit) {
action(this[index])
}
}
@Suppress("unchecked_cast")
internal inline fun <T, reified R> List<T>.safeCastValues(): List<R>? {
fastForEach { if (it !is R) return null }
return this as List<R>
}
internal fun <T : Any> List<T>.singleDistinctValueOrNull(): T? = singleDistinctValueOrNull { it }
internal inline fun <T : Any, R> List<T>.singleDistinctValueOrNull(selector: (T) -> R): R? {
if (isEmpty()) return null
val value = selector(this[0])
for (index in 1 until size) {
if (value != selector(this[index])) return null
}
return value
}
@@ -96,6 +96,10 @@ abstract class AbstractInlineSourcesCommonizationTest : KtInlineSourceCommonizer
}
}
infix fun String.withSource(@Language("kotlin") sourceContent: String) {
simpleSingleSourceTarget(this, sourceContent)
}
@InlineSourcesCommonizationTestDsl
fun simpleSingleSourceTarget(target: String, @Language("kotlin") sourceCode: String) {
simpleSingleSourceTarget(parseCommonizerTarget(target), sourceCode)