org.jetbrains.kotlin.analysis.api.calls.KtCall.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of kotlin-annotation-processing Show documentation
Show all versions of kotlin-annotation-processing Show documentation
Annotation Processor for Kotlin
/*
* 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.analysis.api.calls
import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeOwner
import org.jetbrains.kotlin.analysis.api.diagnostics.KtDiagnostic
import org.jetbrains.kotlin.analysis.api.symbols.*
import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeToken
import org.jetbrains.kotlin.analysis.api.types.KtType
import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion
import org.jetbrains.kotlin.psi.KtCallExpression
import org.jetbrains.kotlin.analysis.api.signatures.KtCallableSignature
import org.jetbrains.kotlin.analysis.api.signatures.KtFunctionLikeSignature
import org.jetbrains.kotlin.analysis.api.signatures.KtVariableLikeSignature
import org.jetbrains.kotlin.psi.KtExpression
/**
* Call information at call site.
*/
public sealed class KtCallInfo : KtLifetimeOwner
/**
* Successfully resolved call.
*/
public class KtSuccessCallInfo(private val _call: KtCall) : KtCallInfo() {
override val token: KtLifetimeToken
get() = _call.token
public val call: KtCall get() = withValidityAssertion { _call }
}
/**
* Call that contains errors.
*/
public class KtErrorCallInfo(
private val _candidateCalls: List,
private val _diagnostic: KtDiagnostic,
override val token: KtLifetimeToken
) : KtCallInfo() {
public val candidateCalls: List get() = withValidityAssertion { _candidateCalls }
public val diagnostic: KtDiagnostic get() = withValidityAssertion { _diagnostic }
}
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 candidate considered for a call. I.e., one of the overload candidates in scope at the call site.
*/
public sealed class KtCallCandidateInfo(
private val _candidate: KtCall,
private val _isInBestCandidates: Boolean,
) : KtLifetimeOwner {
override val token: KtLifetimeToken
get() = _candidate.token
public val candidate: KtCall get() = withValidityAssertion { _candidate }
/**
* Returns true if the [candidate] is in the final set of candidates that the call is actually resolved to. There can be multiple
* candidates if the call is ambiguous.
*/
public val isInBestCandidates: Boolean get() = withValidityAssertion { _isInBestCandidates }
}
/**
* A candidate that is applicable for a call. A candidate is applicable if the call's arguments are complete and are assignable to the
* candidate's parameters, AND the call's type arguments are complete and fit all the constraints of the candidate's type parameters.
*/
public class KtApplicableCallCandidateInfo(
candidate: KtCall,
isInBestCandidates: Boolean,
) : KtCallCandidateInfo(candidate, isInBestCandidates)
/**
* A candidate that is NOT applicable for a call. A candidate is inapplicable if a call argument is missing or is not assignable to the
* candidate's parameters, OR a call type argument is missing or does not fit the constraints of the candidate's type parameters.
*/
public class KtInapplicableCallCandidateInfo(
candidate: KtCall,
isInBestCandidates: Boolean,
private val _diagnostic: KtDiagnostic,
) : KtCallCandidateInfo(candidate, isInBestCandidates) {
/**
* The reason the [candidate] was not applicable for the call (e.g., argument type mismatch, or no value for parameter).
*/
public val diagnostic: KtDiagnostic get() = withValidityAssertion { _diagnostic }
}
/**
* 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 : KtLifetimeOwner
/**
* A special call for type qualifiers with generic parameters, which, from the PSI perspective, are [KtCallExpression]-s.
*
* Examples:
*
* ```
* fun test() {
* Collection<*>::isEmpty
*
* kotlin.List::size
* }
* ```
*
* Both `Collection<*>` and `List` are [KtCallExpression]-s, so we need to be able to successfully resolve them to something
* sensible - that's why we need [KtGenericTypeQualifier].
*/
public class KtGenericTypeQualifier(
override val token: KtLifetimeToken,
private val _qualifier: KtExpression,
) : KtCall() {
/**
* The full qualifier - either a [KtCallExpression] or a [org.jetbrains.kotlin.psi.KtDotQualifiedExpression].
*/
public val qualifier: KtExpression get() = withValidityAssertion { _qualifier }
}
/**
* A special call for type qualifiers with generic parameters which represent [KtCallExpression] in incomplete code.
*
* Example:
*
* ```
* fun test() {
* List
* }
* ```
*/
public class KtQualifierCall(
override val token: KtLifetimeToken,
private val _qualifier: KtCallExpression,
) : KtCall() {
public val qualifier: KtCallExpression get() = withValidityAssertion { _qualifier }
}
/**
* 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?,
) : KtLifetimeOwner {
override val token: KtLifetimeToken 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: KtLifetimeToken,
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
/**
* This map returns inferred type arguments. If the type placeholders was used, actual inferred type will be used as a value.
* Keys for this map is from the set [partiallyAppliedSymbol].signature.typeParameters.
* In case of resolution or inference error could return empty map.
*/
public abstract val typeArgumentsMapping: Map
}
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 _typeArgumentsMapping: Map,
private val _isImplicitInvoke: Boolean,
) : KtFunctionCall(argumentMapping) {
override val token: KtLifetimeToken get() = _partiallyAppliedSymbol.token
/**
* The function and receivers for this call.
*/
override val partiallyAppliedSymbol: KtPartiallyAppliedFunctionSymbol get() = withValidityAssertion { _partiallyAppliedSymbol }
override val typeArgumentsMapping: Map get() = withValidityAssertion { _typeArgumentsMapping }
/**
* 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: KtLifetimeToken get() = _partiallyAppliedSymbol.token
/**
* The function and receivers for this call.
*/
override val partiallyAppliedSymbol: KtPartiallyAppliedFunctionSymbol get() = withValidityAssertion { _partiallyAppliedSymbol }
override val typeArgumentsMapping: Map get() = withValidityAssertion { emptyMap() }
}
/**
* 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: KtLifetimeToken get() = _partiallyAppliedSymbol.token
/**
* The function and receivers for this call.
*/
override val partiallyAppliedSymbol: KtPartiallyAppliedFunctionSymbol get() = withValidityAssertion { _partiallyAppliedSymbol }
override val typeArgumentsMapping: Map
get() = withValidityAssertion {
check(partiallyAppliedSymbol.symbol.typeParameters.isEmpty()) {
"Type arguments for delegation constructor to java constructor with type parameters not supported. " +
"Symbol: ${partiallyAppliedSymbol.symbol}"
}
emptyMap()
}
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 _typeArgumentsMapping: Map,
private val _simpleAccess: KtSimpleVariableAccess
) : KtVariableAccessCall() {
override val token: KtLifetimeToken get() = _partiallyAppliedSymbol.token
override val partiallyAppliedSymbol: KtPartiallyAppliedVariableSymbol get() = withValidityAssertion { _partiallyAppliedSymbol }
override val typeArgumentsMapping: Map get() = withValidityAssertion { _typeArgumentsMapping }
/**
* 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 _typeArgumentsMapping: Map,
private val _compoundAccess: KtCompoundAccess
) : KtVariableAccessCall(), KtCompoundAccessCall {
override val token: KtLifetimeToken
get() = _partiallyAppliedSymbol.token
override val partiallyAppliedSymbol: KtPartiallyAppliedVariableSymbol get() = withValidityAssertion { _partiallyAppliedSymbol }
override val typeArgumentsMapping: Map get() = withValidityAssertion { _typeArgumentsMapping }
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: KtLifetimeToken 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) :
KtLifetimeOwner {
override val token: KtLifetimeToken
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 : KtLifetimeOwner {
/**
* Returns inferred [KtType] of the receiver.
*
* In case of smart cast on the receiver returns smart cast type.
*
* For builder inference in FIR implementation it currently works incorrectly, see KT-50916.
*/
public abstract val type: KtType
}
/**
* An explicit expression receiver. For example
* ```
* "".length // explicit receiver `""`
* ```
*/
public class KtExplicitReceiverValue(
private val _expression: KtExpression,
private val _type: KtType,
private val _isSafeNavigation: Boolean,
override val token: KtLifetimeToken,
) : 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 }
override val type: KtType get() = withValidityAssertion { _type }
}
/**
* 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,
private val _type: KtType
) : KtReceiverValue() {
override val token: KtLifetimeToken get() = _symbol.token
public val symbol: KtSymbol get() = withValidityAssertion { _symbol }
override val type: KtType get() = withValidityAssertion { _type }
}
/**
* 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: KtLifetimeToken
get() = _original.token
public val original: KtReceiverValue get() = withValidityAssertion { _original }
public override val type: KtType get() = withValidityAssertion { _smartCastType }
}