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

org.jetbrains.kotlin.fir.resolve.calls.TowerDataConsumers.kt Maven / Gradle / Ivy

/*
 * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
 * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
 */

package org.jetbrains.kotlin.fir.resolve.calls

import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.resolve.constructClassType
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.fir.types.ConeClassType
import org.jetbrains.kotlin.fir.types.ConeStarProjection
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
import org.jetbrains.kotlin.types.AbstractTypeChecker

abstract class TowerDataConsumer {
    abstract fun consume(
        kind: TowerDataKind,
        towerScopeLevel: TowerScopeLevel,
//        resultCollector: CandidateCollector,
        group: Int
    ): ProcessorAction

    private var stopGroup = Int.MAX_VALUE
    fun skipGroup(group: Int, resultCollector: CandidateCollector): Boolean {
        if (resultCollector.isSuccess() && stopGroup == Int.MAX_VALUE) {
            stopGroup = group
        }
        if (group >= stopGroup) return true
        return false
    }
}

class QualifiedReceiverTowerDataConsumer>(
    val session: FirSession,
    val name: Name,
    val token: TowerScopeLevel.Token,
    val explicitReceiver: ExpressionReceiverValue,
    val candidateFactory: CandidateFactory,
    val resultCollector: CandidateCollector
) : TowerDataConsumer() {
    override fun consume(
        kind: TowerDataKind,
        towerScopeLevel: TowerScopeLevel,
        group: Int
    ): ProcessorAction {
        if (skipGroup(group, resultCollector)) return ProcessorAction.NEXT
        if (kind != TowerDataKind.EMPTY) return ProcessorAction.NEXT

        return QualifiedReceiverTowerLevel(session, candidateFactory.bodyResolveComponents).processElementsByName(
            token,
            name,
            explicitReceiver,
            processor = TowerLevelProcessorImpl(group)
        )
    }

    private inner class TowerLevelProcessorImpl(val group: Int) : TowerScopeLevel.TowerScopeLevelProcessor {
        override fun consumeCandidate(
            symbol: T,
            dispatchReceiverValue: ClassDispatchReceiverValue?,
            implicitExtensionReceiverValue: ImplicitReceiverValue<*>?
        ): ProcessorAction {
            assert(dispatchReceiverValue == null)
            resultCollector.consumeCandidate(
                group,
                candidateFactory.createCandidate(
                    symbol,
                    dispatchReceiverValue = null,
                    implicitExtensionReceiverValue = null,
                    explicitReceiverKind = ExplicitReceiverKind.NO_EXPLICIT_RECEIVER
                )
            )
            return ProcessorAction.NEXT
        }
    }

}

class PrioritizedTowerDataConsumer(
    val resultCollector: CandidateCollector,
    vararg val consumers: TowerDataConsumer
) : TowerDataConsumer() {
    override fun consume(
        kind: TowerDataKind,
        towerScopeLevel: TowerScopeLevel,
        group: Int
    ): ProcessorAction {
        if (skipGroup(group, resultCollector)) return ProcessorAction.NEXT
        for ((index, consumer) in consumers.withIndex()) {
            val action = consumer.consume(kind, towerScopeLevel, group * consumers.size + index)
            if (action.stop()) {
                return ProcessorAction.STOP
            }
        }
        return ProcessorAction.NEXT
    }
}

// Yet is used exclusively for invokes:
// - initialConsumer consumes property which is invoke receiver
// - additionalConsumers consume invoke calls themselves
class AccumulatingTowerDataConsumer(
    private val resultCollector: CandidateCollector
) : TowerDataConsumer() {
    lateinit var initialConsumer: TowerDataConsumer
    private val additionalConsumers = mutableListOf()

    private data class TowerData(val kind: TowerDataKind, val level: TowerScopeLevel, val group: Int)

    private val accumulatedTowerData = mutableListOf()

    override fun consume(
        kind: TowerDataKind,
        towerScopeLevel: TowerScopeLevel,
        group: Int
    ): ProcessorAction {
        if (skipGroup(group, resultCollector)) return ProcessorAction.NEXT
        accumulatedTowerData += TowerData(kind, towerScopeLevel, group)

        if (initialConsumer.consume(kind, towerScopeLevel, group).stop()) {
            return ProcessorAction.STOP
        }
        for (consumer in additionalConsumers) {
            val action = consumer.consume(kind, towerScopeLevel, group)
            if (action.stop()) {
                return ProcessorAction.STOP
            }
        }
        return ProcessorAction.NEXT
    }

    fun addConsumer(consumer: TowerDataConsumer): ProcessorAction {
        additionalConsumers += consumer
        for ((kind, level, group) in accumulatedTowerData) {
            if (consumer.consume(kind, level, group).stop()) {
                return ProcessorAction.STOP
            }
        }
        return ProcessorAction.NEXT
    }
}

