FIR: Clarify contracts for two versions FirClass<*>::scope

- One of them really creates a scope a specific type
- Another one is used for supertypes and includes creation of FirDelegatedMemberScope wrapper
This commit is contained in:
Denis Zharkov
2020-09-23 14:36:46 +03:00
parent 1adf731fc5
commit cb07ffc4fd
3 changed files with 49 additions and 24 deletions
@@ -15,7 +15,7 @@ import org.jetbrains.kotlin.fir.resolve.transformers.ensureResolved
import org.jetbrains.kotlin.fir.scopes.FirTypeScope
import org.jetbrains.kotlin.fir.scopes.impl.FirStandardOverrideChecker
import org.jetbrains.kotlin.fir.scopes.impl.FirTypeIntersectionScope
import org.jetbrains.kotlin.fir.scopes.scope
import org.jetbrains.kotlin.fir.scopes.scopeForClass
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
import org.jetbrains.kotlin.fir.typeContext
import org.jetbrains.kotlin.fir.types.*
@@ -39,7 +39,7 @@ private fun ConeKotlinType.scope(useSiteSession: FirSession, scopeSession: Scope
val substitution = createSubstitution(fir.typeParameters, fullyExpandedType, useSiteSession)
fir.scope(substitutorByMap(substitution), useSiteSession, scopeSession, skipPrivateMembers = false)
fir.scopeForClass(substitutorByMap(substitution), useSiteSession, scopeSession)
}
is ConeTypeParameterType -> {
val symbol = lookupTag.toSymbol()
@@ -16,7 +16,7 @@ import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
import org.jetbrains.kotlin.fir.resolve.transformers.ensureResolved
import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.scopes.impl.FirClassSubstitutionScope
import org.jetbrains.kotlin.fir.scopes.scope
import org.jetbrains.kotlin.fir.scopes.scopeForClass
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.name.Name
@@ -153,8 +153,8 @@ private fun processConstructors(
} else basicScope
}
is FirClassSymbol ->
(matchedSymbol.fir as FirClass<*>).scope(
substitutor, session, scopeSession, skipPrivateMembers = false,
(matchedSymbol.fir as FirClass<*>).scopeForClass(
substitutor, session, scopeSession
)
}
@@ -13,6 +13,7 @@ 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.ConeClassLikeLookupTag
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.fir.types.ConeClassErrorType
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
@@ -44,12 +45,10 @@ class KotlinScopeProvider(
val symbol = useSiteSuperType.lookupTag.toSymbol(useSiteSession)
if (symbol is FirRegularClassSymbol) {
val delegateField = delegateFields.find { it.returnTypeRef.coneType == useSiteSuperType }
symbol.fir.scope(
symbol.fir.scopeForSupertype(
substitutor(symbol, useSiteSuperType, useSiteSession),
useSiteSession, scopeSession, delegateField,
skipPrivateMembers = true,
classId = klass.classId,
isFromExpectClass = (klass as? FirRegularClass)?.isExpect == true
subClass = klass
).let {
it as? FirTypeScope ?: error("$it is expected to be FirOverrideAwareScope")
}
@@ -101,32 +100,58 @@ fun FirClass<*>.unsubstitutedScope(useSiteSession: FirSession, scopeSession: Sco
return scopeProvider.getUseSiteMemberScope(this, useSiteSession, scopeSession)
}
internal fun FirClass<*>.scope(
fun FirClass<*>.scopeForClass(
substitutor: ConeSubstitutor,
useSiteSession: FirSession,
scopeSession: ScopeSession
): FirTypeScope = scopeForClassImpl(
substitutor, useSiteSession, scopeSession,
skipPrivateMembers = false,
containingClassForAdditionalMembers = symbol.toLookupTag(),
// TODO: why it's always false?
isFromExpectClass = false
)
private fun FirClass<*>.scopeForSupertype(
substitutor: ConeSubstitutor,
useSiteSession: FirSession,
scopeSession: ScopeSession,
delegateField: FirField? = null,
skipPrivateMembers: Boolean,
classId: ClassId? = this.classId,
isFromExpectClass: Boolean = false
): FirTypeScope {
val basicScope = unsubstitutedScope(useSiteSession, scopeSession).let {
if (delegateField != null) {
scopeSession.getOrBuild(delegateField, DelegatedMemberScopeKey(delegateField.symbol.callableId)) {
FirDelegatedMemberScope(it, useSiteSession)
}
} else {
it
delegateField: FirField?,
subClass: FirClass<*>
): FirTypeScope = scopeForClassImpl(
substitutor,
useSiteSession,
scopeSession,
skipPrivateMembers = true,
containingClassForAdditionalMembers = subClass.symbol.toLookupTag(),
isFromExpectClass = (subClass as? FirRegularClass)?.isExpect == true
).let {
if (delegateField != null) {
scopeSession.getOrBuild(delegateField, DelegatedMemberScopeKey(delegateField.symbol.callableId)) {
FirDelegatedMemberScope(it, useSiteSession, subClass.symbol.toLookupTag(), delegateField)
}
} else {
it
}
}
private fun FirClass<*>.scopeForClassImpl(
substitutor: ConeSubstitutor,
useSiteSession: FirSession,
scopeSession: ScopeSession,
skipPrivateMembers: Boolean,
containingClassForAdditionalMembers: ConeClassLikeLookupTag,
isFromExpectClass: Boolean
): FirTypeScope {
val basicScope = unsubstitutedScope(useSiteSession, scopeSession)
if (substitutor == ConeSubstitutor.Empty) return basicScope
return scopeSession.getOrBuild(
this, ConeSubstitutionScopeKey(classId, isFromExpectClass, substitutor)
this, ConeSubstitutionScopeKey(containingClassForAdditionalMembers.classId, isFromExpectClass, substitutor)
) {
FirClassSubstitutionScope(
useSiteSession, basicScope, scopeSession, substitutor,
skipPrivateMembers, classId, makeExpect = isFromExpectClass
skipPrivateMembers, containingClassForAdditionalMembers.classId, makeExpect = isFromExpectClass
)
}
}