FIR: add visibility filtering for qualifier resolve #KT-51621 Fixed

This commit is contained in:
Mikhail Glukhikh
2022-03-15 12:49:01 +03:00
committed by Space
parent 3251c474a2
commit c051edcbee
5 changed files with 42 additions and 26 deletions
@@ -2,5 +2,5 @@ FILE: test.kt
package test
public final fun test(): R|kotlin/Unit| {
R|kotlin/Unit|.R|first/Some.foo|()
Q|first/Some|.R|first/Some.foo|()
}
@@ -22,5 +22,5 @@ import first.*
import second.*
fun test() {
<!NO_COMPANION_OBJECT!>Some<!>.foo()
Some.foo()
}
@@ -288,9 +288,9 @@ class FirCallResolver(
qualifiedAccess.source,
qualifiedAccess.typeArguments,
nonFatalDiagnosticFromExpression,
session,
components
)
?.let { return it }
)?.let { return it }
}
var result = basicResult
@@ -13,11 +13,11 @@ import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
import org.jetbrains.kotlin.fir.expressions.builder.buildResolvedQualifier
import org.jetbrains.kotlin.fir.references.impl.FirSimpleNamedReference
import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents
import org.jetbrains.kotlin.fir.resolve.calls.getSingleVisibleClassifier
import org.jetbrains.kotlin.fir.resolve.createCurrentScopeList
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeDeprecated
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType
import org.jetbrains.kotlin.fir.resolve.typeForQualifier
import org.jetbrains.kotlin.fir.scopes.getSingleClassifier
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.fir.types.FirTypeProjection
@@ -45,7 +45,7 @@ fun BodyResolveComponents.resolveRootPartOfQualifier(
}
for (scope in createCurrentScopeList()) {
scope.getSingleClassifier(name)?.let {
scope.getSingleVisibleClassifier(session, this, name)?.let {
if (it is FirRegularClassSymbol) {
val isVisible = session.visibilityChecker.isVisible(
it.fir,
@@ -88,6 +88,7 @@ fun FirResolvedQualifier.continueQualifier(
source: KtSourceElement?,
typeArguments: List<FirTypeProjection>,
nonFatalDiagnosticsFromExpression: List<ConeDiagnostic>?,
session: FirSession,
components: BodyResolveComponents,
): FirResolvedQualifier? {
val name = namedReference.name
@@ -95,7 +96,7 @@ fun FirResolvedQualifier.continueQualifier(
val firClass = outerClassSymbol.fir
if (firClass !is FirClass) return null
return firClass.scopeProvider.getNestedClassifierScope(firClass, components.session, components.scopeSession)
?.getSingleClassifier(name)
?.getSingleVisibleClassifier(session, components, name)
?.takeIf { it is FirClassLikeSymbol<*> }
?.let { nestedClassSymbol ->
buildResolvedQualifier {
@@ -19,10 +19,12 @@ import org.jetbrains.kotlin.fir.symbols.ensureResolved
import org.jetbrains.kotlin.fir.scopes.FakeOverrideTypeCalculator
import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.scopes.impl.FirFakeOverrideGenerator
import org.jetbrains.kotlin.fir.scopes.processClassifiersByName
import org.jetbrains.kotlin.fir.scopes.scopeForClass
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.visibilityChecker
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.deprecation.DeprecationLevelValue
private operator fun <T> Pair<T, *>?.component1() = this?.first
@@ -75,6 +77,37 @@ internal fun FirScope.processFunctionsAndConstructorsByName(
private data class SymbolWithSubstitutor(val symbol: FirClassifierSymbol<*>, val substitutor: ConeSubstitutor)
fun FirScope.getSingleVisibleClassifier(
session: FirSession,
bodyResolveComponents: BodyResolveComponents,
name: Name
): FirClassifierSymbol<*>? = mutableSetOf<FirClassifierSymbol<*>>().apply {
processClassifiersByName(name) { classifierSymbol ->
if (!classifierSymbol.fir.isInvisibleOrHidden(session, bodyResolveComponents)) {
this.add(classifierSymbol)
}
}
}.singleOrNull()
private fun FirDeclaration.isInvisibleOrHidden(session: FirSession, bodyResolveComponents: BodyResolveComponents): Boolean {
if (this is FirMemberDeclaration) {
if (!session.visibilityChecker.isVisible(
this,
session,
bodyResolveComponents.file,
bodyResolveComponents.containingDeclarations,
dispatchReceiver = null,
isCallToPropertySetter = false
)
) {
return true
}
}
val deprecation = symbol.getDeprecationForCallSite()
return deprecation != null && deprecation.deprecationLevel == DeprecationLevelValue.HIDDEN
}
private fun FirScope.getFirstClassifierOrNull(
callInfo: CallInfo,
session: FirSession,
@@ -85,25 +118,7 @@ private fun FirScope.getFirstClassifierOrNull(
var result: SymbolWithSubstitutor? = null
processClassifiersByNameWithSubstitution(callInfo.name) { symbol, substitutor ->
val classifierDeclaration = symbol.fir
var isSuccessCandidate = true
if (classifierDeclaration is FirMemberDeclaration) {
if (!session.visibilityChecker.isVisible(
classifierDeclaration,
session,
bodyResolveComponents.file,
bodyResolveComponents.containingDeclarations,
dispatchReceiver = null,
isCallToPropertySetter = false
)
) {
isSuccessCandidate = false
}
}
val deprecation = symbol.getDeprecationForCallSite()
if (deprecation != null && deprecation.deprecationLevel == DeprecationLevelValue.HIDDEN) {
isSuccessCandidate = false
}
val isSuccessCandidate = !classifierDeclaration.isInvisibleOrHidden(session, bodyResolveComponents)
when {
isSuccessCandidate && !isSuccessResult -> {