From 53b38937389eb91fb150ef1656d73b18539e65ad Mon Sep 17 00:00:00 2001 From: Tianyu Geng Date: Thu, 18 Nov 2021 17:56:24 -0800 Subject: [PATCH] Analysis API: rework data model of resolve call API --- .../kotlin/analysis/api/calls/KtCall.kt | 608 +++++++++++++----- .../kotlin/analysis/api/calls/ktCallUtils.kt | 2 +- .../analysis/api/components/KtCallResolver.kt | 38 +- 3 files changed, 469 insertions(+), 179 deletions(-) diff --git a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/calls/KtCall.kt b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/calls/KtCall.kt index 1bc2830ea0e..ceef1eb48e3 100644 --- a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/calls/KtCall.kt +++ b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/calls/KtCall.kt @@ -7,171 +7,477 @@ package org.jetbrains.kotlin.analysis.api.calls import org.jetbrains.kotlin.analysis.api.ValidityTokenOwner import org.jetbrains.kotlin.analysis.api.diagnostics.KtDiagnostic -import org.jetbrains.kotlin.analysis.api.symbols.KtFunctionLikeSymbol -import org.jetbrains.kotlin.analysis.api.symbols.KtValueParameterSymbol -import org.jetbrains.kotlin.analysis.api.symbols.KtVariableLikeSymbol +import org.jetbrains.kotlin.analysis.api.symbols.* import org.jetbrains.kotlin.analysis.api.tokens.ValidityToken -import org.jetbrains.kotlin.analysis.api.types.KtSubstitutor +import org.jetbrains.kotlin.analysis.api.types.KtType import org.jetbrains.kotlin.analysis.api.withValidityAssertion import org.jetbrains.kotlin.psi.KtExpression /** - * Represents direct or indirect (via invoke) function call from Kotlin code + * Call information at call site. */ -public sealed class KtCall : ValidityTokenOwner { - public abstract val isErrorCall: Boolean - public abstract val argumentMapping: LinkedHashMap - public abstract val targetFunction: KtCallTarget - public abstract val substitutor: KtSubstitutor -} +public sealed class KtCallInfo : ValidityTokenOwner /** - * Call using `()` of some variable of functional type, e.g., - * - * fun x(f: () -> Int) { - * f() // functional type call - * } + * Successfully resolved call. */ -public class KtFunctionalTypeVariableCall( - private val _target: KtVariableLikeSymbol, - private val _argumentMapping: LinkedHashMap, - private val _targetFunction: KtCallTarget, - private val _substitutor: KtSubstitutor, +public class KtSuccessCallInfo(private val _call: KtCall) : KtCallInfo() { override val token: ValidityToken -) : KtCall() { - public val target: KtVariableLikeSymbol get() = withValidityAssertion { _target } - override val isErrorCall: Boolean get() = withValidityAssertion { false } - override val argumentMapping: LinkedHashMap - get() = withValidityAssertion { _argumentMapping } - override val targetFunction: KtCallTarget - get() = withValidityAssertion { _targetFunction } - override val substitutor: KtSubstitutor - get() = withValidityAssertion { _substitutor } + get() = _call.token + public val call: KtCall get() = withValidityAssertion { _call } } /** - * Direct or indirect call of function declared by user + * Call that contains errors. */ -public sealed class KtDeclaredFunctionCall : KtCall() { - override val isErrorCall: Boolean - get() = withValidityAssertion { 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() {} - */ -public class KtVariableWithInvokeFunctionCall( - private val _target: KtVariableLikeSymbol, - private val _argumentMapping: LinkedHashMap, - private val _targetFunction: KtCallTarget, - private val _substitutor: KtSubstitutor, - override val token: ValidityToken -) : KtDeclaredFunctionCall() { - public val target: KtVariableLikeSymbol get() = withValidityAssertion { _target } - override val argumentMapping: LinkedHashMap - get() = withValidityAssertion { _argumentMapping } - override val targetFunction: KtCallTarget - get() = withValidityAssertion { _targetFunction } - override val substitutor: KtSubstitutor - get() = withValidityAssertion { _substitutor } -} - -/** - * Simple function call, e.g., - * - * x.toString() // function call - */ -public class KtFunctionCall( - private val _argumentMapping: LinkedHashMap, - private val _targetFunction: KtCallTarget, - private val _substitutor: KtSubstitutor, - override val token: ValidityToken -) : KtDeclaredFunctionCall() { - override val argumentMapping: LinkedHashMap - get() = withValidityAssertion { _argumentMapping } - override val targetFunction: KtCallTarget - get() = withValidityAssertion { _targetFunction } - override val substitutor: KtSubstitutor - get() = withValidityAssertion { _substitutor } -} - -/** - * Annotation call, e.g., - * - * @Retention(AnnotationRetention.SOURCE) // annotation call - * annotation class Ann - */ -public class KtAnnotationCall( - private val _argumentMapping: LinkedHashMap, - private val _targetFunction: KtCallTarget, - override val token: ValidityToken -) : KtDeclaredFunctionCall() { - override val argumentMapping: LinkedHashMap - get() = withValidityAssertion { _argumentMapping } - override val targetFunction: KtCallTarget - get() = withValidityAssertion { _targetFunction } - - // Type parameter is allowed for an annotation class but not allowed as members. So substitutor is probably never useful. - override val substitutor: KtSubstitutor = KtSubstitutor.Empty(token) -} -// TODO: Add other properties, e.g., useSiteTarget - -/** - * Delegated constructor call, e.g., - * - * open class A(a: Int) - * class B(b: Int) : A(b) { // delegated constructor call (kind = SUPER_CALL) - * constructor() : this(1) // delegated constructor call (kind = THIS_CALL) - * } - */ -public class KtDelegatedConstructorCall( - private val _argumentMapping: LinkedHashMap, - private val _targetFunction: KtCallTarget, - public val kind: KtDelegatedConstructorCallKind, - override val token: ValidityToken -) : KtDeclaredFunctionCall() { - override val argumentMapping: LinkedHashMap - get() = withValidityAssertion { _argumentMapping } - override val targetFunction: KtCallTarget - get() = withValidityAssertion { _targetFunction } - - // A delegate constructor call never has any type argument. - override val substitutor: KtSubstitutor = KtSubstitutor.Empty(token) -} - -public enum class KtDelegatedConstructorCallKind { SUPER_CALL, THIS_CALL } - -/** - * 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 - */ -public sealed class KtCallTarget : ValidityTokenOwner { - public abstract val candidates: Collection -} - -/** - * Success call of [symbol] - */ -public class KtSuccessCallTarget(private val _symbol: KtFunctionLikeSymbol, override val token: ValidityToken) : KtCallTarget() { - public val symbol: KtFunctionLikeSymbol get() = withValidityAssertion { _symbol } - override val candidates: Collection get() = withValidityAssertion { listOf(symbol) } -} - -/** - * Function call with errors, possible candidates are [candidates] - */ -public class KtErrorCallTarget( - private val _candidates: Collection, +public class KtErrorCallInfo( + private val _candidateCalls: List, private val _diagnostic: KtDiagnostic, override val token: ValidityToken -) : KtCallTarget() { +) : KtCallInfo() { + public val candidateCalls: List get() = withValidityAssertion { _candidateCalls } public val diagnostic: KtDiagnostic get() = withValidityAssertion { _diagnostic } - override val candidates: Collection get() = withValidityAssertion { _candidates } -} \ No newline at end of file +} + +public val KtCallInfo.calls: List + get() = when (this) { + is KtErrorCallInfo -> candidateCalls + is KtSuccessCallInfo -> listOf(call) + } + +public inline fun KtCallInfo.singleCallOrNull(): T? { + return calls.singleOrNull { it is T } as T? +} + +public fun KtCallInfo.singleFunctionCallOrNull(): KtFunctionCall<*>? = singleCallOrNull() +public fun KtCallInfo.singleVariableAccessCall(): KtVariableAccessCall? = singleCallOrNull() + +@Suppress("UNCHECKED_CAST") +public fun KtCallInfo.singleConstructorCallOrNull(): KtFunctionCall? = + singleCallOrNull>()?.takeIf { it.symbol is KtConstructorSymbol } as KtFunctionCall? + +public inline fun KtCallInfo.successfulCallOrNull(): T? { + return (this as? KtSuccessCallInfo)?.call as? T +} + +public fun KtCallInfo.successfulFunctionCallOrNull(): KtFunctionCall<*>? = successfulCallOrNull() +public fun KtCallInfo.successfulVariableAccessCall(): KtVariableAccessCall? = successfulCallOrNull() + +@Suppress("UNCHECKED_CAST") +public fun KtCallInfo.successfulConstructorCallOrNull(): KtFunctionCall? = + successfulCallOrNull>()?.takeIf { it.symbol is KtConstructorSymbol } as KtFunctionCall? +/** + * A call to a function, a simple/compound access to a property, or a simple/compound access through `get` and `set` convention. + */ +public sealed class KtCall : ValidityTokenOwner + +/** + * A callable symbol partially applied with receivers and type arguments. Essentially, this is a call that misses some information. For + * properties, the missing information is the type of access (read, write, or compound access) to this property. For functions, the missing + * information is the value arguments for the call. + */ +public class KtPartiallyAppliedSymbol>( + private val _signature: C, + private val _dispatchReceiver: KtReceiverValue?, + private val _extensionReceiver: KtReceiverValue?, +) : ValidityTokenOwner { + + override val token: ValidityToken get() = _signature.token + + /** + * The function or variable (property) declaration. + */ + public val signature: C get() = withValidityAssertion { _signature } + + /** + * The dispatch receiver for this symbol access. Dispatch receiver is available if the symbol is declared inside a class or object. + */ + public val dispatchReceiver: KtReceiverValue? get() = withValidityAssertion { _dispatchReceiver } + + /** + * The extension receiver for this symbol access. Extension receiver is available if the symbol is declared with an extension receiver. + */ + public val extensionReceiver: KtReceiverValue? get() = withValidityAssertion { _extensionReceiver } +} + +public val > KtPartiallyAppliedSymbol.symbol: S get() = signature.symbol + +/** + * A synthetic call to assert an expression is not null. For example + * ``` + * fun test(s: String?) { + * s!!.length // Here the receiver is a `KtCheckNotNullCall` with base expression `s`. + * } + * ``` + */ +public class KtCheckNotNullCall( + override val token: ValidityToken, + private val _baseExpression: KtExpression, +) : KtCall() { + public val baseExpression: KtExpression get() = withValidityAssertion { _baseExpression } +} + +/** + * A call to a function, or a simple/compound access to a property. + */ +public sealed class KtCallableMemberCall> : KtCall() { + public abstract val partiallyAppliedSymbol: KtPartiallyAppliedSymbol +} + +public val > KtCallableMemberCall.symbol: S get() = partiallyAppliedSymbol.symbol + +public sealed class KtFunctionCall( + private val _argumentMapping: LinkedHashMap>, +) : KtCallableMemberCall>() { + + /** + * The mapping from argument to parameter declaration. In case of vararg parameters, multiple arguments may be mapped to the same + * `KtValueParameterSymbol`. + */ + public val argumentMapping: LinkedHashMap> get() = withValidityAssertion { _argumentMapping } +} + +public typealias KtPartiallyAppliedFunctionSymbol = KtPartiallyAppliedSymbol> + +/** + * A call to a function. + */ +public class KtSimpleFunctionCall( + private val _partiallyAppliedSymbol: KtPartiallyAppliedFunctionSymbol, + argumentMapping: LinkedHashMap>, + private val _isImplicitInvoke: Boolean, +) : KtFunctionCall(argumentMapping) { + override val token: ValidityToken get() = _partiallyAppliedSymbol.token + + /** + * The function and receivers for this call. + */ + override val partiallyAppliedSymbol: KtPartiallyAppliedFunctionSymbol get() = withValidityAssertion { _partiallyAppliedSymbol } + + /** + * Whether this function call is an implicit invoke call on a value that has an `invoke` member function. See + * https://kotlinlang.org/docs/operator-overloading.html#invoke-operator for more details. + */ + public val isImplicitInvoke: Boolean get() = withValidityAssertion { _isImplicitInvoke } +} + +/** + * A call to an annotation. For example + * ``` + * @Deprecated("foo") // call to annotation constructor with single argument `"foo"`. + * fun foo() {} + * ``` + */ +public class KtAnnotationCall( + private val _partiallyAppliedSymbol: KtPartiallyAppliedFunctionSymbol, + argumentMapping: LinkedHashMap>, +) : KtFunctionCall(argumentMapping) { + override val token: ValidityToken get() = _partiallyAppliedSymbol.token + + /** + * The function and receivers for this call. + */ + override val partiallyAppliedSymbol: KtPartiallyAppliedFunctionSymbol get() = withValidityAssertion { _partiallyAppliedSymbol } +} + +/** + * A delegated call to constructors. For example + * ``` + * open class SuperClass(i: Int) + * class SubClass1: SuperClass(1) // a call to constructor of `SuperClass` with single argument `1` + * class SubClass2 : SuperClass { + * constructor(i: Int): super(i) {} // a call to constructor of `SuperClass` with single argument `i` + * constructor(): this(2) {} // a call to constructor of `SubClass2` with single argument `2`. + * } + * ``` + */ +public class KtDelegatedConstructorCall( + private val _partiallyAppliedSymbol: KtPartiallyAppliedFunctionSymbol, + private val _kind: Kind, + argumentMapping: LinkedHashMap>, +) : KtFunctionCall(argumentMapping) { + override val token: ValidityToken get() = _partiallyAppliedSymbol.token + + /** + * The function and receivers for this call. + */ + override val partiallyAppliedSymbol: KtPartiallyAppliedFunctionSymbol get() = withValidityAssertion { _partiallyAppliedSymbol } + + public val kind: Kind get() = withValidityAssertion { _kind } + + public enum class Kind { SUPER_CALL, THIS_CALL } +} + +/** + * An access to variables (including properties). + */ +public sealed class KtVariableAccessCall : KtCallableMemberCall>() + +public typealias KtPartiallyAppliedVariableSymbol = KtPartiallyAppliedSymbol> + +/** + * A simple read or write to a variable or property. + */ +public class KtSimpleVariableAccessCall( + private val _partiallyAppliedSymbol: KtPartiallyAppliedVariableSymbol, + private val _simpleAccess: KtSimpleVariableAccess +) : KtVariableAccessCall() { + + override val token: ValidityToken get() = _partiallyAppliedSymbol.token + + override val partiallyAppliedSymbol: KtPartiallyAppliedVariableSymbol get() = withValidityAssertion { _partiallyAppliedSymbol } + + /** + * The type of access to this property. + */ + public val simpleAccess: KtSimpleVariableAccess get() = withValidityAssertion { _simpleAccess } +} + +public sealed class KtSimpleVariableAccess { + public object Read : KtSimpleVariableAccess() + + public class Write( + /** + * [KtExpression] that represents the new value that should be assigned to this variable. Or null if the assignment is incomplete + * and misses the new value. + */ + public val value: KtExpression? + ) : KtSimpleVariableAccess() +} + +public interface KtCompoundAccessCall { + /** + * The type of this compound access. + */ + public val compoundAccess: KtCompoundAccess +} + +/** + * A compound access of a mutable variable. For example + * ``` + * fun test() { + * var i = 0 + * i += 1 + * // partiallyAppliedSymbol: { + * // symbol: `i` + * // dispatchReceiver: null + * // extensionReceiver: null + * // } + * // accessType: OpAssign { + * // kind: PLUS + * // operand: 1 + * // operationSymbol: Int.plus() + * // } + * + * i++ + * // partiallyAppliedSymbol: { + * // symbol: `i` + * // dispatchReceiver: null + * // extensionReceiver: null + * // } + * // accessType: IncDec { + * // kind: INC + * // precedence: POSTFIX + * // operationSymbol: Int.inc() + * // } + * } + * ``` + * Note that if the variable has a `Assign` member, then it's represented as a simple `KtFunctionCall`. For example, + * ``` + * fun test(m: MutableList) { + * m += "a" // A simple `KtFunctionCall` to `MutableList.plusAssign`, not a `KtVariableAccessCall`. However, the dispatch receiver of this + * // call, `m`, is a simple read access represented as a `KtVariableAccessCall` + * } + * ``` + */ +public class KtCompoundVariableAccessCall( + private val _partiallyAppliedSymbol: KtPartiallyAppliedVariableSymbol, + private val _compoundAccess: KtCompoundAccess +) : KtVariableAccessCall(), KtCompoundAccessCall { + override val token: ValidityToken + get() = _partiallyAppliedSymbol.token + override val partiallyAppliedSymbol: KtPartiallyAppliedVariableSymbol get() = withValidityAssertion { _partiallyAppliedSymbol } + override val compoundAccess: KtCompoundAccess get() = withValidityAssertion { _compoundAccess } +} + +/** + * A compound access using the array access convention. For example, + * ``` + * fun test(m: MutableMap) { + * m["a"] += "b" + * // indexArguments: ["a"] + * // getPartiallyAppliedSymbol: { + * // symbol: MutableMap.get() + * // dispatchReceiver: `m` + * // extensionReceiver: null + * // } + * // setPartiallyAppliedSymbol: { + * // symbol: MutableMap.set() + * // dispatchReceiver: `m` + * // extensionReceiver: null + * // } + * // accessType: OpAssign { + * // kind: PLUS + * // operand: "b" + * // operationSymbol: String?.plus() + * // } + * } + * ``` + * Such a call always involve both calls to `get` and `set` functions. With the example above, a call to `String?.plus` is sandwiched + * between `get` and `set` call to compute the new value passed to `set`. + * + * Note that simple access using the array access convention is not captured by this class. For example, assuming `ThrowingMap` throws + * in case of absent key instead of returning `null`, + * ``` + * fun test(m: ThrowingMap>) { + * m["a"] += "b" + * } + * ``` + * The above call is represented as a simple `KtFunctionCall` to `MutableList.plusAssign`, with the dispatch receiver referencing the + * `m["a"]`, which is again a simple `KtFunctionCall` to `ThrowingMap.get`. + */ +public class KtCompoundArrayAccessCall( + private val _compoundAccess: KtCompoundAccess, + private val _indexArguments: List, + private val _getPartiallyAppliedSymbol: KtPartiallyAppliedFunctionSymbol, + private val _setPartiallyAppliedSymbol: KtPartiallyAppliedFunctionSymbol, + + ) : KtCall(), KtCompoundAccessCall { + + override val token: ValidityToken get() = _compoundAccess.token + + override val compoundAccess: KtCompoundAccess get() = withValidityAssertion { _compoundAccess } + + public val indexArguments: List get() = withValidityAssertion { _indexArguments } + + /** + * The `get` function that's invoked when reading values corresponding to the given [indexArguments]. + */ + public val getPartiallyAppliedSymbol: KtPartiallyAppliedFunctionSymbol get() = withValidityAssertion { _getPartiallyAppliedSymbol } + + /** + * The `set` function that's invoked when writing values corresponding to the given [indexArguments] and computed value from the + * operation. + */ + public val setPartiallyAppliedSymbol: KtPartiallyAppliedFunctionSymbol get() = withValidityAssertion { _setPartiallyAppliedSymbol } +} + +/** + * The type of access to a variable or using the array access convention. + */ +public sealed class KtCompoundAccess(private val _operationPartiallyAppliedSymbol: KtPartiallyAppliedFunctionSymbol) : + ValidityTokenOwner { + + override val token: ValidityToken + get() = _operationPartiallyAppliedSymbol.token + + /** + * The function that compute the value for this compound access. For example, if the access is `+=`, this is the resolved `plus` + * function. If the access is `++`, this is the resolved `inc` function. + */ + public val operationPartiallyAppliedSymbol: KtPartiallyAppliedFunctionSymbol get() = withValidityAssertion { _operationPartiallyAppliedSymbol } + + /** + * A compound access that read, compute, and write the computed value back. Note that calls to `Assign` is not represented by this. + */ + public class CompoundAssign( + operationPartiallyAppliedSymbol: KtPartiallyAppliedFunctionSymbol, + private val _kind: Kind, + private val _operand: KtExpression + ) : KtCompoundAccess(operationPartiallyAppliedSymbol) { + public val kind: Kind get() = withValidityAssertion { _kind } + public val operand: KtExpression get() = withValidityAssertion { _operand } + + public enum class Kind { + PLUS_ASSIGN, MINUS_ASSIGN, TIMES_ASSIGN, DIV_ASSIGN, REM_ASSIGN + } + + } + + /** + * A compound access that read, increment or decrement, and write the computed value back. + */ + public class IncOrDecOperation( + operationPartiallyAppliedSymbol: KtPartiallyAppliedFunctionSymbol, + private val _kind: Kind, + private val _precedence: Precedence, + ) : KtCompoundAccess(operationPartiallyAppliedSymbol) { + public val kind: Kind get() = withValidityAssertion { _kind } + public val precedence: Precedence get() = withValidityAssertion { _precedence } + + public enum class Kind { + INC, DEC + } + + public enum class Precedence { + PREFIX, POSTFIX + } + } +} + +/** + * A receiver value of a call. + */ +public sealed class KtReceiverValue : ValidityTokenOwner + +/** + * An explicit expression receiver. For example + * ``` + * "".length // explicit receiver `""` + * ``` + */ +public class KtExplicitReceiverValue( + private val _expression: KtExpression, + private val _isSafeNavigation: Boolean, + override val token: ValidityToken +) : KtReceiverValue() { + public val expression: KtExpression get() = withValidityAssertion { _expression } + + /** + * Whether safe navigation is used on this receiver. For example + * ``` + * fun test(s1: String?, s2: String) { + * s1?.length // explicit receiver `s1` has `isSafeNavigation = true` + * s2.length // explicit receiver `s2` has `isSafeNavigation = false` + * } + * ``` + */ + public val isSafeNavigation: Boolean get() = withValidityAssertion { _isSafeNavigation } +} + +/** + * An implicit receiver. For example + * ``` + * class A { + * val i: Int = 1 + * fun test() { + * i // implicit receiver bound to class `A` + * } + * } + * + * fun String.test() { + * length // implicit receiver bound to the `KtReceiverParameterSymbol` of type `String` declared by `test`. + * } + * ``` + */ +public class KtImplicitReceiverValue(private val _symbol: KtSymbol) : KtReceiverValue() { + override val token: ValidityToken get() = _symbol.token + public val symbol: KtSymbol get() = withValidityAssertion { _symbol } +} + +/** + * A smart-casted receiver. For example + * ``` + * fun Any.test() { + * if (this is String) { + * length // smart-casted implicit receiver bound to the `KtReceiverParameterSymbol` of type `String` declared by `test`. + * } + * } + * ``` + */ +public class KtSmartCastedReceiverValue(private val _original: KtReceiverValue, private val _smartCastType: KtType) : KtReceiverValue() { + override val token: ValidityToken + get() = _original.token + public val original: KtReceiverValue get() = withValidityAssertion { _original } + public val smartCastType: KtType get() = withValidityAssertion { _smartCastType } +} diff --git a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/calls/ktCallUtils.kt b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/calls/ktCallUtils.kt index c0d5230b8ae..0b1824a4568 100644 --- a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/calls/ktCallUtils.kt +++ b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/calls/ktCallUtils.kt @@ -18,7 +18,7 @@ public fun KtCallTarget.getSingleCandidateSymbolOrNull(): KtFunctionLikeSymbol? } public inline fun KtCall.isSuccessCallOf(predicate: (S) -> Boolean): Boolean { - if (this !is KtFunctionCall) return false + if (this !is KtSimpleFunctionCall) return false val symbol = targetFunction.getSuccessCallSymbolOrNull() ?: return false if (symbol !is S) return false return predicate(symbol) diff --git a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/components/KtCallResolver.kt b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/components/KtCallResolver.kt index 0e8db2d2a41..e936b8be42c 100644 --- a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/components/KtCallResolver.kt +++ b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/components/KtCallResolver.kt @@ -5,43 +5,27 @@ package org.jetbrains.kotlin.analysis.api.components -import org.jetbrains.kotlin.analysis.api.calls.KtCall +import org.jetbrains.kotlin.analysis.api.calls.KtCallInfo import org.jetbrains.kotlin.psi.* public abstract class KtCallResolver : KtAnalysisSessionComponent() { - public abstract fun resolveAccessorCall(call: KtSimpleNameExpression): KtCall? - public abstract fun resolveCall(call: KtCallElement): KtCall? - public abstract fun resolveCall(call: KtBinaryExpression): KtCall? - public abstract fun resolveCall(call: KtUnaryExpression): KtCall? - public abstract fun resolveCall(call: KtArrayAccessExpression): KtCall? + public abstract fun resolveCall(call: KtElement): KtCallInfo? } public interface KtCallResolverMixIn : KtAnalysisSessionMixIn { - /** - * Resolves the given simple name expression to an accessor call if that name refers to a property. - * - * This spans both Kotlin property and synthetic Java property. - */ - public fun KtSimpleNameExpression.resolveAccessorCall(): KtCall? = - analysisSession.callResolver.resolveAccessorCall(this) - public fun KtCallElement.resolveCall(): KtCall? = + public fun KtElement.resolveCall(): KtCallInfo? = analysisSession.callResolver.resolveCall(this) - public fun KtBinaryExpression.resolveCall(): KtCall? = - analysisSession.callResolver.resolveCall(this) + public fun KtCallElement.resolveCall(): KtCallInfo = + analysisSession.callResolver.resolveCall(this) ?: error("KtCallElement should always resolve to a KtCallInfo") - public fun KtUnaryExpression.resolveCall(): KtCall? = - analysisSession.callResolver.resolveCall(this) + public fun KtBinaryExpression.resolveCall(): KtCallInfo = + analysisSession.callResolver.resolveCall(this) ?: error("KtBinaryExpression should always resolve to a KtCallInfo") - public fun KtArrayAccessExpression.resolveCall(): KtCall? = - analysisSession.callResolver.resolveCall(this) + public fun KtUnaryExpression.resolveCall(): KtCallInfo = + analysisSession.callResolver.resolveCall(this) ?: error("KtUnaryExpression should always resolve to a KtCallInfo") - public fun KtElement.resolveCallIfPossible(): KtCall? = when (this) { - is KtCallElement -> resolveCall() - is KtBinaryExpression -> resolveCall() - is KtUnaryExpression -> resolveCall() - is KtArrayAccessExpression -> resolveCall() - else -> null - } + public fun KtArrayAccessExpression.resolveCall(): KtCallInfo = + analysisSession.callResolver.resolveCall(this) ?: error("KtArrayAccessExpression should always resolve to a KtCallInfo") } \ No newline at end of file