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 package test
public final fun test(): R|kotlin/Unit| { 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.* import second.*
fun test() { fun test() {
<!NO_COMPANION_OBJECT!>Some<!>.foo() Some.foo()
} }
@@ -288,9 +288,9 @@ class FirCallResolver(
qualifiedAccess.source, qualifiedAccess.source,
qualifiedAccess.typeArguments, qualifiedAccess.typeArguments,
nonFatalDiagnosticFromExpression, nonFatalDiagnosticFromExpression,
session,
components components
) )?.let { return it }
?.let { return it }
} }
var result = basicResult 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.expressions.builder.buildResolvedQualifier
import org.jetbrains.kotlin.fir.references.impl.FirSimpleNamedReference import org.jetbrains.kotlin.fir.references.impl.FirSimpleNamedReference
import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents 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.createCurrentScopeList
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeDeprecated import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeDeprecated
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType
import org.jetbrains.kotlin.fir.resolve.typeForQualifier 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.FirClassLikeSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.fir.types.FirTypeProjection import org.jetbrains.kotlin.fir.types.FirTypeProjection
@@ -45,7 +45,7 @@ fun BodyResolveComponents.resolveRootPartOfQualifier(
} }
for (scope in createCurrentScopeList()) { for (scope in createCurrentScopeList()) {
scope.getSingleClassifier(name)?.let { scope.getSingleVisibleClassifier(session, this, name)?.let {
if (it is FirRegularClassSymbol) { if (it is FirRegularClassSymbol) {
val isVisible = session.visibilityChecker.isVisible( val isVisible = session.visibilityChecker.isVisible(
it.fir, it.fir,
@@ -88,6 +88,7 @@ fun FirResolvedQualifier.continueQualifier(
source: KtSourceElement?, source: KtSourceElement?,
typeArguments: List<FirTypeProjection>, typeArguments: List<FirTypeProjection>,
nonFatalDiagnosticsFromExpression: List<ConeDiagnostic>?, nonFatalDiagnosticsFromExpression: List<ConeDiagnostic>?,
session: FirSession,
components: BodyResolveComponents, components: BodyResolveComponents,
): FirResolvedQualifier? { ): FirResolvedQualifier? {
val name = namedReference.name val name = namedReference.name
@@ -95,7 +96,7 @@ fun FirResolvedQualifier.continueQualifier(
val firClass = outerClassSymbol.fir val firClass = outerClassSymbol.fir
if (firClass !is FirClass) return null if (firClass !is FirClass) return null
return firClass.scopeProvider.getNestedClassifierScope(firClass, components.session, components.scopeSession) return firClass.scopeProvider.getNestedClassifierScope(firClass, components.session, components.scopeSession)
?.getSingleClassifier(name) ?.getSingleVisibleClassifier(session, components, name)
?.takeIf { it is FirClassLikeSymbol<*> } ?.takeIf { it is FirClassLikeSymbol<*> }
?.let { nestedClassSymbol -> ?.let { nestedClassSymbol ->
buildResolvedQualifier { 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.FakeOverrideTypeCalculator
import org.jetbrains.kotlin.fir.scopes.FirScope import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.scopes.impl.FirFakeOverrideGenerator 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.scopes.scopeForClass
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.fir.visibilityChecker import org.jetbrains.kotlin.fir.visibilityChecker
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.deprecation.DeprecationLevelValue import org.jetbrains.kotlin.resolve.deprecation.DeprecationLevelValue
private operator fun <T> Pair<T, *>?.component1() = this?.first 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) 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( private fun FirScope.getFirstClassifierOrNull(
callInfo: CallInfo, callInfo: CallInfo,
session: FirSession, session: FirSession,
@@ -85,25 +118,7 @@ private fun FirScope.getFirstClassifierOrNull(
var result: SymbolWithSubstitutor? = null var result: SymbolWithSubstitutor? = null
processClassifiersByNameWithSubstitution(callInfo.name) { symbol, substitutor -> processClassifiersByNameWithSubstitution(callInfo.name) { symbol, substitutor ->
val classifierDeclaration = symbol.fir val classifierDeclaration = symbol.fir
var isSuccessCandidate = true val isSuccessCandidate = !classifierDeclaration.isInvisibleOrHidden(session, bodyResolveComponents)
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
}
when { when {
isSuccessCandidate && !isSuccessResult -> { isSuccessCandidate && !isSuccessResult -> {