From 17e181885f8e5f46a424d4c8bebbbad4c93148c2 Mon Sep 17 00:00:00 2001 From: Marco Pennekamp Date: Fri, 22 Sep 2023 13:53:11 +0200 Subject: [PATCH] [AA] Restrict `FirJavaDeclaredMembersOnlyScope` to non-local classes - Comparing the callable ID with the owner's class ID is the simplest way to check whether a callable is declared inside an owner class. However, this does not work for local classes, because they do not have proper class IDs. The same issue occurs when trying to get the containing class, because it is a lookup tag search in symbol providers. - Given that the scope is only needed for Java classes and local Java classes cannot leak from function bodies, the easiest solution is to disallow creating this scope for local classes. ^KT-61800 --- .../api/fir/components/KtFirScopeProvider.kt | 2 +- .../api/fir/scopes/FirCallableFilteringScope.kt | 2 +- ...Scope.kt => FirJavaDeclaredMembersOnlyScope.kt} | 14 ++++++++++++-- 3 files changed, 14 insertions(+), 4 deletions(-) rename analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/scopes/{FirDeclaredMembersOnlyScope.kt => FirJavaDeclaredMembersOnlyScope.kt} (76%) diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirScopeProvider.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirScopeProvider.kt index bf19b54bd9e..f66369df2b5 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirScopeProvider.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirScopeProvider.kt @@ -133,7 +133,7 @@ internal class KtFirScopeProvider( } return scopeSession.getOrBuild(firJavaClass.symbol, cacheKey) { - FirDeclaredMembersOnlyScope(firScope, firJavaClass) + FirJavaDeclaredMembersOnlyScope(firScope, firJavaClass) } } diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/scopes/FirCallableFilteringScope.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/scopes/FirCallableFilteringScope.kt index fe8b4e364df..5c04531179c 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/scopes/FirCallableFilteringScope.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/scopes/FirCallableFilteringScope.kt @@ -13,7 +13,7 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol import org.jetbrains.kotlin.name.Name /** - * A base implementation for [FirNonStaticMembersScope] and [FirDeclaredMembersOnlyScope], which both filter callables based on some + * A base implementation for [FirNonStaticMembersScope] and [FirJavaDeclaredMembersOnlyScope], which both filter callables based on some * condition. */ internal abstract class FirCallableFilteringScope(private val baseScope: FirContainingNamesAwareScope) : FirContainingNamesAwareScope() { diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/scopes/FirDeclaredMembersOnlyScope.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/scopes/FirJavaDeclaredMembersOnlyScope.kt similarity index 76% rename from analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/scopes/FirDeclaredMembersOnlyScope.kt rename to analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/scopes/FirJavaDeclaredMembersOnlyScope.kt index 0b9753571c4..65a05fa463a 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/scopes/FirDeclaredMembersOnlyScope.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/scopes/FirJavaDeclaredMembersOnlyScope.kt @@ -7,16 +7,26 @@ package org.jetbrains.kotlin.analysis.api.fir.scopes import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.utils.classId +import org.jetbrains.kotlin.fir.declarations.utils.isLocal +import org.jetbrains.kotlin.fir.java.declarations.FirJavaClass import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor import org.jetbrains.kotlin.fir.scopes.* import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.SpecialNames -internal class FirDeclaredMembersOnlyScope( +internal class FirJavaDeclaredMembersOnlyScope( private val delegate: FirContainingNamesAwareScope, - private val owner: FirClass, + private val owner: FirJavaClass, ) : FirCallableFilteringScope(delegate) { + init { + // The `isDeclared` check is based on class IDs. Local classes don't have proper class IDs, but because this scope is used to + // represent Java classes viewed from Kotlin code, we shouldn't be able to encounter any local Java classes. + require(!owner.isLocal) { + "Unexpected local Java class in ${FirJavaDeclaredMembersOnlyScope::class.simpleName}." + } + } + private fun FirCallableDeclaration.isDeclared(): Boolean = symbol.callableId.classId == owner.classId && origin !is FirDeclarationOrigin.SubstitutionOverride