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:
committed by
Ilya Kirillov
parent
ace826c570
commit
9b9da94a09
+6
@@ -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<*>? =
|
||||
|
||||
+147
-84
@@ -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>()
|
||||
|
||||
+6
@@ -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 {
|
||||
|
||||
+36
@@ -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 {
|
||||
|
||||
+16
-4
@@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+44
@@ -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>
|
||||
Vendored
+7
@@ -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>
|
||||
}
|
||||
Vendored
+42
@@ -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]>
|
||||
+17
-17
@@ -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]>
|
||||
|
||||
+6
@@ -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)
|
||||
|
||||
+7
@@ -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>
|
||||
}
|
||||
+69
@@ -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'>
|
||||
+9
@@ -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)
|
||||
|
||||
+9
@@ -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)
|
||||
|
||||
+8
@@ -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>
|
||||
}
|
||||
+82
@@ -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>
|
||||
+9
@@ -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>
|
||||
}
|
||||
+56
@@ -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)
|
||||
}
|
||||
+6
@@ -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>()()
|
||||
}
|
||||
+50
@@ -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]>
|
||||
+6
@@ -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>()
|
||||
}
|
||||
+50
@@ -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]>
|
||||
+6
@@ -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>
|
||||
}
|
||||
+50
@@ -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 = {}
|
||||
+3
-1
@@ -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
-1
@@ -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)) {
|
||||
|
||||
+1
-1
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user