From 06bab6ec48d165c2a51b19028cf4bc3f8a73c224 Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Thu, 30 Jan 2020 15:35:49 +0300 Subject: [PATCH] [FIR] Extract QualifierReceiver to a separate file --- .../kotlin/fir/resolve/calls/FirReceivers.kt | 126 ++-------------- .../fir/resolve/calls/QualifierReceiver.kt | 139 ++++++++++++++++++ 2 files changed, 148 insertions(+), 117 deletions(-) create mode 100644 compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/QualifierReceiver.kt diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/FirReceivers.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/FirReceivers.kt index 85bf24a4f61..e3f376e8179 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/FirReceivers.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/FirReceivers.kt @@ -6,27 +6,24 @@ package org.jetbrains.kotlin.fir.resolve.calls import org.jetbrains.kotlin.fir.FirSession -import org.jetbrains.kotlin.fir.declarations.FirClass import org.jetbrains.kotlin.fir.declarations.FirTypeParametersOwner -import org.jetbrains.kotlin.fir.declarations.expandedConeType -import org.jetbrains.kotlin.fir.declarations.impl.FirClassImpl -import org.jetbrains.kotlin.fir.declarations.impl.FirSealedClassImpl import org.jetbrains.kotlin.fir.expressions.FirExpression -import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier import org.jetbrains.kotlin.fir.expressions.impl.FirThisReceiverExpressionImpl import org.jetbrains.kotlin.fir.references.impl.FirImplicitThisReference import org.jetbrains.kotlin.fir.renderWithType -import org.jetbrains.kotlin.fir.resolve.* +import org.jetbrains.kotlin.fir.resolve.ScopeSession +import org.jetbrains.kotlin.fir.resolve.constructType +import org.jetbrains.kotlin.fir.resolve.scope import org.jetbrains.kotlin.fir.scopes.FirScope -import org.jetbrains.kotlin.fir.scopes.KotlinScopeProvider -import org.jetbrains.kotlin.fir.scopes.impl.* import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol -import org.jetbrains.kotlin.fir.symbols.impl.* -import org.jetbrains.kotlin.fir.types.* +import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol +import org.jetbrains.kotlin.fir.types.ConeKotlinErrorType +import org.jetbrains.kotlin.fir.types.ConeKotlinType +import org.jetbrains.kotlin.fir.types.ConeStarProjection +import org.jetbrains.kotlin.fir.types.coneTypeSafe import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl import org.jetbrains.kotlin.fir.types.impl.FirResolvedTypeRefImpl -import org.jetbrains.kotlin.name.ClassId -import java.util.ArrayDeque interface Receiver { fun scope(useSiteSession: FirSession, scopeSession: ScopeSession): FirScope? @@ -70,111 +67,6 @@ abstract class AbstractExplicitReceiverValue : AbstractExplic get() = explicitReceiver } -class QualifierReceiver(override val explicitReceiver: FirResolvedQualifier) : AbstractExplicitReceiver() { - private fun collectSuperTypeScopesComposedByDepth( - klass: FirClass<*>, - useSiteSession: FirSession, - scopeSession: ScopeSession - ): List { - val result = mutableListOf() - val provider = klass.scopeProvider - val levelScopes = mutableListOf() - var currentDepth = 1 - val queue = ArrayDeque>() - queue.addAll( - lookupSuperTypes(klass, lookupInterfaces = true, deep = false, useSiteSession = useSiteSession).map { it to 1 } - ) - val visitedSymbols = mutableSetOf() - while (queue.isNotEmpty()) { - val (useSiteSuperType, depth) = queue.poll() - if (depth > currentDepth) { - currentDepth = depth - result += FirCompositeScope(levelScopes.toMutableList()) - levelScopes.clear() - } - if (useSiteSuperType is ConeClassErrorType) continue - val superTypeSymbol = useSiteSuperType.lookupTag.toSymbol(useSiteSession) as? FirRegularClassSymbol - ?: continue - if (!visitedSymbols.add(superTypeSymbol)) continue - val superTypeScope = provider.getStaticMemberScopeForCallables( - superTypeSymbol.fir, useSiteSession, scopeSession - ) - if (superTypeScope != null) { - levelScopes += superTypeScope - } - queue.addAll( - lookupSuperTypes( - superTypeSymbol.fir, lookupInterfaces = true, deep = false, useSiteSession = useSiteSession - ).map { it to currentDepth + 1 } - ) - } - return result - } - - private fun getClassSymbolWithCallableScopes( - classId: ClassId, - useSiteSession: FirSession, - scopeSession: ScopeSession - ): Pair?, List> { - val symbol = useSiteSession.firSymbolProvider.getClassLikeSymbolByFqName(classId) ?: return null to emptyList() - if (symbol is FirTypeAliasSymbol) { - val expansionSymbol = symbol.fir.expandedConeType?.lookupTag?.toSymbol(useSiteSession) - if (expansionSymbol != null) { - return getClassSymbolWithCallableScopes(expansionSymbol.classId, useSiteSession, scopeSession) - } - } else { - return (symbol as? FirClassSymbol<*>)?.let { klassSymbol -> - val klass = klassSymbol.fir - klassSymbol to run { - val result = mutableListOf() - val provider = klass.scopeProvider - val klassScope = provider.getStaticMemberScopeForCallables(klass, useSiteSession, scopeSession) - if (klassScope != null) { - result += klassScope - if (provider is KotlinScopeProvider) return@run result - result += collectSuperTypeScopesComposedByDepth(klass, useSiteSession, scopeSession) - } - result - } - } ?: (null to emptyList()) - } - - return null to emptyList() - } - - fun qualifierScopes(useSiteSession: FirSession, scopeSession: ScopeSession): List { - val classId = explicitReceiver.classId ?: return emptyList() - - val (classSymbol, callableScopes) = getClassSymbolWithCallableScopes(classId, useSiteSession, scopeSession) - if (classSymbol != null) { - val klass = classSymbol.fir - val classifierScope = if (klass is FirClassImpl || klass is FirSealedClassImpl) { - nestedClassifierScope(klass) - } else { - useSiteSession.firSymbolProvider.getNestedClassifierScope(classId) - } - - return when { - classifierScope == null -> { - callableScopes.map { FirQualifierScope(it, null) } - } - callableScopes.isEmpty() -> { - listOf(FirQualifierScope(null, classifierScope)) - } - else -> { - listOf(FirQualifierScope(callableScopes.first(), classifierScope)) + - callableScopes.drop(1).map { FirQualifierScope(it, null) } - } - } - } - return emptyList() - } - - override fun scope(useSiteSession: FirSession, scopeSession: ScopeSession): FirScope? { - return FirCompositeScope(qualifierScopes(useSiteSession, scopeSession).toMutableList()) - } -} - internal class ExpressionReceiverValue( override val explicitReceiver: FirExpression ) : AbstractExplicitReceiverValue(), ReceiverValue diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/QualifierReceiver.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/QualifierReceiver.kt new file mode 100644 index 00000000000..52789b9292b --- /dev/null +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/QualifierReceiver.kt @@ -0,0 +1,139 @@ +/* + * 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.resolve.calls + +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.declarations.FirClass +import org.jetbrains.kotlin.fir.declarations.expandedConeType +import org.jetbrains.kotlin.fir.declarations.impl.FirClassImpl +import org.jetbrains.kotlin.fir.declarations.impl.FirSealedClassImpl +import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier +import org.jetbrains.kotlin.fir.resolve.ScopeSession +import org.jetbrains.kotlin.fir.resolve.firSymbolProvider +import org.jetbrains.kotlin.fir.resolve.lookupSuperTypes +import org.jetbrains.kotlin.fir.resolve.toSymbol +import org.jetbrains.kotlin.fir.scopes.FirScope +import org.jetbrains.kotlin.fir.scopes.KotlinScopeProvider +import org.jetbrains.kotlin.fir.scopes.impl.FirCompositeScope +import org.jetbrains.kotlin.fir.scopes.impl.FirQualifierScope +import org.jetbrains.kotlin.fir.scopes.impl.nestedClassifierScope +import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirTypeAliasSymbol +import org.jetbrains.kotlin.fir.types.ConeClassErrorType +import org.jetbrains.kotlin.fir.types.ConeClassLikeType +import org.jetbrains.kotlin.name.ClassId +import java.util.ArrayDeque + +class QualifierReceiver(override val explicitReceiver: FirResolvedQualifier) : AbstractExplicitReceiver() { + private fun collectSuperTypeScopesComposedByDepth( + klass: FirClass<*>, + useSiteSession: FirSession, + scopeSession: ScopeSession + ): List { + val result = mutableListOf() + val provider = klass.scopeProvider + val levelScopes = mutableListOf() + var currentDepth = 1 + val queue = + ArrayDeque>() + queue.addAll( + lookupSuperTypes(klass, lookupInterfaces = true, deep = false, useSiteSession = useSiteSession).map { it to 1 } + ) + val visitedSymbols = mutableSetOf() + while (queue.isNotEmpty()) { + val (useSiteSuperType, depth) = queue.poll() + if (depth > currentDepth) { + currentDepth = depth + result += FirCompositeScope(levelScopes.toMutableList()) + levelScopes.clear() + } + if (useSiteSuperType is ConeClassErrorType) continue + val superTypeSymbol = useSiteSuperType.lookupTag.toSymbol(useSiteSession) as? FirRegularClassSymbol + ?: continue + if (!visitedSymbols.add(superTypeSymbol)) continue + val superTypeScope = provider.getStaticMemberScopeForCallables( + superTypeSymbol.fir, useSiteSession, scopeSession + ) + if (superTypeScope != null) { + levelScopes += superTypeScope + } + queue.addAll( + lookupSuperTypes( + superTypeSymbol.fir, lookupInterfaces = true, deep = false, useSiteSession = useSiteSession + ).map { it to currentDepth + 1 } + ) + } + return result + } + + private fun getClassSymbolWithCallableScopes( + classId: ClassId, + useSiteSession: FirSession, + scopeSession: ScopeSession + ): Pair?, List> { + val symbol = useSiteSession.firSymbolProvider.getClassLikeSymbolByFqName(classId) ?: return null to emptyList() + if (symbol is FirTypeAliasSymbol) { + val expansionSymbol = symbol.fir.expandedConeType?.lookupTag?.toSymbol(useSiteSession) + if (expansionSymbol != null) { + return getClassSymbolWithCallableScopes(expansionSymbol.classId, useSiteSession, scopeSession) + } + } else { + return (symbol as? FirClassSymbol<*>)?.let { klassSymbol -> + val klass = klassSymbol.fir + klassSymbol to run { + val result = mutableListOf() + val provider = klass.scopeProvider + val klassScope = provider.getStaticMemberScopeForCallables(klass, useSiteSession, scopeSession) + if (klassScope != null) { + result += klassScope + if (provider is KotlinScopeProvider) return@run result + result += collectSuperTypeScopesComposedByDepth(klass, useSiteSession, scopeSession) + } + result + } + } ?: (null to emptyList()) + } + + return null to emptyList() + } + + fun qualifierScopes(useSiteSession: FirSession, scopeSession: ScopeSession): List { + val classId = explicitReceiver.classId ?: return emptyList() + + val (classSymbol, callableScopes) = getClassSymbolWithCallableScopes(classId, useSiteSession, scopeSession) + if (classSymbol != null) { + val klass = classSymbol.fir + val classifierScope = if (klass is FirClassImpl || klass is FirSealedClassImpl) { + nestedClassifierScope(klass) + } else { + useSiteSession.firSymbolProvider.getNestedClassifierScope(classId) + } + + return when { + classifierScope == null -> { + callableScopes.map { FirQualifierScope(it, null) } + } + callableScopes.isEmpty() -> { + listOf(FirQualifierScope(null, classifierScope)) + } + else -> { + listOf( + FirQualifierScope(callableScopes.first(), classifierScope) + ) + + callableScopes.drop(1).map { + FirQualifierScope(it, null) + } + } + } + } + return emptyList() + } + + override fun scope(useSiteSession: FirSession, scopeSession: ScopeSession): FirScope? { + return FirCompositeScope(qualifierScopes(useSiteSession, scopeSession).toMutableList()) + } +} \ No newline at end of file