FIR: Add CallKind

This commit is contained in:
Simon Ogorodnik
2019-03-19 15:37:49 +03:00
parent a562f3db3c
commit 6799eeb084
2 changed files with 74 additions and 31 deletions
@@ -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>()