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.
/*
* 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.builtins.isBuiltinExtensionFunctionalType
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
import org.jetbrains.kotlin.resolve.calls.tasks.createSynthesizedInvokes
import org.jetbrains.kotlin.resolve.scopes.receivers.DetailedReceiver
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValueWithSmartCastInfo
import org.jetbrains.kotlin.util.OperatorNameConventions
import java.util.*
abstract class AbstractInvokeTowerProcessor(
protected val factoryProviderForInvoke: CandidateFactoryProviderForInvoke,
protected val variableProcessor: ScopeTowerProcessor
) : ScopeTowerProcessor {
// todo optimize it
private val previousData = ArrayList()
private val invokeProcessors: MutableList> = ArrayList()
protected fun hasInvokeProcessors() = invokeProcessors.isNotEmpty()
private inner class VariableInvokeProcessor(
var variableCandidate: C,
val invokeProcessor: ScopeTowerProcessor
) : ScopeTowerProcessor {
override fun process(data: TowerData) = invokeProcessor.process(data).map { candidateGroup ->
candidateGroup.map { factoryProviderForInvoke.transformCandidate(variableCandidate, it) }
}
override fun recordLookups(skippedData: Collection, name: Name) {
invokeProcessor.recordLookups(skippedData, name)
}
}
private fun createVariableInvokeProcessor(variableCandidate: C): VariableInvokeProcessor? =
createInvokeProcessor(variableCandidate)?.let { VariableInvokeProcessor(variableCandidate, it) }
protected abstract fun createInvokeProcessor(variableCandidate: C): ScopeTowerProcessor?
protected abstract fun mayDataBeApplicable(data: TowerData): Boolean
override fun process(data: TowerData): List> {
val candidateGroups = ArrayList>(0)
if (mayDataBeApplicable(data)) {
previousData.add(data)
for (processorsGroup in invokeProcessors) {
candidateGroups.addAll(processorsGroup.processVariableGroup(data))
}
}
for (variableCandidates in variableProcessor.process(data)) {
val variableProcessors = variableCandidates.mapNotNull {
if (it.isSuccessful) createVariableInvokeProcessor(it) else null
}
if (variableProcessors.isNotEmpty()) {
invokeProcessors.add(variableProcessors)
for (oldData in previousData) {
candidateGroups.addAll(variableProcessors.processVariableGroup(oldData))
}
}
}
return candidateGroups
}
private fun Collection.processVariableGroup(data: TowerData): List> {
return when (size) {
0 -> emptyList()
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.process(data).flatten() })
}
}
}
// todo KT-9522 Allow invoke convention for synthetic property
class InvokeTowerProcessor(
val scopeTower: ImplicitScopeTower,
val name: Name,
factoryProviderForInvoke: CandidateFactoryProviderForInvoke,
explicitReceiver: DetailedReceiver?
) : AbstractInvokeTowerProcessor(
factoryProviderForInvoke,
createVariableAndObjectProcessor(
scopeTower,
name,
factoryProviderForInvoke.factoryForVariable(stripExplicitReceiver = false),
explicitReceiver
)
) {
// todo filter by operator
override fun createInvokeProcessor(variableCandidate: C): ScopeTowerProcessor? {
val (variableReceiver, invokeContext) = factoryProviderForInvoke.factoryForInvoke(variableCandidate, useExplicitReceiver = false)
?: return null
return ExplicitReceiverScopeTowerProcessor(
scopeTower,
invokeContext,
variableReceiver
) { getFunctions(OperatorNameConventions.INVOKE, it) }
}
override fun mayDataBeApplicable(data: TowerData) =
data == TowerData.Empty || data is TowerData.TowerLevel
override fun recordLookups(skippedData: Collection, name: Name) {
variableProcessor.recordLookups(skippedData, name)
if (!hasInvokeProcessors()) return
skippedData.forEach {
if (it is TowerData.TowerLevel) {
it.level.recordLookup(OperatorNameConventions.INVOKE)
}
}
}
}
class InvokeExtensionTowerProcessor(
val scopeTower: ImplicitScopeTower,
val name: Name,
factoryProviderForInvoke: CandidateFactoryProviderForInvoke,
private val explicitReceiver: ReceiverValueWithSmartCastInfo?
) : AbstractInvokeTowerProcessor(
factoryProviderForInvoke,
createVariableAndObjectProcessor(
scopeTower,
name,
factoryProviderForInvoke.factoryForVariable(stripExplicitReceiver = true),
explicitReceiver = null
)
) {
override fun createInvokeProcessor(variableCandidate: C): ScopeTowerProcessor? {
val (variableReceiver, invokeContext) = factoryProviderForInvoke.factoryForInvoke(variableCandidate, useExplicitReceiver = true)
?: return null
val invokeDescriptor = scopeTower.getExtensionInvokeCandidateDescriptor(variableReceiver)
?: return null
return InvokeExtensionScopeTowerProcessor(invokeContext, invokeDescriptor, explicitReceiver)
}
override fun mayDataBeApplicable(data: TowerData): Boolean = data == TowerData.Empty || data is TowerData.OnlyImplicitReceiver
override fun recordLookups(skippedData: Collection, name: Name) {
variableProcessor.recordLookups(skippedData, name)
}
}
private class InvokeExtensionScopeTowerProcessor(
context: CandidateFactory,
private val invokeCandidateDescriptor: CandidateWithBoundDispatchReceiver,
private val explicitReceiver: ReceiverValueWithSmartCastInfo?
) : AbstractSimpleScopeTowerProcessor(context) {
override fun simpleProcess(data: TowerData): Collection {
if (explicitReceiver != null && data == TowerData.Empty) {
return listOf(
candidateFactory.createCandidate(
invokeCandidateDescriptor,
ExplicitReceiverKind.BOTH_RECEIVERS,
explicitReceiver
)
)
}
if (explicitReceiver == null && data is TowerData.OnlyImplicitReceiver) {
return listOf(
candidateFactory.createCandidate(
invokeCandidateDescriptor,
ExplicitReceiverKind.DISPATCH_RECEIVER,
data.implicitReceiver
)
)
}
return emptyList()
}
// No lookups happen in `simpleProcess`
override fun recordLookups(skippedData: Collection, name: Name) {}
}
// todo debug info
private fun ImplicitScopeTower.getExtensionInvokeCandidateDescriptor(
extensionFunctionReceiver: ReceiverValueWithSmartCastInfo
): CandidateWithBoundDispatchReceiver? {
val type = extensionFunctionReceiver.receiverValue.type
if (!type.isBuiltinExtensionFunctionalType) return null // todo: missing smart cast?
val invokeDescriptor = type.memberScope.getContributedFunctions(OperatorNameConventions.INVOKE, location).single()
val synthesizedInvokes = createSynthesizedInvokes(listOf(invokeDescriptor))
val synthesizedInvoke = synthesizedInvokes.singleOrNull()
?: error("No single synthesized invoke for $invokeDescriptor: $synthesizedInvokes")
// here we don't add SynthesizedDescriptor diagnostic because it should has priority as member
return CandidateWithBoundDispatchReceiver(extensionFunctionReceiver, synthesizedInvoke, listOf())
}
// case 1.(foo())() or (foo())()
fun createCallTowerProcessorForExplicitInvoke(
scopeTower: ImplicitScopeTower,
functionContext: CandidateFactory,
expressionForInvoke: ReceiverValueWithSmartCastInfo,
explicitReceiver: ReceiverValueWithSmartCastInfo?
): ScopeTowerProcessor {
val invokeExtensionDescriptor = scopeTower.getExtensionInvokeCandidateDescriptor(expressionForInvoke)
if (explicitReceiver != null) {
return if (invokeExtensionDescriptor == null) {
// case 1.(foo())(), where foo() isn't extension function
KnownResultProcessor(emptyList())
} else {
InvokeExtensionScopeTowerProcessor(functionContext, invokeExtensionDescriptor, explicitReceiver = explicitReceiver)
}
} else {
val usualInvoke = ExplicitReceiverScopeTowerProcessor(
scopeTower,
functionContext,
expressionForInvoke
) { getFunctions(OperatorNameConventions.INVOKE, it) } // todo operator
return if (invokeExtensionDescriptor == null) {
usualInvoke
} else {
PrioritizedCompositeScopeTowerProcessor(
usualInvoke,
InvokeExtensionScopeTowerProcessor(functionContext, invokeExtensionDescriptor, explicitReceiver = null)
)
}
}
}