From b7e4fdf4d5088d79dca0e9544f49f1eee6bedfd5 Mon Sep 17 00:00:00 2001 From: Stanislav Erokhin Date: Tue, 8 Dec 2015 18:43:56 +0300 Subject: [PATCH] Add extensionReceiver to ScopeTowerLevel & use it in ImportingScopeBasedTowerLevel --- .../resolve/calls/tower/InvokeProcessors.kt | 2 +- .../calls/tower/NewResolveOldInference.kt | 2 +- .../kotlin/resolve/calls/tower/ScopeTower.kt | 6 +- .../resolve/calls/tower/ScopeTowerImpl.kt | 55 +++---------------- .../calls/tower/ScopeTowerProcessors.kt | 18 +++--- .../kotlin/resolve/calls/tower/TowerLevels.kt | 33 ++++++----- 6 files changed, 40 insertions(+), 76 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/InvokeProcessors.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/InvokeProcessors.kt index c7e4f147d21..938711e4e9d 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/InvokeProcessors.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/InvokeProcessors.kt @@ -141,7 +141,7 @@ private fun ScopeTower.getExtensionInvokeCandidateDescriptor( ): CandidateWithBoundDispatchReceiver? { if (!KotlinBuiltIns.isExactExtensionFunctionType(extensionFunctionReceiver.type)) return null - return ReceiverScopeTowerLevel(this, extensionFunctionReceiver).getFunctions(OperatorNameConventions.INVOKE).single().let { + return ReceiverScopeTowerLevel(this, extensionFunctionReceiver).getFunctions(OperatorNameConventions.INVOKE, null).single().let { assert(it.diagnostics.isEmpty()) val synthesizedInvoke = createSynthesizedInvokes(listOf(it.descriptor)).single() diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewResolveOldInference.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewResolveOldInference.kt index bf89f4e0007..623ffafe005 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewResolveOldInference.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewResolveOldInference.kt @@ -66,7 +66,7 @@ class NewResolveOldInference( val explicitReceiver = context.call.explicitReceiver.check { it.exists() } val dynamicScope = dynamicCallableDescriptors.createDynamicDescriptorScope(context.call, context.scope.ownerDescriptor) - val scopeTower = ScopeTowerImpl(context, dynamicScope, explicitReceiver, context.call.createLookupLocation()) + val scopeTower = ScopeTowerImpl(context, dynamicScope, context.call.createLookupLocation()) val baseContext = Context(scopeTower, name, context, tracing) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/ScopeTower.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/ScopeTower.kt index 834ca890225..8a381f09ce1 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/ScopeTower.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/ScopeTower.kt @@ -41,7 +41,7 @@ interface ScopeTower { val dataFlowInfo: DataFlowDecorator // The closest (the most local) levels goes first - val levels: Sequence + val levels: List } interface DataFlowDecorator { @@ -54,9 +54,9 @@ interface DataFlowDecorator { } interface ScopeTowerLevel { - fun getVariables(name: Name): Collection> + fun getVariables(name: Name, extensionReceiver: ReceiverValue?): Collection> - fun getFunctions(name: Name): Collection> + fun getFunctions(name: Name, extensionReceiver: ReceiverValue?): Collection> } interface CandidateWithBoundDispatchReceiver { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/ScopeTowerImpl.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/ScopeTowerImpl.kt index 05bc01a32b7..e75ed6a2e3d 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/ScopeTowerImpl.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/ScopeTowerImpl.kt @@ -17,7 +17,6 @@ package org.jetbrains.kotlin.resolve.calls.tower import org.jetbrains.kotlin.descriptors.CallableDescriptor -import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor import org.jetbrains.kotlin.incremental.components.LookupLocation import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue @@ -25,8 +24,6 @@ import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory import org.jetbrains.kotlin.resolve.scopes.ImportingScope import org.jetbrains.kotlin.resolve.scopes.LexicalScope import org.jetbrains.kotlin.resolve.scopes.MemberScope -import org.jetbrains.kotlin.resolve.scopes.receivers.ClassQualifier -import org.jetbrains.kotlin.resolve.scopes.receivers.Receiver import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue import org.jetbrains.kotlin.resolve.scopes.utils.getImplicitReceiversHierarchy import org.jetbrains.kotlin.resolve.scopes.utils.parentsWithSelf @@ -45,7 +42,6 @@ internal class CandidateWithBoundDispatchReceiverImpl( internal class ScopeTowerImpl( resolutionContext: ResolutionContext<*>, override val dynamicScope: MemberScope, - private val explicitReceiver: Receiver?, override val location: LookupLocation ): ScopeTower { override val dataFlowInfo: DataFlowDecorator = DataFlowDecoratorImpl(resolutionContext) @@ -54,62 +50,25 @@ internal class ScopeTowerImpl( override val implicitReceivers = resolutionContext.scope.getImplicitReceiversHierarchy(). mapNotNull { it.value.check { !it.type.containsError() } } - override val levels: Sequence = createPrototypeLevels().asSequence().map { it.asTowerLevel(this) } + override val levels: List = createLevels() - // we shouldn't calculate this before we entrance to some importing scope - private val receiversForSyntheticExtensions: Collection by lazy(LazyThreadSafetyMode.PUBLICATION) { - if (explicitReceiver != null) { - if (explicitReceiver is ReceiverValue) { - return@lazy dataFlowInfo.getAllPossibleTypes(explicitReceiver) - } - - if (explicitReceiver is ClassQualifier) { - explicitReceiver.classValueReceiver?.let { - return@lazy dataFlowInfo.getAllPossibleTypes(it) - } - } - - // explicit receiver is package or class without companion object - emptyList() - } - else { - implicitReceivers.flatMap { dataFlowInfo.getAllPossibleTypes(it) } - } - } - - private sealed class LevelFactory { - abstract fun asTowerLevel(resolveTower: ScopeTower): ScopeTowerLevel - - class Scope(val lexicalScope: LexicalScope): LevelFactory() { - override fun asTowerLevel(resolveTower: ScopeTower) = ScopeBasedTowerLevel(resolveTower, lexicalScope) - } - - class Receiver(val implicitReceiver: ReceiverParameterDescriptor): LevelFactory() { - override fun asTowerLevel(resolveTower: ScopeTower) = ReceiverScopeTowerLevel(resolveTower, implicitReceiver.value) - } - - class ImportingScopeFactory(val importingScope: ImportingScope, val lazyReceiversForSyntheticExtensions: () -> Collection): LevelFactory() { - override fun asTowerLevel(resolveTower: ScopeTower) = ImportingScopeBasedTowerLevel(resolveTower, importingScope, lazyReceiversForSyntheticExtensions()) - } - } - - private fun createPrototypeLevels(): List { - val result = ArrayList() + private fun createLevels(): List { + val result = ArrayList() // locals win lexicalScope.parentsWithSelf. filterIsInstance(). filter { it.kind.withLocalDescriptors }. - mapTo(result) { LevelFactory.Scope(it) } + mapTo(result) { ScopeBasedTowerLevel(this, it) } lexicalScope.parentsWithSelf.forEach { scope -> if (scope is LexicalScope) { - if (!scope.kind.withLocalDescriptors) result.add(LevelFactory.Scope(scope)) + if (!scope.kind.withLocalDescriptors) result.add(ScopeBasedTowerLevel(this, scope)) - scope.implicitReceiver?.let { result.add(LevelFactory.Receiver(it)) } + scope.implicitReceiver?.let { result.add(ReceiverScopeTowerLevel(this, it.value)) } } else { - result.add(LevelFactory.ImportingScopeFactory(scope as ImportingScope, { receiversForSyntheticExtensions })) + result.add(ImportingScopeBasedTowerLevel(this, scope as ImportingScope)) } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/ScopeTowerProcessors.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/ScopeTowerProcessors.kt index 9c7c1345d05..5d9c2577c75 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/ScopeTowerProcessors.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/ScopeTowerProcessors.kt @@ -51,7 +51,7 @@ internal abstract class AbstractSimpleScopeTowerProcessor( internal class ExplicitReceiverScopeTowerProcessor( context: TowerContext, val explicitReceiver: ReceiverValue, - val collectCandidates: ScopeTowerLevel.(Name) -> Collection> + val collectCandidates: ScopeTowerLevel.(name: Name, extensionReceiver: ReceiverValue?) -> Collection> ): AbstractSimpleScopeTowerProcessor(context) { override fun simpleProcess(data: TowerData): Collection { return when (data) { @@ -63,12 +63,12 @@ internal class ExplicitReceiverScopeTowerProcessor( private fun resolveAsMember(): Collection { val members = ReceiverScopeTowerLevel(context.scopeTower, explicitReceiver) - .collectCandidates(name).filter { !it.requiresExtensionReceiver } + .collectCandidates(name, null).filter { !it.requiresExtensionReceiver } return members.map { context.createCandidate(it, ExplicitReceiverKind.DISPATCH_RECEIVER, extensionReceiver = null) } } private fun resolveAsExtension(level: ScopeTowerLevel): Collection { - val extensions = level.collectCandidates(name).filter { it.requiresExtensionReceiver } + val extensions = level.collectCandidates(name, explicitReceiver).filter { it.requiresExtensionReceiver } return extensions.map { context.createCandidate(it, ExplicitReceiverKind.EXTENSION_RECEIVER, extensionReceiver = explicitReceiver) } } } @@ -76,12 +76,12 @@ internal class ExplicitReceiverScopeTowerProcessor( private class QualifierScopeTowerProcessor( context: TowerContext, val qualifier: QualifierReceiver, - val collectCandidates: ScopeTowerLevel.(Name) -> Collection> + val collectCandidates: ScopeTowerLevel.(name: Name, extensionReceiver: ReceiverValue?) -> Collection> ): AbstractSimpleScopeTowerProcessor(context) { override fun simpleProcess(data: TowerData): Collection { if (data != TowerData.Empty) return emptyList() - val staticMembers = QualifierScopeTowerLevel(context.scopeTower, qualifier).collectCandidates(name) + val staticMembers = QualifierScopeTowerLevel(context.scopeTower, qualifier).collectCandidates(name, null) .filter { !it.requiresExtensionReceiver } .map { context.createCandidate(it, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, extensionReceiver = null) } return staticMembers @@ -90,17 +90,17 @@ private class QualifierScopeTowerProcessor( private class NoExplicitReceiverScopeTowerProcessor( context: TowerContext, - val collectCandidates: ScopeTowerLevel.(Name) -> Collection> + val collectCandidates: ScopeTowerLevel.(name: Name, extensionReceiver: ReceiverValue?) -> Collection> ) : AbstractSimpleScopeTowerProcessor(context) { override fun simpleProcess(data: TowerData): Collection = when(data) { is TowerData.TowerLevel -> { - data.level.collectCandidates(name).filter { !it.requiresExtensionReceiver }.map { + data.level.collectCandidates(name, null).filter { !it.requiresExtensionReceiver }.map { context.createCandidate(it, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, extensionReceiver = null) } } is TowerData.BothTowerLevelAndImplicitReceiver -> { - data.level.collectCandidates(name).filter { it.requiresExtensionReceiver }.map { + data.level.collectCandidates(name, data.implicitReceiver).filter { it.requiresExtensionReceiver }.map { context.createCandidate(it, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, extensionReceiver = data.implicitReceiver) } } @@ -111,7 +111,7 @@ private class NoExplicitReceiverScopeTowerProcessor( private fun createSimpleProcessor( context: TowerContext, explicitReceiver: Receiver?, - collectCandidates: ScopeTowerLevel.(Name) -> Collection> + collectCandidates: ScopeTowerLevel.(name: Name, extensionReceiver: ReceiverValue?) -> Collection> ) : ScopeTowerProcessor { if (explicitReceiver is ReceiverValue) { return ExplicitReceiverScopeTowerProcessor(context, explicitReceiver, collectCandidates) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/TowerLevels.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/TowerLevels.kt index 23e9908fdf1..c5b6ba580f2 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/TowerLevels.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/TowerLevels.kt @@ -98,11 +98,11 @@ internal class ReceiverScopeTowerLevel( return result } - override fun getVariables(name: Name): Collection> { + override fun getVariables(name: Name, extensionReceiver: ReceiverValue?): Collection> { return collectMembers { getContributedVariables(name, location) } } - override fun getFunctions(name: Name): Collection> { + override fun getFunctions(name: Name, extensionReceiver: ReceiverValue?): Collection> { return collectMembers { getContributedFunctions(name, location) + it.getInnerConstructors(name, location) } @@ -110,12 +110,12 @@ internal class ReceiverScopeTowerLevel( } internal class QualifierScopeTowerLevel(scopeTower: ScopeTower, val qualifier: QualifierReceiver) : AbstractScopeTowerLevel(scopeTower) { - override fun getVariables(name: Name) = qualifier.getNestedClassesAndPackageMembersScope() + override fun getVariables(name: Name, extensionReceiver: ReceiverValue?) = qualifier.getNestedClassesAndPackageMembersScope() .getContributedVariablesAndObjects(name, location).map { createCandidateDescriptor(it, dispatchReceiver = null) } - override fun getFunctions(name: Name) = qualifier.getNestedClassesAndPackageMembersScope() + override fun getFunctions(name: Name, extensionReceiver: ReceiverValue?) = qualifier.getNestedClassesAndPackageMembersScope() .getContributedFunctionsAndConstructors(name, location).map { createCandidateDescriptor(it, dispatchReceiver = null) } @@ -129,12 +129,12 @@ internal open class ScopeBasedTowerLevel protected constructor( internal constructor(scopeTower: ScopeTower, lexicalScope: LexicalScope): this(scopeTower, lexicalScope as ResolutionScope) - override fun getVariables(name: Name): Collection> + override fun getVariables(name: Name, extensionReceiver: ReceiverValue?): Collection> = resolutionScope.getContributedVariablesAndObjects(name, location).map { createCandidateDescriptor(it, dispatchReceiver = null) } - override fun getFunctions(name: Name): Collection> + override fun getFunctions(name: Name, extensionReceiver: ReceiverValue?): Collection> = resolutionScope.getContributedFunctionsAndConstructors(name, location).map { createCandidateDescriptor(it, dispatchReceiver = null) } @@ -142,22 +142,27 @@ internal open class ScopeBasedTowerLevel protected constructor( internal class ImportingScopeBasedTowerLevel( scopeTower: ScopeTower, - private val importingScope: ImportingScope, - private val receiversForSyntheticExtensions: Collection + private val importingScope: ImportingScope ): ScopeBasedTowerLevel(scopeTower, importingScope) { - override fun getVariables(name: Name): Collection> { - val synthetic = importingScope.getContributedSyntheticExtensionProperties(receiversForSyntheticExtensions, name, location).map { + override fun getVariables(name: Name, extensionReceiver: ReceiverValue?): Collection> { + if (extensionReceiver == null) return super.getVariables(name, null) + + val extensionReceiverTypes = scopeTower.dataFlowInfo.getAllPossibleTypes(extensionReceiver) + val synthetic = importingScope.getContributedSyntheticExtensionProperties(extensionReceiverTypes, name, location).map { createCandidateDescriptor(it, dispatchReceiver = null) } - return super.getVariables(name) + synthetic + return super.getVariables(name, null) + synthetic } - override fun getFunctions(name: Name): Collection> { - val synthetic = importingScope.getContributedSyntheticExtensionFunctions(receiversForSyntheticExtensions, name, location).map { + override fun getFunctions(name: Name, extensionReceiver: ReceiverValue?): Collection> { + if (extensionReceiver == null) return super.getFunctions(name, null) + + val extensionReceiverTypes = scopeTower.dataFlowInfo.getAllPossibleTypes(extensionReceiver) + val synthetic = importingScope.getContributedSyntheticExtensionFunctions(extensionReceiverTypes, name, location).map { createCandidateDescriptor(it, dispatchReceiver = null) } - return super.getFunctions(name) + synthetic + return super.getFunctions(name, null) + synthetic } }