Refactor ScopeTowerProcessor

This commit is contained in:
Stanislav Erokhin
2015-11-27 04:26:35 +03:00
parent bc49825f55
commit 5edadfe8ea
3 changed files with 85 additions and 140 deletions
@@ -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()
}
}
@@ -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 }
}
}