[Analysis API FIR] fix call resolution of non-resolvable elements
This commit is contained in:
+2
-2
@@ -145,7 +145,7 @@ internal class KtFe10CallResolver(
|
|||||||
get() = analysisSession.token
|
get() = analysisSession.token
|
||||||
|
|
||||||
override fun resolveCall(psi: KtElement): KtCallInfo? = with(analysisContext.analyze(psi, AnalysisMode.PARTIAL_WITH_DIAGNOSTICS)) {
|
override fun resolveCall(psi: KtElement): KtCallInfo? = with(analysisContext.analyze(psi, AnalysisMode.PARTIAL_WITH_DIAGNOSTICS)) {
|
||||||
if (psi.isNotResolvable()) return null
|
if (!canBeResolvedAsCall(psi)) return null
|
||||||
|
|
||||||
val parentBinaryExpression = psi.parentOfType<KtBinaryExpression>()
|
val parentBinaryExpression = psi.parentOfType<KtBinaryExpression>()
|
||||||
val lhs = KtPsiUtil.deparenthesize(parentBinaryExpression?.left)
|
val lhs = KtPsiUtil.deparenthesize(parentBinaryExpression?.left)
|
||||||
@@ -177,7 +177,7 @@ internal class KtFe10CallResolver(
|
|||||||
|
|
||||||
override fun collectCallCandidates(psi: KtElement): List<KtCallCandidateInfo> =
|
override fun collectCallCandidates(psi: KtElement): List<KtCallCandidateInfo> =
|
||||||
with(analysisContext.analyze(psi, AnalysisMode.PARTIAL_WITH_DIAGNOSTICS)) {
|
with(analysisContext.analyze(psi, AnalysisMode.PARTIAL_WITH_DIAGNOSTICS)) {
|
||||||
if (psi.isNotResolvable()) return emptyList()
|
if (!canBeResolvedAsCall(psi)) return emptyList()
|
||||||
|
|
||||||
val resolvedKtCallInfo = resolveCall(psi)
|
val resolvedKtCallInfo = resolveCall(psi)
|
||||||
val bestCandidateDescriptors =
|
val bestCandidateDescriptors =
|
||||||
|
|||||||
+28
@@ -854,6 +854,34 @@ public class Fe10IdeNormalAnalysisSourceModuleResolveCallTestGenerated extends A
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@TestMetadata("analysis/analysis-api/testData/components/callResolver/resolveCall/nonCalls")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
public class NonCalls {
|
||||||
|
@Test
|
||||||
|
public void testAllFilesPresentInNonCalls() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/components/callResolver/resolveCall/nonCalls"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("ifExpression.kt")
|
||||||
|
public void testIfExpression() throws Exception {
|
||||||
|
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/nonCalls/ifExpression.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("literalExpression.kt")
|
||||||
|
public void testLiteralExpression() throws Exception {
|
||||||
|
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/nonCalls/literalExpression.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("whenExpression.kt")
|
||||||
|
public void testWhenExpression() throws Exception {
|
||||||
|
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/nonCalls/whenExpression.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
@TestMetadata("analysis/analysis-api/testData/components/callResolver/resolveCall/withTestCompilerPluginEnabled")
|
@TestMetadata("analysis/analysis-api/testData/components/callResolver/resolveCall/withTestCompilerPluginEnabled")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
|||||||
+13
-11
@@ -86,18 +86,20 @@ internal class KtFirCallResolver(
|
|||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun resolveCall(psi: KtElement): KtCallInfo? = wrapError(psi) {
|
override fun resolveCall(psi: KtElement): KtCallInfo? {
|
||||||
val ktCallInfos = getCallInfo(psi) { psiToResolve, resolveCalleeExpressionOfFunctionCall, resolveFragmentOfCall ->
|
return wrapError(psi) {
|
||||||
listOfNotNull(
|
val ktCallInfos = getCallInfo(psi) { psiToResolve, resolveCalleeExpressionOfFunctionCall, resolveFragmentOfCall ->
|
||||||
toKtCallInfo(
|
listOfNotNull(
|
||||||
psiToResolve,
|
toKtCallInfo(
|
||||||
resolveCalleeExpressionOfFunctionCall,
|
psiToResolve,
|
||||||
resolveFragmentOfCall
|
resolveCalleeExpressionOfFunctionCall,
|
||||||
|
resolveFragmentOfCall
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
}
|
||||||
|
check(ktCallInfos.size <= 1) { "Should only return 1 KtCallInfo" }
|
||||||
|
ktCallInfos.singleOrNull()
|
||||||
}
|
}
|
||||||
check(ktCallInfos.size <= 1) { "Should only return 1 KtCallInfo" }
|
|
||||||
ktCallInfos.singleOrNull()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private inline fun <T> getCallInfo(
|
private inline fun <T> getCallInfo(
|
||||||
@@ -108,7 +110,7 @@ internal class KtFirCallResolver(
|
|||||||
resolveFragmentOfCall: Boolean
|
resolveFragmentOfCall: Boolean
|
||||||
) -> List<T>
|
) -> List<T>
|
||||||
): List<T> {
|
): List<T> {
|
||||||
if (psi.isNotResolvable()) return emptyList()
|
if (!canBeResolvedAsCall(psi)) return emptyList()
|
||||||
|
|
||||||
val containingCallExpressionForCalleeExpression = psi.getContainingCallExpressionForCalleeExpression()
|
val containingCallExpressionForCalleeExpression = psi.getContainingCallExpressionForCalleeExpression()
|
||||||
val containingBinaryExpressionForLhs = psi.getContainingBinaryExpressionForIncompleteLhs()
|
val containingBinaryExpressionForLhs = psi.getContainingBinaryExpressionForIncompleteLhs()
|
||||||
|
|||||||
+28
@@ -854,6 +854,34 @@ public class FirIdeNormalAnalysisSourceModuleResolveCallTestGenerated extends Ab
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@TestMetadata("analysis/analysis-api/testData/components/callResolver/resolveCall/nonCalls")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
public class NonCalls {
|
||||||
|
@Test
|
||||||
|
public void testAllFilesPresentInNonCalls() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/components/callResolver/resolveCall/nonCalls"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("ifExpression.kt")
|
||||||
|
public void testIfExpression() throws Exception {
|
||||||
|
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/nonCalls/ifExpression.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("literalExpression.kt")
|
||||||
|
public void testLiteralExpression() throws Exception {
|
||||||
|
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/nonCalls/literalExpression.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("whenExpression.kt")
|
||||||
|
public void testWhenExpression() throws Exception {
|
||||||
|
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/nonCalls/whenExpression.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
@TestMetadata("analysis/analysis-api/testData/components/callResolver/resolveCall/withTestCompilerPluginEnabled")
|
@TestMetadata("analysis/analysis-api/testData/components/callResolver/resolveCall/withTestCompilerPluginEnabled")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
|||||||
+12
-10
@@ -45,17 +45,19 @@ abstract class AbstractKtCallResolver : KtCallResolver() {
|
|||||||
return KtPsiUtil.deparenthesize(safeQualifiedExpression.receiverExpression) == KtPsiUtil.deparenthesize(this)
|
return KtPsiUtil.deparenthesize(safeQualifiedExpression.receiverExpression) == KtPsiUtil.deparenthesize(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected fun canBeResolvedAsCall(ktElement: KtElement): Boolean = when (ktElement) {
|
||||||
|
is KtBinaryExpression -> ktElement.operationToken !in nonCallBinaryOperator
|
||||||
|
is KtOperationReferenceExpression -> ktElement.operationSignTokenType !in nonCallBinaryOperator
|
||||||
|
is KtCallElement -> true
|
||||||
|
is KtConstructorCalleeExpression -> true
|
||||||
|
is KtDotQualifiedExpression -> true
|
||||||
|
is KtNameReferenceExpression -> true
|
||||||
|
is KtOperationExpression -> true
|
||||||
|
is KtArrayAccessExpression -> true
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
|
|
||||||
protected companion object {
|
protected companion object {
|
||||||
private val nonCallBinaryOperator: Set<KtSingleValueToken> = setOf(KtTokens.ELVIS, KtTokens.EQEQEQ, KtTokens.EXCLEQEQEQ)
|
private val nonCallBinaryOperator: Set<KtSingleValueToken> = setOf(KtTokens.ELVIS, KtTokens.EQEQEQ, KtTokens.EXCLEQEQEQ)
|
||||||
|
|
||||||
/**
|
|
||||||
* We don't want to resolve the operators from the [AbstractKtCallResolver.nonCallBinaryOperator] list, because it's either
|
|
||||||
* not possible or not desirable.
|
|
||||||
*/
|
|
||||||
fun KtElement.isNotResolvable(): Boolean {
|
|
||||||
return this is KtBinaryExpression && operationToken in nonCallBinaryOperator ||
|
|
||||||
this is KtOperationReferenceExpression && operationSignTokenType in nonCallBinaryOperator
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+28
@@ -853,4 +853,32 @@ public class FirStandaloneNormalAnalysisSourceModuleResolveCallTestGenerated ext
|
|||||||
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/assignments/insidePlusAssignTarget.kt");
|
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/assignments/insidePlusAssignTarget.kt");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@TestMetadata("analysis/analysis-api/testData/components/callResolver/resolveCall/nonCalls")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
public class NonCalls {
|
||||||
|
@Test
|
||||||
|
public void testAllFilesPresentInNonCalls() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/components/callResolver/resolveCall/nonCalls"), Pattern.compile("^(.+)\\.kt$"), null, true, "withTestCompilerPluginEnabled");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("ifExpression.kt")
|
||||||
|
public void testIfExpression() throws Exception {
|
||||||
|
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/nonCalls/ifExpression.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("literalExpression.kt")
|
||||||
|
public void testLiteralExpression() throws Exception {
|
||||||
|
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/nonCalls/literalExpression.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("whenExpression.kt")
|
||||||
|
public void testWhenExpression() throws Exception {
|
||||||
|
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/nonCalls/whenExpression.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+3
@@ -0,0 +1,3 @@
|
|||||||
|
fun main() {
|
||||||
|
val x = <expr>if (true) 1 else 2</expr>
|
||||||
|
}
|
||||||
Vendored
+1
@@ -0,0 +1 @@
|
|||||||
|
null
|
||||||
Vendored
+3
@@ -0,0 +1,3 @@
|
|||||||
|
fun main() {
|
||||||
|
val x = <expr>1</expr>
|
||||||
|
}
|
||||||
Vendored
+1
@@ -0,0 +1 @@
|
|||||||
|
null
|
||||||
Vendored
+3
@@ -0,0 +1,3 @@
|
|||||||
|
fun main() {
|
||||||
|
val x = <expr>when (true) { else -> 2 }</expr>
|
||||||
|
}
|
||||||
Vendored
+1
@@ -0,0 +1 @@
|
|||||||
|
null
|
||||||
Vendored
+1
-1
@@ -1,3 +1,3 @@
|
|||||||
KtErrorCallInfo:
|
KtErrorCallInfo:
|
||||||
candidateCalls = []
|
candidateCalls = []
|
||||||
diagnostic = ERROR<OTHER_ERROR: Unknown (other) error>
|
diagnostic = ERROR<null: Erroneous delegated constructor call>
|
||||||
Reference in New Issue
Block a user