Analysis API: Fix issues related to implicit invoke calls:

- Correctly set explicit receiver value.
- Restore original function call from FirImplicitFunctionCall (i.e.,
calls implicitly resolved to `invoke`) to get the correct name for
getting all candidates.
- Collect candidates at all tower levels.

Also make order of candidate calls in tests deterministic.
This commit is contained in:
Mark Punzalan
2022-01-31 17:58:32 +00:00
committed by Ilya Kirillov
parent ace826c570
commit 9b9da94a09
30 changed files with 763 additions and 109 deletions
@@ -40,6 +40,12 @@ public class Fe10ResolveCallTestGenerated extends AbstractResolveCallTest {
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/ambiguous.kt");
}
@Test
@TestMetadata("ambiguousImplicitInvoke.kt")
public void testAmbiguousImplicitInvoke() throws Exception {
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/ambiguousImplicitInvoke.kt");
}
@Test
@TestMetadata("ambiguousWithExplicitTypeParameters.kt")
public void testAmbiguousWithExplicitTypeParameters() throws Exception {
@@ -42,7 +42,10 @@ fun FirFunctionCall.isImplicitFunctionCall(): Boolean {
calleeReference.getCandidateSymbols().any(FirBasedSymbol<*>::isInvokeFunction)
}
private fun FirBasedSymbol<*>.isInvokeFunction() =
/**
* Returns `true` if the symbol is for a function named `invoke`.
*/
internal fun FirBasedSymbol<*>.isInvokeFunction() =
(this as? FirNamedFunctionSymbol)?.fir?.name == OperatorNameConventions.INVOKE
fun FirFunctionCall.getCalleeSymbol(): FirBasedSymbol<*>? =
@@ -9,11 +9,13 @@ import org.jetbrains.kotlin.analysis.api.calls.*
import org.jetbrains.kotlin.analysis.api.diagnostics.KtNonBoundToPsiErrorDiagnostic
import org.jetbrains.kotlin.analysis.api.fir.KtFirAnalysisSession
import org.jetbrains.kotlin.analysis.api.fir.getCandidateSymbols
import org.jetbrains.kotlin.analysis.api.fir.isInvokeFunction
import org.jetbrains.kotlin.analysis.api.fir.symbols.KtFirArrayOfSymbolProvider.arrayOf
import org.jetbrains.kotlin.analysis.api.fir.symbols.KtFirArrayOfSymbolProvider.arrayOfSymbol
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.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.symbols.*
import org.jetbrains.kotlin.analysis.api.tokens.ValidityToken
@@ -21,14 +23,16 @@ import org.jetbrains.kotlin.analysis.api.types.KtSubstitutor
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.getOrBuildFirFile
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.resolveToFirSymbol
import org.jetbrains.kotlin.diagnostics.KtDiagnostic
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.analysis.checkers.toRegularClassSymbol
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
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.expressions.*
import org.jetbrains.kotlin.fir.expressions.builder.buildFunctionCall
import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
import org.jetbrains.kotlin.fir.references.FirNamedReference
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
@@ -38,6 +42,7 @@ import org.jetbrains.kotlin.fir.resolve.calls.AbstractCandidate
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.dfa.unwrapSmartcastExpression
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeDiagnosticWithCandidates
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeHiddenCandidateError
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
@@ -52,8 +57,10 @@ import org.jetbrains.kotlin.fir.symbols.SymbolInternals
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.KtPsiUtil.deparenthesize
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
import org.jetbrains.kotlin.toKtPsiSourceElement
import org.jetbrains.kotlin.util.OperatorNameConventions
import org.jetbrains.kotlin.util.OperatorNameConventions.EQUALS
@@ -255,59 +262,88 @@ internal class KtFirCallResolver(
handleCompoundAccessCall(psi, fir, resolveFragmentOfCall)?.let { return it }
var firstArgIsExtensionReceiver = false
var isImplicitInvoke = false
val partiallyAppliedSymbol = if (candidate != null) {
// TODO: Ideally, we should get the substitutor from the candidate. But it seems there is no way to get the substitutor from the
// candidate, `Candidate.substitutor` is not complete. maybe we can carry over the final substitutor if it's available from
// body resolve phase?
val substitutor =
(fir as? FirQualifiedAccess)?.createSubstitutorFromTypeArguments(targetSymbol) ?: KtSubstitutor.Empty(token)
KtPartiallyAppliedSymbol(
unsubstitutedKtSignature.substitute(substitutor),
candidate.dispatchReceiverValue?.receiverExpression?.toKtReceiverValue(),
candidate.extensionReceiverValue?.receiverExpression?.toKtReceiverValue(),
)
} else if (fir is FirQualifiedAccess) {
val dispatchReceiver: KtReceiverValue?
val extensionReceiver: KtReceiverValue?
if (fir is FirImplicitInvokeCall) {
val explicitReceiverPsi = when (psi) {
is KtQualifiedExpression -> (psi.selectorExpression as KtCallExpression).calleeExpression
is KtCallExpression -> psi.calleeExpression
else -> error("unexpected PSI $psi for FirImplicitInvokeCall")
} ?: error("missing calleeExpression in PSI $psi for FirImplicitInvokeCall")
// For implicit invoke, the explicit receiver is always set in FIR and this receiver is the variable or property that has
// the `invoke` member function. In this case, we use the `calleeExpression` in the `KtCallExpression` as the PSI
// representation of this receiver. Caller can then use this PSI for further call resolution, which is implemented by the
// parameter `resolveCalleeExpressionOfFunctionCall` in `toKtCallInfo`.
val explicitReceiver = KtExplicitReceiverValue(explicitReceiverPsi, false, token)
// TODO: Ideally, we should get the substitutor from the candidate. But it seems there is no way to get the substitutor from the
// candidate, `Candidate.substitutor` is not complete. maybe we can carry over the final substitutor if it's available from
// body resolve phase?
val substitutor =
(fir as? FirQualifiedAccess)?.createSubstitutorFromTypeArguments(targetSymbol) ?: KtSubstitutor.Empty(token)
// Specially handle @ExtensionFunctionType
if (fir.dispatchReceiver.typeRef.coneTypeSafe<ConeKotlinType>()?.isExtensionFunctionType == true) {
firstArgIsExtensionReceiver = true
}
fun createKtPartiallyAppliedSymbolForImplicitInvoke(
dispatchReceiver: FirExpression,
extensionReceiver: FirExpression,
explicitReceiverKind: ExplicitReceiverKind
): KtPartiallyAppliedSymbol<KtCallableSymbol, KtSignature<KtCallableSymbol>> {
isImplicitInvoke = true
val explicitReceiverPsi = when (psi) {
is KtQualifiedExpression -> (psi.selectorExpression as KtCallExpression).calleeExpression
is KtCallExpression -> psi.calleeExpression
else -> error("unexpected PSI $psi for FirImplicitInvokeCall")
} ?: error("missing calleeExpression in PSI $psi for FirImplicitInvokeCall")
// For implicit invoke, the explicit receiver is always set in FIR and this receiver is the variable or property that has
// the `invoke` member function. In this case, we use the `calleeExpression` in the `KtCallExpression` as the PSI
// representation of this receiver. Caller can then use this PSI for further call resolution, which is implemented by the
// parameter `resolveCalleeExpressionOfFunctionCall` in `toKtCallInfo`.
val explicitReceiverValue = KtExplicitReceiverValue(explicitReceiverPsi, false, token)
if (fir.explicitReceiver == fir.dispatchReceiver) {
dispatchReceiver = explicitReceiver
if (firstArgIsExtensionReceiver) {
extensionReceiver = fir.arguments.first().toKtReceiverValue()
} else {
extensionReceiver = fir.extensionReceiver.toKtReceiverValue()
}
// Specially handle @ExtensionFunctionType
if (dispatchReceiver.typeRef.coneTypeSafe<ConeKotlinType>()?.isExtensionFunctionType == true) {
firstArgIsExtensionReceiver = true
}
val dispatchReceiverValue: KtReceiverValue?
val extensionReceiverValue: KtReceiverValue?
if (explicitReceiverKind == ExplicitReceiverKind.DISPATCH_RECEIVER) {
dispatchReceiverValue = explicitReceiverValue
if (firstArgIsExtensionReceiver) {
extensionReceiverValue = (fir as FirFunctionCall).arguments.first().toKtReceiverValue()
} else {
dispatchReceiver = fir.dispatchReceiver.toKtReceiverValue()
extensionReceiver = explicitReceiver
extensionReceiverValue = extensionReceiver.toKtReceiverValue()
}
} else {
dispatchReceiver = fir.dispatchReceiver.toKtReceiverValue()
extensionReceiver = fir.extensionReceiver.toKtReceiverValue()
dispatchReceiverValue = dispatchReceiver.toKtReceiverValue()
extensionReceiverValue = explicitReceiverValue
}
val substitutor = fir.createConeSubstitutorFromTypeArguments() ?: return null
KtPartiallyAppliedSymbol(
unsubstitutedKtSignature.substitute(substitutor.toKtSubstitutor()),
dispatchReceiver,
extensionReceiver,
return KtPartiallyAppliedSymbol(
unsubstitutedKtSignature.substitute(substitutor),
dispatchReceiverValue,
extensionReceiverValue,
)
}
val partiallyAppliedSymbol = if (candidate != null) {
if (fir is FirImplicitInvokeCall ||
(fir.calleeOrCandidateName != OperatorNameConventions.INVOKE && targetSymbol.isInvokeFunction())
) {
// Implicit invoke (e.g., `x()`) will have a different callee symbol (e.g., `x`) than the candidate (e.g., `invoke`).
createKtPartiallyAppliedSymbolForImplicitInvoke(
candidate.dispatchReceiverValue?.receiverExpression ?: FirNoReceiverExpression,
candidate.extensionReceiverValue?.receiverExpression ?: FirNoReceiverExpression,
candidate.explicitReceiverKind
)
} else {
KtPartiallyAppliedSymbol(
unsubstitutedKtSignature.substitute(substitutor),
candidate.dispatchReceiverValue?.receiverExpression?.toKtReceiverValue(),
candidate.extensionReceiverValue?.receiverExpression?.toKtReceiverValue(),
)
}
} else if (fir is FirQualifiedAccess) {
if (fir is FirImplicitInvokeCall) {
val explicitReceiverKind = if (fir.explicitReceiver == fir.dispatchReceiver) {
ExplicitReceiverKind.DISPATCH_RECEIVER
} else {
ExplicitReceiverKind.EXTENSION_RECEIVER
}
createKtPartiallyAppliedSymbolForImplicitInvoke(fir.dispatchReceiver, fir.extensionReceiver, explicitReceiverKind)
} else {
KtPartiallyAppliedSymbol(
unsubstitutedKtSignature.substitute(substitutor),
fir.dispatchReceiver.toKtReceiverValue(),
fir.extensionReceiver.toKtReceiverValue()
)
}
} else {
KtPartiallyAppliedSymbol(unsubstitutedKtSignature, _dispatchReceiver = null, _extensionReceiver = null)
}
@@ -366,7 +402,7 @@ internal class KtFirCallResolver(
argumentMappingWithoutExtensionReceiver
?.createArgumentMapping(partiallyAppliedSymbol.signature as KtFunctionLikeSignature<*>)
?: LinkedHashMap(),
fir is FirImplicitInvokeCall
isImplicitInvoke
)
}
is FirExpressionWithSmartcast -> createKtCall(psi, fir.originalExpression, candidate, resolveFragmentOfCall)
@@ -673,51 +709,50 @@ internal class KtFirCallResolver(
private val resolutionContext = ResolutionContext(firSession, bodyResolveComponents, stubBodyResolveTransformer.context)
@OptIn(PrivateForInline::class)
fun getAllCandidates(functionCall: FirFunctionCall, element: KtElement): List<KtCallInfo> {
val towerContext = firResolveState.getTowerContextProvider(element.containingKtFile).getClosestAvailableParentContext(element)
towerContext?.let { bodyResolveComponents.context.replaceTowerDataContext(it) }
// Note: All candidate symbols should have the same name
val name =
functionCall.calleeReference.getCandidateSymbols().firstOrNull()?.safeAs<FirFunctionSymbol<*>>()?.name ?: return emptyList()
return bodyResolveComponents.context.withFile(firFile, bodyResolveComponents) {
val candidates = bodyResolveComponents.callResolver.collectAllCandidates(
functionCall,
name,
element.getContainingDeclarations(),
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
)
candidates.mapNotNull { convertToKtCallInfo(functionCall, element, it.candidate, it.isInBestCandidates) }
}
return candidates.mapNotNull { convertToKtCallInfo(originalFunctionCall, element, it.candidate, it.isInBestCandidates) }
}
private fun KtElement.getContainingDeclarations(): List<FirDeclaration> {
fun KtElement.getContainingKtDeclaration(): KtDeclaration? =
when (val container = this.parentOfType<KtDeclaration>()) {
is KtDestructuringDeclaration -> container.parentOfType()
else -> container
}
val containingDeclarations = mutableListOf<FirDeclaration>()
var current = getContainingKtDeclaration()
while (current != null) {
val firElement = current.getOrBuildFir(firResolveState)
val firDeclaration = when (firElement) {
is FirAnonymousObjectExpression -> firElement.anonymousObject
is FirAnonymousFunctionExpression -> firElement.anonymousFunction
is FirDeclaration -> firElement
else -> error(
"Expected a FirDeclaration for KtDeclaration (type: ${current::class.simpleName}) " +
"but was ${firElement?.let { it::class.simpleName }}. KtDeclaration text:\n${current.text}"
)
}
containingDeclarations += firDeclaration
current = current.getContainingKtDeclaration()
}
return containingDeclarations.asReversed()
@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)
}
@OptIn(SymbolInternals::class)
private fun convertToKtCallInfo(
functionCall: FirFunctionCall,
element: KtElement,
@@ -739,6 +774,34 @@ internal class KtFirCallResolver(
}
}
private val FirResolvable.calleeOrCandidateName: Name?
get() {
val calleeReference = calleeReference
if (calleeReference !is FirNamedReference) return null
// In most cases, we can get the callee name from the callee's candidate symbols. However, there is at least one case where we
// cannot do so:
// ```
// fun x(c: Char) {}
// fun call(x: kotlin.Int) {
// operator fun Int.invoke(a: Int) {}
// operator fun Int.invoke(b: Boolean) {}
// <expr>x()</expr>
// }
// ```
// The candidates for the call will both be `invoke`. We can keep it simple by getting the name from the callee reference's PSI
// element (`x` in the above example) if possible.
return when (val psi = calleeReference.psi) {
is KtNameReferenceExpression -> psi.getReferencedNameAsName()
else -> {
// 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
// the applicability if not successful.
calleeReference.getCandidateSymbols().firstOrNull()?.safeAs<FirCallableSymbol<*>>()?.name
}
}
}
private fun FirArrayOfCall.toKtCallInfo(): KtCallInfo? {
val arrayOfSymbol = with(analysisSession) {
val type = typeRef.coneTypeSafe<ConeClassLikeType>()
@@ -40,6 +40,12 @@ public class FirResolveCallTestGenerated extends AbstractResolveCallTest {
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/ambiguous.kt");
}
@Test
@TestMetadata("ambiguousImplicitInvoke.kt")
public void testAmbiguousImplicitInvoke() throws Exception {
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/ambiguousImplicitInvoke.kt");
}
@Test
@TestMetadata("ambiguousWithExplicitTypeParameters.kt")
public void testAmbiguousWithExplicitTypeParameters() throws Exception {
@@ -55,6 +55,12 @@ public class FirResolveCandidatesTestGenerated extends AbstractResolveCandidates
runTest("analysis/analysis-api/testData/components/callResolver/resolveCandidates/multipleCandidates/ambiguous.kt");
}
@Test
@TestMetadata("ambiguousImplicitInvoke.kt")
public void testAmbiguousImplicitInvoke() throws Exception {
runTest("analysis/analysis-api/testData/components/callResolver/resolveCandidates/multipleCandidates/ambiguousImplicitInvoke.kt");
}
@Test
@TestMetadata("ambiguousWithExplicitTypeParameters.kt")
public void testAmbiguousWithExplicitTypeParameters() throws Exception {
@@ -66,6 +72,18 @@ public class FirResolveCandidatesTestGenerated extends AbstractResolveCandidates
public void testAmbiguousWithInferredTypeParameters() throws Exception {
runTest("analysis/analysis-api/testData/components/callResolver/resolveCandidates/multipleCandidates/ambiguousWithInferredTypeParameters.kt");
}
@Test
@TestMetadata("implicitInvoke.kt")
public void testImplicitInvoke() throws Exception {
runTest("analysis/analysis-api/testData/components/callResolver/resolveCandidates/multipleCandidates/implicitInvoke.kt");
}
@Test
@TestMetadata("implicitInvokeWithReceiver.kt")
public void testImplicitInvokeWithReceiver() throws Exception {
runTest("analysis/analysis-api/testData/components/callResolver/resolveCandidates/multipleCandidates/implicitInvokeWithReceiver.kt");
}
}
@Nested
@@ -77,6 +95,24 @@ public class FirResolveCandidatesTestGenerated extends AbstractResolveCandidates
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate"), Pattern.compile("^(.+)\\.kt$"), null, true);
}
@Test
@TestMetadata("consecutiveImplicitInvoke1.kt")
public void testConsecutiveImplicitInvoke1() throws Exception {
runTest("analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/consecutiveImplicitInvoke1.kt");
}
@Test
@TestMetadata("consecutiveImplicitInvoke2.kt")
public void testConsecutiveImplicitInvoke2() throws Exception {
runTest("analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/consecutiveImplicitInvoke2.kt");
}
@Test
@TestMetadata("consecutiveImplicitInvoke3.kt")
public void testConsecutiveImplicitInvoke3() throws Exception {
runTest("analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/consecutiveImplicitInvoke3.kt");
}
@Test
@TestMetadata("functionCall.kt")
public void testFunctionCall() throws Exception {
@@ -7,7 +7,9 @@ package org.jetbrains.kotlin.analysis.api.impl.base.test.components
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
import org.jetbrains.kotlin.analysis.api.calls.KtCall
import org.jetbrains.kotlin.analysis.api.calls.KtCallInfo
import org.jetbrains.kotlin.analysis.api.calls.KtCallableMemberCall
import org.jetbrains.kotlin.analysis.api.diagnostics.KtDiagnostic
import org.jetbrains.kotlin.analysis.api.impl.base.KtMapBackedSubstitutor
import org.jetbrains.kotlin.analysis.api.symbols.*
@@ -80,7 +82,8 @@ internal fun KtAnalysisSession.stringRepresentation(call: KtCallInfo): String {
is Name -> asString()
else -> buildString {
val clazz = this@stringValue::class
append(clazz.simpleName!!)
val className = clazz.simpleName!!
append(className)
appendLine(":")
clazz.memberProperties
.filter { it.name != "token" && it.visibility == KVisibility.PUBLIC }
@@ -88,9 +91,18 @@ internal fun KtAnalysisSession.stringRepresentation(call: KtCallInfo): String {
val name = property.name
@Suppress("UNCHECKED_CAST")
val value =
(property as KProperty1<Any, *>).get(this@stringValue)?.stringValue()?.indented()
"$name = $value"
val value = (property as KProperty1<Any, *>).get(this@stringValue)?.let {
if (className == "KtErrorCallInfo" && name == "candidateCalls") {
// The order of calls in KtErrorCallInfo.candidateCalls is non-deterministic. Sort by symbol string value.
(it as Collection<KtCall>).sortedWith { call1, call2 ->
if (call1 is KtCallableMemberCall<*, *> && call2 is KtCallableMemberCall<*, *>) {
call1.partiallyAppliedSymbol.stringValue().compareTo(call2.partiallyAppliedSymbol.stringValue())
} else 0
}
} else it
}
val valueAsString = value?.stringValue()?.indented()
"$name = $valueAsString"
}
}
}
@@ -0,0 +1,44 @@
KtErrorCallInfo:
candidateCalls = [
KtSimpleFunctionCall:
isImplicitInvoke = true
partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
dispatchReceiver = null
extensionReceiver = KtExplicitReceiverValue:
expression = x
isSafeNavigation = false
signature = KtFunctionLikeSignature:
receiverType = kotlin.Int
returnType = kotlin.Unit
symbol = invoke(<extension receiver>: kotlin.Int, a: kotlin.String): kotlin.Unit
valueParameters = [
KtVariableLikeSignature:
name = a
receiverType = null
returnType = kotlin.String
symbol = a: kotlin.String
]
argumentMapping = {},
KtSimpleFunctionCall:
isImplicitInvoke = true
partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
dispatchReceiver = null
extensionReceiver = KtExplicitReceiverValue:
expression = x
isSafeNavigation = false
signature = KtFunctionLikeSignature:
receiverType = kotlin.Int
returnType = kotlin.Unit
symbol = invoke(<extension receiver>: kotlin.Int, b: kotlin.Boolean): kotlin.Unit
valueParameters = [
KtVariableLikeSignature:
name = b
receiverType = null
returnType = kotlin.Boolean
symbol = b: kotlin.Boolean
]
argumentMapping = {}
]
diagnostic = ERROR<NONE_APPLICABLE: None of the following functions can be called with the arguments supplied:
local final operator fun Int.invoke(b: Boolean): Unit defined in call
local final operator fun Int.invoke(a: String): Unit defined in call>
@@ -0,0 +1,7 @@
fun x(c: Char) {}
fun call(x: kotlin.Int) {
operator fun Int.invoke(a: String) {}
operator fun Int.invoke(b: Boolean) {}
<expr>x()</expr>
}
@@ -0,0 +1,42 @@
KtErrorCallInfo:
candidateCalls = [
KtSimpleFunctionCall:
isImplicitInvoke = true
partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
dispatchReceiver = null
extensionReceiver = KtExplicitReceiverValue:
expression = x
isSafeNavigation = false
signature = KtFunctionLikeSignature:
receiverType = kotlin.Int
returnType = kotlin.Unit
symbol = invoke(<extension receiver>: kotlin.Int, a: kotlin.String): kotlin.Unit
valueParameters = [
KtVariableLikeSignature:
name = a
receiverType = null
returnType = kotlin.String
symbol = a: kotlin.String
]
argumentMapping = {},
KtSimpleFunctionCall:
isImplicitInvoke = true
partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
dispatchReceiver = null
extensionReceiver = KtExplicitReceiverValue:
expression = x
isSafeNavigation = false
signature = KtFunctionLikeSignature:
receiverType = kotlin.Int
returnType = kotlin.Unit
symbol = invoke(<extension receiver>: kotlin.Int, b: kotlin.Boolean): kotlin.Unit
valueParameters = [
KtVariableLikeSignature:
name = b
receiverType = null
returnType = kotlin.Boolean
symbol = b: kotlin.Boolean
]
argumentMapping = {}
]
diagnostic = ERROR<NONE_APPLICABLE: None of the following functions are applicable: [<local>/invoke, <local>/invoke]>
@@ -1,22 +1,5 @@
KtErrorCallInfo:
candidateCalls = [
KtDelegatedConstructorCall:
kind = THIS_CALL
partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
dispatchReceiver = null
extensionReceiver = null
signature = KtFunctionLikeSignature:
receiverType = null
returnType = Sub
symbol = <constructor>(p: kotlin.Int): Sub
valueParameters = [
KtVariableLikeSignature:
name = p
receiverType = null
returnType = kotlin.Int
symbol = p: kotlin.Int
]
argumentMapping = {},
KtDelegatedConstructorCall:
kind = THIS_CALL
partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
@@ -38,6 +21,23 @@ KtErrorCallInfo:
returnType = kotlin.Int
symbol = j: kotlin.Int
]
argumentMapping = {},
KtDelegatedConstructorCall:
kind = THIS_CALL
partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
dispatchReceiver = null
extensionReceiver = null
signature = KtFunctionLikeSignature:
receiverType = null
returnType = Sub
symbol = <constructor>(p: kotlin.Int): Sub
valueParameters = [
KtVariableLikeSignature:
name = p
receiverType = null
returnType = kotlin.Int
symbol = p: kotlin.Int
]
argumentMapping = {}
]
diagnostic = ERROR<NONE_APPLICABLE: None of the following functions are applicable: [/Sub.Sub, /Sub.Sub]>
@@ -11,12 +11,14 @@ KtErrorCallInfo:
symbol = /function(a: kotlin.Char): kotlin.Unit
valueParameters = [
KtVariableLikeSignature:
name = a
receiverType = null
returnType = kotlin.Char
symbol = a: kotlin.Char
]
argumentMapping = {
1 -> (KtVariableLikeSignature:
name = a
receiverType = null
returnType = kotlin.Char
symbol = a: kotlin.Char)
@@ -37,12 +39,14 @@ KtErrorCallInfo:
symbol = /function(b: kotlin.Boolean): kotlin.Unit
valueParameters = [
KtVariableLikeSignature:
name = b
receiverType = null
returnType = kotlin.Boolean
symbol = b: kotlin.Boolean
]
argumentMapping = {
1 -> (KtVariableLikeSignature:
name = b
receiverType = null
returnType = kotlin.Boolean
symbol = b: kotlin.Boolean)
@@ -63,12 +67,14 @@ KtErrorCallInfo:
symbol = /function(c: kotlin.String): kotlin.Unit
valueParameters = [
KtVariableLikeSignature:
name = c
receiverType = null
returnType = kotlin.String
symbol = c: kotlin.String
]
argumentMapping = {
1 -> (KtVariableLikeSignature:
name = c
receiverType = null
returnType = kotlin.String
symbol = c: kotlin.String)
@@ -0,0 +1,7 @@
fun x(c: Char) {}
fun call(x: kotlin.Int) {
operator fun Int.invoke(a: String) {}
operator fun Int.invoke(b: Boolean) {}
<expr>x()</expr>
}
@@ -0,0 +1,69 @@
KtErrorCallInfo:
candidateCalls = [
KtSimpleFunctionCall:
isImplicitInvoke = true
partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
dispatchReceiver = null
extensionReceiver = KtExplicitReceiverValue:
expression = x
isSafeNavigation = false
signature = KtFunctionLikeSignature:
receiverType = kotlin.Int
returnType = kotlin.Unit
symbol = invoke(<extension receiver>: kotlin.Int, a: kotlin.String): kotlin.Unit
valueParameters = [
KtVariableLikeSignature:
name = a
receiverType = null
returnType = kotlin.String
symbol = a: kotlin.String
]
argumentMapping = {}
]
diagnostic = ERROR<NO_VALUE_FOR_PARAMETER: No value passed for parameter 'a'>
KtErrorCallInfo:
candidateCalls = [
KtSimpleFunctionCall:
isImplicitInvoke = true
partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
dispatchReceiver = null
extensionReceiver = KtExplicitReceiverValue:
expression = x
isSafeNavigation = false
signature = KtFunctionLikeSignature:
receiverType = kotlin.Int
returnType = kotlin.Unit
symbol = invoke(<extension receiver>: kotlin.Int, b: kotlin.Boolean): kotlin.Unit
valueParameters = [
KtVariableLikeSignature:
name = b
receiverType = null
returnType = kotlin.Boolean
symbol = b: kotlin.Boolean
]
argumentMapping = {}
]
diagnostic = ERROR<NO_VALUE_FOR_PARAMETER: No value passed for parameter 'b'>
KtErrorCallInfo:
candidateCalls = [
KtSimpleFunctionCall:
isImplicitInvoke = false
partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
dispatchReceiver = null
extensionReceiver = null
signature = KtFunctionLikeSignature:
receiverType = null
returnType = kotlin.Unit
symbol = /x(c: kotlin.Char): kotlin.Unit
valueParameters = [
KtVariableLikeSignature:
name = c
receiverType = null
returnType = kotlin.Char
symbol = c: kotlin.Char
]
argumentMapping = {}
]
diagnostic = ERROR<NO_VALUE_FOR_PARAMETER: No value passed for parameter 'c'>
@@ -11,16 +11,19 @@ KtErrorCallInfo:
symbol = /function(t: T, a: kotlin.Char): kotlin.Unit
valueParameters = [
KtVariableLikeSignature:
name = t
receiverType = null
returnType = kotlin.Int
symbol = t: T,
KtVariableLikeSignature:
name = a
receiverType = null
returnType = kotlin.Char
symbol = a: kotlin.Char
]
argumentMapping = {
1 -> (KtVariableLikeSignature:
name = t
receiverType = null
returnType = kotlin.Int
symbol = t: T)
@@ -41,16 +44,19 @@ KtErrorCallInfo:
symbol = /function(u: U, b: kotlin.Boolean): kotlin.Unit
valueParameters = [
KtVariableLikeSignature:
name = u
receiverType = null
returnType = kotlin.Int
symbol = u: U,
KtVariableLikeSignature:
name = b
receiverType = null
returnType = kotlin.Boolean
symbol = b: kotlin.Boolean
]
argumentMapping = {
1 -> (KtVariableLikeSignature:
name = u
receiverType = null
returnType = kotlin.Int
symbol = u: U)
@@ -71,16 +77,19 @@ KtErrorCallInfo:
symbol = /function(v: V, c: kotlin.String): kotlin.Unit
valueParameters = [
KtVariableLikeSignature:
name = v
receiverType = null
returnType = kotlin.Int
symbol = v: V,
KtVariableLikeSignature:
name = c
receiverType = null
returnType = kotlin.String
symbol = c: kotlin.String
]
argumentMapping = {
1 -> (KtVariableLikeSignature:
name = v
receiverType = null
returnType = kotlin.Int
symbol = v: V)
@@ -11,16 +11,19 @@ KtErrorCallInfo:
symbol = /function(t: T, a: kotlin.Char): kotlin.Unit
valueParameters = [
KtVariableLikeSignature:
name = t
receiverType = null
returnType = T
symbol = t: T,
KtVariableLikeSignature:
name = a
receiverType = null
returnType = kotlin.Char
symbol = a: kotlin.Char
]
argumentMapping = {
1 -> (KtVariableLikeSignature:
name = t
receiverType = null
returnType = T
symbol = t: T)
@@ -41,16 +44,19 @@ KtErrorCallInfo:
symbol = /function(u: U, b: kotlin.Boolean): kotlin.Unit
valueParameters = [
KtVariableLikeSignature:
name = u
receiverType = null
returnType = U
symbol = u: U,
KtVariableLikeSignature:
name = b
receiverType = null
returnType = kotlin.Boolean
symbol = b: kotlin.Boolean
]
argumentMapping = {
1 -> (KtVariableLikeSignature:
name = u
receiverType = null
returnType = U
symbol = u: U)
@@ -71,16 +77,19 @@ KtErrorCallInfo:
symbol = /function(v: V, c: kotlin.String): kotlin.Unit
valueParameters = [
KtVariableLikeSignature:
name = v
receiverType = null
returnType = V
symbol = v: V,
KtVariableLikeSignature:
name = c
receiverType = null
returnType = kotlin.String
symbol = c: kotlin.String
]
argumentMapping = {
1 -> (KtVariableLikeSignature:
name = v
receiverType = null
returnType = V
symbol = v: V)
@@ -0,0 +1,8 @@
operator fun Int.invoke(i: Int) {}
fun x(c: Char) {}
fun call(x: kotlin.Int) {
fun x(b: Boolean) {}
<expr>x(true)</expr>
}
@@ -0,0 +1,82 @@
KtSuccessCallInfo:
call = KtSimpleFunctionCall:
isImplicitInvoke = false
partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
dispatchReceiver = null
extensionReceiver = null
signature = KtFunctionLikeSignature:
receiverType = null
returnType = kotlin.Unit
symbol = x(b: kotlin.Boolean): kotlin.Unit
valueParameters = [
KtVariableLikeSignature:
name = b
receiverType = null
returnType = kotlin.Boolean
symbol = b: kotlin.Boolean
]
argumentMapping = {
true -> (KtVariableLikeSignature:
name = b
receiverType = null
returnType = kotlin.Boolean
symbol = b: kotlin.Boolean)
}
KtErrorCallInfo:
candidateCalls = [
KtSimpleFunctionCall:
isImplicitInvoke = false
partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
dispatchReceiver = null
extensionReceiver = null
signature = KtFunctionLikeSignature:
receiverType = null
returnType = kotlin.Unit
symbol = /x(c: kotlin.Char): kotlin.Unit
valueParameters = [
KtVariableLikeSignature:
name = c
receiverType = null
returnType = kotlin.Char
symbol = c: kotlin.Char
]
argumentMapping = {
true -> (KtVariableLikeSignature:
name = c
receiverType = null
returnType = kotlin.Char
symbol = c: kotlin.Char)
}
]
diagnostic = ERROR<ARGUMENT_TYPE_MISMATCH: Argument type mismatch: actual type is kotlin/Boolean but kotlin/Char was expected>
KtErrorCallInfo:
candidateCalls = [
KtSimpleFunctionCall:
isImplicitInvoke = true
partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
dispatchReceiver = null
extensionReceiver = KtExplicitReceiverValue:
expression = x
isSafeNavigation = false
signature = KtFunctionLikeSignature:
receiverType = kotlin.Int
returnType = kotlin.Unit
symbol = /invoke(<extension receiver>: kotlin.Int, i: kotlin.Int): kotlin.Unit
valueParameters = [
KtVariableLikeSignature:
name = i
receiverType = null
returnType = kotlin.Int
symbol = i: kotlin.Int
]
argumentMapping = {
true -> (KtVariableLikeSignature:
name = i
receiverType = null
returnType = kotlin.Int
symbol = i: kotlin.Int)
}
]
diagnostic = ERROR<ARGUMENT_TYPE_MISMATCH: Argument type mismatch: actual type is kotlin/Boolean but kotlin/Int was expected>
@@ -0,0 +1,9 @@
operator fun Int.invoke(i: Int) {}
class A(val x: Int) {
fun x(b: Boolean) {}
}
fun call(a: A) {
<expr>a.x(1)</expr>
}
@@ -0,0 +1,56 @@
KtErrorCallInfo:
candidateCalls = [
KtSimpleFunctionCall:
isImplicitInvoke = false
partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
dispatchReceiver = KtExplicitReceiverValue:
expression = a
isSafeNavigation = false
extensionReceiver = null
signature = KtFunctionLikeSignature:
receiverType = null
returnType = kotlin.Unit
symbol = /A.x(<dispatch receiver>: A, b: kotlin.Boolean): kotlin.Unit
valueParameters = [
KtVariableLikeSignature:
name = b
receiverType = null
returnType = kotlin.Boolean
symbol = b: kotlin.Boolean
]
argumentMapping = {
1 -> (KtVariableLikeSignature:
name = b
receiverType = null
returnType = kotlin.Boolean
symbol = b: kotlin.Boolean)
}
]
diagnostic = ERROR<ARGUMENT_TYPE_MISMATCH: Argument type mismatch: actual type is kotlin/Int but kotlin/Boolean was expected>
KtSuccessCallInfo:
call = KtSimpleFunctionCall:
isImplicitInvoke = true
partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
dispatchReceiver = null
extensionReceiver = KtExplicitReceiverValue:
expression = x
isSafeNavigation = false
signature = KtFunctionLikeSignature:
receiverType = kotlin.Int
returnType = kotlin.Unit
symbol = /invoke(<extension receiver>: kotlin.Int, i: kotlin.Int): kotlin.Unit
valueParameters = [
KtVariableLikeSignature:
name = i
receiverType = null
returnType = kotlin.Int
symbol = i: kotlin.Int
]
argumentMapping = {
1 -> (KtVariableLikeSignature:
name = i
receiverType = null
returnType = kotlin.Int
symbol = i: kotlin.Int)
}
@@ -0,0 +1,6 @@
operator fun Int.invoke() : Long = 1L
operator fun Long.invoke() : Double = 1.0
operator fun Double.invoke() {}
fun test(i: Int) {
<expr>i()</expr>()()
}
@@ -0,0 +1,50 @@
KtSuccessCallInfo:
call = KtSimpleFunctionCall:
isImplicitInvoke = true
partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
dispatchReceiver = null
extensionReceiver = KtExplicitReceiverValue:
expression = i
isSafeNavigation = false
signature = KtFunctionLikeSignature:
receiverType = kotlin.Int
returnType = kotlin.Long
symbol = /invoke(<extension receiver>: kotlin.Int): kotlin.Long
valueParameters = []
argumentMapping = {}
KtErrorCallInfo:
candidateCalls = [
KtSimpleFunctionCall:
isImplicitInvoke = true
partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
dispatchReceiver = null
extensionReceiver = KtExplicitReceiverValue:
expression = i
isSafeNavigation = false
signature = KtFunctionLikeSignature:
receiverType = kotlin.Long
returnType = kotlin.Double
symbol = /invoke(<extension receiver>: kotlin.Long): kotlin.Double
valueParameters = []
argumentMapping = {}
]
diagnostic = ERROR<UNRESOLVED_REFERENCE_WRONG_RECEIVER: Unresolved reference. None of the following candidates is applicable because of receiver type mismatch: [/invoke]>
KtErrorCallInfo:
candidateCalls = [
KtSimpleFunctionCall:
isImplicitInvoke = true
partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
dispatchReceiver = null
extensionReceiver = KtExplicitReceiverValue:
expression = i
isSafeNavigation = false
signature = KtFunctionLikeSignature:
receiverType = kotlin.Double
returnType = kotlin.Unit
symbol = /invoke(<extension receiver>: kotlin.Double): kotlin.Unit
valueParameters = []
argumentMapping = {}
]
diagnostic = ERROR<UNRESOLVED_REFERENCE_WRONG_RECEIVER: Unresolved reference. None of the following candidates is applicable because of receiver type mismatch: [/invoke]>
@@ -0,0 +1,6 @@
operator fun Int.invoke() : Long = 1L
operator fun Long.invoke() : Double = 1.0
operator fun Double.invoke() {}
fun test(i: Int) {
<expr>i()()</expr>()
}
@@ -0,0 +1,50 @@
KtErrorCallInfo:
candidateCalls = [
KtSimpleFunctionCall:
isImplicitInvoke = true
partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
dispatchReceiver = null
extensionReceiver = KtExplicitReceiverValue:
expression = i()
isSafeNavigation = false
signature = KtFunctionLikeSignature:
receiverType = kotlin.Int
returnType = kotlin.Long
symbol = /invoke(<extension receiver>: kotlin.Int): kotlin.Long
valueParameters = []
argumentMapping = {}
]
diagnostic = ERROR<UNRESOLVED_REFERENCE_WRONG_RECEIVER: Unresolved reference. None of the following candidates is applicable because of receiver type mismatch: [/invoke]>
KtSuccessCallInfo:
call = KtSimpleFunctionCall:
isImplicitInvoke = true
partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
dispatchReceiver = null
extensionReceiver = KtExplicitReceiverValue:
expression = i()
isSafeNavigation = false
signature = KtFunctionLikeSignature:
receiverType = kotlin.Long
returnType = kotlin.Double
symbol = /invoke(<extension receiver>: kotlin.Long): kotlin.Double
valueParameters = []
argumentMapping = {}
KtErrorCallInfo:
candidateCalls = [
KtSimpleFunctionCall:
isImplicitInvoke = true
partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
dispatchReceiver = null
extensionReceiver = KtExplicitReceiverValue:
expression = i()
isSafeNavigation = false
signature = KtFunctionLikeSignature:
receiverType = kotlin.Double
returnType = kotlin.Unit
symbol = /invoke(<extension receiver>: kotlin.Double): kotlin.Unit
valueParameters = []
argumentMapping = {}
]
diagnostic = ERROR<UNRESOLVED_REFERENCE_WRONG_RECEIVER: Unresolved reference. None of the following candidates is applicable because of receiver type mismatch: [/invoke]>
@@ -0,0 +1,6 @@
operator fun Int.invoke() : Long = 1L
operator fun Long.invoke() : Double = 1.0
operator fun Double.invoke() {}
fun test(i: Int) {
<expr>i()()()</expr>
}
@@ -0,0 +1,50 @@
KtErrorCallInfo:
candidateCalls = [
KtSimpleFunctionCall:
isImplicitInvoke = true
partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
dispatchReceiver = null
extensionReceiver = KtExplicitReceiverValue:
expression = i()()
isSafeNavigation = false
signature = KtFunctionLikeSignature:
receiverType = kotlin.Int
returnType = kotlin.Long
symbol = /invoke(<extension receiver>: kotlin.Int): kotlin.Long
valueParameters = []
argumentMapping = {}
]
diagnostic = ERROR<UNRESOLVED_REFERENCE_WRONG_RECEIVER: Unresolved reference. None of the following candidates is applicable because of receiver type mismatch: [/invoke]>
KtErrorCallInfo:
candidateCalls = [
KtSimpleFunctionCall:
isImplicitInvoke = true
partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
dispatchReceiver = null
extensionReceiver = KtExplicitReceiverValue:
expression = i()()
isSafeNavigation = false
signature = KtFunctionLikeSignature:
receiverType = kotlin.Long
returnType = kotlin.Double
symbol = /invoke(<extension receiver>: kotlin.Long): kotlin.Double
valueParameters = []
argumentMapping = {}
]
diagnostic = ERROR<UNRESOLVED_REFERENCE_WRONG_RECEIVER: Unresolved reference. None of the following candidates is applicable because of receiver type mismatch: [/invoke]>
KtSuccessCallInfo:
call = KtSimpleFunctionCall:
isImplicitInvoke = true
partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
dispatchReceiver = null
extensionReceiver = KtExplicitReceiverValue:
expression = i()()
isSafeNavigation = false
signature = KtFunctionLikeSignature:
receiverType = kotlin.Double
returnType = kotlin.Unit
symbol = /invoke(<extension receiver>: kotlin.Double): kotlin.Unit
valueParameters = []
argumentMapping = {}
@@ -2,7 +2,9 @@ KtSuccessCallInfo:
call = KtSimpleFunctionCall:
isImplicitInvoke = true
partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
dispatchReceiver = null
dispatchReceiver = KtExplicitReceiverValue:
expression = x
isSafeNavigation = false
extensionReceiver = null
signature = KtFunctionLikeSignature:
receiverType = null
@@ -3,7 +3,9 @@ KtSuccessCallInfo:
isImplicitInvoke = true
partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
dispatchReceiver = null
extensionReceiver = null
extensionReceiver = KtExplicitReceiverValue:
expression = x
isSafeNavigation = false
signature = KtFunctionLikeSignature:
receiverType = kotlin.Int
returnType = kotlin.String
@@ -178,6 +178,9 @@ class FirCallResolver(
return super.consumeCandidate(group, candidate, context)
}
// We want to get candidates at all tower levels.
override fun shouldStopAtTheLevel(group: TowerGroup): Boolean = false
val allCandidates: List<Candidate>
get() = allCandidatesSet.toList()
}
@@ -322,6 +322,11 @@ private inline fun <T : FirExpression> BodyResolveComponents.transformExpression
smartcastBuilder: () -> FirWrappedExpressionWithSmartcastBuilder<T>,
smartcastToNullBuilder: () -> FirWrappedExpressionWithSmartcastToNullBuilder<T>
): FirWrappedExpressionWithSmartcastBuilder<T>? {
// No need to check for smartcast if the expression was already resolved.
containingDeclarations.lastOrNull()?.let { closestDeclaration ->
if (closestDeclaration.resolvePhase >= FirResolvePhase.BODY_RESOLVE) return null
}
val (stability, typesFromSmartCast) = smartcastExtractor(expression) ?: return null
val smartcastStability = stability.impliedSmartcastStability
?: if (dataFlowAnalyzer.isAccessToUnstableLocalVariable(expression)) {
@@ -48,7 +48,7 @@ open class CandidateCollector(
fun bestCandidates(): List<Candidate> = candidates
fun shouldStopAtTheLevel(group: TowerGroup): Boolean =
open fun shouldStopAtTheLevel(group: TowerGroup): Boolean =
currentApplicability.shouldStopResolve && bestGroup < group
fun isSuccess(): Boolean {