All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jetbrains.kotlin.resolve.calls.tower.InvokeProcessors.kt Maven / Gradle / Ivy

There is a newer version: 2.0.0
Show newest version
/*
 * 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.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.VariableDescriptor
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,
        private val variableProcessor: ScopeTowerProcessor
) : ScopeTowerProcessor {
    // todo optimize it
    private val previousData = ArrayList()
    private val invokeProcessors: MutableList> = ArrayList()

    private inner class VariableInvokeProcessor(val variableCandidate: C): ScopeTowerProcessor {
        val invokeProcessor: ScopeTowerProcessor = createInvokeProcessor(variableCandidate)

        override fun process(data: TowerData)
                = invokeProcessor.process(data).map { candidateGroup ->
                    candidateGroup.map { factoryProviderForInvoke.transformCandidate(variableCandidate, it) }
                }
    }

    protected abstract fun createInvokeProcessor(variableCandidate: C): ScopeTowerProcessor

    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 {
                it.isSuccessful
            }

            if (successfulVariables.isNotEmpty()) {
                val variableProcessors = successfulVariables.map { VariableInvokeProcessor(it) }
                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 KnownResultProcessor(emptyList())
        return ExplicitReceiverScopeTowerProcessor(scopeTower, invokeContext, variableReceiver) { getFunctions(OperatorNameConventions.INVOKE, it) }
    }
}

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 KnownResultProcessor(emptyList())
        val invokeDescriptor = scopeTower.getExtensionInvokeCandidateDescriptor(variableReceiver)
                               ?: return KnownResultProcessor(emptyList())
        return InvokeExtensionScopeTowerProcessor(invokeContext, invokeDescriptor, explicitReceiver)
    }
}

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()
    }
}

// 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 CandidateWithBoundDispatchReceiverImpl(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) {
        if (invokeExtensionDescriptor == null) {
            // case 1.(foo())(), where foo() isn't extension function
            return KnownResultProcessor(emptyList())
        }
        else {
            return InvokeExtensionScopeTowerProcessor(functionContext, invokeExtensionDescriptor, explicitReceiver = explicitReceiver)
        }
    }
    else {
        val usualInvoke = ExplicitReceiverScopeTowerProcessor(scopeTower, functionContext, expressionForInvoke) { getFunctions(OperatorNameConventions.INVOKE, it) } // todo operator

        if (invokeExtensionDescriptor == null) {
            return usualInvoke
        }
        else {
            return CompositeScopeTowerProcessor(
                    usualInvoke,
                    InvokeExtensionScopeTowerProcessor(functionContext, invokeExtensionDescriptor, explicitReceiver = null)
            )
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy