FIR IDE: rework KtCall to work with error cals

This commit is contained in:
Ilya Kirillov
2020-12-07 17:43:29 +01:00
parent e6327ef490
commit f30c6bf86a
27 changed files with 256 additions and 124 deletions
@@ -1,30 +0,0 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.frontend.api
import org.jetbrains.kotlin.idea.frontend.api.symbols.*
sealed class CallInfo {
abstract val isSuspendCall: Boolean
abstract val targetFunction: KtFunctionLikeSymbol?
}
data class VariableAsFunctionCallInfo(val target: KtVariableLikeSymbol, override val isSuspendCall: Boolean) : CallInfo() {
override val targetFunction: KtFunctionLikeSymbol? = null
}
data class VariableAsFunctionLikeCallInfo(val target: KtVariableLikeSymbol, val invokeFunction: KtFunctionSymbol) : CallInfo() {
override val isSuspendCall: Boolean get() = invokeFunction.isSuspend
override val targetFunction get() = invokeFunction
}
data class FunctionCallInfo(override val targetFunction: KtFunctionLikeSymbol) : CallInfo() {
override val isSuspendCall: Boolean
get() = when (targetFunction) {
is KtFunctionSymbol -> targetFunction.isSuspend
else -> false
}
}
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.idea.frontend.api
import org.jetbrains.kotlin.diagnostics.Diagnostic
import org.jetbrains.kotlin.idea.frontend.api.calls.KtCall
import org.jetbrains.kotlin.idea.frontend.api.components.*
import org.jetbrains.kotlin.idea.frontend.api.scopes.*
import org.jetbrains.kotlin.idea.frontend.api.symbols.*
@@ -118,9 +119,9 @@ abstract class KtAnalysisSession(override val token: ValidityToken) : ValidityTo
fun <S : KtSymbol> KtSymbolPointer<S>.restoreSymbol(): S? = restoreSymbol(this@KtAnalysisSession)
fun KtCallExpression.resolveCall(): CallInfo? = callResolver.resolveCall(this)
fun KtCallExpression.resolveCall(): KtCall? = callResolver.resolveCall(this)
fun KtBinaryExpression.resolveCall(): CallInfo? = callResolver.resolveCall(this)
fun KtBinaryExpression.resolveCall(): KtCall? = callResolver.resolveCall(this)
fun KtReference.resolveToSymbols(): Collection<KtSymbol> {
check(this is KtSymbolBasedReference) { "To get reference symbol the one should be KtSymbolBasedReference" }
@@ -0,0 +1,81 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.frontend.api.calls
import org.jetbrains.kotlin.idea.frontend.api.diagnostics.KtDiagnostic
import org.jetbrains.kotlin.idea.frontend.api.symbols.*
/**
* Represents direct or indirect (via invoke) function call from Kotlin code
*/
sealed class KtCall {
abstract val isErrorCall: Boolean
}
/**
* Call using `()` of some variable of functional type, e.g.,
*
* fun x(f: () -> Int) {
* f() // functional type call
* }
*/
class KtFunctionalTypeVariableCall(val target: KtVariableLikeSymbol) : KtCall() {
override val isErrorCall: Boolean get() = false
}
/**
* Direct or indirect call of function declared by user
*/
sealed class KtDeclaredFunctionCall : KtCall() {
abstract val targetFunction: KtCallTarget
override val isErrorCall: Boolean
get() = targetFunction is KtErrorCallTarget
}
/**
* Call using () on variable on some non-functional type, considers that `invoke` function is declared somewhere
*
* fun x(y: Int) {
* y() // variable with invoke function call
* }
*
* fun Int.invoke() {}
*/
class KtVariableWithInvokeFunctionCall(
val target: KtVariableLikeSymbol,
val invokeFunction: KtCallTarget,
) : KtDeclaredFunctionCall() {
override val targetFunction: KtCallTarget get() = invokeFunction
}
/**
* Simple function call, e.g.,
*
* x.toString() // function call
*/
data class KtFunctionCall(override val targetFunction: KtCallTarget) : KtDeclaredFunctionCall()
/**
* Represents function(s) in which call was resolved,
* Can be success [KtSuccessCallTarget] in this case there only one such function
* Or erroneous [KtErrorCallTarget] in this case there can be any count of candidates
*/
sealed class KtCallTarget {
abstract val candidates: Collection<KtFunctionLikeSymbol>
}
/**
* Success call of [symbol]
*/
class KtSuccessCallTarget(val symbol: KtFunctionLikeSymbol) : KtCallTarget() {
override val candidates: Collection<KtFunctionLikeSymbol>
get() = listOf(symbol)
}
/**
* Function all with errors, possible candidates are [candidates]
*/
class KtErrorCallTarget(override val candidates: Collection<KtFunctionLikeSymbol>, val diagnostic: KtDiagnostic) : KtCallTarget()
@@ -0,0 +1,20 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.frontend.api.calls
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtFunctionLikeSymbol
fun KtCallTarget.getSuccessCallSymbolOrNull(): KtFunctionLikeSymbol? = when (this) {
is KtSuccessCallTarget -> symbol
is KtErrorCallTarget -> null
}
inline fun <reified S : KtFunctionLikeSymbol> KtCall.isSuccessCallOf(predicate: (S) -> Boolean): Boolean {
if (this !is KtFunctionCall) return false
val symbol = targetFunction.getSuccessCallSymbolOrNull() ?: return false
if (symbol !is S) return false
return predicate(symbol)
}
@@ -5,11 +5,11 @@
package org.jetbrains.kotlin.idea.frontend.api.components
import org.jetbrains.kotlin.idea.frontend.api.CallInfo
import org.jetbrains.kotlin.idea.frontend.api.calls.KtCall
import org.jetbrains.kotlin.psi.KtBinaryExpression
import org.jetbrains.kotlin.psi.KtCallExpression
abstract class KtCallResolver : KtAnalysisSessionComponent() {
abstract fun resolveCall(call: KtCallExpression): CallInfo?
abstract fun resolveCall(call: KtBinaryExpression): CallInfo?
abstract fun resolveCall(call: KtCallExpression): KtCall?
abstract fun resolveCall(call: KtBinaryExpression): KtCall?
}
@@ -0,0 +1,12 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.frontend.api.diagnostics
sealed class KtDiagnostic {
abstract val message: String
}
data class KtSimpleDiagnostic(override val message: String): KtDiagnostic()