[AA] Remove classifiers from non-static declared member scopes

- The semantics of a non-static declared member scope should be as
  follows: For a variable `c: C` of class type `C`, the declared member
  scope should contain all members `x` accessible as `c.x` (visibility
  notwithstanding) which are *also* explicitly declared in `C`.
- Classifiers are not accessible as properties of a variable `c`, only
  as static members of the class `C` itself, so non-static declared
  member scopes should not contain any classifiers.

^KT-61800
This commit is contained in:
Marco Pennekamp
2023-09-14 22:38:14 +02:00
committed by Space Team
parent 8b24baade9
commit 5679acbbdb
17 changed files with 200 additions and 159 deletions
@@ -105,7 +105,7 @@ internal class KtFirScopeProvider(
): FirContainingNamesAwareScope {
val combinedScope = getCombinedFirKotlinDeclaredMemberScope(classSymbol)
return when (kind) {
DeclaredMemberScopeKind.NON_STATIC -> FirNonStaticCallablesScope(combinedScope)
DeclaredMemberScopeKind.NON_STATIC -> FirNonStaticCallablesOnlyScope(combinedScope)
DeclaredMemberScopeKind.STATIC -> FirStaticScope(combinedScope)
}
}
@@ -115,11 +115,14 @@ internal class KtFirScopeProvider(
val scopeSession = getScopeSession()
val firScope = when (kind) {
DeclaredMemberScopeKind.NON_STATIC -> JavaScopeProvider.getUseSiteMemberScope(
firJavaClass,
useSiteSession,
scopeSession,
memberRequiredPhase = FirResolvePhase.TYPES,
// `FirNoClassifiersScope` is a workaround for non-static member scopes containing classifiers (see KT-61900).
DeclaredMemberScopeKind.NON_STATIC -> FirNoClassifiersScope(
JavaScopeProvider.getUseSiteMemberScope(
firJavaClass,
useSiteSession,
scopeSession,
memberRequiredPhase = FirResolvePhase.TYPES,
)
)
DeclaredMemberScopeKind.STATIC -> JavaScopeProvider.getStaticScope(firJavaClass, useSiteSession, scopeSession) ?: return null
}
@@ -12,6 +12,10 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
import org.jetbrains.kotlin.name.Name
/**
* A base implementation for [FirNonStaticCallablesOnlyScope] and [FirDeclaredMembersOnlyScope], which both filter callables based on some
* condition.
*/
internal abstract class FirCallableFilteringScope(private val baseScope: FirContainingNamesAwareScope) : FirContainingNamesAwareScope() {
protected abstract fun isTargetCallable(callable: FirCallableSymbol<*>): Boolean
@@ -0,0 +1,19 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.analysis.api.fir.scopes
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.scopes.FirContainingNamesAwareScope
import org.jetbrains.kotlin.fir.scopes.FirDelegatingContainingNamesAwareScope
import org.jetbrains.kotlin.fir.symbols.impl.FirClassifierSymbol
import org.jetbrains.kotlin.name.Name
internal class FirNoClassifiersScope(delegate: FirContainingNamesAwareScope) : FirDelegatingContainingNamesAwareScope(delegate) {
override fun getClassifierNames(): Set<Name> = emptySet()
override fun processClassifiersByNameWithSubstitution(name: Name, processor: (FirClassifierSymbol<*>, ConeSubstitutor) -> Unit) {
}
}
@@ -0,0 +1,32 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.analysis.api.fir.scopes
import org.jetbrains.kotlin.fir.declarations.utils.isStatic
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.scopes.FirContainingNamesAwareScope
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirClassifierSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol
import org.jetbrains.kotlin.name.Name
/**
* Excludes static callables and all classifiers.
*/
internal class FirNonStaticCallablesOnlyScope(
private val delegate: FirContainingNamesAwareScope,
) : FirCallableFilteringScope(delegate) {
override fun isTargetCallable(callable: FirCallableSymbol<*>): Boolean = !callable.fir.isStatic
override fun processDeclaredConstructors(processor: (FirConstructorSymbol) -> Unit) {
delegate.processDeclaredConstructors(processor)
}
override fun getClassifierNames(): Set<Name> = emptySet()
override fun processClassifiersByNameWithSubstitution(name: Name, processor: (FirClassifierSymbol<*>, ConeSubstitutor) -> Unit) {
}
}
@@ -157,7 +157,11 @@ public interface KtScopeProviderMixIn : KtAnalysisSessionMixIn {
withValidityAssertion { analysisSession.scopeProvider.getCombinedMemberScope(this) }
/**
* Returns a [KtScope] containing the *non-static* callables and all classifiers explicitly declared in the given [KtSymbolWithMembers].
* Returns a [KtScope] containing the *non-static* callables (functions, properties, and constructors) explicitly declared in the given
* [KtSymbolWithMembers].
*
* The declared member scope does not contain classifiers (including the companion object). To retrieve the classifiers declared in this
* [KtSymbolWithMembers], please use the *static* declared member scope provided by [getStaticDeclaredMemberScope].
*
* @see getStaticDeclaredMemberScope
*/
@@ -165,7 +169,8 @@ public interface KtScopeProviderMixIn : KtAnalysisSessionMixIn {
withValidityAssertion { analysisSession.scopeProvider.getDeclaredMemberScope(this) }
/**
* Returns a [KtScope] containing the *static* members explicitly declared in the given [KtSymbolWithMembers].
* Returns a [KtScope] containing the *static* callables (functions and properties) and all classifiers (classes and objects) explicitly
* declared in the given [KtSymbolWithMembers].
*
* It is worth noting that, while Java classes may contain declarations of static callables freely, in Kotlin only enum classes define
* static callables. Hence, for non-enum Kotlin classes, it is not expected that the static declared member scope will contain any
@@ -2,10 +2,4 @@ fun foo(): kotlin.Int
val bar: kotlin.String
class C2
object O2
companion object
constructor()
@@ -119,93 +119,6 @@ KtKotlinPropertySymbol:
javaSetterName: null
setterDeprecationStatus: null
KtNamedClassOrObjectSymbol:
annotationsList: []
classIdIfNonLocal: test/C.C2
classKind: CLASS
companionObject: null
contextReceivers: []
isActual: false
isData: false
isExpect: false
isExternal: false
isFun: false
isInline: false
isInner: false
modality: FINAL
name: C2
origin: SOURCE
superTypes: [
KtUsualClassType:
annotationsList: []
ownTypeArguments: []
type: kotlin/Any
]
symbolKind: CLASS_MEMBER
typeParameters: []
visibility: Public
getContainingModule: KtSourceModule "Sources of main"
annotationApplicableTargets: null
deprecationStatus: null
KtNamedClassOrObjectSymbol:
annotationsList: []
classIdIfNonLocal: test/C.O2
classKind: OBJECT
companionObject: null
contextReceivers: []
isActual: false
isData: false
isExpect: false
isExternal: false
isFun: false
isInline: false
isInner: false
modality: FINAL
name: O2
origin: SOURCE
superTypes: [
KtUsualClassType:
annotationsList: []
ownTypeArguments: []
type: kotlin/Any
]
symbolKind: CLASS_MEMBER
typeParameters: []
visibility: Public
getContainingModule: KtSourceModule "Sources of main"
annotationApplicableTargets: null
deprecationStatus: null
KtNamedClassOrObjectSymbol:
annotationsList: []
classIdIfNonLocal: test/C.Companion
classKind: COMPANION_OBJECT
companionObject: null
contextReceivers: []
isActual: false
isData: false
isExpect: false
isExternal: false
isFun: false
isInline: false
isInner: false
modality: FINAL
name: Companion
origin: SOURCE
superTypes: [
KtUsualClassType:
annotationsList: []
ownTypeArguments: []
type: kotlin/Any
]
symbolKind: CLASS_MEMBER
typeParameters: []
visibility: Public
getContainingModule: KtSourceModule "Sources of main"
annotationApplicableTargets: null
deprecationStatus: null
KtConstructorSymbol:
annotationsList: []
callableIdIfNonLocal: null
@@ -12,6 +12,8 @@ public interface SuperInterface {
// FILE: SuperClass.java
public abstract class SuperClass implements SuperInterface {
public static class NestedSuperClass { }
@Override
public int getActualRandomNumber() {
return getRandomNumber();
@@ -26,6 +28,8 @@ public abstract class SuperClass implements SuperInterface {
// FILE: JavaClass.java
public class JavaClass extends SuperClass {
public static class NestedClass { }
public static int foo = 1;
public static String bar() {
@@ -12,6 +12,8 @@ public interface SuperInterface {
// FILE: SuperClass.java
public abstract class SuperClass implements SuperInterface {
public static class NestedSuperClass { }
@Override
public int getActualRandomNumber() {
return getRandomNumber();
@@ -26,6 +28,8 @@ public abstract class SuperClass implements SuperInterface {
// FILE: JavaClass.java
public class JavaClass extends SuperClass {
public static class NestedClass { }
public static int foo = 1;
public static String bar() {
@@ -9,4 +9,8 @@ open fun hashCode(): kotlin.Int
open fun toString(): kotlin.String
open class NestedClass
open class NestedSuperClass
constructor()
@@ -204,6 +204,64 @@ KtFunctionSymbol:
getContainingModule: KtBinaryModule "Builtins for JVM (1.8)"
deprecationStatus: null
KtNamedClassOrObjectSymbol:
annotationsList: []
classIdIfNonLocal: JavaClass.NestedClass
classKind: CLASS
companionObject: null
contextReceivers: []
isActual: false
isData: false
isExpect: false
isExternal: false
isFun: false
isInline: false
isInner: false
modality: OPEN
name: NestedClass
origin: JAVA
superTypes: [
KtUsualClassType:
annotationsList: []
ownTypeArguments: []
type: kotlin/Any
]
symbolKind: CLASS_MEMBER
typeParameters: []
visibility: Public
getContainingModule: KtSourceModule "Sources of main"
annotationApplicableTargets: null
deprecationStatus: null
KtNamedClassOrObjectSymbol:
annotationsList: []
classIdIfNonLocal: SuperClass.NestedSuperClass
classKind: CLASS
companionObject: null
contextReceivers: []
isActual: false
isData: false
isExpect: false
isExternal: false
isFun: false
isInline: false
isInner: false
modality: OPEN
name: NestedSuperClass
origin: JAVA
superTypes: [
KtUsualClassType:
annotationsList: []
ownTypeArguments: []
type: kotlin/Any
]
symbolKind: CLASS_MEMBER
typeParameters: []
visibility: Public
getContainingModule: KtSourceModule "Sources of main"
annotationApplicableTargets: null
deprecationStatus: null
KtConstructorSymbol:
annotationsList: []
callableIdIfNonLocal: null
@@ -13,7 +13,7 @@ public abstract class JavaClass {
public static int y = 1;
public class C1 {
public static class C1 {
}
}
@@ -12,6 +12,8 @@ public interface SuperInterface {
// FILE: SuperClass.java
public abstract class SuperClass implements SuperInterface {
public static class NestedSuperClass { }
@Override
public int getActualRandomNumber() {
return getRandomNumber();
@@ -26,6 +28,8 @@ public abstract class SuperClass implements SuperInterface {
// FILE: JavaClass.java
public class JavaClass extends SuperClass {
public static class NestedClass { }
public static int foo = 1;
public static String bar() {
@@ -1,3 +1,5 @@
open fun bar(): kotlin.String!
open var foo: kotlin.Int
open fun bar(): kotlin.String!
open class NestedClass
@@ -1,24 +1,3 @@
KtJavaFieldSymbol:
annotationsList: []
callableIdIfNonLocal: /JavaClass.foo
contextReceivers: []
isExtension: false
isStatic: true
isVal: false
modality: OPEN
name: foo
origin: JAVA
receiverParameter: null
returnType: KtUsualClassType:
annotationsList: []
ownTypeArguments: []
type: kotlin/Int
symbolKind: CLASS_MEMBER
typeParameters: []
visibility: Public
getContainingModule: KtSourceModule "Sources of main"
deprecationStatus: null
KtFunctionSymbol:
annotationsList: []
callableIdIfNonLocal: /JavaClass.bar
@@ -48,4 +27,54 @@ KtFunctionSymbol:
valueParameters: []
visibility: Public
getContainingModule: KtSourceModule "Sources of main"
deprecationStatus: null
KtJavaFieldSymbol:
annotationsList: []
callableIdIfNonLocal: /JavaClass.foo
contextReceivers: []
isExtension: false
isStatic: true
isVal: false
modality: OPEN
name: foo
origin: JAVA
receiverParameter: null
returnType: KtUsualClassType:
annotationsList: []
ownTypeArguments: []
type: kotlin/Int
symbolKind: CLASS_MEMBER
typeParameters: []
visibility: Public
getContainingModule: KtSourceModule "Sources of main"
deprecationStatus: null
KtNamedClassOrObjectSymbol:
annotationsList: []
classIdIfNonLocal: JavaClass.NestedClass
classKind: CLASS
companionObject: null
contextReceivers: []
isActual: false
isData: false
isExpect: false
isExternal: false
isFun: false
isInline: false
isInner: false
modality: OPEN
name: NestedClass
origin: JAVA
superTypes: [
KtUsualClassType:
annotationsList: []
ownTypeArguments: []
type: kotlin/Any
]
symbolKind: CLASS_MEMBER
typeParameters: []
visibility: Public
getContainingModule: KtSourceModule "Sources of main"
annotationApplicableTargets: null
deprecationStatus: null
@@ -13,7 +13,7 @@ public abstract class JavaClass {
public static int y = 1;
public class C1 {
public static class C1 {
}
}
@@ -1,34 +0,0 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.scopes.impl
import org.jetbrains.kotlin.fir.declarations.utils.isStatic
import org.jetbrains.kotlin.fir.scopes.FirContainingNamesAwareScope
import org.jetbrains.kotlin.fir.scopes.FirDelegatingContainingNamesAwareScope
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
import org.jetbrains.kotlin.name.Name
/**
* A counterpart to [FirStaticScope] that contains only the *non-static* callables and all classifiers of the [delegate] scope.
*/
class FirNonStaticCallablesScope(private val delegate: FirContainingNamesAwareScope) : FirDelegatingContainingNamesAwareScope(delegate) {
override fun processFunctionsByName(name: Name, processor: (FirNamedFunctionSymbol) -> Unit) {
delegate.processFunctionsByName(name) {
if (!it.fir.isStatic) {
processor(it)
}
}
}
override fun processPropertiesByName(name: Name, processor: (FirVariableSymbol<*>) -> Unit) {
delegate.processPropertiesByName(name) {
if (!it.fir.isStatic) {
processor(it)
}
}
}
}