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>? { ): CandidateWithBoundDispatchReceiver<FunctionDescriptor>? {
if (!KotlinBuiltIns.isExactExtensionFunctionType(extensionFunctionReceiver.type)) return null 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()) assert(it.diagnostics.isEmpty())
val synthesizedInvoke = createSynthesizedInvokes(listOf(it.descriptor)).single() val synthesizedInvoke = createSynthesizedInvokes(listOf(it.descriptor)).single()
@@ -66,7 +66,7 @@ class NewResolveOldInference(
val explicitReceiver = context.call.explicitReceiver.check { it.exists() } val explicitReceiver = context.call.explicitReceiver.check { it.exists() }
val dynamicScope = dynamicCallableDescriptors.createDynamicDescriptorScope(context.call, context.scope.ownerDescriptor) 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) val baseContext = Context(scopeTower, name, context, tracing)
@@ -41,7 +41,7 @@ interface ScopeTower {
val dataFlowInfo: DataFlowDecorator val dataFlowInfo: DataFlowDecorator
// The closest (the most local) levels goes first // The closest (the most local) levels goes first
val levels: Sequence<ScopeTowerLevel> val levels: List<ScopeTowerLevel>
} }
interface DataFlowDecorator { interface DataFlowDecorator {
@@ -54,9 +54,9 @@ interface DataFlowDecorator {
} }
interface ScopeTowerLevel { 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> { interface CandidateWithBoundDispatchReceiver<out D : CallableDescriptor> {
@@ -17,7 +17,6 @@
package org.jetbrains.kotlin.resolve.calls.tower package org.jetbrains.kotlin.resolve.calls.tower
import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor
import org.jetbrains.kotlin.incremental.components.LookupLocation import org.jetbrains.kotlin.incremental.components.LookupLocation
import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue 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.ImportingScope
import org.jetbrains.kotlin.resolve.scopes.LexicalScope import org.jetbrains.kotlin.resolve.scopes.LexicalScope
import org.jetbrains.kotlin.resolve.scopes.MemberScope 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.receivers.ReceiverValue
import org.jetbrains.kotlin.resolve.scopes.utils.getImplicitReceiversHierarchy import org.jetbrains.kotlin.resolve.scopes.utils.getImplicitReceiversHierarchy
import org.jetbrains.kotlin.resolve.scopes.utils.parentsWithSelf import org.jetbrains.kotlin.resolve.scopes.utils.parentsWithSelf
@@ -45,7 +42,6 @@ internal class CandidateWithBoundDispatchReceiverImpl<D : CallableDescriptor>(
internal class ScopeTowerImpl( internal class ScopeTowerImpl(
resolutionContext: ResolutionContext<*>, resolutionContext: ResolutionContext<*>,
override val dynamicScope: MemberScope, override val dynamicScope: MemberScope,
private val explicitReceiver: Receiver?,
override val location: LookupLocation override val location: LookupLocation
): ScopeTower { ): ScopeTower {
override val dataFlowInfo: DataFlowDecorator = DataFlowDecoratorImpl(resolutionContext) override val dataFlowInfo: DataFlowDecorator = DataFlowDecoratorImpl(resolutionContext)
@@ -54,62 +50,25 @@ internal class ScopeTowerImpl(
override val implicitReceivers = resolutionContext.scope.getImplicitReceiversHierarchy(). override val implicitReceivers = resolutionContext.scope.getImplicitReceiversHierarchy().
mapNotNull { it.value.check { !it.type.containsError() } } 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 fun createLevels(): List<ScopeTowerLevel> {
private val receiversForSyntheticExtensions: Collection<KotlinType> by lazy(LazyThreadSafetyMode.PUBLICATION) { val result = ArrayList<ScopeTowerLevel>()
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>()
// locals win // locals win
lexicalScope.parentsWithSelf. lexicalScope.parentsWithSelf.
filterIsInstance<LexicalScope>(). filterIsInstance<LexicalScope>().
filter { it.kind.withLocalDescriptors }. filter { it.kind.withLocalDescriptors }.
mapTo(result) { LevelFactory.Scope(it) } mapTo(result) { ScopeBasedTowerLevel(this, it) }
lexicalScope.parentsWithSelf.forEach { scope -> lexicalScope.parentsWithSelf.forEach { scope ->
if (scope is LexicalScope) { 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 { 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>( internal class ExplicitReceiverScopeTowerProcessor<C>(
context: TowerContext<C>, context: TowerContext<C>,
val explicitReceiver: ReceiverValue, val explicitReceiver: ReceiverValue,
val collectCandidates: ScopeTowerLevel.(Name) -> Collection<CandidateWithBoundDispatchReceiver<*>> val collectCandidates: ScopeTowerLevel.(name: Name, extensionReceiver: ReceiverValue?) -> Collection<CandidateWithBoundDispatchReceiver<*>>
): AbstractSimpleScopeTowerProcessor<C>(context) { ): AbstractSimpleScopeTowerProcessor<C>(context) {
override fun simpleProcess(data: TowerData): Collection<C> { override fun simpleProcess(data: TowerData): Collection<C> {
return when (data) { return when (data) {
@@ -63,12 +63,12 @@ internal class ExplicitReceiverScopeTowerProcessor<C>(
private fun resolveAsMember(): Collection<C> { private fun resolveAsMember(): Collection<C> {
val members = ReceiverScopeTowerLevel(context.scopeTower, explicitReceiver) 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) } return members.map { context.createCandidate(it, ExplicitReceiverKind.DISPATCH_RECEIVER, extensionReceiver = null) }
} }
private fun resolveAsExtension(level: ScopeTowerLevel): Collection<C> { 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) } return extensions.map { context.createCandidate(it, ExplicitReceiverKind.EXTENSION_RECEIVER, extensionReceiver = explicitReceiver) }
} }
} }
@@ -76,12 +76,12 @@ internal class ExplicitReceiverScopeTowerProcessor<C>(
private class QualifierScopeTowerProcessor<C>( private class QualifierScopeTowerProcessor<C>(
context: TowerContext<C>, context: TowerContext<C>,
val qualifier: QualifierReceiver, val qualifier: QualifierReceiver,
val collectCandidates: ScopeTowerLevel.(Name) -> Collection<CandidateWithBoundDispatchReceiver<*>> val collectCandidates: ScopeTowerLevel.(name: Name, extensionReceiver: ReceiverValue?) -> Collection<CandidateWithBoundDispatchReceiver<*>>
): AbstractSimpleScopeTowerProcessor<C>(context) { ): AbstractSimpleScopeTowerProcessor<C>(context) {
override fun simpleProcess(data: TowerData): Collection<C> { override fun simpleProcess(data: TowerData): Collection<C> {
if (data != TowerData.Empty) return emptyList() 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 } .filter { !it.requiresExtensionReceiver }
.map { context.createCandidate(it, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, extensionReceiver = null) } .map { context.createCandidate(it, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, extensionReceiver = null) }
return staticMembers return staticMembers
@@ -90,17 +90,17 @@ private class QualifierScopeTowerProcessor<C>(
private class NoExplicitReceiverScopeTowerProcessor<C>( private class NoExplicitReceiverScopeTowerProcessor<C>(
context: TowerContext<C>, context: TowerContext<C>,
val collectCandidates: ScopeTowerLevel.(Name) -> Collection<CandidateWithBoundDispatchReceiver<*>> val collectCandidates: ScopeTowerLevel.(name: Name, extensionReceiver: ReceiverValue?) -> Collection<CandidateWithBoundDispatchReceiver<*>>
) : AbstractSimpleScopeTowerProcessor<C>(context) { ) : AbstractSimpleScopeTowerProcessor<C>(context) {
override fun simpleProcess(data: TowerData): Collection<C> override fun simpleProcess(data: TowerData): Collection<C>
= when(data) { = when(data) {
is TowerData.TowerLevel -> { 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) context.createCandidate(it, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, extensionReceiver = null)
} }
} }
is TowerData.BothTowerLevelAndImplicitReceiver -> { 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) context.createCandidate(it, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, extensionReceiver = data.implicitReceiver)
} }
} }
@@ -111,7 +111,7 @@ private class NoExplicitReceiverScopeTowerProcessor<C>(
private fun <C> createSimpleProcessor( private fun <C> createSimpleProcessor(
context: TowerContext<C>, context: TowerContext<C>,
explicitReceiver: Receiver?, explicitReceiver: Receiver?,
collectCandidates: ScopeTowerLevel.(Name) -> Collection<CandidateWithBoundDispatchReceiver<*>> collectCandidates: ScopeTowerLevel.(name: Name, extensionReceiver: ReceiverValue?) -> Collection<CandidateWithBoundDispatchReceiver<*>>
) : ScopeTowerProcessor<C> { ) : ScopeTowerProcessor<C> {
if (explicitReceiver is ReceiverValue) { if (explicitReceiver is ReceiverValue) {
return ExplicitReceiverScopeTowerProcessor(context, explicitReceiver, collectCandidates) return ExplicitReceiverScopeTowerProcessor(context, explicitReceiver, collectCandidates)
@@ -98,11 +98,11 @@ internal class ReceiverScopeTowerLevel(
return result 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) } 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 { return collectMembers {
getContributedFunctions(name, location) + it.getInnerConstructors(name, location) getContributedFunctions(name, location) + it.getInnerConstructors(name, location)
} }
@@ -110,12 +110,12 @@ internal class ReceiverScopeTowerLevel(
} }
internal class QualifierScopeTowerLevel(scopeTower: ScopeTower, val qualifier: QualifierReceiver) : AbstractScopeTowerLevel(scopeTower) { 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 { .getContributedVariablesAndObjects(name, location).map {
createCandidateDescriptor(it, dispatchReceiver = null) createCandidateDescriptor(it, dispatchReceiver = null)
} }
override fun getFunctions(name: Name) = qualifier.getNestedClassesAndPackageMembersScope() override fun getFunctions(name: Name, extensionReceiver: ReceiverValue?) = qualifier.getNestedClassesAndPackageMembersScope()
.getContributedFunctionsAndConstructors(name, location).map { .getContributedFunctionsAndConstructors(name, location).map {
createCandidateDescriptor(it, dispatchReceiver = null) 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) 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 { = resolutionScope.getContributedVariablesAndObjects(name, location).map {
createCandidateDescriptor(it, dispatchReceiver = null) 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 { = resolutionScope.getContributedFunctionsAndConstructors(name, location).map {
createCandidateDescriptor(it, dispatchReceiver = null) createCandidateDescriptor(it, dispatchReceiver = null)
} }
@@ -142,22 +142,27 @@ internal open class ScopeBasedTowerLevel protected constructor(
internal class ImportingScopeBasedTowerLevel( internal class ImportingScopeBasedTowerLevel(
scopeTower: ScopeTower, scopeTower: ScopeTower,
private val importingScope: ImportingScope, private val importingScope: ImportingScope
private val receiversForSyntheticExtensions: Collection<KotlinType>
): ScopeBasedTowerLevel(scopeTower, importingScope) { ): ScopeBasedTowerLevel(scopeTower, importingScope) {
override fun getVariables(name: Name): Collection<CandidateWithBoundDispatchReceiver<VariableDescriptor>> { override fun getVariables(name: Name, extensionReceiver: ReceiverValue?): Collection<CandidateWithBoundDispatchReceiver<VariableDescriptor>> {
val synthetic = importingScope.getContributedSyntheticExtensionProperties(receiversForSyntheticExtensions, name, location).map { 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) createCandidateDescriptor(it, dispatchReceiver = null)
} }
return super.getVariables(name) + synthetic return super.getVariables(name, null) + synthetic
} }
override fun getFunctions(name: Name): Collection<CandidateWithBoundDispatchReceiver<FunctionDescriptor>> { override fun getFunctions(name: Name, extensionReceiver: ReceiverValue?): Collection<CandidateWithBoundDispatchReceiver<FunctionDescriptor>> {
val synthetic = importingScope.getContributedSyntheticExtensionFunctions(receiversForSyntheticExtensions, name, location).map { 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) createCandidateDescriptor(it, dispatchReceiver = null)
} }
return super.getFunctions(name) + synthetic return super.getFunctions(name, null) + synthetic
} }
} }