[FIR] Add ir support
This commit is contained in:
committed by
TeamCityServer
parent
8b918e12b2
commit
79ceaf03bf
+10
-3
@@ -699,6 +699,7 @@ class Fir2IrDeclarationStorage(
|
|||||||
|
|
||||||
private val FirProperty.fieldVisibility: Visibility
|
private val FirProperty.fieldVisibility: Visibility
|
||||||
get() = when {
|
get() = when {
|
||||||
|
hasExplicitBackingField -> backingField?.visibility ?: status.visibility
|
||||||
isLateInit -> setter?.visibility ?: status.visibility
|
isLateInit -> setter?.visibility ?: status.visibility
|
||||||
isConst -> status.visibility
|
isConst -> status.visibility
|
||||||
hasJvmFieldAnnotation -> status.visibility
|
hasJvmFieldAnnotation -> status.visibility
|
||||||
@@ -798,7 +799,6 @@ class Fir2IrDeclarationStorage(
|
|||||||
parent = irParent
|
parent = irParent
|
||||||
}
|
}
|
||||||
val type = property.returnTypeRef.toIrType()
|
val type = property.returnTypeRef.toIrType()
|
||||||
val initializer = property.initializer
|
|
||||||
val delegate = property.delegate
|
val delegate = property.delegate
|
||||||
val getter = property.getter
|
val getter = property.getter
|
||||||
val setter = property.setter
|
val setter = property.setter
|
||||||
@@ -810,14 +810,21 @@ class Fir2IrDeclarationStorage(
|
|||||||
Name.identifier("${property.name}\$delegate"), true, delegate
|
Name.identifier("${property.name}\$delegate"), true, delegate
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
val initializer = property.backingField?.initializer ?: property.initializer
|
||||||
|
// There are cases when we get here for properties
|
||||||
|
// that have no backing field. For example, in the
|
||||||
|
// funExpression.kt test there's an attempt
|
||||||
|
// to access the `javaClass` property of the `foo0`'s
|
||||||
|
// `block` argument
|
||||||
|
val typeToUse = property.backingField?.returnTypeRef?.toIrType() ?: type
|
||||||
createBackingField(
|
createBackingField(
|
||||||
property, IrDeclarationOrigin.PROPERTY_BACKING_FIELD,
|
property, IrDeclarationOrigin.PROPERTY_BACKING_FIELD,
|
||||||
components.visibilityConverter.convertToDescriptorVisibility(property.fieldVisibility),
|
components.visibilityConverter.convertToDescriptorVisibility(property.fieldVisibility),
|
||||||
property.name, property.isVal, initializer, type
|
property.name, property.isVal, initializer, typeToUse
|
||||||
).also { field ->
|
).also { field ->
|
||||||
if (initializer is FirConstExpression<*>) {
|
if (initializer is FirConstExpression<*>) {
|
||||||
// TODO: Normally we shouldn't have error type here
|
// TODO: Normally we shouldn't have error type here
|
||||||
val constType = initializer.typeRef.toIrType().takeIf { it !is IrErrorType } ?: type
|
val constType = initializer.typeRef.toIrType().takeIf { it !is IrErrorType } ?: typeToUse
|
||||||
field.initializer = factory.createExpressionBody(initializer.toIrConst(constType))
|
field.initializer = factory.createExpressionBody(initializer.toIrConst(constType))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -158,7 +158,7 @@ internal class ClassMemberGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun convertPropertyContent(irProperty: IrProperty, property: FirProperty, containingClass: FirClass?): IrProperty {
|
fun convertPropertyContent(irProperty: IrProperty, property: FirProperty, containingClass: FirClass?): IrProperty {
|
||||||
val initializer = property.initializer
|
val initializer = property.backingField?.initializer ?: property.initializer
|
||||||
val delegate = property.delegate
|
val delegate = property.delegate
|
||||||
val propertyType = property.returnTypeRef.toIrType()
|
val propertyType = property.returnTypeRef.toIrType()
|
||||||
irProperty.initializeBackingField(property, initializerExpression = initializer ?: delegate)
|
irProperty.initializeBackingField(property, initializerExpression = initializer ?: delegate)
|
||||||
|
|||||||
@@ -29,6 +29,8 @@ import org.jetbrains.kotlin.name.Name
|
|||||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
|
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
|
||||||
import org.jetbrains.kotlin.fir.backend.*
|
import org.jetbrains.kotlin.fir.backend.*
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.*
|
import org.jetbrains.kotlin.fir.declarations.utils.*
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrExpressionBody
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol
|
import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol
|
||||||
|
|
||||||
class Fir2IrLazyProperty(
|
class Fir2IrLazyProperty(
|
||||||
@@ -88,6 +90,16 @@ class Fir2IrLazyProperty(
|
|||||||
with(typeConverter) { fir.returnTypeRef.toIrType() }
|
with(typeConverter) { fir.returnTypeRef.toIrType() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun toIrInitializer(initializer: FirExpression?): IrExpressionBody? {
|
||||||
|
return if (initializer is FirConstExpression<*>) {
|
||||||
|
// TODO: Normally we shouldn't have error type here
|
||||||
|
val constType = with(typeConverter) { initializer.typeRef.toIrType().takeIf { it !is IrErrorType } ?: type }
|
||||||
|
factory.createExpressionBody(initializer.toIrConst(constType))
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||||
override var backingField: IrField? by lazyVar(lock) {
|
override var backingField: IrField? by lazyVar(lock) {
|
||||||
// TODO: this checks are very preliminary, FIR resolve should determine backing field presence itself
|
// TODO: this checks are very preliminary, FIR resolve should determine backing field presence itself
|
||||||
@@ -96,6 +108,26 @@ class Fir2IrLazyProperty(
|
|||||||
!fir.isConst && (fir.modality == Modality.ABSTRACT || parent is IrClass && parent.isInterface) -> {
|
!fir.isConst && (fir.modality == Modality.ABSTRACT || parent is IrClass && parent.isInterface) -> {
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
fir.hasExplicitBackingField -> {
|
||||||
|
with(declarationStorage) {
|
||||||
|
val backingFieldType = with(typeConverter) {
|
||||||
|
fir.backingField?.returnTypeRef?.toIrType()
|
||||||
|
}
|
||||||
|
val initializer = fir.backingField?.initializer ?: fir.initializer
|
||||||
|
val visibility = fir.backingField?.visibility ?: fir.visibility
|
||||||
|
createBackingField(
|
||||||
|
fir,
|
||||||
|
IrDeclarationOrigin.PROPERTY_BACKING_FIELD,
|
||||||
|
components.visibilityConverter.convertToDescriptorVisibility(visibility),
|
||||||
|
fir.name,
|
||||||
|
fir.isVal,
|
||||||
|
initializer,
|
||||||
|
backingFieldType
|
||||||
|
).also { field ->
|
||||||
|
field.initializer = toIrInitializer(initializer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
fir.initializer != null || fir.getter is FirDefaultPropertyGetter || fir.isVar && fir.setter is FirDefaultPropertySetter -> {
|
fir.initializer != null || fir.getter is FirDefaultPropertyGetter || fir.isVar && fir.setter is FirDefaultPropertySetter -> {
|
||||||
with(declarationStorage) {
|
with(declarationStorage) {
|
||||||
createBackingField(
|
createBackingField(
|
||||||
@@ -103,12 +135,7 @@ class Fir2IrLazyProperty(
|
|||||||
components.visibilityConverter.convertToDescriptorVisibility(fir.visibility), fir.name, fir.isVal, fir.initializer,
|
components.visibilityConverter.convertToDescriptorVisibility(fir.visibility), fir.name, fir.isVal, fir.initializer,
|
||||||
type
|
type
|
||||||
).also { field ->
|
).also { field ->
|
||||||
val initializer = fir.initializer
|
field.initializer = toIrInitializer(fir.initializer)
|
||||||
if (initializer is FirConstExpression<*>) {
|
|
||||||
// TODO: Normally we shouldn't have error type here
|
|
||||||
val constType = with(typeConverter) { initializer.typeRef.toIrType().takeIf { it !is IrErrorType } ?: type }
|
|
||||||
field.initializer = factory.createExpressionBody(initializer.toIrConst(constType))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.fir
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.utils.hasExplicitBackingField
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.isInner
|
import org.jetbrains.kotlin.fir.declarations.utils.isInner
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.isReferredViaField
|
import org.jetbrains.kotlin.fir.declarations.utils.isReferredViaField
|
||||||
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
|
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
|
||||||
@@ -44,6 +45,7 @@ import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
|
|||||||
import org.jetbrains.kotlin.resolve.calls.tower.CandidateApplicability
|
import org.jetbrains.kotlin.resolve.calls.tower.CandidateApplicability
|
||||||
import org.jetbrains.kotlin.resolve.calls.tower.isSuccess
|
import org.jetbrains.kotlin.resolve.calls.tower.isSuccess
|
||||||
import org.jetbrains.kotlin.types.Variance
|
import org.jetbrains.kotlin.types.Variance
|
||||||
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
|
|
||||||
class FirCallResolver(
|
class FirCallResolver(
|
||||||
private val components: FirAbstractBodyResolveTransformer.BodyResolveTransformerComponents,
|
private val components: FirAbstractBodyResolveTransformer.BodyResolveTransformerComponents,
|
||||||
@@ -727,6 +729,11 @@ class FirCallResolver(
|
|||||||
resolvedSymbol = coneSymbol
|
resolvedSymbol = coneSymbol
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (coneSymbol.safeAs<FirPropertySymbol>()?.hasExplicitBackingField == true) {
|
||||||
|
return FirPropertyWithExplicitBackingFieldResolvedNamedReference(
|
||||||
|
source, name, candidate.symbol, candidate.hasVisibleBackingField
|
||||||
|
)
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* This `if` is an optimization for local variables and properties without type parameters
|
* This `if` is an optimization for local variables and properties without type parameters
|
||||||
* Since they have no type variables, so we can don't run completion on them at all and create
|
* Since they have no type variables, so we can don't run completion on them at all and create
|
||||||
|
|||||||
@@ -18,11 +18,13 @@ import org.jetbrains.kotlin.fir.resolve.calls.FirSyntheticFunctionSymbol
|
|||||||
import org.jetbrains.kotlin.fir.resolve.calls.ReceiverValue
|
import org.jetbrains.kotlin.fir.resolve.calls.ReceiverValue
|
||||||
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
|
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
|
||||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirBackingFieldSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||||
import org.jetbrains.kotlin.fir.types.*
|
import org.jetbrains.kotlin.fir.types.*
|
||||||
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.types.AbstractTypeChecker
|
import org.jetbrains.kotlin.types.AbstractTypeChecker
|
||||||
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
|
|
||||||
abstract class FirModuleVisibilityChecker : FirSessionComponent {
|
abstract class FirModuleVisibilityChecker : FirSessionComponent {
|
||||||
abstract fun <T> isInFriendModule(declaration: T): Boolean where T : FirMemberDeclaration, T : FirDeclaration
|
abstract fun <T> isInFriendModule(declaration: T): Boolean where T : FirMemberDeclaration, T : FirDeclaration
|
||||||
@@ -51,6 +53,23 @@ abstract class FirVisibilityChecker : FirSessionComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun FirMemberDeclaration.getBackingFieldIfApplicable(): FirBackingField? {
|
||||||
|
val field = this.safeAs<FirProperty>()?.getExplicitBackingField()
|
||||||
|
?: return null
|
||||||
|
|
||||||
|
// This check prevents resolving protected and
|
||||||
|
// public fields.
|
||||||
|
if (
|
||||||
|
field.visibility == Visibilities.PrivateToThis ||
|
||||||
|
field.visibility == Visibilities.Private ||
|
||||||
|
field.visibility == Visibilities.Internal
|
||||||
|
) {
|
||||||
|
return field
|
||||||
|
}
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
fun isVisible(
|
fun isVisible(
|
||||||
declaration: FirMemberDeclaration,
|
declaration: FirMemberDeclaration,
|
||||||
candidate: Candidate
|
candidate: Candidate
|
||||||
@@ -71,7 +90,20 @@ abstract class FirVisibilityChecker : FirSessionComponent {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
return isVisible(declaration, session, useSiteFile, containingDeclarations, candidate.dispatchReceiverValue)
|
val visible = isVisible(declaration, session, useSiteFile, containingDeclarations, candidate.dispatchReceiverValue)
|
||||||
|
val backingField = declaration.getBackingFieldIfApplicable()
|
||||||
|
|
||||||
|
if (visible && backingField != null) {
|
||||||
|
candidate.hasVisibleBackingField = isVisible(
|
||||||
|
backingField,
|
||||||
|
session,
|
||||||
|
useSiteFile,
|
||||||
|
containingDeclarations,
|
||||||
|
candidate.dispatchReceiverValue,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return visible
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isVisible(
|
fun isVisible(
|
||||||
@@ -277,6 +309,7 @@ val FirSession.visibilityChecker: FirVisibilityChecker by FirSession.sessionComp
|
|||||||
|
|
||||||
fun FirBasedSymbol<*>.getOwnerLookupTag(): ConeClassLikeLookupTag? {
|
fun FirBasedSymbol<*>.getOwnerLookupTag(): ConeClassLikeLookupTag? {
|
||||||
return when (this) {
|
return when (this) {
|
||||||
|
is FirBackingFieldSymbol -> fir.propertySymbol.getOwnerLookupTag()
|
||||||
is FirClassLikeSymbol<*> -> {
|
is FirClassLikeSymbol<*> -> {
|
||||||
if (classId.isLocal) {
|
if (classId.isLocal) {
|
||||||
(fir as? FirRegularClass)?.containingClassForLocal()
|
(fir as? FirRegularClass)?.containingClassForLocal()
|
||||||
|
|||||||
@@ -11,7 +11,9 @@ import org.jetbrains.kotlin.config.LanguageFeature
|
|||||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
import org.jetbrains.kotlin.fir.*
|
import org.jetbrains.kotlin.fir.*
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.utils.canNarrowDownGetterType
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.expandedConeType
|
import org.jetbrains.kotlin.fir.declarations.utils.expandedConeType
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.utils.isFinal
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.isInner
|
import org.jetbrains.kotlin.fir.declarations.utils.isInner
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.isLocal
|
import org.jetbrains.kotlin.fir.declarations.utils.isLocal
|
||||||
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
|
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
|
||||||
@@ -187,6 +189,30 @@ internal fun typeForQualifierByDeclaration(declaration: FirDeclaration, resultTy
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun FirPropertyWithExplicitBackingFieldResolvedNamedReference.getNarrowedDownSymbol(): FirBasedSymbol<*> {
|
||||||
|
val propertyReceiver = resolvedSymbol.safeAs<FirPropertySymbol>()
|
||||||
|
?: return resolvedSymbol
|
||||||
|
|
||||||
|
// This can happen in case of 2 properties referencing
|
||||||
|
// each other recursively. See: Jet81.fir.kt
|
||||||
|
if (
|
||||||
|
propertyReceiver.fir.returnTypeRef is FirImplicitTypeRef ||
|
||||||
|
propertyReceiver.fir.backingField?.returnTypeRef is FirImplicitTypeRef
|
||||||
|
) {
|
||||||
|
return resolvedSymbol
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
propertyReceiver.isFinal &&
|
||||||
|
hasVisibleBackingField &&
|
||||||
|
propertyReceiver.canNarrowDownGetterType
|
||||||
|
) {
|
||||||
|
return propertyReceiver.fir.backingField?.symbol ?: resolvedSymbol
|
||||||
|
}
|
||||||
|
|
||||||
|
return resolvedSymbol
|
||||||
|
}
|
||||||
|
|
||||||
fun <T : FirResolvable> BodyResolveComponents.typeFromCallee(access: T): FirResolvedTypeRef {
|
fun <T : FirResolvable> BodyResolveComponents.typeFromCallee(access: T): FirResolvedTypeRef {
|
||||||
return when (val newCallee = access.calleeReference) {
|
return when (val newCallee = access.calleeReference) {
|
||||||
is FirErrorNamedReference ->
|
is FirErrorNamedReference ->
|
||||||
@@ -198,16 +224,8 @@ fun <T : FirResolvable> BodyResolveComponents.typeFromCallee(access: T): FirReso
|
|||||||
typeFromSymbol(newCallee.candidateSymbol, false)
|
typeFromSymbol(newCallee.candidateSymbol, false)
|
||||||
}
|
}
|
||||||
is FirPropertyWithExplicitBackingFieldResolvedNamedReference -> {
|
is FirPropertyWithExplicitBackingFieldResolvedNamedReference -> {
|
||||||
val backingField = newCallee.resolvedSymbol
|
val symbol = newCallee.getNarrowedDownSymbol()
|
||||||
.safeAs<FirPropertySymbol>()
|
typeFromSymbol(symbol, false)
|
||||||
?.fir
|
|
||||||
?.backingField
|
|
||||||
|
|
||||||
if (newCallee.hasVisibleBackingField && backingField != null) {
|
|
||||||
typeFromSymbol(backingField.symbol, false)
|
|
||||||
} else {
|
|
||||||
typeFromSymbol(newCallee.resolvedSymbol, false)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
is FirResolvedNamedReference -> {
|
is FirResolvedNamedReference -> {
|
||||||
typeFromSymbol(newCallee.resolvedSymbol, false)
|
typeFromSymbol(newCallee.resolvedSymbol, false)
|
||||||
|
|||||||
@@ -145,6 +145,8 @@ class Candidate(
|
|||||||
fun extensionReceiverExpression(): FirExpression =
|
fun extensionReceiverExpression(): FirExpression =
|
||||||
extensionReceiverValue?.receiverExpression?.takeIf { it !is FirExpressionStub } ?: FirNoReceiverExpression
|
extensionReceiverValue?.receiverExpression?.takeIf { it !is FirExpressionStub } ?: FirNoReceiverExpression
|
||||||
|
|
||||||
|
var hasVisibleBackingField = false
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean {
|
override fun equals(other: Any?): Boolean {
|
||||||
if (this === other) return true
|
if (this === other) return true
|
||||||
if (javaClass != other?.javaClass) return false
|
if (javaClass != other?.javaClass) return false
|
||||||
|
|||||||
+18
@@ -8,8 +8,11 @@ package org.jetbrains.kotlin.fir.resolve.calls
|
|||||||
import org.jetbrains.kotlin.fir.FirImplementationDetail
|
import org.jetbrains.kotlin.fir.FirImplementationDetail
|
||||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||||
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
|
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
|
||||||
|
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||||
import org.jetbrains.kotlin.fir.references.impl.FirSimpleNamedReference
|
import org.jetbrains.kotlin.fir.references.impl.FirSimpleNamedReference
|
||||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.visitors.FirTransformer
|
||||||
|
import org.jetbrains.kotlin.fir.visitors.FirVisitor
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
|
||||||
@OptIn(FirImplementationDetail::class)
|
@OptIn(FirImplementationDetail::class)
|
||||||
@@ -32,3 +35,18 @@ class FirErrorReferenceWithCandidate(
|
|||||||
) : FirNamedReferenceWithCandidate(source, name, candidate) {
|
) : FirNamedReferenceWithCandidate(source, name, candidate) {
|
||||||
override val isError: Boolean get() = true
|
override val isError: Boolean get() = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class FirPropertyWithExplicitBackingFieldResolvedNamedReference(
|
||||||
|
override val source: FirSourceElement?,
|
||||||
|
override val name: Name,
|
||||||
|
override val resolvedSymbol: FirBasedSymbol<*>,
|
||||||
|
val hasVisibleBackingField: Boolean,
|
||||||
|
) : FirResolvedNamedReference() {
|
||||||
|
override val candidateSymbol: FirBasedSymbol<*>? get() = null
|
||||||
|
|
||||||
|
override fun <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D) {}
|
||||||
|
|
||||||
|
override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirPropertyWithExplicitBackingFieldResolvedNamedReference {
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -69,11 +69,6 @@ open class ExpressionReceiverValue(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class NarrowedExpressionReceiverValue(
|
|
||||||
explicitReceiver: FirExpression,
|
|
||||||
override val type: ConeKotlinType,
|
|
||||||
) : ExpressionReceiverValue(explicitReceiver)
|
|
||||||
|
|
||||||
sealed class ImplicitReceiverValue<S : FirBasedSymbol<*>>(
|
sealed class ImplicitReceiverValue<S : FirBasedSymbol<*>>(
|
||||||
val boundSymbol: S,
|
val boundSymbol: S,
|
||||||
type: ConeKotlinType,
|
type: ConeKotlinType,
|
||||||
|
|||||||
+1
-66
@@ -5,34 +5,21 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.resolve.calls.tower
|
package org.jetbrains.kotlin.fir.resolve.calls.tower
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
|
||||||
import org.jetbrains.kotlin.fir.asReversedFrozen
|
import org.jetbrains.kotlin.fir.asReversedFrozen
|
||||||
import org.jetbrains.kotlin.fir.containingClass
|
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.canNarrowDownGetterType
|
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.isFinal
|
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.visibility
|
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
|
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
|
||||||
import org.jetbrains.kotlin.fir.expressions.builder.buildExpressionStub
|
import org.jetbrains.kotlin.fir.expressions.builder.buildExpressionStub
|
||||||
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
|
||||||
import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents
|
import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents
|
||||||
import org.jetbrains.kotlin.fir.resolve.DoubleColonLHS
|
import org.jetbrains.kotlin.fir.resolve.DoubleColonLHS
|
||||||
import org.jetbrains.kotlin.fir.resolve.FirTowerDataContext
|
import org.jetbrains.kotlin.fir.resolve.FirTowerDataContext
|
||||||
import org.jetbrains.kotlin.fir.resolve.calls.*
|
import org.jetbrains.kotlin.fir.resolve.calls.*
|
||||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
|
||||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
|
||||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
|
||||||
import org.jetbrains.kotlin.fir.types.FirImplicitTypeRef
|
|
||||||
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
|
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
|
||||||
import org.jetbrains.kotlin.fir.types.coneType
|
|
||||||
import org.jetbrains.kotlin.fir.types.impl.FirImplicitBuiltinTypeRef
|
import org.jetbrains.kotlin.fir.types.impl.FirImplicitBuiltinTypeRef
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
|
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.HIDES_MEMBERS_NAME_LIST
|
import org.jetbrains.kotlin.resolve.descriptorUtil.HIDES_MEMBERS_NAME_LIST
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
|
||||||
|
|
||||||
|
|
||||||
internal class TowerDataElementsForName(
|
internal class TowerDataElementsForName(
|
||||||
name: Name,
|
name: Name,
|
||||||
@@ -236,64 +223,12 @@ internal open class FirTowerResolveTask(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun FirPropertySymbol.hasAccessibleBackingField(info: CallInfo): Boolean {
|
|
||||||
val receiverContainer = containingClass()?.toSymbol(info.session)
|
|
||||||
|
|
||||||
if (!this.isFinal) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return when (fir.backingField?.visibility) {
|
|
||||||
Visibilities.Private -> {
|
|
||||||
info.containingDeclarations.any {
|
|
||||||
it.symbol == receiverContainer
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Visibilities.Internal -> {
|
|
||||||
receiverContainer?.moduleData == info.containingFile.moduleData
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun FirExpression.getNarrowedDownReturnType(info: CallInfo): ConeKotlinType? {
|
|
||||||
val propertyReceiver = this.safeAs<FirQualifiedAccessExpression>()
|
|
||||||
?.calleeReference
|
|
||||||
?.safeAs<FirResolvedNamedReference>()
|
|
||||||
?.resolvedSymbol
|
|
||||||
?.safeAs<FirPropertySymbol>()
|
|
||||||
?: return null
|
|
||||||
|
|
||||||
// This can happen in case of 2 properties referencing
|
|
||||||
// each other recursively. See: Jet81.fir.kt
|
|
||||||
if (
|
|
||||||
propertyReceiver.fir.returnTypeRef is FirImplicitTypeRef ||
|
|
||||||
propertyReceiver.fir.backingField?.returnTypeRef is FirImplicitTypeRef
|
|
||||||
) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
if (propertyReceiver.hasAccessibleBackingField(info) && propertyReceiver.canNarrowDownGetterType) {
|
|
||||||
return propertyReceiver.fir.backingField?.returnTypeRef?.coneType
|
|
||||||
}
|
|
||||||
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun runResolverForExpressionReceiver(
|
suspend fun runResolverForExpressionReceiver(
|
||||||
info: CallInfo,
|
info: CallInfo,
|
||||||
receiver: FirExpression,
|
receiver: FirExpression,
|
||||||
parentGroup: TowerGroup = TowerGroup.EmptyRoot
|
parentGroup: TowerGroup = TowerGroup.EmptyRoot
|
||||||
) {
|
) {
|
||||||
val narrowedType = receiver.getNarrowedDownReturnType(info)
|
val explicitReceiverValue = ExpressionReceiverValue(receiver)
|
||||||
|
|
||||||
val explicitReceiverValue = if (narrowedType != null) {
|
|
||||||
NarrowedExpressionReceiverValue(receiver, narrowedType)
|
|
||||||
} else {
|
|
||||||
ExpressionReceiverValue(receiver)
|
|
||||||
}
|
|
||||||
|
|
||||||
processExtensionsThatHideMembers(info, explicitReceiverValue, parentGroup)
|
processExtensionsThatHideMembers(info, explicitReceiverValue, parentGroup)
|
||||||
|
|
||||||
|
|||||||
+3
@@ -29,6 +29,9 @@ class FirProviderImpl(val session: FirSession, val kotlinScopeProvider: FirKotli
|
|||||||
symbol.originalIfFakeOverride()?.let {
|
symbol.originalIfFakeOverride()?.let {
|
||||||
return getFirCallableContainerFile(it)
|
return getFirCallableContainerFile(it)
|
||||||
}
|
}
|
||||||
|
if (symbol is FirBackingFieldSymbol) {
|
||||||
|
return getFirCallableContainerFile(symbol.fir.propertySymbol)
|
||||||
|
}
|
||||||
if (symbol is FirAccessorSymbol) {
|
if (symbol is FirAccessorSymbol) {
|
||||||
val fir = symbol.fir
|
val fir = symbol.fir
|
||||||
if (fir is FirSyntheticProperty) {
|
if (fir is FirSyntheticProperty) {
|
||||||
|
|||||||
Reference in New Issue
Block a user