[Commonizer] Move ClassTypeCommonizer and TypeAliasTypeCommonizer into seperate files

This commit is contained in:
sebastian.sellmair
2021-06-30 10:28:59 +02:00
committed by Space
parent 8f73df0f85
commit d7022cb378
3 changed files with 192 additions and 175 deletions
@@ -0,0 +1,71 @@
/*
* 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.core
import org.jetbrains.kotlin.commonizer.cir.CirClassType
import org.jetbrains.kotlin.commonizer.cir.CirEntityId
import org.jetbrains.kotlin.commonizer.mergedtree.CirKnownClassifiers
import org.jetbrains.kotlin.commonizer.utils.isUnderKotlinNativeSyntheticPackages
import org.jetbrains.kotlin.descriptors.Visibility
internal class ClassTypeCommonizer(private val classifiers: CirKnownClassifiers) :
AbstractStandardCommonizer<CirClassType, CirClassType>() {
private lateinit var classId: CirEntityId
private val outerType = OuterClassTypeCommonizer(classifiers)
private lateinit var anyVisibility: Visibility
private val arguments = TypeArgumentListCommonizer(classifiers)
private var isMarkedNullable = false
override fun commonizationResult() = CirClassType.createInterned(
classId = classId,
outerType = outerType.result,
// N.B. The 'visibility' field in class types is needed ONLY for TA commonization. The class type constructed here is
// intended to be used in "common" target. It could not participate in TA commonization. So, it does not matter which
// exactly visibility will be recorded for commonized class type. Passing the visibility of the first class type
// to reach better interning rate.
visibility = anyVisibility,
arguments = arguments.result,
isMarkedNullable = isMarkedNullable
)
override fun initialize(first: CirClassType) {
classId = first.classifierId
anyVisibility = first.visibility
isMarkedNullable = first.isMarkedNullable
}
override fun doCommonizeWith(next: CirClassType) =
isMarkedNullable == next.isMarkedNullable
&& classId == next.classifierId
&& outerType.commonizeWith(next.outerType)
&& isClassifierAvailableInCommon(classifiers, classId)
&& arguments.commonizeWith(next.arguments)
}
private fun isClassifierAvailableInCommon(classifiers: CirKnownClassifiers, classId: CirEntityId): Boolean {
if (classifiers.commonDependencies.hasClassifier(classId)) {
// The class is from common fragment of dependency library (ex: stdlib). Already commonized.
return true
} else if (classId.packageName.isUnderKotlinNativeSyntheticPackages) {
// C/Obj-C forward declarations are:
// - Either resolved to real classes/interfaces from other interop libraries (which are generated by C-interop tool and
// are known to have modality/visibility/other attributes to successfully pass commonization).
// - Or resolved to the same synthetic classes/interfaces.
// ... and therefore are considered as successfully commonized.
return true
}
// Looking for a a node that provides a non-null (successfully commonized) classifier declaration
return (classifiers.commonizedNodes.classNode(classId)?.commonDeclaration?.invoke()
?: classifiers.commonizedNodes.typeAliasNode(classId)?.commonDeclaration?.invoke()) != null
}
private class OuterClassTypeCommonizer(classifiers: CirKnownClassifiers) :
AbstractNullableCommonizer<CirClassType, CirClassType, CirClassType, CirClassType>(
wrappedCommonizerFactory = { ClassTypeCommonizer(classifiers) },
extractor = { it },
builder = { it }
)
@@ -0,0 +1,121 @@
/*
* 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.core
import org.jetbrains.kotlin.commonizer.cir.*
import org.jetbrains.kotlin.commonizer.core.CommonizedTypeAliasAnswer.Companion.FAILURE_MISSING_IN_SOME_TARGET
import org.jetbrains.kotlin.commonizer.core.CommonizedTypeAliasAnswer.Companion.SUCCESS_FROM_DEPENDENCY_LIBRARY
import org.jetbrains.kotlin.commonizer.mergedtree.CirKnownClassifiers
internal class TypeAliasTypeCommonizer(private val classifiers: CirKnownClassifiers) :
AbstractStandardCommonizer<CirTypeAliasType, CirClassOrTypeAliasType>() {
private lateinit var typeAliasId: CirEntityId
private val arguments = TypeArgumentListCommonizer(classifiers)
private var isMarkedNullable = false
private var commonizedTypeBuilder: CommonizedTypeAliasTypeBuilder? = null // null means not selected yet
override fun commonizationResult() =
(commonizedTypeBuilder ?: failInEmptyState()).build(
typeAliasId = typeAliasId,
arguments = arguments.result,
isMarkedNullable = isMarkedNullable
)
override fun initialize(first: CirTypeAliasType) {
typeAliasId = first.classifierId
isMarkedNullable = first.expandedType().isMarkedNullable
}
override fun doCommonizeWith(next: CirTypeAliasType): Boolean {
if (isMarkedNullable != next.expandedType().isMarkedNullable || typeAliasId != next.classifierId)
return false
if (commonizedTypeBuilder == null) {
val answer = commonizeTypeAlias(typeAliasId, classifiers)
if (!answer.isCommon)
return false
commonizedTypeBuilder = when (val commonClassifier = answer.commonClassifier) {
is CirClass -> CommonizedTypeAliasTypeBuilder.forClass(commonClassifier)
is CirTypeAlias -> CommonizedTypeAliasTypeBuilder.forTypeAlias(commonClassifier)
null -> {
val underlyingType = computeSuitableUnderlyingType(classifiers, next.underlyingType) ?: return false
CommonizedTypeAliasTypeBuilder.forKnownUnderlyingType(underlyingType)
}
else -> error("Unexpected common classifier type: ${commonClassifier::class.java}, $commonClassifier")
}
}
return arguments.commonizeWith(next.arguments)
}
// builds a new type for "common" library fragment for the given combination of type alias types in "platform" fragments
internal interface CommonizedTypeAliasTypeBuilder {
fun build(typeAliasId: CirEntityId, arguments: List<CirTypeProjection>, isMarkedNullable: Boolean): CirClassOrTypeAliasType
companion object {
// type alias has been commonized to expect class, need to build type for expect class
fun forClass(commonClass: CirClass) = object : CommonizedTypeAliasTypeBuilder {
override fun build(typeAliasId: CirEntityId, arguments: List<CirTypeProjection>, isMarkedNullable: Boolean) =
CirClassType.createInterned(
classId = typeAliasId,
outerType = null, // there can't be outer type // TODO NOW!!!
visibility = commonClass.visibility,
arguments = arguments,
isMarkedNullable = isMarkedNullable
)
}
// type alias has been commonized to another type alias with the different underlying type, need to build type for
// new type alias
fun forTypeAlias(modifiedTypeAlias: CirTypeAlias) = forKnownUnderlyingType(modifiedTypeAlias.underlyingType)
// type alias don't needs to be commonized because it is from the standard library
fun forKnownUnderlyingType(underlyingType: CirClassOrTypeAliasType) = object : CommonizedTypeAliasTypeBuilder {
override fun build(
typeAliasId: CirEntityId,
arguments: List<CirTypeProjection>,
isMarkedNullable: Boolean
): CirTypeAliasType {
val underlyingTypeWithProperNullability = underlyingType.makeNullableIfNecessary(isMarkedNullable)
return CirTypeAliasType.createInterned(
typeAliasId = typeAliasId,
underlyingType = underlyingTypeWithProperNullability, // TODO replace arguments???
arguments = arguments,
isMarkedNullable = isMarkedNullable
)
}
}
}
}
}
private fun commonizeTypeAlias(typeAliasId: CirEntityId, classifiers: CirKnownClassifiers): CommonizedTypeAliasAnswer {
if (classifiers.commonDependencies.hasClassifier(typeAliasId)) {
// The type alias is from common fragment of dependency library (ex: stdlib). Already commonized.
return SUCCESS_FROM_DEPENDENCY_LIBRARY
}
val typeAliasNode = classifiers.commonizedNodes.typeAliasNode(typeAliasId)
val classNode = classifiers.commonizedNodes.classNode(typeAliasId)
if (typeAliasNode == null && classNode == null) {
return FAILURE_MISSING_IN_SOME_TARGET
}
return CommonizedTypeAliasAnswer.create(typeAliasNode?.commonDeclaration?.invoke() ?: classNode?.commonDeclaration?.invoke())
}
private class CommonizedTypeAliasAnswer(val isCommon: Boolean, val commonClassifier: CirClassifier?) {
companion object {
val SUCCESS_FROM_DEPENDENCY_LIBRARY = CommonizedTypeAliasAnswer(true, null)
val FAILURE_MISSING_IN_SOME_TARGET = CommonizedTypeAliasAnswer(false, null)
fun create(commonClassifier: CirClassifier?) =
if (commonClassifier != null) CommonizedTypeAliasAnswer(true, commonClassifier) else FAILURE_MISSING_IN_SOME_TARGET
}
}
@@ -6,12 +6,7 @@
package org.jetbrains.kotlin.commonizer.core
import org.jetbrains.kotlin.commonizer.cir.*
import org.jetbrains.kotlin.commonizer.core.CommonizedTypeAliasAnswer.Companion.FAILURE_MISSING_IN_SOME_TARGET
import org.jetbrains.kotlin.commonizer.core.CommonizedTypeAliasAnswer.Companion.SUCCESS_FROM_DEPENDENCY_LIBRARY
import org.jetbrains.kotlin.commonizer.core.CommonizedTypeAliasAnswer.Companion.create
import org.jetbrains.kotlin.commonizer.mergedtree.CirKnownClassifiers
import org.jetbrains.kotlin.commonizer.utils.isUnderKotlinNativeSyntheticPackages
import org.jetbrains.kotlin.descriptors.Visibility
class TypeCommonizer(private val classifiers: CirKnownClassifiers) : AbstractStandardCommonizer<CirType, CirType>() {
private lateinit var typeCommonizer: Commonizer<*, CirType>
@@ -36,132 +31,6 @@ class TypeCommonizer(private val classifiers: CirKnownClassifiers) : AbstractSta
}
}
internal class ClassTypeCommonizer(private val classifiers: CirKnownClassifiers) :
AbstractStandardCommonizer<CirClassType, CirClassType>() {
private lateinit var classId: CirEntityId
private val outerType = OuterClassTypeCommonizer(classifiers)
private lateinit var anyVisibility: Visibility
private val arguments = TypeArgumentListCommonizer(classifiers)
private var isMarkedNullable = false
override fun commonizationResult() = CirClassType.createInterned(
classId = classId,
outerType = outerType.result,
// N.B. The 'visibility' field in class types is needed ONLY for TA commonization. The class type constructed here is
// intended to be used in "common" target. It could not participate in TA commonization. So, it does not matter which
// exactly visibility will be recorded for commonized class type. Passing the visibility of the first class type
// to reach better interning rate.
visibility = anyVisibility,
arguments = arguments.result,
isMarkedNullable = isMarkedNullable
)
override fun initialize(first: CirClassType) {
classId = first.classifierId
anyVisibility = first.visibility
isMarkedNullable = first.isMarkedNullable
}
override fun doCommonizeWith(next: CirClassType) =
isMarkedNullable == next.isMarkedNullable
&& classId == next.classifierId
&& outerType.commonizeWith(next.outerType)
&& commonizeClass(classId, classifiers)
&& arguments.commonizeWith(next.arguments)
}
// TODO NOW
internal class OuterClassTypeCommonizer(classifiers: CirKnownClassifiers) :
AbstractNullableCommonizer<CirClassType, CirClassType, CirClassType, CirClassType>(
wrappedCommonizerFactory = { ClassTypeCommonizer(classifiers) },
extractor = { it },
builder = { it }
)
internal class TypeAliasTypeCommonizer(private val classifiers: CirKnownClassifiers) :
AbstractStandardCommonizer<CirTypeAliasType, CirClassOrTypeAliasType>() {
private lateinit var typeAliasId: CirEntityId
private val arguments = TypeArgumentListCommonizer(classifiers)
private var isMarkedNullable = false
private var commonizedTypeBuilder: CommonizedTypeAliasTypeBuilder? = null // null means not selected yet
override fun commonizationResult() =
(commonizedTypeBuilder ?: failInEmptyState()).build(
typeAliasId = typeAliasId,
arguments = arguments.result,
isMarkedNullable = isMarkedNullable
)
override fun initialize(first: CirTypeAliasType) {
typeAliasId = first.classifierId
isMarkedNullable = first.expandedType().isMarkedNullable
}
override fun doCommonizeWith(next: CirTypeAliasType): Boolean {
if (isMarkedNullable != next.expandedType().isMarkedNullable || typeAliasId != next.classifierId)
return false
if (commonizedTypeBuilder == null) {
val answer = commonizeTypeAlias(typeAliasId, classifiers)
if (!answer.commonized)
return false
commonizedTypeBuilder = when (val commonClassifier = answer.commonClassifier) {
is CirClass -> CommonizedTypeAliasTypeBuilder.forClass(commonClassifier)
is CirTypeAlias -> CommonizedTypeAliasTypeBuilder.forTypeAlias(commonClassifier)
null -> {
val underlyingType = computeSuitableUnderlyingType(classifiers, next.underlyingType) ?: return false
CommonizedTypeAliasTypeBuilder.forKnownUnderlyingType(underlyingType)
}
else -> error("Unexpected common classifier type: ${commonClassifier::class.java}, $commonClassifier")
}
}
return arguments.commonizeWith(next.arguments)
}
// builds a new type for "common" library fragment for the given combination of type alias types in "platform" fragments
internal interface CommonizedTypeAliasTypeBuilder {
fun build(typeAliasId: CirEntityId, arguments: List<CirTypeProjection>, isMarkedNullable: Boolean): CirClassOrTypeAliasType
companion object {
// type alias has been commonized to expect class, need to build type for expect class
fun forClass(commonClass: CirClass) = object : CommonizedTypeAliasTypeBuilder {
override fun build(typeAliasId: CirEntityId, arguments: List<CirTypeProjection>, isMarkedNullable: Boolean) =
CirClassType.createInterned(
classId = typeAliasId,
outerType = null, // there can't be outer type // TODO NOW!!!
visibility = commonClass.visibility,
arguments = arguments,
isMarkedNullable = isMarkedNullable
)
}
// type alias has been commonized to another type alias with the different underlying type, need to build type for
// new type alias
fun forTypeAlias(modifiedTypeAlias: CirTypeAlias) = forKnownUnderlyingType(modifiedTypeAlias.underlyingType)
// type alias don't needs to be commonized because it is from the standard library
fun forKnownUnderlyingType(underlyingType: CirClassOrTypeAliasType) = object : CommonizedTypeAliasTypeBuilder {
override fun build(
typeAliasId: CirEntityId,
arguments: List<CirTypeProjection>,
isMarkedNullable: Boolean
): CirTypeAliasType {
val underlyingTypeWithProperNullability = underlyingType.makeNullableIfNecessary(isMarkedNullable)
return CirTypeAliasType.createInterned(
typeAliasId = typeAliasId,
underlyingType = underlyingTypeWithProperNullability, // TODO replace arguments???
arguments = arguments,
isMarkedNullable = isMarkedNullable
)
}
}
}
}
}
private class TypeParameterTypeCommonizer : AbstractStandardCommonizer<CirTypeParameterType, CirTypeParameterType>() {
private lateinit var temp: CirTypeParameterType
@@ -192,47 +61,3 @@ private class FlexibleTypeCommonizer(classifiers: CirKnownClassifiers) : Abstrac
override fun doCommonizeWith(next: CirFlexibleType) =
lowerBound.commonizeWith(next.lowerBound) && upperBound.commonizeWith(next.upperBound)
}
private fun commonizeClass(classId: CirEntityId, classifiers: CirKnownClassifiers): Boolean {
if (classifiers.commonDependencies.hasClassifier(classId)) {
// The class is from common fragment of dependency library (ex: stdlib). Already commonized.
return true
} else if (classId.packageName.isUnderKotlinNativeSyntheticPackages) {
// C/Obj-C forward declarations are:
// - Either resolved to real classes/interfaces from other interop libraries (which are generated by C-interop tool and
// are known to have modality/visibility/other attributes to successfully pass commonization).
// - Or resolved to the same synthetic classes/interfaces.
// ... and therefore are considered as successfully commonized.
return true
}
// Looking for a a node that provides a non-null (successfully commonized) classifier declaration
return (classifiers.commonizedNodes.classNode(classId)?.commonDeclaration?.invoke()
?: classifiers.commonizedNodes.typeAliasNode(classId)?.commonDeclaration?.invoke()) != null
}
private fun commonizeTypeAlias(typeAliasId: CirEntityId, classifiers: CirKnownClassifiers): CommonizedTypeAliasAnswer {
if (classifiers.commonDependencies.hasClassifier(typeAliasId)) {
// The type alias is from common fragment of dependency library (ex: stdlib). Already commonized.
return SUCCESS_FROM_DEPENDENCY_LIBRARY
}
val typeAliasNode = classifiers.commonizedNodes.typeAliasNode(typeAliasId)
val classNode = classifiers.commonizedNodes.classNode(typeAliasId)
if (typeAliasNode == null && classNode == null) {
return FAILURE_MISSING_IN_SOME_TARGET
}
return create(typeAliasNode?.commonDeclaration?.invoke() ?: classNode?.commonDeclaration?.invoke())
}
internal class CommonizedTypeAliasAnswer(val commonized: Boolean, val commonClassifier: CirClassifier?) {
companion object {
val SUCCESS_FROM_DEPENDENCY_LIBRARY = CommonizedTypeAliasAnswer(true, null)
val FAILURE_MISSING_IN_SOME_TARGET = CommonizedTypeAliasAnswer(false, null)
fun create(commonClassifier: CirClassifier?) =
if (commonClassifier != null) CommonizedTypeAliasAnswer(true, commonClassifier) else FAILURE_MISSING_IN_SOME_TARGET
}
}