From 5edadfe8ea36ab437dfcf869851cdb19804fc047 Mon Sep 17 00:00:00 2001 From: Stanislav Erokhin Date: Fri, 27 Nov 2015 04:26:35 +0300 Subject: [PATCH] Refactor ScopeTowerProcessor --- .../resolve/calls/tower/InvokeProcessors.kt | 102 +++++++----------- .../calls/tower/ScopeTowerProcessors.kt | 94 ++++++---------- .../resolve/calls/tower/TowerResolver.kt | 29 ++--- 3 files changed, 85 insertions(+), 140 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/InvokeProcessors.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/InvokeProcessors.kt index c76e2877b3e..c7e4f147d21 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/InvokeProcessors.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/InvokeProcessors.kt @@ -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( private val variableProcessor: ScopeTowerProcessor ) : ScopeTowerProcessor { // todo optimize it - private val previousActions = ArrayList.() -> Unit>() - private val candidateGroups: MutableList> = ArrayList() - + private val previousData = ArrayList() private val invokeProcessors: MutableList> = ArrayList() + private inner class VariableInvokeProcessor(val variableCandidate: C): ScopeTowerProcessor { + val invokeProcessor: ScopeTowerProcessor = createInvokeProcessor(variableCandidate) - private inner class VariableInvokeProcessor( - val variableCandidate: C, - val invokeProcessor: ScopeTowerProcessor = createInvokeProcessor(variableCandidate) - ): ScopeTowerProcessor by invokeProcessor { - override fun getCandidatesGroups(): List> - = 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 - private fun findVariablesAndCreateNewInvokeCandidates() { - for (variableCandidates in variableProcessor.getCandidatesGroups()) { + override fun process(data: TowerData): List> { + previousData.add(data) + + val candidateGroups = ArrayList>(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.collectCandidateGroups(): List> { + private fun Collection.processVariableGroup(data: TowerData): List> { 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.() -> 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> = SmartList(candidateGroups) } // todo KT-9522 Allow invoke convention for synthetic property @@ -135,33 +118,20 @@ internal class InvokeExtensionTowerProcessor( private class InvokeExtensionScopeTowerProcessor( context: TowerContext, - val invokeCandidateDescriptor: CandidateWithBoundDispatchReceiver, - val explicitReceiver: ReceiverValue? -) : AbstractScopeTowerProcessor(context) { - override var candidates: Collection = resolve(explicitReceiver) + private val invokeCandidateDescriptor: CandidateWithBoundDispatchReceiver, + private val explicitReceiver: ReceiverValue? +) : AbstractSimpleScopeTowerProcessor(context) { - private fun resolve(extensionReceiver: ReceiverValue?): Collection { - 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 { + 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() } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/ScopeTowerProcessors.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/ScopeTowerProcessors.kt index 4eb581cf15e..e1b9c088afb 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/ScopeTowerProcessors.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/ScopeTowerProcessors.kt @@ -26,56 +26,39 @@ import org.jetbrains.kotlin.utils.addToStdlib.check internal class KnownResultProcessor( - result: Collection + val result: Collection ): ScopeTowerProcessor { - 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( vararg val processors: ScopeTowerProcessor ) : ScopeTowerProcessor { - override fun processTowerLevel(level: ScopeTowerLevel) = processors.forEach { it.processTowerLevel(level) } - - override fun processImplicitReceiver(implicitReceiver: ReceiverValue) - = processors.forEach { it.processImplicitReceiver(implicitReceiver) } - - override fun getCandidatesGroups(): List> = processors.flatMap { it.getCandidatesGroups() } + override fun process(data: TowerData): List> = processors.flatMap { it.process(data) } } -internal abstract class AbstractScopeTowerProcessor( +internal abstract class AbstractSimpleScopeTowerProcessor( val context: TowerContext ) : ScopeTowerProcessor { protected val name: Name get() = context.name - protected abstract var candidates: Collection + protected abstract fun simpleProcess(data: TowerData): Collection - override fun getCandidatesGroups() = listOfNotNull(candidates.check { it.isNotEmpty() }) + override fun process(data: TowerData): List> = listOfNotNull(simpleProcess(data).check { it.isNotEmpty() }) } internal class ExplicitReceiverScopeTowerProcessor( context: TowerContext, val explicitReceiver: ReceiverValue, val collectCandidates: ScopeTowerLevel.(Name) -> Collection> -): AbstractScopeTowerProcessor(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(context) { + override fun simpleProcess(data: TowerData): Collection { + return when (data) { + TowerData.Empty -> resolveAsMember() + is TowerData.TowerLevel -> resolveAsExtension(data.level) + else -> emptyList() + } } private fun resolveAsMember(): Collection { @@ -95,20 +78,10 @@ private class QualifierScopeTowerProcessor( context: TowerContext, val qualifier: QualifierReceiver, val collectCandidates: ScopeTowerLevel.(Name) -> Collection> -): AbstractScopeTowerProcessor(context) { - override var candidates = resolve() +): AbstractSimpleScopeTowerProcessor(context) { + override fun simpleProcess(data: TowerData): Collection { + 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 { 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( private class NoExplicitReceiverScopeTowerProcessor( context: TowerContext, val collectCandidates: ScopeTowerLevel.(Name) -> Collection> -) : AbstractScopeTowerProcessor(context) { - override var candidates: Collection = emptyList() - - private var descriptorsRequestImplicitReceiver = emptyList>() - - 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(context) { + override fun simpleProcess(data: TowerData): Collection + = 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 createSimpleProcessor( diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/TowerResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/TowerResolver.kt index bb1f06973a5..80b416d0bd8 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/TowerResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/TowerResolver.kt @@ -41,14 +41,17 @@ interface TowerContext { fun contextForInvoke(variable: C, useExplicitReceiver: Boolean): Pair> } +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 { - - 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> + fun process(data: TowerData): List> } class TowerResolver { @@ -60,13 +63,12 @@ class TowerResolver { val resultCollector = ResultCollector { context.getStatus(it) } - fun collectCandidates(action: ScopeTowerProcessor.() -> Unit): Collection? { - processor.action() + fun collectCandidates(data: TowerData): Collection? { 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 } } }