[Commonizer] Use ClassId instead of FqName for addressing classes and TAs

This commit is contained in:
Dmitriy Dolovov
2020-07-01 00:13:00 +07:00
parent 57aefbcd57
commit ffd0c69698
39 changed files with 408 additions and 261 deletions
@@ -5,13 +5,10 @@
package org.jetbrains.kotlin.descriptors.commonizer.builder
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassKind.ANNOTATION_CLASS
import org.jetbrains.kotlin.descriptors.SourceElement
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirAnnotation
import org.jetbrains.kotlin.descriptors.commonizer.utils.concat
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.constants.AnnotationValue
import org.jetbrains.kotlin.storage.getValue
@@ -19,14 +16,8 @@ class CommonizedAnnotationDescriptor(
targetComponents: TargetDeclarationsBuilderComponents,
cirAnnotation: CirAnnotation
) : AnnotationDescriptor {
override val fqName: FqName = cirAnnotation.fqName
override val type by targetComponents.storageManager.createLazyValue {
val annotationClass = findClassOrTypeAlias(targetComponents, fqName)
check(annotationClass is ClassDescriptor && annotationClass.kind == ANNOTATION_CLASS) {
"Not an annotation class: ${annotationClass::class.java}, $annotationClass"
}
annotationClass.defaultType
cirAnnotation.type.buildType(targetComponents, TypeParameterResolver.EMPTY)
}
override val allValueArguments by targetComponents.storageManager.createLazyValue {
@@ -80,7 +80,7 @@ internal class DeclarationsBuilderVisitor2(
}
override fun visitClassNode(node: CirClassNode, data: List<DeclarationDescriptor?>): List<DeclarationDescriptor?> {
val classes = components.cache.getCachedClasses(node.fqName)
val classes = components.cache.getCachedClasses(node.classId)
// build class constructors:
val allConstructorsByTargets = Array<MutableList<CommonizedClassConstructorDescriptor>>(node.dimension) { ArrayList() }
@@ -8,13 +8,10 @@ package org.jetbrains.kotlin.descriptors.commonizer.builder
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.commonizer.cir.*
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirSimpleTypeKind.Companion.areCompatible
import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.cirSimpleTypeKind
import org.jetbrains.kotlin.descriptors.commonizer.utils.isUnderStandardKotlinPackages
import org.jetbrains.kotlin.descriptors.commonizer.utils.resolveClassOrTypeAliasByFqName
import org.jetbrains.kotlin.descriptors.commonizer.utils.resolveClassOrTypeAlias
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.resolve.DescriptorFactory
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.types.*
@@ -106,17 +103,26 @@ internal fun CirSimpleType.buildType(
targetComponents: TargetDeclarationsBuilderComponents,
typeParameterResolver: TypeParameterResolver
): SimpleType {
val classifier: ClassifierDescriptor = when (kind) {
CirSimpleTypeKind.TYPE_PARAMETER -> {
typeParameterResolver.resolve(fqName.shortName())
?: error("Type parameter $fqName not found in ${typeParameterResolver::class.java}, $typeParameterResolver for ${targetComponents.target}")
val classifier: ClassifierDescriptor = when (val classifierId = classifierId) {
is CirClassifierId.Class -> {
findClassOrTypeAlias(targetComponents, classifierId.classId).checkClassifierType<ClassDescriptor>()
}
is CirClassifierId.TypeAlias -> {
val classId = classifierId.classId
val classOrTypeAlias: ClassifierDescriptorWithTypeParameters = findClassOrTypeAlias(targetComponents, classId)
CirSimpleTypeKind.CLASS, CirSimpleTypeKind.TYPE_ALIAS -> {
val classOrTypeAlias = findClassOrTypeAlias(targetComponents, fqName)
checkClassifier(classOrTypeAlias, kind, fqName.isUnderStandardKotlinPackages || !targetComponents.isCommon)
classOrTypeAlias
if (classId.packageFqName.isUnderStandardKotlinPackages || !targetComponents.isCommon) {
// classifier type could be only type alias
classOrTypeAlias.checkClassifierType<TypeAliasDescriptor>()
} else {
// classifier could be class or type alias
classOrTypeAlias
}
}
is CirClassifierId.TypeParameter -> {
val name = classifierId.name
typeParameterResolver.resolve(name)
?: error("Type parameter $name not found in ${typeParameterResolver::class.java}, $typeParameterResolver for ${targetComponents.target}")
}
}
@@ -141,36 +147,27 @@ internal fun CirSimpleType.buildType(
internal fun findClassOrTypeAlias(
targetComponents: TargetDeclarationsBuilderComponents,
fqName: FqName
classId: ClassId
): ClassifierDescriptorWithTypeParameters = when {
fqName.isUnderStandardKotlinPackages -> {
classId.packageFqName.isUnderStandardKotlinPackages -> {
// look up for classifier in built-ins module:
val builtInsModule = targetComponents.builtIns.builtInsModule
// TODO: this works fine for Native as far as built-ins module contains full Native stdlib, but this is not enough for JVM and JS
builtInsModule.resolveClassOrTypeAliasByFqName(fqName, NoLookupLocation.FOR_ALREADY_TRACKED)
?: error("Classifier $fqName not found in built-ins module $builtInsModule for ${targetComponents.target}")
builtInsModule.resolveClassOrTypeAlias(classId)
?: error("Classifier ${classId.asString()} not found in built-ins module $builtInsModule for ${targetComponents.target}")
}
else -> {
// otherwise, find the appropriate user classifier:
targetComponents.findAppropriateClassOrTypeAlias(fqName)
?: error("Classifier $fqName not found in created descriptors cache for ${targetComponents.target}")
targetComponents.findAppropriateClassOrTypeAlias(classId)
?: error("Classifier ${classId.asString()} not found in created descriptors cache for ${targetComponents.target}")
}
}
private fun checkClassifier(classifier: ClassifierDescriptor, kind: CirSimpleTypeKind, strict: Boolean) {
val classifierKind = classifier.cirSimpleTypeKind
if (strict) {
check(kind == classifierKind) {
"Mismatched classifier kinds.\nFound: $classifierKind, ${classifier::class.java}, $classifier\nShould be: $kind"
}
} else {
check(areCompatible(classifierKind, kind)) {
"Incompatible classifier kinds.\nExpect: $classifierKind, ${classifier::class.java}, $classifier\nActual: $kind"
}
}
private inline fun <reified T : ClassifierDescriptorWithTypeParameters> ClassifierDescriptorWithTypeParameters.checkClassifierType(): T {
check(this is T) { "Mismatched classifier kinds.\nFound: ${this::class.java}, $this\nShould be: ${T::class.java}" }
return this
}
private fun CirTypeProjection.buildArgument(
@@ -15,7 +15,7 @@ import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirClassConstructo
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirClassNode
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirNode.Companion.indexOfCommon
import org.jetbrains.kotlin.descriptors.commonizer.utils.CommonizedGroup
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.ClassId
internal fun CirClassNode.buildDescriptors(
components: GlobalDeclarationsBuilderComponents,
@@ -26,10 +26,10 @@ internal fun CirClassNode.buildDescriptors(
val markAsActual = commonClass != null && commonClass.kind != ClassKind.ENUM_ENTRY
targetDeclarations.forEachIndexed { index, clazz ->
clazz?.buildDescriptor(components, output, index, containingDeclarations, fqName, isActual = markAsActual)
clazz?.buildDescriptor(components, output, index, containingDeclarations, classId, isActual = markAsActual)
}
commonClass?.buildDescriptor(components, output, indexOfCommon, containingDeclarations, fqName, isExpect = true)
commonClass?.buildDescriptor(components, output, indexOfCommon, containingDeclarations, classId, isExpect = true)
// log stats
components.statsCollector?.logStats(output)
@@ -40,7 +40,7 @@ internal fun CirClass.buildDescriptor(
output: CommonizedGroup<in ClassifierDescriptorWithTypeParameters>,
index: Int,
containingDeclarations: List<DeclarationDescriptor?>,
fqName: FqName,
classId: ClassId,
isExpect: Boolean = false,
isActual: Boolean = false
) {
@@ -63,12 +63,12 @@ internal fun CirClass.buildDescriptor(
isExpect = isExpect,
isActual = isActual,
cirDeclaredTypeParameters = typeParameters,
companionObjectName = companion?.shortName(),
companionObjectName = companion,
cirSupertypes = supertypes
)
// cache created class descriptor:
components.cache.cache(fqName, index, classDescriptor)
components.cache.cache(classId, index, classDescriptor)
output[index] = classDescriptor
}
@@ -13,12 +13,12 @@ import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirNode.Companion.
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirNode.Companion.indexOfCommon
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirRootNode
import org.jetbrains.kotlin.descriptors.commonizer.stats.StatsCollector
import org.jetbrains.kotlin.descriptors.commonizer.utils.CommonizedGroup
import org.jetbrains.kotlin.descriptors.commonizer.utils.*
import org.jetbrains.kotlin.descriptors.commonizer.utils.CommonizedGroupMap
import org.jetbrains.kotlin.descriptors.commonizer.utils.createKotlinNativeForwardDeclarationsModule
import org.jetbrains.kotlin.descriptors.commonizer.utils.isUnderKotlinNativeSyntheticPackages
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.storage.StorageManager
@@ -33,8 +33,8 @@ class DeclarationsBuilderCache(private val dimension: Int) {
private val modules = CommonizedGroup<List<ModuleDescriptorImpl>>(dimension)
private val packageFragments = CommonizedGroupMap<Pair<Name, FqName>, CommonizedPackageFragmentDescriptor>(dimension)
private val classes = CommonizedGroupMap<FqName, CommonizedClassDescriptor>(dimension)
private val typeAliases = CommonizedGroupMap<FqName, CommonizedTypeAliasDescriptor>(dimension)
private val classes = CommonizedGroupMap<ClassId, CommonizedClassDescriptor>(dimension)
private val typeAliases = CommonizedGroupMap<ClassId, CommonizedTypeAliasDescriptor>(dimension)
private val forwardDeclarationsModules = CommonizedGroup<ModuleDescriptorImpl>(dimension)
private val allModulesWithDependencies = CommonizedGroup<List<ModuleDescriptor>>(dimension)
@@ -42,15 +42,15 @@ class DeclarationsBuilderCache(private val dimension: Int) {
fun getCachedPackageFragments(moduleName: Name, packageFqName: FqName): List<CommonizedPackageFragmentDescriptor?> =
packageFragments.getOrFail(moduleName to packageFqName)
fun getCachedClasses(fqName: FqName): List<CommonizedClassDescriptor?> = classes.getOrFail(fqName)
fun getCachedClasses(classId: ClassId): List<CommonizedClassDescriptor?> = classes.getOrFail(classId)
fun getCachedClassifier(fqName: FqName, index: Int): ClassifierDescriptorWithTypeParameters? {
fun getCachedClassifier(classId: ClassId, index: Int): ClassifierDescriptorWithTypeParameters? {
// first, look up for class
val classes: CommonizedGroup<CommonizedClassDescriptor>? = classes.getOrNull(fqName)
val classes: CommonizedGroup<CommonizedClassDescriptor>? = classes.getOrNull(classId)
classes?.get(index)?.let { return it }
// then, for type alias
val typeAliases: CommonizedGroup<CommonizedTypeAliasDescriptor>? = typeAliases.getOrNull(fqName)
val typeAliases: CommonizedGroup<CommonizedTypeAliasDescriptor>? = typeAliases.getOrNull(classId)
typeAliases?.get(index)?.let { return it }
val indexOfCommon = dimension - 1
@@ -73,12 +73,12 @@ class DeclarationsBuilderCache(private val dimension: Int) {
packageFragments[moduleName to packageFqName][index] = descriptor
}
fun cache(fqName: FqName, index: Int, descriptor: CommonizedClassDescriptor) {
classes[fqName][index] = descriptor
fun cache(classId: ClassId, index: Int, descriptor: CommonizedClassDescriptor) {
classes[classId][index] = descriptor
}
fun cache(fqName: FqName, index: Int, descriptor: CommonizedTypeAliasDescriptor) {
typeAliases[fqName][index] = descriptor
fun cache(classId: ClassId, index: Int, descriptor: CommonizedTypeAliasDescriptor) {
typeAliases[classId][index] = descriptor
}
fun getOrPutForwardDeclarationsModule(index: Int, computable: () -> ModuleDescriptorImpl): ModuleDescriptorImpl {
@@ -136,31 +136,21 @@ class TargetDeclarationsBuilderComponents(
private val cache: DeclarationsBuilderCache
) {
// N.B. this function may create new classifiers for types from Kotlin/Native forward declarations packages
fun findAppropriateClassOrTypeAlias(fqName: FqName): ClassifierDescriptorWithTypeParameters? {
fun findAppropriateClassOrTypeAlias(classId: ClassId): ClassifierDescriptorWithTypeParameters? {
return if (fqName.isUnderKotlinNativeSyntheticPackages) {
return if (classId.packageFqName.isUnderKotlinNativeSyntheticPackages) {
// that's a synthetic Kotlin/Native classifier that was exported as forward declaration in one or more modules,
// but did not match any existing class or typealias
val module = cache.getOrPutForwardDeclarationsModule(index) {
cache.getOrPutForwardDeclarationsModule(index) {
// N.B. forward declarations module is created only on demand
createKotlinNativeForwardDeclarationsModule(
storageManager = storageManager,
builtIns = builtIns
)
}
// create and return new classifier
module.packageFragmentProvider
.getPackageFragments(fqName.parent())
.single()
.getMemberScope()
.getContributedClassifier(
name = fqName.shortName(),
location = NoLookupLocation.FOR_ALREADY_TRACKED
) as ClassifierDescriptorWithTypeParameters
}.resolveClassOrTypeAlias(classId)
} else {
// look up in created descriptors cache
cache.getCachedClassifier(fqName, index)
cache.getCachedClassifier(classId, index)
}
}
}
@@ -13,7 +13,7 @@ import org.jetbrains.kotlin.descriptors.commonizer.cir.CirTypeAlias
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirTypeAliasNode
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirNode.Companion.indexOfCommon
import org.jetbrains.kotlin.descriptors.commonizer.utils.CommonizedGroup
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.ClassId
internal fun CirTypeAliasNode.buildDescriptors(
components: GlobalDeclarationsBuilderComponents,
@@ -29,14 +29,14 @@ internal fun CirTypeAliasNode.buildDescriptors(
if (!isLiftedUp) {
targetDeclarations.forEachIndexed { index, typeAlias ->
typeAlias?.buildDescriptor(components, output, index, containingDeclarations, fqName, isActual = markAsActual)
typeAlias?.buildDescriptor(components, output, index, containingDeclarations, classId, isActual = markAsActual)
}
}
if (commonTypeAlias != null) {
commonTypeAlias.buildDescriptor(components, output, indexOfCommon, containingDeclarations, fqName)
commonTypeAlias.buildDescriptor(components, output, indexOfCommon, containingDeclarations, classId)
} else if (commonClassifier != null && commonClassifier is CirClass) {
commonClassifier.buildDescriptor(components, output, indexOfCommon, containingDeclarations, fqName, isExpect = true)
commonClassifier.buildDescriptor(components, output, indexOfCommon, containingDeclarations, classId, isExpect = true)
}
// log stats
@@ -48,7 +48,7 @@ private fun CirTypeAlias.buildDescriptor(
output: CommonizedGroup<ClassifierDescriptorWithTypeParameters>,
index: Int,
containingDeclarations: List<DeclarationDescriptor?>,
fqName: FqName,
classId: ClassId,
isActual: Boolean = false
) {
val targetComponents = components.targetComponents[index]
@@ -77,7 +77,7 @@ private fun CirTypeAlias.buildDescriptor(
)
// cache created type alias descriptor:
components.cache.cache(fqName, index, typeAliasDescriptor)
components.cache.cache(classId, index, typeAliasDescriptor)
output[index] = typeAliasDescriptor
}
@@ -8,7 +8,8 @@ package org.jetbrains.kotlin.descriptors.commonizer.cir
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.constants.ConstantValue
interface CirAnnotation : CirHasFqName {
interface CirAnnotation {
val type: CirSimpleType
val constantValueArguments: Map<Name, ConstantValue<*>>
val annotationValueArguments: Map<Name, CirAnnotation>
}
@@ -6,11 +6,11 @@
package org.jetbrains.kotlin.descriptors.commonizer.cir
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
interface CirClass : CirClassifier, CirHasModality {
val kind: ClassKind
var companion: FqName? // null means no companion object
var companion: Name? // null means no companion object
val isCompanion: Boolean
val isData: Boolean
val isInline: Boolean
@@ -0,0 +1,19 @@
/*
* Copyright 2010-2020 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.descriptors.commonizer.cir
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name
sealed class CirClassifierId {
interface ClassOrTypeAlias {
val classId: ClassId
}
data class Class(override val classId: ClassId) : ClassOrTypeAlias, CirClassifierId()
data class TypeAlias(override val classId: ClassId) : ClassOrTypeAlias, CirClassifierId()
data class TypeParameter(val name: Name) : CirClassifierId()
}
@@ -5,8 +5,6 @@
package org.jetbrains.kotlin.descriptors.commonizer.cir
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirSimpleTypeKind.CLASS
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirSimpleTypeKind.TYPE_ALIAS
import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirTypeFactory
import org.jetbrains.kotlin.types.AbbreviatedType
import org.jetbrains.kotlin.types.Variance
@@ -26,24 +24,11 @@ sealed class CirType {
*
* Note: Annotations at simple types are not preserved. After commonization all annotations assigned to types will be lost.
*/
abstract class CirSimpleType : CirType(), CirHasVisibility, CirHasFqName {
abstract val kind: CirSimpleTypeKind
abstract class CirSimpleType : CirType(), CirHasVisibility {
abstract val classifierId: CirClassifierId
abstract val arguments: List<CirTypeProjection>
abstract val isMarkedNullable: Boolean
abstract val isDefinitelyNotNullType: Boolean
inline val isClassOrTypeAlias: Boolean get() = (kind == CLASS || kind == TYPE_ALIAS)
}
enum class CirSimpleTypeKind {
CLASS,
TYPE_ALIAS,
TYPE_PARAMETER;
companion object {
fun areCompatible(expect: CirSimpleTypeKind, actual: CirSimpleTypeKind): Boolean =
expect == actual || (expect == CLASS && actual == TYPE_ALIAS)
}
}
data class CirTypeProjection(val projectionKind: Variance, val isStarProjection: Boolean, val type: CirType)
@@ -8,11 +8,11 @@ package org.jetbrains.kotlin.descriptors.commonizer.cir.factory
import gnu.trove.THashMap
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirAnnotation
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirSimpleType
import org.jetbrains.kotlin.descriptors.commonizer.cir.impl.CirAnnotationImpl
import org.jetbrains.kotlin.descriptors.commonizer.utils.Interner
import org.jetbrains.kotlin.descriptors.commonizer.utils.checkConstantSupportedInCommonization
import org.jetbrains.kotlin.descriptors.commonizer.utils.intern
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.constants.AnnotationValue
import org.jetbrains.kotlin.resolve.constants.ConstantValue
@@ -21,11 +21,11 @@ object CirAnnotationFactory {
private val interner = Interner<CirAnnotation>()
fun create(source: AnnotationDescriptor): CirAnnotation {
val fqName: FqName = source.fqName?.intern() ?: error("Annotation with no FQ name: ${source::class.java}, $source")
val type = CirTypeFactory.create(source.type) as CirSimpleType
val allValueArguments: Map<Name, ConstantValue<*>> = source.allValueArguments
if (allValueArguments.isEmpty())
return create(fqName = fqName, constantValueArguments = emptyMap(), annotationValueArguments = emptyMap())
return create(type = type, constantValueArguments = emptyMap(), annotationValueArguments = emptyMap())
val constantValueArguments: MutableMap<Name, ConstantValue<*>> = THashMap()
val annotationValueArguments: MutableMap<Name, CirAnnotation> = THashMap()
@@ -45,20 +45,20 @@ object CirAnnotationFactory {
}
return create(
fqName = fqName,
type = type,
constantValueArguments = constantValueArguments,
annotationValueArguments = annotationValueArguments
)
}
fun create(
fqName: FqName,
type: CirSimpleType,
constantValueArguments: Map<Name, ConstantValue<*>>,
annotationValueArguments: Map<Name, CirAnnotation>
): CirAnnotation {
return interner.intern(
CirAnnotationImpl(
fqName = fqName,
type = type,
constantValueArguments = constantValueArguments,
annotationValueArguments = annotationValueArguments
)
@@ -15,9 +15,7 @@ import org.jetbrains.kotlin.descriptors.commonizer.cir.CirType
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirTypeParameter
import org.jetbrains.kotlin.descriptors.commonizer.cir.impl.CirClassImpl
import org.jetbrains.kotlin.descriptors.commonizer.utils.intern
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
object CirClassFactory {
fun create(source: ClassDescriptor): CirClass = create(
@@ -27,7 +25,7 @@ object CirClassFactory {
visibility = source.visibility,
modality = source.modality,
kind = source.kind,
companion = source.companionObjectDescriptor?.fqNameSafe?.intern(),
companion = source.companionObjectDescriptor?.name?.intern(),
isCompanion = source.isCompanionObject,
isData = source.isData,
isInline = source.isInline,
@@ -44,7 +42,7 @@ object CirClassFactory {
visibility: Visibility,
modality: Modality,
kind: ClassKind,
companion: FqName?,
companion: Name?,
isCompanion: Boolean,
isData: Boolean,
isInline: Boolean,
@@ -0,0 +1,30 @@
package org.jetbrains.kotlin.descriptors.commonizer.cir.factory
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
import org.jetbrains.kotlin.descriptors.TypeAliasDescriptor
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirClassifierId
import org.jetbrains.kotlin.descriptors.commonizer.utils.Interner
import org.jetbrains.kotlin.descriptors.commonizer.utils.intern
import org.jetbrains.kotlin.descriptors.commonizer.utils.internedClassId
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name
@Suppress("MemberVisibilityCanBePrivate")
object CirClassifierIdFactory {
private val interner = Interner<CirClassifierId>()
fun create(source: ClassifierDescriptor): CirClassifierId {
return when (source) {
is ClassDescriptor -> createForClass(source.internedClassId)
is TypeAliasDescriptor -> createForTypeAlias(source.internedClassId)
is TypeParameterDescriptor -> createForTypeParameter(source.name.intern())
else -> error("Unexpected classifier descriptor type: ${source::class.java}, $this")
}
}
fun createForClass(classId: ClassId): CirClassifierId = interner.intern(CirClassifierId.Class(classId))
fun createForTypeAlias(classId: ClassId): CirClassifierId = interner.intern(CirClassifierId.TypeAlias(classId))
fun createForTypeParameter(name: Name): CirClassifierId = interner.intern(CirClassifierId.TypeParameter(name))
}
@@ -7,7 +7,6 @@ package org.jetbrains.kotlin.descriptors.commonizer.cir.factory
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirPackage
import org.jetbrains.kotlin.descriptors.commonizer.cir.impl.CirPackageImpl
import org.jetbrains.kotlin.descriptors.commonizer.utils.intern
import org.jetbrains.kotlin.name.FqName
object CirPackageFactory {
@@ -5,13 +5,14 @@
package org.jetbrains.kotlin.descriptors.commonizer.cir.factory
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
import org.jetbrains.kotlin.descriptors.ClassifierDescriptorWithTypeParameters
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.descriptors.commonizer.cir.*
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirSimpleTypeKind.*
import org.jetbrains.kotlin.descriptors.commonizer.cir.impl.CirSimpleTypeImpl
import org.jetbrains.kotlin.descriptors.commonizer.utils.Interner
import org.jetbrains.kotlin.descriptors.commonizer.utils.declarationDescriptor
import org.jetbrains.kotlin.descriptors.commonizer.utils.fqNameInterned
import org.jetbrains.kotlin.descriptors.commonizer.utils.fqNameWithTypeParameters
import org.jetbrains.kotlin.types.*
@@ -29,10 +30,9 @@ object CirTypeFactory {
val abbreviation: SimpleType = (source as? AbbreviatedType)?.abbreviation ?: source
val classifierDescriptor: ClassifierDescriptor = abbreviation.declarationDescriptor
val simpleType = CirSimpleTypeImpl(
kind = classifierDescriptor.cirSimpleTypeKind,
return create(
classifierId = CirClassifierIdFactory.create(classifierDescriptor),
visibility = (classifierDescriptor as? ClassifierDescriptorWithTypeParameters)?.visibility ?: Visibilities.UNKNOWN,
fqName = abbreviation.fqNameInterned,
arguments = abbreviation.arguments.map { projection ->
CirTypeProjection(
projectionKind = projection.projectionKind,
@@ -44,15 +44,25 @@ object CirTypeFactory {
isDefinitelyNotNullType = abbreviation.isDefinitelyNotNullType,
fqNameWithTypeParameters = source.fqNameWithTypeParameters
)
}
return interner.intern(simpleType)
fun create(
classifierId: CirClassifierId,
visibility: Visibility,
arguments: List<CirTypeProjection>,
isMarkedNullable: Boolean,
isDefinitelyNotNullType: Boolean,
signature: CirTypeSignature
): CirSimpleType {
return interner.intern(
CirSimpleTypeImpl(
classifierId = classifierId,
visibility = visibility,
arguments = arguments,
isMarkedNullable = isMarkedNullable,
isDefinitelyNotNullType = isDefinitelyNotNullType,
signature = signature
)
)
}
}
val ClassifierDescriptor.cirSimpleTypeKind: CirSimpleTypeKind
get() = when (this) {
is ClassDescriptor -> CLASS
is TypeAliasDescriptor -> TYPE_ALIAS
is TypeParameterDescriptor -> TYPE_PARAMETER
else -> error("Unexpected classifier descriptor type: ${this::class.java}, $this")
}
@@ -6,21 +6,21 @@
package org.jetbrains.kotlin.descriptors.commonizer.cir.impl
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirAnnotation
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirSimpleType
import org.jetbrains.kotlin.descriptors.commonizer.utils.appendHashCode
import org.jetbrains.kotlin.descriptors.commonizer.utils.hashCode
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.constants.ConstantValue
data class CirAnnotationImpl(
override val fqName: FqName,
override val type: CirSimpleType,
override val constantValueArguments: Map<Name, ConstantValue<*>>,
override val annotationValueArguments: Map<Name, CirAnnotation>
) : CirAnnotation {
// See also org.jetbrains.kotlin.types.KotlinType.cachedHashCode
private var cachedHashCode = 0
private fun computeHashCode() = hashCode(fqName)
private fun computeHashCode() = hashCode(type)
.appendHashCode(constantValueArguments)
.appendHashCode(annotationValueArguments)
@@ -37,7 +37,7 @@ data class CirAnnotationImpl(
if (other === this) return true
return other is CirAnnotation
&& fqName == other.fqName
&& type == other.type
&& constantValueArguments == other.constantValueArguments
&& annotationValueArguments == other.annotationValueArguments
}
@@ -12,7 +12,6 @@ import org.jetbrains.kotlin.descriptors.commonizer.cir.CirAnnotation
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirClass
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirType
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirTypeParameter
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
data class CirClassImpl(
@@ -22,7 +21,7 @@ data class CirClassImpl(
override val visibility: Visibility,
override val modality: Modality,
override val kind: ClassKind,
override var companion: FqName?,
override var companion: Name?,
override val isCompanion: Boolean,
override val isData: Boolean,
override val isInline: Boolean,
@@ -6,17 +6,13 @@
package org.jetbrains.kotlin.descriptors.commonizer.cir.impl
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirSimpleType
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirSimpleTypeKind
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirTypeProjection
import org.jetbrains.kotlin.descriptors.commonizer.cir.*
import org.jetbrains.kotlin.descriptors.commonizer.utils.appendHashCode
import org.jetbrains.kotlin.descriptors.commonizer.utils.hashCode
import org.jetbrains.kotlin.name.FqName
data class CirSimpleTypeImpl(
override val kind: CirSimpleTypeKind,
override val classifierId: CirClassifierId,
override val visibility: Visibility, // visibility of the classifier descriptor
override val fqName: FqName,
override val arguments: List<CirTypeProjection>,
override val isMarkedNullable: Boolean,
override val isDefinitelyNotNullType: Boolean,
@@ -25,9 +21,8 @@ data class CirSimpleTypeImpl(
// See also org.jetbrains.kotlin.types.KotlinType.cachedHashCode
private var cachedHashCode = 0
private fun computeHashCode() = hashCode(kind)
private fun computeHashCode() = hashCode(classifierId)
.appendHashCode(visibility)
.appendHashCode(fqName)
.appendHashCode(arguments)
.appendHashCode(isMarkedNullable)
.appendHashCode(isDefinitelyNotNullType)
@@ -46,8 +41,7 @@ data class CirSimpleTypeImpl(
other === this -> true
other is CirSimpleType -> {
isMarkedNullable == other.isMarkedNullable
&& fqName == other.fqName
&& kind == other.kind
&& classifierId == other.classifierId
&& visibility == other.visibility
&& arguments == other.arguments
&& fqNameWithTypeParameters == other.fqNameWithTypeParameters
@@ -8,7 +8,7 @@ package org.jetbrains.kotlin.descriptors.commonizer.cir.impl
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirClass
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirClassifier
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirRecursionMarker
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
object CirClassRecursionMarker : CirClass, CirRecursionMarker {
override val annotations get() = unsupported()
@@ -17,7 +17,7 @@ object CirClassRecursionMarker : CirClass, CirRecursionMarker {
override val visibility get() = unsupported()
override val modality get() = unsupported()
override val kind get() = unsupported()
override var companion: FqName?
override var companion: Name?
get() = unsupported()
set(_) = unsupported()
override val isCompanion get() = unsupported()
@@ -5,10 +5,16 @@
package org.jetbrains.kotlin.descriptors.commonizer.core
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirAnnotation
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirClassifierId
import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirAnnotationFactory
import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirClassifierIdFactory
import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirTypeFactory
import org.jetbrains.kotlin.descriptors.commonizer.core.AnnotationsCommonizer.Companion.FALLBACK_MESSAGE
import org.jetbrains.kotlin.descriptors.commonizer.utils.DEPRECATED_ANNOTATION_FQN
import org.jetbrains.kotlin.descriptors.commonizer.utils.DEPRECATED_ANNOTATION_CID
import org.jetbrains.kotlin.descriptors.commonizer.utils.intern
import org.jetbrains.kotlin.descriptors.commonizer.utils.internedClassId
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
@@ -32,9 +38,13 @@ class AnnotationsCommonizer : AbstractStandardCommonizer<List<CirAnnotation>, Li
override fun initialize(first: List<CirAnnotation>) = Unit
override fun doCommonizeWith(next: List<CirAnnotation>): Boolean {
val nextDeprecatedAnnotation = next.firstOrNull { it.fqName == DEPRECATED_ANNOTATION_FQN } ?: return true
val nextDeprecatedAnnotation = next.firstOrNull { annotation ->
(annotation.type.classifierId as? CirClassifierId.ClassOrTypeAlias)?.classId == DEPRECATED_ANNOTATION_CID
} ?: return true
val deprecatedAnnotationCommonizer = deprecatedAnnotationCommonizer
?: DeprecatedAnnotationCommonizer().also { this.deprecatedAnnotationCommonizer = it }
return deprecatedAnnotationCommonizer.commonizeWith(nextDeprecatedAnnotation)
}
@@ -70,7 +80,7 @@ private class DeprecatedAnnotationCommonizer : Commonizer<CirAnnotation, CirAnno
mapOf(PROPERTY_NAME_REPLACE_WITH to replaceWithExpression.toReplaceWithValue(replaceWithImports))
return CirAnnotationFactory.create(
fqName = DEPRECATED_ANNOTATION_FQN,
type = DEPRECATED_ANNOTATION_TYPE,
constantValueArguments = constantValueArguments,
annotationValueArguments = annotationValueArguments
)
@@ -126,12 +136,12 @@ private class DeprecatedAnnotationCommonizer : Commonizer<CirAnnotation, CirAnno
@Suppress("NOTHING_TO_INLINE")
companion object {
private val PROPERTY_NAME_MESSAGE = Name.identifier(Deprecated::message.name)
private val PROPERTY_NAME_REPLACE_WITH = Name.identifier(Deprecated::replaceWith.name)
private val PROPERTY_NAME_LEVEL = Name.identifier(Deprecated::level.name)
private val PROPERTY_NAME_MESSAGE = Name.identifier(Deprecated::message.name).intern()
private val PROPERTY_NAME_REPLACE_WITH = Name.identifier(Deprecated::replaceWith.name).intern()
private val PROPERTY_NAME_LEVEL = Name.identifier(Deprecated::level.name).intern()
private val PROPERTY_NAME_EXPRESSION = Name.identifier(ReplaceWith::expression.name)
private val PROPERTY_NAME_IMPORTS = Name.identifier(ReplaceWith::imports.name)
private val PROPERTY_NAME_EXPRESSION = Name.identifier(ReplaceWith::expression.name).intern()
private val PROPERTY_NAME_IMPORTS = Name.identifier(ReplaceWith::imports.name).intern()
// Optimization: Keep most frequently used message constants.
private val FREQUENTLY_USED_MESSAGE_VALUES: Map<String, StringValue> = listOf(
@@ -140,15 +150,24 @@ private class DeprecatedAnnotationCommonizer : Commonizer<CirAnnotation, CirAnno
).associateWith { StringValue(it) }
private val FALLBACK_MESSAGE_VALUE = StringValue(FALLBACK_MESSAGE)
private val DEPRECATION_LEVEL_FQN = FqName(DeprecationLevel::class.java.name)
private val DEPRECATION_LEVEL_CLASS_ID = ClassId.topLevel(DEPRECATION_LEVEL_FQN)
private val DEPRECATED_ANNOTATION_TYPE = buildAnnotationType(DEPRECATED_ANNOTATION_CID)
private val REPLACE_WITH_ANNOTATION_TYPE = buildAnnotationType(internedClassId(FqName(ReplaceWith::class.java.name)))
private val DEPRECATION_LEVEL_CID = internedClassId(FqName(DeprecationLevel::class.java.name))
// Optimization: Keep DeprecationLevel enum constants.
private val DEPRECATION_LEVEL_ENUM_ENTRY_VALUES: Map<String, EnumValue> = DeprecationLevel.values().associate {
it.name to EnumValue(DEPRECATION_LEVEL_CLASS_ID, Name.identifier(it.name))
it.name to EnumValue(DEPRECATION_LEVEL_CID, Name.identifier(it.name).intern())
}
private val REPLACE_WITH_FQN = FqName(ReplaceWith::class.java.name)
private fun buildAnnotationType(classId: ClassId) = CirTypeFactory.create(
classifierId = CirClassifierIdFactory.createForClass(classId),
visibility = Visibilities.PUBLIC,
arguments = emptyList(),
isMarkedNullable = false,
isDefinitelyNotNullType = false,
signature = classId.asString()
)
private fun CirAnnotation.getDeprecationMessage(): String? = constantValueArguments.getString(PROPERTY_NAME_MESSAGE)
@@ -204,7 +223,7 @@ private class DeprecatedAnnotationCommonizer : Commonizer<CirAnnotation, CirAnno
private inline fun createReplaceWithAnnotation(expression: String, imports: List<String>): CirAnnotation =
CirAnnotationFactory.create(
fqName = REPLACE_WITH_FQN,
type = REPLACE_WITH_ANNOTATION_TYPE,
constantValueArguments = mapOf(
PROPERTY_NAME_EXPRESSION to StringValue(expression),
PROPERTY_NAME_IMPORTS to ArrayValue(
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.descriptors.commonizer.core
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirType
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.*
import org.jetbrains.kotlin.descriptors.commonizer.utils.CommonizedGroupMap
import org.jetbrains.kotlin.descriptors.commonizer.utils.internedClassId
internal class CommonizationVisitor(
private val root: CirRootNode
@@ -77,15 +78,16 @@ internal class CommonizationVisitor(
}
if (commonClass != null) {
// companion object should have the same FQ name for each target class, then it could be set to common class
val companionObjectFqName = node.targetDeclarations.mapTo(HashSet()) { it!!.companion }.singleOrNull()
if (companionObjectFqName != null) {
val companionObjectNode = root.cache.classes[companionObjectFqName]
?: error("Can't find companion object with FQ name $companionObjectFqName")
// companion object should have the same name for each target class, then it could be set to common class
val companionObjectName = node.targetDeclarations.mapTo(HashSet()) { it!!.companion }.singleOrNull()
if (companionObjectName != null) {
val companionObjectClassId = internedClassId(node.classId, companionObjectName)
val companionObjectNode = root.cache.classes[companionObjectClassId]
?: error("Can't find companion object with class ID $companionObjectClassId")
if (companionObjectNode.commonDeclaration() != null) {
// companion object has been successfully commonized
commonClass.companion = companionObjectFqName
commonClass.companion = companionObjectName
}
}
@@ -95,6 +95,6 @@ private class TypeAliasExpectClassCommonizer : AbstractStandardCommonizer<CirTyp
override fun doCommonizeWith(next: CirTypeAlias) =
next.typeParameters.isEmpty() // TAs with declared type parameters can't be commonized
&& next.underlyingType.arguments.isEmpty() // TAs with functional types or types with parameters at the right-hand side can't be commonized
&& next.underlyingType.kind == CirSimpleTypeKind.CLASS // right-hand side could have only class
&& next.underlyingType.classifierId is CirClassifierId.Class // right-hand side could have only class
&& classVisibility.commonizeWith(next.underlyingType) // the visibilities of the right-hand classes should be equal
}
@@ -5,10 +5,7 @@
package org.jetbrains.kotlin.descriptors.commonizer.core
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirFlexibleType
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirSimpleType
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirSimpleTypeKind
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirType
import org.jetbrains.kotlin.descriptors.commonizer.cir.*
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirClassifiersCache
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirNode
import org.jetbrains.kotlin.descriptors.commonizer.utils.isUnderStandardKotlinPackages
@@ -39,29 +36,42 @@ internal fun areTypesEqual(cache: CirClassifiersCache, a: CirType, b: CirType):
}
private fun areSimpleTypesEqual(cache: CirClassifiersCache, a: CirSimpleType, b: CirSimpleType): Boolean {
if (a !== b
&& (a.arguments.size != b.arguments.size
|| a.isMarkedNullable != b.isMarkedNullable
|| a.isDefinitelyNotNullType != b.isDefinitelyNotNullType
|| a.fqName != b.fqName)
) {
return false
val aId = a.classifierId
val bId = b.classifierId
if (a !== b) {
if (a.arguments.size != b.arguments.size
|| a.isMarkedNullable != b.isMarkedNullable
|| a.isDefinitelyNotNullType != b.isDefinitelyNotNullType
) {
return false
}
if (aId is CirClassifierId.ClassOrTypeAlias) {
if (bId !is CirClassifierId.ClassOrTypeAlias || aId.classId != bId.classId) return false
}
if (aId is CirClassifierId.TypeParameter) {
if (bId !is CirClassifierId.TypeParameter || aId.name != bId.name) return false
}
}
fun isClassOrTypeAliasUnderStandardKotlinPackages() =
// N.B. only for descriptors that represent classes or type aliases, but not type parameters!
a.isClassOrTypeAlias && b.isClassOrTypeAlias && a.fqName.isUnderStandardKotlinPackages
// N.B. only for descriptors that represent classes or type aliases, but not type parameters!
fun isClassOrTypeAliasUnderStandardKotlinPackages(): Boolean {
return (aId as? CirClassifierId.ClassOrTypeAlias)?.classId?.packageFqName?.isUnderStandardKotlinPackages == true
}
fun descriptorsCanBeCommonizedThemselves() =
a.kind == b.kind && when (a.kind) {
CirSimpleTypeKind.CLASS -> cache.classes[a.fqName].canBeCommonized()
CirSimpleTypeKind.TYPE_ALIAS -> cache.typeAliases[a.fqName].canBeCommonized()
CirSimpleTypeKind.TYPE_PARAMETER -> {
fun descriptorsCanBeCommonizedThemselves(): Boolean {
return when (aId) {
is CirClassifierId.Class -> bId is CirClassifierId.Class && cache.classes[aId.classId].canBeCommonized()
is CirClassifierId.TypeAlias -> bId is CirClassifierId.TypeAlias && cache.typeAliases[aId.classId].canBeCommonized()
is CirClassifierId.TypeParameter -> {
// Real type parameter commonization is performed in TypeParameterCommonizer.
// Here it is enough to check that FQ names are equal (which is already done above).
true
}
}
}
val descriptorsCanBeCommonized =
/* either class or type alias from Kotlin stdlib */ isClassOrTypeAliasUnderStandardKotlinPackages()
@@ -8,15 +8,15 @@ package org.jetbrains.kotlin.descriptors.commonizer.mergedtree
import gnu.trove.THashMap
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirClass
import org.jetbrains.kotlin.descriptors.commonizer.utils.CommonizedGroup
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.storage.NullableLazyValue
class CirClassNode(
override val targetDeclarations: CommonizedGroup<CirClass>,
override val commonDeclaration: NullableLazyValue<CirClass>,
override val fqName: FqName
) : CirNodeWithFqName<CirClass, CirClass> {
override val classId: ClassId
) : CirNodeWithClassId<CirClass, CirClass> {
val constructors: MutableMap<ConstructorApproximationKey, CirClassConstructorNode> = THashMap()
val properties: MutableMap<PropertyApproximationKey, CirPropertyNode> = THashMap()
@@ -5,9 +5,9 @@
package org.jetbrains.kotlin.descriptors.commonizer.mergedtree
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.ClassId
interface CirClassifiersCache {
val classes: Map<FqName, CirClassNode>
val typeAliases: Map<FqName, CirTypeAliasNode>
val classes: Map<ClassId, CirClassNode>
val typeAliases: Map<ClassId, CirTypeAliasNode>
}
@@ -24,7 +24,10 @@ interface CirNode<T : CirDeclaration, R : CirDeclaration> {
fun toString(node: CirNode<*, *>) = buildString {
if (node is CirNodeWithFqName) {
append("fqName=").append(node.fqName).append(", ")
append("fqName=").append(node.fqName.asString()).append(", ")
}
if (node is CirNodeWithClassId) {
append("classId=").append(node.classId.asString()).append(", ")
}
append("target=")
node.targetDeclarations.joinTo(this)
@@ -0,0 +1,13 @@
/*
* Copyright 2010-2020 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.descriptors.commonizer.mergedtree
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirDeclaration
import org.jetbrains.kotlin.name.ClassId
interface CirNodeWithClassId<T : CirDeclaration, R : CirDeclaration> : CirNode<T, R> {
val classId: ClassId
}
@@ -8,7 +8,7 @@ package org.jetbrains.kotlin.descriptors.commonizer.mergedtree
import gnu.trove.THashMap
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirRoot
import org.jetbrains.kotlin.descriptors.commonizer.utils.CommonizedGroup
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.storage.NullableLazyValue
@@ -17,8 +17,8 @@ class CirRootNode(
override val commonDeclaration: NullableLazyValue<CirRoot>
) : CirNode<CirRoot, CirRoot> {
class CirClassifiersCacheImpl : CirClassifiersCache {
override val classes = THashMap<FqName, CirClassNode>()
override val typeAliases = THashMap<FqName, CirTypeAliasNode>()
override val classes = THashMap<ClassId, CirClassNode>()
override val typeAliases = THashMap<ClassId, CirTypeAliasNode>()
}
val modules: MutableMap<Name, CirModuleNode> = THashMap()
@@ -14,9 +14,10 @@ import org.jetbrains.kotlin.descriptors.commonizer.cir.CirClass
import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.*
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirRootNode.CirClassifiersCacheImpl
import org.jetbrains.kotlin.descriptors.commonizer.utils.intern
import org.jetbrains.kotlin.descriptors.commonizer.utils.internedClassId
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.storage.NullableLazyValue
import org.jetbrains.kotlin.storage.StorageManager
@@ -115,10 +116,20 @@ class CirTreeMerger(
val typeAliases: MutableMap<Name, CirTypeAliasNode> = packageNode.typeAliases
packageMemberScope.collectMembers(
PropertyCollector { processProperty(properties, targetIndex, it, null) },
FunctionCollector { processFunction(functions, targetIndex, it, null) },
ClassCollector { processClass(classes, targetIndex, it, null) },
TypeAliasCollector { processTypeAlias(typeAliases, targetIndex, it) }
PropertyCollector { propertyDescriptor ->
processProperty(properties, targetIndex, propertyDescriptor, null)
},
FunctionCollector { functionDescriptor ->
processFunction(functions, targetIndex, functionDescriptor, null)
},
ClassCollector { classDescriptor ->
processClass(classes, targetIndex, classDescriptor, null) { className ->
internedClassId(packageFqName, className)
}
},
TypeAliasCollector { typeAliasDescriptor ->
processTypeAlias(typeAliases, targetIndex, typeAliasDescriptor, packageFqName)
}
)
}
@@ -150,10 +161,14 @@ class CirTreeMerger(
classes: MutableMap<Name, CirClassNode>,
targetIndex: Int,
classDescriptor: ClassDescriptor,
parentCommonDeclaration: NullableLazyValue<*>?
parentCommonDeclaration: NullableLazyValue<*>?,
classIdFunction: (Name) -> ClassId
) {
val classNode: CirClassNode = classes.getOrPut(classDescriptor.name.intern()) {
buildClassNode(storageManager, size, cacheRW, parentCommonDeclaration, classDescriptor.fqNameSafe.intern())
val className = classDescriptor.name.intern()
val classId = classIdFunction(className)
val classNode: CirClassNode = classes.getOrPut(className) {
buildClassNode(storageManager, size, cacheRW, parentCommonDeclaration, classId)
}
classNode.targetDeclarations[targetIndex] = CirClassFactory.create(classDescriptor)
@@ -167,9 +182,17 @@ class CirTreeMerger(
classDescriptor.constructors.forEach { processClassConstructor(constructors, targetIndex, it, parentCommonDeclarationForMembers) }
classDescriptor.unsubstitutedMemberScope.collectMembers(
PropertyCollector { processProperty(properties, targetIndex, it, parentCommonDeclarationForMembers) },
FunctionCollector { processFunction(functions, targetIndex, it, parentCommonDeclarationForMembers) },
ClassCollector { processClass(nestedClasses, targetIndex, it, parentCommonDeclarationForMembers) }
PropertyCollector { propertyDescriptor ->
processProperty(properties, targetIndex, propertyDescriptor, parentCommonDeclarationForMembers)
},
FunctionCollector { functionDescriptor ->
processFunction(functions, targetIndex, functionDescriptor, parentCommonDeclarationForMembers)
},
ClassCollector { nestedClassDescriptor ->
processClass(nestedClasses, targetIndex, nestedClassDescriptor, parentCommonDeclarationForMembers) { nestedClassName ->
internedClassId(classId, nestedClassName)
}
}
)
}
@@ -188,10 +211,14 @@ class CirTreeMerger(
private fun processTypeAlias(
typeAliases: MutableMap<Name, CirTypeAliasNode>,
targetIndex: Int,
typeAliasDescriptor: TypeAliasDescriptor
typeAliasDescriptor: TypeAliasDescriptor,
packageFqName: FqName
) {
val typeAliasNode: CirTypeAliasNode = typeAliases.getOrPut(typeAliasDescriptor.name.intern()) {
buildTypeAliasNode(storageManager, size, cacheRW, typeAliasDescriptor.fqNameSafe.intern())
val typeAliasName = typeAliasDescriptor.name.intern()
val typeAliasClassId = internedClassId(packageFqName, typeAliasName)
val typeAliasNode: CirTypeAliasNode = typeAliases.getOrPut(typeAliasName) {
buildTypeAliasNode(storageManager, size, cacheRW, typeAliasClassId)
}
typeAliasNode.targetDeclarations[targetIndex] = CirTypeAliasFactory.create(typeAliasDescriptor)
}
@@ -8,14 +8,14 @@ package org.jetbrains.kotlin.descriptors.commonizer.mergedtree
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirClassifier
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirTypeAlias
import org.jetbrains.kotlin.descriptors.commonizer.utils.CommonizedGroup
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.storage.NullableLazyValue
class CirTypeAliasNode(
override val targetDeclarations: CommonizedGroup<CirTypeAlias>,
override val commonDeclaration: NullableLazyValue<CirClassifier>,
override val fqName: FqName
) : CirNodeWithFqName<CirTypeAlias, CirClassifier> {
override val classId: ClassId
) : CirNodeWithClassId<CirTypeAlias, CirClassifier> {
override fun <R, T> accept(visitor: CirNodeVisitor<R, T>, data: T): R =
visitor.visitTypeAliasNode(this, data)
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.descriptors.commonizer.cir.impl.CirClassifierRecursi
import org.jetbrains.kotlin.descriptors.commonizer.core.*
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirRootNode.CirClassifiersCacheImpl
import org.jetbrains.kotlin.descriptors.commonizer.utils.CommonizedGroup
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.storage.NullableLazyValue
@@ -81,7 +82,7 @@ internal fun buildClassNode(
size: Int,
cacheRW: CirClassifiersCacheImpl,
parentCommonDeclaration: NullableLazyValue<*>?,
fqName: FqName
classId: ClassId
): CirClassNode = buildNode(
storageManager = storageManager,
size = size,
@@ -89,8 +90,8 @@ internal fun buildClassNode(
commonizerProducer = { ClassCommonizer(cacheRW) },
recursionMarker = CirClassRecursionMarker,
nodeProducer = { targetDeclarations, commonDeclaration ->
CirClassNode(targetDeclarations, commonDeclaration, fqName).also {
cacheRW.classes[fqName] = it
CirClassNode(targetDeclarations, commonDeclaration, classId).also {
cacheRW.classes[classId] = it
}
}
)
@@ -112,15 +113,15 @@ internal fun buildTypeAliasNode(
storageManager: StorageManager,
size: Int,
cacheRW: CirClassifiersCacheImpl,
fqName: FqName
classId: ClassId
): CirTypeAliasNode = buildNode(
storageManager = storageManager,
size = size,
commonizerProducer = { TypeAliasCommonizer(cacheRW) },
recursionMarker = CirClassifierRecursionMarker,
nodeProducer = { targetDeclarations, commonDeclaration ->
CirTypeAliasNode(targetDeclarations, commonDeclaration, fqName).also {
cacheRW.typeAliases[fqName] = it
CirTypeAliasNode(targetDeclarations, commonDeclaration, classId).also {
cacheRW.typeAliases[classId] = it
}
}
)
@@ -6,10 +6,12 @@
package org.jetbrains.kotlin.descriptors.commonizer.utils
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.serialization.konan.impl.ForwardDeclarationsFqNames
internal val DEPRECATED_ANNOTATION_FQN: FqName = FqName(Deprecated::class.java.name)
internal val DEPRECATED_ANNOTATION_FQN: FqName = FqName(Deprecated::class.java.name).intern()
internal val DEPRECATED_ANNOTATION_CID: ClassId = internedClassId(DEPRECATED_ANNOTATION_FQN)
private val STANDARD_KOTLIN_PACKAGE_PREFIXES = listOf(
KotlinBuiltIns.BUILT_INS_PACKAGE_NAME.asString(),
@@ -0,0 +1,37 @@
/*
* Copyright 2010-2020 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.descriptors.commonizer.utils
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
internal fun FqName.intern(): FqName = fqNameInterner.intern(this)
internal fun Name.intern(): Name = nameInterner.intern(this)
@Suppress("NOTHING_TO_INLINE")
internal inline fun internedClassId(topLevelFqName: FqName): ClassId {
val packageFqName = topLevelFqName.parent().intern()
val className = topLevelFqName.shortName().intern()
return internedClassId(packageFqName, className)
}
internal fun internedClassId(packageFqName: FqName, classifierName: Name): ClassId {
val relativeClassName = FqName.topLevel(classifierName).intern()
return ClassId(packageFqName, relativeClassName, false).intern()
}
internal fun internedClassId(ownerClassId: ClassId, nestedClassName: Name): ClassId {
val relativeClassName = ownerClassId.relativeClassName.child(nestedClassName).intern()
return ClassId(ownerClassId.packageFqName, relativeClassName, ownerClassId.isLocal).intern()
}
@Suppress("NOTHING_TO_INLINE")
private inline fun ClassId.intern(): ClassId = classIdInterner.intern(this)
private val fqNameInterner = Interner<FqName>()
private val nameInterner = Interner<Name>()
private val classIdInterner = Interner<ClassId>()
@@ -11,11 +11,13 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassifierDescriptorWithTypeParameters
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.incremental.components.LookupLocation
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.konan.util.KlibMetadataFactories
import org.jetbrains.kotlin.library.metadata.NativeTypeTransformer
import org.jetbrains.kotlin.library.metadata.NullFlexibleTypeDeserializer
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.serialization.konan.impl.KlibResolvedModuleDescriptorsFactoryImpl
import org.jetbrains.kotlin.storage.StorageManager
@@ -33,20 +35,31 @@ internal fun createKotlinNativeForwardDeclarationsModule(
)
// similar to org.jetbrains.kotlin.descriptors.DescriptorUtilKt#resolveClassByFqName, but resolves also type aliases
internal fun ModuleDescriptor.resolveClassOrTypeAliasByFqName(
fqName: FqName,
lookupLocation: LookupLocation
): ClassifierDescriptorWithTypeParameters? {
if (fqName.isRoot) return null
internal fun ModuleDescriptor.resolveClassOrTypeAlias(classId: ClassId): ClassifierDescriptorWithTypeParameters? {
val relativeClassName: FqName = classId.relativeClassName
if (relativeClassName.isRoot)
return null
(getPackage(fqName.parent()).memberScope.getContributedClassifier(
fqName.shortName(),
lookupLocation
) as? ClassifierDescriptorWithTypeParameters)?.let { return it }
var memberScope: MemberScope = getPackage(classId.packageFqName).memberScope
return (resolveClassOrTypeAliasByFqName(fqName.parent(), lookupLocation) as? ClassDescriptor)
?.unsubstitutedInnerClassesScope
?.getContributedClassifier(fqName.shortName(), lookupLocation) as? ClassifierDescriptorWithTypeParameters
val classifierName = if ('.' in relativeClassName.asString()) {
// resolve member scope of the nested class
relativeClassName.pathSegments().reduce { first, second ->
memberScope = (memberScope.getContributedClassifier(
first,
NoLookupLocation.FOR_ALREADY_TRACKED
) as? ClassDescriptor)?.unsubstitutedMemberScope ?: return null
second
}
} else {
relativeClassName.shortName()
}
return memberScope.getContributedClassifier(
classifierName,
NoLookupLocation.FOR_ALREADY_TRACKED
) as? ClassifierDescriptorWithTypeParameters
}
internal val NativeFactories = KlibMetadataFactories(::KonanBuiltIns, NullFlexibleTypeDeserializer, NativeTypeTransformer())
@@ -5,21 +5,27 @@
package org.jetbrains.kotlin.descriptors.commonizer.utils
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.descriptors.ClassifierDescriptorWithTypeParameters
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
import org.jetbrains.kotlin.types.AbbreviatedType
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
internal inline val KotlinType.declarationDescriptor: ClassifierDescriptor
get() = (constructor.declarationDescriptor ?: error("No declaration descriptor found for $constructor"))
internal inline val KotlinType.fqNameInterned: FqName
get() = declarationDescriptor.fqNameSafe.intern()
internal fun FqName.intern(): FqName = fqNameInterner.intern(this)
internal fun Name.intern(): Name = nameInterner.intern(this)
internal val ClassifierDescriptorWithTypeParameters.internedClassId: ClassId
get() = when (val owner = containingDeclaration) {
is PackageFragmentDescriptor -> internedClassId(owner.fqName.intern(), name.intern())
is ClassDescriptor -> internedClassId(owner.internedClassId, name.intern())
else -> error("Unexpected containing declaration type for $this: ${owner::class}, $owner")
}
internal val KotlinType.fqNameWithTypeParameters: String
get() {
@@ -28,12 +34,10 @@ internal val KotlinType.fqNameWithTypeParameters: String
}
private fun StringBuilder.buildFqNameWithTypeParameters(type: KotlinType, exploredTypeParameters: MutableSet<KotlinType>) {
val abbreviation = (type as? AbbreviatedType)?.abbreviation ?: type
append(abbreviation.fqNameInterned)
val typeParameterDescriptor = TypeUtils.getTypeParameterDescriptorOrNull(type)
if (typeParameterDescriptor != null) {
// N.B this is type parameter type
append(typeParameterDescriptor.name.asString())
if (exploredTypeParameters.add(type.makeNotNullable())) { // print upper bounds once the first time when type parameter type is met
append(":[")
@@ -46,6 +50,8 @@ private fun StringBuilder.buildFqNameWithTypeParameters(type: KotlinType, explor
}
} else {
// N.B. this is classifier type
val abbreviation = (type as? AbbreviatedType)?.abbreviation ?: type
append(abbreviation.declarationDescriptor.classId!!.asString())
val arguments = type.arguments
if (arguments.isNotEmpty()) {
@@ -73,6 +79,3 @@ private fun StringBuilder.buildFqNameWithTypeParameters(type: KotlinType, explor
// dedicated to hold unique entries of "fqNameWithTypeParameters"
private val stringInterner = Interner<String>()
private val fqNameInterner = Interner<FqName>()
private val nameInterner = Interner<Name>()
@@ -6,7 +6,10 @@
package org.jetbrains.kotlin.descriptors.commonizer.core
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirAnnotation
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirSimpleType
import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirAnnotationFactory
import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirTypeFactory
import org.jetbrains.kotlin.descriptors.commonizer.utils.mockClassType
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
@@ -287,7 +290,7 @@ private fun mockAnnotation(
constantValueArguments: Map<Name, ConstantValue<*>> = emptyMap(),
annotationValueArguments: Map<Name, CirAnnotation> = emptyMap()
): CirAnnotation = CirAnnotationFactory.create(
fqName = FqName(fqName),
type = CirTypeFactory.create(mockClassType(fqName)) as CirSimpleType,
constantValueArguments = constantValueArguments,
annotationValueArguments = annotationValueArguments
)
@@ -16,7 +16,7 @@ import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.buildClassNode
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.buildTypeAliasNode
import org.jetbrains.kotlin.descriptors.commonizer.utils.mockClassType
import org.jetbrains.kotlin.descriptors.commonizer.utils.mockTAType
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
import org.jetbrains.kotlin.storage.LockBasedStorageManager
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.getAbbreviation
@@ -459,27 +459,26 @@ class TypeCommonizerTest : AbstractCommonizerTest<CirType, CirType>() {
val descriptor = (type.getAbbreviation() ?: type).constructor.declarationDescriptor
when (descriptor) {
is ClassDescriptor -> {
val fqName = descriptor.fqNameSafe
val node = cache.classes.getOrPut(fqName) {
val classId = descriptor.classId ?: error("No class ID for ${descriptor::class.java}, $descriptor")
val node = cache.classes.getOrPut(classId) {
buildClassNode(
storageManager = LockBasedStorageManager.NO_LOCKS,
size = variants.size,
cacheRW = cache,
parentCommonDeclaration = null,
fqName = fqName
classId = classId
)
}
node.targetDeclarations[index] = CirClassFactory.create(descriptor)
}
is TypeAliasDescriptor -> {
val fqName = descriptor.fqNameSafe
val node = cache.typeAliases.getOrPut(fqName) {
val classId = descriptor.classId ?: error("No class ID for ${descriptor::class.java}, $descriptor")
val node = cache.typeAliases.getOrPut(classId) {
buildTypeAliasNode(
storageManager = LockBasedStorageManager.NO_LOCKS,
size = variants.size,
cacheRW = cache,
fqName = fqName
classId = classId
)
}
node.targetDeclarations[index] = CirTypeAliasFactory.create(descriptor)
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.constants.AnnotationValue
import org.jetbrains.kotlin.resolve.constants.ConstantValue
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.types.KotlinType
@@ -484,10 +485,10 @@ internal class ComparingDeclarationsVisitor(
context.nextLevel("Unwrapped/unabbreviated type annotations")
)
val expectedFqName = expectedUnwrapped.fqNameInterned
val actualFqName = actualUnwrapped.fqNameInterned
val expectedId = expectedUnwrapped.declarationDescriptor.run { classId?.asString() ?: name.asString() }
val actualId = actualUnwrapped.declarationDescriptor.run { classId?.asString() ?: name.asString() }
context.assertEquals(expectedFqName, actualFqName, "type FQN")
context.assertEquals(expectedId, actualId, "type class ID / name")
val expectedArguments = expectedUnwrapped.arguments
val actualArguments = actualUnwrapped.arguments
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.descriptors.commonizer.builder.*
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirClassNode
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirClassifiersCache
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirTypeAliasNode
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.parentOrNull
import org.jetbrains.kotlin.resolve.scopes.MemberScope
@@ -120,8 +121,8 @@ private fun createPackageFragmentForClassifier(classifierFqName: FqName): Packag
}
internal val EMPTY_CLASSIFIERS_CACHE = object : CirClassifiersCache {
override val classes: Map<FqName, CirClassNode> get() = emptyMap()
override val typeAliases: Map<FqName, CirTypeAliasNode> get() = emptyMap()
override val classes: Map<ClassId, CirClassNode> get() = emptyMap()
override val typeAliases: Map<ClassId, CirTypeAliasNode> get() = emptyMap()
}
internal class MockBuiltInsProvider(private val builtIns: KotlinBuiltIns) : BuiltInsProvider {