Analysis API: Move AllCandidatesResolver closer to

SingleCandidateResolver and share common code.
This commit is contained in:
Mark Punzalan
2022-02-04 12:21:48 +00:00
committed by Ilya Kirillov
parent 7a1ef25333
commit b8cdfc5aad
5 changed files with 158 additions and 126 deletions
@@ -12,10 +12,7 @@ import org.jetbrains.kotlin.analysis.api.fir.evaluate.FirAnnotationValueConverte
import org.jetbrains.kotlin.analysis.api.symbols.KtSymbol import org.jetbrains.kotlin.analysis.api.symbols.KtSymbol
import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
import org.jetbrains.kotlin.fir.expressions.FirAnnotation import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
import org.jetbrains.kotlin.fir.expressions.FirImplicitInvokeCall
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
import org.jetbrains.kotlin.fir.psi import org.jetbrains.kotlin.fir.psi
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
import org.jetbrains.kotlin.fir.references.FirNamedReference import org.jetbrains.kotlin.fir.references.FirNamedReference
@@ -23,9 +20,13 @@ import org.jetbrains.kotlin.fir.references.FirReference
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
import org.jetbrains.kotlin.fir.resolve.diagnostics.* import org.jetbrains.kotlin.fir.resolve.diagnostics.*
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtCallElement import org.jetbrains.kotlin.psi.KtCallElement
import org.jetbrains.kotlin.psi.KtNameReferenceExpression
import org.jetbrains.kotlin.util.OperatorNameConventions import org.jetbrains.kotlin.util.OperatorNameConventions
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
/** /**
* Checks if the function call is an implicit invoke call with a simple qualified receiver, or looks like it. * Checks if the function call is an implicit invoke call with a simple qualified receiver, or looks like it.
@@ -15,24 +15,22 @@ import org.jetbrains.kotlin.analysis.api.fir.symbols.KtFirArrayOfSymbolProvider.
import org.jetbrains.kotlin.analysis.api.fir.symbols.KtFirArrayOfSymbolProvider.arrayTypeToArrayOfCall import org.jetbrains.kotlin.analysis.api.fir.symbols.KtFirArrayOfSymbolProvider.arrayTypeToArrayOfCall
import org.jetbrains.kotlin.analysis.api.fir.symbols.KtFirFunctionSymbol import org.jetbrains.kotlin.analysis.api.fir.symbols.KtFirFunctionSymbol
import org.jetbrains.kotlin.analysis.api.impl.barebone.parentOfType import org.jetbrains.kotlin.analysis.api.impl.barebone.parentOfType
import org.jetbrains.kotlin.analysis.api.impl.barebone.parentsOfType
import org.jetbrains.kotlin.analysis.api.impl.base.components.AbstractKtCallResolver import org.jetbrains.kotlin.analysis.api.impl.base.components.AbstractKtCallResolver
import org.jetbrains.kotlin.analysis.api.symbols.* import org.jetbrains.kotlin.analysis.api.symbols.*
import org.jetbrains.kotlin.analysis.api.tokens.ValidityToken import org.jetbrains.kotlin.analysis.api.tokens.ValidityToken
import org.jetbrains.kotlin.analysis.api.types.KtSubstitutor import org.jetbrains.kotlin.analysis.api.types.KtSubstitutor
import org.jetbrains.kotlin.analysis.api.withValidityAssertion import org.jetbrains.kotlin.analysis.api.withValidityAssertion
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFir import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFir
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFirFile import org.jetbrains.kotlin.analysis.low.level.api.fir.resolver.AllCandidatesResolver
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.resolveToFirSymbol
import org.jetbrains.kotlin.diagnostics.KtDiagnostic import org.jetbrains.kotlin.diagnostics.KtDiagnostic
import org.jetbrains.kotlin.fir.* import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.analysis.checkers.toRegularClassSymbol import org.jetbrains.kotlin.fir.analysis.checkers.toRegularClassSymbol
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.declarations.FirValueParameter import org.jetbrains.kotlin.fir.declarations.FirValueParameter
import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.builder.buildFunctionCall import org.jetbrains.kotlin.fir.expressions.builder.buildFunctionCall
import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression
import org.jetbrains.kotlin.fir.psi
import org.jetbrains.kotlin.fir.realPsi
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
import org.jetbrains.kotlin.fir.references.FirNamedReference import org.jetbrains.kotlin.fir.references.FirNamedReference
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
@@ -40,15 +38,12 @@ import org.jetbrains.kotlin.fir.references.FirSuperReference
import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.calls.AbstractCandidate import org.jetbrains.kotlin.fir.resolve.calls.AbstractCandidate
import org.jetbrains.kotlin.fir.resolve.calls.Candidate import org.jetbrains.kotlin.fir.resolve.calls.Candidate
import org.jetbrains.kotlin.fir.resolve.calls.ResolutionContext
import org.jetbrains.kotlin.fir.resolve.createConeDiagnosticForCandidateWithError import org.jetbrains.kotlin.fir.resolve.createConeDiagnosticForCandidateWithError
import org.jetbrains.kotlin.fir.resolve.dfa.unwrapSmartcastExpression import org.jetbrains.kotlin.fir.resolve.dfa.unwrapSmartcastExpression
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeDiagnosticWithCandidates import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeDiagnosticWithCandidates
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeHiddenCandidateError import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeHiddenCandidateError
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirAbstractBodyResolveTransformer
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirBodyResolveTransformer
import org.jetbrains.kotlin.fir.scopes.ProcessorAction import org.jetbrains.kotlin.fir.scopes.ProcessorAction
import org.jetbrains.kotlin.fir.scopes.impl.declaredMemberScope import org.jetbrains.kotlin.fir.scopes.impl.declaredMemberScope
import org.jetbrains.kotlin.fir.scopes.processOverriddenFunctions import org.jetbrains.kotlin.fir.scopes.processOverriddenFunctions
@@ -732,10 +727,7 @@ internal class KtFirCallResolver(
) ?: emptyList() ) ?: emptyList()
} }
return when (this) { return when (this) {
is FirFunctionCall -> { is FirFunctionCall -> collectCallCandidates(psi, resolveFragmentOfCall)
val firFile = psi.containingKtFile.getOrBuildFirFile(firResolveState)
AllCandidatesResolver(analysisSession.rootModuleSession, firFile).getAllCandidates(this, psi, resolveFragmentOfCall)
}
is FirSafeCallExpression -> selector.collectCallCandidates( is FirSafeCallExpression -> selector.collectCallCandidates(
psi, psi,
resolveCalleeExpressionOfFunctionCall, resolveCalleeExpressionOfFunctionCall,
@@ -757,98 +749,68 @@ internal class KtFirCallResolver(
} }
} }
private inner class AllCandidatesResolver(private val firSession: FirSession, private val firFile: FirFile) { private fun FirFunctionCall.collectCallCandidates(
private val scopeSession = ScopeSession() psi: KtElement,
resolveFragmentOfCall: Boolean
// TODO: This transformer is not intended for actual transformations and created here only to simplify access to call resolver ): List<KtCallInfo> {
private val stubBodyResolveTransformer = FirBodyResolveTransformer( // If a function call is resolved to an implicit invoke call, the FirImplicitInvokeCall will have the `invoke()` function as the
session = firSession, // callee and the variable as the explicit receiver. To correctly get all candidates, we need to get the original function
phase = FirResolvePhase.BODY_RESOLVE, // call's explicit receiver (if there is any) and callee (i.e., the variable).
implicitTypeOnly = false, val unwrappedExplicitReceiver = explicitReceiver?.unwrapSmartcastExpression()
scopeSession = scopeSession, val originalFunctionCall =
) if (this is FirImplicitInvokeCall && unwrappedExplicitReceiver is FirPropertyAccessExpression) {
val originalCallee = unwrappedExplicitReceiver.calleeReference.safeAs<FirNamedReference>() ?: return emptyList()
private val bodyResolveComponents = buildFunctionCall {
FirAbstractBodyResolveTransformer.BodyResolveTransformerComponents( // NOTE: We only need to copy the explicit receiver and not the dispatch and extension receivers as only the explicit
firSession, // receiver is needed by the resolver. The dispatch and extension receivers are only assigned after resolution when a
scopeSession, // candidate is selected.
stubBodyResolveTransformer, source = this@collectCallCandidates.source
stubBodyResolveTransformer.context, annotations.addAll(this@collectCallCandidates.annotations)
) typeArguments.addAll(this@collectCallCandidates.typeArguments)
explicitReceiver = unwrappedExplicitReceiver.explicitReceiver
private val resolutionContext = ResolutionContext(firSession, bodyResolveComponents, stubBodyResolveTransformer.context) argumentList = this@collectCallCandidates.argumentList
calleeReference = originalCallee
fun getAllCandidates(functionCall: FirFunctionCall, element: KtElement, resolveFragmentOfCall: Boolean): List<KtCallInfo> {
initializeBodyResolveContext(element)
// If a function call is resolved to an implicit invoke call, the FirImplicitInvokeCall will have the `invoke()` function as the
// callee and the variable as the explicit receiver. To correctly get all candidates, we need to get the original function
// call's explicit receiver (if there is any) and callee (i.e., the variable).
val unwrappedExplicitReceiver = functionCall.explicitReceiver?.unwrapSmartcastExpression()
val originalFunctionCall =
if (functionCall is FirImplicitInvokeCall && unwrappedExplicitReceiver is FirPropertyAccessExpression) {
val originalCallee = unwrappedExplicitReceiver.calleeReference.safeAs<FirNamedReference>() ?: return emptyList()
buildFunctionCall {
source = functionCall.source
annotations.addAll(functionCall.annotations)
typeArguments.addAll(functionCall.typeArguments)
explicitReceiver = unwrappedExplicitReceiver.explicitReceiver
argumentList = functionCall.argumentList
calleeReference = originalCallee
}
} else {
functionCall
} }
val calleeName = originalFunctionCall.calleeOrCandidateName ?: return emptyList()
val candidates = bodyResolveComponents.context.withFile(firFile, bodyResolveComponents) {
bodyResolveComponents.callResolver.collectAllCandidates(
originalFunctionCall,
calleeName,
bodyResolveComponents.context.containers,
resolutionContext
)
}
return candidates.mapNotNull {
convertToKtCallInfo(
originalFunctionCall,
element,
it.candidate,
it.isInBestCandidates,
resolveFragmentOfCall
)
}
}
@OptIn(PrivateForInline::class, SymbolInternals::class)
private fun initializeBodyResolveContext(element: KtElement) {
// Set up needed context to get all candidates.
val towerContext = firResolveState.getTowerContextProvider(element.containingKtFile).getClosestAvailableParentContext(element)
towerContext?.let { bodyResolveComponents.context.replaceTowerDataContext(it) }
val containingDeclarations =
element.parentsOfType<KtDeclaration>().map { it.resolveToFirSymbol(firResolveState).fir }.toList().asReversed()
bodyResolveComponents.context.containers.addAll(containingDeclarations)
}
private fun convertToKtCallInfo(
functionCall: FirFunctionCall,
element: KtElement,
candidate: Candidate,
isInBestCandidates: Boolean,
resolveFragmentOfCall: Boolean
): KtCallInfo? {
val call = createKtCall(element, functionCall, candidate, resolveFragmentOfCall)
?: error("expect `createKtCall` to succeed for candidate")
return if (candidate.isSuccessful && isInBestCandidates) {
KtSuccessCallInfo(call)
} else { } else {
val diagnostic = createConeDiagnosticForCandidateWithError(candidate.currentApplicability, candidate) this
if (diagnostic is ConeHiddenCandidateError) return null
val ktDiagnostic =
functionCall.source?.let { diagnostic.asKtDiagnostic(it, element.toKtPsiSourceElement(), diagnosticCache) }
?: KtNonBoundToPsiErrorDiagnostic(factoryName = null, diagnostic.reason, token)
KtErrorCallInfo(listOf(call), ktDiagnostic, token)
} }
val calleeName = originalFunctionCall.calleeOrCandidateName ?: return emptyList()
val candidates = AllCandidatesResolver(analysisSession.rootModuleSession).getAllCandidates(
analysisSession.firResolveState,
originalFunctionCall,
calleeName,
psi
)
return candidates.mapNotNull {
convertToKtCallInfo(
originalFunctionCall,
psi,
it.candidate,
it.isInBestCandidates,
resolveFragmentOfCall
)
}
}
private fun convertToKtCallInfo(
functionCall: FirFunctionCall,
element: KtElement,
candidate: Candidate,
isInBestCandidates: Boolean,
resolveFragmentOfCall: Boolean
): KtCallInfo? {
val call = createKtCall(element, functionCall, candidate, resolveFragmentOfCall)
?: error("expect `createKtCall` to succeed for candidate")
return if (candidate.isSuccessful && isInBestCandidates) {
KtSuccessCallInfo(call)
} else {
val diagnostic = createConeDiagnosticForCandidateWithError(candidate.currentApplicability, candidate)
if (diagnostic is ConeHiddenCandidateError) return null
val ktDiagnostic =
functionCall.source?.let { diagnostic.asKtDiagnostic(it, element.toKtPsiSourceElement(), diagnosticCache) }
?: KtNonBoundToPsiErrorDiagnostic(factoryName = null, diagnostic.reason, token)
KtErrorCallInfo(listOf(call), ktDiagnostic, token)
} }
} }
@@ -873,7 +835,7 @@ internal class KtFirCallResolver(
is KtNameReferenceExpression -> psi.getReferencedNameAsName() is KtNameReferenceExpression -> psi.getReferencedNameAsName()
else -> { else -> {
// This could be KtArrayAccessExpression or KtOperationReferenceExpression. // This could be KtArrayAccessExpression or KtOperationReferenceExpression.
// Note: All candidate symbols should have the same name. We go by the symbol because `originalCallee.name` will include // Note: All candidate symbols should have the same name. We go by the symbol because `calleeReference.name` will include
// the applicability if not successful. // the applicability if not successful.
calleeReference.getCandidateSymbols().firstOrNull()?.safeAs<FirCallableSymbol<*>>()?.name calleeReference.getCandidateSymbols().firstOrNull()?.safeAs<FirCallableSymbol<*>>()?.name
} }
@@ -0,0 +1,54 @@
/*
* Copyright 2010-2022 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.analysis.low.level.api.fir.resolver
import org.jetbrains.kotlin.analysis.api.impl.barebone.parentsOfType
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.LLFirModuleResolveState
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFirFile
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.resolveToFirSymbol
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.OverloadCandidate
import org.jetbrains.kotlin.fir.PrivateForInline
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
import org.jetbrains.kotlin.fir.resolve.calls.ResolutionContext
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtElement
class AllCandidatesResolver(firSession: FirSession) {
private val bodyResolveComponents = createStubBodyResolveComponents(firSession)
private val resolutionContext = ResolutionContext(firSession, bodyResolveComponents, bodyResolveComponents.transformer.context)
fun getAllCandidates(
resolveState: LLFirModuleResolveState,
functionCall: FirFunctionCall,
calleeName: Name,
element: KtElement
): List<OverloadCandidate> {
initializeBodyResolveContext(resolveState, element)
val firFile = element.containingKtFile.getOrBuildFirFile(resolveState)
return bodyResolveComponents.context.withFile(firFile, bodyResolveComponents) {
bodyResolveComponents.callResolver.collectAllCandidates(
functionCall,
calleeName,
bodyResolveComponents.context.containers,
resolutionContext
)
}
}
@OptIn(PrivateForInline::class, SymbolInternals::class)
private fun initializeBodyResolveContext(resolveState: LLFirModuleResolveState, element: KtElement) {
// Set up needed context to get all candidates.
val towerContext = resolveState.getTowerContextProvider(element.containingKtFile).getClosestAvailableParentContext(element)
towerContext?.let { bodyResolveComponents.context.replaceTowerDataContext(it) }
val containingDeclarations =
element.parentsOfType<KtDeclaration>().map { it.resolveToFirSymbol(resolveState).fir }.toList().asReversed()
bodyResolveComponents.context.containers.addAll(containingDeclarations)
}
}
@@ -7,7 +7,6 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.resolver
import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirFile import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.expressions.FirArgumentList import org.jetbrains.kotlin.fir.expressions.FirArgumentList
import org.jetbrains.kotlin.fir.expressions.FirEmptyArgumentList import org.jetbrains.kotlin.fir.expressions.FirEmptyArgumentList
import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.expressions.FirExpression
@@ -16,8 +15,6 @@ import org.jetbrains.kotlin.fir.expressions.builder.buildFunctionCall
import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.calls.* import org.jetbrains.kotlin.fir.resolve.calls.*
import org.jetbrains.kotlin.fir.resolve.inference.FirCallCompleter import org.jetbrains.kotlin.fir.resolve.inference.FirCallCompleter
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirAbstractBodyResolveTransformer
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirBodyResolveTransformer
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.types.FirTypeProjection import org.jetbrains.kotlin.fir.types.FirTypeProjection
import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.fir.types.FirTypeRef
@@ -29,22 +26,9 @@ class SingleCandidateResolver(
) { ) {
private val scopeSession = ScopeSession() private val scopeSession = ScopeSession()
// TODO This transformer is not intended for actual transformations and created here only to simplify access to body resolve components private val bodyResolveComponents = createStubBodyResolveComponents(firSession)
private val stubBodyResolveTransformer = object : FirBodyResolveTransformer(
session = firSession,
phase = FirResolvePhase.BODY_RESOLVE,
implicitTypeOnly = false,
scopeSession = scopeSession,
) {}
private val bodyResolveComponents =
FirAbstractBodyResolveTransformer.BodyResolveTransformerComponents(
firSession,
scopeSession,
stubBodyResolveTransformer,
stubBodyResolveTransformer.context,
)
private val firCallCompleter = FirCallCompleter( private val firCallCompleter = FirCallCompleter(
stubBodyResolveTransformer, bodyResolveComponents.transformer,
bodyResolveComponents, bodyResolveComponents,
) )
private val resolutionStageRunner = ResolutionStageRunner() private val resolutionStageRunner = ResolutionStageRunner()
@@ -62,7 +46,7 @@ class SingleCandidateResolver(
val dispatchReceiverValue = infoProvider.dispatchReceiverValue() val dispatchReceiverValue = infoProvider.dispatchReceiverValue()
val implicitExtensionReceiverValue = infoProvider.implicitExtensionReceiverValue() val implicitExtensionReceiverValue = infoProvider.implicitExtensionReceiverValue()
val resolutionContext = stubBodyResolveTransformer.resolutionContext val resolutionContext = bodyResolveComponents.transformer.resolutionContext
val candidate = CandidateFactory(resolutionContext, callInfo).createCandidate( val candidate = CandidateFactory(resolutionContext, callInfo).createCandidate(
callInfo, callInfo,
@@ -0,0 +1,31 @@
/*
* Copyright 2010-2022 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.analysis.low.level.api.fir.resolver
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirAbstractBodyResolveTransformer
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirBodyResolveTransformer
internal fun createStubBodyResolveComponents(firSession: FirSession): FirAbstractBodyResolveTransformer.BodyResolveTransformerComponents {
val scopeSession = ScopeSession()
// This transformer is not intended for actual transformations and created here only to simplify access to resolve components
val stubBodyResolveTransformer = FirBodyResolveTransformer(
session = firSession,
phase = FirResolvePhase.BODY_RESOLVE,
implicitTypeOnly = false,
scopeSession = scopeSession,
)
return FirAbstractBodyResolveTransformer.BodyResolveTransformerComponents(
firSession,
scopeSession,
stubBodyResolveTransformer,
stubBodyResolveTransformer.context,
)
}