[FIR] Abstract away symbol.fir in FirImportsChecker
It's easier to reason about correctness of `symbol.fir` when it's localized in small helper functions.
This commit is contained in:
committed by
Space Team
parent
52d712e110
commit
965d8d2fd5
+18
-22
@@ -19,10 +19,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.toInvisibleReferenceDiagnos
|
||||
import org.jetbrains.kotlin.fir.analysis.getLastImportedFqNameSegmentSource
|
||||
import org.jetbrains.kotlin.fir.analysis.getSourceForImportSegment
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isEnumClass
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isOperator
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isStatic
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.visibility
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.*
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.firProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.getContainingFile
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
|
||||
@@ -31,7 +28,7 @@ import org.jetbrains.kotlin.fir.resolve.transformers.PackageResolutionResult
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.resolveToPackageOrClass
|
||||
import org.jetbrains.kotlin.fir.scopes.FirContainingNamesAwareScope
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.declaredMemberScope
|
||||
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
|
||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.fir.visibilityChecker
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
@@ -39,7 +36,6 @@ import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.types.expressions.OperatorConventions
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.filterIsInstanceWithChecker
|
||||
|
||||
@OptIn(SymbolInternals::class)
|
||||
object FirImportsChecker : FirFileChecker() {
|
||||
override fun check(declaration: FirFile, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
declaration.imports.forEach { import ->
|
||||
@@ -83,7 +79,7 @@ object FirImportsChecker : FirFileChecker() {
|
||||
if (classSymbol != null && classSymbol.classKind.isObject) {
|
||||
reporter.reportOn(import.source, FirErrors.CANNOT_ALL_UNDER_IMPORT_FROM_SINGLETON, classSymbol.classId.shortClassName, context)
|
||||
}
|
||||
if (!classLike.fir.isVisible(context)) {
|
||||
if (!classLike.isVisible(context)) {
|
||||
val source = import.getLastImportedFqNameSegmentSource() ?: error("`${import.source}` does not contain `$fqName`")
|
||||
reporter.report(classLike.toInvisibleReferenceDiagnostic(source), context)
|
||||
}
|
||||
@@ -101,7 +97,7 @@ object FirImportsChecker : FirFileChecker() {
|
||||
val parentClassSymbol = parentClassId.resolveToClass(context) ?: return
|
||||
|
||||
fun reportInvisibleParentClasses(classSymbol: FirRegularClassSymbol, depth: Int) {
|
||||
if (!classSymbol.fir.isVisible(context)) {
|
||||
if (!classSymbol.isVisible(context)) {
|
||||
val source = import.getSourceForImportSegment(indexFromLast = depth)
|
||||
reporter.report(classSymbol.toInvisibleReferenceDiagnostic(source), context)
|
||||
}
|
||||
@@ -130,12 +126,12 @@ object FirImportsChecker : FirFileChecker() {
|
||||
return
|
||||
}
|
||||
|
||||
var resolvedDeclaration: FirMemberDeclaration? = null
|
||||
var resolvedDeclaration: FirBasedSymbol<*>? = null
|
||||
|
||||
ClassId.topLevel(importedFqName).resolveToClass(context)?.let {
|
||||
resolvedDeclaration = it.fir
|
||||
resolvedDeclaration = it
|
||||
|
||||
if (it.fir.isVisible(context)) {
|
||||
if (it.isVisible(context)) {
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -145,18 +141,18 @@ object FirImportsChecker : FirFileChecker() {
|
||||
val topLevelCallableSymbol = symbolProvider.getTopLevelCallableSymbols(importedFqName.parent(), importedName)
|
||||
|
||||
for (it in topLevelCallableSymbol) {
|
||||
if (it.fir.isVisible(context)) {
|
||||
if (it.isVisible(context)) {
|
||||
return
|
||||
}
|
||||
|
||||
if (resolvedDeclaration == null) {
|
||||
resolvedDeclaration = it.fir
|
||||
resolvedDeclaration = it
|
||||
}
|
||||
}
|
||||
|
||||
resolvedDeclaration?.let {
|
||||
val source = import.getSourceForImportSegment(0) ?: import.source
|
||||
reporter.report(it.symbol.toInvisibleReferenceDiagnostic(source), context)
|
||||
reporter.report(it.toInvisibleReferenceDiagnostic(source), context)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -167,18 +163,18 @@ object FirImportsChecker : FirFileChecker() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun FirMemberDeclaration.isVisible(context: CheckerContext): Boolean {
|
||||
private fun FirBasedSymbol<*>.isVisible(context: CheckerContext): Boolean {
|
||||
val useSiteFile = context.containingFile ?: return false
|
||||
|
||||
val visibility = visibility
|
||||
val fir = asMemberDeclarationResolvedTo(FirResolvePhase.STATUS) ?: return false
|
||||
val visibility = fir.visibility
|
||||
|
||||
if (visibility != Visibilities.Unknown && !visibility.mustCheckInImports()) return true
|
||||
if (visibility == Visibilities.Private || visibility == Visibilities.PrivateToThis) {
|
||||
return useSiteFile == context.session.firProvider.getContainingFile(symbol)
|
||||
return useSiteFile == context.session.firProvider.getContainingFile(this)
|
||||
}
|
||||
|
||||
return context.session.visibilityChecker.isVisible(
|
||||
this,
|
||||
fir,
|
||||
context.session,
|
||||
useSiteFile,
|
||||
emptyList(),
|
||||
@@ -283,7 +279,7 @@ object FirImportsChecker : FirFileChecker() {
|
||||
|
||||
// Next, we try static scope, which can provide static (Java) members from super classes. Note that it's not available
|
||||
// for pure Kotlin classes.
|
||||
fir.staticScope(context.sessionHolder),
|
||||
staticScope(context.sessionHolder),
|
||||
|
||||
// Finally, we fall back to unsubstitutedScope to catch all
|
||||
unsubstitutedScope(context)
|
||||
@@ -303,13 +299,13 @@ object FirImportsChecker : FirFileChecker() {
|
||||
|
||||
for (scope in scopes) {
|
||||
scope.processFunctionsByName(name) { sym ->
|
||||
if (sym.fir.isVisible(context) && isApplicable(sym)) found = true
|
||||
if (sym.isVisible(context) && isApplicable(sym)) found = true
|
||||
symbol = sym
|
||||
}
|
||||
if (found) return ImportStatus.OK
|
||||
|
||||
scope.processPropertiesByName(name) { sym ->
|
||||
if (sym.fir.isVisible(context) && isApplicable(sym)) found = true
|
||||
if (sym.isVisible(context) && isApplicable(sym)) found = true
|
||||
symbol = sym
|
||||
}
|
||||
if (found) return ImportStatus.OK
|
||||
|
||||
+4
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||
import org.jetbrains.kotlin.fir.scopes.FirTypeScope
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirLocalScope
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.wrapNestedClassifierScopeWithSubstitutionForSuperType
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
||||
import org.jetbrains.kotlin.fir.types.ConeErrorType
|
||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
@@ -303,6 +304,9 @@ fun FirScope.asTowerDataElement(isLocal: Boolean): FirTowerDataElement =
|
||||
fun FirScope.asTowerDataElementForStaticScope(staticScopeOwnerSymbol: FirRegularClassSymbol?): FirTowerDataElement =
|
||||
FirTowerDataElement(scope = this, implicitReceiver = null, isLocal = false, staticScopeOwnerSymbol = staticScopeOwnerSymbol)
|
||||
|
||||
fun FirClassSymbol<*>.staticScope(sessionHolder: SessionHolder): FirContainingNamesAwareScope? =
|
||||
fir.staticScope(sessionHolder)
|
||||
|
||||
fun FirClass.staticScope(sessionHolder: SessionHolder): FirContainingNamesAwareScope? =
|
||||
staticScope(sessionHolder.session, sessionHolder.scopeSession)
|
||||
|
||||
|
||||
+7
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.declarations.utils
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
|
||||
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
|
||||
import org.jetbrains.kotlin.fir.types.coneTypeSafe
|
||||
import org.jetbrains.kotlin.fir.types.isNullableAny
|
||||
@@ -59,6 +60,12 @@ val FirMemberDeclaration.nameOrSpecialName: Name
|
||||
is FirClassLikeDeclaration -> classId.shortClassName
|
||||
}
|
||||
|
||||
fun FirBasedSymbol<*>.asMemberDeclarationResolvedTo(phase: FirResolvePhase): FirMemberDeclaration? {
|
||||
return (fir as? FirMemberDeclaration)?.also {
|
||||
lazyResolveToPhase(phase)
|
||||
}
|
||||
}
|
||||
|
||||
val FirNamedFunctionSymbol.isMethodOfAny: Boolean
|
||||
get() {
|
||||
if (receiverParameter != null) return false
|
||||
|
||||
Reference in New Issue
Block a user