Refactoring: replace ReceiverValue to ReceiverValueWithSmartCastInfo, Receiver to DetailedReceiver

This commit is contained in:
Stanislav Erokhin
2016-08-26 13:57:51 +03:00
parent d4a2cad35c
commit 0c60cda22a
8 changed files with 133 additions and 133 deletions
@@ -46,11 +46,13 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.*
import org.jetbrains.kotlin.resolve.scopes.utils.getImplicitReceiversHierarchy import org.jetbrains.kotlin.resolve.scopes.utils.getImplicitReceiversHierarchy
import org.jetbrains.kotlin.types.DeferredType import org.jetbrains.kotlin.types.DeferredType
import org.jetbrains.kotlin.types.ErrorUtils import org.jetbrains.kotlin.types.ErrorUtils
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.isDynamic import org.jetbrains.kotlin.types.isDynamic
import org.jetbrains.kotlin.types.typeUtil.containsError import org.jetbrains.kotlin.types.typeUtil.containsError
import org.jetbrains.kotlin.util.OperatorNameConventions import org.jetbrains.kotlin.util.OperatorNameConventions
import org.jetbrains.kotlin.utils.addToStdlib.check import org.jetbrains.kotlin.utils.addToStdlib.check
import org.jetbrains.kotlin.utils.sure import org.jetbrains.kotlin.utils.sure
import java.util.*
class NewResolutionOldInference( class NewResolutionOldInference(
private val candidateResolver: CandidateResolver, private val candidateResolver: CandidateResolver,
@@ -66,14 +68,14 @@ class NewResolutionOldInference(
name: Name, name: Name,
tracing: TracingStrategy, tracing: TracingStrategy,
scopeTower: ScopeTower, scopeTower: ScopeTower,
explicitReceiver: Receiver?, explicitReceiver: DetailedReceiver?,
context: BasicCallResolutionContext context: BasicCallResolutionContext
): ScopeTowerProcessor<MyCandidate<D>> ): ScopeTowerProcessor<MyCandidate<D>>
object Function : ResolutionKind<FunctionDescriptor>() { object Function : ResolutionKind<FunctionDescriptor>() {
override fun createTowerProcessor( override fun createTowerProcessor(
outer: NewResolutionOldInference, name: Name, tracing: TracingStrategy, outer: NewResolutionOldInference, name: Name, tracing: TracingStrategy,
scopeTower: ScopeTower, explicitReceiver: Receiver?, context: BasicCallResolutionContext scopeTower: ScopeTower, explicitReceiver: DetailedReceiver?, context: BasicCallResolutionContext
): ScopeTowerProcessor<MyCandidate<FunctionDescriptor>> { ): ScopeTowerProcessor<MyCandidate<FunctionDescriptor>> {
val functionContext = outer.SimpleContext<FunctionDescriptor>(scopeTower, name, context, tracing) val functionContext = outer.SimpleContext<FunctionDescriptor>(scopeTower, name, context, tracing)
return createFunctionProcessor(functionContext, outer.InvokeContext(functionContext), explicitReceiver) return createFunctionProcessor(functionContext, outer.InvokeContext(functionContext), explicitReceiver)
@@ -83,7 +85,7 @@ class NewResolutionOldInference(
object Variable : ResolutionKind<VariableDescriptor>() { object Variable : ResolutionKind<VariableDescriptor>() {
override fun createTowerProcessor( override fun createTowerProcessor(
outer: NewResolutionOldInference, name: Name, tracing: TracingStrategy, outer: NewResolutionOldInference, name: Name, tracing: TracingStrategy,
scopeTower: ScopeTower, explicitReceiver: Receiver?, context: BasicCallResolutionContext scopeTower: ScopeTower, explicitReceiver: DetailedReceiver?, context: BasicCallResolutionContext
): ScopeTowerProcessor<MyCandidate<VariableDescriptor>> { ): ScopeTowerProcessor<MyCandidate<VariableDescriptor>> {
val simpleContext = outer.SimpleContext<VariableDescriptor>(scopeTower, name, context, tracing) val simpleContext = outer.SimpleContext<VariableDescriptor>(scopeTower, name, context, tracing)
return createVariableAndObjectProcessor(simpleContext, explicitReceiver) return createVariableAndObjectProcessor(simpleContext, explicitReceiver)
@@ -93,7 +95,7 @@ class NewResolutionOldInference(
object CallableReference : ResolutionKind<CallableDescriptor>() { object CallableReference : ResolutionKind<CallableDescriptor>() {
override fun createTowerProcessor( override fun createTowerProcessor(
outer: NewResolutionOldInference, name: Name, tracing: TracingStrategy, outer: NewResolutionOldInference, name: Name, tracing: TracingStrategy,
scopeTower: ScopeTower, explicitReceiver: Receiver?, context: BasicCallResolutionContext scopeTower: ScopeTower, explicitReceiver: DetailedReceiver?, context: BasicCallResolutionContext
): ScopeTowerProcessor<MyCandidate<CallableDescriptor>> { ): ScopeTowerProcessor<MyCandidate<CallableDescriptor>> {
val simpleContextF = outer.SimpleContext<FunctionDescriptor>(scopeTower, name, context, tracing) val simpleContextF = outer.SimpleContext<FunctionDescriptor>(scopeTower, name, context, tracing)
val simpleContextV = outer.SimpleContext<VariableDescriptor>(scopeTower, name, context, tracing) val simpleContextV = outer.SimpleContext<VariableDescriptor>(scopeTower, name, context, tracing)
@@ -107,7 +109,7 @@ class NewResolutionOldInference(
object Invoke : ResolutionKind<FunctionDescriptor>() { object Invoke : ResolutionKind<FunctionDescriptor>() {
override fun createTowerProcessor( override fun createTowerProcessor(
outer: NewResolutionOldInference, name: Name, tracing: TracingStrategy, outer: NewResolutionOldInference, name: Name, tracing: TracingStrategy,
scopeTower: ScopeTower, explicitReceiver: Receiver?, context: BasicCallResolutionContext scopeTower: ScopeTower, explicitReceiver: DetailedReceiver?, context: BasicCallResolutionContext
): ScopeTowerProcessor<MyCandidate<FunctionDescriptor>> { ): ScopeTowerProcessor<MyCandidate<FunctionDescriptor>> {
val functionContext = outer.SimpleContext<FunctionDescriptor>(scopeTower, name, context, tracing) val functionContext = outer.SimpleContext<FunctionDescriptor>(scopeTower, name, context, tracing)
// todo // todo
@@ -115,7 +117,7 @@ class NewResolutionOldInference(
"Call should be CallForImplicitInvoke, but it is: ${context.call}" "Call should be CallForImplicitInvoke, but it is: ${context.call}"
} }
return createProcessorWithReceiverValueOrEmpty(explicitReceiver) { return createProcessorWithReceiverValueOrEmpty(explicitReceiver) {
createCallTowerProcessorForExplicitInvoke(functionContext, call.dispatchReceiver, it) createCallTowerProcessorForExplicitInvoke(functionContext, context.transformToReceiverWithSmartCastInfo(call.dispatchReceiver), it)
} }
} }
@@ -124,7 +126,7 @@ class NewResolutionOldInference(
class GivenCandidates<D : CallableDescriptor> : ResolutionKind<D>() { class GivenCandidates<D : CallableDescriptor> : ResolutionKind<D>() {
override fun createTowerProcessor( override fun createTowerProcessor(
outer: NewResolutionOldInference, name: Name, tracing: TracingStrategy, outer: NewResolutionOldInference, name: Name, tracing: TracingStrategy,
scopeTower: ScopeTower, explicitReceiver: Receiver?, context: BasicCallResolutionContext scopeTower: ScopeTower, explicitReceiver: DetailedReceiver?, context: BasicCallResolutionContext
): ScopeTowerProcessor<MyCandidate<D>> { ): ScopeTowerProcessor<MyCandidate<D>> {
throw IllegalStateException("Should be not called") throw IllegalStateException("Should be not called")
} }
@@ -138,11 +140,17 @@ class NewResolutionOldInference(
tracing: TracingStrategy tracing: TracingStrategy
): OverloadResolutionResultsImpl<D> { ): OverloadResolutionResultsImpl<D> {
val explicitReceiver = context.call.explicitReceiver val explicitReceiver = context.call.explicitReceiver
val detailedReceiver = if (explicitReceiver is QualifierReceiver?) {
explicitReceiver
}
else {
context.transformToReceiverWithSmartCastInfo(explicitReceiver as ReceiverValue)
}
val dynamicScope = dynamicCallableDescriptors.createDynamicDescriptorScope(context.call, context.scope.ownerDescriptor) val dynamicScope = dynamicCallableDescriptors.createDynamicDescriptorScope(context.call, context.scope.ownerDescriptor)
val scopeTower = ScopeTowerImpl(context, dynamicScope, syntheticScopes, context.call.createLookupLocation()) val scopeTower = ScopeTowerImpl(context, dynamicScope, syntheticScopes, context.call.createLookupLocation())
val processor = kind.createTowerProcessor(this, name, tracing, scopeTower, explicitReceiver, context) val processor = kind.createTowerProcessor(this, name, tracing, scopeTower, detailedReceiver, context)
if (context.collectAllCandidates) { if (context.collectAllCandidates) {
return allCandidatesResult(towerResolver.collectAllCandidates(scopeTower, processor)) return allCandidatesResult(towerResolver.collectAllCandidates(scopeTower, processor))
@@ -240,18 +248,15 @@ class NewResolutionOldInference(
override val syntheticScopes: SyntheticScopes, override val syntheticScopes: SyntheticScopes,
override val location: LookupLocation override val location: LookupLocation
): ScopeTower { ): ScopeTower {
override val dataFlowInfo: DataFlowDecorator = object : DataFlowDecorator() { private val cache = HashMap<ReceiverValue, ReceiverValueWithSmartCastInfo>()
override fun calculateSmartCastInfo(receiver: ReceiverValue): SmartCastInfo {
val dataFlowValue = DataFlowValueFactory.createDataFlowValue(receiver, resolutionContext) override fun getImplicitReceiver(scope: LexicalScope): ReceiverValueWithSmartCastInfo? =
return SmartCastInfo(dataFlowValue.isStable, resolutionContext.dataFlowInfo.getCollectedTypes(dataFlowValue)) scope.implicitReceiver?.value?.let {
} cache.getOrPut(it) { resolutionContext.transformToReceiverWithSmartCastInfo(it) }
} }
override val lexicalScope: LexicalScope get() = resolutionContext.scope override val lexicalScope: LexicalScope get() = resolutionContext.scope
override val implicitReceivers = resolutionContext.scope.getImplicitReceiversHierarchy().
mapNotNull { it.value.check { !it.type.containsError() } }
override val isDebuggerContext: Boolean get() = resolutionContext.isDebuggerContext override val isDebuggerContext: Boolean get() = resolutionContext.isDebuggerContext
} }
@@ -277,18 +282,19 @@ class NewResolutionOldInference(
override fun createCandidate( override fun createCandidate(
towerCandidate: CandidateWithBoundDispatchReceiver<D>, towerCandidate: CandidateWithBoundDispatchReceiver<D>,
explicitReceiverKind: ExplicitReceiverKind, explicitReceiverKind: ExplicitReceiverKind,
extensionReceiver: ReceiverValue? extensionReceiver: ReceiverValueWithSmartCastInfo?
): MyCandidate<D> { ): MyCandidate<D> {
val candidateTrace = TemporaryBindingTrace.create(basicCallContext.trace, "Context for resolve candidate") val candidateTrace = TemporaryBindingTrace.create(basicCallContext.trace, "Context for resolve candidate")
val candidateCall = ResolvedCallImpl( val candidateCall = ResolvedCallImpl(
basicCallContext.call, towerCandidate.descriptor, basicCallContext.call, towerCandidate.descriptor,
towerCandidate.dispatchReceiver, extensionReceiver, towerCandidate.dispatchReceiver?.receiverValue, extensionReceiver?.receiverValue,
explicitReceiverKind, null, candidateTrace, tracing, explicitReceiverKind, null, candidateTrace, tracing,
basicCallContext.dataFlowInfoForArguments // todo may be we should create new mutable info for arguments basicCallContext.dataFlowInfoForArguments // todo may be we should create new mutable info for arguments
) )
// see spec-docs/dynamic-types.md // see spec-docs/dynamic-types.md
if (extensionReceiver != null && extensionReceiver.type.isDynamic() if (extensionReceiver != null && extensionReceiver.receiverValue.type.isDynamic()
&& !towerCandidate.descriptor.extensionReceiverParameter!!.value.type.isDynamic()) { && !towerCandidate.descriptor.extensionReceiverParameter!!.value.type.isDynamic()) {
return MyCandidate(ResolutionCandidateStatus(listOf(ExtensionWithStaticTypeWithDynamicReceiver)), candidateCall) return MyCandidate(ResolutionCandidateStatus(listOf(ExtensionWithStaticTypeWithDynamicReceiver)), candidateCall)
} }
@@ -351,7 +357,7 @@ class NewResolutionOldInference(
override fun contextForInvoke( override fun contextForInvoke(
variable: MyCandidate<VariableDescriptor>, variable: MyCandidate<VariableDescriptor>,
useExplicitReceiver: Boolean useExplicitReceiver: Boolean
): Pair<ReceiverValue, TowerContext<FunctionDescriptor, MyCandidate<FunctionDescriptor>>>? { ): Pair<ReceiverValueWithSmartCastInfo, TowerContext<FunctionDescriptor, MyCandidate<FunctionDescriptor>>>? {
assert(variable.resolvedCall.status.possibleTransformToSuccess()) { assert(variable.resolvedCall.status.possibleTransformToSuccess()) {
"Incorrect status: ${variable.resolvedCall.status} for variable call: ${variable.resolvedCall} " + "Incorrect status: ${variable.resolvedCall.status} for variable call: ${variable.resolvedCall} " +
"and descriptor: ${variable.resolvedCall.candidateDescriptor}" "and descriptor: ${variable.resolvedCall.candidateDescriptor}"
@@ -381,17 +387,20 @@ class NewResolutionOldInference(
.replaceCall(functionCall) .replaceCall(functionCall)
.replaceContextDependency(ContextDependency.DEPENDENT) // todo .replaceContextDependency(ContextDependency.DEPENDENT) // todo
val scopeTower = functionContext.scopeTower val newContext = SimpleContext<FunctionDescriptor>(functionContext.scopeTower, OperatorNameConventions.INVOKE, basicCallResolutionContext, tracingForInvoke)
val newScopeTower = ScopeTowerImpl(basicCallResolutionContext, scopeTower.dynamicScope, scopeTower.syntheticScopes, scopeTower.location)
val newContext = SimpleContext<FunctionDescriptor>(newScopeTower, OperatorNameConventions.INVOKE, basicCallResolutionContext, tracingForInvoke)
return variableReceiver to newContext return basicCallResolutionContext.transformToReceiverWithSmartCastInfo(variableReceiver) to newContext
} }
} }
} }
private fun ResolutionContext<*>.transformToReceiverWithSmartCastInfo(receiver: ReceiverValue): ReceiverValueWithSmartCastInfo {
val dataFlowValue = DataFlowValueFactory.createDataFlowValue(receiver, this)
return ReceiverValueWithSmartCastInfo(receiver, dataFlowInfo.getCollectedTypes(dataFlowValue), dataFlowValue.isStable)
}
@Deprecated("Temporary error") @Deprecated("Temporary error")
internal class PreviousResolutionError(candidateLevel: ResolutionCandidateApplicability): ResolutionDiagnostic(candidateLevel) internal class PreviousResolutionError(candidateLevel: ResolutionCandidateApplicability): ResolutionDiagnostic(candidateLevel)
@@ -21,8 +21,8 @@ import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.VariableDescriptor import org.jetbrains.kotlin.descriptors.VariableDescriptor
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
import org.jetbrains.kotlin.resolve.calls.tasks.createSynthesizedInvokes import org.jetbrains.kotlin.resolve.calls.tasks.createSynthesizedInvokes
import org.jetbrains.kotlin.resolve.scopes.receivers.Receiver import org.jetbrains.kotlin.resolve.scopes.receivers.DetailedReceiver
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValueWithSmartCastInfo
import org.jetbrains.kotlin.util.OperatorNameConventions import org.jetbrains.kotlin.util.OperatorNameConventions
import java.util.* import java.util.*
@@ -87,7 +87,7 @@ abstract class AbstractInvokeTowerProcessor<F : Candidate<FunctionDescriptor>, V
// todo KT-9522 Allow invoke convention for synthetic property // todo KT-9522 Allow invoke convention for synthetic property
class InvokeTowerProcessor<F : Candidate<FunctionDescriptor>, V : Candidate<VariableDescriptor>>( class InvokeTowerProcessor<F : Candidate<FunctionDescriptor>, V : Candidate<VariableDescriptor>>(
invokeContext: InvokeTowerContext<F, V>, invokeContext: InvokeTowerContext<F, V>,
explicitReceiver: Receiver? explicitReceiver: DetailedReceiver?
) : AbstractInvokeTowerProcessor<F, V>( ) : AbstractInvokeTowerProcessor<F, V>(
invokeContext, invokeContext,
createVariableAndObjectProcessor(invokeContext.contextForVariable(stripExplicitReceiver = false), explicitReceiver) createVariableAndObjectProcessor(invokeContext.contextForVariable(stripExplicitReceiver = false), explicitReceiver)
@@ -103,7 +103,7 @@ class InvokeTowerProcessor<F : Candidate<FunctionDescriptor>, V : Candidate<Vari
class InvokeExtensionTowerProcessor<F : Candidate<FunctionDescriptor>, V : Candidate<VariableDescriptor>>( class InvokeExtensionTowerProcessor<F : Candidate<FunctionDescriptor>, V : Candidate<VariableDescriptor>>(
invokeContext: InvokeTowerContext<F, V>, invokeContext: InvokeTowerContext<F, V>,
private val explicitReceiver: ReceiverValue? private val explicitReceiver: ReceiverValueWithSmartCastInfo?
) : AbstractInvokeTowerProcessor<F, V>( ) : AbstractInvokeTowerProcessor<F, V>(
invokeContext, invokeContext,
createVariableAndObjectProcessor(invokeContext.contextForVariable(stripExplicitReceiver = true), explicitReceiver = null) createVariableAndObjectProcessor(invokeContext.contextForVariable(stripExplicitReceiver = true), explicitReceiver = null)
@@ -121,7 +121,7 @@ class InvokeExtensionTowerProcessor<F : Candidate<FunctionDescriptor>, V : Candi
private class InvokeExtensionScopeTowerProcessor<C : Candidate<FunctionDescriptor>>( private class InvokeExtensionScopeTowerProcessor<C : Candidate<FunctionDescriptor>>(
context: TowerContext<FunctionDescriptor, C>, context: TowerContext<FunctionDescriptor, C>,
private val invokeCandidateDescriptor: CandidateWithBoundDispatchReceiver<FunctionDescriptor>, private val invokeCandidateDescriptor: CandidateWithBoundDispatchReceiver<FunctionDescriptor>,
private val explicitReceiver: ReceiverValue? private val explicitReceiver: ReceiverValueWithSmartCastInfo?
) : AbstractSimpleScopeTowerProcessor<FunctionDescriptor, C>(context) { ) : AbstractSimpleScopeTowerProcessor<FunctionDescriptor, C>(context) {
override fun simpleProcess(data: TowerData): Collection<C> { override fun simpleProcess(data: TowerData): Collection<C> {
@@ -139,11 +139,12 @@ private class InvokeExtensionScopeTowerProcessor<C : Candidate<FunctionDescripto
// todo debug info // todo debug info
private fun ScopeTower.getExtensionInvokeCandidateDescriptor( private fun ScopeTower.getExtensionInvokeCandidateDescriptor(
extensionFunctionReceiver: ReceiverValue extensionFunctionReceiver: ReceiverValueWithSmartCastInfo
): CandidateWithBoundDispatchReceiver<FunctionDescriptor>? { ): CandidateWithBoundDispatchReceiver<FunctionDescriptor>? {
if (!extensionFunctionReceiver.type.isExtensionFunctionType) return null val type = extensionFunctionReceiver.receiverValue.type
if (!type.isExtensionFunctionType) return null // todo: missing smart cast?
val invokeDescriptor = extensionFunctionReceiver.type.memberScope.getContributedFunctions(OperatorNameConventions.INVOKE, location).single() val invokeDescriptor = type.memberScope.getContributedFunctions(OperatorNameConventions.INVOKE, location).single()
val synthesizedInvoke = createSynthesizedInvokes(listOf(invokeDescriptor)).single() val synthesizedInvoke = createSynthesizedInvokes(listOf(invokeDescriptor)).single()
// here we don't add SynthesizedDescriptor diagnostic because it should has priority as member // here we don't add SynthesizedDescriptor diagnostic because it should has priority as member
@@ -153,8 +154,8 @@ private fun ScopeTower.getExtensionInvokeCandidateDescriptor(
// case 1.(foo())() or (foo())() // case 1.(foo())() or (foo())()
fun <F : Candidate<FunctionDescriptor>> createCallTowerProcessorForExplicitInvoke( fun <F : Candidate<FunctionDescriptor>> createCallTowerProcessorForExplicitInvoke(
functionContext: TowerContext<FunctionDescriptor, F>, functionContext: TowerContext<FunctionDescriptor, F>,
expressionForInvoke: ReceiverValue, expressionForInvoke: ReceiverValueWithSmartCastInfo,
explicitReceiver: ReceiverValue? explicitReceiver: ReceiverValueWithSmartCastInfo?
): ScopeTowerProcessor<F> { ): ScopeTowerProcessor<F> {
val invokeExtensionDescriptor = functionContext.scopeTower.getExtensionInvokeCandidateDescriptor(expressionForInvoke) val invokeExtensionDescriptor = functionContext.scopeTower.getExtensionInvokeCandidateDescriptor(expressionForInvoke)
if (explicitReceiver != null) { if (explicitReceiver != null) {
@@ -22,52 +22,29 @@ import org.jetbrains.kotlin.name.Name
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.SyntheticScopes import org.jetbrains.kotlin.resolve.scopes.SyntheticScopes
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValueWithSmartCastInfo
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
import java.util.*
interface ScopeTower { interface ScopeTower {
/**
* Adds receivers to the list in order of locality, so that the closest (the most local) receiver goes first
* Doesn't include receivers with error types
*/
val implicitReceivers: List<ReceiverValue>
val lexicalScope: LexicalScope val lexicalScope: LexicalScope
fun getImplicitReceiver(scope: LexicalScope): ReceiverValueWithSmartCastInfo?
val dynamicScope: MemberScope val dynamicScope: MemberScope
val syntheticScopes: SyntheticScopes val syntheticScopes: SyntheticScopes
val location: LookupLocation val location: LookupLocation
val dataFlowInfo: DataFlowDecorator
val isDebuggerContext: Boolean val isDebuggerContext: Boolean
} }
abstract class DataFlowDecorator() {
private val cache = HashMap<ReceiverValue, SmartCastInfo>()
fun isStableReceiver(receiver: ReceiverValue): Boolean = getSmartCastInfo(receiver).isStable
// doesn't include receiver.type
fun getSmartCastTypes(receiver: ReceiverValue): Set<KotlinType> = getSmartCastInfo(receiver).possibleTypes
private fun getSmartCastInfo(receiver: ReceiverValue): SmartCastInfo
= cache.getOrPut(receiver) { calculateSmartCastInfo(receiver) }
protected data class SmartCastInfo(val isStable: Boolean, val possibleTypes: Set<KotlinType>)
protected abstract fun calculateSmartCastInfo(receiver: ReceiverValue): SmartCastInfo
}
interface ScopeTowerLevel { interface ScopeTowerLevel {
fun getVariables(name: Name, extensionReceiver: ReceiverValue?): Collection<CandidateWithBoundDispatchReceiver<VariableDescriptor>> fun getVariables(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?): Collection<CandidateWithBoundDispatchReceiver<VariableDescriptor>>
fun getObjects(name: Name, extensionReceiver: ReceiverValue?): Collection<CandidateWithBoundDispatchReceiver<VariableDescriptor>> fun getObjects(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?): Collection<CandidateWithBoundDispatchReceiver<VariableDescriptor>>
fun getFunctions(name: Name, extensionReceiver: ReceiverValue?): Collection<CandidateWithBoundDispatchReceiver<FunctionDescriptor>> fun getFunctions(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?): Collection<CandidateWithBoundDispatchReceiver<FunctionDescriptor>>
} }
interface CandidateWithBoundDispatchReceiver<out D : CallableDescriptor> { interface CandidateWithBoundDispatchReceiver<out D : CallableDescriptor> {
@@ -75,7 +52,7 @@ interface CandidateWithBoundDispatchReceiver<out D : CallableDescriptor> {
val diagnostics: List<ResolutionDiagnostic> val diagnostics: List<ResolutionDiagnostic>
val dispatchReceiver: ReceiverValue? val dispatchReceiver: ReceiverValueWithSmartCastInfo?
fun copy(newDescriptor: @UnsafeVariance D): CandidateWithBoundDispatchReceiver<D> fun copy(newDescriptor: @UnsafeVariance D): CandidateWithBoundDispatchReceiver<D>
} }
@@ -23,9 +23,7 @@ import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
import org.jetbrains.kotlin.resolve.coroutine.CoroutineReceiverValue import org.jetbrains.kotlin.resolve.coroutine.CoroutineReceiverValue
import org.jetbrains.kotlin.resolve.coroutine.createCoroutineSuspensionFunctionView import org.jetbrains.kotlin.resolve.coroutine.createCoroutineSuspensionFunctionView
import org.jetbrains.kotlin.resolve.scopes.receivers.QualifierReceiver import org.jetbrains.kotlin.resolve.scopes.receivers.*
import org.jetbrains.kotlin.resolve.scopes.receivers.Receiver
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
import org.jetbrains.kotlin.utils.addToStdlib.check import org.jetbrains.kotlin.utils.addToStdlib.check
@@ -54,8 +52,8 @@ internal abstract class AbstractSimpleScopeTowerProcessor<D : CallableDescriptor
internal class ExplicitReceiverScopeTowerProcessor<D : CallableDescriptor, C: Candidate<D>>( internal class ExplicitReceiverScopeTowerProcessor<D : CallableDescriptor, C: Candidate<D>>(
context: TowerContext<D, C>, context: TowerContext<D, C>,
val explicitReceiver: ReceiverValue, val explicitReceiver: ReceiverValueWithSmartCastInfo,
val collectCandidates: ScopeTowerLevel.(name: Name, extensionReceiver: ReceiverValue?) -> Collection<CandidateWithBoundDispatchReceiver<D>> val collectCandidates: ScopeTowerLevel.(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?) -> Collection<CandidateWithBoundDispatchReceiver<D>>
): AbstractSimpleScopeTowerProcessor<D, C>(context) { ): AbstractSimpleScopeTowerProcessor<D, C>(context) {
override fun simpleProcess(data: TowerData): Collection<C> { override fun simpleProcess(data: TowerData): Collection<C> {
return when (data) { return when (data) {
@@ -80,7 +78,7 @@ internal class ExplicitReceiverScopeTowerProcessor<D : CallableDescriptor, C: Ca
private class QualifierScopeTowerProcessor<D : CallableDescriptor, C: Candidate<D>>( private class QualifierScopeTowerProcessor<D : CallableDescriptor, C: Candidate<D>>(
context: TowerContext<D, C>, context: TowerContext<D, C>,
val qualifier: QualifierReceiver, val qualifier: QualifierReceiver,
val collectCandidates: ScopeTowerLevel.(name: Name, extensionReceiver: ReceiverValue?) -> Collection<CandidateWithBoundDispatchReceiver<D>> val collectCandidates: ScopeTowerLevel.(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?) -> Collection<CandidateWithBoundDispatchReceiver<D>>
): AbstractSimpleScopeTowerProcessor<D, C>(context) { ): AbstractSimpleScopeTowerProcessor<D, 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()
@@ -94,7 +92,7 @@ private class QualifierScopeTowerProcessor<D : CallableDescriptor, C: Candidate<
private class NoExplicitReceiverScopeTowerProcessor<D : CallableDescriptor, C: Candidate<D>>( private class NoExplicitReceiverScopeTowerProcessor<D : CallableDescriptor, C: Candidate<D>>(
context: TowerContext<D, C>, context: TowerContext<D, C>,
val collectCandidates: ScopeTowerLevel.(name: Name, extensionReceiver: ReceiverValue?) -> Collection<CandidateWithBoundDispatchReceiver<D>> val collectCandidates: ScopeTowerLevel.(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?) -> Collection<CandidateWithBoundDispatchReceiver<D>>
) : AbstractSimpleScopeTowerProcessor<D, C>(context) { ) : AbstractSimpleScopeTowerProcessor<D, C>(context) {
override fun simpleProcess(data: TowerData): Collection<C> override fun simpleProcess(data: TowerData): Collection<C>
= when(data) { = when(data) {
@@ -111,7 +109,7 @@ private class NoExplicitReceiverScopeTowerProcessor<D : CallableDescriptor, C: C
context.createCandidate( context.createCandidate(
it, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, extensionReceiver = data.implicitReceiver)) it, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, extensionReceiver = data.implicitReceiver))
if (data.implicitReceiver is CoroutineReceiverValue) { if (data.implicitReceiver.receiverValue is CoroutineReceiverValue) {
val newDescriptor = it.descriptor.createCoroutineSuspensionFunctionView() ?: return@forEach val newDescriptor = it.descriptor.createCoroutineSuspensionFunctionView() ?: return@forEach
result.add( result.add(
context.createCandidate( context.createCandidate(
@@ -128,11 +126,11 @@ private class NoExplicitReceiverScopeTowerProcessor<D : CallableDescriptor, C: C
private fun <D : CallableDescriptor, C: Candidate<D>> createSimpleProcessor( private fun <D : CallableDescriptor, C: Candidate<D>> createSimpleProcessor(
context: TowerContext<D, C>, context: TowerContext<D, C>,
explicitReceiver: Receiver?, explicitReceiver: DetailedReceiver?,
classValueReceiver: Boolean, classValueReceiver: Boolean,
collectCandidates: ScopeTowerLevel.(name: Name, extensionReceiver: ReceiverValue?) -> Collection<CandidateWithBoundDispatchReceiver<D>> collectCandidates: ScopeTowerLevel.(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?) -> Collection<CandidateWithBoundDispatchReceiver<D>>
) : ScopeTowerProcessor<C> { ) : ScopeTowerProcessor<C> {
if (explicitReceiver is ReceiverValue) { if (explicitReceiver is ReceiverValueWithSmartCastInfo) {
return ExplicitReceiverScopeTowerProcessor(context, explicitReceiver, collectCandidates) return ExplicitReceiverScopeTowerProcessor(context, explicitReceiver, collectCandidates)
} }
else if (explicitReceiver is QualifierReceiver) { else if (explicitReceiver is QualifierReceiver) {
@@ -140,7 +138,7 @@ private fun <D : CallableDescriptor, C: Candidate<D>> createSimpleProcessor(
if (!classValueReceiver) return qualifierProcessor if (!classValueReceiver) return qualifierProcessor
// todo enum entry, object. // todo enum entry, object.
val classValue = explicitReceiver.classValueReceiver ?: return qualifierProcessor val classValue = explicitReceiver.classValueReceiverWithSmartCastInfo ?: return qualifierProcessor
return CompositeScopeTowerProcessor( return CompositeScopeTowerProcessor(
qualifierProcessor, qualifierProcessor,
ExplicitReceiverScopeTowerProcessor(context, classValue, collectCandidates) ExplicitReceiverScopeTowerProcessor(context, classValue, collectCandidates)
@@ -155,25 +153,25 @@ private fun <D : CallableDescriptor, C: Candidate<D>> createSimpleProcessor(
} }
fun <C : Candidate<VariableDescriptor>> createVariableProcessor( fun <C : Candidate<VariableDescriptor>> createVariableProcessor(
context: TowerContext<VariableDescriptor, C>, explicitReceiver: Receiver?, classValueReceiver: Boolean = true context: TowerContext<VariableDescriptor, C>, explicitReceiver: DetailedReceiver?, classValueReceiver: Boolean = true
) = createSimpleProcessor(context, explicitReceiver, classValueReceiver, ScopeTowerLevel::getVariables) ) = createSimpleProcessor(context, explicitReceiver, classValueReceiver, ScopeTowerLevel::getVariables)
fun <C : Candidate<VariableDescriptor>> createVariableAndObjectProcessor( fun <C : Candidate<VariableDescriptor>> createVariableAndObjectProcessor(
context: TowerContext<VariableDescriptor, C>, explicitReceiver: Receiver?, classValueReceiver: Boolean = true context: TowerContext<VariableDescriptor, C>, explicitReceiver: DetailedReceiver?, classValueReceiver: Boolean = true
) = CompositeScopeTowerProcessor( ) = CompositeScopeTowerProcessor(
createVariableProcessor(context, explicitReceiver), createVariableProcessor(context, explicitReceiver),
createSimpleProcessor(context, explicitReceiver, classValueReceiver, ScopeTowerLevel::getObjects) createSimpleProcessor(context, explicitReceiver, classValueReceiver, ScopeTowerLevel::getObjects)
) )
fun <C : Candidate<FunctionDescriptor>> createSimpleFunctionProcessor( fun <C : Candidate<FunctionDescriptor>> createSimpleFunctionProcessor(
context: TowerContext<FunctionDescriptor, C>, explicitReceiver: Receiver?, classValueReceiver: Boolean = true context: TowerContext<FunctionDescriptor, C>, explicitReceiver: DetailedReceiver?, classValueReceiver: Boolean = true
) = createSimpleProcessor(context, explicitReceiver, classValueReceiver, ScopeTowerLevel::getFunctions) ) = createSimpleProcessor(context, explicitReceiver, classValueReceiver, ScopeTowerLevel::getFunctions)
fun <F: Candidate<FunctionDescriptor>, V: Candidate<VariableDescriptor>> createFunctionProcessor( fun <F: Candidate<FunctionDescriptor>, V: Candidate<VariableDescriptor>> createFunctionProcessor(
simpleContext: TowerContext<FunctionDescriptor, F>, simpleContext: TowerContext<FunctionDescriptor, F>,
invokeContext: InvokeTowerContext<F, V>, invokeContext: InvokeTowerContext<F, V>,
explicitReceiver: Receiver? explicitReceiver: DetailedReceiver?
): CompositeScopeTowerProcessor<F> { ): CompositeScopeTowerProcessor<F> {
// a.foo() -- simple function call // a.foo() -- simple function call
@@ -190,14 +188,14 @@ fun <F: Candidate<FunctionDescriptor>, V: Candidate<VariableDescriptor>> createF
fun <D : CallableDescriptor, C: Candidate<D>> createProcessorWithReceiverValueOrEmpty( fun <D : CallableDescriptor, C: Candidate<D>> createProcessorWithReceiverValueOrEmpty(
explicitReceiver: Receiver?, explicitReceiver: DetailedReceiver?,
create: (ReceiverValue?) -> ScopeTowerProcessor<C> create: (ReceiverValueWithSmartCastInfo?) -> ScopeTowerProcessor<C>
): ScopeTowerProcessor<C> { ): ScopeTowerProcessor<C> {
return if (explicitReceiver is QualifierReceiver) { return if (explicitReceiver is QualifierReceiver) {
explicitReceiver.classValueReceiver?.let(create) explicitReceiver.classValueReceiverWithSmartCastInfo?.let(create)
?: KnownResultProcessor<C>(listOf()) ?: KnownResultProcessor<C>(listOf())
} }
else { else {
create(explicitReceiver as ReceiverValue?) create(explicitReceiver as ReceiverValueWithSmartCastInfo?)
} }
} }
@@ -29,10 +29,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.hasClassValueDescriptor
import org.jetbrains.kotlin.resolve.descriptorUtil.hasHidesMembersAnnotation import org.jetbrains.kotlin.resolve.descriptorUtil.hasHidesMembersAnnotation
import org.jetbrains.kotlin.resolve.descriptorUtil.hasLowPriorityInOverloadResolution import org.jetbrains.kotlin.resolve.descriptorUtil.hasLowPriorityInOverloadResolution
import org.jetbrains.kotlin.resolve.scopes.* import org.jetbrains.kotlin.resolve.scopes.*
import org.jetbrains.kotlin.resolve.scopes.receivers.CastImplicitClassReceiver import org.jetbrains.kotlin.resolve.scopes.receivers.*
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver
import org.jetbrains.kotlin.resolve.scopes.receivers.QualifierReceiver
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
import org.jetbrains.kotlin.resolve.scopes.utils.collectFunctions import org.jetbrains.kotlin.resolve.scopes.utils.collectFunctions
import org.jetbrains.kotlin.resolve.scopes.utils.collectVariables import org.jetbrains.kotlin.resolve.scopes.utils.collectVariables
import org.jetbrains.kotlin.resolve.selectMostSpecificInEachOverridableGroup import org.jetbrains.kotlin.resolve.selectMostSpecificInEachOverridableGroup
@@ -49,7 +46,7 @@ internal abstract class AbstractScopeTowerLevel(
protected fun <D : CallableDescriptor> createCandidateDescriptor( protected fun <D : CallableDescriptor> createCandidateDescriptor(
descriptor: D, descriptor: D,
dispatchReceiver: ReceiverValue?, dispatchReceiver: ReceiverValueWithSmartCastInfo?,
specialError: ResolutionDiagnostic? = null, specialError: ResolutionDiagnostic? = null,
dispatchReceiverSmartCastType: KotlinType? = null dispatchReceiverSmartCastType: KotlinType? = null
): CandidateWithBoundDispatchReceiver<D> { ): CandidateWithBoundDispatchReceiver<D> {
@@ -67,7 +64,7 @@ internal abstract class AbstractScopeTowerLevel(
val shouldSkipVisibilityCheck = scopeTower.isDebuggerContext val shouldSkipVisibilityCheck = scopeTower.isDebuggerContext
if (!shouldSkipVisibilityCheck) { if (!shouldSkipVisibilityCheck) {
Visibilities.findInvisibleMember( Visibilities.findInvisibleMember(
getReceiverValueWithSmartCast(dispatchReceiver, dispatchReceiverSmartCastType), getReceiverValueWithSmartCast(dispatchReceiver?.receiverValue, dispatchReceiverSmartCastType),
descriptor, descriptor,
scopeTower.lexicalScope.ownerDescriptor scopeTower.lexicalScope.ownerDescriptor
)?.let { diagnostics.add(VisibilityError(it)) } )?.let { diagnostics.add(VisibilityError(it)) }
@@ -82,28 +79,28 @@ internal abstract class AbstractScopeTowerLevel(
// todo add static methods & fields with error // todo add static methods & fields with error
internal class ReceiverScopeTowerLevel( internal class ReceiverScopeTowerLevel(
scopeTower: ScopeTower, scopeTower: ScopeTower,
val dispatchReceiver: ReceiverValue val dispatchReceiver: ReceiverValueWithSmartCastInfo
): AbstractScopeTowerLevel(scopeTower) { ): AbstractScopeTowerLevel(scopeTower) {
private fun <D : CallableDescriptor> collectMembers( private fun <D : CallableDescriptor> collectMembers(
getMembers: ResolutionScope.(KotlinType?) -> Collection<D> getMembers: ResolutionScope.(KotlinType?) -> Collection<D>
): Collection<CandidateWithBoundDispatchReceiver<D>> { ): Collection<CandidateWithBoundDispatchReceiver<D>> {
val result = ArrayList<CandidateWithBoundDispatchReceiver<D>>(0) val result = ArrayList<CandidateWithBoundDispatchReceiver<D>>(0)
dispatchReceiver.type.memberScope.getMembers(dispatchReceiver.type).mapTo(result) { val receiverValue = dispatchReceiver.receiverValue
receiverValue.type.memberScope.getMembers(receiverValue.type).mapTo(result) {
createCandidateDescriptor(it, dispatchReceiver) createCandidateDescriptor(it, dispatchReceiver)
} }
val smartCastPossibleTypes = scopeTower.dataFlowInfo.getSmartCastTypes(dispatchReceiver) val unstableError = if (dispatchReceiver.isStable) null else UnstableSmartCastDiagnostic
val unstableError = if (scopeTower.dataFlowInfo.isStableReceiver(dispatchReceiver)) null else UnstableSmartCastDiagnostic
val unstableCandidates = if (unstableError != null) ArrayList<CandidateWithBoundDispatchReceiver<D>>(0) else null val unstableCandidates = if (unstableError != null) ArrayList<CandidateWithBoundDispatchReceiver<D>>(0) else null
for (possibleType in smartCastPossibleTypes) { for (possibleType in dispatchReceiver.possibleTypes) {
possibleType.memberScope.getMembers(possibleType).mapTo(unstableCandidates ?: result) { possibleType.memberScope.getMembers(possibleType).mapTo(unstableCandidates ?: result) {
createCandidateDescriptor(it, dispatchReceiver.smartCastReceiver(possibleType), unstableError, dispatchReceiverSmartCastType = possibleType) createCandidateDescriptor(it, dispatchReceiver.smartCastReceiver(possibleType), unstableError, dispatchReceiverSmartCastType = possibleType)
} }
} }
if (smartCastPossibleTypes.isNotEmpty()) { if (dispatchReceiver.possibleTypes.isNotEmpty()) {
if (unstableCandidates == null) { if (unstableCandidates == null) {
result.retainAll(result.selectMostSpecificInEachOverridableGroup { descriptor }) result.retainAll(result.selectMostSpecificInEachOverridableGroup { descriptor })
} }
@@ -112,13 +109,13 @@ internal class ReceiverScopeTowerLevel(
} }
} }
if (dispatchReceiver.type.isDynamic()) { if (receiverValue.type.isDynamic()) {
scopeTower.dynamicScope.getMembers(null).mapTo(result) { scopeTower.dynamicScope.getMembers(null).mapTo(result) {
createCandidateDescriptor(it, dispatchReceiver, DynamicDescriptorDiagnostic) createCandidateDescriptor(it, dispatchReceiver, DynamicDescriptorDiagnostic)
} }
} }
if (dispatchReceiver is CoroutineReceiverValue) { if (receiverValue is CoroutineReceiverValue) {
result.addAll(result.mapNotNull { result.addAll(result.mapNotNull {
val suspensionFunctionView = it.descriptor.createCoroutineSuspensionFunctionView() ?: return@mapNotNull null val suspensionFunctionView = it.descriptor.createCoroutineSuspensionFunctionView() ?: return@mapNotNull null
createCandidateDescriptor(suspensionFunctionView, dispatchReceiver) createCandidateDescriptor(suspensionFunctionView, dispatchReceiver)
@@ -128,18 +125,22 @@ internal class ReceiverScopeTowerLevel(
return result return result
} }
private fun ReceiverValue.smartCastReceiver(targetType: KotlinType) private fun ReceiverValueWithSmartCastInfo.smartCastReceiver(targetType: KotlinType): ReceiverValueWithSmartCastInfo {
= if (this is ImplicitClassReceiver) CastImplicitClassReceiver(this.classDescriptor, targetType) else this if (receiverValue !is ImplicitClassReceiver) return this
override fun getVariables(name: Name, extensionReceiver: ReceiverValue?): Collection<CandidateWithBoundDispatchReceiver<VariableDescriptor>> { val newReceiverValue = CastImplicitClassReceiver(receiverValue.classDescriptor, targetType)
return ReceiverValueWithSmartCastInfo(newReceiverValue, possibleTypes, isStable)
}
override fun getVariables(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?): Collection<CandidateWithBoundDispatchReceiver<VariableDescriptor>> {
return collectMembers { getContributedVariables(name, location) } return collectMembers { getContributedVariables(name, location) }
} }
override fun getObjects(name: Name, extensionReceiver: ReceiverValue?): Collection<CandidateWithBoundDispatchReceiver<VariableDescriptor>> { override fun getObjects(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?): Collection<CandidateWithBoundDispatchReceiver<VariableDescriptor>> {
return emptyList() return emptyList()
} }
override fun getFunctions(name: Name, extensionReceiver: ReceiverValue?): Collection<CandidateWithBoundDispatchReceiver<FunctionDescriptor>> { override fun getFunctions(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?): Collection<CandidateWithBoundDispatchReceiver<FunctionDescriptor>> {
return collectMembers { return collectMembers {
getContributedFunctions(name, location) + it.getInnerConstructors(name, location) getContributedFunctions(name, location) + it.getInnerConstructors(name, location)
} }
@@ -147,17 +148,17 @@ 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, extensionReceiver: ReceiverValue?) = qualifier.staticScope override fun getVariables(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?) = qualifier.staticScope
.getContributedVariables(name, location).map { .getContributedVariables(name, location).map {
createCandidateDescriptor(it, dispatchReceiver = null) createCandidateDescriptor(it, dispatchReceiver = null)
} }
override fun getObjects(name: Name, extensionReceiver: ReceiverValue?) = qualifier.staticScope override fun getObjects(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?) = qualifier.staticScope
.getContributedObjectVariables(name, location).map { .getContributedObjectVariables(name, location).map {
createCandidateDescriptor(it, dispatchReceiver = null) createCandidateDescriptor(it, dispatchReceiver = null)
} }
override fun getFunctions(name: Name, extensionReceiver: ReceiverValue?) = qualifier.staticScope override fun getFunctions(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?) = qualifier.staticScope
.getContributedFunctionsAndConstructors(name, location).map { .getContributedFunctionsAndConstructors(name, location).map {
createCandidateDescriptor(it, dispatchReceiver = null) createCandidateDescriptor(it, dispatchReceiver = null)
} }
@@ -171,17 +172,17 @@ 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, extensionReceiver: ReceiverValue?): Collection<CandidateWithBoundDispatchReceiver<VariableDescriptor>> override fun getVariables(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?): Collection<CandidateWithBoundDispatchReceiver<VariableDescriptor>>
= resolutionScope.getContributedVariables(name, location).map { = resolutionScope.getContributedVariables(name, location).map {
createCandidateDescriptor(it, dispatchReceiver = null) createCandidateDescriptor(it, dispatchReceiver = null)
} }
override fun getObjects(name: Name, extensionReceiver: ReceiverValue?): Collection<CandidateWithBoundDispatchReceiver<VariableDescriptor>> override fun getObjects(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?): Collection<CandidateWithBoundDispatchReceiver<VariableDescriptor>>
= resolutionScope.getContributedObjectVariables(name, location).map { = resolutionScope.getContributedObjectVariables(name, location).map {
createCandidateDescriptor(it, dispatchReceiver = null) createCandidateDescriptor(it, dispatchReceiver = null)
} }
override fun getFunctions(name: Name, extensionReceiver: ReceiverValue?): Collection<CandidateWithBoundDispatchReceiver<FunctionDescriptor>> override fun getFunctions(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?): Collection<CandidateWithBoundDispatchReceiver<FunctionDescriptor>>
= resolutionScope.getContributedFunctionsAndConstructors(name, location).map { = resolutionScope.getContributedFunctionsAndConstructors(name, location).map {
createCandidateDescriptor(it, dispatchReceiver = null) createCandidateDescriptor(it, dispatchReceiver = null)
} }
@@ -195,41 +196,42 @@ internal class SyntheticScopeBasedTowerLevel(
scopeTower: ScopeTower, scopeTower: ScopeTower,
private val syntheticScopes: SyntheticScopes private val syntheticScopes: SyntheticScopes
): AbstractScopeTowerLevel(scopeTower) { ): AbstractScopeTowerLevel(scopeTower) {
override fun getVariables(name: Name, extensionReceiver: ReceiverValue?): Collection<CandidateWithBoundDispatchReceiver<VariableDescriptor>> { private val ReceiverValueWithSmartCastInfo.allTypes: Set<KotlinType>
get() = possibleTypes + receiverValue.type
override fun getVariables(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?): Collection<CandidateWithBoundDispatchReceiver<VariableDescriptor>> {
if (extensionReceiver == null) return emptyList() if (extensionReceiver == null) return emptyList()
val extensionReceiverTypes = scopeTower.dataFlowInfo.getAllPossibleTypes(extensionReceiver) return syntheticScopes.collectSyntheticExtensionProperties(extensionReceiver.allTypes, name, location).map {
return syntheticScopes.collectSyntheticExtensionProperties(extensionReceiverTypes, name, location).map {
createCandidateDescriptor(it, dispatchReceiver = null) createCandidateDescriptor(it, dispatchReceiver = null)
} }
} }
override fun getObjects(name: Name, extensionReceiver: ReceiverValue?): Collection<CandidateWithBoundDispatchReceiver<VariableDescriptor>> override fun getObjects(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?): Collection<CandidateWithBoundDispatchReceiver<VariableDescriptor>>
= emptyList() = emptyList()
override fun getFunctions(name: Name, extensionReceiver: ReceiverValue?): Collection<CandidateWithBoundDispatchReceiver<FunctionDescriptor>> { override fun getFunctions(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?): Collection<CandidateWithBoundDispatchReceiver<FunctionDescriptor>> {
if (extensionReceiver == null) return emptyList() if (extensionReceiver == null) return emptyList()
val extensionReceiverTypes = scopeTower.dataFlowInfo.getAllPossibleTypes(extensionReceiver) return syntheticScopes.collectSyntheticExtensionFunctions(extensionReceiver.allTypes, name, location).map {
return syntheticScopes.collectSyntheticExtensionFunctions(extensionReceiverTypes, name, location).map {
createCandidateDescriptor(it, dispatchReceiver = null) createCandidateDescriptor(it, dispatchReceiver = null)
} }
} }
} }
internal class HidesMembersTowerLevel(scopeTower: ScopeTower): AbstractScopeTowerLevel(scopeTower) { internal class HidesMembersTowerLevel(scopeTower: ScopeTower): AbstractScopeTowerLevel(scopeTower) {
override fun getVariables(name: Name, extensionReceiver: ReceiverValue?) override fun getVariables(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?)
= getCandidates(name, extensionReceiver, LexicalScope::collectVariables) = getCandidates(name, extensionReceiver, LexicalScope::collectVariables)
override fun getObjects(name: Name, extensionReceiver: ReceiverValue?) override fun getObjects(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?)
= emptyList<CandidateWithBoundDispatchReceiver<VariableDescriptor>>() = emptyList<CandidateWithBoundDispatchReceiver<VariableDescriptor>>()
override fun getFunctions(name: Name, extensionReceiver: ReceiverValue?) override fun getFunctions(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?)
= getCandidates(name, extensionReceiver, LexicalScope::collectFunctions) = getCandidates(name, extensionReceiver, LexicalScope::collectFunctions)
private fun <T: CallableDescriptor> getCandidates( private fun <T: CallableDescriptor> getCandidates(
name: Name, name: Name,
extensionReceiver: ReceiverValue?, extensionReceiver: ReceiverValueWithSmartCastInfo?,
collectCandidates: LexicalScope.(Name, LookupLocation) -> Collection<T> collectCandidates: LexicalScope.(Name, LookupLocation) -> Collection<T>
): Collection<CandidateWithBoundDispatchReceiver<T>> { ): Collection<CandidateWithBoundDispatchReceiver<T>> {
if (extensionReceiver == null || name !in HIDES_MEMBERS_NAME_LIST) return emptyList() if (extensionReceiver == null || name !in HIDES_MEMBERS_NAME_LIST) return emptyList()
@@ -24,7 +24,7 @@ import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStat
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
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.receivers.ReceiverValue import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValueWithSmartCastInfo
import org.jetbrains.kotlin.resolve.scopes.utils.parentsWithSelf import org.jetbrains.kotlin.resolve.scopes.utils.parentsWithSelf
import org.jetbrains.kotlin.utils.addToStdlib.check import org.jetbrains.kotlin.utils.addToStdlib.check
import java.util.* import java.util.*
@@ -45,7 +45,7 @@ interface TowerContext<D : CallableDescriptor, out C: Candidate<D>> {
fun createCandidate( fun createCandidate(
towerCandidate: CandidateWithBoundDispatchReceiver<D>, towerCandidate: CandidateWithBoundDispatchReceiver<D>,
explicitReceiverKind: ExplicitReceiverKind, explicitReceiverKind: ExplicitReceiverKind,
extensionReceiver: ReceiverValue? extensionReceiver: ReceiverValueWithSmartCastInfo?
): C ): C
} }
@@ -57,14 +57,14 @@ interface InvokeTowerContext<F : Candidate<FunctionDescriptor>, V : Candidate<Va
// foo() -> ReceiverValue(foo), context for invoke // foo() -> ReceiverValue(foo), context for invoke
// null means that there is no invoke on variable // null means that there is no invoke on variable
fun contextForInvoke(variable: V, useExplicitReceiver: Boolean): Pair<ReceiverValue, TowerContext<FunctionDescriptor, F>>? fun contextForInvoke(variable: V, useExplicitReceiver: Boolean): Pair<ReceiverValueWithSmartCastInfo, TowerContext<FunctionDescriptor, F>>?
} }
sealed class TowerData { sealed class TowerData {
object Empty : TowerData() object Empty : TowerData()
class OnlyImplicitReceiver(val implicitReceiver: ReceiverValue): TowerData() class OnlyImplicitReceiver(val implicitReceiver: ReceiverValueWithSmartCastInfo): TowerData()
class TowerLevel(val level: ScopeTowerLevel) : TowerData() class TowerLevel(val level: ScopeTowerLevel) : TowerData()
class BothTowerLevelAndImplicitReceiver(val level: ScopeTowerLevel, val implicitReceiver: ReceiverValue) : TowerData() class BothTowerLevelAndImplicitReceiver(val level: ScopeTowerLevel, val implicitReceiver: ReceiverValueWithSmartCastInfo) : TowerData()
} }
interface ScopeTowerProcessor<out C> { interface ScopeTowerProcessor<out C> {
@@ -93,7 +93,7 @@ class TowerResolver {
if (scope is LexicalScope) { if (scope is LexicalScope) {
if (!scope.kind.withLocalDescriptors) result.add(ScopeBasedTowerLevel(this, scope)) if (!scope.kind.withLocalDescriptors) result.add(ScopeBasedTowerLevel(this, scope))
scope.implicitReceiver?.let { result.add(ReceiverScopeTowerLevel(this, it.value)) } getImplicitReceiver(scope)?.let { result.add(ReceiverScopeTowerLevel(this, it)) }
} }
else { else {
result.add(ImportingScopeBasedTowerLevel(this, scope as ImportingScope)) result.add(ImportingScopeBasedTowerLevel(this, scope as ImportingScope))
@@ -138,7 +138,7 @@ class TowerResolver {
TowerData.TowerLevel(ScopeBasedTowerLevel(this, scope)).process()?.let { return it } TowerData.TowerLevel(ScopeBasedTowerLevel(this, scope)).process()?.let { return it }
} }
val implicitReceiver = scope.implicitReceiver?.value val implicitReceiver = getImplicitReceiver(scope)
if (implicitReceiver != null) { if (implicitReceiver != null) {
// hides members extensions // hides members extensions
TowerData.BothTowerLevelAndImplicitReceiver(hidesMembersLevel, implicitReceiver).process()?.let { return it } TowerData.BothTowerLevelAndImplicitReceiver(hidesMembersLevel, implicitReceiver).process()?.let { return it }
@@ -18,7 +18,7 @@ package org.jetbrains.kotlin.resolve.calls.tower
import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValueWithSmartCastInfo
val ResolutionCandidateApplicability.isSuccess: Boolean val ResolutionCandidateApplicability.isSuccess: Boolean
get() = this <= ResolutionCandidateApplicability.RESOLVED_LOW_PRIORITY get() = this <= ResolutionCandidateApplicability.RESOLVED_LOW_PRIORITY
@@ -29,10 +29,8 @@ val CallableDescriptor.isSynthesized: Boolean
val CandidateWithBoundDispatchReceiver<*>.requiresExtensionReceiver: Boolean val CandidateWithBoundDispatchReceiver<*>.requiresExtensionReceiver: Boolean
get() = descriptor.extensionReceiverParameter != null get() = descriptor.extensionReceiverParameter != null
fun DataFlowDecorator.getAllPossibleTypes(receiver: ReceiverValue) = getSmartCastTypes(receiver) + receiver.type
internal class CandidateWithBoundDispatchReceiverImpl<out D : CallableDescriptor>( internal class CandidateWithBoundDispatchReceiverImpl<out D : CallableDescriptor>(
override val dispatchReceiver: ReceiverValue?, override val dispatchReceiver: ReceiverValueWithSmartCastInfo?,
override val descriptor: D, override val descriptor: D,
override val diagnostics: List<ResolutionDiagnostic> override val diagnostics: List<ResolutionDiagnostic>
) : CandidateWithBoundDispatchReceiver<D> { ) : CandidateWithBoundDispatchReceiver<D> {
@@ -18,11 +18,26 @@ package org.jetbrains.kotlin.resolve.scopes.receivers
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.types.KotlinType
interface QualifierReceiver : Receiver { // this receiver used only for resolution. see subtypes
interface DetailedReceiver
class ReceiverValueWithSmartCastInfo(
val receiverValue: ReceiverValue,
val possibleTypes: Set<KotlinType>, // doesn't include receiver.type
val isStable: Boolean
): DetailedReceiver
interface QualifierReceiver : Receiver, DetailedReceiver {
val descriptor: DeclarationDescriptor val descriptor: DeclarationDescriptor
val staticScope: MemberScope val staticScope: MemberScope
val classValueReceiver: ReceiverValue? val classValueReceiver: ReceiverValue?
// for qualifiers smart cast is impossible
val classValueReceiverWithSmartCastInfo: ReceiverValueWithSmartCastInfo?
get() = classValueReceiver?.let { ReceiverValueWithSmartCastInfo(it, emptySet(), true) }
} }