FIR2IR: add declarations to all library classes from kotlin.* package
Before this commit, all library classes were just stubs. This commit helps to solve problems with some functions indirectly used by BE, like IntProgression.first.
This commit is contained in:
@@ -8,6 +8,9 @@ package org.jetbrains.kotlin.fir.backend
|
||||
import com.intellij.psi.PsiCompiledElement
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.FirClass
|
||||
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
||||
import org.jetbrains.kotlin.fir.declarations.FirVariable
|
||||
import org.jetbrains.kotlin.fir.expressions.FirConstExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirConstKind
|
||||
import org.jetbrains.kotlin.fir.psi
|
||||
@@ -31,6 +34,7 @@ import org.jetbrains.kotlin.ir.types.impl.IrStarProjectionImpl
|
||||
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||
import org.jetbrains.kotlin.psi.psiUtil.startOffsetSkippingComments
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
@@ -215,3 +219,38 @@ private fun FirConstKind<*>.toIrConstKind(): IrConstKind<*> = when (this) {
|
||||
FirConstKind.Double -> IrConstKind.Double
|
||||
FirConstKind.IntegerLiteral -> throw IllegalArgumentException()
|
||||
}
|
||||
|
||||
internal fun FirClass<*>.collectCallableNamesFromSupertypes(session: FirSession, result: MutableList<Name> = mutableListOf()): List<Name> {
|
||||
for (superTypeRef in superTypeRefs) {
|
||||
superTypeRef.collectCallableNamesFromThisAndSupertypes(session, result)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
private fun FirTypeRef.collectCallableNamesFromThisAndSupertypes(
|
||||
session: FirSession,
|
||||
result: MutableList<Name> = mutableListOf()
|
||||
): List<Name> {
|
||||
if (this is FirResolvedTypeRef) {
|
||||
val superType = type
|
||||
if (superType is ConeClassLikeType) {
|
||||
when (val superSymbol = superType.lookupTag.toSymbol(session)) {
|
||||
is FirClassSymbol -> {
|
||||
val superClass = superSymbol.fir as FirClass<*>
|
||||
for (declaration in superClass.declarations) {
|
||||
when (declaration) {
|
||||
is FirSimpleFunction -> result += declaration.name
|
||||
is FirVariable<*> -> result += declaration.name
|
||||
}
|
||||
}
|
||||
superClass.collectCallableNamesFromSupertypes(session, result)
|
||||
}
|
||||
is FirTypeAliasSymbol -> {
|
||||
val superAlias = superSymbol.fir
|
||||
superAlias.expandedTypeRef.collectCallableNamesFromThisAndSupertypes(session, result)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
+54
-5
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.fir.descriptors.FirPackageFragmentDescriptor
|
||||
import org.jetbrains.kotlin.fir.psi
|
||||
import org.jetbrains.kotlin.fir.render
|
||||
import org.jetbrains.kotlin.fir.resolve.*
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirClassSubstitutionScope
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
@@ -159,7 +160,7 @@ class Fir2IrDeclarationStorage(
|
||||
return this
|
||||
}
|
||||
|
||||
fun getIrClass(klass: FirClass<*>, setParent: Boolean = true): IrClass {
|
||||
fun getIrClass(klass: FirClass<*>, setParentAndContent: Boolean = true): IrClass {
|
||||
val regularClass = klass as? FirRegularClass
|
||||
|
||||
fun create(): IrClass {
|
||||
@@ -187,7 +188,7 @@ class Fir2IrDeclarationStorage(
|
||||
isFun = false // TODO FirRegularClass.isFun
|
||||
).apply {
|
||||
descriptor.bind(this)
|
||||
if (setParent && regularClass != null) {
|
||||
if (setParentAndContent && regularClass != null) {
|
||||
val classId = regularClass.classId
|
||||
val parentId = classId.outerClassId
|
||||
if (parentId != null) {
|
||||
@@ -216,9 +217,57 @@ class Fir2IrDeclarationStorage(
|
||||
return created
|
||||
}
|
||||
// NB: klass can be either FirRegularClass or FirAnonymousObject
|
||||
return classCache.getOrPut(klass as FirRegularClass, { create() }) {
|
||||
it.declareSupertypesAndTypeParameters(klass)
|
||||
it.setThisReceiver()
|
||||
return classCache.getOrPut(klass as FirRegularClass, { create() }) { irClass ->
|
||||
irClass.declareSupertypesAndTypeParameters(klass)
|
||||
irClass.setThisReceiver()
|
||||
if (setParentAndContent && regularClass != null &&
|
||||
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
|
||||
// TODO: think how to refactor this piece of code and/or merge it with similar Fir2IrVisitor fragment
|
||||
val processedNames = mutableSetOf<Name>()
|
||||
for (declaration in regularClass.declarations) {
|
||||
irClass.declarations += when (declaration) {
|
||||
is FirSimpleFunction -> {
|
||||
processedNames += declaration.name
|
||||
getIrFunction(declaration, irClass, shouldLeaveScope = true)
|
||||
}
|
||||
is FirProperty -> {
|
||||
processedNames += declaration.name
|
||||
getIrProperty(declaration, irClass)
|
||||
}
|
||||
is FirConstructor -> getIrConstructor(declaration, irClass, shouldLeaveScope = true)
|
||||
is FirRegularClass -> getIrClass(declaration)
|
||||
else -> continue
|
||||
}
|
||||
}
|
||||
val allNames = regularClass.collectCallableNamesFromSupertypes(session)
|
||||
val scope = regularClass.buildUseSiteMemberScope(session, ScopeSession())
|
||||
if (scope != null) {
|
||||
for (name in allNames) {
|
||||
if (name in processedNames) continue
|
||||
processedNames += name
|
||||
scope.processFunctionsByName(name) { functionSymbol ->
|
||||
if (functionSymbol is FirNamedFunctionSymbol) {
|
||||
val fakeOverrideSymbol =
|
||||
FirClassSubstitutionScope.createFakeOverrideFunction(session, functionSymbol.fir, functionSymbol)
|
||||
irClass.declarations += getIrFunction(fakeOverrideSymbol.fir, irClass, shouldLeaveScope = true)
|
||||
}
|
||||
}
|
||||
scope.processPropertiesByName(name) { propertySymbol ->
|
||||
if (propertySymbol is FirPropertySymbol) {
|
||||
val fakeOverrideSymbol =
|
||||
FirClassSubstitutionScope.createFakeOverrideProperty(session, propertySymbol.fir, propertySymbol)
|
||||
irClass.declarations += getIrProperty(fakeOverrideSymbol.fir, irClass)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (irDeclaration in irClass.declarations) {
|
||||
irDeclaration.parent = irClass
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -183,44 +183,12 @@ class Fir2IrVisitor(
|
||||
return irEnumEntry.setParentByParentStack()
|
||||
}
|
||||
|
||||
private fun FirTypeRef.collectCallableNamesFromThisAndSupertypes(result: MutableList<Name> = mutableListOf()): List<Name> {
|
||||
if (this is FirResolvedTypeRef) {
|
||||
val superType = type
|
||||
if (superType is ConeClassLikeType) {
|
||||
when (val superSymbol = superType.lookupTag.toSymbol(this@Fir2IrVisitor.session)) {
|
||||
is FirClassSymbol -> {
|
||||
val superClass = superSymbol.fir as FirClass<*>
|
||||
for (declaration in superClass.declarations) {
|
||||
when (declaration) {
|
||||
is FirSimpleFunction -> result += declaration.name
|
||||
is FirVariable<*> -> result += declaration.name
|
||||
}
|
||||
}
|
||||
superClass.collectCallableNamesFromSupertypes(result)
|
||||
}
|
||||
is FirTypeAliasSymbol -> {
|
||||
val superAlias = superSymbol.fir
|
||||
superAlias.expandedTypeRef.collectCallableNamesFromThisAndSupertypes(result)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
private fun FirClass<*>.collectCallableNamesFromSupertypes(result: MutableList<Name> = mutableListOf()): List<Name> {
|
||||
for (superTypeRef in superTypeRefs) {
|
||||
superTypeRef.collectCallableNamesFromThisAndSupertypes(result)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
private fun FirClass<*>.getPrimaryConstructorIfAny(): FirConstructor? =
|
||||
declarations.filterIsInstance<FirConstructor>().firstOrNull()?.takeIf { it.isPrimary }
|
||||
|
||||
private fun IrClass.addFakeOverrides(klass: FirClass<*>, processedCallableNames: MutableList<Name>) {
|
||||
if (fakeOverrideMode == FakeOverrideMode.NONE) return
|
||||
val superTypesCallableNames = klass.collectCallableNamesFromSupertypes()
|
||||
val superTypesCallableNames = klass.collectCallableNamesFromSupertypes(session)
|
||||
val useSiteMemberScope = (klass as? FirRegularClass)?.buildUseSiteMemberScope(session, ScopeSession()) ?: return
|
||||
for (name in superTypesCallableNames) {
|
||||
if (name in processedCallableNames) continue
|
||||
@@ -315,7 +283,7 @@ class Fir2IrVisitor(
|
||||
}
|
||||
|
||||
override fun visitRegularClass(regularClass: FirRegularClass, data: Any?): IrElement {
|
||||
return declarationStorage.getIrClass(regularClass, setParent = false)
|
||||
return declarationStorage.getIrClass(regularClass, setParentAndContent = false)
|
||||
.setParentByParentStack()
|
||||
.withParent {
|
||||
setClassContent(regularClass)
|
||||
@@ -360,7 +328,7 @@ class Fir2IrVisitor(
|
||||
lastClass
|
||||
} else {
|
||||
val firClass = classLikeSymbol.fir as FirClass<*>
|
||||
declarationStorage.getIrClass(firClass, setParent = false)
|
||||
declarationStorage.getIrClass(firClass, setParentAndContent = false)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -850,7 +818,7 @@ class Fir2IrVisitor(
|
||||
it is FirAnonymousObject || it is FirRegularClass && it.classKind == ClassKind.OBJECT
|
||||
}
|
||||
firClass?.convertWithOffsets { startOffset, endOffset ->
|
||||
val irClass = declarationStorage.getIrClass(firClass, setParent = false)
|
||||
val irClass = declarationStorage.getIrClass(firClass, setParentAndContent = false)
|
||||
IrGetObjectValueImpl(startOffset, endOffset, irClass.defaultType, irClass.symbol)
|
||||
}
|
||||
}
|
||||
@@ -928,7 +896,7 @@ class Fir2IrVisitor(
|
||||
it is FirAnonymousObject || it is FirRegularClass && it.classKind == ClassKind.OBJECT
|
||||
}
|
||||
if (firObject != null) {
|
||||
val irObject = declarationStorage.getIrClass(firObject, setParent = false)
|
||||
val irObject = declarationStorage.getIrClass(firObject, setParentAndContent = false)
|
||||
if (irObject != classStack.lastOrNull()) {
|
||||
return thisReceiverExpression.convertWithOffsets { startOffset, endOffset ->
|
||||
IrGetObjectValueImpl(startOffset, endOffset, irObject.defaultType, irObject.symbol)
|
||||
@@ -1360,7 +1328,8 @@ class Fir2IrVisitor(
|
||||
FirOperation.MINUS_ASSIGN, FirOperation.TIMES_ASSIGN,
|
||||
FirOperation.DIV_ASSIGN, FirOperation.REM_ASSIGN,
|
||||
FirOperation.IS, FirOperation.NOT_IS,
|
||||
FirOperation.AS, FirOperation.SAFE_AS -> {
|
||||
FirOperation.AS, FirOperation.SAFE_AS
|
||||
-> {
|
||||
TODO("Should not be here: incompatible operation in FirOperatorCall: $operation")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user