[FIR] Extract ResolutionStageRunner component
That component is responsible to run all resolution stages on candidate and calculating resulting applicability. This is needed for completion of `when` and `try` as function calls
This commit is contained in:
committed by
Mikhail Glukhikh
parent
8bbb60df25
commit
53404e5dac
@@ -41,7 +41,8 @@ class FirCallResolver(
|
|||||||
private val scopes: List<FirScope>,
|
private val scopes: List<FirScope>,
|
||||||
private val localScopes: List<FirScope>,
|
private val localScopes: List<FirScope>,
|
||||||
private val implicitReceiverStack: List<ImplicitReceiverValue>,
|
private val implicitReceiverStack: List<ImplicitReceiverValue>,
|
||||||
private val qualifiedResolver: FirQualifiedNameResolver
|
private val qualifiedResolver: FirQualifiedNameResolver,
|
||||||
|
private val resolutionStageRunner: ResolutionStageRunner
|
||||||
) : BodyResolveComponents by transformer {
|
) : BodyResolveComponents by transformer {
|
||||||
|
|
||||||
fun resolveCallAndSelectCandidate(functionCall: FirFunctionCall, expectedTypeRef: FirTypeRef?, file: FirFile): FirFunctionCall {
|
fun resolveCallAndSelectCandidate(functionCall: FirFunctionCall, expectedTypeRef: FirTypeRef?, file: FirFile): FirFunctionCall {
|
||||||
@@ -66,7 +67,7 @@ class FirCallResolver(
|
|||||||
file,
|
file,
|
||||||
transformer.container
|
transformer.container
|
||||||
) { it.resultType }
|
) { it.resultType }
|
||||||
val resolver = CallResolver(returnTypeCalculator, inferenceComponents)
|
val resolver = CallResolver(returnTypeCalculator, inferenceComponents, resolutionStageRunner)
|
||||||
resolver.callInfo = info
|
resolver.callInfo = info
|
||||||
resolver.scopes = (scopes + localScopes).asReversed()
|
resolver.scopes = (scopes + localScopes).asReversed()
|
||||||
|
|
||||||
@@ -156,7 +157,7 @@ class FirCallResolver(
|
|||||||
file,
|
file,
|
||||||
transformer.container
|
transformer.container
|
||||||
) { it.resultType }
|
) { it.resultType }
|
||||||
val resolver = CallResolver(returnTypeCalculator, inferenceComponents)
|
val resolver = CallResolver(returnTypeCalculator, inferenceComponents, resolutionStageRunner)
|
||||||
resolver.callInfo = info
|
resolver.callInfo = info
|
||||||
resolver.scopes = (scopes + localScopes).asReversed()
|
resolver.scopes = (scopes + localScopes).asReversed()
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,11 @@ enum class TowerDataKind {
|
|||||||
TOWER_LEVEL
|
TOWER_LEVEL
|
||||||
}
|
}
|
||||||
|
|
||||||
class CallResolver(val typeCalculator: ReturnTypeCalculator, val components: InferenceComponents) {
|
class CallResolver(
|
||||||
|
val typeCalculator: ReturnTypeCalculator,
|
||||||
|
val components: InferenceComponents,
|
||||||
|
val resolutionStageRunner: ResolutionStageRunner
|
||||||
|
) {
|
||||||
var callInfo: CallInfo? = null
|
var callInfo: CallInfo? = null
|
||||||
var scopes: List<FirScope>? = null
|
var scopes: List<FirScope>? = null
|
||||||
|
|
||||||
@@ -51,7 +55,7 @@ class CallResolver(val typeCalculator: ReturnTypeCalculator, val components: Inf
|
|||||||
return group
|
return group
|
||||||
}
|
}
|
||||||
|
|
||||||
val collector by lazy { CandidateCollector(components) }
|
val collector by lazy { CandidateCollector(components, resolutionStageRunner) }
|
||||||
lateinit var towerDataConsumer: TowerDataConsumer
|
lateinit var towerDataConsumer: TowerDataConsumer
|
||||||
private lateinit var implicitReceiverValues: List<ImplicitReceiverValue>
|
private lateinit var implicitReceiverValues: List<ImplicitReceiverValue>
|
||||||
|
|
||||||
|
|||||||
+8
-39
@@ -9,14 +9,11 @@ import org.jetbrains.kotlin.fir.expressions.impl.FirQualifiedAccessExpressionImp
|
|||||||
import org.jetbrains.kotlin.fir.resolve.transformers.firUnsafe
|
import org.jetbrains.kotlin.fir.resolve.transformers.firUnsafe
|
||||||
import org.jetbrains.kotlin.fir.symbols.ConeCallableSymbol
|
import org.jetbrains.kotlin.fir.symbols.ConeCallableSymbol
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||||
import kotlin.coroutines.Continuation
|
|
||||||
import kotlin.coroutines.CoroutineContext
|
|
||||||
import kotlin.coroutines.EmptyCoroutineContext
|
|
||||||
import kotlin.coroutines.intrinsics.createCoroutineUnintercepted
|
|
||||||
import kotlin.coroutines.resume
|
|
||||||
|
|
||||||
open class CandidateCollector(val components: InferenceComponents) {
|
|
||||||
|
|
||||||
|
open class CandidateCollector(
|
||||||
|
val components: InferenceComponents,
|
||||||
|
val resolutionStageRunner: ResolutionStageRunner
|
||||||
|
) {
|
||||||
val groupNumbers = mutableListOf<Int>()
|
val groupNumbers = mutableListOf<Int>()
|
||||||
val candidates = mutableListOf<Candidate>()
|
val candidates = mutableListOf<Candidate>()
|
||||||
|
|
||||||
@@ -28,37 +25,8 @@ open class CandidateCollector(val components: InferenceComponents) {
|
|||||||
currentApplicability = CandidateApplicability.HIDDEN
|
currentApplicability = CandidateApplicability.HIDDEN
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getApplicability(
|
|
||||||
group: Int,
|
|
||||||
candidate: Candidate
|
|
||||||
): CandidateApplicability {
|
|
||||||
val sink = CheckerSinkImpl(components)
|
|
||||||
var finished = false
|
|
||||||
sink.continuation = suspend {
|
|
||||||
for (stage in candidate.callInfo.callKind.sequence()) {
|
|
||||||
stage.check(candidate, sink, candidate.callInfo)
|
|
||||||
}
|
|
||||||
}.createCoroutineUnintercepted(completion = object : Continuation<Unit> {
|
|
||||||
override val context: CoroutineContext
|
|
||||||
get() = EmptyCoroutineContext
|
|
||||||
|
|
||||||
override fun resumeWith(result: Result<Unit>) {
|
|
||||||
result.exceptionOrNull()?.let { throw it }
|
|
||||||
finished = true
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
while (!finished) {
|
|
||||||
sink.continuation!!.resume(Unit)
|
|
||||||
if (sink.current < CandidateApplicability.SYNTHETIC_RESOLVED) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return sink.current
|
|
||||||
}
|
|
||||||
|
|
||||||
open fun consumeCandidate(group: Int, candidate: Candidate): CandidateApplicability {
|
open fun consumeCandidate(group: Int, candidate: Candidate): CandidateApplicability {
|
||||||
val applicability = getApplicability(group, candidate)
|
val applicability = resolutionStageRunner.processCandidate(candidate)
|
||||||
|
|
||||||
if (applicability > currentApplicability) {
|
if (applicability > currentApplicability) {
|
||||||
groupNumbers.clear()
|
groupNumbers.clear()
|
||||||
@@ -103,8 +71,9 @@ class InvokeReceiverCandidateCollector(
|
|||||||
val callResolver: CallResolver,
|
val callResolver: CallResolver,
|
||||||
val invokeCallInfo: CallInfo,
|
val invokeCallInfo: CallInfo,
|
||||||
components: InferenceComponents,
|
components: InferenceComponents,
|
||||||
val invokeConsumer: AccumulatingTowerDataConsumer
|
val invokeConsumer: AccumulatingTowerDataConsumer,
|
||||||
) : CandidateCollector(components) {
|
resolutionStageRunner: ResolutionStageRunner
|
||||||
|
) : CandidateCollector(components, resolutionStageRunner) {
|
||||||
override fun consumeCandidate(group: Int, candidate: Candidate): CandidateApplicability {
|
override fun consumeCandidate(group: Int, candidate: Candidate): CandidateApplicability {
|
||||||
val applicability = super.consumeCandidate(group, candidate)
|
val applicability = super.consumeCandidate(group, candidate)
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -94,7 +94,8 @@ fun createFunctionConsumer(
|
|||||||
callResolver,
|
callResolver,
|
||||||
invokeCallInfo = callInfo,
|
invokeCallInfo = callInfo,
|
||||||
components = inferenceComponents,
|
components = inferenceComponents,
|
||||||
invokeConsumer = this
|
invokeConsumer = this,
|
||||||
|
resolutionStageRunner = resultCollector.resolutionStageRunner
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+40
@@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* 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 kotlin.coroutines.Continuation
|
||||||
|
import kotlin.coroutines.CoroutineContext
|
||||||
|
import kotlin.coroutines.EmptyCoroutineContext
|
||||||
|
import kotlin.coroutines.intrinsics.createCoroutineUnintercepted
|
||||||
|
import kotlin.coroutines.resume
|
||||||
|
|
||||||
|
class ResolutionStageRunner(val components: InferenceComponents) {
|
||||||
|
fun processCandidate(candidate: Candidate): CandidateApplicability {
|
||||||
|
val sink = CheckerSinkImpl(components)
|
||||||
|
var finished = false
|
||||||
|
sink.continuation = suspend {
|
||||||
|
for (stage in candidate.callInfo.callKind.sequence()) {
|
||||||
|
stage.check(candidate, sink, candidate.callInfo)
|
||||||
|
}
|
||||||
|
}.createCoroutineUnintercepted(completion = object : Continuation<Unit> {
|
||||||
|
override val context: CoroutineContext
|
||||||
|
get() = EmptyCoroutineContext
|
||||||
|
|
||||||
|
override fun resumeWith(result: Result<Unit>) {
|
||||||
|
result.exceptionOrNull()?.let { throw it }
|
||||||
|
finished = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
while (!finished) {
|
||||||
|
sink.continuation!!.resume(Unit)
|
||||||
|
if (sink.current < CandidateApplicability.SYNTHETIC_RESOLVED) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sink.current
|
||||||
|
}
|
||||||
|
}
|
||||||
+10
-1
@@ -71,7 +71,16 @@ open class FirBodyResolveTransformer(
|
|||||||
|
|
||||||
private val callCompleter: FirCallCompleter = FirCallCompleter(this, inferenceComponents)
|
private val callCompleter: FirCallCompleter = FirCallCompleter(this, inferenceComponents)
|
||||||
private val qualifiedResolver: FirQualifiedNameResolver = FirQualifiedNameResolver(this)
|
private val qualifiedResolver: FirQualifiedNameResolver = FirQualifiedNameResolver(this)
|
||||||
private val callResolver: FirCallResolver = FirCallResolver(this, inferenceComponents, scopes, localScopes, implicitReceiverStack, qualifiedResolver)
|
private val resolutionStageRunner: ResolutionStageRunner = ResolutionStageRunner(inferenceComponents)
|
||||||
|
private val callResolver: FirCallResolver = FirCallResolver(
|
||||||
|
this,
|
||||||
|
inferenceComponents,
|
||||||
|
scopes,
|
||||||
|
localScopes,
|
||||||
|
implicitReceiverStack,
|
||||||
|
qualifiedResolver,
|
||||||
|
resolutionStageRunner
|
||||||
|
)
|
||||||
|
|
||||||
override fun transformFile(file: FirFile, data: Any?): CompositeTransformResult<FirFile> {
|
override fun transformFile(file: FirFile, data: Any?): CompositeTransformResult<FirFile> {
|
||||||
packageFqName = file.packageFqName
|
packageFqName = file.packageFqName
|
||||||
|
|||||||
Reference in New Issue
Block a user