FIR. Add visibility/deprecation filtering to getFirstClassifierOrNull

This commit is contained in:
Simon Ogorodnik
2022-02-22 23:16:25 +03:00
committed by Space
parent 4ba5a55626
commit d054976389
3 changed files with 46 additions and 16 deletions
@@ -22,20 +22,20 @@ import org.jetbrains.kotlin.fir.scopes.impl.FirFakeOverrideGenerator
import org.jetbrains.kotlin.fir.scopes.scopeForClass
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.fir.visibilityChecker
import org.jetbrains.kotlin.resolve.deprecation.DeprecationLevelValue
private operator fun <T> Pair<T, *>?.component1() = this?.first
private operator fun <T> Pair<*, T>?.component2() = this?.second
internal fun FirScope.processConstructorsByName(
name: Name,
callInfo: CallInfo,
session: FirSession,
bodyResolveComponents: BodyResolveComponents,
includeInnerConstructors: Boolean,
processor: (FirCallableSymbol<*>) -> Unit
) {
// TODO: Handle case with two or more accessible classifiers
val classifierInfo = getFirstClassifierOrNull(name)
val classifierInfo = getFirstClassifierOrNull(callInfo, session, bodyResolveComponents)
if (classifierInfo != null) {
val (matchedClassifierSymbol, substitutor) = classifierInfo
val matchedClassSymbol = matchedClassifierSymbol as? FirClassLikeSymbol<*>
@@ -58,30 +58,60 @@ internal fun FirScope.processConstructorsByName(
}
internal fun FirScope.processFunctionsAndConstructorsByName(
name: Name,
callInfo: CallInfo,
session: FirSession,
bodyResolveComponents: BodyResolveComponents,
includeInnerConstructors: Boolean,
processor: (FirCallableSymbol<*>) -> Unit
) {
processConstructorsByName(
name, session, bodyResolveComponents,
callInfo, session, bodyResolveComponents,
includeInnerConstructors = includeInnerConstructors,
processor
)
processFunctionsByName(name, processor)
processFunctionsByName(callInfo.name, processor)
}
private fun FirScope.getFirstClassifierOrNull(name: Name): Pair<FirClassifierSymbol<*>, ConeSubstitutor>? {
private fun FirScope.getFirstClassifierOrNull(
callInfo: CallInfo,
session: FirSession,
bodyResolveComponents: BodyResolveComponents
): Pair<FirClassifierSymbol<*>, ConeSubstitutor>? {
var successful = false
var ambiguity = false
var result: Pair<FirClassifierSymbol<*>, ConeSubstitutor>? = null
processClassifiersByNameWithSubstitution(name) { symbol, substitution ->
if (result == null) {
processClassifiersByNameWithSubstitution(callInfo.name) { symbol, substitution ->
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
}
if (result == null || (!successful && isSuccessCandidate)) {
successful = isSuccessCandidate
result = symbol to substitution
} else {
ambiguity = true
}
}
return result
return result.takeUnless { ambiguity }
}
private fun processSyntheticConstructors(
@@ -143,7 +143,7 @@ class MemberScopeTowerLevel(
return processMembers(processor) { consumer ->
withMemberCallLookup(lookupTracker, info) { lookupCtx ->
this.processFunctionsAndConstructorsByName(
info.name, session, bodyResolveComponents,
info, session, bodyResolveComponents,
includeInnerConstructors = true,
processor = {
lookupCtx.recordCallableMemberLookup(it)
@@ -313,7 +313,7 @@ class ScopeTowerLevel(
var empty = true
session.lookupTracker?.recordCallLookup(info, scope.scopeOwnerLookupNames)
scope.processFunctionsAndConstructorsByName(
info.name,
info,
session,
bodyResolveComponents,
includeInnerConstructors = includeInnerConstructors
@@ -35,7 +35,7 @@ import lib1Case2.*
import kotlin.text.*
fun case2() {
<!DEBUG_INFO_CALL("fqName: kotlin.text.Regex.Regex; typeCall: function")!>Regex("")<!>
<!DEBUG_INFO_CALL("fqName: fqName is unknown; typeCall: unresolved")!><!OVERLOAD_RESOLUTION_AMBIGUITY!>Regex<!>("")<!>
}
// FILE: Lib2.kt
@@ -68,7 +68,7 @@ import libCase3.*
import kotlin.text.*
fun case3() {
<!DEBUG_INFO_CALL("fqName: kotlin.text.Regex.Regex; typeCall: function")!>Regex("")<!>
<!DEBUG_INFO_CALL("fqName: libCase3.Regex.Companion.invoke; typeCall: variable&invoke")!>Regex("")<!>
}
// FILE: Lib3.kt
@@ -95,7 +95,7 @@ import lib1Case4.*
import kotlin.text.*
fun case4() {
<!DEBUG_INFO_CALL("fqName: kotlin.text.Regex.Regex; typeCall: function")!>Regex("")<!>
<!DEBUG_INFO_CALL("fqName: lib1Case4.Regex.Companion.invoke; typeCall: variable&invoke")!>Regex("")<!>
}
// FILE: Lib4.kt