[FIR] Fix visibility issues with private members within inner and anonymous scopes ^KT-49992 Fixed
This commit is contained in:
@@ -6,17 +6,17 @@
|
||||
package org.jetbrains.kotlin.fir
|
||||
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.descriptors.Visibility
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticPropertyAccessor
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.*
|
||||
import org.jetbrains.kotlin.fir.expressions.FirPropertyAccessExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirThisReceiverExpression
|
||||
import org.jetbrains.kotlin.fir.references.FirSuperReference
|
||||
import org.jetbrains.kotlin.fir.resolve.*
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.ExpressionReceiverValue
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.FirSyntheticFunctionSymbol
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.ReceiverValue
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.*
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.firProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
|
||||
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
|
||||
@@ -140,6 +140,7 @@ abstract class FirVisibilityChecker : FirSessionComponent {
|
||||
): Boolean {
|
||||
val symbol = declaration.symbol
|
||||
val provider = session.firProvider
|
||||
|
||||
return when (declaration.visibility) {
|
||||
Visibilities.Internal -> {
|
||||
declaration.moduleData == session.moduleData || session.moduleVisibilityChecker?.isInFriendModule(declaration) == true
|
||||
@@ -168,7 +169,13 @@ abstract class FirVisibilityChecker : FirSessionComponent {
|
||||
}
|
||||
else -> {
|
||||
// Member: visible inside parent class, including all its member classes
|
||||
canSeePrivateMemberOf(containingDeclarations, ownerLookupTag, session)
|
||||
canSeePrivateMemberOf(
|
||||
containingDeclarations,
|
||||
ownerLookupTag,
|
||||
dispatchReceiver,
|
||||
isVariableOrNamedFunction = symbol.isVariableOrNamedFunction(),
|
||||
session
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -180,7 +187,7 @@ abstract class FirVisibilityChecker : FirSessionComponent {
|
||||
val ownerId = symbol.getOwnerLookupTag()
|
||||
ownerId != null && canSeeProtectedMemberOf(
|
||||
containingDeclarations, dispatchReceiver, ownerId, session,
|
||||
isVariableOrNamedFunction = symbol is FirVariableSymbol || symbol is FirNamedFunctionSymbol || symbol is FirPropertyAccessorSymbol,
|
||||
isVariableOrNamedFunction = symbol.isVariableOrNamedFunction(),
|
||||
symbol.fir is FirSyntheticPropertyAccessor,
|
||||
supertypeSupplier
|
||||
)
|
||||
@@ -213,21 +220,76 @@ abstract class FirVisibilityChecker : FirSessionComponent {
|
||||
private fun canSeePrivateMemberOf(
|
||||
containingDeclarationOfUseSite: List<FirDeclaration>,
|
||||
ownerLookupTag: ConeClassLikeLookupTag,
|
||||
dispatchReceiver: ReceiverValue?,
|
||||
isVariableOrNamedFunction: Boolean,
|
||||
session: FirSession
|
||||
): Boolean {
|
||||
ownerLookupTag.ownerIfCompanion(session)?.let { companionOwnerLookupTag ->
|
||||
return canSeePrivateMemberOf(containingDeclarationOfUseSite, companionOwnerLookupTag, session)
|
||||
return canSeePrivateMemberOf(
|
||||
containingDeclarationOfUseSite,
|
||||
companionOwnerLookupTag,
|
||||
dispatchReceiver,
|
||||
isVariableOrNamedFunction,
|
||||
session
|
||||
)
|
||||
}
|
||||
|
||||
for (declaration in containingDeclarationOfUseSite) {
|
||||
if (declaration !is FirClass) continue
|
||||
val boundSymbol = declaration.symbol
|
||||
if (boundSymbol.classId.isSame(ownerLookupTag.classId)) {
|
||||
return true
|
||||
fun matchWithContainingDeclarations(): Boolean {
|
||||
for (declaration in containingDeclarationOfUseSite) {
|
||||
if (declaration !is FirClass) continue
|
||||
val boundSymbol = declaration.symbol
|
||||
if (boundSymbol.classId.isSame(ownerLookupTag.classId)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
return false
|
||||
return if (isVariableOrNamedFunction && dispatchReceiver?.type is ConeClassLikeType) {
|
||||
if (dispatchReceiver is ImplicitDispatchReceiverValue) {
|
||||
val dispatchReceiverOwnerClassId = dispatchReceiver.ownerIfCompanion(session)?.classId ?: dispatchReceiver.type.classId
|
||||
var isMemberFound = false
|
||||
for (declaration in containingDeclarationOfUseSite) {
|
||||
if (declaration !is FirClass) continue
|
||||
|
||||
val boundSymbol = declaration.symbol
|
||||
var isSameClasses = false
|
||||
if (!isMemberFound) {
|
||||
isSameClasses = boundSymbol.classId.isSame(ownerLookupTag.classId)
|
||||
if (isSameClasses) {
|
||||
isMemberFound = true
|
||||
}
|
||||
}
|
||||
if (isMemberFound) {
|
||||
if (!isSameClasses && !(
|
||||
declaration.isInner ||
|
||||
(declaration.containingNonLocalClass(session) as? FirRegularClass)?.classKind == ClassKind.OBJECT)
|
||||
) {
|
||||
// It should not be ordinary classes between use site and declaration
|
||||
return false
|
||||
}
|
||||
if (boundSymbol.classId.isSame(dispatchReceiverOwnerClassId!!)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
isMemberFound
|
||||
} else {
|
||||
val receiverExpression = dispatchReceiver.receiverExpression
|
||||
if (receiverExpression is FirThisReceiverExpression &&
|
||||
receiverExpression.source != null &&
|
||||
(containingDeclarationOfUseSite.lastOrNull() as? FirFunction)?.symbol?.isExtension != true
|
||||
) {
|
||||
// Processing of explicit no extension `this`
|
||||
val dispatchReceiverOwnerClassId = dispatchReceiver.ownerIfCompanion(session)?.classId ?: dispatchReceiver.type.classId
|
||||
dispatchReceiverOwnerClassId?.isSame(ownerLookupTag.classId) == true
|
||||
} else {
|
||||
matchWithContainingDeclarations()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
matchWithContainingDeclarations()
|
||||
}
|
||||
}
|
||||
|
||||
// 'local' isn't taken into account here
|
||||
@@ -350,7 +412,14 @@ abstract class FirVisibilityChecker : FirSessionComponent {
|
||||
isSyntheticProperty: Boolean,
|
||||
supertypeSupplier: SupertypeSupplier
|
||||
): Boolean {
|
||||
if (canSeePrivateMemberOf(containingDeclarationOfUseSite, ownerLookupTag, session)) return true
|
||||
if (canSeePrivateMemberOf(
|
||||
containingDeclarationOfUseSite,
|
||||
ownerLookupTag,
|
||||
dispatchReceiver,
|
||||
isVariableOrNamedFunction,
|
||||
session
|
||||
)
|
||||
) return true
|
||||
|
||||
for (containingDeclaration in containingDeclarationOfUseSite) {
|
||||
if (containingDeclaration is FirClass) {
|
||||
@@ -405,3 +474,7 @@ fun FirBasedSymbol<*>.getOwnerLookupTag(): ConeClassLikeLookupTag? {
|
||||
else -> error("Unsupported owner search for ${fir.javaClass}: ${fir.render()}")
|
||||
}
|
||||
}
|
||||
|
||||
fun FirBasedSymbol<*>.isVariableOrNamedFunction(): Boolean {
|
||||
return this is FirVariableSymbol || this is FirNamedFunctionSymbol || this is FirPropertyAccessorSymbol
|
||||
}
|
||||
Reference in New Issue
Block a user