[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) { class C(a: A) : B(a) {
override fun foo() { override fun foo() {
// Should be resolved to delegated B.foo (no error) // 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 -> is FirClassSymbol ->
(matchedSymbol.fir as FirClass<*>).scope( (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.descriptors.ClassKind
import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirClass import org.jetbrains.kotlin.fir.declarations.*
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.resolve.* import org.jetbrains.kotlin.fir.resolve.*
import org.jetbrains.kotlin.fir.resolve.toSymbol import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
import org.jetbrains.kotlin.fir.scopes.impl.* 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.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.fir.types.ConeClassErrorType import org.jetbrains.kotlin.fir.types.ConeClassErrorType
import org.jetbrains.kotlin.fir.types.ConeClassLikeType import org.jetbrains.kotlin.fir.types.ConeClassLikeType
import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
class KotlinScopeProvider( class KotlinScopeProvider(
@@ -39,14 +38,16 @@ class KotlinScopeProvider(
val decoratedDeclaredMemberScope = val decoratedDeclaredMemberScope =
declaredMemberScopeDecorator(klass, declaredScope, useSiteSession, scopeSession) declaredMemberScopeDecorator(klass, declaredScope, useSiteSession, scopeSession)
val delegateFields = klass.declarations.filterIsInstance<FirField>().filter { it.isSynthetic }
val scopes = lookupSuperTypes(klass, lookupInterfaces = true, deep = false, useSiteSession = useSiteSession) val scopes = lookupSuperTypes(klass, lookupInterfaces = true, deep = false, useSiteSession = useSiteSession)
.mapNotNull { useSiteSuperType -> .mapNotNull { useSiteSuperType ->
if (useSiteSuperType is ConeClassErrorType) return@mapNotNull null if (useSiteSuperType is ConeClassErrorType) return@mapNotNull null
val symbol = useSiteSuperType.lookupTag.toSymbol(useSiteSession) val symbol = useSiteSuperType.lookupTag.toSymbol(useSiteSession)
if (symbol is FirRegularClassSymbol) { if (symbol is FirRegularClassSymbol) {
val delegateField = delegateFields.find { it.returnTypeRef.coneType == useSiteSuperType }
symbol.fir.scope( symbol.fir.scope(
substitutor(symbol, useSiteSuperType, useSiteSession), substitutor(symbol, useSiteSuperType, useSiteSession),
useSiteSession, scopeSession, useSiteSession, scopeSession, delegateField,
skipPrivateMembers = true, skipPrivateMembers = true,
classId = klass.classId, classId = klass.classId,
isFromExpectClass = (klass as? FirRegularClass)?.isExpect == true isFromExpectClass = (klass as? FirRegularClass)?.isExpect == true
@@ -94,6 +95,8 @@ data class ConeSubstitutionScopeKey(
val classId: ClassId?, val isFromExpectClass: Boolean, val substitutor: ConeSubstitutor val classId: ClassId?, val isFromExpectClass: Boolean, val substitutor: ConeSubstitutor
) : ScopeSessionKey<FirClass<*>, FirClassSubstitutionScope>() ) : ScopeSessionKey<FirClass<*>, FirClassSubstitutionScope>()
data class DelegatedMemberScopeKey(val callableId: CallableId) : ScopeSessionKey<FirField, FirDelegatedMemberScope>()
fun FirClass<*>.unsubstitutedScope(useSiteSession: FirSession, scopeSession: ScopeSession): FirTypeScope { fun FirClass<*>.unsubstitutedScope(useSiteSession: FirSession, scopeSession: ScopeSession): FirTypeScope {
return scopeProvider.getUseSiteMemberScope(this, useSiteSession, scopeSession) return scopeProvider.getUseSiteMemberScope(this, useSiteSession, scopeSession)
} }
@@ -102,13 +105,20 @@ internal fun FirClass<*>.scope(
substitutor: ConeSubstitutor, substitutor: ConeSubstitutor,
useSiteSession: FirSession, useSiteSession: FirSession,
scopeSession: ScopeSession, scopeSession: ScopeSession,
delegateField: FirField? = null,
skipPrivateMembers: Boolean, skipPrivateMembers: Boolean,
classId: ClassId? = this.classId, classId: ClassId? = this.classId,
isFromExpectClass: Boolean = false isFromExpectClass: Boolean = false
): FirTypeScope { ): FirTypeScope {
val basicScope = scopeProvider.getUseSiteMemberScope( val basicScope = unsubstitutedScope(useSiteSession, scopeSession).let {
this, useSiteSession, scopeSession if (delegateField != null) {
) scopeSession.getOrBuild(delegateField, DelegatedMemberScopeKey(delegateField.symbol.callableId)) {
FirDelegatedMemberScope(it, useSiteSession)
}
} else {
it
}
}
if (substitutor == ConeSubstitutor.Empty) return basicScope if (substitutor == ConeSubstitutor.Empty) return basicScope
return scopeSession.getOrBuild( 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 Enhancement : FirDeclarationOrigin()
object ImportedFromObject : FirDeclarationOrigin() object ImportedFromObject : FirDeclarationOrigin()
object IntersectionOverride : FirDeclarationOrigin() object IntersectionOverride : FirDeclarationOrigin()
object Delegated : FirDeclarationOrigin()
class Plugin(val key: FirPluginKey) : FirDeclarationOrigin() class Plugin(val key: FirPluginKey) : FirDeclarationOrigin()
} }