[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
This commit is contained in:
Marco Pennekamp
2023-09-22 13:53:11 +02:00
committed by Space Team
parent 3d1262140d
commit 17e181885f
3 changed files with 14 additions and 4 deletions
@@ -133,7 +133,7 @@ internal class KtFirScopeProvider(
}
return scopeSession.getOrBuild(firJavaClass.symbol, cacheKey) {
FirDeclaredMembersOnlyScope(firScope, firJavaClass)
FirJavaDeclaredMembersOnlyScope(firScope, firJavaClass)
}
}
@@ -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() {
@@ -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