KaDefinitelyNotNullType¶
@SubclassOptInRequired(markerClass = [KaImplementationDetail::class])
abstract class KaDefinitelyNotNullType : KaType
KaDefinitelyNotNullType represents a definitely not-null type, such as T & Any for a type parameter T.
Constructors¶
KaDefinitelyNotNullType¶
constructor()
Properties¶
abbreviation¶
abstract val abbreviation: KaUsualClassType?
The abbreviated type for this expanded KaType, or null if this type has not been expanded from an abbreviated type or the abbreviated type cannot be resolved.
An abbreviated type is a type alias application that has been expanded to some other Kotlin type. For example, if we have a type alias typealias MyString = String and its application MyString, String would be the type alias expansion and MyString its abbreviated type.
The abbreviated type contains the type arguments of a specific type alias application. For example, if we have a typealias MyList<A> = List<A>, for an application MyList<String>, MyList<String> would be the abbreviated type for such a type alias application, not simply MyList.
If this KaType is an unexpanded type alias application, abbreviation is null. Not all type alias applications are currently expanded right away and the Analysis API makes no guarantees about the specific circumstances.
While abbreviation is available for all KaTypes, it can currently only be present in KaClassTypes. However, abbreviated types are a general concept and if the type system changes (e.g. with denotable union/intersection types), other kinds of types may also be expanded from a type alias. This would allow more kinds of types to carry an abbreviated type.
The abbreviation itself is always a KaUsualClassType, as the application of a type alias is always a class type. It cannot be a KaClassErrorType because abbreviation would then be null.
Resolvability
Even when this KaType is an expansion, the abbreviated type may be null if it is not resolvable from this type's use-site module. This can occur when the abbreviated type from a module M1 was expanded at some declaration D in module M2, and the use-site module uses D, but only has a dependency on M2. Then the type alias of M1 remains unresolved and abbreviation is null.
Type arguments and nested abbreviated types
The type arguments of an abbreviated type are not converted to abbreviated types automatically. That is, if a type argument is a type expansion, its abbreviation doesn't automatically replace the expanded type. For example:
MyList<MyString> may be expanded to a type List<String> with an abbreviated type MyList<String>, where String also has the abbreviated type MyString. The abbreviated type is not MyList<MyString>, although it might be rendered as such.
Transitive expansion
Types are always expanded to their final form. That is, if we have a chain of type alias expansions, the KaType only represents the final expanded type, and its abbreviation the initial type alias application. For example:
Here, outer's type would be expanded to String, but its abbreviated type would be Outer. Inner would be lost.
abbreviationOrSelf¶
The KaType's abbreviated type, or the type itself if it doesn't have an abbreviated type.
A common pattern is to prefer the abbreviated type if it exists, and otherwise take the original type, for example to find the best target for navigation.
allSupertypes¶
Returns all supertypes of the given KaType. The resulting sequence is ordered by a breadth-first traversal of the class hierarchy, without duplicates.
Parameters
- shouldApproximate: Whether to approximate
non-denotabletypes. SeedirectSupertypesfor more information.
context(session: KaSession)
val KaType.allSupertypes: Sequence<KaType>
annotations¶
abstract val annotations: KaAnnotationList
A list of annotations applied to the annotated entity.
arrayElementType¶
context(session: KaSession)
val KaType.arrayElementType: KaType?
augmentedByWarningLevelAnnotations¶
context(session: KaSession)
val KaType.augmentedByWarningLevelAnnotations: KaType
A KaType derived from the given type by enforcing warning-level nullability annotations. If the derived type doesn't differ from the original type, the original type is used.
In general, Java type enhancement allows the Kotlin compiler to infer a more specific nullability for a Java type based on its nullability annotations. Normally, only strict nullability annotations have an impact on a resolved type's nullability. These annotations are already taken into account in KaType.
However, there are also warning-level nullability annotations, such as Android's RecentlyNullable and RecentlyNonNull. These annotations have weaker constraints and don't affect a resolved type's nullability. augmentedByWarningLevelAnnotations is a KaType with weak annotations treated as strict ones.
See the list of default report levels for different nullability annotations in NULLABILITY_ANNOTATION_SETTINGS
Examples
-
For
@androidx.annotation.RecentlyNullable X!augmentedByWarningLevelAnnotationsisX?. -
For
@androidx.annotation.RecentlyNonNull X!augmentedByWarningLevelAnnotationsisX.
classId¶
The ClassId provided the type exposes any (it is the case for KaClassType).
defaultInitializer¶
context(session: KaSession)
val KaType.defaultInitializer: String?
The default initializer for the given KaType, or null if the type is neither nullable, a primitive, nor a string.
directSupertypes¶
Returns the direct supertypes of the given KaType.
For flexible types, direct supertypes of both the upper and lower bounds are returned. If that's not desirable, use directSupertypes on KaFlexibleType.upperBound or KaFlexibleType.lowerBound.
Example
Given MutableList<String>, directSupertypes returns List<String> and MutableCollection<String>
Parameters
- shouldApproximate: Whether to approximate
non-denotabletypes. For example, the supertype ofList<out String>isCollection<CAPTURED out String>. With approximation set totrue,Collection<out String>is returned instead.
context(session: KaSession)
val KaType.directSupertypes: Sequence<KaType>
The direct supertypes of the given KaType.
For flexible types, direct supertypes of both the upper and lower bounds are included. If that's not desirable, use directSupertypes on KaFlexibleType.upperBound or KaFlexibleType.lowerBound.
Denotable types are not approximated.
Example
Given MutableList<String>, directSupertypes contains List<String> and MutableCollection<String>
expandedSymbol¶
context(session: KaSession)
val KaType.expandedSymbol: KaClassSymbol?
The class symbol backing the given KaType, if available.
fullyExpandedType¶
context(session: KaSession)
val KaType.fullyExpandedType: KaType
The type that corresponds to the given KaType with fully expanded type aliases.
Type aliases are usually expanded immediately by the compiler, so most KaTypes should already present in their expanded forms. Nonetheless, it is possible to obtain unexpanded types from the Analysis API, and fullyExpandedType may be used to expand type aliases in such types.
Example
interface Base
typealias FirstAlias = @Anno1 Base
typealias SecondAlias = @Anno2 FirstAlias
fun foo(): @Anno3 SecondAlias = TODO()
The return type of foo() will be @Anno3 @Anno2 @Anno1 Base instead of @Anno3 SecondAlias
See also
functionTypeFamily¶
context(session: KaSession)
val KaType.functionTypeFamily: KaFunctionTypeFamily?
The function type family of the given KaType, or null if the type is not a function type.
For example, (Int) -> String belongs to the Function family, while suspend () -> Unit belongs to the SuspendFunction family.
See also
hasFlexibleNullability¶
context(session: KaSession)
val KaType.hasFlexibleNullability: Boolean
Whether the KaType is a org.jetbrains.kotlin.analysis.api.types.KaFlexibleType / org.jetbrains.kotlin.analysis.api.types.KaDynamicType with flexible nullability or org.jetbrains.kotlin.analysis.api.types.KaErrorType with unknown nullability. Both safe and ordinary calls are valid on such types.
Note that a flexible / dynamic type has a flexible nullability when the lower bound is non-nullable and the upper bound is nullable. E.g. T! has T as the lower bound and T? as the upper bound, hence it has a flexible nullability.
isArrayOrPrimitiveArray¶
context(session: KaSession)
val KaType.isArrayOrPrimitiveArray: Boolean
Whether the KaType is an array or a primitive array type.
isDenotable¶
context(session: KaSession)
val KaType.isDenotable: Boolean
Whether the KaType is denotable. A denotable type can be expressed in Kotlin code, as opposed to being only constructible via compiler type operations (such as type inference).
isFunctionalInterface¶
context(session: KaSession)
val KaType.isFunctionalInterface: Boolean
Whether the KaType is a functional interface type, such as Runnable. Such types are also known as SAM types.
isFunctionType¶
context(session: KaSession)
val KaType.isFunctionType: Boolean
Whether the KaType is a kotlin.Function type.
isKFunctionType¶
context(session: KaSession)
val KaType.isKFunctionType: Boolean
Whether the KaType is a kotlin.reflect.KFunction type.
isKSuspendFunctionType¶
context(session: KaSession)
val KaType.isKSuspendFunctionType: Boolean
Whether the KaType is a KSuspendFunction type.
isMarkedNullable¶
context(session: KaSession)
val KaType.isMarkedNullable: Boolean
Whether the KaType is explicitly marked as nullable, i.e., is represented as T?.
Note that this property just reflects the presence of nullability in the type signature, and sometimes isMarkedNullable being false doesn't imply that the given type cannot hold null or be assigned with it.
For example, isMarkedNullable doesn't expand type aliases to check the nullability of their underlying type:
The type of x is NonMarkedNullableAlias, which is not marked as nullable. However, it still represents a nullable type and can hold null and can be assigned with that.
To explicitly check whether a type can potentially hold null, use isNullable.
isNestedArray¶
context(session: KaSession)
val KaType.isNestedArray: Boolean
Whether the KaType is an array or a primitive array type, and its element is also an array type.
isNullable¶
context(session: KaSession)
val KaType.isNullable: Boolean
Whether a public value of the KaType can potentially be null.
If a type can be null, it means that this type is not a subtype of Any. However, it does not mean one can assign null to a variable of this type. It may be unknown whether this type can accept null.
Example
A public value of type T : Any? can potentially be null. But one cannot assign null to such a variable because the instantiated type may not be nullable.
isPrimitiveBacked¶
context(session: KaSession)
val KaType.isPrimitiveBacked: Boolean
Whether the given KaType is backed by a single JVM primitive type.
isSuspendFunctionType¶
context(session: KaSession)
val KaType.isSuspendFunctionType: Boolean
Whether the KaType is a suspend function type.
original¶
scope¶
context(session: KaSession)
val KaType.scope: KaTypeScope?
A KaTypeScope for the given KaType, or null if the type is erroneous. The scope includes all members which are callable on a given type. It also includes synthetic Java properties.
symbol¶
val KaType.symbol: KaClassLikeSymbol?
A KaClassLikeSymbol for this KaType if the type represents a uniquely resolvable class/object/type alias.
syntheticJavaPropertiesScope¶
context(session: KaSession)
val KaType.syntheticJavaPropertiesScope: KaTypeScope?
A KaTypeScope containing the synthetic Java properties created for a given KaType.
token¶
abstract val token: KaLifetimeToken
The KaLifetimeToken which determines the lifetime of the lifetime owner.
Functions¶
approximateToDenotableSubtype¶
context(session: KaSession)
fun KaType.approximateToDenotableSubtype(): KaType?
approximateToDenotableSubtypeOrSelf¶
context(session: KaSession)
fun KaType.approximateToDenotableSubtypeOrSelf(): KaType
approximateToDenotableSupertype¶
context(session: KaSession)
fun KaType.approximateToDenotableSupertype(allowLocalDenotableTypes: Boolean): KaType?
Approximates KaType to a denotable supertype.
The function returns null if the type is already denotable and does not need approximation. Otherwise, for a type T, returns a denotable type S such that T <: S, with all type arguments of S also being denotable.
Parameters
- allowLocalDenotableTypes: Whether locally declared types should be approximated to local supertypes instead of non-local ones. Local type approximation is sensible when the resulting
KaTypeis analyzed in the same local context.
context(session: KaSession)
fun KaType.approximateToDenotableSupertype(position: KtElement): KaType?
Approximates KaType to a denotable supertype based on the given position.
This position is used when approximating local types. If the given type is local, then the function returns the first supertype, which is visible from the given position. Note that position is required to be within KaAnalysisScopeProvider.analysisScope, otherwise, an exception is thrown.
The function returns null if the type is already denotable and does not need approximation. Otherwise, for a type T, returns a denotable type S such that T <: S, with all type arguments of S also being denotable.
Example:
In the example above we are trying to approximate the type of object: A() {} expression, which is a local type <anonymous>: A. When this type is approximated using <position_2> the function returns A, as this type is visible from this position. However, when approximating from <position_1>, the function returns Any, as A is not visible from this position, so the only option left is Any.
approximateToDenotableSupertypeOrSelf¶
context(session: KaSession)
fun KaType.approximateToDenotableSupertypeOrSelf(allowLocalDenotableTypes: Boolean): KaType
context(session: KaSession)
fun KaType.approximateToDenotableSupertypeOrSelf(position: KtElement): KaType
asPsiType¶
context(session: KaSession)
fun KaType.asPsiType(
useSitePosition: PsiElement,
allowErrorTypes: Boolean,
mode: KaTypeMappingMode = KaTypeMappingMode.DEFAULT,
isAnnotationMethod: Boolean = false,
suppressWildcards: Boolean? = null,
preserveAnnotations: Boolean = true,
allowNonJvmPlatforms: Boolean = false
): PsiType?
Converts the given KaType to a PsiType in the context of the useSitePosition.
assertIsValidAndAccessible¶
inline fun KaLifetimeOwner.assertIsValidAndAccessible()
createPointer¶
abstract override fun createPointer(): KaTypePointer<KaDefinitelyNotNullType>
Creates a type pointer.
Unlike KaType, a KaTypePointer may be safely stored and passed around outside the (analyze)org.jetbrains.kotlin.analysis.api.session.analyze block. Use the KaSession.restore function to get the type instance back. Note that depending on the use-site session (analysisScope)KaSession.analysisScope, a type might not be restored.
hasCommonSubtypeWith¶
context(session: KaSession)
fun KaType.hasCommonSubtypeWith(that: KaType): Boolean
isSubtypeOf¶
context(session: KaSession)
fun KaType.isSubtypeOf(supertype: KaType): Boolean
context(session: KaSession)
fun KaType.isSubtypeOf(supertype: KaType, errorTypePolicy: KaSubtypingErrorTypePolicy): Boolean
Returns whether this KaType is a subtype of supertype. The relation is non-strict, i.e. any type t is a subtype of itself.
The errorTypePolicy determines the treatment of error types in the subtyping check.
context(session: KaSession)
fun KaType.isSubtypeOf(classId: ClassId): Boolean
Returns whether this KaType is a subtype of a class called classId.
This function provides a convenient way to check if a class extends a certain base class or interface while disregarding type arguments. For example, one may check if this KaType is a subtype of StandardClassIds.Iterable.
See the overload taking a KaSubtypingErrorTypePolicy for the treatment of error types.
context(session: KaSession)
fun KaType.isSubtypeOf(classId: ClassId, errorTypePolicy: KaSubtypingErrorTypePolicy): Boolean
Returns whether this KaType is a subtype of a class called classId.
This function provides a convenient way to check if a class extends a certain base class or interface while disregarding type arguments. For example, one may check if this KaType is a subtype of StandardClassIds.Iterable.
The errorTypePolicy is applied as such: If this KaType is an error type, the LENIENT policy leads to a trivially true result. Errors in type arguments are not considered, as the subclass check is concerned with the applied class type and not its type arguments.
This function for ClassIds is a convenient dual to other isSubtypeOf functions. As such, its result is the same as a call to isSubtypeOf with the following right-hand KaType: a.b.Class<*, *, ...>? given a class ID a.b.Class with all type arguments instantiated to a star projection.
This has the following interesting implications:
-
If the
classIdpoints to or actualizes to a type alias, subclassing is checked for the expanded type, as otherisSubtypeOfimplementations also take expansion into account. If the type alias doesn't expand to aKaClassType,isSubtypeOfis triviallyfalse. -
If the
classIdcannot be resolved, it effectively means that we would have an "unresolved symbol" errorKaTypeon the right-hand side ofisSubtypeOf. Hence, with aLENIENTerror type policy,isSubtypeOfistruefor all unresolved class IDs.
context(session: KaSession)
fun KaType.isSubtypeOf(symbol: KaClassLikeSymbol): Boolean
Returns whether this KaType is a subtype of a class represented by symbol.
This function provides a convenient way to check if a class extends a certain base class or interface while disregarding type arguments.
See the overload taking a KaSubtypingErrorTypePolicy for the treatment of error types.
context(session: KaSession)
fun KaType.isSubtypeOf(symbol: KaClassLikeSymbol, errorTypePolicy: KaSubtypingErrorTypePolicy): Boolean
Returns whether this KaType is a subtype of a class represented by symbol.
This function provides a convenient way to check if a class extends a certain base class or interface while disregarding type arguments.
The errorTypePolicy is applied as such: If this KaType is an error type, the LENIENT policy leads to a trivially true result. Errors in type arguments are not considered, as the subclass check is concerned with the applied class type and not its type arguments.
This function for KaClassLikeSymbols is a convenient dual to other isSubtypeOf functions. As such, its result is the same as a call to isSubtypeOf with the following right-hand KaType: a.b.Class<*, *, ...>? given a class called a.b.Class with all type arguments instantiated to a star projection.
This has the following interesting implication: If the symbol points to or actualizes to a type alias, subclassing is checked for the expanded type, as other isSubtypeOf implementations also take expansion into account. If the type alias doesn't expand to a KaClassType, isSubtypeOf is trivially false.
isValid¶
fun KaLifetimeOwner.isValid(): Boolean
Whether the lifetime owner is still valid, i.e. we are still in the scope of the lifetime owner's regular lifetime.
lowerBoundIfFlexible¶
context(session: KaSession)
fun KaType.lowerBoundIfFlexible(): KaType
Returns the KaFlexibleType's lower bound, or the type itself if it is not flexible.
mapToJvmTypeDescriptor¶
context(session: KaSession)
fun KaType.mapToJvmTypeDescriptor(): String
Convert the given KaType to a JVM type descriptor with the KaTypeMappingMode.DEFAULT. To learn more about JVM descriptors, check out the JVM specification.
render¶
Renders the given KaType into a string using the default rendering strategy (KaTypeRendererForSource.WITH_QUALIFIED_NAMES).
context(session: KaSession)
fun KaType.render(renderer: KaTypeRenderer, position: Variance): String
semanticallyEquals¶
context(session: KaSession)
fun KaType.semanticallyEquals(other: KaType): Boolean
Returns whether this KaType is semantically equal to other.
Semantic equality stands in contrast to the structural equality implemented by KaType.equals. See KaType for a detailed discussion about structural vs. semantic type equality.
context(session: KaSession)
fun KaType.semanticallyEquals(other: KaType, errorTypePolicy: KaSubtypingErrorTypePolicy): Boolean
Returns whether this KaType is semantically equal to other.
Semantic equality stands in contrast to the structural equality implemented by KaType.equals. See KaType for a detailed discussion about structural vs. semantic type equality.
The errorTypePolicy determines the treatment of error types in the equality check.
upperBoundIfFlexible¶
context(session: KaSession)
fun KaType.upperBoundIfFlexible(): KaType
Returns the KaFlexibleType's upper bound, or the type itself if it is not flexible.
withNullability¶
context(session: KaSession)
fun KaType.withNullability(isMarkedNullable: Boolean): KaType
Creates a new KaType based on the given type with the updated nullability specified by isMarkedNullable.
withValidityAssertion¶
inline fun <R> KaLifetimeOwner.withValidityAssertion(action: () -> R): R
Executes action only if the KaLifetimeOwner is still valid and accessible. Otherwise, throws a validity exception based on the concrete violation.