[Analysis API FIR] fix NPE of == call resolve without builtins

We should not expect builtins to be always available as they are taken from indecies.

For K1 and FIR Standalone implementations, the builtins are always available.

^KT-62957 fixed
This commit is contained in:
Ilya Kirillov
2023-10-27 16:07:27 +02:00
committed by Space Team
parent 1aa5cf031f
commit 4720a0faa7
8 changed files with 92 additions and 6 deletions
@@ -664,6 +664,12 @@ public class Fe10IdeNormalAnalysisSourceModuleResolveCallTestGenerated extends A
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/memberFunctionCallWithTypeArgument.kt");
}
@Test
@TestMetadata("noBuiltIns.kt")
public void testNoBuiltIns() throws Exception {
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/noBuiltIns.kt");
}
@Test
@TestMetadata("postfixUnaryOperatorOnVar.kt")
public void testPostfixUnaryOperatorOnVar() throws Exception {
@@ -79,14 +79,15 @@ internal class KtFirCallResolver(
override val analysisSession: KtFirAnalysisSession,
override val token: KtLifetimeToken,
) : AbstractKtCallResolver(), KtFirAnalysisSessionComponent {
private val equalsSymbolInAny: FirNamedFunctionSymbol by lazy(LazyThreadSafetyMode.PUBLICATION) {
private val equalsSymbolInAny: FirNamedFunctionSymbol? by lazy(LazyThreadSafetyMode.PUBLICATION) {
val session = analysisSession.useSiteSession
val anyFirClass = session.builtinTypes.anyType.toRegularClassSymbol(session) ?: return@lazy null
val scope = session.declaredMemberScope(
session.builtinTypes.anyType.toRegularClassSymbol(session)!!,
anyFirClass,
memberRequiredPhase = FirResolvePhase.STATUS,
)
lateinit var result: FirNamedFunctionSymbol
var result: FirNamedFunctionSymbol? = null
scope.processFunctionsByName(EQUALS) {
result = it
}
@@ -1217,13 +1218,12 @@ internal class KtFirCallResolver(
val rightPsi = binaryExpression.right ?: return null
return when (operation) {
FirOperation.EQ, FirOperation.NOT_EQ -> {
val equalsSymbolInAny = equalsSymbolInAny
val leftOperand = arguments.firstOrNull() ?: return null
val session = analysisSession.useSiteSession
val leftOperandType = leftOperand.resolvedType
val classSymbol = leftOperandType.fullyExpandedType(session).toSymbol(session) as? FirClassSymbol<*>
val equalsSymbol = classSymbol?.getEqualsSymbol(equalsSymbolInAny) ?: equalsSymbolInAny
val equalsSymbol = classSymbol?.getEqualsSymbol() ?: equalsSymbolInAny ?: return null
val ktSignature = equalsSymbol.toKtSignature()
KtSuccessCallInfo(
KtSimpleFunctionCall(
@@ -1244,7 +1244,7 @@ internal class KtFirCallResolver(
}
}
private fun FirClassSymbol<*>.getEqualsSymbol(equalsSymbolInAny: FirNamedFunctionSymbol): FirNamedFunctionSymbol {
private fun FirClassSymbol<*>.getEqualsSymbol(): FirNamedFunctionSymbol? {
val scope = unsubstitutedScope(
analysisSession.useSiteSession,
analysisSession.getScopeSessionFor(analysisSession.useSiteSession),
@@ -664,6 +664,12 @@ public class FirIdeNormalAnalysisSourceModuleResolveCallTestGenerated extends Ab
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/memberFunctionCallWithTypeArgument.kt");
}
@Test
@TestMetadata("noBuiltIns.kt")
public void testNoBuiltIns() throws Exception {
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/noBuiltIns.kt");
}
@Test
@TestMetadata("postfixUnaryOperatorOnVar.kt")
public void testPostfixUnaryOperatorOnVar() throws Exception {
@@ -664,6 +664,12 @@ public class FirStandaloneNormalAnalysisSourceModuleResolveCallTestGenerated ext
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/memberFunctionCallWithTypeArgument.kt");
}
@Test
@TestMetadata("noBuiltIns.kt")
public void testNoBuiltIns() throws Exception {
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/noBuiltIns.kt");
}
@Test
@TestMetadata("postfixUnaryOperatorOnVar.kt")
public void testPostfixUnaryOperatorOnVar() throws Exception {
@@ -0,0 +1,31 @@
KtSuccessCallInfo:
call = KtSimpleFunctionCall:
isImplicitInvoke = false
partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
dispatchReceiver = KtExplicitReceiverValue:
expression = 1
isSafeNavigation = false
type = kotlin.Int
extensionReceiver = null
signature = KtFunctionLikeSignature:
receiverType = null
returnType = kotlin.Boolean
symbol = kotlin/Int.equals(<dispatch receiver>: kotlin.Int, other: kotlin.Any?): kotlin.Boolean
valueParameters = [
KtVariableLikeSignature:
name = other
receiverType = null
returnType = kotlin.Any?
symbol = other: kotlin.Any?
callableIdIfNonLocal = null
]
callableIdIfNonLocal = kotlin/Int.equals
typeArgumentsMapping = {}
argumentMapping = {
2 -> (KtVariableLikeSignature:
name = other
receiverType = null
returnType = kotlin.Any?
symbol = other: kotlin.Any?
callableIdIfNonLocal = null)
}
@@ -0,0 +1,5 @@
// NO_RUNTIME
fun call() {
<expr>1 == 2</expr>
}
@@ -0,0 +1,31 @@
KtSuccessCallInfo:
call = KtSimpleFunctionCall:
isImplicitInvoke = false
partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
dispatchReceiver = KtExplicitReceiverValue:
expression = 1
isSafeNavigation = false
type = kotlin.Int
extensionReceiver = null
signature = KtFunctionLikeSignature:
receiverType = null
returnType = kotlin.Boolean
symbol = kotlin/Int.equals(<dispatch receiver>: kotlin.Int, other: kotlin.Any?): kotlin.Boolean
valueParameters = [
KtVariableLikeSignature:
name = other
receiverType = null
returnType = kotlin.Any?
symbol = other: kotlin.Any?
callableIdIfNonLocal = null
]
callableIdIfNonLocal = kotlin/Int.equals
typeArgumentsMapping = {}
argumentMapping = {
2 -> (KtVariableLikeSignature:
name = other
receiverType = null
returnType = kotlin.Any?
symbol = other: kotlin.Any?
callableIdIfNonLocal = null)
}
@@ -0,0 +1 @@
null