Add extensionReceiver to ScopeTowerLevel & use it in ImportingScopeBasedTowerLevel

This commit is contained in:
Stanislav Erokhin
2015-12-08 18:43:56 +03:00
parent 57b5588498
commit b7e4fdf4d5
6 changed files with 40 additions and 76 deletions
@@ -141,7 +141,7 @@ private fun ScopeTower.getExtensionInvokeCandidateDescriptor(
): CandidateWithBoundDispatchReceiver<FunctionDescriptor>? {
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()
@@ -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)
@@ -41,7 +41,7 @@ interface ScopeTower {
val dataFlowInfo: DataFlowDecorator
// The closest (the most local) levels goes first
val levels: Sequence<ScopeTowerLevel>
val levels: List<ScopeTowerLevel>
}
interface DataFlowDecorator {
@@ -54,9 +54,9 @@ interface DataFlowDecorator {
}
interface ScopeTowerLevel {
fun getVariables(name: Name): Collection<CandidateWithBoundDispatchReceiver<VariableDescriptor>>
fun getVariables(name: Name, extensionReceiver: ReceiverValue?): Collection<CandidateWithBoundDispatchReceiver<VariableDescriptor>>
fun getFunctions(name: Name): Collection<CandidateWithBoundDispatchReceiver<FunctionDescriptor>>
fun getFunctions(name: Name, extensionReceiver: ReceiverValue?): Collection<CandidateWithBoundDispatchReceiver<FunctionDescriptor>>
}
interface CandidateWithBoundDispatchReceiver<out D : CallableDescriptor> {
@@ -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<D : CallableDescriptor>(
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<ScopeTowerLevel> = createPrototypeLevels().asSequence().map { it.asTowerLevel(this) }
override val levels: List<ScopeTowerLevel> = createLevels()
// we shouldn't calculate this before we entrance to some importing scope
private val receiversForSyntheticExtensions: Collection<KotlinType> 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<KotlinType>): LevelFactory() {
override fun asTowerLevel(resolveTower: ScopeTower) = ImportingScopeBasedTowerLevel(resolveTower, importingScope, lazyReceiversForSyntheticExtensions())
}
}
private fun createPrototypeLevels(): List<LevelFactory> {
val result = ArrayList<LevelFactory>()
private fun createLevels(): List<ScopeTowerLevel> {
val result = ArrayList<ScopeTowerLevel>()
// locals win
lexicalScope.parentsWithSelf.
filterIsInstance<LexicalScope>().
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))
}
}
@@ -51,7 +51,7 @@ internal abstract class AbstractSimpleScopeTowerProcessor<C>(
internal class ExplicitReceiverScopeTowerProcessor<C>(
context: TowerContext<C>,
val explicitReceiver: ReceiverValue,
val collectCandidates: ScopeTowerLevel.(Name) -> Collection<CandidateWithBoundDispatchReceiver<*>>
val collectCandidates: ScopeTowerLevel.(name: Name, extensionReceiver: ReceiverValue?) -> Collection<CandidateWithBoundDispatchReceiver<*>>
): AbstractSimpleScopeTowerProcessor<C>(context) {
override fun simpleProcess(data: TowerData): Collection<C> {
return when (data) {
@@ -63,12 +63,12 @@ internal class ExplicitReceiverScopeTowerProcessor<C>(
private fun resolveAsMember(): Collection<C> {
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<C> {
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<C>(
private class QualifierScopeTowerProcessor<C>(
context: TowerContext<C>,
val qualifier: QualifierReceiver,
val collectCandidates: ScopeTowerLevel.(Name) -> Collection<CandidateWithBoundDispatchReceiver<*>>
val collectCandidates: ScopeTowerLevel.(name: Name, extensionReceiver: ReceiverValue?) -> Collection<CandidateWithBoundDispatchReceiver<*>>
): AbstractSimpleScopeTowerProcessor<C>(context) {
override fun simpleProcess(data: TowerData): Collection<C> {
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<C>(
private class NoExplicitReceiverScopeTowerProcessor<C>(
context: TowerContext<C>,
val collectCandidates: ScopeTowerLevel.(Name) -> Collection<CandidateWithBoundDispatchReceiver<*>>
val collectCandidates: ScopeTowerLevel.(name: Name, extensionReceiver: ReceiverValue?) -> Collection<CandidateWithBoundDispatchReceiver<*>>
) : AbstractSimpleScopeTowerProcessor<C>(context) {
override fun simpleProcess(data: TowerData): Collection<C>
= 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<C>(
private fun <C> createSimpleProcessor(
context: TowerContext<C>,
explicitReceiver: Receiver?,
collectCandidates: ScopeTowerLevel.(Name) -> Collection<CandidateWithBoundDispatchReceiver<*>>
collectCandidates: ScopeTowerLevel.(name: Name, extensionReceiver: ReceiverValue?) -> Collection<CandidateWithBoundDispatchReceiver<*>>
) : ScopeTowerProcessor<C> {
if (explicitReceiver is ReceiverValue) {
return ExplicitReceiverScopeTowerProcessor(context, explicitReceiver, collectCandidates)
@@ -98,11 +98,11 @@ internal class ReceiverScopeTowerLevel(
return result
}
override fun getVariables(name: Name): Collection<CandidateWithBoundDispatchReceiver<VariableDescriptor>> {
override fun getVariables(name: Name, extensionReceiver: ReceiverValue?): Collection<CandidateWithBoundDispatchReceiver<VariableDescriptor>> {
return collectMembers { getContributedVariables(name, location) }
}
override fun getFunctions(name: Name): Collection<CandidateWithBoundDispatchReceiver<FunctionDescriptor>> {
override fun getFunctions(name: Name, extensionReceiver: ReceiverValue?): Collection<CandidateWithBoundDispatchReceiver<FunctionDescriptor>> {
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<CandidateWithBoundDispatchReceiver<VariableDescriptor>>
override fun getVariables(name: Name, extensionReceiver: ReceiverValue?): Collection<CandidateWithBoundDispatchReceiver<VariableDescriptor>>
= resolutionScope.getContributedVariablesAndObjects(name, location).map {
createCandidateDescriptor(it, dispatchReceiver = null)
}
override fun getFunctions(name: Name): Collection<CandidateWithBoundDispatchReceiver<FunctionDescriptor>>
override fun getFunctions(name: Name, extensionReceiver: ReceiverValue?): Collection<CandidateWithBoundDispatchReceiver<FunctionDescriptor>>
= 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<KotlinType>
private val importingScope: ImportingScope
): ScopeBasedTowerLevel(scopeTower, importingScope) {
override fun getVariables(name: Name): Collection<CandidateWithBoundDispatchReceiver<VariableDescriptor>> {
val synthetic = importingScope.getContributedSyntheticExtensionProperties(receiversForSyntheticExtensions, name, location).map {
override fun getVariables(name: Name, extensionReceiver: ReceiverValue?): Collection<CandidateWithBoundDispatchReceiver<VariableDescriptor>> {
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<CandidateWithBoundDispatchReceiver<FunctionDescriptor>> {
val synthetic = importingScope.getContributedSyntheticExtensionFunctions(receiversForSyntheticExtensions, name, location).map {
override fun getFunctions(name: Name, extensionReceiver: ReceiverValue?): Collection<CandidateWithBoundDispatchReceiver<FunctionDescriptor>> {
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
}
}