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() = if (data == TowerData.Empty) listOfNotNull(result.takeIf { it.isNotEmpty() }) else emptyList()
} }
// use this if processors priority is important
class CompositeScopeTowerProcessor<out C>( class CompositeScopeTowerProcessor<out C>(
vararg val processors: ScopeTowerProcessor<C> vararg val processors: ScopeTowerProcessor<C>
) : ScopeTowerProcessor<C> { ) : ScopeTowerProcessor<C> {
override fun process(data: TowerData): List<Collection<C>> = processors.flatMap { it.process(data) } 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>( internal abstract class AbstractSimpleScopeTowerProcessor<C: Candidate>(
val candidateFactory: CandidateFactory<C> val candidateFactory: CandidateFactory<C>
) : ScopeTowerProcessor<C> { ) : SimpleScopeTowerProcessor<C>
protected abstract fun simpleProcess(data: TowerData): Collection<C>
override fun process(data: TowerData): List<Collection<C>> = listOfNotNull(simpleProcess(data).takeIf { it.isNotEmpty() })
}
private typealias CandidatesCollector = private typealias CandidatesCollector =
ScopeTowerLevel.(extensionReceiver: ReceiverValueWithSmartCastInfo?) -> Collection<CandidateWithBoundDispatchReceiver> 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( private fun <C : Candidate> createSimpleProcessor(
scopeTower: ImplicitScopeTower, scopeTower: ImplicitScopeTower,
context: CandidateFactory<C>, context: CandidateFactory<C>,
@@ -168,28 +188,23 @@ private fun <C : Candidate> createSimpleProcessor(
classValueReceiver: Boolean, classValueReceiver: Boolean,
collectCandidates: CandidatesCollector collectCandidates: CandidatesCollector
) : ScopeTowerProcessor<C> { ) : ScopeTowerProcessor<C> {
return when (explicitReceiver) { val withoutClassValueProcessor = createSimpleProcessorWithoutClassValueReceiver(scopeTower, context, explicitReceiver, collectCandidates)
is ReceiverValueWithSmartCastInfo -> {
ExplicitReceiverScopeTowerProcessor(scopeTower, context, explicitReceiver, collectCandidates)
}
is QualifierReceiver -> {
val qualifierProcessor = QualifierScopeTowerProcessor(scopeTower, context, explicitReceiver, collectCandidates)
if (!classValueReceiver) return qualifierProcessor
// todo enum entry, object. if (classValueReceiver && explicitReceiver is QualifierReceiver) {
val classValue = explicitReceiver.classValueReceiverWithSmartCastInfo ?: return qualifierProcessor val classValue = explicitReceiver.classValueReceiverWithSmartCastInfo ?: return withoutClassValueProcessor
CompositeScopeTowerProcessor( return CompositeScopeTowerProcessor(
qualifierProcessor, withoutClassValueProcessor,
ExplicitReceiverScopeTowerProcessor(scopeTower, context, classValue, collectCandidates) ExplicitReceiverScopeTowerProcessor(scopeTower, context, classValue, collectCandidates)
) )
}
else -> {
assert(explicitReceiver == null) {
"Illegal explicit receiver: $explicitReceiver(${explicitReceiver!!::class.java.simpleName})"
}
NoExplicitReceiverScopeTowerProcessor(context, 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, fun <C : Candidate> createVariableProcessor(scopeTower: ImplicitScopeTower, name: Name,
@@ -64,6 +64,12 @@ interface ScopeTowerProcessor<out C> {
fun process(data: TowerData): List<Collection<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 { class TowerResolver {
fun <C: Candidate> runResolve( fun <C: Candidate> runResolve(
scopeTower: ImplicitScopeTower, scopeTower: ImplicitScopeTower,