[Analysis API FIR] fix candidate collection for delegatedConstructor call
^KTIJ-20446
This commit is contained in:
+24
@@ -79,6 +79,12 @@ public class Fe10IdeNormalAnalysisSourceModuleResolveCandidatesTestGenerated ext
|
|||||||
runTest("analysis/analysis-api/testData/components/callResolver/resolveCandidates/multipleCandidates/ambiguousWithInferredTypeParameters.kt");
|
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
|
@Test
|
||||||
@TestMetadata("implicitInvoke.kt")
|
@TestMetadata("implicitInvoke.kt")
|
||||||
public void testImplicitInvoke() throws Exception {
|
public void testImplicitInvoke() throws Exception {
|
||||||
@@ -207,6 +213,24 @@ public class Fe10IdeNormalAnalysisSourceModuleResolveCandidatesTestGenerated ext
|
|||||||
runTest("analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/consecutiveImplicitInvoke3.kt");
|
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
|
@Test
|
||||||
@TestMetadata("eqEqCall_fromAny.kt")
|
@TestMetadata("eqEqCall_fromAny.kt")
|
||||||
public void testEqEqCall_fromAny() throws Exception {
|
public void testEqEqCall_fromAny() throws Exception {
|
||||||
|
|||||||
+24
-4
@@ -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.low.level.api.fir.resolver.AllCandidatesResolver
|
||||||
import org.jetbrains.kotlin.analysis.utils.printer.parentOfType
|
import org.jetbrains.kotlin.analysis.utils.printer.parentOfType
|
||||||
import org.jetbrains.kotlin.fir.FirElement
|
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.analysis.checkers.toRegularClassSymbol
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
|
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
|
||||||
import org.jetbrains.kotlin.fir.declarations.fullyExpandedClass
|
import org.jetbrains.kotlin.fir.declarations.fullyExpandedClass
|
||||||
@@ -843,6 +842,7 @@ internal class KtFirCallResolver(
|
|||||||
resolveFragmentOfCall
|
resolveFragmentOfCall
|
||||||
).toKtCallCandidateInfos()
|
).toKtCallCandidateInfos()
|
||||||
is FirResolvedQualifier -> toKtCallCandidateInfos()
|
is FirResolvedQualifier -> toKtCallCandidateInfos()
|
||||||
|
is FirDelegatedConstructorCall -> collectCallCandidatesForDelegatedConstructorCall(psi, resolveFragmentOfCall)
|
||||||
else -> toKtCallInfo(psi, resolveCalleeExpressionOfFunctionCall, resolveFragmentOfCall).toKtCallCandidateInfos()
|
else -> toKtCallInfo(psi, resolveCalleeExpressionOfFunctionCall, resolveFragmentOfCall).toKtCallCandidateInfos()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -912,6 +912,26 @@ internal class KtFirCallResolver(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun FirDelegatedConstructorCall.collectCallCandidatesForDelegatedConstructorCall(
|
||||||
|
psi: KtElement,
|
||||||
|
resolveFragmentOfCall: Boolean
|
||||||
|
): List<KtCallCandidateInfo> {
|
||||||
|
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<KtCallCandidateInfo> {
|
private fun KtCallInfo?.toKtCallCandidateInfos(): List<KtCallCandidateInfo> {
|
||||||
return when (this) {
|
return when (this) {
|
||||||
is KtSuccessCallInfo -> listOf(KtApplicableCallCandidateInfo(call, isInBestCandidates = true))
|
is KtSuccessCallInfo -> listOf(KtApplicableCallCandidateInfo(call, isInBestCandidates = true))
|
||||||
@@ -921,13 +941,13 @@ internal class KtFirCallResolver(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun convertToKtCallCandidateInfo(
|
private fun convertToKtCallCandidateInfo(
|
||||||
functionCall: FirFunctionCall,
|
resolvable: FirResolvable,
|
||||||
element: KtElement,
|
element: KtElement,
|
||||||
candidate: Candidate,
|
candidate: Candidate,
|
||||||
isInBestCandidates: Boolean,
|
isInBestCandidates: Boolean,
|
||||||
resolveFragmentOfCall: Boolean
|
resolveFragmentOfCall: Boolean
|
||||||
): KtCallCandidateInfo? {
|
): KtCallCandidateInfo? {
|
||||||
val call = createKtCall(element, functionCall, candidate, resolveFragmentOfCall)
|
val call = createKtCall(element, resolvable, candidate, resolveFragmentOfCall)
|
||||||
?: error("expect `createKtCall` to succeed for candidate")
|
?: error("expect `createKtCall` to succeed for candidate")
|
||||||
if (candidate.isSuccessful) {
|
if (candidate.isSuccessful) {
|
||||||
return KtApplicableCallCandidateInfo(call, isInBestCandidates)
|
return KtApplicableCallCandidateInfo(call, isInBestCandidates)
|
||||||
@@ -936,7 +956,7 @@ internal class KtFirCallResolver(
|
|||||||
val diagnostic = createConeDiagnosticForCandidateWithError(candidate.currentApplicability, candidate)
|
val diagnostic = createConeDiagnosticForCandidateWithError(candidate.currentApplicability, candidate)
|
||||||
if (diagnostic is ConeHiddenCandidateError) return null
|
if (diagnostic is ConeHiddenCandidateError) return null
|
||||||
val ktDiagnostic =
|
val ktDiagnostic =
|
||||||
functionCall.source?.let { diagnostic.asKtDiagnostic(it, element.toKtPsiSourceElement()) }
|
resolvable.source?.let { diagnostic.asKtDiagnostic(it, element.toKtPsiSourceElement()) }
|
||||||
?: KtNonBoundToPsiErrorDiagnostic(factoryName = null, diagnostic.reason, token)
|
?: KtNonBoundToPsiErrorDiagnostic(factoryName = null, diagnostic.reason, token)
|
||||||
return KtInapplicableCallCandidateInfo(call, isInBestCandidates, ktDiagnostic)
|
return KtInapplicableCallCandidateInfo(call, isInBestCandidates, ktDiagnostic)
|
||||||
}
|
}
|
||||||
|
|||||||
+24
@@ -79,6 +79,12 @@ public class FirIdeNormalAnalysisSourceModuleResolveCandidatesTestGenerated exte
|
|||||||
runTest("analysis/analysis-api/testData/components/callResolver/resolveCandidates/multipleCandidates/ambiguousWithInferredTypeParameters.kt");
|
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
|
@Test
|
||||||
@TestMetadata("implicitInvoke.kt")
|
@TestMetadata("implicitInvoke.kt")
|
||||||
public void testImplicitInvoke() throws Exception {
|
public void testImplicitInvoke() throws Exception {
|
||||||
@@ -207,6 +213,24 @@ public class FirIdeNormalAnalysisSourceModuleResolveCandidatesTestGenerated exte
|
|||||||
runTest("analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/consecutiveImplicitInvoke3.kt");
|
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
|
@Test
|
||||||
@TestMetadata("eqEqCall_fromAny.kt")
|
@TestMetadata("eqEqCall_fromAny.kt")
|
||||||
public void testEqEqCall_fromAny() throws Exception {
|
public void testEqEqCall_fromAny() throws Exception {
|
||||||
|
|||||||
+24
@@ -79,6 +79,12 @@ public class FirStandaloneNormalAnalysisSourceModuleResolveCandidatesTestGenerat
|
|||||||
runTest("analysis/analysis-api/testData/components/callResolver/resolveCandidates/multipleCandidates/ambiguousWithInferredTypeParameters.kt");
|
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
|
@Test
|
||||||
@TestMetadata("implicitInvoke.kt")
|
@TestMetadata("implicitInvoke.kt")
|
||||||
public void testImplicitInvoke() throws Exception {
|
public void testImplicitInvoke() throws Exception {
|
||||||
@@ -207,6 +213,24 @@ public class FirStandaloneNormalAnalysisSourceModuleResolveCandidatesTestGenerat
|
|||||||
runTest("analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/consecutiveImplicitInvoke3.kt");
|
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
|
@Test
|
||||||
@TestMetadata("eqEqCall_fromAny.kt")
|
@TestMetadata("eqEqCall_fromAny.kt")
|
||||||
public void testEqEqCall_fromAny() throws Exception {
|
public void testEqEqCall_fromAny() throws Exception {
|
||||||
|
|||||||
+77
@@ -0,0 +1,77 @@
|
|||||||
|
KtInapplicableCallCandidateInfo:
|
||||||
|
diagnostic = ERROR<null: OTHER_ERROR with <init>>
|
||||||
|
candidate = KtDelegatedConstructorCall:
|
||||||
|
kind = SUPER_CALL
|
||||||
|
partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
|
||||||
|
dispatchReceiver = null
|
||||||
|
extensionReceiver = null
|
||||||
|
signature = KtFunctionLikeSignature:
|
||||||
|
receiverType = null
|
||||||
|
returnType = A
|
||||||
|
symbol = <constructor>(): A
|
||||||
|
valueParameters = []
|
||||||
|
callableIdIfNonLocal = null
|
||||||
|
typeArgumentsMapping = {}
|
||||||
|
argumentMapping = {}
|
||||||
|
isInBestCandidates = false
|
||||||
|
|
||||||
|
KtInapplicableCallCandidateInfo:
|
||||||
|
diagnostic = ERROR<null: OTHER_ERROR with <init>>
|
||||||
|
candidate = KtDelegatedConstructorCall:
|
||||||
|
kind = SUPER_CALL
|
||||||
|
partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
|
||||||
|
dispatchReceiver = null
|
||||||
|
extensionReceiver = null
|
||||||
|
signature = KtFunctionLikeSignature:
|
||||||
|
receiverType = null
|
||||||
|
returnType = A
|
||||||
|
symbol = <constructor>(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 = <constructor>(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
|
||||||
+6
@@ -0,0 +1,6 @@
|
|||||||
|
open class A(x: Int) {
|
||||||
|
protected constructor() : this(1) {}
|
||||||
|
private constructor(p: String) : this(2) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
class B(): <expr>A</expr>(5)
|
||||||
+70
@@ -0,0 +1,70 @@
|
|||||||
|
KtInapplicableCallCandidateInfo:
|
||||||
|
diagnostic = ERROR<TOO_MANY_ARGUMENTS: Too many arguments for protected constructor(): R|A|>
|
||||||
|
candidate = KtDelegatedConstructorCall:
|
||||||
|
kind = SUPER_CALL
|
||||||
|
partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
|
||||||
|
dispatchReceiver = null
|
||||||
|
extensionReceiver = null
|
||||||
|
signature = KtFunctionLikeSignature:
|
||||||
|
receiverType = null
|
||||||
|
returnType = A
|
||||||
|
symbol = <constructor>(): A
|
||||||
|
valueParameters = []
|
||||||
|
callableIdIfNonLocal = null
|
||||||
|
typeArgumentsMapping = {}
|
||||||
|
argumentMapping = {}
|
||||||
|
isInBestCandidates = false
|
||||||
|
|
||||||
|
KtInapplicableCallCandidateInfo:
|
||||||
|
diagnostic = ERROR<INVISIBLE_REFERENCE: Symbol constructor(p: String): A is invisible>
|
||||||
|
candidate = KtDelegatedConstructorCall:
|
||||||
|
kind = SUPER_CALL
|
||||||
|
partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
|
||||||
|
dispatchReceiver = null
|
||||||
|
extensionReceiver = null
|
||||||
|
signature = KtFunctionLikeSignature:
|
||||||
|
receiverType = null
|
||||||
|
returnType = A
|
||||||
|
symbol = <constructor>(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 = <constructor>(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
|
||||||
+4
@@ -0,0 +1,4 @@
|
|||||||
|
open class A(x: Int) {
|
||||||
|
}
|
||||||
|
|
||||||
|
class B(): <expr>A</expr>(5)
|
||||||
+29
@@ -0,0 +1,29 @@
|
|||||||
|
KtApplicableCallCandidateInfo:
|
||||||
|
candidate = KtDelegatedConstructorCall:
|
||||||
|
kind = SUPER_CALL
|
||||||
|
partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
|
||||||
|
dispatchReceiver = null
|
||||||
|
extensionReceiver = null
|
||||||
|
signature = KtFunctionLikeSignature:
|
||||||
|
receiverType = null
|
||||||
|
returnType = A
|
||||||
|
symbol = <constructor>(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
|
||||||
+30
@@ -0,0 +1,30 @@
|
|||||||
|
KtInapplicableCallCandidateInfo:
|
||||||
|
diagnostic = ERROR<null: OTHER_ERROR with <init>>
|
||||||
|
candidate = KtDelegatedConstructorCall:
|
||||||
|
kind = SUPER_CALL
|
||||||
|
partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
|
||||||
|
dispatchReceiver = null
|
||||||
|
extensionReceiver = null
|
||||||
|
signature = KtFunctionLikeSignature:
|
||||||
|
receiverType = null
|
||||||
|
returnType = A
|
||||||
|
symbol = <constructor>(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
|
||||||
+4
@@ -0,0 +1,4 @@
|
|||||||
|
open class A(x: String) {
|
||||||
|
}
|
||||||
|
|
||||||
|
class B(): <expr>A</expr>(5)
|
||||||
+30
@@ -0,0 +1,30 @@
|
|||||||
|
KtInapplicableCallCandidateInfo:
|
||||||
|
diagnostic = ERROR<ARGUMENT_TYPE_MISMATCH: Argument type mismatch: actual type is kotlin/Int but kotlin/String was expected>
|
||||||
|
candidate = KtDelegatedConstructorCall:
|
||||||
|
kind = SUPER_CALL
|
||||||
|
partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
|
||||||
|
dispatchReceiver = null
|
||||||
|
extensionReceiver = null
|
||||||
|
signature = KtFunctionLikeSignature:
|
||||||
|
receiverType = null
|
||||||
|
returnType = A
|
||||||
|
symbol = <constructor>(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
|
||||||
+16
@@ -0,0 +1,16 @@
|
|||||||
|
KtInapplicableCallCandidateInfo:
|
||||||
|
diagnostic = ERROR<null: OTHER_ERROR with <init>>
|
||||||
|
candidate = KtDelegatedConstructorCall:
|
||||||
|
kind = SUPER_CALL
|
||||||
|
partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
|
||||||
|
dispatchReceiver = null
|
||||||
|
extensionReceiver = null
|
||||||
|
signature = KtFunctionLikeSignature:
|
||||||
|
receiverType = null
|
||||||
|
returnType = A
|
||||||
|
symbol = <constructor>(): A
|
||||||
|
valueParameters = []
|
||||||
|
callableIdIfNonLocal = null
|
||||||
|
typeArgumentsMapping = {}
|
||||||
|
argumentMapping = {}
|
||||||
|
isInBestCandidates = true
|
||||||
+4
@@ -0,0 +1,4 @@
|
|||||||
|
open class A() {
|
||||||
|
}
|
||||||
|
|
||||||
|
class B(): <expr>A</expr>(5)
|
||||||
+16
@@ -0,0 +1,16 @@
|
|||||||
|
KtInapplicableCallCandidateInfo:
|
||||||
|
diagnostic = ERROR<TOO_MANY_ARGUMENTS: Too many arguments for public constructor(): R|A|>
|
||||||
|
candidate = KtDelegatedConstructorCall:
|
||||||
|
kind = SUPER_CALL
|
||||||
|
partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
|
||||||
|
dispatchReceiver = null
|
||||||
|
extensionReceiver = null
|
||||||
|
signature = KtFunctionLikeSignature:
|
||||||
|
receiverType = null
|
||||||
|
returnType = A
|
||||||
|
symbol = <constructor>(): A
|
||||||
|
valueParameters = []
|
||||||
|
callableIdIfNonLocal = null
|
||||||
|
typeArgumentsMapping = {}
|
||||||
|
argumentMapping = {}
|
||||||
|
isInBestCandidates = true
|
||||||
+54
-11
@@ -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.getOrBuildFirFile
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.resolveToFirSymbol
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.resolveToFirSymbol
|
||||||
import org.jetbrains.kotlin.analysis.utils.printer.parentsOfType
|
import org.jetbrains.kotlin.analysis.utils.printer.parentsOfType
|
||||||
import org.jetbrains.kotlin.fir.FirSession
|
import org.jetbrains.kotlin.fir.*
|
||||||
import org.jetbrains.kotlin.fir.OverloadCandidate
|
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||||
import org.jetbrains.kotlin.fir.PrivateForInline
|
import org.jetbrains.kotlin.fir.expressions.FirDelegatedConstructorCall
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
|
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.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.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.name.Name
|
||||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||||
import org.jetbrains.kotlin.psi.KtElement
|
import org.jetbrains.kotlin.psi.KtElement
|
||||||
|
|
||||||
class AllCandidatesResolver(firSession: FirSession) {
|
class AllCandidatesResolver(private val firSession: FirSession) {
|
||||||
private val bodyResolveComponents = createStubBodyResolveComponents(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)
|
private val resolutionContext = ResolutionContext(firSession, bodyResolveComponents, bodyResolveComponents.transformer.context)
|
||||||
|
|
||||||
fun getAllCandidates(
|
fun getAllCandidates(
|
||||||
@@ -33,12 +63,25 @@ class AllCandidatesResolver(firSession: FirSession) {
|
|||||||
|
|
||||||
val firFile = element.containingKtFile.getOrBuildFirFile(firResolveSession)
|
val firFile = element.containingKtFile.getOrBuildFirFile(firResolveSession)
|
||||||
return bodyResolveComponents.context.withFile(firFile, bodyResolveComponents) {
|
return bodyResolveComponents.context.withFile(firFile, bodyResolveComponents) {
|
||||||
bodyResolveComponents.callResolver.collectAllCandidates(
|
bodyResolveComponents.callResolver
|
||||||
functionCall,
|
.collectAllCandidates(functionCall, calleeName, bodyResolveComponents.context.containers, resolutionContext)
|
||||||
calleeName,
|
}
|
||||||
bodyResolveComponents.context.containers,
|
}
|
||||||
resolutionContext
|
|
||||||
)
|
fun getAllCandidatesForDelegatedConstructor(
|
||||||
|
firResolveSession: LLFirResolveSession,
|
||||||
|
delegatedConstructorCall: FirDelegatedConstructorCall,
|
||||||
|
element: KtElement
|
||||||
|
): List<OverloadCandidate> {
|
||||||
|
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())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -38,7 +38,7 @@ internal fun createStubBodyResolveComponents(firSession: FirSession): FirAbstrac
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private class StubBodyResolveTransformerComponents(
|
internal open class StubBodyResolveTransformerComponents(
|
||||||
session: FirSession,
|
session: FirSession,
|
||||||
scopeSession: ScopeSession,
|
scopeSession: ScopeSession,
|
||||||
transformer: FirBodyResolveTransformer,
|
transformer: FirBodyResolveTransformer,
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
|||||||
|
|
||||||
class FirCallResolver(
|
class FirCallResolver(
|
||||||
private val components: FirAbstractBodyResolveTransformer.BodyResolveTransformerComponents,
|
private val components: FirAbstractBodyResolveTransformer.BodyResolveTransformerComponents,
|
||||||
|
private val towerResolver: FirTowerResolver = FirTowerResolver(components, components.resolutionStageRunner)
|
||||||
) {
|
) {
|
||||||
private val session = components.session
|
private val session = components.session
|
||||||
private val overloadByLambdaReturnTypeResolver = FirOverloadByLambdaReturnTypeResolver(components)
|
private val overloadByLambdaReturnTypeResolver = FirOverloadByLambdaReturnTypeResolver(components)
|
||||||
@@ -63,10 +64,6 @@ class FirCallResolver(
|
|||||||
this.transformer = transformer
|
this.transformer = transformer
|
||||||
}
|
}
|
||||||
|
|
||||||
private val towerResolver = FirTowerResolver(
|
|
||||||
components, components.resolutionStageRunner,
|
|
||||||
)
|
|
||||||
|
|
||||||
val conflictResolver: ConeCallConflictResolver =
|
val conflictResolver: ConeCallConflictResolver =
|
||||||
session.callConflictResolverFactory.create(TypeSpecificityComparator.NONE, session.inferenceComponents, components)
|
session.callConflictResolverFactory.create(TypeSpecificityComparator.NONE, session.inferenceComponents, components)
|
||||||
|
|
||||||
@@ -168,24 +165,6 @@ class FirCallResolver(
|
|||||||
containingDeclarations: List<FirDeclaration> = transformer.components.containingDeclarations,
|
containingDeclarations: List<FirDeclaration> = transformer.components.containingDeclarations,
|
||||||
resolutionContext: ResolutionContext = transformer.resolutionContext
|
resolutionContext: ResolutionContext = transformer.resolutionContext
|
||||||
): List<OverloadCandidate> {
|
): List<OverloadCandidate> {
|
||||||
class AllCandidatesCollector(
|
|
||||||
components: BodyResolveComponents,
|
|
||||||
resolutionStageRunner: ResolutionStageRunner
|
|
||||||
) : CandidateCollector(components, resolutionStageRunner) {
|
|
||||||
private val allCandidatesSet = mutableSetOf<Candidate>()
|
|
||||||
|
|
||||||
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<Candidate>
|
|
||||||
get() = allCandidatesSet.toList()
|
|
||||||
}
|
|
||||||
|
|
||||||
val collector = AllCandidatesCollector(components, components.resolutionStageRunner)
|
val collector = AllCandidatesCollector(components, components.resolutionStageRunner)
|
||||||
val origin = (qualifiedAccess as? FirFunctionCall)?.origin ?: FirFunctionCallOrigin.Regular
|
val origin = (qualifiedAccess as? FirFunctionCall)?.origin ?: FirFunctionCallOrigin.Regular
|
||||||
val result =
|
val result =
|
||||||
@@ -843,3 +822,21 @@ class FirCallResolver(
|
|||||||
|
|
||||||
/** A candidate in the overload candidate set. */
|
/** A candidate in the overload candidate set. */
|
||||||
data class OverloadCandidate(val candidate: Candidate, val isInBestCandidates: Boolean)
|
data class OverloadCandidate(val candidate: Candidate, val isInBestCandidates: Boolean)
|
||||||
|
|
||||||
|
class AllCandidatesCollector(
|
||||||
|
components: BodyResolveComponents,
|
||||||
|
resolutionStageRunner: ResolutionStageRunner
|
||||||
|
) : CandidateCollector(components, resolutionStageRunner) {
|
||||||
|
private val allCandidatesSet = mutableSetOf<Candidate>()
|
||||||
|
|
||||||
|
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<Candidate>
|
||||||
|
get() = allCandidatesSet.toList()
|
||||||
|
}
|
||||||
|
|||||||
+1
-1
@@ -20,8 +20,8 @@ import org.jetbrains.kotlin.types.AbstractTypeChecker
|
|||||||
class FirTowerResolver(
|
class FirTowerResolver(
|
||||||
private val components: BodyResolveComponents,
|
private val components: BodyResolveComponents,
|
||||||
resolutionStageRunner: ResolutionStageRunner,
|
resolutionStageRunner: ResolutionStageRunner,
|
||||||
|
private val collector: CandidateCollector = CandidateCollector(components, resolutionStageRunner)
|
||||||
) {
|
) {
|
||||||
private val collector = CandidateCollector(components, resolutionStageRunner)
|
|
||||||
private val manager = TowerResolveManager(collector)
|
private val manager = TowerResolveManager(collector)
|
||||||
|
|
||||||
fun runResolver(
|
fun runResolver(
|
||||||
|
|||||||
Reference in New Issue
Block a user