[Analysis API FIR] fix call resolution on error elements
This commit is contained in:
+37
-17
@@ -6,6 +6,7 @@
|
||||
package org.jetbrains.kotlin.analysis.api.fir.components
|
||||
|
||||
import org.jetbrains.kotlin.analysis.api.calls.*
|
||||
import org.jetbrains.kotlin.analysis.api.diagnostics.KtDiagnostic
|
||||
import org.jetbrains.kotlin.analysis.api.diagnostics.KtNonBoundToPsiErrorDiagnostic
|
||||
import org.jetbrains.kotlin.analysis.api.fir.KtFirAnalysisSession
|
||||
import org.jetbrains.kotlin.analysis.api.fir.getCandidateSymbols
|
||||
@@ -71,6 +72,7 @@ import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
import org.jetbrains.kotlin.analysis.utils.errors.buildErrorWithAttachment
|
||||
import org.jetbrains.kotlin.analysis.utils.errors.shouldIjPlatformExceptionBeRethrown
|
||||
import org.jetbrains.kotlin.analysis.utils.errors.withPsiEntry
|
||||
import org.jetbrains.kotlin.fir.diagnostics.FirDiagnosticHolder
|
||||
|
||||
internal class KtFirCallResolver(
|
||||
override val analysisSession: KtFirAnalysisSession,
|
||||
@@ -88,15 +90,21 @@ internal class KtFirCallResolver(
|
||||
|
||||
override fun resolveCall(psi: KtElement): KtCallInfo? {
|
||||
return wrapError(psi) {
|
||||
val ktCallInfos = getCallInfo(psi) { psiToResolve, resolveCalleeExpressionOfFunctionCall, resolveFragmentOfCall ->
|
||||
listOfNotNull(
|
||||
toKtCallInfo(
|
||||
psiToResolve,
|
||||
resolveCalleeExpressionOfFunctionCall,
|
||||
resolveFragmentOfCall
|
||||
val ktCallInfos = getCallInfo(
|
||||
psi,
|
||||
getErrorCallInfo = { psiToResolve ->
|
||||
listOf(KtErrorCallInfo(emptyList(), createKtDiagnostic(psiToResolve), token))
|
||||
},
|
||||
getCallInfo = { psiToResolve, resolveCalleeExpressionOfFunctionCall, resolveFragmentOfCall ->
|
||||
listOfNotNull(
|
||||
toKtCallInfo(
|
||||
psiToResolve,
|
||||
resolveCalleeExpressionOfFunctionCall,
|
||||
resolveFragmentOfCall
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
check(ktCallInfos.size <= 1) { "Should only return 1 KtCallInfo" }
|
||||
ktCallInfos.singleOrNull()
|
||||
}
|
||||
@@ -104,6 +112,7 @@ internal class KtFirCallResolver(
|
||||
|
||||
private inline fun <T> getCallInfo(
|
||||
psi: KtElement,
|
||||
getErrorCallInfo: FirDiagnosticHolder.(psiToResolve: KtElement) -> List<T>,
|
||||
getCallInfo: FirElement.(
|
||||
psiToResolve: KtElement,
|
||||
resolveCalleeExpressionOfFunctionCall: Boolean,
|
||||
@@ -121,6 +130,9 @@ internal class KtFirCallResolver(
|
||||
?: containingUnaryExpressionForIncOrDec
|
||||
?: psi
|
||||
val fir = psiToResolve.getOrBuildFir(analysisSession.firResolveSession) ?: return emptyList()
|
||||
if (fir is FirDiagnosticHolder) {
|
||||
return fir.getErrorCallInfo(psiToResolve)
|
||||
}
|
||||
return fir.getCallInfo(
|
||||
psiToResolve,
|
||||
psiToResolve == containingCallExpressionForCalleeExpression,
|
||||
@@ -163,8 +175,7 @@ internal class KtFirCallResolver(
|
||||
}
|
||||
is FirErrorNamedReference -> {
|
||||
val diagnostic = calleeReference.diagnostic
|
||||
val ktDiagnostic = (source?.let { diagnostic.asKtDiagnostic(it, psi.toKtPsiSourceElement()) }
|
||||
?: KtNonBoundToPsiErrorDiagnostic(factoryName = null, diagnostic.reason, token))
|
||||
val ktDiagnostic = calleeReference.createKtDiagnostic(psi)
|
||||
|
||||
if (diagnostic is ConeHiddenCandidateError)
|
||||
return KtErrorCallInfo(emptyList(), ktDiagnostic, token)
|
||||
@@ -793,13 +804,17 @@ internal class KtFirCallResolver(
|
||||
}
|
||||
|
||||
override fun collectCallCandidates(psi: KtElement): List<KtCallCandidateInfo> = wrapError(psi) {
|
||||
getCallInfo(psi) { psiToResolve, resolveCalleeExpressionOfFunctionCall, resolveFragmentOfCall ->
|
||||
collectCallCandidates(
|
||||
psiToResolve,
|
||||
resolveCalleeExpressionOfFunctionCall,
|
||||
resolveFragmentOfCall
|
||||
)
|
||||
}
|
||||
getCallInfo(
|
||||
psi,
|
||||
getErrorCallInfo = { emptyList() },
|
||||
getCallInfo = { psiToResolve, resolveCalleeExpressionOfFunctionCall, resolveFragmentOfCall ->
|
||||
collectCallCandidates(
|
||||
psiToResolve,
|
||||
resolveCalleeExpressionOfFunctionCall,
|
||||
resolveFragmentOfCall
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
// TODO: Refactor common code with FirElement.toKtCallInfo() when other FirResolvables are handled
|
||||
@@ -1185,4 +1200,9 @@ internal class KtFirCallResolver(
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun FirDiagnosticHolder.createKtDiagnostic(psi: KtElement?): KtDiagnostic {
|
||||
return (source?.let { diagnostic.asKtDiagnostic(it, psi?.toKtPsiSourceElement()) }
|
||||
?: KtNonBoundToPsiErrorDiagnostic(factoryName = null, diagnostic.reason, token))
|
||||
}
|
||||
}
|
||||
|
||||
+16
@@ -854,6 +854,22 @@ public class FirIdeNormalAnalysisSourceModuleResolveCallTestGenerated extends Ab
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("analysis/analysis-api/testData/components/callResolver/resolveCall/invalidCode")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class InvalidCode {
|
||||
@Test
|
||||
public void testAllFilesPresentInInvalidCode() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/components/callResolver/resolveCall/invalidCode"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("getterAssignment.kt")
|
||||
public void testGetterAssignment() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/invalidCode/getterAssignment.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("analysis/analysis-api/testData/components/callResolver/resolveCall/nonCalls")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
|
||||
Reference in New Issue
Block a user