[FIR] Implement INVISIBLE_SETTER

This commit is contained in:
Ivan Kochurkin
2021-07-27 22:40:00 +03:00
committed by teamcityserver
parent ca4410aa53
commit b3d7ed569d
39 changed files with 288 additions and 180 deletions
@@ -5,22 +5,23 @@
package org.jetbrains.kotlin.fir
import org.jetbrains.kotlin.config.LanguageFeature
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.FirQualifiedAccessExpression
import org.jetbrains.kotlin.fir.expressions.FirThisReceiverExpression
import org.jetbrains.kotlin.fir.references.impl.FirExplicitSuperReference
import org.jetbrains.kotlin.fir.resolve.*
import org.jetbrains.kotlin.fir.resolve.calls.Candidate
import org.jetbrains.kotlin.fir.resolve.calls.FirSyntheticFunctionSymbol
import org.jetbrains.kotlin.fir.resolve.calls.ReceiverValue
import org.jetbrains.kotlin.fir.resolve.firProvider
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
import org.jetbrains.kotlin.fir.resolve.lookupSuperTypes
import org.jetbrains.kotlin.fir.resolve.symbolProvider
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
import org.jetbrains.kotlin.fir.types.toSymbol
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
@@ -116,7 +117,13 @@ abstract class FirVisibilityChecker : FirSessionComponent {
Visibilities.Protected -> {
val ownerId = symbol.getOwnerId()
ownerId != null && canSeeProtectedMemberOf(containingDeclarations, dispatchReceiver, ownerId, session)
ownerId != null && canSeeProtectedMemberOf(
containingDeclarations,
dispatchReceiver,
ownerId,
symbol.fir is FirSyntheticPropertyAccessor,
session
)
}
else -> platformVisibilityCheck(
@@ -171,22 +178,43 @@ abstract class FirVisibilityChecker : FirSessionComponent {
}
private fun canSeeProtectedMemberOf(
containingUseSiteClass: FirClass,
containingUseSiteClassSymbol: FirClassSymbol<*>,
dispatchReceiver: ReceiverValue?,
ownerId: ClassId, session: FirSession
ownerId: ClassId,
isSyntheticProperty: Boolean,
session: FirSession
): Boolean {
dispatchReceiver?.ownerIfCompanion(session)?.let { companionOwnerClassId ->
if (containingUseSiteClass.isSubClass(companionOwnerClassId, session)) return true
if (containingUseSiteClassSymbol.isSubClass(companionOwnerClassId, session)) return true
}
// TODO: Add check for receiver, see org.jetbrains.kotlin.descriptors.Visibility#doesReceiverFitForProtectedVisibility
return containingUseSiteClass.isSubClass(ownerId, session)
if (containingUseSiteClassSymbol.isSubClass(ownerId, session)) {
val receiverExpression = dispatchReceiver?.receiverExpression
if (receiverExpression == null ||
receiverExpression is FirThisReceiverExpression ||
(receiverExpression is FirQualifiedAccessExpression && receiverExpression.calleeReference is FirExplicitSuperReference) ||
dispatchReceiver.type.toSymbol(session).isSubClass(containingUseSiteClassSymbol.classId, session)
) {
return true
}
if (isSyntheticProperty) {
return if (session.languageVersionSettings.supportsFeature(LanguageFeature.ImproveReportingDiagnosticsOnProtectedMembersOfBaseClass))
containingUseSiteClassSymbol.classId.packageFqName == ownerId.packageFqName
else
true
}
}
return false
}
private fun FirClass.isSubClass(ownerId: ClassId, session: FirSession): Boolean {
private fun FirBasedSymbol<*>?.isSubClass(ownerId: ClassId, session: FirSession): Boolean {
val classSymbol = this as? FirClassSymbol<*> ?: return false
val classId = classSymbol.classId
if (classId.isSame(ownerId)) return true
return lookupSuperTypes(this, lookupInterfaces = true, deep = true, session).any { superType ->
return lookupSuperTypes(classSymbol, lookupInterfaces = true, deep = true, session).any { superType ->
(superType as? ConeClassLikeType)?.fullyExpandedType(session)?.lookupTag?.classId?.isSame(ownerId) == true
}
}
@@ -207,14 +235,16 @@ abstract class FirVisibilityChecker : FirSessionComponent {
protected fun canSeeProtectedMemberOf(
containingDeclarationOfUseSite: List<FirDeclaration>,
dispatchReceiver: ReceiverValue?,
ownerId: ClassId, session: FirSession
ownerId: ClassId,
isSyntheticProperty: Boolean,
session: FirSession
): Boolean {
if (canSeePrivateMemberOf(containingDeclarationOfUseSite, ownerId, session)) return true
for (containingDeclaration in containingDeclarationOfUseSite) {
if (containingDeclaration !is FirClass) continue
val boundSymbol = containingDeclaration.symbol
if (canSeeProtectedMemberOf(boundSymbol.fir, dispatchReceiver, ownerId, session)) return true
if (canSeeProtectedMemberOf(boundSymbol.fir.symbol, dispatchReceiver, ownerId, isSyntheticProperty, session)) return true
}
return false
@@ -49,9 +49,20 @@ fun lookupSuperTypes(
useSiteSession: FirSession,
supertypeSupplier: SupertypeSupplier = SupertypeSupplier.Default,
substituteTypes: Boolean = false
): List<ConeClassLikeType> {
return lookupSuperTypes(klass.symbol, lookupInterfaces, deep, useSiteSession, supertypeSupplier, substituteTypes)
}
fun lookupSuperTypes(
classSymbol: FirClassSymbol<*>,
lookupInterfaces: Boolean,
deep: Boolean,
useSiteSession: FirSession,
supertypeSupplier: SupertypeSupplier = SupertypeSupplier.Default,
substituteTypes: Boolean = false
): List<ConeClassLikeType> {
return SmartList<ConeClassLikeType>().also {
klass.symbol.collectSuperTypes(it, SmartSet.create(), deep, lookupInterfaces, substituteTypes, useSiteSession, supertypeSupplier)
classSymbol.collectSuperTypes(it, SmartSet.create(), deep, lookupInterfaces, substituteTypes, useSiteSession, supertypeSupplier)
}
}