Refactoring. Add type safety to resolution.
This commit is contained in:
+38
-37
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.resolve.calls.tower
|
||||
|
||||
import org.jetbrains.kotlin.builtins.isExtensionFunctionType
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.createSynthesizedInvokes
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.Receiver
|
||||
@@ -25,29 +26,29 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
import java.util.*
|
||||
|
||||
abstract class AbstractInvokeTowerProcessor<C>(
|
||||
protected val functionContext: TowerContext<C>,
|
||||
private val variableProcessor: ScopeTowerProcessor<C>
|
||||
) : ScopeTowerProcessor<C> {
|
||||
abstract class AbstractInvokeTowerProcessor<F : Candidate<FunctionDescriptor>, V : Candidate<VariableDescriptor>>(
|
||||
protected val invokeContext: InvokeTowerContext<F, V>,
|
||||
private val variableProcessor: ScopeTowerProcessor<V>
|
||||
) : ScopeTowerProcessor<F> {
|
||||
// todo optimize it
|
||||
private val previousData = ArrayList<TowerData>()
|
||||
private val invokeProcessors: MutableList<Collection<VariableInvokeProcessor>> = ArrayList()
|
||||
|
||||
private inner class VariableInvokeProcessor(val variableCandidate: C): ScopeTowerProcessor<C> {
|
||||
val invokeProcessor: ScopeTowerProcessor<C> = createInvokeProcessor(variableCandidate)
|
||||
private inner class VariableInvokeProcessor(val variableCandidate: V): ScopeTowerProcessor<F> {
|
||||
val invokeProcessor: ScopeTowerProcessor<F> = createInvokeProcessor(variableCandidate)
|
||||
|
||||
override fun process(data: TowerData)
|
||||
= invokeProcessor.process(data).map { candidateGroup ->
|
||||
candidateGroup.map { functionContext.transformCandidate(variableCandidate, it) }
|
||||
candidateGroup.map { invokeContext.transformCandidate(variableCandidate, it) }
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract fun createInvokeProcessor(variableCandidate: C): ScopeTowerProcessor<C>
|
||||
protected abstract fun createInvokeProcessor(variableCandidate: V): ScopeTowerProcessor<F>
|
||||
|
||||
override fun process(data: TowerData): List<Collection<C>> {
|
||||
override fun process(data: TowerData): List<Collection<F>> {
|
||||
previousData.add(data)
|
||||
|
||||
val candidateGroups = ArrayList<Collection<C>>(0)
|
||||
val candidateGroups = ArrayList<Collection<F>>(0)
|
||||
|
||||
for (processorsGroup in invokeProcessors) {
|
||||
candidateGroups.addAll(processorsGroup.processVariableGroup(data))
|
||||
@@ -55,7 +56,7 @@ abstract class AbstractInvokeTowerProcessor<C>(
|
||||
|
||||
for (variableCandidates in variableProcessor.process(data)) {
|
||||
val successfulVariables = variableCandidates.filter {
|
||||
functionContext.getStatus(it).resultingApplicability.isSuccess
|
||||
it.isSuccessful
|
||||
}
|
||||
|
||||
if (successfulVariables.isNotEmpty()) {
|
||||
@@ -71,7 +72,7 @@ abstract class AbstractInvokeTowerProcessor<C>(
|
||||
return candidateGroups
|
||||
}
|
||||
|
||||
private fun Collection<VariableInvokeProcessor>.processVariableGroup(data: TowerData): List<Collection<C>> {
|
||||
private fun Collection<VariableInvokeProcessor>.processVariableGroup(data: TowerData): List<Collection<F>> {
|
||||
return when (size) {
|
||||
0 -> emptyList()
|
||||
1 -> single().process(data)
|
||||
@@ -84,44 +85,44 @@ abstract class AbstractInvokeTowerProcessor<C>(
|
||||
}
|
||||
|
||||
// todo KT-9522 Allow invoke convention for synthetic property
|
||||
class InvokeTowerProcessor<C>(
|
||||
functionContext: TowerContext<C>,
|
||||
class InvokeTowerProcessor<F : Candidate<FunctionDescriptor>, V : Candidate<VariableDescriptor>>(
|
||||
invokeContext: InvokeTowerContext<F, V>,
|
||||
private val explicitReceiver: Receiver?
|
||||
) : AbstractInvokeTowerProcessor<C>(
|
||||
functionContext,
|
||||
createVariableProcessor(functionContext.contextForVariable(stripExplicitReceiver = false), explicitReceiver)
|
||||
) : AbstractInvokeTowerProcessor<F, V>(
|
||||
invokeContext,
|
||||
createVariableProcessor(invokeContext.contextForVariable(stripExplicitReceiver = false), explicitReceiver)
|
||||
) {
|
||||
|
||||
// todo filter by operator
|
||||
override fun createInvokeProcessor(variableCandidate: C): ScopeTowerProcessor<C> {
|
||||
val (variableReceiver, invokeContext) = functionContext.contextForInvoke(variableCandidate, useExplicitReceiver = false)
|
||||
override fun createInvokeProcessor(variableCandidate: V): ScopeTowerProcessor<F> {
|
||||
val (variableReceiver, invokeContext) = invokeContext.contextForInvoke(variableCandidate, useExplicitReceiver = false)
|
||||
?: return KnownResultProcessor(emptyList())
|
||||
return ExplicitReceiverScopeTowerProcessor(invokeContext, variableReceiver, ScopeTowerLevel::getFunctions)
|
||||
}
|
||||
}
|
||||
|
||||
class InvokeExtensionTowerProcessor<C>(
|
||||
functionContext: TowerContext<C>,
|
||||
class InvokeExtensionTowerProcessor<F : Candidate<FunctionDescriptor>, V : Candidate<VariableDescriptor>>(
|
||||
invokeContext: InvokeTowerContext<F, V>,
|
||||
private val explicitReceiver: ReceiverValue?
|
||||
) : AbstractInvokeTowerProcessor<C>(
|
||||
functionContext,
|
||||
createVariableProcessor(functionContext.contextForVariable(stripExplicitReceiver = true), explicitReceiver = null)
|
||||
) : AbstractInvokeTowerProcessor<F, V>(
|
||||
invokeContext,
|
||||
createVariableProcessor(invokeContext.contextForVariable(stripExplicitReceiver = true), explicitReceiver = null)
|
||||
) {
|
||||
|
||||
override fun createInvokeProcessor(variableCandidate: C): ScopeTowerProcessor<C> {
|
||||
val (variableReceiver, invokeContext) = functionContext.contextForInvoke(variableCandidate, useExplicitReceiver = true)
|
||||
override fun createInvokeProcessor(variableCandidate: V): ScopeTowerProcessor<F> {
|
||||
val (variableReceiver, invokeContext) = invokeContext.contextForInvoke(variableCandidate, useExplicitReceiver = true)
|
||||
?: return KnownResultProcessor(emptyList())
|
||||
val invokeDescriptor = functionContext.scopeTower.getExtensionInvokeCandidateDescriptor(variableReceiver)
|
||||
val invokeDescriptor = invokeContext.scopeTower.getExtensionInvokeCandidateDescriptor(variableReceiver)
|
||||
?: return KnownResultProcessor(emptyList())
|
||||
return InvokeExtensionScopeTowerProcessor(invokeContext, invokeDescriptor, explicitReceiver)
|
||||
}
|
||||
}
|
||||
|
||||
private class InvokeExtensionScopeTowerProcessor<C>(
|
||||
context: TowerContext<C>,
|
||||
private class InvokeExtensionScopeTowerProcessor<C : Candidate<FunctionDescriptor>>(
|
||||
context: TowerContext<FunctionDescriptor, C>,
|
||||
private val invokeCandidateDescriptor: CandidateWithBoundDispatchReceiver<FunctionDescriptor>,
|
||||
private val explicitReceiver: ReceiverValue?
|
||||
) : AbstractSimpleScopeTowerProcessor<C>(context) {
|
||||
) : AbstractSimpleScopeTowerProcessor<FunctionDescriptor, C>(context) {
|
||||
|
||||
override fun simpleProcess(data: TowerData): Collection<C> {
|
||||
if (explicitReceiver != null && data == TowerData.Empty) {
|
||||
@@ -150,23 +151,23 @@ private fun ScopeTower.getExtensionInvokeCandidateDescriptor(
|
||||
}
|
||||
|
||||
// case 1.(foo())() or (foo())()
|
||||
fun <C> createCallTowerProcessorForExplicitInvoke(
|
||||
contextForInvoke: TowerContext<C>,
|
||||
fun <F : Candidate<FunctionDescriptor>, V : Candidate<VariableDescriptor>> createCallTowerProcessorForExplicitInvoke(
|
||||
invokeContext: InvokeTowerContext<F, V>,
|
||||
expressionForInvoke: ReceiverValue,
|
||||
explicitReceiver: ReceiverValue?
|
||||
): ScopeTowerProcessor<C> {
|
||||
val invokeExtensionDescriptor = contextForInvoke.scopeTower.getExtensionInvokeCandidateDescriptor(expressionForInvoke)
|
||||
): ScopeTowerProcessor<F> {
|
||||
val invokeExtensionDescriptor = invokeContext.scopeTower.getExtensionInvokeCandidateDescriptor(expressionForInvoke)
|
||||
if (explicitReceiver != null) {
|
||||
if (invokeExtensionDescriptor == null) {
|
||||
// case 1.(foo())(), where foo() isn't extension function
|
||||
return KnownResultProcessor(emptyList())
|
||||
}
|
||||
else {
|
||||
return InvokeExtensionScopeTowerProcessor(contextForInvoke, invokeExtensionDescriptor, explicitReceiver = explicitReceiver)
|
||||
return InvokeExtensionScopeTowerProcessor(invokeContext, invokeExtensionDescriptor, explicitReceiver = explicitReceiver)
|
||||
}
|
||||
}
|
||||
else {
|
||||
val usualInvoke = ExplicitReceiverScopeTowerProcessor(contextForInvoke, expressionForInvoke, ScopeTowerLevel::getFunctions) // todo operator
|
||||
val usualInvoke = ExplicitReceiverScopeTowerProcessor(invokeContext, expressionForInvoke, ScopeTowerLevel::getFunctions) // todo operator
|
||||
|
||||
if (invokeExtensionDescriptor == null) {
|
||||
return usualInvoke
|
||||
@@ -174,7 +175,7 @@ fun <C> createCallTowerProcessorForExplicitInvoke(
|
||||
else {
|
||||
return CompositeScopeTowerProcessor(
|
||||
usualInvoke,
|
||||
InvokeExtensionScopeTowerProcessor(contextForInvoke, invokeExtensionDescriptor, explicitReceiver = null)
|
||||
InvokeExtensionScopeTowerProcessor(invokeContext, invokeExtensionDescriptor, explicitReceiver = null)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+22
-19
@@ -16,6 +16,9 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve.calls.tower
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.QualifierReceiver
|
||||
@@ -37,8 +40,8 @@ class CompositeScopeTowerProcessor<C>(
|
||||
override fun process(data: TowerData): List<Collection<C>> = processors.flatMap { it.process(data) }
|
||||
}
|
||||
|
||||
internal abstract class AbstractSimpleScopeTowerProcessor<C>(
|
||||
val context: TowerContext<C>
|
||||
internal abstract class AbstractSimpleScopeTowerProcessor<D : CallableDescriptor, C: Candidate<D>>(
|
||||
val context: TowerContext<D, C>
|
||||
) : ScopeTowerProcessor<C> {
|
||||
protected val name: Name get() = context.name
|
||||
|
||||
@@ -47,11 +50,11 @@ internal abstract class AbstractSimpleScopeTowerProcessor<C>(
|
||||
override fun process(data: TowerData): List<Collection<C>> = listOfNotNull(simpleProcess(data).check { it.isNotEmpty() })
|
||||
}
|
||||
|
||||
internal class ExplicitReceiverScopeTowerProcessor<C>(
|
||||
context: TowerContext<C>,
|
||||
internal class ExplicitReceiverScopeTowerProcessor<D : CallableDescriptor, C: Candidate<D>>(
|
||||
context: TowerContext<D, C>,
|
||||
val explicitReceiver: ReceiverValue,
|
||||
val collectCandidates: ScopeTowerLevel.(name: Name, extensionReceiver: ReceiverValue?) -> Collection<CandidateWithBoundDispatchReceiver<*>>
|
||||
): AbstractSimpleScopeTowerProcessor<C>(context) {
|
||||
val collectCandidates: ScopeTowerLevel.(name: Name, extensionReceiver: ReceiverValue?) -> Collection<CandidateWithBoundDispatchReceiver<D>>
|
||||
): AbstractSimpleScopeTowerProcessor<D, C>(context) {
|
||||
override fun simpleProcess(data: TowerData): Collection<C> {
|
||||
return when (data) {
|
||||
TowerData.Empty -> resolveAsMember()
|
||||
@@ -72,11 +75,11 @@ internal class ExplicitReceiverScopeTowerProcessor<C>(
|
||||
}
|
||||
}
|
||||
|
||||
private class QualifierScopeTowerProcessor<C>(
|
||||
context: TowerContext<C>,
|
||||
private class QualifierScopeTowerProcessor<D : CallableDescriptor, C: Candidate<D>>(
|
||||
context: TowerContext<D, C>,
|
||||
val qualifier: QualifierReceiver,
|
||||
val collectCandidates: ScopeTowerLevel.(name: Name, extensionReceiver: ReceiverValue?) -> Collection<CandidateWithBoundDispatchReceiver<*>>
|
||||
): AbstractSimpleScopeTowerProcessor<C>(context) {
|
||||
val collectCandidates: ScopeTowerLevel.(name: Name, extensionReceiver: ReceiverValue?) -> Collection<CandidateWithBoundDispatchReceiver<D>>
|
||||
): AbstractSimpleScopeTowerProcessor<D, C>(context) {
|
||||
override fun simpleProcess(data: TowerData): Collection<C> {
|
||||
if (data != TowerData.Empty) return emptyList()
|
||||
|
||||
@@ -87,10 +90,10 @@ private class QualifierScopeTowerProcessor<C>(
|
||||
}
|
||||
}
|
||||
|
||||
private class NoExplicitReceiverScopeTowerProcessor<C>(
|
||||
context: TowerContext<C>,
|
||||
val collectCandidates: ScopeTowerLevel.(name: Name, extensionReceiver: ReceiverValue?) -> Collection<CandidateWithBoundDispatchReceiver<*>>
|
||||
) : AbstractSimpleScopeTowerProcessor<C>(context) {
|
||||
private class NoExplicitReceiverScopeTowerProcessor<D : CallableDescriptor, C: Candidate<D>>(
|
||||
context: TowerContext<D, C>,
|
||||
val collectCandidates: ScopeTowerLevel.(name: Name, extensionReceiver: ReceiverValue?) -> Collection<CandidateWithBoundDispatchReceiver<D>>
|
||||
) : AbstractSimpleScopeTowerProcessor<D, C>(context) {
|
||||
override fun simpleProcess(data: TowerData): Collection<C>
|
||||
= when(data) {
|
||||
is TowerData.TowerLevel -> {
|
||||
@@ -107,10 +110,10 @@ private class NoExplicitReceiverScopeTowerProcessor<C>(
|
||||
}
|
||||
}
|
||||
|
||||
private fun <C> createSimpleProcessor(
|
||||
context: TowerContext<C>,
|
||||
private fun <D : CallableDescriptor, C: Candidate<D>> createSimpleProcessor(
|
||||
context: TowerContext<D, C>,
|
||||
explicitReceiver: Receiver?,
|
||||
collectCandidates: ScopeTowerLevel.(name: Name, extensionReceiver: ReceiverValue?) -> Collection<CandidateWithBoundDispatchReceiver<*>>
|
||||
collectCandidates: ScopeTowerLevel.(name: Name, extensionReceiver: ReceiverValue?) -> Collection<CandidateWithBoundDispatchReceiver<D>>
|
||||
) : ScopeTowerProcessor<C> {
|
||||
if (explicitReceiver is ReceiverValue) {
|
||||
return ExplicitReceiverScopeTowerProcessor(context, explicitReceiver, collectCandidates)
|
||||
@@ -133,8 +136,8 @@ private fun <C> createSimpleProcessor(
|
||||
}
|
||||
}
|
||||
|
||||
fun <C> createVariableProcessor(context: TowerContext<C>, explicitReceiver: Receiver?)
|
||||
fun <C : Candidate<VariableDescriptor>> createVariableProcessor(context: TowerContext<VariableDescriptor, C>, explicitReceiver: Receiver?)
|
||||
= createSimpleProcessor(context, explicitReceiver, ScopeTowerLevel::getVariables)
|
||||
|
||||
fun <C> createFunctionProcessor(context: TowerContext<C>, explicitReceiver: Receiver?)
|
||||
fun <C : Candidate<FunctionDescriptor>> createFunctionProcessor(context: TowerContext<FunctionDescriptor, C>, explicitReceiver: Receiver?)
|
||||
= createSimpleProcessor(context, explicitReceiver, ScopeTowerLevel::getFunctions)
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve.calls.tower
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
|
||||
@@ -26,25 +29,35 @@ import org.jetbrains.kotlin.resolve.scopes.utils.parentsWithSelf
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.check
|
||||
import java.util.*
|
||||
|
||||
interface TowerContext<C> {
|
||||
interface Candidate<out D : CallableDescriptor> {
|
||||
val descriptor: D
|
||||
|
||||
// this operation should be very fast
|
||||
val isSuccessful: Boolean
|
||||
|
||||
val status: ResolutionCandidateStatus
|
||||
}
|
||||
|
||||
interface TowerContext<D : CallableDescriptor, C: Candidate<D>> {
|
||||
val name: Name
|
||||
val scopeTower: ScopeTower
|
||||
|
||||
fun createCandidate(
|
||||
towerCandidate: CandidateWithBoundDispatchReceiver<*>,
|
||||
towerCandidate: CandidateWithBoundDispatchReceiver<D>,
|
||||
explicitReceiverKind: ExplicitReceiverKind,
|
||||
extensionReceiver: ReceiverValue?
|
||||
): C
|
||||
}
|
||||
|
||||
fun getStatus(candidate: C): ResolutionCandidateStatus
|
||||
interface InvokeTowerContext<F : Candidate<FunctionDescriptor>, V : Candidate<VariableDescriptor>>: TowerContext<FunctionDescriptor, F> {
|
||||
|
||||
fun transformCandidate(variable: C, invoke: C): C
|
||||
fun transformCandidate(variable: V, invoke: F): F
|
||||
|
||||
fun contextForVariable(stripExplicitReceiver: Boolean): TowerContext<C>
|
||||
fun contextForVariable(stripExplicitReceiver: Boolean): TowerContext<VariableDescriptor, V>
|
||||
|
||||
// foo() -> ReceiverValue(foo), context for invoke
|
||||
// null means that there is no invoke on variable
|
||||
fun contextForInvoke(variable: C, useExplicitReceiver: Boolean): Pair<ReceiverValue, TowerContext<C>>?
|
||||
fun contextForInvoke(variable: V, useExplicitReceiver: Boolean): Pair<ReceiverValue, TowerContext<FunctionDescriptor, F>>?
|
||||
}
|
||||
|
||||
sealed class TowerData {
|
||||
@@ -54,21 +67,24 @@ sealed class TowerData {
|
||||
class BothTowerLevelAndImplicitReceiver(val level: ScopeTowerLevel, val implicitReceiver: ReceiverValue) : TowerData()
|
||||
}
|
||||
|
||||
interface ScopeTowerProcessor<C> {
|
||||
interface ScopeTowerProcessor<out C> {
|
||||
// Candidates with matched receivers (dispatch receiver was already matched in ScopeTowerLevel)
|
||||
// Candidates in one groups have same priority, first group has highest priority.
|
||||
fun process(data: TowerData): List<Collection<C>>
|
||||
}
|
||||
|
||||
class TowerResolver {
|
||||
fun <C> runResolve(
|
||||
context: TowerContext<C>,
|
||||
fun <C: Candidate<*>> runResolve(
|
||||
scopeTower: ScopeTower,
|
||||
processor: ScopeTowerProcessor<C>,
|
||||
useOrder: Boolean
|
||||
): Collection<C> = context.scopeTower.run(processor, SuccessfulResultCollector { context.getStatus(it) }, useOrder)
|
||||
): Collection<C> = scopeTower.run(processor, SuccessfulResultCollector { it.status }, useOrder)
|
||||
|
||||
fun <C> collectAllCandidates(context: TowerContext<C>, processor: ScopeTowerProcessor<C>): Collection<C>
|
||||
= context.scopeTower.run(processor, AllCandidatesCollector { context.getStatus(it) }, false)
|
||||
fun <C: Candidate<*>> collectAllCandidates(
|
||||
scopeTower: ScopeTower,
|
||||
processor: ScopeTowerProcessor<C>
|
||||
): Collection<C>
|
||||
= scopeTower.run(processor, AllCandidatesCollector { it.status }, false)
|
||||
|
||||
private fun ScopeTower.createNonLocalLevels(): List<ScopeTowerLevel> {
|
||||
val result = ArrayList<ScopeTowerLevel>()
|
||||
|
||||
Reference in New Issue
Block a user