FIR. Remove visibility filtering from importing scopes
This commit is contained in:
+6
-39
@@ -6,12 +6,9 @@
|
|||||||
package org.jetbrains.kotlin.fir.scopes.impl
|
package org.jetbrains.kotlin.fir.scopes.impl
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
|
||||||
import org.jetbrains.kotlin.fir.FirSession
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirResolvedImport
|
import org.jetbrains.kotlin.fir.declarations.FirResolvedImport
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.expandedConeType
|
import org.jetbrains.kotlin.fir.declarations.utils.expandedConeType
|
||||||
import org.jetbrains.kotlin.fir.moduleData
|
|
||||||
import org.jetbrains.kotlin.fir.moduleVisibilityChecker
|
|
||||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||||
import org.jetbrains.kotlin.fir.resolve.transformers.ensureResolvedForCalls
|
import org.jetbrains.kotlin.fir.resolve.transformers.ensureResolvedForCalls
|
||||||
@@ -21,32 +18,9 @@ import org.jetbrains.kotlin.fir.symbols.impl.*
|
|||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
|
||||||
enum class FirImportingScopeFilter {
|
|
||||||
ALL, INVISIBLE_CLASSES, MEMBERS_AND_VISIBLE_CLASSES;
|
|
||||||
|
|
||||||
fun check(symbol: FirClassLikeSymbol<*>, session: FirSession): Boolean {
|
|
||||||
if (this == ALL) return true
|
|
||||||
// TODO: also check DeprecationLevel.HIDDEN and required Kotlin version
|
|
||||||
val fir = symbol.fir
|
|
||||||
val isVisible = when (fir.status.visibility) {
|
|
||||||
// When importing from the same module, status may be unknown because the status resolver depends on super types
|
|
||||||
// to determine visibility for functions, so it may not have finished yet. Since we only care about classes,
|
|
||||||
// though, "unknown" will always become public anyway.
|
|
||||||
Visibilities.Unknown -> true
|
|
||||||
Visibilities.Internal ->
|
|
||||||
symbol.fir.moduleData == session.moduleData || session.moduleVisibilityChecker?.isInFriendModule(fir) == true
|
|
||||||
// All non-`internal` visibilities are either even more restrictive (e.g. `private`) or must not
|
|
||||||
// be checked in imports (e.g. `protected` may be valid in some use sites).
|
|
||||||
else -> !fir.status.visibility.mustCheckInImports()
|
|
||||||
}
|
|
||||||
return isVisible == (this == MEMBERS_AND_VISIBLE_CLASSES)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract class FirAbstractImportingScope(
|
abstract class FirAbstractImportingScope(
|
||||||
session: FirSession,
|
session: FirSession,
|
||||||
protected val scopeSession: ScopeSession,
|
protected val scopeSession: ScopeSession,
|
||||||
protected val filter: FirImportingScopeFilter,
|
|
||||||
lookupInFir: Boolean
|
lookupInFir: Boolean
|
||||||
) : FirAbstractProviderBasedScope(session, lookupInFir) {
|
) : FirAbstractProviderBasedScope(session, lookupInFir) {
|
||||||
private val FirClassLikeSymbol<*>.fullyExpandedSymbol: FirClassSymbol<*>?
|
private val FirClassLikeSymbol<*>.fullyExpandedSymbol: FirClassSymbol<*>?
|
||||||
@@ -67,27 +41,21 @@ abstract class FirAbstractImportingScope(
|
|||||||
fun getStaticsScope(classId: ClassId): FirContainingNamesAwareScope? =
|
fun getStaticsScope(classId: ClassId): FirContainingNamesAwareScope? =
|
||||||
provider.getClassLikeSymbolByClassId(classId)?.fullyExpandedSymbol?.getStaticsScope()
|
provider.getClassLikeSymbolByClassId(classId)?.fullyExpandedSymbol?.getStaticsScope()
|
||||||
|
|
||||||
protected fun findSingleClassifierSymbolByName(name: Name?, imports: List<FirResolvedImport>): FirClassLikeSymbol<*>? {
|
protected fun processImportsByName(
|
||||||
var result: FirClassLikeSymbol<*>? = null
|
name: Name?,
|
||||||
|
imports: List<FirResolvedImport>,
|
||||||
|
processor: (FirClassLikeSymbol<*>) -> Unit
|
||||||
|
) {
|
||||||
for (import in imports) {
|
for (import in imports) {
|
||||||
val importedName = name ?: import.importedName ?: continue
|
val importedName = name ?: import.importedName ?: continue
|
||||||
val classId = import.resolvedParentClassId?.createNestedClassId(importedName)
|
val classId = import.resolvedParentClassId?.createNestedClassId(importedName)
|
||||||
?: ClassId.topLevel(import.packageFqName.child(importedName))
|
?: ClassId.topLevel(import.packageFqName.child(importedName))
|
||||||
val symbol = provider.getClassLikeSymbolByClassId(classId) ?: continue
|
val symbol = provider.getClassLikeSymbolByClassId(classId) ?: continue
|
||||||
if (!filter.check(symbol, session)) continue
|
processor(symbol)
|
||||||
result = when (result) {
|
|
||||||
null, symbol -> symbol
|
|
||||||
// TODO: if there is an ambiguity at this scope, further scopes should not be checked.
|
|
||||||
// Doing otherwise causes KT-39073. Also, returning null here instead of an error symbol
|
|
||||||
// or something produces poor quality diagnostics ("unresolved name" rather than "ambiguity").
|
|
||||||
else -> return null
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun processFunctionsByName(name: Name?, imports: List<FirResolvedImport>, processor: (FirNamedFunctionSymbol) -> Unit) {
|
protected fun processFunctionsByName(name: Name?, imports: List<FirResolvedImport>, processor: (FirNamedFunctionSymbol) -> Unit) {
|
||||||
if (filter == FirImportingScopeFilter.INVISIBLE_CLASSES) return
|
|
||||||
for (import in imports) {
|
for (import in imports) {
|
||||||
val importedName = name ?: import.importedName ?: continue
|
val importedName = name ?: import.importedName ?: continue
|
||||||
val staticsScope = import.resolvedParentClassId?.let(::getStaticsScope)
|
val staticsScope = import.resolvedParentClassId?.let(::getStaticsScope)
|
||||||
@@ -103,7 +71,6 @@ abstract class FirAbstractImportingScope(
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected fun processPropertiesByName(name: Name?, imports: List<FirResolvedImport>, processor: (FirVariableSymbol<*>) -> Unit) {
|
protected fun processPropertiesByName(name: Name?, imports: List<FirResolvedImport>, processor: (FirVariableSymbol<*>) -> Unit) {
|
||||||
if (filter == FirImportingScopeFilter.INVISIBLE_CLASSES) return
|
|
||||||
for (import in imports) {
|
for (import in imports) {
|
||||||
val importedName = name ?: import.importedName ?: continue
|
val importedName = name ?: import.importedName ?: continue
|
||||||
val staticsScope = import.resolvedParentClassId?.let(::getStaticsScope)
|
val staticsScope = import.resolvedParentClassId?.let(::getStaticsScope)
|
||||||
|
|||||||
+4
-3
@@ -17,15 +17,16 @@ import org.jetbrains.kotlin.name.Name
|
|||||||
abstract class FirAbstractSimpleImportingScope(
|
abstract class FirAbstractSimpleImportingScope(
|
||||||
session: FirSession,
|
session: FirSession,
|
||||||
scopeSession: ScopeSession
|
scopeSession: ScopeSession
|
||||||
) : FirAbstractImportingScope(session, scopeSession, FirImportingScopeFilter.ALL, lookupInFir = true) {
|
) : FirAbstractImportingScope(session, scopeSession, lookupInFir = true) {
|
||||||
|
|
||||||
// TODO try to hide this
|
// TODO try to hide this
|
||||||
abstract val simpleImports: Map<Name, List<FirResolvedImport>>
|
abstract val simpleImports: Map<Name, List<FirResolvedImport>>
|
||||||
|
|
||||||
override fun processClassifiersByNameWithSubstitution(name: Name, processor: (FirClassifierSymbol<*>, ConeSubstitutor) -> Unit) {
|
override fun processClassifiersByNameWithSubstitution(name: Name, processor: (FirClassifierSymbol<*>, ConeSubstitutor) -> Unit) {
|
||||||
val imports = simpleImports[name] ?: return
|
val imports = simpleImports[name] ?: return
|
||||||
val symbol = findSingleClassifierSymbolByName(null, imports) ?: return
|
processImportsByName(null, imports) { symbol ->
|
||||||
processor(symbol, ConeSubstitutor.Empty)
|
processor(symbol, ConeSubstitutor.Empty)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun processFunctionsByName(name: Name, processor: (FirNamedFunctionSymbol) -> Unit) {
|
override fun processFunctionsByName(name: Name, processor: (FirNamedFunctionSymbol) -> Unit) {
|
||||||
|
|||||||
+6
-5
@@ -17,9 +17,8 @@ import org.jetbrains.kotlin.name.Name
|
|||||||
abstract class FirAbstractStarImportingScope(
|
abstract class FirAbstractStarImportingScope(
|
||||||
session: FirSession,
|
session: FirSession,
|
||||||
scopeSession: ScopeSession,
|
scopeSession: ScopeSession,
|
||||||
filter: FirImportingScopeFilter,
|
|
||||||
lookupInFir: Boolean
|
lookupInFir: Boolean
|
||||||
) : FirAbstractImportingScope(session, scopeSession, filter, lookupInFir) {
|
) : FirAbstractImportingScope(session, scopeSession, lookupInFir) {
|
||||||
|
|
||||||
// TODO try to hide this
|
// TODO try to hide this
|
||||||
abstract val starImports: List<FirResolvedImport>
|
abstract val starImports: List<FirResolvedImport>
|
||||||
@@ -30,10 +29,12 @@ abstract class FirAbstractStarImportingScope(
|
|||||||
if ((!name.isSpecial && name.identifier.isEmpty()) || starImports.isEmpty() || name in absentClassifierNames) {
|
if ((!name.isSpecial && name.identifier.isEmpty()) || starImports.isEmpty() || name in absentClassifierNames) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val symbol = findSingleClassifierSymbolByName(name, starImports)
|
var foundAny = false
|
||||||
if (symbol != null) {
|
processImportsByName(name, starImports) { symbol ->
|
||||||
|
foundAny = true
|
||||||
processor(symbol, ConeSubstitutor.Empty)
|
processor(symbol, ConeSubstitutor.Empty)
|
||||||
} else {
|
}
|
||||||
|
if (!foundAny) {
|
||||||
absentClassifierNames += name
|
absentClassifierNames += name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-4
@@ -20,10 +20,9 @@ import org.jetbrains.kotlin.name.Name
|
|||||||
class FirDefaultStarImportingScope(
|
class FirDefaultStarImportingScope(
|
||||||
session: FirSession,
|
session: FirSession,
|
||||||
scopeSession: ScopeSession,
|
scopeSession: ScopeSession,
|
||||||
filter: FirImportingScopeFilter,
|
|
||||||
priority: DefaultImportPriority
|
priority: DefaultImportPriority
|
||||||
) : FirAbstractStarImportingScope(
|
) : FirAbstractStarImportingScope(
|
||||||
session, scopeSession, filter,
|
session, scopeSession,
|
||||||
lookupInFir = session.languageVersionSettings.getFlag(AnalysisFlags.allowKotlinPackage)
|
lookupInFir = session.languageVersionSettings.getFlag(AnalysisFlags.allowKotlinPackage)
|
||||||
) {
|
) {
|
||||||
// TODO: put languageVersionSettings into FirSession?
|
// TODO: put languageVersionSettings into FirSession?
|
||||||
@@ -44,7 +43,6 @@ class FirDefaultStarImportingScope(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun processFunctionsByName(name: Name, processor: (FirNamedFunctionSymbol) -> Unit) {
|
override fun processFunctionsByName(name: Name, processor: (FirNamedFunctionSymbol) -> Unit) {
|
||||||
if (filter == FirImportingScopeFilter.INVISIBLE_CLASSES) return
|
|
||||||
if (name.isSpecial || name.identifier.isNotEmpty()) {
|
if (name.isSpecial || name.identifier.isNotEmpty()) {
|
||||||
for (import in starImports) {
|
for (import in starImports) {
|
||||||
for (symbol in provider.getTopLevelFunctionSymbols(import.packageFqName, name)) {
|
for (symbol in provider.getTopLevelFunctionSymbols(import.packageFqName, name)) {
|
||||||
@@ -55,7 +53,6 @@ class FirDefaultStarImportingScope(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun processPropertiesByName(name: Name, processor: (FirVariableSymbol<*>) -> Unit) {
|
override fun processPropertiesByName(name: Name, processor: (FirVariableSymbol<*>) -> Unit) {
|
||||||
if (filter == FirImportingScopeFilter.INVISIBLE_CLASSES) return
|
|
||||||
if (name.isSpecial || name.identifier.isNotEmpty()) {
|
if (name.isSpecial || name.identifier.isNotEmpty()) {
|
||||||
for (import in starImports) {
|
for (import in starImports) {
|
||||||
for (symbol in provider.getTopLevelPropertySymbols(import.packageFqName, name)) {
|
for (symbol in provider.getTopLevelPropertySymbols(import.packageFqName, name)) {
|
||||||
|
|||||||
+2
-3
@@ -13,9 +13,8 @@ import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
|||||||
open class FirExplicitStarImportingScope(
|
open class FirExplicitStarImportingScope(
|
||||||
imports: List<FirImport>,
|
imports: List<FirImport>,
|
||||||
session: FirSession,
|
session: FirSession,
|
||||||
scopeSession: ScopeSession,
|
scopeSession: ScopeSession
|
||||||
filter: FirImportingScopeFilter
|
) : FirAbstractStarImportingScope(session, scopeSession, lookupInFir = true) {
|
||||||
) : FirAbstractStarImportingScope(session, scopeSession, filter, lookupInFir = true) {
|
|
||||||
override val starImports = imports.filterIsInstance<FirResolvedImport>().filter { it.isAllUnder }
|
override val starImports = imports.filterIsInstance<FirResolvedImport>().filter { it.isAllUnder }
|
||||||
|
|
||||||
override val scopeOwnerLookupNames: List<String> by lazy(LazyThreadSafetyMode.PUBLICATION) {
|
override val scopeOwnerLookupNames: List<String> by lazy(LazyThreadSafetyMode.PUBLICATION) {
|
||||||
|
|||||||
+1
-1
@@ -23,7 +23,7 @@ class FirWhenSubjectImportingScope(
|
|||||||
classId: ClassId, session: FirSession, scopeSession: ScopeSession
|
classId: ClassId, session: FirSession, scopeSession: ScopeSession
|
||||||
) : FirExplicitStarImportingScope(
|
) : FirExplicitStarImportingScope(
|
||||||
listOf(buildResolvedImportByClassId(classId)),
|
listOf(buildResolvedImportByClassId(classId)),
|
||||||
session, scopeSession, FirImportingScopeFilter.ALL
|
session, scopeSession
|
||||||
) {
|
) {
|
||||||
override fun processPropertiesByName(name: Name, processor: (FirVariableSymbol<*>) -> Unit) {
|
override fun processPropertiesByName(name: Name, processor: (FirVariableSymbol<*>) -> Unit) {
|
||||||
super.processPropertiesByName(name) {
|
super.processPropertiesByName(name) {
|
||||||
|
|||||||
@@ -15,8 +15,7 @@ import org.jetbrains.kotlin.fir.scopes.impl.*
|
|||||||
import org.jetbrains.kotlin.fir.symbols.ensureResolved
|
import org.jetbrains.kotlin.fir.symbols.ensureResolved
|
||||||
|
|
||||||
private val ALL_IMPORTS = scopeSessionKey<FirFile, ListStorageFirScope>()
|
private val ALL_IMPORTS = scopeSessionKey<FirFile, ListStorageFirScope>()
|
||||||
private val INVISIBLE_DEFAULT_STAR_IMPORT = scopeSessionKey<DefaultImportPriority, FirDefaultStarImportingScope>()
|
private val DEFAULT_STAR_IMPORT = scopeSessionKey<DefaultImportPriority, FirDefaultStarImportingScope>()
|
||||||
private val VISIBLE_DEFAULT_STAR_IMPORT = scopeSessionKey<DefaultImportPriority, FirDefaultStarImportingScope>()
|
|
||||||
private val DEFAULT_SIMPLE_IMPORT = scopeSessionKey<DefaultImportPriority, FirDefaultSimpleImportingScope>()
|
private val DEFAULT_SIMPLE_IMPORT = scopeSessionKey<DefaultImportPriority, FirDefaultSimpleImportingScope>()
|
||||||
|
|
||||||
fun createImportingScopes(
|
fun createImportingScopes(
|
||||||
@@ -39,22 +38,13 @@ private fun doCreateImportingScopes(
|
|||||||
): List<FirScope> {
|
): List<FirScope> {
|
||||||
file.ensureResolved(FirResolvePhase.IMPORTS)
|
file.ensureResolved(FirResolvePhase.IMPORTS)
|
||||||
return listOf(
|
return listOf(
|
||||||
// from low priority to high priority
|
scopeSession.getOrBuild(DefaultImportPriority.LOW, DEFAULT_STAR_IMPORT) {
|
||||||
scopeSession.getOrBuild(DefaultImportPriority.LOW, INVISIBLE_DEFAULT_STAR_IMPORT) {
|
FirDefaultStarImportingScope(session, scopeSession, DefaultImportPriority.LOW)
|
||||||
FirDefaultStarImportingScope(session, scopeSession, FirImportingScopeFilter.INVISIBLE_CLASSES, DefaultImportPriority.LOW)
|
|
||||||
},
|
},
|
||||||
scopeSession.getOrBuild(DefaultImportPriority.HIGH, INVISIBLE_DEFAULT_STAR_IMPORT) {
|
scopeSession.getOrBuild(DefaultImportPriority.HIGH, DEFAULT_STAR_IMPORT) {
|
||||||
FirDefaultStarImportingScope(session, scopeSession, FirImportingScopeFilter.INVISIBLE_CLASSES, DefaultImportPriority.HIGH)
|
FirDefaultStarImportingScope(session, scopeSession, DefaultImportPriority.HIGH)
|
||||||
},
|
},
|
||||||
FirExplicitStarImportingScope(file.imports, session, scopeSession, FirImportingScopeFilter.INVISIBLE_CLASSES),
|
FirExplicitStarImportingScope(file.imports, session, scopeSession),
|
||||||
// TODO: invisible classes from current package should go before this point
|
|
||||||
scopeSession.getOrBuild(DefaultImportPriority.LOW, VISIBLE_DEFAULT_STAR_IMPORT) {
|
|
||||||
FirDefaultStarImportingScope(session, scopeSession, FirImportingScopeFilter.MEMBERS_AND_VISIBLE_CLASSES, DefaultImportPriority.LOW)
|
|
||||||
},
|
|
||||||
scopeSession.getOrBuild(DefaultImportPriority.HIGH, VISIBLE_DEFAULT_STAR_IMPORT) {
|
|
||||||
FirDefaultStarImportingScope(session, scopeSession, FirImportingScopeFilter.MEMBERS_AND_VISIBLE_CLASSES, DefaultImportPriority.HIGH)
|
|
||||||
},
|
|
||||||
FirExplicitStarImportingScope(file.imports, session, scopeSession, FirImportingScopeFilter.MEMBERS_AND_VISIBLE_CLASSES),
|
|
||||||
|
|
||||||
scopeSession.getOrBuild(DefaultImportPriority.LOW, DEFAULT_SIMPLE_IMPORT) {
|
scopeSession.getOrBuild(DefaultImportPriority.LOW, DEFAULT_SIMPLE_IMPORT) {
|
||||||
FirDefaultSimpleImportingScope(session, scopeSession, priority = DefaultImportPriority.LOW)
|
FirDefaultSimpleImportingScope(session, scopeSession, priority = DefaultImportPriority.LOW)
|
||||||
|
|||||||
Reference in New Issue
Block a user