[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");
|
||||
}
|
||||
|
||||
@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 {
|
||||
|
||||
+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.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<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> {
|
||||
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)
|
||||
}
|
||||
|
||||
+24
@@ -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 {
|
||||
|
||||
+24
@@ -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 {
|
||||
|
||||
+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.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<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,
|
||||
scopeSession: ScopeSession,
|
||||
transformer: FirBodyResolveTransformer,
|
||||
|
||||
@@ -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<FirDeclaration> = transformer.components.containingDeclarations,
|
||||
resolutionContext: ResolutionContext = transformer.resolutionContext
|
||||
): 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 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<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(
|
||||
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(
|
||||
|
||||
Reference in New Issue
Block a user