mirror of
https://github.com/jlengrand/kotlin.git
synced 2026-03-28 08:31:30 +00:00
[FIR2IR] Extract separate classifier storage from declaration storage
This commit is contained in:
@@ -21,7 +21,6 @@ import org.jetbrains.kotlin.fir.references.FirThisReference
|
||||
import org.jetbrains.kotlin.fir.references.impl.FirPropertyFromParameterResolvedNamedReference
|
||||
import org.jetbrains.kotlin.fir.resolve.*
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.SyntheticPropertySymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.AccessorSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
@@ -70,28 +69,32 @@ class ConversionTypeContext internal constructor(
|
||||
}
|
||||
}
|
||||
|
||||
fun FirClassifierSymbol<*>.toIrSymbol(
|
||||
fun FirClassifierSymbol<*>.toSymbol(
|
||||
session: FirSession,
|
||||
declarationStorage: Fir2IrDeclarationStorage,
|
||||
classifierStorage: Fir2IrClassifierStorage,
|
||||
typeContext: ConversionTypeContext = ConversionTypeContext.DEFAULT
|
||||
): IrClassifierSymbol {
|
||||
return when (this) {
|
||||
is FirTypeParameterSymbol -> {
|
||||
declarationStorage.getIrTypeParameterSymbol(this, typeContext)
|
||||
classifierStorage.getIrTypeParameterSymbol(this, typeContext)
|
||||
}
|
||||
is FirTypeAliasSymbol -> {
|
||||
val typeAlias = fir
|
||||
val coneClassLikeType = (typeAlias.expandedTypeRef as FirResolvedTypeRef).type as ConeClassLikeType
|
||||
coneClassLikeType.lookupTag.toSymbol(session)!!.toIrSymbol(session, declarationStorage)
|
||||
coneClassLikeType.lookupTag.toSymbol(session)!!.toSymbol(session, classifierStorage)
|
||||
}
|
||||
is FirClassSymbol -> {
|
||||
declarationStorage.getIrClassSymbol(this)
|
||||
classifierStorage.getIrClassSymbol(this)
|
||||
}
|
||||
else -> throw AssertionError("Should not be here: $this")
|
||||
}
|
||||
}
|
||||
|
||||
fun FirReference.toSymbol(declarationStorage: Fir2IrDeclarationStorage): IrSymbol? {
|
||||
fun FirReference.toSymbol(
|
||||
session: FirSession,
|
||||
classifierStorage: Fir2IrClassifierStorage,
|
||||
declarationStorage: Fir2IrDeclarationStorage
|
||||
): IrSymbol? {
|
||||
return when (this) {
|
||||
is FirResolvedNamedReference -> {
|
||||
when (val resolvedSymbol = resolvedSymbol) {
|
||||
@@ -100,15 +103,18 @@ fun FirReference.toSymbol(declarationStorage: Fir2IrDeclarationStorage): IrSymbo
|
||||
resolvedSymbol.overriddenSymbol?.takeIf { it.callableId == resolvedSymbol.callableId } ?: resolvedSymbol
|
||||
originalCallableSymbol.toSymbol(declarationStorage)
|
||||
}
|
||||
is FirClassifierSymbol<*> -> {
|
||||
resolvedSymbol.toSymbol(session, classifierStorage)
|
||||
}
|
||||
else -> {
|
||||
resolvedSymbol.toSymbol(declarationStorage)
|
||||
throw AssertionError("Unknown symbol: $resolvedSymbol")
|
||||
}
|
||||
}
|
||||
}
|
||||
is FirThisReference -> {
|
||||
when (val boundSymbol = boundSymbol?.toSymbol(declarationStorage)) {
|
||||
is IrClassSymbol -> boundSymbol.owner.thisReceiver?.symbol
|
||||
is IrFunctionSymbol -> boundSymbol.owner.extensionReceiverParameter?.symbol
|
||||
when (val boundSymbol = boundSymbol) {
|
||||
is FirClassSymbol<*> -> classifierStorage.getIrClassSymbol(boundSymbol).owner.thisReceiver?.symbol
|
||||
is FirFunctionSymbol -> declarationStorage.getIrFunctionSymbol(boundSymbol).owner.extensionReceiverParameter?.symbol
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
@@ -116,10 +122,11 @@ fun FirReference.toSymbol(declarationStorage: Fir2IrDeclarationStorage): IrSymbo
|
||||
}
|
||||
}
|
||||
|
||||
private fun AbstractFirBasedSymbol<*>.toSymbol(declarationStorage: Fir2IrDeclarationStorage): IrSymbol? = when (this) {
|
||||
is FirClassSymbol -> declarationStorage.getIrClassSymbol(this)
|
||||
private fun FirCallableSymbol<*>.toSymbol(declarationStorage: Fir2IrDeclarationStorage): IrSymbol? = when (this) {
|
||||
is FirFunctionSymbol<*> -> declarationStorage.getIrFunctionSymbol(this)
|
||||
is FirPropertySymbol -> if (fir.isLocal) declarationStorage.getIrValueSymbol(this) else declarationStorage.getIrPropertyOrFieldSymbol(this)
|
||||
is FirPropertySymbol -> {
|
||||
if (fir.isLocal) declarationStorage.getIrValueSymbol(this) else declarationStorage.getIrPropertyOrFieldSymbol(this)
|
||||
}
|
||||
is FirFieldSymbol -> declarationStorage.getIrPropertyOrFieldSymbol(this)
|
||||
is FirBackingFieldSymbol -> declarationStorage.getIrBackingFieldSymbol(this)
|
||||
is FirDelegateFieldSymbol<*> -> declarationStorage.getIrBackingFieldSymbol(this)
|
||||
|
||||
@@ -0,0 +1,364 @@
|
||||
/*
|
||||
* 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.fir.backend
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.resolve.firProvider
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrClassImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrEnumEntryImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrTypeParameterImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
|
||||
import org.jetbrains.kotlin.ir.descriptors.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrEnumConstructorCallImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBodyImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
|
||||
import org.jetbrains.kotlin.ir.util.SymbolTable
|
||||
import org.jetbrains.kotlin.ir.util.constructors
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
class Fir2IrClassifierStorage(
|
||||
session: FirSession,
|
||||
private val irSymbolTable: SymbolTable
|
||||
) {
|
||||
private val firProvider = session.firProvider
|
||||
|
||||
private val classCache = mutableMapOf<FirRegularClass, IrClass>()
|
||||
|
||||
private val typeParameterCache = mutableMapOf<FirTypeParameter, IrTypeParameter>()
|
||||
|
||||
private val typeParameterCacheForSetter = mutableMapOf<FirTypeParameter, IrTypeParameter>()
|
||||
|
||||
private val enumEntryCache = mutableMapOf<FirEnumEntry, IrEnumEntry>()
|
||||
|
||||
private val localStorage = Fir2IrLocalStorage()
|
||||
|
||||
lateinit var typeConverter: Fir2IrTypeConverter
|
||||
|
||||
lateinit var declarationStorage: Fir2IrDeclarationStorage
|
||||
|
||||
private fun FirTypeRef.toIrType(typeContext: ConversionTypeContext = ConversionTypeContext.DEFAULT): IrType =
|
||||
with(typeConverter) { toIrType(typeContext) }
|
||||
|
||||
internal fun IrDeclaration.declareThisReceiverParameter(
|
||||
parent: IrDeclarationParent,
|
||||
thisType: IrType,
|
||||
thisOrigin: IrDeclarationOrigin,
|
||||
startOffset: Int = this.startOffset,
|
||||
endOffset: Int = this.endOffset
|
||||
): IrValueParameter {
|
||||
val receiverDescriptor = WrappedReceiverParameterDescriptor()
|
||||
return irSymbolTable.declareValueParameter(
|
||||
startOffset, endOffset, thisOrigin, receiverDescriptor, thisType
|
||||
) { symbol ->
|
||||
IrValueParameterImpl(
|
||||
startOffset, endOffset, thisOrigin, symbol,
|
||||
Name.special("<this>"), -1, thisType,
|
||||
varargElementType = null, isCrossinline = false, isNoinline = false
|
||||
).apply {
|
||||
this.parent = parent
|
||||
receiverDescriptor.bind(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrClass.setThisReceiver() {
|
||||
irSymbolTable.enterScope(descriptor)
|
||||
val typeArguments = this.typeParameters.map {
|
||||
IrSimpleTypeImpl(it.symbol, false, emptyList(), emptyList())
|
||||
}
|
||||
thisReceiver = declareThisReceiverParameter(
|
||||
parent = this,
|
||||
thisType = IrSimpleTypeImpl(symbol, false, typeArguments, emptyList()),
|
||||
thisOrigin = IrDeclarationOrigin.INSTANCE_RECEIVER
|
||||
)
|
||||
irSymbolTable.leaveScope(descriptor)
|
||||
}
|
||||
|
||||
internal fun preCacheTypeParameters(owner: FirTypeParametersOwner) {
|
||||
owner.typeParameters.mapIndexed { index, typeParameter ->
|
||||
getIrTypeParameter(typeParameter, index)
|
||||
if (owner is FirProperty && owner.isVar) {
|
||||
getIrTypeParameter(typeParameter, index, ConversionTypeContext.DEFAULT.inSetter())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal fun IrTypeParametersContainer.setTypeParameters(
|
||||
owner: FirTypeParametersOwner,
|
||||
typeContext: ConversionTypeContext = ConversionTypeContext.DEFAULT
|
||||
) {
|
||||
typeParameters = owner.typeParameters.mapIndexed { index, typeParameter ->
|
||||
getIrTypeParameter(typeParameter, index, typeContext).apply { parent = this@setTypeParameters }
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrClass.declareSupertypesAndTypeParameters(klass: FirClass<*>): IrClass {
|
||||
if (klass is FirRegularClass) {
|
||||
setTypeParameters(klass)
|
||||
}
|
||||
superTypes = klass.superTypeRefs.map { superTypeRef -> superTypeRef.toIrType() }
|
||||
return this
|
||||
}
|
||||
|
||||
fun getCachedIrClass(klass: FirClass<*>): IrClass? {
|
||||
return if (klass is FirAnonymousObject || klass is FirRegularClass && klass.visibility == Visibilities.LOCAL) {
|
||||
localStorage.getLocalClass(klass)
|
||||
} else {
|
||||
classCache[klass]
|
||||
}
|
||||
}
|
||||
|
||||
private fun FirRegularClass.enumClassModality(): Modality {
|
||||
return when {
|
||||
declarations.any { it is FirCallableMemberDeclaration<*> && it.modality == Modality.ABSTRACT } -> {
|
||||
Modality.ABSTRACT
|
||||
}
|
||||
declarations.any { it is FirEnumEntry && it.initializer != null } -> {
|
||||
Modality.OPEN
|
||||
}
|
||||
else -> {
|
||||
Modality.FINAL
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal fun createIrClass(klass: FirClass<*>, parent: IrDeclarationParent? = null): IrClass {
|
||||
// NB: klass can be either FirRegularClass or FirAnonymousObject
|
||||
if (klass is FirAnonymousObject) {
|
||||
return createIrAnonymousObject(klass, irParent = parent)
|
||||
}
|
||||
val regularClass = klass as FirRegularClass
|
||||
val origin =
|
||||
if (firProvider.getFirClassifierContainerFileIfAny(klass.symbol) != null) IrDeclarationOrigin.DEFINED
|
||||
else IrDeclarationOrigin.IR_EXTERNAL_DECLARATION_STUB
|
||||
val irClass = registerIrClass(regularClass, parent, origin)
|
||||
processClassHeader(regularClass, irClass)
|
||||
return irClass
|
||||
}
|
||||
|
||||
fun processClassHeader(regularClass: FirRegularClass, irClass: IrClass = getCachedIrClass(regularClass)!!): IrClass {
|
||||
irClass.declareSupertypesAndTypeParameters(regularClass)
|
||||
irClass.setThisReceiver()
|
||||
return irClass
|
||||
}
|
||||
|
||||
fun registerIrClass(
|
||||
regularClass: FirRegularClass,
|
||||
parent: IrDeclarationParent? = null,
|
||||
origin: IrDeclarationOrigin = IrDeclarationOrigin.DEFINED
|
||||
): IrClass {
|
||||
val descriptor = WrappedClassDescriptor()
|
||||
val visibility = regularClass.visibility
|
||||
val modality = if (regularClass.classKind == ClassKind.ENUM_CLASS) {
|
||||
regularClass.enumClassModality()
|
||||
} else {
|
||||
regularClass.modality ?: Modality.FINAL
|
||||
}
|
||||
val irClass = regularClass.convertWithOffsets { startOffset, endOffset ->
|
||||
irSymbolTable.declareClass(startOffset, endOffset, origin, descriptor, modality, visibility) { symbol ->
|
||||
IrClassImpl(
|
||||
startOffset,
|
||||
endOffset,
|
||||
origin,
|
||||
symbol,
|
||||
regularClass.name,
|
||||
regularClass.classKind,
|
||||
visibility,
|
||||
modality,
|
||||
isCompanion = regularClass.isCompanion,
|
||||
isInner = regularClass.isInner,
|
||||
isData = regularClass.isData,
|
||||
isExternal = regularClass.isExternal,
|
||||
isInline = regularClass.isInline,
|
||||
isExpect = regularClass.isExpect,
|
||||
isFun = false // TODO FirRegularClass.isFun
|
||||
).apply {
|
||||
descriptor.bind(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (parent != null) {
|
||||
irClass.parent = parent
|
||||
}
|
||||
if (regularClass.visibility == Visibilities.LOCAL) {
|
||||
localStorage.putLocalClass(regularClass, irClass)
|
||||
} else {
|
||||
classCache[regularClass] = irClass
|
||||
}
|
||||
return irClass
|
||||
}
|
||||
|
||||
fun createIrAnonymousObject(
|
||||
anonymousObject: FirAnonymousObject,
|
||||
visibility: Visibility = Visibilities.LOCAL,
|
||||
name: Name = Name.special("<no name provided>"),
|
||||
irParent: IrDeclarationParent? = null
|
||||
): IrClass {
|
||||
val descriptor = WrappedClassDescriptor()
|
||||
val origin = IrDeclarationOrigin.DEFINED
|
||||
val modality = Modality.FINAL
|
||||
val result = anonymousObject.convertWithOffsets { startOffset, endOffset ->
|
||||
irSymbolTable.declareClass(startOffset, endOffset, origin, descriptor, modality, visibility) { symbol ->
|
||||
IrClassImpl(
|
||||
startOffset, endOffset, origin, symbol, name,
|
||||
// NB: for unknown reason, IR uses 'CLASS' kind for simple anonymous objects
|
||||
anonymousObject.classKind.takeIf { it == ClassKind.ENUM_ENTRY } ?: ClassKind.CLASS,
|
||||
visibility, modality,
|
||||
isCompanion = false, isInner = false, isData = false,
|
||||
isExternal = false, isInline = false, isExpect = false, isFun = false
|
||||
).apply {
|
||||
descriptor.bind(this)
|
||||
setThisReceiver()
|
||||
if (irParent != null) {
|
||||
this.parent = irParent
|
||||
}
|
||||
}
|
||||
}
|
||||
}.declareSupertypesAndTypeParameters(anonymousObject)
|
||||
localStorage.putLocalClass(anonymousObject, result)
|
||||
return result
|
||||
}
|
||||
|
||||
private fun getIrAnonymousObjectForEnumEntry(anonymousObject: FirAnonymousObject, name: Name, irParent: IrClass?): IrClass {
|
||||
localStorage.getLocalClass(anonymousObject)?.let { return it }
|
||||
return createIrAnonymousObject(anonymousObject, Visibilities.PRIVATE, name, irParent)
|
||||
}
|
||||
|
||||
private fun getIrTypeParameter(
|
||||
typeParameter: FirTypeParameter,
|
||||
index: Int = -1,
|
||||
typeContext: ConversionTypeContext = ConversionTypeContext.DEFAULT
|
||||
): IrTypeParameter {
|
||||
// Here transformation is a bit difficult because one FIR property type parameter
|
||||
// can be transformed to two different type parameters: one for getter and another one for setter
|
||||
val simpleCachedParameter = typeParameterCache[typeParameter]
|
||||
if (simpleCachedParameter != null) {
|
||||
if (typeContext.origin != ConversionTypeOrigin.SETTER) {
|
||||
return simpleCachedParameter
|
||||
}
|
||||
if (index < 0) {
|
||||
val parent = simpleCachedParameter.parent
|
||||
if (parent !is IrSimpleFunction || parent.returnType == typeConverter.unitType) {
|
||||
return simpleCachedParameter
|
||||
}
|
||||
}
|
||||
}
|
||||
if (typeContext.origin == ConversionTypeOrigin.SETTER) {
|
||||
typeParameterCacheForSetter[typeParameter]?.let { return it }
|
||||
}
|
||||
return typeParameter.run {
|
||||
// Yet I don't want to enable this requirement because it breaks some tests
|
||||
// However, if we get here it *should* mean that type parameter index is given explicitly
|
||||
// At this moment (20.02.2020) this requirement breaks 11/355 Fir2IrText tests
|
||||
// require(index != -1)
|
||||
val descriptor = WrappedTypeParameterDescriptor()
|
||||
val origin = IrDeclarationOrigin.DEFINED
|
||||
val irTypeParameter =
|
||||
convertWithOffsets { startOffset, endOffset ->
|
||||
irSymbolTable.declareGlobalTypeParameter(startOffset, endOffset, origin, descriptor) { symbol ->
|
||||
IrTypeParameterImpl(
|
||||
startOffset, endOffset, origin, symbol,
|
||||
name, if (index < 0) 0 else index,
|
||||
isReified,
|
||||
variance
|
||||
).apply {
|
||||
descriptor.bind(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Cache the type parameter BEFORE processing its bounds/supertypes, to properly handle recursive type bounds.
|
||||
if (typeContext.origin == ConversionTypeOrigin.SETTER) {
|
||||
typeParameterCacheForSetter[typeParameter] = irTypeParameter
|
||||
} else {
|
||||
typeParameterCache[typeParameter] = irTypeParameter
|
||||
}
|
||||
bounds.mapTo(irTypeParameter.superTypes) { it.toIrType() }
|
||||
irTypeParameter
|
||||
}
|
||||
}
|
||||
|
||||
fun putEnumEntryClassInScope(enumEntry: FirEnumEntry, correspondingClass: IrClass) {
|
||||
localStorage.putLocalClass(enumEntry.initializer as FirAnonymousObject, correspondingClass)
|
||||
}
|
||||
|
||||
fun getCachedIrEnumEntry(enumEntry: FirEnumEntry): IrEnumEntry? = enumEntryCache[enumEntry]
|
||||
|
||||
fun createIrEnumEntry(
|
||||
enumEntry: FirEnumEntry,
|
||||
irParent: IrClass?,
|
||||
origin: IrDeclarationOrigin = IrDeclarationOrigin.DEFINED
|
||||
): IrEnumEntry {
|
||||
return enumEntry.convertWithOffsets { startOffset, endOffset ->
|
||||
val desc = WrappedEnumEntryDescriptor()
|
||||
declarationStorage.enterScope(desc)
|
||||
val result = irSymbolTable.declareEnumEntry(startOffset, endOffset, origin, desc) { symbol ->
|
||||
IrEnumEntryImpl(
|
||||
startOffset, endOffset, origin, symbol, enumEntry.name
|
||||
).apply {
|
||||
desc.bind(this)
|
||||
val irType = enumEntry.returnTypeRef.toIrType()
|
||||
if (irParent != null) {
|
||||
this.parent = irParent
|
||||
}
|
||||
val initializer = enumEntry.initializer
|
||||
if (initializer != null) {
|
||||
initializer as FirAnonymousObject
|
||||
val klass = getIrAnonymousObjectForEnumEntry(initializer, enumEntry.name, irParent)
|
||||
|
||||
this.correspondingClass = klass
|
||||
} else if (irParent != null) {
|
||||
this.initializerExpression = IrExpressionBodyImpl(
|
||||
IrEnumConstructorCallImpl(startOffset, endOffset, irType, irParent.constructors.first().symbol)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
declarationStorage.leaveScope(desc)
|
||||
enumEntryCache[enumEntry] = result
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
fun getIrClassSymbol(firClassSymbol: FirClassSymbol<*>): IrClassSymbol {
|
||||
val firClass = firClassSymbol.fir
|
||||
getCachedIrClass(firClass)?.let { return irSymbolTable.referenceClass(it.descriptor) }
|
||||
// TODO: remove all this code and change to unbound symbol creation
|
||||
val irClass = createIrClass(firClass)
|
||||
if (firClass is FirAnonymousObject || firClass is FirRegularClass && firClass.visibility == Visibilities.LOCAL) {
|
||||
return irSymbolTable.referenceClass(irClass.descriptor)
|
||||
}
|
||||
val classId = firClassSymbol.classId
|
||||
val parentId = classId.outerClassId
|
||||
val irParent = declarationStorage.findIrParent(classId.packageFqName, parentId, firClassSymbol)
|
||||
if (irParent != null) {
|
||||
irClass.parent = irParent
|
||||
}
|
||||
if (irParent is IrExternalPackageFragment) {
|
||||
declarationStorage.addDeclarationsToExternalClass(firClass as FirRegularClass, irClass)
|
||||
}
|
||||
|
||||
return irSymbolTable.referenceClass(irClass.descriptor)
|
||||
}
|
||||
|
||||
fun getIrTypeParameterSymbol(
|
||||
firTypeParameterSymbol: FirTypeParameterSymbol,
|
||||
typeContext: ConversionTypeContext
|
||||
): IrTypeParameterSymbol {
|
||||
// TODO: use cached type parameter here
|
||||
val irTypeParameter = getIrTypeParameter(firTypeParameterSymbol.fir, typeContext = typeContext)
|
||||
return irSymbolTable.referenceTypeParameter(irTypeParameter.descriptor)
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.psi2ir.PsiSourceManager
|
||||
class Fir2IrConverter(
|
||||
private val moduleDescriptor: FirModuleDescriptor,
|
||||
private val sourceManager: PsiSourceManager,
|
||||
private val classifierStorage: Fir2IrClassifierStorage,
|
||||
private val declarationStorage: Fir2IrDeclarationStorage
|
||||
) {
|
||||
|
||||
@@ -71,7 +72,7 @@ class Fir2IrConverter(
|
||||
|
||||
fun processAnonymousObjectMembers(
|
||||
anonymousObject: FirAnonymousObject,
|
||||
irClass: IrClass = declarationStorage.getCachedIrClass(anonymousObject)!!
|
||||
irClass: IrClass = classifierStorage.getCachedIrClass(anonymousObject)!!
|
||||
): IrClass {
|
||||
anonymousObject.getPrimaryConstructorIfAny()?.let {
|
||||
irClass.declarations += declarationStorage.createIrConstructor(it, irClass)
|
||||
@@ -89,7 +90,7 @@ class Fir2IrConverter(
|
||||
|
||||
private fun processClassMembers(
|
||||
regularClass: FirRegularClass,
|
||||
irClass: IrClass = declarationStorage.getCachedIrClass(regularClass)!!
|
||||
irClass: IrClass = classifierStorage.getCachedIrClass(regularClass)!!
|
||||
): IrClass {
|
||||
regularClass.getPrimaryConstructorIfAny()?.let {
|
||||
irClass.declarations += declarationStorage.createIrConstructor(it, irClass)
|
||||
@@ -102,7 +103,7 @@ class Fir2IrConverter(
|
||||
}
|
||||
|
||||
private fun registerClassAndNestedClasses(regularClass: FirRegularClass, parent: IrDeclarationParent): IrClass {
|
||||
val irClass = declarationStorage.registerIrClass(regularClass, parent)
|
||||
val irClass = classifierStorage.registerIrClass(regularClass, parent)
|
||||
regularClass.declarations.forEach {
|
||||
if (it is FirRegularClass) {
|
||||
registerClassAndNestedClasses(it, irClass)
|
||||
@@ -112,7 +113,7 @@ class Fir2IrConverter(
|
||||
}
|
||||
|
||||
private fun processClassAndNestedClassHeaders(regularClass: FirRegularClass) {
|
||||
declarationStorage.processClassHeader(regularClass)
|
||||
classifierStorage.processClassHeader(regularClass)
|
||||
regularClass.declarations.forEach {
|
||||
if (it is FirRegularClass) {
|
||||
processClassAndNestedClassHeaders(it)
|
||||
@@ -137,7 +138,7 @@ class Fir2IrConverter(
|
||||
null
|
||||
}
|
||||
is FirEnumEntry -> {
|
||||
declarationStorage.createIrEnumEntry(declaration, parent as IrClass)
|
||||
classifierStorage.createIrEnumEntry(declaration, parent as IrClass)
|
||||
}
|
||||
is FirAnonymousInitializer -> {
|
||||
declarationStorage.createIrAnonymousInitializer(declaration, parent as IrClass)
|
||||
@@ -169,12 +170,16 @@ class Fir2IrConverter(
|
||||
val builtIns = IrBuiltIns(moduleDescriptor.builtIns, typeTranslator, signaturer, symbolTable)
|
||||
val sourceManager = PsiSourceManager()
|
||||
val declarationStorage = Fir2IrDeclarationStorage(session, symbolTable, moduleDescriptor)
|
||||
val typeConverter = Fir2IrTypeConverter(session, declarationStorage, builtIns)
|
||||
val classifierStorage = Fir2IrClassifierStorage(session, symbolTable)
|
||||
val typeConverter = Fir2IrTypeConverter(session, classifierStorage, builtIns)
|
||||
declarationStorage.typeConverter = typeConverter
|
||||
classifierStorage.typeConverter = typeConverter
|
||||
declarationStorage.classifierStorage = classifierStorage
|
||||
classifierStorage.declarationStorage = declarationStorage
|
||||
typeConverter.initBuiltinTypes()
|
||||
val irFiles = mutableListOf<IrFile>()
|
||||
|
||||
val converter = Fir2IrConverter(moduleDescriptor, sourceManager, declarationStorage)
|
||||
val converter = Fir2IrConverter(moduleDescriptor, sourceManager, classifierStorage, declarationStorage)
|
||||
for (firFile in firFiles) {
|
||||
converter.registerFileAndClasses(firFile)
|
||||
}
|
||||
@@ -186,7 +191,7 @@ class Fir2IrConverter(
|
||||
}
|
||||
|
||||
val fir2irVisitor = Fir2IrVisitor(
|
||||
session, symbolTable, declarationStorage, converter, typeConverter, builtIns, fakeOverrideMode
|
||||
session, symbolTable, classifierStorage, declarationStorage, converter, typeConverter, builtIns, fakeOverrideMode
|
||||
)
|
||||
for (firFile in firFiles) {
|
||||
val irFile = firFile.accept(fir2irVisitor, null) as IrFile
|
||||
|
||||
@@ -5,7 +5,9 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.backend
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyGetter
|
||||
@@ -28,14 +30,11 @@ import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.*
|
||||
import org.jetbrains.kotlin.ir.descriptors.*
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrEnumConstructorCallImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrErrorExpressionImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBodyImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.*
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
|
||||
import org.jetbrains.kotlin.ir.util.SymbolTable
|
||||
import org.jetbrains.kotlin.ir.util.constructors
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
@@ -56,12 +55,6 @@ class Fir2IrDeclarationStorage(
|
||||
|
||||
private val fileCache = mutableMapOf<FirFile, IrFile>()
|
||||
|
||||
private val classCache = mutableMapOf<FirRegularClass, IrClass>()
|
||||
|
||||
private val typeParameterCache = mutableMapOf<FirTypeParameter, IrTypeParameter>()
|
||||
|
||||
private val typeParameterCacheForSetter = mutableMapOf<FirTypeParameter, IrTypeParameter>()
|
||||
|
||||
private val functionCache = mutableMapOf<FirFunction<*>, IrSimpleFunction>()
|
||||
|
||||
private val constructorCache = mutableMapOf<FirConstructor, IrConstructor>()
|
||||
@@ -72,12 +65,12 @@ class Fir2IrDeclarationStorage(
|
||||
|
||||
private val fieldCache = mutableMapOf<FirField, IrField>()
|
||||
|
||||
private val enumEntryCache = mutableMapOf<FirEnumEntry, IrEnumEntry>()
|
||||
|
||||
private val localStorage = Fir2IrLocalStorage()
|
||||
|
||||
lateinit var typeConverter: Fir2IrTypeConverter
|
||||
|
||||
lateinit var classifierStorage: Fir2IrClassifierStorage
|
||||
|
||||
fun registerFile(firFile: FirFile, irFile: IrFile) {
|
||||
fileCache[firFile] = irFile
|
||||
}
|
||||
@@ -121,68 +114,7 @@ class Fir2IrDeclarationStorage(
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrDeclaration.declareThisReceiverParameter(
|
||||
parent: IrDeclarationParent,
|
||||
thisType: IrType,
|
||||
thisOrigin: IrDeclarationOrigin,
|
||||
startOffset: Int = this.startOffset,
|
||||
endOffset: Int = this.endOffset
|
||||
): IrValueParameter {
|
||||
val receiverDescriptor = WrappedReceiverParameterDescriptor()
|
||||
return irSymbolTable.declareValueParameter(
|
||||
startOffset, endOffset, thisOrigin, receiverDescriptor, thisType
|
||||
) { symbol ->
|
||||
IrValueParameterImpl(
|
||||
startOffset, endOffset, thisOrigin, symbol,
|
||||
Name.special("<this>"), -1, thisType,
|
||||
varargElementType = null, isCrossinline = false, isNoinline = false
|
||||
).apply {
|
||||
this.parent = parent
|
||||
receiverDescriptor.bind(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrClass.setThisReceiver() {
|
||||
enterScope(descriptor)
|
||||
val typeArguments = this.typeParameters.map {
|
||||
IrSimpleTypeImpl(it.symbol, false, emptyList(), emptyList())
|
||||
}
|
||||
thisReceiver = declareThisReceiverParameter(
|
||||
parent = this,
|
||||
thisType = IrSimpleTypeImpl(symbol, false, typeArguments, emptyList()),
|
||||
thisOrigin = IrDeclarationOrigin.INSTANCE_RECEIVER
|
||||
)
|
||||
leaveScope(descriptor)
|
||||
}
|
||||
|
||||
private fun preCacheTypeParameters(owner: FirTypeParametersOwner) {
|
||||
owner.typeParameters.mapIndexed { index, typeParameter ->
|
||||
getIrTypeParameter(typeParameter, index)
|
||||
if (owner is FirProperty && owner.isVar) {
|
||||
getIrTypeParameter(typeParameter, index, ConversionTypeContext.DEFAULT.inSetter())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrTypeParametersContainer.setTypeParameters(
|
||||
owner: FirTypeParametersOwner,
|
||||
typeContext: ConversionTypeContext = ConversionTypeContext.DEFAULT
|
||||
) {
|
||||
typeParameters = owner.typeParameters.mapIndexed { index, typeParameter ->
|
||||
getIrTypeParameter(typeParameter, index, typeContext).apply { parent = this@setTypeParameters }
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrClass.declareSupertypesAndTypeParameters(klass: FirClass<*>): IrClass {
|
||||
if (klass is FirRegularClass) {
|
||||
setTypeParameters(klass)
|
||||
}
|
||||
superTypes = klass.superTypeRefs.map { superTypeRef -> superTypeRef.toIrType() }
|
||||
return this
|
||||
}
|
||||
|
||||
private fun addDeclarationsToExternalClass(regularClass: FirRegularClass, irClass: IrClass) {
|
||||
internal fun addDeclarationsToExternalClass(regularClass: FirRegularClass, irClass: IrClass) {
|
||||
if (regularClass.symbol.classId.packageFqName.startsWith(Name.identifier("kotlin"))) {
|
||||
// Note: yet this is necessary only for *Range / *Progression classes
|
||||
// due to BE optimizations (for lowering) that use their first / last / step members
|
||||
@@ -202,7 +134,7 @@ class Fir2IrDeclarationStorage(
|
||||
createIrConstructor(declaration, irClass)
|
||||
}
|
||||
is FirRegularClass -> {
|
||||
createIrClass(declaration, irClass)
|
||||
classifierStorage.createIrClass(declaration, irClass)
|
||||
}
|
||||
else -> continue
|
||||
}
|
||||
@@ -235,190 +167,12 @@ class Fir2IrDeclarationStorage(
|
||||
}
|
||||
}
|
||||
|
||||
fun getCachedIrClass(klass: FirClass<*>): IrClass? {
|
||||
return if (klass is FirAnonymousObject || klass is FirRegularClass && klass.visibility == Visibilities.LOCAL) {
|
||||
localStorage.getLocalClass(klass)
|
||||
} else {
|
||||
classCache[klass]
|
||||
}
|
||||
}
|
||||
|
||||
private fun FirRegularClass.enumClassModality(): Modality {
|
||||
return when {
|
||||
declarations.any { it is FirCallableMemberDeclaration<*> && it.modality == Modality.ABSTRACT } -> {
|
||||
Modality.ABSTRACT
|
||||
}
|
||||
declarations.any { it is FirEnumEntry && it.initializer != null } -> {
|
||||
Modality.OPEN
|
||||
}
|
||||
else -> {
|
||||
Modality.FINAL
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun createIrClass(klass: FirClass<*>, parent: IrDeclarationParent? = null): IrClass {
|
||||
// NB: klass can be either FirRegularClass or FirAnonymousObject
|
||||
if (klass is FirAnonymousObject) {
|
||||
return createIrAnonymousObject(klass, irParent = parent)
|
||||
}
|
||||
val regularClass = klass as FirRegularClass
|
||||
val origin =
|
||||
if (firProvider.getFirClassifierContainerFileIfAny(klass.symbol) != null) IrDeclarationOrigin.DEFINED
|
||||
else IrDeclarationOrigin.IR_EXTERNAL_DECLARATION_STUB
|
||||
val irClass = registerIrClass(regularClass, parent, origin)
|
||||
processClassHeader(regularClass, irClass)
|
||||
return irClass
|
||||
}
|
||||
|
||||
fun processClassHeader(regularClass: FirRegularClass, irClass: IrClass = getCachedIrClass(regularClass)!!): IrClass {
|
||||
irClass.declareSupertypesAndTypeParameters(regularClass)
|
||||
irClass.setThisReceiver()
|
||||
return irClass
|
||||
}
|
||||
|
||||
fun registerIrClass(
|
||||
regularClass: FirRegularClass,
|
||||
parent: IrDeclarationParent? = null,
|
||||
origin: IrDeclarationOrigin = IrDeclarationOrigin.DEFINED
|
||||
): IrClass {
|
||||
val descriptor = WrappedClassDescriptor()
|
||||
val visibility = regularClass.visibility
|
||||
val modality = if (regularClass.classKind == ClassKind.ENUM_CLASS) {
|
||||
regularClass.enumClassModality()
|
||||
} else {
|
||||
regularClass.modality ?: Modality.FINAL
|
||||
}
|
||||
val irClass = regularClass.convertWithOffsets { startOffset, endOffset ->
|
||||
irSymbolTable.declareClass(startOffset, endOffset, origin, descriptor, modality, visibility) { symbol ->
|
||||
IrClassImpl(
|
||||
startOffset,
|
||||
endOffset,
|
||||
origin,
|
||||
symbol,
|
||||
regularClass.name,
|
||||
regularClass.classKind,
|
||||
visibility,
|
||||
modality,
|
||||
isCompanion = regularClass.isCompanion,
|
||||
isInner = regularClass.isInner,
|
||||
isData = regularClass.isData,
|
||||
isExternal = regularClass.isExternal,
|
||||
isInline = regularClass.isInline,
|
||||
isExpect = regularClass.isExpect,
|
||||
isFun = false // TODO FirRegularClass.isFun
|
||||
).apply {
|
||||
descriptor.bind(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (parent != null) {
|
||||
irClass.parent = parent
|
||||
}
|
||||
if (regularClass.visibility == Visibilities.LOCAL) {
|
||||
localStorage.putLocalClass(regularClass, irClass)
|
||||
} else {
|
||||
classCache[regularClass] = irClass
|
||||
}
|
||||
return irClass
|
||||
}
|
||||
|
||||
fun createIrAnonymousObject(
|
||||
anonymousObject: FirAnonymousObject,
|
||||
visibility: Visibility = Visibilities.LOCAL,
|
||||
name: Name = Name.special("<no name provided>"),
|
||||
irParent: IrDeclarationParent? = null
|
||||
): IrClass {
|
||||
val descriptor = WrappedClassDescriptor()
|
||||
val origin = IrDeclarationOrigin.DEFINED
|
||||
val modality = Modality.FINAL
|
||||
val result = anonymousObject.convertWithOffsets { startOffset, endOffset ->
|
||||
irSymbolTable.declareClass(startOffset, endOffset, origin, descriptor, modality, visibility) { symbol ->
|
||||
IrClassImpl(
|
||||
startOffset, endOffset, origin, symbol, name,
|
||||
// NB: for unknown reason, IR uses 'CLASS' kind for simple anonymous objects
|
||||
anonymousObject.classKind.takeIf { it == ClassKind.ENUM_ENTRY } ?: ClassKind.CLASS,
|
||||
visibility, modality,
|
||||
isCompanion = false, isInner = false, isData = false,
|
||||
isExternal = false, isInline = false, isExpect = false, isFun = false
|
||||
).apply {
|
||||
descriptor.bind(this)
|
||||
setThisReceiver()
|
||||
if (irParent != null) {
|
||||
this.parent = irParent
|
||||
}
|
||||
}
|
||||
}
|
||||
}.declareSupertypesAndTypeParameters(anonymousObject)
|
||||
localStorage.putLocalClass(anonymousObject, result)
|
||||
return result
|
||||
}
|
||||
|
||||
private fun getIrAnonymousObjectForEnumEntry(anonymousObject: FirAnonymousObject, name: Name, irParent: IrClass?): IrClass {
|
||||
localStorage.getLocalClass(anonymousObject)?.let { return it }
|
||||
return createIrAnonymousObject(anonymousObject, Visibilities.PRIVATE, name, irParent)
|
||||
}
|
||||
|
||||
private fun getIrTypeParameter(
|
||||
typeParameter: FirTypeParameter,
|
||||
index: Int = -1,
|
||||
typeContext: ConversionTypeContext = ConversionTypeContext.DEFAULT
|
||||
): IrTypeParameter {
|
||||
// Here transformation is a bit difficult because one FIR property type parameter
|
||||
// can be transformed to two different type parameters: one for getter and another one for setter
|
||||
val simpleCachedParameter = typeParameterCache[typeParameter]
|
||||
if (simpleCachedParameter != null) {
|
||||
if (typeContext.origin != ConversionTypeOrigin.SETTER) {
|
||||
return simpleCachedParameter
|
||||
}
|
||||
if (index < 0) {
|
||||
val parent = simpleCachedParameter.parent
|
||||
if (parent !is IrSimpleFunction || parent.returnType == typeConverter.unitType) {
|
||||
return simpleCachedParameter
|
||||
}
|
||||
}
|
||||
}
|
||||
if (typeContext.origin == ConversionTypeOrigin.SETTER) {
|
||||
typeParameterCacheForSetter[typeParameter]?.let { return it }
|
||||
}
|
||||
return typeParameter.run {
|
||||
// Yet I don't want to enable this requirement because it breaks some tests
|
||||
// However, if we get here it *should* mean that type parameter index is given explicitly
|
||||
// At this moment (20.02.2020) this requirement breaks 11/355 Fir2IrText tests
|
||||
// require(index != -1)
|
||||
val descriptor = WrappedTypeParameterDescriptor()
|
||||
val origin = IrDeclarationOrigin.DEFINED
|
||||
val irTypeParameter =
|
||||
convertWithOffsets { startOffset, endOffset ->
|
||||
irSymbolTable.declareGlobalTypeParameter(startOffset, endOffset, origin, descriptor) { symbol ->
|
||||
IrTypeParameterImpl(
|
||||
startOffset, endOffset, origin, symbol,
|
||||
name, if (index < 0) 0 else index,
|
||||
isReified,
|
||||
variance
|
||||
).apply {
|
||||
descriptor.bind(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Cache the type parameter BEFORE processing its bounds/supertypes, to properly handle recursive type bounds.
|
||||
if (typeContext.origin == ConversionTypeOrigin.SETTER) {
|
||||
typeParameterCacheForSetter[typeParameter] = irTypeParameter
|
||||
} else {
|
||||
typeParameterCache[typeParameter] = irTypeParameter
|
||||
}
|
||||
bounds.mapTo(irTypeParameter.superTypes) { it.toIrType() }
|
||||
irTypeParameter
|
||||
}
|
||||
}
|
||||
|
||||
private fun findIrParent(packageFqName: FqName, parentClassId: ClassId?, firBasedSymbol: FirBasedSymbol<*>): IrDeclarationParent? {
|
||||
internal fun findIrParent(packageFqName: FqName, parentClassId: ClassId?, firBasedSymbol: FirBasedSymbol<*>): IrDeclarationParent? {
|
||||
return if (parentClassId != null) {
|
||||
// TODO: this will never work for local classes
|
||||
val parentFirSymbol = firSymbolProvider.getClassLikeSymbolByFqName(parentClassId)
|
||||
if (parentFirSymbol is FirClassSymbol) {
|
||||
val parentIrSymbol = getIrClassSymbol(parentFirSymbol)
|
||||
val parentIrSymbol = classifierStorage.getIrClassSymbol(parentFirSymbol)
|
||||
parentIrSymbol.owner
|
||||
} else {
|
||||
null
|
||||
@@ -485,7 +239,9 @@ class Fir2IrDeclarationStorage(
|
||||
) {
|
||||
val parent = this
|
||||
if (function is FirSimpleFunction) {
|
||||
setTypeParameters(function)
|
||||
with(classifierStorage) {
|
||||
setTypeParameters(function)
|
||||
}
|
||||
}
|
||||
val forSetter = function is FirPropertyAccessor && function.isSetter
|
||||
val typeContext = ConversionTypeContext(
|
||||
@@ -509,24 +265,26 @@ class Fir2IrDeclarationStorage(
|
||||
if (function !is FirConstructor) {
|
||||
val thisOrigin = IrDeclarationOrigin.DEFINED
|
||||
val receiverTypeRef = if (function !is FirPropertyAccessor) function?.receiverTypeRef else parentPropertyReceiverType
|
||||
if (receiverTypeRef != null) {
|
||||
extensionReceiverParameter = receiverTypeRef.convertWithOffsets { startOffset, endOffset ->
|
||||
declareThisReceiverParameter(
|
||||
with(classifierStorage) {
|
||||
if (receiverTypeRef != null) {
|
||||
extensionReceiverParameter = receiverTypeRef.convertWithOffsets { startOffset, endOffset ->
|
||||
declareThisReceiverParameter(
|
||||
parent,
|
||||
thisType = receiverTypeRef.toIrType(typeContext),
|
||||
thisOrigin = thisOrigin,
|
||||
startOffset = startOffset,
|
||||
endOffset = endOffset
|
||||
)
|
||||
}
|
||||
}
|
||||
if (function !is FirAnonymousFunction && containingClass != null && !isStatic) {
|
||||
dispatchReceiverParameter = declareThisReceiverParameter(
|
||||
parent,
|
||||
thisType = receiverTypeRef.toIrType(typeContext),
|
||||
thisOrigin = thisOrigin,
|
||||
startOffset = startOffset,
|
||||
endOffset = endOffset
|
||||
thisType = containingClass.thisReceiver!!.type,
|
||||
thisOrigin = thisOrigin
|
||||
)
|
||||
}
|
||||
}
|
||||
if (function !is FirAnonymousFunction && containingClass != null && !isStatic) {
|
||||
dispatchReceiverParameter = declareThisReceiverParameter(
|
||||
parent,
|
||||
thisType = containingClass.thisReceiver!!.type,
|
||||
thisOrigin = thisOrigin
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -552,10 +310,6 @@ class Fir2IrDeclarationStorage(
|
||||
return this
|
||||
}
|
||||
|
||||
fun putEnumEntryClassInScope(enumEntry: FirEnumEntry, correspondingClass: IrClass) {
|
||||
localStorage.putLocalClass(enumEntry.initializer as FirAnonymousObject, correspondingClass)
|
||||
}
|
||||
|
||||
fun getCachedIrFunction(function: FirFunction<*>): IrSimpleFunction? {
|
||||
return if (function !is FirSimpleFunction || function.visibility == Visibilities.LOCAL) {
|
||||
localStorage.getLocalFunction(function)
|
||||
@@ -578,7 +332,7 @@ class Fir2IrDeclarationStorage(
|
||||
function.symbol.callableId.isKFunctionInvoke() -> IrDeclarationOrigin.FAKE_OVERRIDE
|
||||
else -> origin
|
||||
}
|
||||
preCacheTypeParameters(function)
|
||||
classifierStorage.preCacheTypeParameters(function)
|
||||
val name = simpleFunction?.name
|
||||
?: if (isLambda) Name.special("<anonymous>") else Name.special("<no name provided>")
|
||||
val visibility = simpleFunction?.visibility ?: Visibilities.LOCAL
|
||||
@@ -694,12 +448,14 @@ class Fir2IrDeclarationStorage(
|
||||
isFakeOverride = origin == IrDeclarationOrigin.FAKE_OVERRIDE,
|
||||
isOperator = false
|
||||
).apply {
|
||||
setTypeParameters(
|
||||
property, ConversionTypeContext(
|
||||
definitelyNotNull = false,
|
||||
origin = if (isSetter) ConversionTypeOrigin.SETTER else ConversionTypeOrigin.DEFAULT
|
||||
with(classifierStorage) {
|
||||
setTypeParameters(
|
||||
property, ConversionTypeContext(
|
||||
definitelyNotNull = false,
|
||||
origin = if (isSetter) ConversionTypeOrigin.SETTER else ConversionTypeOrigin.DEFAULT
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
if (propertyAccessor == null && isSetter) {
|
||||
declareDefaultSetterParameter(
|
||||
property.returnTypeRef.toIrType(ConversionTypeContext.DEFAULT.inSetter())
|
||||
@@ -719,44 +475,6 @@ class Fir2IrDeclarationStorage(
|
||||
}
|
||||
}
|
||||
|
||||
fun getCachedIrEnumEntry(enumEntry: FirEnumEntry): IrEnumEntry? = enumEntryCache[enumEntry]
|
||||
|
||||
fun createIrEnumEntry(
|
||||
enumEntry: FirEnumEntry,
|
||||
irParent: IrClass?,
|
||||
origin: IrDeclarationOrigin = IrDeclarationOrigin.DEFINED
|
||||
): IrEnumEntry {
|
||||
return enumEntry.convertWithOffsets { startOffset, endOffset ->
|
||||
val desc = WrappedEnumEntryDescriptor()
|
||||
enterScope(desc)
|
||||
val result = irSymbolTable.declareEnumEntry(startOffset, endOffset, origin, desc) { symbol ->
|
||||
IrEnumEntryImpl(
|
||||
startOffset, endOffset, origin, symbol, enumEntry.name
|
||||
).apply {
|
||||
desc.bind(this)
|
||||
val irType = enumEntry.returnTypeRef.toIrType()
|
||||
if (irParent != null) {
|
||||
this.parent = irParent
|
||||
}
|
||||
val initializer = enumEntry.initializer
|
||||
if (initializer != null) {
|
||||
initializer as FirAnonymousObject
|
||||
val klass = getIrAnonymousObjectForEnumEntry(initializer, enumEntry.name, irParent)
|
||||
|
||||
this.correspondingClass = klass
|
||||
} else if (irParent != null) {
|
||||
this.initializerExpression = IrExpressionBodyImpl(
|
||||
IrEnumConstructorCallImpl(startOffset, endOffset, irType, irParent.constructors.first().symbol)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
leaveScope(desc)
|
||||
enumEntryCache[enumEntry] = result
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
fun createIrProperty(
|
||||
property: FirProperty,
|
||||
irParent: IrDeclarationParent?,
|
||||
@@ -764,7 +482,7 @@ class Fir2IrDeclarationStorage(
|
||||
): IrProperty {
|
||||
val containerSource = property.containerSource
|
||||
val descriptor = containerSource?.let { WrappedPropertyDescriptorWithContainerSource(it) } ?: WrappedPropertyDescriptor()
|
||||
preCacheTypeParameters(property)
|
||||
classifierStorage.preCacheTypeParameters(property)
|
||||
return property.convertWithOffsets { startOffset, endOffset ->
|
||||
enterScope(descriptor)
|
||||
val result = irSymbolTable.declareProperty(
|
||||
@@ -936,36 +654,6 @@ class Fir2IrDeclarationStorage(
|
||||
}
|
||||
}
|
||||
|
||||
fun getIrClassSymbol(firClassSymbol: FirClassSymbol<*>): IrClassSymbol {
|
||||
val firClass = firClassSymbol.fir
|
||||
getCachedIrClass(firClass)?.let { return irSymbolTable.referenceClass(it.descriptor) }
|
||||
// TODO: remove all this code and change to unbound symbol creation
|
||||
val irClass = createIrClass(firClass)
|
||||
if (firClass is FirAnonymousObject || firClass is FirRegularClass && firClass.visibility == Visibilities.LOCAL) {
|
||||
return irSymbolTable.referenceClass(irClass.descriptor)
|
||||
}
|
||||
val classId = firClassSymbol.classId
|
||||
val parentId = classId.outerClassId
|
||||
val irParent = findIrParent(classId.packageFqName, parentId, firClassSymbol)
|
||||
if (irParent != null) {
|
||||
irClass.parent = irParent
|
||||
}
|
||||
if (irParent is IrExternalPackageFragment) {
|
||||
addDeclarationsToExternalClass(firClass as FirRegularClass, irClass)
|
||||
}
|
||||
|
||||
return irSymbolTable.referenceClass(irClass.descriptor)
|
||||
}
|
||||
|
||||
fun getIrTypeParameterSymbol(
|
||||
firTypeParameterSymbol: FirTypeParameterSymbol,
|
||||
typeContext: ConversionTypeContext
|
||||
): IrTypeParameterSymbol {
|
||||
// TODO: use cached type parameter here
|
||||
val irTypeParameter = getIrTypeParameter(firTypeParameterSymbol.fir, typeContext = typeContext)
|
||||
return irSymbolTable.referenceTypeParameter(irTypeParameter.descriptor)
|
||||
}
|
||||
|
||||
fun getIrConstructorSymbol(firConstructorSymbol: FirConstructorSymbol): IrConstructorSymbol {
|
||||
val firConstructor = firConstructorSymbol.fir
|
||||
getCachedIrConstructor(firConstructor)?.let { return irSymbolTable.referenceConstructor(it.descriptor) }
|
||||
@@ -1043,11 +731,11 @@ class Fir2IrDeclarationStorage(
|
||||
fun getIrValueSymbol(firVariableSymbol: FirVariableSymbol<*>): IrSymbol {
|
||||
return when (val firDeclaration = firVariableSymbol.fir) {
|
||||
is FirEnumEntry -> {
|
||||
getCachedIrEnumEntry(firDeclaration)?.let { return irSymbolTable.referenceEnumEntry(it.descriptor) }
|
||||
classifierStorage.getCachedIrEnumEntry(firDeclaration)?.let { return irSymbolTable.referenceEnumEntry(it.descriptor) }
|
||||
val containingFile = firProvider.getFirCallableContainerFile(firVariableSymbol)
|
||||
val parentClassSymbol = firVariableSymbol.callableId.classId?.let { firSymbolProvider.getClassLikeSymbolByFqName(it) }
|
||||
val irParentClass = (parentClassSymbol?.fir as? FirClass<*>)?.let { getCachedIrClass(it) }
|
||||
val irEnumEntry = createIrEnumEntry(
|
||||
val irParentClass = (parentClassSymbol?.fir as? FirClass<*>)?.let { classifierStorage.getCachedIrClass(it) }
|
||||
val irEnumEntry = classifierStorage.createIrEnumEntry(
|
||||
firDeclaration,
|
||||
irParent = irParentClass,
|
||||
origin = if (containingFile == null) IrDeclarationOrigin.IR_EXTERNAL_DECLARATION_STUB else IrDeclarationOrigin.DEFINED
|
||||
|
||||
@@ -21,7 +21,7 @@ import org.jetbrains.kotlin.types.Variance
|
||||
|
||||
class Fir2IrTypeConverter(
|
||||
private val session: FirSession,
|
||||
private val declarationStorage: Fir2IrDeclarationStorage,
|
||||
private val classifierStorage: Fir2IrClassifierStorage,
|
||||
private val irBuiltIns: IrBuiltIns
|
||||
) {
|
||||
lateinit var nothingType: IrType
|
||||
@@ -49,7 +49,7 @@ class Fir2IrTypeConverter(
|
||||
is ConeLookupTagBasedType -> {
|
||||
val irSymbol = getArrayType(this.classId) ?: run {
|
||||
val firSymbol = this.lookupTag.toSymbol(session) ?: return createErrorType()
|
||||
firSymbol.toIrSymbol(session, declarationStorage, typeContext)
|
||||
firSymbol.toSymbol(session, classifierStorage, typeContext)
|
||||
}
|
||||
// TODO: annotations
|
||||
IrSimpleTypeImpl(
|
||||
|
||||
@@ -47,6 +47,7 @@ import java.util.*
|
||||
class Fir2IrVisitor(
|
||||
private val session: FirSession,
|
||||
private val symbolTable: SymbolTable,
|
||||
private val classifierStorage: Fir2IrClassifierStorage,
|
||||
private val declarationStorage: Fir2IrDeclarationStorage,
|
||||
private val converter: Fir2IrConverter,
|
||||
private val typeConverter: Fir2IrTypeConverter,
|
||||
@@ -95,10 +96,10 @@ class Fir2IrVisitor(
|
||||
// ==================================================================================
|
||||
|
||||
override fun visitEnumEntry(enumEntry: FirEnumEntry, data: Any?): IrElement {
|
||||
val irEnumEntry = declarationStorage.getCachedIrEnumEntry(enumEntry)!!
|
||||
val irEnumEntry = classifierStorage.getCachedIrEnumEntry(enumEntry)!!
|
||||
val correspondingClass = irEnumEntry.correspondingClass ?: return irEnumEntry
|
||||
declarationStorage.enterScope(irEnumEntry.descriptor)
|
||||
declarationStorage.putEnumEntryClassInScope(enumEntry, correspondingClass)
|
||||
classifierStorage.putEnumEntryClassInScope(enumEntry, correspondingClass)
|
||||
converter.processAnonymousObjectMembers(enumEntry.initializer as FirAnonymousObject, correspondingClass)
|
||||
conversionScope.withParent(correspondingClass) {
|
||||
setClassContent(enumEntry.initializer as FirAnonymousObject)
|
||||
@@ -150,7 +151,7 @@ class Fir2IrVisitor(
|
||||
override fun visitRegularClass(regularClass: FirRegularClass, data: Any?): IrElement {
|
||||
if (regularClass.visibility == Visibilities.LOCAL) {
|
||||
val irParent = conversionScope.parentFromStack()
|
||||
val irClass = declarationStorage.getCachedIrClass(regularClass)?.apply { this.parent = irParent }
|
||||
val irClass = classifierStorage.getCachedIrClass(regularClass)?.apply { this.parent = irParent }
|
||||
if (irClass != null) {
|
||||
converter.processRegisteredLocalClassAndNestedClasses(regularClass, irClass)
|
||||
return conversionScope.withParent(irClass) {
|
||||
@@ -159,7 +160,7 @@ class Fir2IrVisitor(
|
||||
}
|
||||
converter.processLocalClassAndNestedClasses(regularClass, irParent)
|
||||
}
|
||||
val irClass = declarationStorage.getCachedIrClass(regularClass)!!
|
||||
val irClass = classifierStorage.getCachedIrClass(regularClass)!!
|
||||
return conversionScope.withParent(irClass) {
|
||||
setClassContent(regularClass)
|
||||
}
|
||||
@@ -168,8 +169,8 @@ class Fir2IrVisitor(
|
||||
override fun visitAnonymousObject(anonymousObject: FirAnonymousObject, data: Any?): IrElement {
|
||||
val irParent = conversionScope.parentFromStack()
|
||||
// NB: for implicit types it is possible that anonymous object is already cached
|
||||
val irAnonymousObject = declarationStorage.getCachedIrClass(anonymousObject)?.apply { this.parent = irParent }
|
||||
?: declarationStorage.createIrAnonymousObject(anonymousObject, irParent = irParent)
|
||||
val irAnonymousObject = classifierStorage.getCachedIrClass(anonymousObject)?.apply { this.parent = irParent }
|
||||
?: classifierStorage.createIrAnonymousObject(anonymousObject, irParent = irParent)
|
||||
converter.processAnonymousObjectMembers(anonymousObject, irAnonymousObject)
|
||||
conversionScope.withParent(irAnonymousObject) {
|
||||
setClassContent(anonymousObject)
|
||||
@@ -499,7 +500,7 @@ class Fir2IrVisitor(
|
||||
|
||||
private fun FirQualifiedAccess.toIrExpression(typeRef: FirTypeRef): IrExpression {
|
||||
val type = typeRef.toIrType()
|
||||
val symbol = calleeReference.toSymbol(declarationStorage)
|
||||
val symbol = calleeReference.toSymbol(session, classifierStorage, declarationStorage)
|
||||
return typeRef.convertWithOffsets { startOffset, endOffset ->
|
||||
if (calleeReference is FirSuperReference) {
|
||||
if (typeRef !is FirComposedSuperTypeRef) {
|
||||
@@ -647,7 +648,7 @@ class Fir2IrVisitor(
|
||||
it is FirAnonymousObject || it is FirRegularClass && it.classKind == ClassKind.OBJECT
|
||||
}
|
||||
firClass?.convertWithOffsets { startOffset, endOffset ->
|
||||
val irClass = declarationStorage.getCachedIrClass(firClass)!!
|
||||
val irClass = classifierStorage.getCachedIrClass(firClass)!!
|
||||
IrGetObjectValueImpl(startOffset, endOffset, irClass.defaultType, irClass.symbol)
|
||||
}
|
||||
}
|
||||
@@ -715,7 +716,7 @@ class Fir2IrVisitor(
|
||||
it is FirAnonymousObject || it is FirRegularClass && it.classKind == ClassKind.OBJECT
|
||||
}
|
||||
if (firObject != null) {
|
||||
val irObject = declarationStorage.getCachedIrClass(firObject)!!
|
||||
val irObject = classifierStorage.getCachedIrClass(firObject)!!
|
||||
if (irObject != conversionScope.lastClass()) {
|
||||
return thisReceiverExpression.convertWithOffsets { startOffset, endOffset ->
|
||||
IrGetObjectValueImpl(startOffset, endOffset, irObject.defaultType, irObject.symbol)
|
||||
@@ -750,7 +751,7 @@ class Fir2IrVisitor(
|
||||
}
|
||||
|
||||
override fun visitCallableReferenceAccess(callableReferenceAccess: FirCallableReferenceAccess, data: Any?): IrElement {
|
||||
val symbol = callableReferenceAccess.calleeReference.toSymbol(declarationStorage)
|
||||
val symbol = callableReferenceAccess.calleeReference.toSymbol(session, classifierStorage, declarationStorage)
|
||||
val type = callableReferenceAccess.typeRef.toIrType()
|
||||
return callableReferenceAccess.convertWithOffsets { startOffset, endOffset ->
|
||||
when (symbol) {
|
||||
@@ -792,7 +793,7 @@ class Fir2IrVisitor(
|
||||
|
||||
override fun visitVariableAssignment(variableAssignment: FirVariableAssignment, data: Any?): IrElement {
|
||||
val calleeReference = variableAssignment.calleeReference
|
||||
val symbol = calleeReference.toSymbol(declarationStorage)
|
||||
val symbol = calleeReference.toSymbol(session, classifierStorage, declarationStorage)
|
||||
return variableAssignment.convertWithOffsets { startOffset, endOffset ->
|
||||
if (symbol != null && symbol.isBound) {
|
||||
when (symbol) {
|
||||
@@ -1235,7 +1236,7 @@ class Fir2IrVisitor(
|
||||
val irClassType = argument.typeRef.toIrType()
|
||||
val irClassReferenceSymbol = when (argument) {
|
||||
is FirResolvedReifiedParameterReference -> {
|
||||
declarationStorage.getIrTypeParameterSymbol(argument.symbol, ConversionTypeContext.DEFAULT)
|
||||
classifierStorage.getIrTypeParameterSymbol(argument.symbol, ConversionTypeContext.DEFAULT)
|
||||
}
|
||||
is FirResolvedQualifier -> {
|
||||
val symbol = argument.symbol as? FirClassSymbol
|
||||
@@ -1244,7 +1245,7 @@ class Fir2IrVisitor(
|
||||
startOffset, endOffset, irType, "Resolved qualifier ${argument.render()} does not have correct symbol"
|
||||
)
|
||||
}
|
||||
declarationStorage.getIrClassSymbol(symbol)
|
||||
classifierStorage.getIrClassSymbol(symbol)
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
@@ -1274,7 +1275,7 @@ class Fir2IrVisitor(
|
||||
if (classSymbol != null) {
|
||||
IrGetObjectValueImpl(
|
||||
startOffset, endOffset, irType,
|
||||
classSymbol.toIrSymbol(session, declarationStorage) as IrClassSymbol
|
||||
classSymbol.toSymbol(session, classifierStorage) as IrClassSymbol
|
||||
)
|
||||
} else {
|
||||
IrErrorCallExpressionImpl(
|
||||
|
||||
Reference in New Issue
Block a user