class ExplicitReceiverTowerDataConsumer>(
    val session: FirSession,
    val name: Name,
    val token: TowerScopeLevel.Token,
    val explicitReceiver: ExpressionReceiverValue,
    val candidateFactory: CandidateFactory,
    val resultCollector: CandidateCollector
) : TowerDataConsumer() {

    companion object {
        val defaultPackage = Name.identifier("kotlin")
    }

    override fun consume(
        kind: TowerDataKind,
        towerScopeLevel: TowerScopeLevel,
        group: Int
    ): ProcessorAction {
        if (skipGroup(group, resultCollector)) return ProcessorAction.NEXT
        return when (kind) {
            TowerDataKind.EMPTY ->
                MemberScopeTowerLevel(session, explicitReceiver, scopeSession = candidateFactory.bodyResolveComponents.scopeSession)
                    .processElementsByName(
                        token,
                        name,
                        explicitReceiver = null,
                        processor = EmptyKindTowerProcessor(group)
                    )
            TowerDataKind.TOWER_LEVEL -> {
                if (token == TowerScopeLevel.Token.Objects) return ProcessorAction.NEXT
                towerScopeLevel.processElementsByName(
                    token,
                    name,
                    explicitReceiver = explicitReceiver,
                    processor = TowerLevelKindTowerProcessor(group)
                )
            }
        }
    }


    private inner class EmptyKindTowerProcessor(val group: Int) : TowerScopeLevel.TowerScopeLevelProcessor {
        override fun consumeCandidate(
            symbol: T,
            dispatchReceiverValue: ClassDispatchReceiverValue?,
            implicitExtensionReceiverValue: ImplicitReceiverValue<*>?
        ): ProcessorAction {
            resultCollector.consumeCandidate(
                group,
                candidateFactory.createCandidate(
                    symbol,
                    dispatchReceiverValue,
                    implicitExtensionReceiverValue,
                    ExplicitReceiverKind.DISPATCH_RECEIVER
                )
            )
            return ProcessorAction.NEXT
        }
    }

    private inner class TowerLevelKindTowerProcessor(val group: Int) : TowerScopeLevel.TowerScopeLevelProcessor {
        override fun consumeCandidate(
            symbol: T,
            dispatchReceiverValue: ClassDispatchReceiverValue?,
            implicitExtensionReceiverValue: ImplicitReceiverValue<*>?
        ): ProcessorAction {
            if (symbol is FirNamedFunctionSymbol && symbol.callableId.packageName.startsWith(defaultPackage)) {
                val explicitReceiverType = explicitReceiver.type
                if (dispatchReceiverValue == null && explicitReceiverType is ConeClassType) {
                    val declarationReceiverTypeRef =
                        (symbol as? FirCallableSymbol<*>)?.fir?.receiverTypeRef as? FirResolvedTypeRef
                    val declarationReceiverType = declarationReceiverTypeRef?.type
                    if (declarationReceiverType is ConeClassType) {
                        if (!AbstractTypeChecker.isSubtypeOf(
                                candidateFactory.bodyResolveComponents.inferenceComponents.ctx,
                                explicitReceiverType,
                                declarationReceiverType.lookupTag.constructClassType(
                                    declarationReceiverType.typeArguments.map { ConeStarProjection }.toTypedArray(),
                                    isNullable = true
                                )
                            )
                        ) {
                            return ProcessorAction.NEXT
                        }
                    }
                }
            }
            val candidate = candidateFactory.createCandidate(
                symbol,
                dispatchReceiverValue,
                implicitExtensionReceiverValue,
                ExplicitReceiverKind.EXTENSION_RECEIVER
            )

            resultCollector.consumeCandidate(
                group,
                candidate
            )
            return ProcessorAction.NEXT
        }
    }
}

class NoExplicitReceiverTowerDataConsumer>(
    val session: FirSession,
    val name: Name,
    val token: TowerScopeLevel.Token,
    val candidateFactory: CandidateFactory,
    val resultCollector: CandidateCollector
) : TowerDataConsumer() {
    override fun consume(
        kind: TowerDataKind,
        towerScopeLevel: TowerScopeLevel,
        group: Int
    ): ProcessorAction {
        if (skipGroup(group, resultCollector)) return ProcessorAction.NEXT
        return when (kind) {

            TowerDataKind.TOWER_LEVEL -> {
                towerScopeLevel.processElementsByName(
                    token,
                    name,
                    explicitReceiver = null,
                    processor = TowerLevelProcessorImpl(group)
                )
            }
            else -> ProcessorAction.NEXT
        }
    }

    private inner class TowerLevelProcessorImpl(val group: Int) : TowerScopeLevel.TowerScopeLevelProcessor {
        override fun consumeCandidate(
            symbol: T,
            dispatchReceiverValue: ClassDispatchReceiverValue?,
            implicitExtensionReceiverValue: ImplicitReceiverValue<*>?
        ): ProcessorAction {
            resultCollector.consumeCandidate(
                group,
                candidateFactory.createCandidate(
                    symbol,
                    dispatchReceiverValue,
                    implicitExtensionReceiverValue,
                    ExplicitReceiverKind.NO_EXPLICIT_RECEIVER
                )
            )
            return ProcessorAction.NEXT
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy