FIR: Add CallKind
This commit is contained in:
@@ -7,13 +7,11 @@ package org.jetbrains.kotlin.fir.resolve.calls
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.fir.FirSession
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
|
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirFunction
|
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||||
import org.jetbrains.kotlin.fir.resolve.FirSymbolProvider
|
import org.jetbrains.kotlin.fir.resolve.FirSymbolProvider
|
||||||
import org.jetbrains.kotlin.fir.resolve.defaultType
|
import org.jetbrains.kotlin.fir.resolve.defaultType
|
||||||
import org.jetbrains.kotlin.fir.resolve.scope
|
import org.jetbrains.kotlin.fir.resolve.scope
|
||||||
import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculator
|
import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculator
|
||||||
import org.jetbrains.kotlin.fir.resolve.transformers.firUnsafe
|
|
||||||
import org.jetbrains.kotlin.fir.scopes.FirPosition
|
import org.jetbrains.kotlin.fir.scopes.FirPosition
|
||||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||||
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
|
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
|
||||||
@@ -21,11 +19,11 @@ import org.jetbrains.kotlin.fir.scopes.processClassifiersByNameWithAction
|
|||||||
import org.jetbrains.kotlin.fir.service
|
import org.jetbrains.kotlin.fir.service
|
||||||
import org.jetbrains.kotlin.fir.symbols.*
|
import org.jetbrains.kotlin.fir.symbols.*
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
|
|
||||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||||
import org.jetbrains.kotlin.fir.types.coneTypeUnsafe
|
import org.jetbrains.kotlin.fir.types.coneTypeUnsafe
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.cast
|
import org.jetbrains.kotlin.utils.addToStdlib.cast
|
||||||
|
|
||||||
|
|
||||||
@@ -49,25 +47,29 @@ class CheckerSinkImpl : CheckerSink {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private abstract class Checker {
|
|
||||||
abstract fun check(candidate: Candidate, sink: CheckerSink, callInfo: CallInfo)
|
|
||||||
|
|
||||||
}
|
class Candidate(
|
||||||
|
val symbol: ConeSymbol,
|
||||||
|
val receiverKind: ExplicitReceiverKind,
|
||||||
|
val callKind: CallKind
|
||||||
|
)
|
||||||
|
|
||||||
private object MapArguments : Checker() {
|
sealed class CallKind {
|
||||||
override fun check(candidate: Candidate, sink: CheckerSink, callInfo: CallInfo) {
|
abstract fun sequence(): List<ResolutionStage>
|
||||||
val symbol = candidate.symbol as? FirFunctionSymbol ?: return sink.reportApplicability(CandidateApplicability.HIDDEN)
|
object Function : CallKind() {
|
||||||
if (symbol.firUnsafe<FirFunction>().valueParameters.size != callInfo.argumentCount) {
|
override fun sequence(): List<ResolutionStage> {
|
||||||
return sink.reportApplicability(CandidateApplicability.PARAMETER_MAPPING_ERROR)
|
return functionCallResolutionSequence()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
object VariableAccess : CallKind() {
|
||||||
|
override fun sequence(): List<ResolutionStage> {
|
||||||
|
return qualifiedAccessResolutionSequence()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class Candidate(val symbol: ConeSymbol) {}
|
|
||||||
|
|
||||||
|
|
||||||
enum class TowerDataKind {
|
enum class TowerDataKind {
|
||||||
EMPTY,
|
EMPTY,
|
||||||
TOWER_LEVEL
|
TOWER_LEVEL
|
||||||
@@ -179,7 +181,7 @@ fun createVariableConsumer(
|
|||||||
explicitReceiver: FirExpression?,
|
explicitReceiver: FirExpression?,
|
||||||
explicitReceiverType: FirTypeRef?
|
explicitReceiverType: FirTypeRef?
|
||||||
): TowerDataConsumer {
|
): TowerDataConsumer {
|
||||||
return createSimpleConsumer(session, name, TowerScopeLevel.Token.Properties, explicitReceiver, explicitReceiverType)
|
return createSimpleConsumer(session, name, TowerScopeLevel.Token.Properties, explicitReceiver, explicitReceiverType, CallKind.VariableAccess)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createFunctionConsumer(
|
fun createFunctionConsumer(
|
||||||
@@ -188,7 +190,7 @@ fun createFunctionConsumer(
|
|||||||
explicitReceiver: FirExpression?,
|
explicitReceiver: FirExpression?,
|
||||||
explicitReceiverType: FirTypeRef?
|
explicitReceiverType: FirTypeRef?
|
||||||
): TowerDataConsumer {
|
): TowerDataConsumer {
|
||||||
return createSimpleConsumer(session, name, TowerScopeLevel.Token.Functions, explicitReceiver, explicitReceiverType)
|
return createSimpleConsumer(session, name, TowerScopeLevel.Token.Functions, explicitReceiver, explicitReceiverType, CallKind.Function)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -197,15 +199,16 @@ fun createSimpleConsumer(
|
|||||||
name: Name,
|
name: Name,
|
||||||
token: TowerScopeLevel.Token<*>,
|
token: TowerScopeLevel.Token<*>,
|
||||||
explicitReceiver: FirExpression?,
|
explicitReceiver: FirExpression?,
|
||||||
explicitReceiverType: FirTypeRef?
|
explicitReceiverType: FirTypeRef?,
|
||||||
|
callKind: CallKind
|
||||||
): TowerDataConsumer {
|
): TowerDataConsumer {
|
||||||
return if (explicitReceiver != null) {
|
return if (explicitReceiver != null) {
|
||||||
ExplicitReceiverTowerDataConsumer(session, name, token, object : ReceiverValueWithPossibleTypes {
|
ExplicitReceiverTowerDataConsumer(session, name, token, object : ReceiverValueWithPossibleTypes {
|
||||||
override val type: ConeKotlinType
|
override val type: ConeKotlinType
|
||||||
get() = explicitReceiverType!!.coneTypeUnsafe()
|
get() = explicitReceiverType!!.coneTypeUnsafe()
|
||||||
})
|
}, callKind)
|
||||||
} else {
|
} else {
|
||||||
NoExplicitReceiverTowerDataConsumer(session, name, token)
|
NoExplicitReceiverTowerDataConsumer(session, name, token, callKind)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -213,7 +216,8 @@ class ExplicitReceiverTowerDataConsumer<T : ConeSymbol>(
|
|||||||
val session: FirSession,
|
val session: FirSession,
|
||||||
val name: Name,
|
val name: Name,
|
||||||
val token: TowerScopeLevel.Token<T>,
|
val token: TowerScopeLevel.Token<T>,
|
||||||
val explicitReceiver: ReceiverValueWithPossibleTypes
|
val explicitReceiver: ReceiverValueWithPossibleTypes,
|
||||||
|
val callKind: CallKind
|
||||||
) : TowerDataConsumer() {
|
) : TowerDataConsumer() {
|
||||||
|
|
||||||
var groupId = 0
|
var groupId = 0
|
||||||
@@ -233,7 +237,7 @@ class ExplicitReceiverTowerDataConsumer<T : ConeSymbol>(
|
|||||||
null,
|
null,
|
||||||
object : TowerScopeLevel.TowerScopeLevelProcessor<T> {
|
object : TowerScopeLevel.TowerScopeLevelProcessor<T> {
|
||||||
override fun consumeCandidate(symbol: T, boundDispatchReceiver: ReceiverValueWithPossibleTypes?): ProcessorAction {
|
override fun consumeCandidate(symbol: T, boundDispatchReceiver: ReceiverValueWithPossibleTypes?): ProcessorAction {
|
||||||
resultCollector.consumeCandidate(groupId, symbol)
|
resultCollector.consumeCandidate(groupId, Candidate(symbol, ExplicitReceiverKind.DISPATCH_RECEIVER, callKind))
|
||||||
return ProcessorAction.NEXT
|
return ProcessorAction.NEXT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -245,7 +249,7 @@ class ExplicitReceiverTowerDataConsumer<T : ConeSymbol>(
|
|||||||
explicitReceiver,
|
explicitReceiver,
|
||||||
object : TowerScopeLevel.TowerScopeLevelProcessor<T> {
|
object : TowerScopeLevel.TowerScopeLevelProcessor<T> {
|
||||||
override fun consumeCandidate(symbol: T, boundDispatchReceiver: ReceiverValueWithPossibleTypes?): ProcessorAction {
|
override fun consumeCandidate(symbol: T, boundDispatchReceiver: ReceiverValueWithPossibleTypes?): ProcessorAction {
|
||||||
resultCollector.consumeCandidate(groupId, symbol)
|
resultCollector.consumeCandidate(groupId, Candidate(symbol, ExplicitReceiverKind.EXTENSION_RECEIVER, callKind))
|
||||||
return ProcessorAction.NEXT
|
return ProcessorAction.NEXT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -258,7 +262,8 @@ class ExplicitReceiverTowerDataConsumer<T : ConeSymbol>(
|
|||||||
class NoExplicitReceiverTowerDataConsumer<T : ConeSymbol>(
|
class NoExplicitReceiverTowerDataConsumer<T : ConeSymbol>(
|
||||||
val session: FirSession,
|
val session: FirSession,
|
||||||
val name: Name,
|
val name: Name,
|
||||||
val token: TowerScopeLevel.Token<T>
|
val token: TowerScopeLevel.Token<T>,
|
||||||
|
val callKind: CallKind
|
||||||
) : TowerDataConsumer() {
|
) : TowerDataConsumer() {
|
||||||
var groupId = 0
|
var groupId = 0
|
||||||
|
|
||||||
@@ -279,7 +284,7 @@ class NoExplicitReceiverTowerDataConsumer<T : ConeSymbol>(
|
|||||||
null,
|
null,
|
||||||
object : TowerScopeLevel.TowerScopeLevelProcessor<T> {
|
object : TowerScopeLevel.TowerScopeLevelProcessor<T> {
|
||||||
override fun consumeCandidate(symbol: T, boundDispatchReceiver: ReceiverValueWithPossibleTypes?): ProcessorAction {
|
override fun consumeCandidate(symbol: T, boundDispatchReceiver: ReceiverValueWithPossibleTypes?): ProcessorAction {
|
||||||
resultCollector.consumeCandidate(groupId, symbol)
|
resultCollector.consumeCandidate(groupId, Candidate(symbol, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, callKind))
|
||||||
return ProcessorAction.NEXT
|
return ProcessorAction.NEXT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -325,7 +330,7 @@ enum class CandidateApplicability {
|
|||||||
class CandidateCollector(val callInfo: CallInfo) {
|
class CandidateCollector(val callInfo: CallInfo) {
|
||||||
|
|
||||||
val groupNumbers = mutableListOf<Int>()
|
val groupNumbers = mutableListOf<Int>()
|
||||||
val candidates = mutableListOf<ConeSymbol>()
|
val candidates = mutableListOf<Candidate>()
|
||||||
|
|
||||||
|
|
||||||
var currentApplicability = CandidateApplicability.HIDDEN
|
var currentApplicability = CandidateApplicability.HIDDEN
|
||||||
@@ -339,18 +344,21 @@ class CandidateCollector(val callInfo: CallInfo) {
|
|||||||
|
|
||||||
protected fun getApplicability(
|
protected fun getApplicability(
|
||||||
group: Int,
|
group: Int,
|
||||||
symbol: ConeSymbol
|
candidate: Candidate
|
||||||
): CandidateApplicability {
|
): CandidateApplicability {
|
||||||
|
|
||||||
val sink = CheckerSinkImpl()
|
val sink = CheckerSinkImpl()
|
||||||
|
|
||||||
MapArguments.check(Candidate(symbol), sink, callInfo)
|
|
||||||
|
candidate.callKind.sequence().forEach {
|
||||||
|
it.check(candidate, sink, callInfo)
|
||||||
|
}
|
||||||
|
|
||||||
return sink.current
|
return sink.current
|
||||||
}
|
}
|
||||||
|
|
||||||
fun consumeCandidate(group: Int, symbol: ConeSymbol) {
|
fun consumeCandidate(group: Int, candidate: Candidate) {
|
||||||
val applicability = getApplicability(group, symbol)
|
val applicability = getApplicability(group, candidate)
|
||||||
|
|
||||||
if (applicability > currentApplicability) {
|
if (applicability > currentApplicability) {
|
||||||
groupNumbers.clear()
|
groupNumbers.clear()
|
||||||
@@ -360,7 +368,7 @@ class CandidateCollector(val callInfo: CallInfo) {
|
|||||||
|
|
||||||
|
|
||||||
if (applicability == currentApplicability) {
|
if (applicability == currentApplicability) {
|
||||||
candidates.add(symbol)
|
candidates.add(candidate)
|
||||||
groupNumbers.add(group)
|
groupNumbers.add(group)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -377,7 +385,7 @@ class CandidateCollector(val callInfo: CallInfo) {
|
|||||||
result.clear()
|
result.clear()
|
||||||
}
|
}
|
||||||
if (bestGroup == group) {
|
if (bestGroup == group) {
|
||||||
result.add(candidate)
|
result.add(candidate.symbol)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2019 JetBrains s.r.o. 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.declarations.FirFunction
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.transformers.firUnsafe
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
|
||||||
|
|
||||||
|
|
||||||
|
sealed class ResolutionStage {
|
||||||
|
abstract fun check(candidate: Candidate, sink: CheckerSink, callInfo: CallInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed class CheckerStage : ResolutionStage()
|
||||||
|
|
||||||
|
internal object MapArguments : ResolutionStage() {
|
||||||
|
override fun check(candidate: Candidate, sink: CheckerSink, callInfo: CallInfo) {
|
||||||
|
val symbol = candidate.symbol as? FirFunctionSymbol ?: return sink.reportApplicability(CandidateApplicability.HIDDEN)
|
||||||
|
if (symbol.firUnsafe<FirFunction>().valueParameters.size != callInfo.argumentCount) {
|
||||||
|
return sink.reportApplicability(CandidateApplicability.PARAMETER_MAPPING_ERROR)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
internal fun functionCallResolutionSequence() =
|
||||||
|
listOf<ResolutionStage>(MapArguments)
|
||||||
|
|
||||||
|
|
||||||
|
internal fun qualifiedAccessResolutionSequence() =
|
||||||
|
listOf<ResolutionStage>()
|
||||||
Reference in New Issue
Block a user