Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.jetbrains.kotlin.resolve.calls.tower.ScopeTowerProcessors.kt Maven / Gradle / Ivy
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.resolve.calls.tower
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.calls.components.candidate.ResolutionCandidate
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject
import org.jetbrains.kotlin.resolve.scopes.receivers.DetailedReceiver
import org.jetbrains.kotlin.resolve.scopes.receivers.QualifierReceiver
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValueWithSmartCastInfo
class KnownResultProcessor(
val result: Collection
) : ScopeTowerProcessor {
override fun process(data: TowerData) = if (data == TowerData.Empty) listOfNotNull(result.takeIf { it.isNotEmpty() }) else emptyList()
override fun recordLookups(skippedData: Collection, name: Name) {}
}
// use this if processors priority is important
class PrioritizedCompositeScopeTowerProcessor(
vararg val processors: ScopeTowerProcessor
) : ScopeTowerProcessor {
override fun process(data: TowerData): List> = processors.flatMap { it.process(data) }
override fun recordLookups(skippedData: Collection, name: Name) {
processors.forEach { it.recordLookups(skippedData, name) }
}
}
class VariableAndObjectScopeTowerProcessor(
private val variableProcessor: ScopeTowerProcessor,
private val objectProcessor: ScopeTowerProcessor
) : ScopeTowerProcessor {
override fun process(data: TowerData): List> {
val variablesResult = variableProcessor.process(data)
val objectResult = objectProcessor.process(data)
if (objectResult.isEmpty()) return variablesResult
if (objectResult.none { level ->
level.any {
it.isEnumEntryCandidate()
}
}
) return variablesResult + objectResult
val result = mutableListOf>()
result.addAll(variablesResult.map { it.toMutableList() })
for ((index, objectLevel) in objectResult.withIndex()) {
val enumEntryLevel = objectLevel.filter { it.isEnumEntryCandidate() }
if (enumEntryLevel.isEmpty()) continue
if (index < variablesResult.size) {
// It's guaranteed this element is a mutable list
(result[index] as MutableList).addAll(enumEntryLevel)
} else {
result.add(enumEntryLevel)
}
}
for (objectLevel in objectResult) {
val nonEnumEntryLevel = objectLevel.filter { !it.isEnumEntryCandidate() }
if (nonEnumEntryLevel.isEmpty()) continue
result.add(nonEnumEntryLevel)
}
return result
}
private fun Candidate.isEnumEntryCandidate(): Boolean {
if (this !is ResolutionCandidate) return false
val callableDescriptor = resolvedCall.candidateDescriptor as? FakeCallableDescriptorForObject ?: return false
return callableDescriptor.classDescriptor.kind == ClassKind.ENUM_ENTRY
}
override fun recordLookups(skippedData: Collection, name: Name) {
variableProcessor.recordLookups(skippedData, name)
objectProcessor.recordLookups(skippedData, name)
}
}
// use this if all processors has same priority
class SamePriorityCompositeScopeTowerProcessor(
private vararg val processors: SimpleScopeTowerProcessor
) : SimpleScopeTowerProcessor {
override fun simpleProcess(data: TowerData): Collection = processors.flatMap { it.simpleProcess(data) }
override fun recordLookups(skippedData: Collection, name: Name) {
processors.forEach { it.recordLookups(skippedData, name) }
}
}
interface SimpleScopeTowerProcessor : ScopeTowerProcessor {
fun simpleProcess(data: TowerData): Collection
override fun process(data: TowerData): List> = listOfNotNull(simpleProcess(data).takeIf { it.isNotEmpty() })
}
internal abstract class AbstractSimpleScopeTowerProcessor(
val candidateFactory: CandidateFactory
) : SimpleScopeTowerProcessor {
fun createCandidates(
collector: Collection,
kind: ExplicitReceiverKind,
receiver: ReceiverValueWithSmartCastInfo?
) : Collection {
val result = mutableListOf()
for (candidate in collector) {
if (candidate.requiresExtensionReceiver == (receiver != null)) {
result.add(
candidateFactory.createCandidate(
candidate,
kind,
extensionReceiver = receiver
)
)
}
}
return result
}
}
private typealias CandidatesCollector =
ScopeTowerLevel.(extensionReceiver: ReceiverValueWithSmartCastInfo?) -> Collection
internal class ExplicitReceiverScopeTowerProcessor(
val scopeTower: ImplicitScopeTower,
context: CandidateFactory,
val explicitReceiver: ReceiverValueWithSmartCastInfo,
val collectCandidates: CandidatesCollector
) : AbstractSimpleScopeTowerProcessor(context) {
override fun simpleProcess(data: TowerData): Collection {
return when (data) {
TowerData.Empty -> createCandidates(
MemberScopeTowerLevel(scopeTower, explicitReceiver).collectCandidates(null),
ExplicitReceiverKind.DISPATCH_RECEIVER,
null
)
is TowerData.TowerLevel -> createCandidates(
data.level.collectCandidates(explicitReceiver),
ExplicitReceiverKind.EXTENSION_RECEIVER,
explicitReceiver
)
else -> emptyList()
}
}
override fun recordLookups(skippedData: Collection, name: Name) {
for (data in skippedData) {
if (data is TowerData.TowerLevel) {
data.level.recordLookup(name)
}
}
}
}
private class QualifierScopeTowerProcessor(
val scopeTower: ImplicitScopeTower,
context: CandidateFactory,
val qualifier: QualifierReceiver,
val collectCandidates: CandidatesCollector
) : AbstractSimpleScopeTowerProcessor(context) {
override fun simpleProcess(data: TowerData): Collection {
if (data != TowerData.Empty) return emptyList()
return createCandidates(
QualifierScopeTowerLevel(scopeTower, qualifier).collectCandidates(null),
ExplicitReceiverKind.NO_EXPLICIT_RECEIVER,
null
)
}
// QualifierScopeTowerProcessor works only with TowerData.Empty that should not be ignored
override fun recordLookups(skippedData: Collection, name: Name) {}
}
private class NoExplicitReceiverScopeTowerProcessor(
context: CandidateFactory,
val collectCandidates: CandidatesCollector
) : AbstractSimpleScopeTowerProcessor(context) {
override fun simpleProcess(data: TowerData): Collection = when (data) {
is TowerData.TowerLevel -> createCandidates(
data.level.collectCandidates(null),
ExplicitReceiverKind.NO_EXPLICIT_RECEIVER,
null
)
is TowerData.BothTowerLevelAndImplicitReceiver -> createCandidates(
data.level.collectCandidates(data.implicitReceiver),
ExplicitReceiverKind.NO_EXPLICIT_RECEIVER,
data.implicitReceiver
)
is TowerData.BothTowerLevelAndContextReceiversGroup -> {
val groupsOfDuplicateCandidates = data.contextReceiversGroup.flatMap { receiver ->
data.level.collectCandidates(receiver).map { it to receiver }
}.filter { (candidate, _) ->
candidate.requiresExtensionReceiver
}.groupBy { it.first.descriptor }.values
val candidateToReceivers = groupsOfDuplicateCandidates.map { l ->
val candidate = l.first().first
val receivers = l.map { it.second }
candidate to receivers
}
candidateToReceivers.map {
candidateFactory.createCandidate(
it.first,
ExplicitReceiverKind.NO_EXPLICIT_RECEIVER,
it.second
)
}
}
else -> emptyList()
}
override fun recordLookups(skippedData: Collection, name: Name) {
for (data in skippedData) {
when (data) {
is TowerData.TowerLevel -> data.level.recordLookup(name)
is TowerData.BothTowerLevelAndImplicitReceiver -> data.level.recordLookup(name)
is TowerData.BothTowerLevelAndContextReceiversGroup -> data.level.recordLookup(name)
is TowerData.ForLookupForNoExplicitReceiver -> data.level.recordLookup(name)
else -> {}
}
}
}
}
private fun createSimpleProcessorWithoutClassValueReceiver(
scopeTower: ImplicitScopeTower,
context: CandidateFactory,
explicitReceiver: DetailedReceiver?,
collectCandidates: CandidatesCollector
): SimpleScopeTowerProcessor =
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 createSimpleProcessor(
scopeTower: ImplicitScopeTower,
context: CandidateFactory,
explicitReceiver: DetailedReceiver?,
classValueReceiver: Boolean,
collectCandidates: CandidatesCollector
): ScopeTowerProcessor {
val withoutClassValueProcessor =
createSimpleProcessorWithoutClassValueReceiver(scopeTower, context, explicitReceiver, collectCandidates)
if (classValueReceiver && explicitReceiver is QualifierReceiver) {
val classValue = explicitReceiver.classValueReceiverWithSmartCastInfo ?: return withoutClassValueProcessor
return PrioritizedCompositeScopeTowerProcessor(
withoutClassValueProcessor,
ExplicitReceiverScopeTowerProcessor(scopeTower, context, classValue, collectCandidates)
)
}
return withoutClassValueProcessor
}
fun createCallableReferenceProcessor(
scopeTower: ImplicitScopeTower,
name: Name, context: CandidateFactory,
explicitReceiver: DetailedReceiver?
): SimpleScopeTowerProcessor {
val variable = createSimpleProcessorWithoutClassValueReceiver(scopeTower, context, explicitReceiver) { getVariables(name, it) }
val function = createSimpleProcessorWithoutClassValueReceiver(scopeTower, context, explicitReceiver) { getFunctions(name, it) }
return SamePriorityCompositeScopeTowerProcessor(variable, function)
}
fun createVariableProcessor(
scopeTower: ImplicitScopeTower, name: Name,
context: CandidateFactory, explicitReceiver: DetailedReceiver?, classValueReceiver: Boolean = true
) = createSimpleProcessor(scopeTower, context, explicitReceiver, classValueReceiver) { getVariables(name, it) }
fun createVariableAndObjectProcessor(
scopeTower: ImplicitScopeTower, name: Name,
context: CandidateFactory, explicitReceiver: DetailedReceiver?, classValueReceiver: Boolean = true
) = VariableAndObjectScopeTowerProcessor(
createVariableProcessor(scopeTower, name, context, explicitReceiver),
createSimpleProcessor(scopeTower, context, explicitReceiver, classValueReceiver) { getObjects(name, it) }
)
fun createSimpleFunctionProcessor(
scopeTower: ImplicitScopeTower, name: Name,
context: CandidateFactory, explicitReceiver: DetailedReceiver?, classValueReceiver: Boolean = true
) = createSimpleProcessor(scopeTower, context, explicitReceiver, classValueReceiver) { getFunctions(name, it) }
fun createFunctionProcessor(
scopeTower: ImplicitScopeTower,
name: Name,
simpleContext: CandidateFactory,
factoryProviderForInvoke: CandidateFactoryProviderForInvoke,
explicitReceiver: DetailedReceiver?
): PrioritizedCompositeScopeTowerProcessor {
// a.foo() -- simple function call
val simpleFunction = createSimpleFunctionProcessor(scopeTower, name, simpleContext, explicitReceiver)
// a.foo() -- property a.foo + foo.invoke()
val invokeProcessor = InvokeTowerProcessor(scopeTower, name, factoryProviderForInvoke, explicitReceiver)
// a.foo() -- property foo is extension function with receiver a -- a.invoke()
val invokeExtensionProcessor = createProcessorWithReceiverValueOrEmpty(explicitReceiver) {
InvokeExtensionTowerProcessor(scopeTower, name, factoryProviderForInvoke, it)
}
return PrioritizedCompositeScopeTowerProcessor(simpleFunction, invokeProcessor, invokeExtensionProcessor)
}
fun createProcessorWithReceiverValueOrEmpty(
explicitReceiver: DetailedReceiver?,
create: (ReceiverValueWithSmartCastInfo?) -> ScopeTowerProcessor
): ScopeTowerProcessor {
return if (explicitReceiver is QualifierReceiver) {
explicitReceiver.classValueReceiverWithSmartCastInfo?.let(create)
?: KnownResultProcessor(listOf())
} else {
create(explicitReceiver as ReceiverValueWithSmartCastInfo?)
}
}