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 com.intellij.psi.PsiCompiledElement
|
||||||
import org.jetbrains.kotlin.fir.FirElement
|
import org.jetbrains.kotlin.fir.FirElement
|
||||||
import org.jetbrains.kotlin.fir.FirSession
|
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.FirConstExpression
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirConstKind
|
import org.jetbrains.kotlin.fir.expressions.FirConstKind
|
||||||
import org.jetbrains.kotlin.fir.psi
|
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.ir.types.impl.makeTypeProjection
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.name.FqName
|
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.endOffset
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.startOffsetSkippingComments
|
import org.jetbrains.kotlin.psi.psiUtil.startOffsetSkippingComments
|
||||||
import org.jetbrains.kotlin.types.Variance
|
import org.jetbrains.kotlin.types.Variance
|
||||||
@@ -215,3 +219,38 @@ private fun FirConstKind<*>.toIrConstKind(): IrConstKind<*> = when (this) {
|
|||||||
FirConstKind.Double -> IrConstKind.Double
|
FirConstKind.Double -> IrConstKind.Double
|
||||||
FirConstKind.IntegerLiteral -> throw IllegalArgumentException()
|
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.psi
|
||||||
import org.jetbrains.kotlin.fir.render
|
import org.jetbrains.kotlin.fir.render
|
||||||
import org.jetbrains.kotlin.fir.resolve.*
|
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.symbols.impl.*
|
||||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||||
@@ -159,7 +160,7 @@ class Fir2IrDeclarationStorage(
|
|||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getIrClass(klass: FirClass<*>, setParent: Boolean = true): IrClass {
|
fun getIrClass(klass: FirClass<*>, setParentAndContent: Boolean = true): IrClass {
|
||||||
val regularClass = klass as? FirRegularClass
|
val regularClass = klass as? FirRegularClass
|
||||||
|
|
||||||
fun create(): IrClass {
|
fun create(): IrClass {
|
||||||
@@ -187,7 +188,7 @@ class Fir2IrDeclarationStorage(
|
|||||||
isFun = false // TODO FirRegularClass.isFun
|
isFun = false // TODO FirRegularClass.isFun
|
||||||
).apply {
|
).apply {
|
||||||
descriptor.bind(this)
|
descriptor.bind(this)
|
||||||
if (setParent && regularClass != null) {
|
if (setParentAndContent && regularClass != null) {
|
||||||
val classId = regularClass.classId
|
val classId = regularClass.classId
|
||||||
val parentId = classId.outerClassId
|
val parentId = classId.outerClassId
|
||||||
if (parentId != null) {
|
if (parentId != null) {
|
||||||
@@ -216,9 +217,57 @@ class Fir2IrDeclarationStorage(
|
|||||||
return created
|
return created
|
||||||
}
|
}
|
||||||
// NB: klass can be either FirRegularClass or FirAnonymousObject
|
// NB: klass can be either FirRegularClass or FirAnonymousObject
|
||||||
return classCache.getOrPut(klass as FirRegularClass, { create() }) {
|
return classCache.getOrPut(klass as FirRegularClass, { create() }) { irClass ->
|
||||||
it.declareSupertypesAndTypeParameters(klass)
|
irClass.declareSupertypesAndTypeParameters(klass)
|
||||||
it.setThisReceiver()
|
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()
|
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? =
|
private fun FirClass<*>.getPrimaryConstructorIfAny(): FirConstructor? =
|
||||||
declarations.filterIsInstance<FirConstructor>().firstOrNull()?.takeIf { it.isPrimary }
|
declarations.filterIsInstance<FirConstructor>().firstOrNull()?.takeIf { it.isPrimary }
|
||||||
|
|
||||||
private fun IrClass.addFakeOverrides(klass: FirClass<*>, processedCallableNames: MutableList<Name>) {
|
private fun IrClass.addFakeOverrides(klass: FirClass<*>, processedCallableNames: MutableList<Name>) {
|
||||||
if (fakeOverrideMode == FakeOverrideMode.NONE) return
|
if (fakeOverrideMode == FakeOverrideMode.NONE) return
|
||||||
val superTypesCallableNames = klass.collectCallableNamesFromSupertypes()
|
val superTypesCallableNames = klass.collectCallableNamesFromSupertypes(session)
|
||||||
val useSiteMemberScope = (klass as? FirRegularClass)?.buildUseSiteMemberScope(session, ScopeSession()) ?: return
|
val useSiteMemberScope = (klass as? FirRegularClass)?.buildUseSiteMemberScope(session, ScopeSession()) ?: return
|
||||||
for (name in superTypesCallableNames) {
|
for (name in superTypesCallableNames) {
|
||||||
if (name in processedCallableNames) continue
|
if (name in processedCallableNames) continue
|
||||||
@@ -315,7 +283,7 @@ class Fir2IrVisitor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitRegularClass(regularClass: FirRegularClass, data: Any?): IrElement {
|
override fun visitRegularClass(regularClass: FirRegularClass, data: Any?): IrElement {
|
||||||
return declarationStorage.getIrClass(regularClass, setParent = false)
|
return declarationStorage.getIrClass(regularClass, setParentAndContent = false)
|
||||||
.setParentByParentStack()
|
.setParentByParentStack()
|
||||||
.withParent {
|
.withParent {
|
||||||
setClassContent(regularClass)
|
setClassContent(regularClass)
|
||||||
@@ -360,7 +328,7 @@ class Fir2IrVisitor(
|
|||||||
lastClass
|
lastClass
|
||||||
} else {
|
} else {
|
||||||
val firClass = classLikeSymbol.fir as FirClass<*>
|
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
|
it is FirAnonymousObject || it is FirRegularClass && it.classKind == ClassKind.OBJECT
|
||||||
}
|
}
|
||||||
firClass?.convertWithOffsets { startOffset, endOffset ->
|
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)
|
IrGetObjectValueImpl(startOffset, endOffset, irClass.defaultType, irClass.symbol)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -928,7 +896,7 @@ class Fir2IrVisitor(
|
|||||||
it is FirAnonymousObject || it is FirRegularClass && it.classKind == ClassKind.OBJECT
|
it is FirAnonymousObject || it is FirRegularClass && it.classKind == ClassKind.OBJECT
|
||||||
}
|
}
|
||||||
if (firObject != null) {
|
if (firObject != null) {
|
||||||
val irObject = declarationStorage.getIrClass(firObject, setParent = false)
|
val irObject = declarationStorage.getIrClass(firObject, setParentAndContent = false)
|
||||||
if (irObject != classStack.lastOrNull()) {
|
if (irObject != classStack.lastOrNull()) {
|
||||||
return thisReceiverExpression.convertWithOffsets { startOffset, endOffset ->
|
return thisReceiverExpression.convertWithOffsets { startOffset, endOffset ->
|
||||||
IrGetObjectValueImpl(startOffset, endOffset, irObject.defaultType, irObject.symbol)
|
IrGetObjectValueImpl(startOffset, endOffset, irObject.defaultType, irObject.symbol)
|
||||||
@@ -1360,7 +1328,8 @@ class Fir2IrVisitor(
|
|||||||
FirOperation.MINUS_ASSIGN, FirOperation.TIMES_ASSIGN,
|
FirOperation.MINUS_ASSIGN, FirOperation.TIMES_ASSIGN,
|
||||||
FirOperation.DIV_ASSIGN, FirOperation.REM_ASSIGN,
|
FirOperation.DIV_ASSIGN, FirOperation.REM_ASSIGN,
|
||||||
FirOperation.IS, FirOperation.NOT_IS,
|
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")
|
TODO("Should not be here: incompatible operation in FirOperatorCall: $operation")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user