[FIR] Introduce & use FirDelegatedMemberScope

This commit is contained in:
Mikhail Glukhikh
2020-08-26 16:06:17 +03:00
parent f0af930288
commit 5384ccf02f
5 changed files with 142 additions and 10 deletions
@@ -7,6 +7,6 @@ open class B(private val a: A) : A by a
class C(a: A) : B(a) {
override fun foo() {
// Should be resolved to delegated B.foo (no error)
super.<!ABSTRACT_SUPER_CALL!>foo<!>()
super.foo()
}
}
@@ -164,7 +164,7 @@ private fun processConstructors(
}
is FirClassSymbol ->
(matchedSymbol.fir as FirClass<*>).scope(
substitutor, session, scopeSession, false,
substitutor, session, scopeSession, skipPrivateMembers = false,
)
}
@@ -7,18 +7,17 @@ package org.jetbrains.kotlin.fir.scopes
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirClass
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.classId
import org.jetbrains.kotlin.fir.declarations.isExpect
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.resolve.*
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
import org.jetbrains.kotlin.fir.scopes.impl.*
import org.jetbrains.kotlin.fir.symbols.CallableId
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.fir.types.ConeClassErrorType
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.name.ClassId
class KotlinScopeProvider(
@@ -39,14 +38,16 @@ class KotlinScopeProvider(
val decoratedDeclaredMemberScope =
declaredMemberScopeDecorator(klass, declaredScope, useSiteSession, scopeSession)
val delegateFields = klass.declarations.filterIsInstance<FirField>().filter { it.isSynthetic }
val scopes = lookupSuperTypes(klass, lookupInterfaces = true, deep = false, useSiteSession = useSiteSession)
.mapNotNull { useSiteSuperType ->
if (useSiteSuperType is ConeClassErrorType) return@mapNotNull null
val symbol = useSiteSuperType.lookupTag.toSymbol(useSiteSession)
if (symbol is FirRegularClassSymbol) {
val delegateField = delegateFields.find { it.returnTypeRef.coneType == useSiteSuperType }
symbol.fir.scope(
substitutor(symbol, useSiteSuperType, useSiteSession),
useSiteSession, scopeSession,
useSiteSession, scopeSession, delegateField,
skipPrivateMembers = true,
classId = klass.classId,
isFromExpectClass = (klass as? FirRegularClass)?.isExpect == true
@@ -94,6 +95,8 @@ data class ConeSubstitutionScopeKey(
val classId: ClassId?, val isFromExpectClass: Boolean, val substitutor: ConeSubstitutor
) : ScopeSessionKey<FirClass<*>, FirClassSubstitutionScope>()
data class DelegatedMemberScopeKey(val callableId: CallableId) : ScopeSessionKey<FirField, FirDelegatedMemberScope>()
fun FirClass<*>.unsubstitutedScope(useSiteSession: FirSession, scopeSession: ScopeSession): FirTypeScope {
return scopeProvider.getUseSiteMemberScope(this, useSiteSession, scopeSession)
}
@@ -102,13 +105,20 @@ internal fun FirClass<*>.scope(
substitutor: ConeSubstitutor,
useSiteSession: FirSession,
scopeSession: ScopeSession,
delegateField: FirField? = null,
skipPrivateMembers: Boolean,
classId: ClassId? = this.classId,
isFromExpectClass: Boolean = false
): FirTypeScope {
val basicScope = scopeProvider.getUseSiteMemberScope(
this, useSiteSession, scopeSession
)
val basicScope = unsubstitutedScope(useSiteSession, scopeSession).let {
if (delegateField != null) {
scopeSession.getOrBuild(delegateField, DelegatedMemberScopeKey(delegateField.symbol.callableId)) {
FirDelegatedMemberScope(it, useSiteSession)
}
} else {
it
}
}
if (substitutor == ConeSubstitutor.Empty) return basicScope
return scopeSession.getOrBuild(
@@ -0,0 +1,121 @@
/*
* Copyright 2010-2020 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.descriptors.Modality
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.builder.buildProperty
import org.jetbrains.kotlin.fir.declarations.builder.buildSimpleFunction
import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl
import org.jetbrains.kotlin.fir.scopes.FirTypeScope
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
import org.jetbrains.kotlin.name.Name
class FirDelegatedMemberScope(
private val useSiteScope: FirTypeScope,
private val session: FirSession
) : FirTypeScope() {
private val delegatedFunctionCache = mutableMapOf<FirNamedFunctionSymbol, FirNamedFunctionSymbol>()
private val delegatedPropertyCache = mutableMapOf<FirPropertySymbol, FirPropertySymbol>()
override fun processFunctionsByName(name: Name, processor: (FirFunctionSymbol<*>) -> Unit) {
useSiteScope.processFunctionsByName(name) processor@{ functionSymbol ->
if (functionSymbol !is FirNamedFunctionSymbol) {
processor(functionSymbol)
return@processor
}
val original = functionSymbol.fir
if (original.modality == Modality.FINAL) {
processor(functionSymbol)
return@processor
}
val delegatedSymbol = delegatedFunctionCache.getOrPut(functionSymbol) {
val delegatedFunction = buildSimpleFunction {
origin = FirDeclarationOrigin.Delegated
session = this@FirDelegatedMemberScope.session
this.name = name
symbol = FirNamedFunctionSymbol(
functionSymbol.callableId,
overriddenSymbol = functionSymbol
)
status = FirDeclarationStatusImpl(original.visibility, Modality.OPEN).apply {
isOperator = original.isOperator
}
resolvePhase = FirResolvePhase.BODY_RESOLVE
returnTypeRef = original.returnTypeRef
receiverTypeRef = original.receiverTypeRef
valueParameters.addAll(original.valueParameters)
typeParameters.addAll(original.typeParameters)
annotations.addAll(original.annotations)
}
delegatedFunction.symbol as FirNamedFunctionSymbol
}
processor(delegatedSymbol)
}
}
override fun processPropertiesByName(name: Name, processor: (FirVariableSymbol<*>) -> Unit) {
useSiteScope.processPropertiesByName(name) processor@{ propertySymbol ->
if (propertySymbol !is FirPropertySymbol) {
processor(propertySymbol)
return@processor
}
val original = propertySymbol.fir
if (original.modality == Modality.FINAL) {
processor(propertySymbol)
return@processor
}
val delegatedSymbol = delegatedPropertyCache.getOrPut(propertySymbol) {
val delegatedProperty = buildProperty {
origin = FirDeclarationOrigin.Delegated
session = this@FirDelegatedMemberScope.session
this.name = name
symbol = FirPropertySymbol(
propertySymbol.callableId,
overriddenSymbol = propertySymbol
)
isVar = original.isVar
isLocal = false
status = FirDeclarationStatusImpl(original.visibility, Modality.OPEN)
resolvePhase = FirResolvePhase.BODY_RESOLVE
returnTypeRef = original.returnTypeRef
receiverTypeRef = original.receiverTypeRef
typeParameters.addAll(original.typeParameters)
annotations.addAll(original.annotations)
}
delegatedProperty.symbol
}
processor(delegatedSymbol)
}
}
override fun processDirectOverriddenFunctionsWithBaseScope(
functionSymbol: FirFunctionSymbol<*>,
processor: (FirFunctionSymbol<*>, FirTypeScope) -> ProcessorAction
): ProcessorAction {
return useSiteScope.processDirectOverriddenFunctionsWithBaseScope(functionSymbol, processor)
}
override fun processDirectOverriddenPropertiesWithBaseScope(
propertySymbol: FirPropertySymbol,
processor: (FirPropertySymbol, FirTypeScope) -> ProcessorAction
): ProcessorAction {
return useSiteScope.processDirectOverriddenPropertiesWithBaseScope(propertySymbol, processor)
}
override fun getCallableNames(): Set<Name> {
return useSiteScope.getCallableNames()
}
override fun getClassifierNames(): Set<Name> {
return useSiteScope.getClassifierNames()
}
}
@@ -15,6 +15,7 @@ sealed class FirDeclarationOrigin {
object Enhancement : FirDeclarationOrigin()
object ImportedFromObject : FirDeclarationOrigin()
object IntersectionOverride : FirDeclarationOrigin()
object Delegated : FirDeclarationOrigin()
class Plugin(val key: FirPluginKey) : FirDeclarationOrigin()
}