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