Refactor ScopeTowerProcessor
This commit is contained in:
+36
-66
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve.calls.tower
|
||||
|
||||
import com.intellij.util.SmartList
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
|
||||
@@ -32,73 +31,57 @@ internal abstract class AbstractInvokeTowerProcessor<C>(
|
||||
private val variableProcessor: ScopeTowerProcessor<C>
|
||||
) : ScopeTowerProcessor<C> {
|
||||
// todo optimize it
|
||||
private val previousActions = ArrayList<ScopeTowerProcessor<C>.() -> Unit>()
|
||||
private val candidateGroups: MutableList<Collection<C>> = ArrayList()
|
||||
|
||||
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: C,
|
||||
val invokeProcessor: ScopeTowerProcessor<C> = createInvokeProcessor(variableCandidate)
|
||||
): ScopeTowerProcessor<C> by invokeProcessor {
|
||||
override fun getCandidatesGroups(): List<Collection<C>>
|
||||
= invokeProcessor.getCandidatesGroups().map { candidateGroup ->
|
||||
override fun process(data: TowerData)
|
||||
= invokeProcessor.process(data).map { candidateGroup ->
|
||||
candidateGroup.map { functionContext.transformCandidate(variableCandidate, it) }
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract fun createInvokeProcessor(variableCandidate: C): ScopeTowerProcessor<C>
|
||||
|
||||
private fun findVariablesAndCreateNewInvokeCandidates() {
|
||||
for (variableCandidates in variableProcessor.getCandidatesGroups()) {
|
||||
override fun process(data: TowerData): List<Collection<C>> {
|
||||
previousData.add(data)
|
||||
|
||||
val candidateGroups = ArrayList<Collection<C>>(0)
|
||||
|
||||
for (processorsGroup in invokeProcessors) {
|
||||
candidateGroups.addAll(processorsGroup.processVariableGroup(data))
|
||||
}
|
||||
|
||||
for (variableCandidates in variableProcessor.process(data)) {
|
||||
val successfulVariables = variableCandidates.filter {
|
||||
functionContext.getStatus(it).resultingApplicability.isSuccess
|
||||
}
|
||||
|
||||
if (successfulVariables.isNotEmpty()) {
|
||||
val processors = successfulVariables.map { VariableInvokeProcessor(it) }
|
||||
invokeProcessors.add(processors)
|
||||
val variableProcessors = successfulVariables.map { VariableInvokeProcessor(it) }
|
||||
invokeProcessors.add(variableProcessors)
|
||||
|
||||
for (previousAction in previousActions) {
|
||||
processors.forEach(previousAction)
|
||||
candidateGroups.addAll(processors.collectCandidateGroups())
|
||||
for (oldData in previousData) {
|
||||
candidateGroups.addAll(variableProcessors.processVariableGroup(oldData))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return candidateGroups
|
||||
}
|
||||
|
||||
private fun Collection<VariableInvokeProcessor>.collectCandidateGroups(): List<Collection<C>> {
|
||||
private fun Collection<VariableInvokeProcessor>.processVariableGroup(data: TowerData): List<Collection<C>> {
|
||||
return when (size) {
|
||||
0 -> emptyList()
|
||||
1 -> single().getCandidatesGroups()
|
||||
// overload on variables see KT-10093 Resolve depends on the order of declaration for variable with implicit invoke
|
||||
1 -> single().process(data)
|
||||
// overload on variables see KT-10093 Resolve depends on the order of declaration for variable with implicit invoke
|
||||
|
||||
else -> listOf(this.flatMap { it.getCandidatesGroups().flatten() })
|
||||
else -> listOf(this.flatMap { it.process(data).flatten() })
|
||||
}
|
||||
}
|
||||
|
||||
private fun proceed(action: ScopeTowerProcessor<C>.() -> Unit) {
|
||||
candidateGroups.clear()
|
||||
previousActions.add(action)
|
||||
|
||||
for (processorsGroup in invokeProcessors) {
|
||||
processorsGroup.forEach(action)
|
||||
candidateGroups.addAll(processorsGroup.collectCandidateGroups())
|
||||
}
|
||||
|
||||
variableProcessor.action()
|
||||
findVariablesAndCreateNewInvokeCandidates()
|
||||
}
|
||||
|
||||
init { proceed { /* do nothing */ } }
|
||||
|
||||
override fun processTowerLevel(level: ScopeTowerLevel) = proceed { this.processTowerLevel(level) }
|
||||
|
||||
override fun processImplicitReceiver(implicitReceiver: ReceiverValue)
|
||||
= proceed { this.processImplicitReceiver(implicitReceiver) }
|
||||
|
||||
override fun getCandidatesGroups(): List<Collection<C>> = SmartList(candidateGroups)
|
||||
}
|
||||
|
||||
// todo KT-9522 Allow invoke convention for synthetic property
|
||||
@@ -135,33 +118,20 @@ internal class InvokeExtensionTowerProcessor<C>(
|
||||
|
||||
private class InvokeExtensionScopeTowerProcessor<C>(
|
||||
context: TowerContext<C>,
|
||||
val invokeCandidateDescriptor: CandidateWithBoundDispatchReceiver<FunctionDescriptor>,
|
||||
val explicitReceiver: ReceiverValue?
|
||||
) : AbstractScopeTowerProcessor<C>(context) {
|
||||
override var candidates: Collection<C> = resolve(explicitReceiver)
|
||||
private val invokeCandidateDescriptor: CandidateWithBoundDispatchReceiver<FunctionDescriptor>,
|
||||
private val explicitReceiver: ReceiverValue?
|
||||
) : AbstractSimpleScopeTowerProcessor<C>(context) {
|
||||
|
||||
private fun resolve(extensionReceiver: ReceiverValue?): Collection<C> {
|
||||
if (extensionReceiver == null) return emptyList()
|
||||
|
||||
// todo
|
||||
val explicitReceiverKind = if (explicitReceiver != null) ExplicitReceiverKind.BOTH_RECEIVERS else ExplicitReceiverKind.DISPATCH_RECEIVER
|
||||
|
||||
val candidate = context.createCandidate(invokeCandidateDescriptor, explicitReceiverKind, extensionReceiver)
|
||||
return listOf(candidate)
|
||||
}
|
||||
|
||||
override fun processTowerLevel(level: ScopeTowerLevel) {
|
||||
candidates = emptyList()
|
||||
}
|
||||
|
||||
// todo optimize
|
||||
override fun processImplicitReceiver(implicitReceiver: ReceiverValue) {
|
||||
if (explicitReceiver == null) {
|
||||
candidates = resolve(implicitReceiver)
|
||||
override fun simpleProcess(data: TowerData): Collection<C> {
|
||||
if (explicitReceiver != null && data == TowerData.Empty) {
|
||||
return listOf(context.createCandidate(invokeCandidateDescriptor, ExplicitReceiverKind.BOTH_RECEIVERS, explicitReceiver))
|
||||
}
|
||||
else {
|
||||
candidates = emptyList()
|
||||
|
||||
if (explicitReceiver == null && data is TowerData.OnlyImplicitReceiver) {
|
||||
return listOf(context.createCandidate(invokeCandidateDescriptor, ExplicitReceiverKind.DISPATCH_RECEIVER, data.implicitReceiver))
|
||||
}
|
||||
|
||||
return emptyList()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+32
-62
@@ -26,56 +26,39 @@ import org.jetbrains.kotlin.utils.addToStdlib.check
|
||||
|
||||
|
||||
internal class KnownResultProcessor<C>(
|
||||
result: Collection<C>
|
||||
val result: Collection<C>
|
||||
): ScopeTowerProcessor<C> {
|
||||
var candidates = result
|
||||
|
||||
override fun processTowerLevel(level: ScopeTowerLevel) {
|
||||
candidates = emptyList()
|
||||
}
|
||||
|
||||
override fun processImplicitReceiver(implicitReceiver: ReceiverValue) {
|
||||
candidates = emptyList()
|
||||
}
|
||||
|
||||
override fun getCandidatesGroups() = listOfNotNull(candidates.check { it.isNotEmpty() })
|
||||
override fun process(data: TowerData)
|
||||
= if (data == TowerData.Empty) listOfNotNull(result.check { it.isNotEmpty() }) else emptyList()
|
||||
}
|
||||
|
||||
internal class CompositeScopeTowerProcessor<C>(
|
||||
vararg val processors: ScopeTowerProcessor<C>
|
||||
) : ScopeTowerProcessor<C> {
|
||||
override fun processTowerLevel(level: ScopeTowerLevel) = processors.forEach { it.processTowerLevel(level) }
|
||||
|
||||
override fun processImplicitReceiver(implicitReceiver: ReceiverValue)
|
||||
= processors.forEach { it.processImplicitReceiver(implicitReceiver) }
|
||||
|
||||
override fun getCandidatesGroups(): List<Collection<C>> = processors.flatMap { it.getCandidatesGroups() }
|
||||
override fun process(data: TowerData): List<Collection<C>> = processors.flatMap { it.process(data) }
|
||||
}
|
||||
|
||||
internal abstract class AbstractScopeTowerProcessor<C>(
|
||||
internal abstract class AbstractSimpleScopeTowerProcessor<C>(
|
||||
val context: TowerContext<C>
|
||||
) : ScopeTowerProcessor<C> {
|
||||
protected val name: Name get() = context.name
|
||||
|
||||
protected abstract var candidates: Collection<C>
|
||||
protected abstract fun simpleProcess(data: TowerData): Collection<C>
|
||||
|
||||
override fun getCandidatesGroups() = listOfNotNull(candidates.check { it.isNotEmpty() })
|
||||
override fun process(data: TowerData): List<Collection<C>> = listOfNotNull(simpleProcess(data).check { it.isNotEmpty() })
|
||||
}
|
||||
|
||||
internal class ExplicitReceiverScopeTowerProcessor<C>(
|
||||
context: TowerContext<C>,
|
||||
val explicitReceiver: ReceiverValue,
|
||||
val collectCandidates: ScopeTowerLevel.(Name) -> Collection<CandidateWithBoundDispatchReceiver<*>>
|
||||
): AbstractScopeTowerProcessor<C>(context) {
|
||||
override var candidates = resolveAsMember()
|
||||
|
||||
override fun processTowerLevel(level: ScopeTowerLevel) {
|
||||
candidates = resolveAsExtension(level)
|
||||
}
|
||||
|
||||
override fun processImplicitReceiver(implicitReceiver: ReceiverValue) {
|
||||
// no candidates, because we already have receiver
|
||||
candidates = emptyList()
|
||||
): AbstractSimpleScopeTowerProcessor<C>(context) {
|
||||
override fun simpleProcess(data: TowerData): Collection<C> {
|
||||
return when (data) {
|
||||
TowerData.Empty -> resolveAsMember()
|
||||
is TowerData.TowerLevel -> resolveAsExtension(data.level)
|
||||
else -> emptyList()
|
||||
}
|
||||
}
|
||||
|
||||
private fun resolveAsMember(): Collection<C> {
|
||||
@@ -95,20 +78,10 @@ private class QualifierScopeTowerProcessor<C>(
|
||||
context: TowerContext<C>,
|
||||
val qualifier: QualifierReceiver,
|
||||
val collectCandidates: ScopeTowerLevel.(Name) -> Collection<CandidateWithBoundDispatchReceiver<*>>
|
||||
): AbstractScopeTowerProcessor<C>(context) {
|
||||
override var candidates = resolve()
|
||||
): AbstractSimpleScopeTowerProcessor<C>(context) {
|
||||
override fun simpleProcess(data: TowerData): Collection<C> {
|
||||
if (data != TowerData.Empty) return emptyList()
|
||||
|
||||
override fun processTowerLevel(level: ScopeTowerLevel) {
|
||||
// no candidates, because we done all already
|
||||
candidates = emptyList()
|
||||
}
|
||||
|
||||
override fun processImplicitReceiver(implicitReceiver: ReceiverValue) {
|
||||
// no candidates, because we done all already
|
||||
candidates = emptyList()
|
||||
}
|
||||
|
||||
private fun resolve(): Collection<C> {
|
||||
val staticMembers = QualifierScopeTowerLevel(context.scopeTower, qualifier).collectCandidates(name)
|
||||
.filter { !it.requiresExtensionReceiver }
|
||||
.map { context.createCandidate(it, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, extensionReceiver = null) }
|
||||
@@ -119,24 +92,21 @@ private class QualifierScopeTowerProcessor<C>(
|
||||
private class NoExplicitReceiverScopeTowerProcessor<C>(
|
||||
context: TowerContext<C>,
|
||||
val collectCandidates: ScopeTowerLevel.(Name) -> Collection<CandidateWithBoundDispatchReceiver<*>>
|
||||
) : AbstractScopeTowerProcessor<C>(context) {
|
||||
override var candidates: Collection<C> = emptyList()
|
||||
|
||||
private var descriptorsRequestImplicitReceiver = emptyList<CandidateWithBoundDispatchReceiver<*>>()
|
||||
|
||||
override fun processTowerLevel(level: ScopeTowerLevel) {
|
||||
val descriptors = level.collectCandidates(name)
|
||||
|
||||
descriptorsRequestImplicitReceiver = descriptors.filter { it.requiresExtensionReceiver }
|
||||
|
||||
candidates = descriptors.filter { !it.requiresExtensionReceiver }
|
||||
.map { context.createCandidate(it, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, extensionReceiver = null) }
|
||||
}
|
||||
|
||||
override fun processImplicitReceiver(implicitReceiver: ReceiverValue) {
|
||||
candidates = descriptorsRequestImplicitReceiver
|
||||
.map { context.createCandidate(it, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, extensionReceiver = implicitReceiver) }
|
||||
}
|
||||
) : AbstractSimpleScopeTowerProcessor<C>(context) {
|
||||
override fun simpleProcess(data: TowerData): Collection<C>
|
||||
= when(data) {
|
||||
is TowerData.TowerLevel -> {
|
||||
data.level.collectCandidates(name).filter { !it.requiresExtensionReceiver }.map {
|
||||
context.createCandidate(it, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, extensionReceiver = null)
|
||||
}
|
||||
}
|
||||
is TowerData.BothTowerLevelAndImplicitReceiver -> {
|
||||
data.level.collectCandidates(name).filter { it.requiresExtensionReceiver }.map {
|
||||
context.createCandidate(it, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, extensionReceiver = data.implicitReceiver)
|
||||
}
|
||||
}
|
||||
else -> emptyList()
|
||||
}
|
||||
}
|
||||
|
||||
private fun <C> createSimpleProcessor(
|
||||
|
||||
@@ -41,14 +41,17 @@ interface TowerContext<C> {
|
||||
fun contextForInvoke(variable: C, useExplicitReceiver: Boolean): Pair<ReceiverValue, TowerContext<C>>
|
||||
}
|
||||
|
||||
internal sealed class TowerData {
|
||||
object Empty : TowerData()
|
||||
class OnlyImplicitReceiver(val implicitReceiver: ReceiverValue): TowerData()
|
||||
class TowerLevel(val level: ScopeTowerLevel) : TowerData()
|
||||
class BothTowerLevelAndImplicitReceiver(val level: ScopeTowerLevel, val implicitReceiver: ReceiverValue) : TowerData()
|
||||
}
|
||||
|
||||
internal interface ScopeTowerProcessor<C> {
|
||||
|
||||
fun processTowerLevel(level: ScopeTowerLevel)
|
||||
fun processImplicitReceiver(implicitReceiver: ReceiverValue)
|
||||
|
||||
// Candidates with matched receivers (dispatch receiver was already matched in ScopeTowerLevel)
|
||||
// Candidates in one groups have same priority, first group has highest priority.
|
||||
fun getCandidatesGroups(): List<Collection<C>>
|
||||
fun process(data: TowerData): List<Collection<C>>
|
||||
}
|
||||
|
||||
class TowerResolver {
|
||||
@@ -60,13 +63,12 @@ class TowerResolver {
|
||||
|
||||
val resultCollector = ResultCollector<C> { context.getStatus(it) }
|
||||
|
||||
fun collectCandidates(action: ScopeTowerProcessor<C>.() -> Unit): Collection<C>? {
|
||||
processor.action()
|
||||
fun collectCandidates(data: TowerData): Collection<C>? {
|
||||
val candidatesGroups = if (useOrder) {
|
||||
processor.getCandidatesGroups()
|
||||
processor.process(data)
|
||||
}
|
||||
else {
|
||||
listOf(processor.getCandidatesGroups().flatMap { it })
|
||||
listOf(processor.process(data).flatMap { it })
|
||||
}
|
||||
|
||||
for (candidatesGroup in candidatesGroups) {
|
||||
@@ -77,13 +79,16 @@ class TowerResolver {
|
||||
}
|
||||
|
||||
// possible there is explicit member
|
||||
collectCandidates { /* do nothing */ }?.let { return it }
|
||||
collectCandidates(TowerData.Empty)?.let { return it }
|
||||
for (implicitReceiver in context.scopeTower.implicitReceivers) {
|
||||
collectCandidates(TowerData.OnlyImplicitReceiver(implicitReceiver))?.let { return it }
|
||||
}
|
||||
|
||||
for (level in context.scopeTower.levels) {
|
||||
collectCandidates { processTowerLevel(level) }?.let { return it }
|
||||
collectCandidates(TowerData.TowerLevel(level))?.let { return it }
|
||||
|
||||
for (implicitReceiver in context.scopeTower.implicitReceivers) {
|
||||
collectCandidates { processImplicitReceiver(implicitReceiver) }?.let { return it }
|
||||
collectCandidates(TowerData.BothTowerLevelAndImplicitReceiver(level, implicitReceiver))?.let { return it }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user