Fir2Ir: rework FirIrProvider

This commit is contained in:
Georgy Bronnikov
2021-12-21 18:57:05 +03:00
committed by Alexander Udalov
parent 4a450a6627
commit 0012ba79e1
2 changed files with 51 additions and 28 deletions
@@ -5,6 +5,8 @@
package org.jetbrains.kotlin.fir.backend package org.jetbrains.kotlin.fir.backend
import org.jetbrains.kotlin.backend.common.serialization.encodings.BinarySymbolData.SymbolKind
import org.jetbrains.kotlin.backend.common.serialization.kind
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
@@ -12,6 +14,7 @@ import org.jetbrains.kotlin.fir.symbols.SymbolInternals
import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrDeclaration import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrDeclarationParent import org.jetbrains.kotlin.ir.declarations.IrDeclarationParent
import org.jetbrains.kotlin.ir.declarations.IrProperty
import org.jetbrains.kotlin.ir.linkage.IrProvider import org.jetbrains.kotlin.ir.linkage.IrProvider
import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.util.IdSignature import org.jetbrains.kotlin.ir.util.IdSignature
@@ -22,60 +25,80 @@ import org.jetbrains.kotlin.name.Name
@OptIn(SymbolInternals::class) @OptIn(SymbolInternals::class)
class FirIrProvider(val fir2IrComponents: Fir2IrComponents) : IrProvider { class FirIrProvider(val fir2IrComponents: Fir2IrComponents) : IrProvider {
private val symbolProvider = fir2IrComponents.session.symbolProvider private val symbolProvider = fir2IrComponents.session.symbolProvider
private val declarationStorage = fir2IrComponents.declarationStorage
private val classifierStorage = fir2IrComponents.classifierStorage
override fun getDeclaration(symbol: IrSymbol): IrDeclaration? { override fun getDeclaration(symbol: IrSymbol): IrDeclaration? {
val declarationStorage = fir2IrComponents.declarationStorage
val classifierStorage = fir2IrComponents.classifierStorage
val signature = symbol.signature ?: return null val signature = symbol.signature ?: return null
return getDeclarationForSignature(signature, symbol.kind())
}
val commonSignature = when(signature) { private fun getDeclarationForSignature(signature: IdSignature, kind: SymbolKind): IrDeclaration? = when (signature) {
is IdSignature.CommonSignature -> signature is IdSignature.AccessorSignature -> getDeclarationForAccessorSignature(signature)
is IdSignature.AccessorSignature -> signature.accessorSignature is IdSignature.CompositeSignature -> getDeclarationForCompositeSignature(signature, kind)
else -> is IdSignature.CommonSignature -> getDeclarationForCommonSignature(signature, kind)
TODO("Unknown signature type") else -> error("Unexpected signature kind: $signature")
}
private fun getDeclarationForAccessorSignature(signature: IdSignature.AccessorSignature): IrDeclaration? {
val property = getDeclarationForSignature(signature.propertySignature, SymbolKind.PROPERTY_SYMBOL) as? IrProperty ?: return null
return when (signature.accessorSignature.shortName) {
property.getter?.name?.asString() -> property.getter
property.setter?.name?.asString() -> property.setter
else -> null
} }
}
val packageFqName = FqName(commonSignature.packageFqName) private fun getDeclarationForCompositeSignature(signature: IdSignature.CompositeSignature, kind: SymbolKind): IrDeclaration? {
val nameSegments = commonSignature.nameSegments if (kind == SymbolKind.TYPE_PARAMETER_SYMBOL) {
TODO()
}
return getDeclarationForSignature(signature.nearestPublicSig(), kind)
}
private fun getDeclarationForCommonSignature(signature: IdSignature.CommonSignature, kind: SymbolKind): IrDeclaration? {
val packageFqName = FqName(signature.packageFqName)
val nameSegments = signature.nameSegments
val topName = Name.identifier(nameSegments[0]) val topName = Name.identifier(nameSegments[0])
val packageFragment = declarationStorage.getIrExternalPackageFragment(packageFqName) val packageFragment = declarationStorage.getIrExternalPackageFragment(packageFqName)
val firCandidates: List<FirDeclaration> val firCandidates: List<FirDeclaration>
val parent: IrDeclarationParent val parent: IrDeclarationParent
if (nameSegments.size == 1 && symbol !is IrClassSymbol) { if (nameSegments.size == 1 && kind != SymbolKind.CLASS_SYMBOL) {
firCandidates = symbolProvider.getTopLevelCallableSymbols(packageFqName, topName).map { it.fir } firCandidates = symbolProvider.getTopLevelCallableSymbols(packageFqName, topName).map { it.fir }
parent = packageFragment // TODO: need to insert file facade class on JVM parent = packageFragment // TODO: need to insert file facade class on JVM
} else { } else {
var firParentClass: FirRegularClass? = null var firParentClass: FirRegularClass? = null
var firClass = symbolProvider.getClassLikeSymbolByClassId(ClassId(packageFqName, topName))?.fir as? FirRegularClass ?: return null var firClass = symbolProvider.getClassLikeSymbolByClassId(ClassId(packageFqName, topName))?.fir as? FirRegularClass
val midSegments = if (symbol is IrClassSymbol) nameSegments.drop(1) else nameSegments.drop(1).dropLast(1) ?: return null
val midSegments = if (kind == SymbolKind.CLASS_SYMBOL) nameSegments.drop(1) else nameSegments.drop(1).dropLast(1)
for (midName in midSegments) { for (midName in midSegments) {
firParentClass = firClass firParentClass = firClass
firClass = firClass.declarations.singleOrNull { (it as? FirRegularClass)?.name?.asString() == midName } as? FirRegularClass firClass = firClass.declarations.singleOrNull { (it as? FirRegularClass)?.name?.asString() == midName } as? FirRegularClass
?: return null ?: return null
} }
val scope = firClass.unsubstitutedScope(fir2IrComponents.session, fir2IrComponents.scopeSession, withForcedTypeCalculator = true) val scope =
when (symbol) { firClass.unsubstitutedScope(fir2IrComponents.session, fir2IrComponents.scopeSession, withForcedTypeCalculator = true)
is IrClassSymbol -> { when (kind) {
SymbolKind.CLASS_SYMBOL -> {
firCandidates = listOf(firClass) firCandidates = listOf(firClass)
parent = firParentClass?.let { classifierStorage.getIrClassSymbol(it.symbol).owner } ?: packageFragment parent = firParentClass?.let { classifierStorage.getIrClassSymbol(it.symbol).owner } ?: packageFragment
} }
is IrConstructorSymbol -> { SymbolKind.CONSTRUCTOR_SYMBOL -> {
val constructors = mutableListOf<FirConstructor>() val constructors = mutableListOf<FirConstructor>()
scope.processDeclaredConstructors { constructors.add(it.fir) } scope.processDeclaredConstructors { constructors.add(it.fir) }
firCandidates = constructors firCandidates = constructors
parent = classifierStorage.getIrClassSymbol(firClass.symbol).owner parent = classifierStorage.getIrClassSymbol(firClass.symbol).owner
} }
is IrSimpleFunctionSymbol -> { SymbolKind.FUNCTION_SYMBOL -> {
val lastName = Name.guessByFirstCharacter(nameSegments.last()) val lastName = Name.guessByFirstCharacter(nameSegments.last())
val functions = mutableListOf<FirSimpleFunction>() val functions = mutableListOf<FirSimpleFunction>()
scope.processFunctionsByName(lastName) { functions.add(it.fir) } scope.processFunctionsByName(lastName) { functions.add(it.fir) }
firCandidates = functions firCandidates = functions
parent = classifierStorage.getIrClassSymbol(firClass.symbol).owner parent = classifierStorage.getIrClassSymbol(firClass.symbol).owner
} }
is IrPropertySymbol -> { SymbolKind.PROPERTY_SYMBOL -> {
val lastName = Name.guessByFirstCharacter(nameSegments.last()) val lastName = Name.guessByFirstCharacter(nameSegments.last())
val properties = mutableListOf<FirVariable>() val properties = mutableListOf<FirVariable>()
scope.processPropertiesByName(lastName) { properties.add(it.fir) } scope.processPropertiesByName(lastName) { properties.add(it.fir) }
@@ -94,25 +117,25 @@ class FirIrProvider(val fir2IrComponents: Fir2IrComponents) : IrProvider {
val firDeclaration = firCandidates.firstOrNull { fir2IrComponents.signatureComposer.composeSignature(it) == signature } val firDeclaration = firCandidates.firstOrNull { fir2IrComponents.signatureComposer.composeSignature(it) == signature }
?: return null ?: return null
return when (symbol) { return when (kind) {
is IrClassSymbol -> classifierStorage.getIrClassSymbol((firDeclaration as FirRegularClass).symbol).owner SymbolKind.CLASS_SYMBOL -> classifierStorage.getIrClassSymbol((firDeclaration as FirRegularClass).symbol).owner
is IrConstructorSymbol -> { SymbolKind.CONSTRUCTOR_SYMBOL -> {
val firConstructor = firDeclaration as FirConstructor val firConstructor = firDeclaration as FirConstructor
declarationStorage.getOrCreateIrConstructor(firConstructor, parent as IrClass) declarationStorage.getOrCreateIrConstructor(firConstructor, parent as IrClass)
} }
is IrSimpleFunctionSymbol -> { SymbolKind.FUNCTION_SYMBOL -> {
val firSimpleFunction = firDeclaration as FirSimpleFunction val firSimpleFunction = firDeclaration as FirSimpleFunction
declarationStorage.getOrCreateIrFunction(firSimpleFunction, parent) declarationStorage.getOrCreateIrFunction(firSimpleFunction, parent)
} }
is IrPropertySymbol -> { SymbolKind.PROPERTY_SYMBOL -> {
val firProperty = firDeclaration as FirProperty val firProperty = firDeclaration as FirProperty
declarationStorage.getOrCreateIrProperty(firProperty, parent) declarationStorage.getOrCreateIrProperty(firProperty, parent)
} }
is IrFieldSymbol -> { SymbolKind.FIELD_SYMBOL -> {
val firField = firDeclaration as FirField val firField = firDeclaration as FirField
declarationStorage.getOrCreateIrPropertyByPureField(firField, parent) declarationStorage.getOrCreateIrPropertyByPureField(firField, parent)
} }
else -> error("Don't know how to deal with this symbol kind: $symbol") else -> error("Don't know how to deal with this symbol kind: $kind")
} }
} }
} }
@@ -14,7 +14,7 @@ import org.jetbrains.kotlin.ir.util.IdSignature
import org.jetbrains.kotlin.library.IrLibrary import org.jetbrains.kotlin.library.IrLibrary
import org.jetbrains.kotlin.library.KotlinAbiVersion import org.jetbrains.kotlin.library.KotlinAbiVersion
internal fun IrSymbol.kind(): BinarySymbolData.SymbolKind { fun IrSymbol.kind(): BinarySymbolData.SymbolKind {
return when (this) { return when (this) {
is IrClassSymbol -> BinarySymbolData.SymbolKind.CLASS_SYMBOL is IrClassSymbol -> BinarySymbolData.SymbolKind.CLASS_SYMBOL
is IrConstructorSymbol -> BinarySymbolData.SymbolKind.CONSTRUCTOR_SYMBOL is IrConstructorSymbol -> BinarySymbolData.SymbolKind.CONSTRUCTOR_SYMBOL