From a0f0fa5a4758795781fb58625fa3fc8774de96b2 Mon Sep 17 00:00:00 2001 From: Ilya Kirillov Date: Wed, 20 Jul 2022 19:20:49 +0200 Subject: [PATCH] [Analysis API FIR] fix candidate collection for delegatedConstructor call ^KTIJ-20446 --- ...eModuleResolveCandidatesTestGenerated.java | 24 ++++++ .../api/fir/components/KtFirCallResolver.kt | 28 ++++++- ...eModuleResolveCandidatesTestGenerated.java | 24 ++++++ ...eModuleResolveCandidatesTestGenerated.java | 24 ++++++ .../delegatedConstructor.descriptors.txt | 77 +++++++++++++++++++ .../delegatedConstructor.kt | 6 ++ .../delegatedConstructor.txt | 70 +++++++++++++++++ .../delegatedConstructorApplicable.kt | 4 + .../delegatedConstructorApplicable.txt | 29 +++++++ ...tedConstructorInapplicable.descriptors.txt | 30 ++++++++ .../delegatedConstructorInapplicable.kt | 4 + .../delegatedConstructorInapplicable.txt | 30 ++++++++ ...leDifferentParametersCount.descriptors.txt | 16 ++++ ...torInapplicableDifferentParametersCount.kt | 4 + ...orInapplicableDifferentParametersCount.txt | 16 ++++ .../api/fir/resolver/AllCandidatesResolver.kt | 65 +++++++++++++--- .../level/api/fir/resolver/resolverUtils.kt | 2 +- .../jetbrains/kotlin/fir/FirCallResolver.kt | 41 +++++----- .../resolve/calls/tower/FirTowerResolver.kt | 2 +- 19 files changed, 457 insertions(+), 39 deletions(-) create mode 100644 analysis/analysis-api/testData/components/callResolver/resolveCandidates/multipleCandidates/delegatedConstructor.descriptors.txt create mode 100644 analysis/analysis-api/testData/components/callResolver/resolveCandidates/multipleCandidates/delegatedConstructor.kt create mode 100644 analysis/analysis-api/testData/components/callResolver/resolveCandidates/multipleCandidates/delegatedConstructor.txt create mode 100644 analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/delegatedConstructorApplicable.kt create mode 100644 analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/delegatedConstructorApplicable.txt create mode 100644 analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/delegatedConstructorInapplicable.descriptors.txt create mode 100644 analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/delegatedConstructorInapplicable.kt create mode 100644 analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/delegatedConstructorInapplicable.txt create mode 100644 analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/delegatedConstructorInapplicableDifferentParametersCount.descriptors.txt create mode 100644 analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/delegatedConstructorInapplicableDifferentParametersCount.kt create mode 100644 analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/delegatedConstructorInapplicableDifferentParametersCount.txt diff --git a/analysis/analysis-api-fe10/tests-gen/org/jetbrains/kotlin/analysis/api/fe10/test/cases/generated/cases/components/callResolver/Fe10IdeNormalAnalysisSourceModuleResolveCandidatesTestGenerated.java b/analysis/analysis-api-fe10/tests-gen/org/jetbrains/kotlin/analysis/api/fe10/test/cases/generated/cases/components/callResolver/Fe10IdeNormalAnalysisSourceModuleResolveCandidatesTestGenerated.java index 7495840de01..0a146c45486 100644 --- a/analysis/analysis-api-fe10/tests-gen/org/jetbrains/kotlin/analysis/api/fe10/test/cases/generated/cases/components/callResolver/Fe10IdeNormalAnalysisSourceModuleResolveCandidatesTestGenerated.java +++ b/analysis/analysis-api-fe10/tests-gen/org/jetbrains/kotlin/analysis/api/fe10/test/cases/generated/cases/components/callResolver/Fe10IdeNormalAnalysisSourceModuleResolveCandidatesTestGenerated.java @@ -79,6 +79,12 @@ public class Fe10IdeNormalAnalysisSourceModuleResolveCandidatesTestGenerated ext runTest("analysis/analysis-api/testData/components/callResolver/resolveCandidates/multipleCandidates/ambiguousWithInferredTypeParameters.kt"); } + @Test + @TestMetadata("delegatedConstructor.kt") + public void testDelegatedConstructor() throws Exception { + runTest("analysis/analysis-api/testData/components/callResolver/resolveCandidates/multipleCandidates/delegatedConstructor.kt"); + } + @Test @TestMetadata("implicitInvoke.kt") public void testImplicitInvoke() throws Exception { @@ -207,6 +213,24 @@ public class Fe10IdeNormalAnalysisSourceModuleResolveCandidatesTestGenerated ext runTest("analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/consecutiveImplicitInvoke3.kt"); } + @Test + @TestMetadata("delegatedConstructorApplicable.kt") + public void testDelegatedConstructorApplicable() throws Exception { + runTest("analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/delegatedConstructorApplicable.kt"); + } + + @Test + @TestMetadata("delegatedConstructorInapplicable.kt") + public void testDelegatedConstructorInapplicable() throws Exception { + runTest("analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/delegatedConstructorInapplicable.kt"); + } + + @Test + @TestMetadata("delegatedConstructorInapplicableDifferentParametersCount.kt") + public void testDelegatedConstructorInapplicableDifferentParametersCount() throws Exception { + runTest("analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/delegatedConstructorInapplicableDifferentParametersCount.kt"); + } + @Test @TestMetadata("eqEqCall_fromAny.kt") public void testEqEqCall_fromAny() throws Exception { diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirCallResolver.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirCallResolver.kt index ffe49f48878..3dbce599509 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirCallResolver.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirCallResolver.kt @@ -27,7 +27,6 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFir import org.jetbrains.kotlin.analysis.low.level.api.fir.resolver.AllCandidatesResolver import org.jetbrains.kotlin.analysis.utils.printer.parentOfType import org.jetbrains.kotlin.fir.FirElement -import org.jetbrains.kotlin.fir.analysis.checkers.declaration.expandedClass import org.jetbrains.kotlin.fir.analysis.checkers.toRegularClassSymbol import org.jetbrains.kotlin.fir.declarations.FirValueParameter import org.jetbrains.kotlin.fir.declarations.fullyExpandedClass @@ -843,6 +842,7 @@ internal class KtFirCallResolver( resolveFragmentOfCall ).toKtCallCandidateInfos() is FirResolvedQualifier -> toKtCallCandidateInfos() + is FirDelegatedConstructorCall -> collectCallCandidatesForDelegatedConstructorCall(psi, resolveFragmentOfCall) else -> toKtCallInfo(psi, resolveCalleeExpressionOfFunctionCall, resolveFragmentOfCall).toKtCallCandidateInfos() } } @@ -912,6 +912,26 @@ internal class KtFirCallResolver( } } + private fun FirDelegatedConstructorCall.collectCallCandidatesForDelegatedConstructorCall( + psi: KtElement, + resolveFragmentOfCall: Boolean + ): List { + val candidates = AllCandidatesResolver(analysisSession.useSiteSession).getAllCandidatesForDelegatedConstructor( + analysisSession.firResolveSession, + this, + psi + ) + return candidates.mapNotNull { + convertToKtCallCandidateInfo( + this, + psi, + it.candidate, + it.isInBestCandidates, + resolveFragmentOfCall + ) + } + } + private fun KtCallInfo?.toKtCallCandidateInfos(): List { return when (this) { is KtSuccessCallInfo -> listOf(KtApplicableCallCandidateInfo(call, isInBestCandidates = true)) @@ -921,13 +941,13 @@ internal class KtFirCallResolver( } private fun convertToKtCallCandidateInfo( - functionCall: FirFunctionCall, + resolvable: FirResolvable, element: KtElement, candidate: Candidate, isInBestCandidates: Boolean, resolveFragmentOfCall: Boolean ): KtCallCandidateInfo? { - val call = createKtCall(element, functionCall, candidate, resolveFragmentOfCall) + val call = createKtCall(element, resolvable, candidate, resolveFragmentOfCall) ?: error("expect `createKtCall` to succeed for candidate") if (candidate.isSuccessful) { return KtApplicableCallCandidateInfo(call, isInBestCandidates) @@ -936,7 +956,7 @@ internal class KtFirCallResolver( val diagnostic = createConeDiagnosticForCandidateWithError(candidate.currentApplicability, candidate) if (diagnostic is ConeHiddenCandidateError) return null val ktDiagnostic = - functionCall.source?.let { diagnostic.asKtDiagnostic(it, element.toKtPsiSourceElement()) } + resolvable.source?.let { diagnostic.asKtDiagnostic(it, element.toKtPsiSourceElement()) } ?: KtNonBoundToPsiErrorDiagnostic(factoryName = null, diagnostic.reason, token) return KtInapplicableCallCandidateInfo(call, isInBestCandidates, ktDiagnostic) } diff --git a/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/components/callResolver/FirIdeNormalAnalysisSourceModuleResolveCandidatesTestGenerated.java b/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/components/callResolver/FirIdeNormalAnalysisSourceModuleResolveCandidatesTestGenerated.java index 1ab5c12e0f2..bafb7dd64b4 100644 --- a/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/components/callResolver/FirIdeNormalAnalysisSourceModuleResolveCandidatesTestGenerated.java +++ b/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/components/callResolver/FirIdeNormalAnalysisSourceModuleResolveCandidatesTestGenerated.java @@ -79,6 +79,12 @@ public class FirIdeNormalAnalysisSourceModuleResolveCandidatesTestGenerated exte runTest("analysis/analysis-api/testData/components/callResolver/resolveCandidates/multipleCandidates/ambiguousWithInferredTypeParameters.kt"); } + @Test + @TestMetadata("delegatedConstructor.kt") + public void testDelegatedConstructor() throws Exception { + runTest("analysis/analysis-api/testData/components/callResolver/resolveCandidates/multipleCandidates/delegatedConstructor.kt"); + } + @Test @TestMetadata("implicitInvoke.kt") public void testImplicitInvoke() throws Exception { @@ -207,6 +213,24 @@ public class FirIdeNormalAnalysisSourceModuleResolveCandidatesTestGenerated exte runTest("analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/consecutiveImplicitInvoke3.kt"); } + @Test + @TestMetadata("delegatedConstructorApplicable.kt") + public void testDelegatedConstructorApplicable() throws Exception { + runTest("analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/delegatedConstructorApplicable.kt"); + } + + @Test + @TestMetadata("delegatedConstructorInapplicable.kt") + public void testDelegatedConstructorInapplicable() throws Exception { + runTest("analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/delegatedConstructorInapplicable.kt"); + } + + @Test + @TestMetadata("delegatedConstructorInapplicableDifferentParametersCount.kt") + public void testDelegatedConstructorInapplicableDifferentParametersCount() throws Exception { + runTest("analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/delegatedConstructorInapplicableDifferentParametersCount.kt"); + } + @Test @TestMetadata("eqEqCall_fromAny.kt") public void testEqEqCall_fromAny() throws Exception { diff --git a/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/components/callResolver/FirStandaloneNormalAnalysisSourceModuleResolveCandidatesTestGenerated.java b/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/components/callResolver/FirStandaloneNormalAnalysisSourceModuleResolveCandidatesTestGenerated.java index 62ea7d3e7d4..03f9946b298 100644 --- a/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/components/callResolver/FirStandaloneNormalAnalysisSourceModuleResolveCandidatesTestGenerated.java +++ b/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/components/callResolver/FirStandaloneNormalAnalysisSourceModuleResolveCandidatesTestGenerated.java @@ -79,6 +79,12 @@ public class FirStandaloneNormalAnalysisSourceModuleResolveCandidatesTestGenerat runTest("analysis/analysis-api/testData/components/callResolver/resolveCandidates/multipleCandidates/ambiguousWithInferredTypeParameters.kt"); } + @Test + @TestMetadata("delegatedConstructor.kt") + public void testDelegatedConstructor() throws Exception { + runTest("analysis/analysis-api/testData/components/callResolver/resolveCandidates/multipleCandidates/delegatedConstructor.kt"); + } + @Test @TestMetadata("implicitInvoke.kt") public void testImplicitInvoke() throws Exception { @@ -207,6 +213,24 @@ public class FirStandaloneNormalAnalysisSourceModuleResolveCandidatesTestGenerat runTest("analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/consecutiveImplicitInvoke3.kt"); } + @Test + @TestMetadata("delegatedConstructorApplicable.kt") + public void testDelegatedConstructorApplicable() throws Exception { + runTest("analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/delegatedConstructorApplicable.kt"); + } + + @Test + @TestMetadata("delegatedConstructorInapplicable.kt") + public void testDelegatedConstructorInapplicable() throws Exception { + runTest("analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/delegatedConstructorInapplicable.kt"); + } + + @Test + @TestMetadata("delegatedConstructorInapplicableDifferentParametersCount.kt") + public void testDelegatedConstructorInapplicableDifferentParametersCount() throws Exception { + runTest("analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/delegatedConstructorInapplicableDifferentParametersCount.kt"); + } + @Test @TestMetadata("eqEqCall_fromAny.kt") public void testEqEqCall_fromAny() throws Exception { diff --git a/analysis/analysis-api/testData/components/callResolver/resolveCandidates/multipleCandidates/delegatedConstructor.descriptors.txt b/analysis/analysis-api/testData/components/callResolver/resolveCandidates/multipleCandidates/delegatedConstructor.descriptors.txt new file mode 100644 index 00000000000..dcc646e5c48 --- /dev/null +++ b/analysis/analysis-api/testData/components/callResolver/resolveCandidates/multipleCandidates/delegatedConstructor.descriptors.txt @@ -0,0 +1,77 @@ +KtInapplicableCallCandidateInfo: + diagnostic = ERROR> + candidate = KtDelegatedConstructorCall: + kind = SUPER_CALL + partiallyAppliedSymbol = KtPartiallyAppliedSymbol: + dispatchReceiver = null + extensionReceiver = null + signature = KtFunctionLikeSignature: + receiverType = null + returnType = A + symbol = (): A + valueParameters = [] + callableIdIfNonLocal = null + typeArgumentsMapping = {} + argumentMapping = {} + isInBestCandidates = false + +KtInapplicableCallCandidateInfo: + diagnostic = ERROR> + candidate = KtDelegatedConstructorCall: + kind = SUPER_CALL + partiallyAppliedSymbol = KtPartiallyAppliedSymbol: + dispatchReceiver = null + extensionReceiver = null + signature = KtFunctionLikeSignature: + receiverType = null + returnType = A + symbol = (p: kotlin.String): A + valueParameters = [ + KtVariableLikeSignature: + name = p + receiverType = null + returnType = kotlin.String + symbol = p: kotlin.String + callableIdIfNonLocal = null + ] + callableIdIfNonLocal = null + typeArgumentsMapping = {} + argumentMapping = { + 5 -> (KtVariableLikeSignature: + name = p + receiverType = null + returnType = kotlin.String + symbol = p: kotlin.String + callableIdIfNonLocal = null) + } + isInBestCandidates = false + +KtApplicableCallCandidateInfo: + candidate = KtDelegatedConstructorCall: + kind = SUPER_CALL + partiallyAppliedSymbol = KtPartiallyAppliedSymbol: + dispatchReceiver = null + extensionReceiver = null + signature = KtFunctionLikeSignature: + receiverType = null + returnType = A + symbol = (x: kotlin.Int): A + valueParameters = [ + KtVariableLikeSignature: + name = x + receiverType = null + returnType = kotlin.Int + symbol = x: kotlin.Int + callableIdIfNonLocal = null + ] + callableIdIfNonLocal = null + typeArgumentsMapping = {} + argumentMapping = { + 5 -> (KtVariableLikeSignature: + name = x + receiverType = null + returnType = kotlin.Int + symbol = x: kotlin.Int + callableIdIfNonLocal = null) + } + isInBestCandidates = true \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/callResolver/resolveCandidates/multipleCandidates/delegatedConstructor.kt b/analysis/analysis-api/testData/components/callResolver/resolveCandidates/multipleCandidates/delegatedConstructor.kt new file mode 100644 index 00000000000..91cac3f8c24 --- /dev/null +++ b/analysis/analysis-api/testData/components/callResolver/resolveCandidates/multipleCandidates/delegatedConstructor.kt @@ -0,0 +1,6 @@ +open class A(x: Int) { + protected constructor() : this(1) {} + private constructor(p: String) : this(2) {} +} + +class B(): A(5) \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/callResolver/resolveCandidates/multipleCandidates/delegatedConstructor.txt b/analysis/analysis-api/testData/components/callResolver/resolveCandidates/multipleCandidates/delegatedConstructor.txt new file mode 100644 index 00000000000..8550453be68 --- /dev/null +++ b/analysis/analysis-api/testData/components/callResolver/resolveCandidates/multipleCandidates/delegatedConstructor.txt @@ -0,0 +1,70 @@ +KtInapplicableCallCandidateInfo: + diagnostic = ERROR + candidate = KtDelegatedConstructorCall: + kind = SUPER_CALL + partiallyAppliedSymbol = KtPartiallyAppliedSymbol: + dispatchReceiver = null + extensionReceiver = null + signature = KtFunctionLikeSignature: + receiverType = null + returnType = A + symbol = (): A + valueParameters = [] + callableIdIfNonLocal = null + typeArgumentsMapping = {} + argumentMapping = {} + isInBestCandidates = false + +KtInapplicableCallCandidateInfo: + diagnostic = ERROR + candidate = KtDelegatedConstructorCall: + kind = SUPER_CALL + partiallyAppliedSymbol = KtPartiallyAppliedSymbol: + dispatchReceiver = null + extensionReceiver = null + signature = KtFunctionLikeSignature: + receiverType = null + returnType = A + symbol = (p: kotlin.String): A + valueParameters = [ + KtVariableLikeSignature: + name = p + receiverType = null + returnType = kotlin.String + symbol = p: kotlin.String + callableIdIfNonLocal = null + ] + callableIdIfNonLocal = null + typeArgumentsMapping = {} + argumentMapping = {} + isInBestCandidates = false + +KtApplicableCallCandidateInfo: + candidate = KtDelegatedConstructorCall: + kind = SUPER_CALL + partiallyAppliedSymbol = KtPartiallyAppliedSymbol: + dispatchReceiver = null + extensionReceiver = null + signature = KtFunctionLikeSignature: + receiverType = null + returnType = A + symbol = (x: kotlin.Int): A + valueParameters = [ + KtVariableLikeSignature: + name = x + receiverType = null + returnType = kotlin.Int + symbol = x: kotlin.Int + callableIdIfNonLocal = null + ] + callableIdIfNonLocal = null + typeArgumentsMapping = {} + argumentMapping = { + 5 -> (KtVariableLikeSignature: + name = x + receiverType = null + returnType = kotlin.Int + symbol = x: kotlin.Int + callableIdIfNonLocal = null) + } + isInBestCandidates = true \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/delegatedConstructorApplicable.kt b/analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/delegatedConstructorApplicable.kt new file mode 100644 index 00000000000..560a5fd641f --- /dev/null +++ b/analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/delegatedConstructorApplicable.kt @@ -0,0 +1,4 @@ +open class A(x: Int) { +} + +class B(): A(5) \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/delegatedConstructorApplicable.txt b/analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/delegatedConstructorApplicable.txt new file mode 100644 index 00000000000..ed4f24b332b --- /dev/null +++ b/analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/delegatedConstructorApplicable.txt @@ -0,0 +1,29 @@ +KtApplicableCallCandidateInfo: + candidate = KtDelegatedConstructorCall: + kind = SUPER_CALL + partiallyAppliedSymbol = KtPartiallyAppliedSymbol: + dispatchReceiver = null + extensionReceiver = null + signature = KtFunctionLikeSignature: + receiverType = null + returnType = A + symbol = (x: kotlin.Int): A + valueParameters = [ + KtVariableLikeSignature: + name = x + receiverType = null + returnType = kotlin.Int + symbol = x: kotlin.Int + callableIdIfNonLocal = null + ] + callableIdIfNonLocal = null + typeArgumentsMapping = {} + argumentMapping = { + 5 -> (KtVariableLikeSignature: + name = x + receiverType = null + returnType = kotlin.Int + symbol = x: kotlin.Int + callableIdIfNonLocal = null) + } + isInBestCandidates = true \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/delegatedConstructorInapplicable.descriptors.txt b/analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/delegatedConstructorInapplicable.descriptors.txt new file mode 100644 index 00000000000..47d030f75a2 --- /dev/null +++ b/analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/delegatedConstructorInapplicable.descriptors.txt @@ -0,0 +1,30 @@ +KtInapplicableCallCandidateInfo: + diagnostic = ERROR> + candidate = KtDelegatedConstructorCall: + kind = SUPER_CALL + partiallyAppliedSymbol = KtPartiallyAppliedSymbol: + dispatchReceiver = null + extensionReceiver = null + signature = KtFunctionLikeSignature: + receiverType = null + returnType = A + symbol = (x: kotlin.String): A + valueParameters = [ + KtVariableLikeSignature: + name = x + receiverType = null + returnType = kotlin.String + symbol = x: kotlin.String + callableIdIfNonLocal = null + ] + callableIdIfNonLocal = null + typeArgumentsMapping = {} + argumentMapping = { + 5 -> (KtVariableLikeSignature: + name = x + receiverType = null + returnType = kotlin.String + symbol = x: kotlin.String + callableIdIfNonLocal = null) + } + isInBestCandidates = true \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/delegatedConstructorInapplicable.kt b/analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/delegatedConstructorInapplicable.kt new file mode 100644 index 00000000000..dfa16fd7e74 --- /dev/null +++ b/analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/delegatedConstructorInapplicable.kt @@ -0,0 +1,4 @@ +open class A(x: String) { +} + +class B(): A(5) \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/delegatedConstructorInapplicable.txt b/analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/delegatedConstructorInapplicable.txt new file mode 100644 index 00000000000..e76d057880c --- /dev/null +++ b/analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/delegatedConstructorInapplicable.txt @@ -0,0 +1,30 @@ +KtInapplicableCallCandidateInfo: + diagnostic = ERROR + candidate = KtDelegatedConstructorCall: + kind = SUPER_CALL + partiallyAppliedSymbol = KtPartiallyAppliedSymbol: + dispatchReceiver = null + extensionReceiver = null + signature = KtFunctionLikeSignature: + receiverType = null + returnType = A + symbol = (x: kotlin.String): A + valueParameters = [ + KtVariableLikeSignature: + name = x + receiverType = null + returnType = kotlin.String + symbol = x: kotlin.String + callableIdIfNonLocal = null + ] + callableIdIfNonLocal = null + typeArgumentsMapping = {} + argumentMapping = { + 5 -> (KtVariableLikeSignature: + name = x + receiverType = null + returnType = kotlin.String + symbol = x: kotlin.String + callableIdIfNonLocal = null) + } + isInBestCandidates = true \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/delegatedConstructorInapplicableDifferentParametersCount.descriptors.txt b/analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/delegatedConstructorInapplicableDifferentParametersCount.descriptors.txt new file mode 100644 index 00000000000..de8e7deeaab --- /dev/null +++ b/analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/delegatedConstructorInapplicableDifferentParametersCount.descriptors.txt @@ -0,0 +1,16 @@ +KtInapplicableCallCandidateInfo: + diagnostic = ERROR> + candidate = KtDelegatedConstructorCall: + kind = SUPER_CALL + partiallyAppliedSymbol = KtPartiallyAppliedSymbol: + dispatchReceiver = null + extensionReceiver = null + signature = KtFunctionLikeSignature: + receiverType = null + returnType = A + symbol = (): A + valueParameters = [] + callableIdIfNonLocal = null + typeArgumentsMapping = {} + argumentMapping = {} + isInBestCandidates = true \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/delegatedConstructorInapplicableDifferentParametersCount.kt b/analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/delegatedConstructorInapplicableDifferentParametersCount.kt new file mode 100644 index 00000000000..00c536704f0 --- /dev/null +++ b/analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/delegatedConstructorInapplicableDifferentParametersCount.kt @@ -0,0 +1,4 @@ +open class A() { +} + +class B(): A(5) \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/delegatedConstructorInapplicableDifferentParametersCount.txt b/analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/delegatedConstructorInapplicableDifferentParametersCount.txt new file mode 100644 index 00000000000..92fe708bb2e --- /dev/null +++ b/analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/delegatedConstructorInapplicableDifferentParametersCount.txt @@ -0,0 +1,16 @@ +KtInapplicableCallCandidateInfo: + diagnostic = ERROR + candidate = KtDelegatedConstructorCall: + kind = SUPER_CALL + partiallyAppliedSymbol = KtPartiallyAppliedSymbol: + dispatchReceiver = null + extensionReceiver = null + signature = KtFunctionLikeSignature: + receiverType = null + returnType = A + symbol = (): A + valueParameters = [] + callableIdIfNonLocal = null + typeArgumentsMapping = {} + argumentMapping = {} + isInBestCandidates = true \ No newline at end of file diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/resolver/AllCandidatesResolver.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/resolver/AllCandidatesResolver.kt index ac52a40f3ea..300da5b0af6 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/resolver/AllCandidatesResolver.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/resolver/AllCandidatesResolver.kt @@ -9,18 +9,48 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.api.LLFirResolveSession 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.analysis.utils.printer.parentsOfType -import org.jetbrains.kotlin.fir.FirSession -import org.jetbrains.kotlin.fir.OverloadCandidate -import org.jetbrains.kotlin.fir.PrivateForInline +import org.jetbrains.kotlin.fir.* +import org.jetbrains.kotlin.fir.declarations.FirResolvePhase +import org.jetbrains.kotlin.fir.expressions.FirDelegatedConstructorCall import org.jetbrains.kotlin.fir.expressions.FirFunctionCall +import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.resolve.calls.ResolutionContext +import org.jetbrains.kotlin.fir.resolve.calls.tower.FirTowerResolver +import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirBodyResolveTransformer +import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirExpressionsResolveTransformer import org.jetbrains.kotlin.fir.symbols.SymbolInternals +import org.jetbrains.kotlin.fir.types.ConeClassLikeType +import org.jetbrains.kotlin.fir.types.coneType import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtElement -class AllCandidatesResolver(firSession: FirSession) { - private val bodyResolveComponents = createStubBodyResolveComponents(firSession) +class AllCandidatesResolver(private val firSession: FirSession) { + private val scopeSession = ScopeSession() + + // This transformer is not intended for actual transformations and created here only to simplify access to resolve components + private val stubBodyResolveTransformer = FirBodyResolveTransformer( + session = firSession, + phase = FirResolvePhase.BODY_RESOLVE, + implicitTypeOnly = false, + scopeSession = scopeSession, + ) + + private val bodyResolveComponents = object : StubBodyResolveTransformerComponents( + firSession, + scopeSession, + stubBodyResolveTransformer, + stubBodyResolveTransformer.context, + ) { + val collector = AllCandidatesCollector(this, resolutionStageRunner) + val towerResolver = FirTowerResolver(this, resolutionStageRunner, collector) + override val callResolver = FirCallResolver(this, towerResolver) + + init { + callResolver.initTransformer(FirExpressionsResolveTransformer(stubBodyResolveTransformer)) + } + } + private val resolutionContext = ResolutionContext(firSession, bodyResolveComponents, bodyResolveComponents.transformer.context) fun getAllCandidates( @@ -33,12 +63,25 @@ class AllCandidatesResolver(firSession: FirSession) { val firFile = element.containingKtFile.getOrBuildFirFile(firResolveSession) return bodyResolveComponents.context.withFile(firFile, bodyResolveComponents) { - bodyResolveComponents.callResolver.collectAllCandidates( - functionCall, - calleeName, - bodyResolveComponents.context.containers, - resolutionContext - ) + bodyResolveComponents.callResolver + .collectAllCandidates(functionCall, calleeName, bodyResolveComponents.context.containers, resolutionContext) + } + } + + fun getAllCandidatesForDelegatedConstructor( + firResolveSession: LLFirResolveSession, + delegatedConstructorCall: FirDelegatedConstructorCall, + element: KtElement + ): List { + initializeBodyResolveContext(firResolveSession, element) + + val firFile = element.containingKtFile.getOrBuildFirFile(firResolveSession) + val constructedType = delegatedConstructorCall.constructedTypeRef.coneType as ConeClassLikeType + return bodyResolveComponents.context.withFile(firFile, bodyResolveComponents) { + bodyResolveComponents.callResolver.resolveDelegatingConstructorCall(delegatedConstructorCall, constructedType) + bodyResolveComponents.collector.allCandidates.map { + OverloadCandidate(it, isInBestCandidates = it in bodyResolveComponents.collector.bestCandidates()) + } } } diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/resolver/resolverUtils.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/resolver/resolverUtils.kt index 336e200ea04..d072d790c75 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/resolver/resolverUtils.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/resolver/resolverUtils.kt @@ -38,7 +38,7 @@ internal fun createStubBodyResolveComponents(firSession: FirSession): FirAbstrac ) } -private class StubBodyResolveTransformerComponents( +internal open class StubBodyResolveTransformerComponents( session: FirSession, scopeSession: ScopeSession, transformer: FirBodyResolveTransformer, diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirCallResolver.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirCallResolver.kt index d2b7c891944..ee12de24110 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirCallResolver.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirCallResolver.kt @@ -53,6 +53,7 @@ import org.jetbrains.kotlin.utils.addToStdlib.safeAs class FirCallResolver( private val components: FirAbstractBodyResolveTransformer.BodyResolveTransformerComponents, + private val towerResolver: FirTowerResolver = FirTowerResolver(components, components.resolutionStageRunner) ) { private val session = components.session private val overloadByLambdaReturnTypeResolver = FirOverloadByLambdaReturnTypeResolver(components) @@ -63,10 +64,6 @@ class FirCallResolver( this.transformer = transformer } - private val towerResolver = FirTowerResolver( - components, components.resolutionStageRunner, - ) - val conflictResolver: ConeCallConflictResolver = session.callConflictResolverFactory.create(TypeSpecificityComparator.NONE, session.inferenceComponents, components) @@ -168,24 +165,6 @@ class FirCallResolver( containingDeclarations: List = transformer.components.containingDeclarations, resolutionContext: ResolutionContext = transformer.resolutionContext ): List { - class AllCandidatesCollector( - components: BodyResolveComponents, - resolutionStageRunner: ResolutionStageRunner - ) : CandidateCollector(components, resolutionStageRunner) { - private val allCandidatesSet = mutableSetOf() - - override fun consumeCandidate(group: TowerGroup, candidate: Candidate, context: ResolutionContext): CandidateApplicability { - allCandidatesSet += candidate - 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 - get() = allCandidatesSet.toList() - } - val collector = AllCandidatesCollector(components, components.resolutionStageRunner) val origin = (qualifiedAccess as? FirFunctionCall)?.origin ?: FirFunctionCallOrigin.Regular val result = @@ -843,3 +822,21 @@ class FirCallResolver( /** A candidate in the overload candidate set. */ data class OverloadCandidate(val candidate: Candidate, val isInBestCandidates: Boolean) + +class AllCandidatesCollector( + components: BodyResolveComponents, + resolutionStageRunner: ResolutionStageRunner +) : CandidateCollector(components, resolutionStageRunner) { + private val allCandidatesSet = mutableSetOf() + + override fun consumeCandidate(group: TowerGroup, candidate: Candidate, context: ResolutionContext): CandidateApplicability { + allCandidatesSet += candidate + 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 + get() = allCandidatesSet.toList() +} diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/tower/FirTowerResolver.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/tower/FirTowerResolver.kt index 9d4c930736f..46d18a07559 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/tower/FirTowerResolver.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/tower/FirTowerResolver.kt @@ -20,8 +20,8 @@ import org.jetbrains.kotlin.types.AbstractTypeChecker class FirTowerResolver( private val components: BodyResolveComponents, resolutionStageRunner: ResolutionStageRunner, + private val collector: CandidateCollector = CandidateCollector(components, resolutionStageRunner) ) { - private val collector = CandidateCollector(components, resolutionStageRunner) private val manager = TowerResolveManager(collector) fun runResolver(