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.FirTypeScope
import org.jetbrains.kotlin.fir.scopes.impl.FirStandardOverrideChecker import org.jetbrains.kotlin.fir.scopes.impl.FirStandardOverrideChecker
import org.jetbrains.kotlin.fir.scopes.impl.FirTypeIntersectionScope 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.symbols.impl.FirTypeParameterSymbol
import org.jetbrains.kotlin.fir.typeContext import org.jetbrains.kotlin.fir.typeContext
import org.jetbrains.kotlin.fir.types.* 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) val substitution = createSubstitution(fir.typeParameters, fullyExpandedType, useSiteSession)
fir.scope(substitutorByMap(substitution), useSiteSession, scopeSession, skipPrivateMembers = false) fir.scopeForClass(substitutorByMap(substitution), useSiteSession, scopeSession)
} }
is ConeTypeParameterType -> { is ConeTypeParameterType -> {
val symbol = lookupTag.toSymbol() 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.resolve.transformers.ensureResolved
import org.jetbrains.kotlin.fir.scopes.FirScope import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.scopes.impl.FirClassSubstitutionScope 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.symbols.impl.*
import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
@@ -153,8 +153,8 @@ private fun processConstructors(
} else basicScope } else basicScope
} }
is FirClassSymbol -> is FirClassSymbol ->
(matchedSymbol.fir as FirClass<*>).scope( (matchedSymbol.fir as FirClass<*>).scopeForClass(
substitutor, session, scopeSession, skipPrivateMembers = false, 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.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.CallableId
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
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
@@ -44,12 +45,10 @@ class KotlinScopeProvider(
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 } val delegateField = delegateFields.find { it.returnTypeRef.coneType == useSiteSuperType }
symbol.fir.scope( symbol.fir.scopeForSupertype(
substitutor(symbol, useSiteSuperType, useSiteSession), substitutor(symbol, useSiteSuperType, useSiteSession),
useSiteSession, scopeSession, delegateField, useSiteSession, scopeSession, delegateField,
skipPrivateMembers = true, subClass = klass
classId = klass.classId,
isFromExpectClass = (klass as? FirRegularClass)?.isExpect == true
).let { ).let {
it as? FirTypeScope ?: error("$it is expected to be FirOverrideAwareScope") 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) 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, substitutor: ConeSubstitutor,
useSiteSession: FirSession, useSiteSession: FirSession,
scopeSession: ScopeSession, scopeSession: ScopeSession,
delegateField: FirField? = null, delegateField: FirField?,
skipPrivateMembers: Boolean, subClass: FirClass<*>
classId: ClassId? = this.classId, ): FirTypeScope = scopeForClassImpl(
isFromExpectClass: Boolean = false substitutor,
): FirTypeScope { useSiteSession,
val basicScope = unsubstitutedScope(useSiteSession, scopeSession).let { scopeSession,
if (delegateField != null) { skipPrivateMembers = true,
scopeSession.getOrBuild(delegateField, DelegatedMemberScopeKey(delegateField.symbol.callableId)) { containingClassForAdditionalMembers = subClass.symbol.toLookupTag(),
FirDelegatedMemberScope(it, useSiteSession) isFromExpectClass = (subClass as? FirRegularClass)?.isExpect == true
} ).let {
} else { if (delegateField != null) {
it 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 if (substitutor == ConeSubstitutor.Empty) return basicScope
return scopeSession.getOrBuild( return scopeSession.getOrBuild(
this, ConeSubstitutionScopeKey(classId, isFromExpectClass, substitutor) this, ConeSubstitutionScopeKey(containingClassForAdditionalMembers.classId, isFromExpectClass, substitutor)
) { ) {
FirClassSubstitutionScope( FirClassSubstitutionScope(
useSiteSession, basicScope, scopeSession, substitutor, useSiteSession, basicScope, scopeSession, substitutor,
skipPrivateMembers, classId, makeExpect = isFromExpectClass skipPrivateMembers, containingClassForAdditionalMembers.classId, makeExpect = isFromExpectClass
) )
} }
} }