Add way to create callable reference processor

Priority of variables and function should be the same.
Because of this we create new CompositeSimpleScopeTowerProcessor,
which merge candidates for properties and function into one candidate group
This commit is contained in:
Stanislav Erokhin
2017-05-08 12:49:00 +03:00
committed by Mikhail Zarechenskiy
parent 36ea9484a9
commit 02f4558683
2 changed files with 47 additions and 26 deletions
@@ -31,20 +31,23 @@ class KnownResultProcessor<out C>(
= if (data == TowerData.Empty) listOfNotNull(result.takeIf { it.isNotEmpty() }) else emptyList()
}
// use this if processors priority is important
class CompositeScopeTowerProcessor<out C>(
vararg val processors: ScopeTowerProcessor<C>
) : ScopeTowerProcessor<C> {
override fun process(data: TowerData): List<Collection<C>> = processors.flatMap { it.process(data) }
}
// use this if all processors has same priority
class CompositeSimpleScopeTowerProcessor<C : Candidate>(
private vararg val processors: SimpleScopeTowerProcessor<C>
): SimpleScopeTowerProcessor<C> {
override fun simpleProcess(data: TowerData): Collection<C> = processors.flatMap { it.simpleProcess(data) }
}
internal abstract class AbstractSimpleScopeTowerProcessor<C: Candidate>(
val candidateFactory: CandidateFactory<C>
) : ScopeTowerProcessor<C> {
protected abstract fun simpleProcess(data: TowerData): Collection<C>
override fun process(data: TowerData): List<Collection<C>> = listOfNotNull(simpleProcess(data).takeIf { it.isNotEmpty() })
}
) : SimpleScopeTowerProcessor<C>
private typealias CandidatesCollector =
ScopeTowerLevel.(extensionReceiver: ReceiverValueWithSmartCastInfo?) -> Collection<CandidateWithBoundDispatchReceiver>
@@ -161,6 +164,23 @@ private fun <D : CallableDescriptor, C : Candidate> processCommonAndSyntheticMem
}
}
private fun <C : Candidate> createSimpleProcessorWithoutClassValueReceiver(
scopeTower: ImplicitScopeTower,
context: CandidateFactory<C>,
explicitReceiver: DetailedReceiver?,
collectCandidates: CandidatesCollector
): SimpleScopeTowerProcessor<C> =
when (explicitReceiver) {
is ReceiverValueWithSmartCastInfo -> ExplicitReceiverScopeTowerProcessor(scopeTower, context, explicitReceiver, collectCandidates)
is QualifierReceiver -> QualifierScopeTowerProcessor(scopeTower, context, explicitReceiver, collectCandidates)
else -> {
assert(explicitReceiver == null) {
"Illegal explicit receiver: $explicitReceiver(${explicitReceiver!!::class.java.simpleName})"
}
NoExplicitReceiverScopeTowerProcessor(context, collectCandidates)
}
}
private fun <C : Candidate> createSimpleProcessor(
scopeTower: ImplicitScopeTower,
context: CandidateFactory<C>,
@@ -168,28 +188,23 @@ private fun <C : Candidate> createSimpleProcessor(
classValueReceiver: Boolean,
collectCandidates: CandidatesCollector
) : ScopeTowerProcessor<C> {
return when (explicitReceiver) {
is ReceiverValueWithSmartCastInfo -> {
ExplicitReceiverScopeTowerProcessor(scopeTower, context, explicitReceiver, collectCandidates)
}
is QualifierReceiver -> {
val qualifierProcessor = QualifierScopeTowerProcessor(scopeTower, context, explicitReceiver, collectCandidates)
if (!classValueReceiver) return qualifierProcessor
val withoutClassValueProcessor = createSimpleProcessorWithoutClassValueReceiver(scopeTower, context, explicitReceiver, collectCandidates)
// todo enum entry, object.
val classValue = explicitReceiver.classValueReceiverWithSmartCastInfo ?: return qualifierProcessor
CompositeScopeTowerProcessor(
qualifierProcessor,
ExplicitReceiverScopeTowerProcessor(scopeTower, context, classValue, collectCandidates)
)
}
else -> {
assert(explicitReceiver == null) {
"Illegal explicit receiver: $explicitReceiver(${explicitReceiver!!::class.java.simpleName})"
}
NoExplicitReceiverScopeTowerProcessor(context, collectCandidates)
}
if (classValueReceiver && explicitReceiver is QualifierReceiver) {
val classValue = explicitReceiver.classValueReceiverWithSmartCastInfo ?: return withoutClassValueProcessor
return CompositeScopeTowerProcessor(
withoutClassValueProcessor,
ExplicitReceiverScopeTowerProcessor(scopeTower, context, classValue, collectCandidates)
)
}
return withoutClassValueProcessor
}
fun <C : Candidate> createCallableReferenceProcessor(scopeTower: ImplicitScopeTower, name: Name, context: CandidateFactory<C>,
explicitReceiver: DetailedReceiver?): SimpleScopeTowerProcessor<C> {
val variable = createSimpleProcessorWithoutClassValueReceiver(scopeTower, context, explicitReceiver) { getVariables(name, it) }
val function = createSimpleProcessorWithoutClassValueReceiver(scopeTower, context, explicitReceiver) { getFunctions(name, it) }
return CompositeSimpleScopeTowerProcessor(variable, function)
}
fun <C : Candidate> createVariableProcessor(scopeTower: ImplicitScopeTower, name: Name,
@@ -64,6 +64,12 @@ interface ScopeTowerProcessor<out C> {
fun process(data: TowerData): List<Collection<C>>
}
interface SimpleScopeTowerProcessor<out C> : ScopeTowerProcessor<C> {
fun simpleProcess(data: TowerData): Collection<C>
override fun process(data: TowerData): List<Collection<C>> = listOfNotNull(simpleProcess(data).takeIf { it.isNotEmpty() })
}
class TowerResolver {
fun <C: Candidate> runResolve(
scopeTower: ImplicitScopeTower,