How KSP models Kotlin code
Type and resolution
The resolution takes most of the cost of the underlying API implementation. So type references are designed to be resolved by processors explicitly (with a few exceptions). When a type (such as
KSAnnotation.annotationType) is referenced, it is always a
KSTypeReference, which is a
KSReferenceElement with annotations and modifiers.
KSTypeReference can be resolved to a
KSType, which refers to a type in Kotlin's type system.
KSTypeReference has a
KSReferenceElement, which models Kotlin's program structure: namely, how the reference is written. It corresponds to the
type element in Kotlin's grammar.
KSReferenceElement can be a
KSCallableReference, which contains a lot of useful information without the need for resolution. For example,
If the original declaration referenced by a
KSTypeReference is needed, it can usually be found by resolving to
KSType and accessing through
KSType.declaration. Moving from where a type is mentioned to where its class is defined looks like this:
Type resolution is costly and therefore has explicit form. Some of the information obtained from resolution is already available in
KSReferenceElement. For example,
KSClassifierReference.referencedName can filter out a lot of elements that are not interesting. You should resolve type only if you need specific information from
KSTypeReference pointing to a function type has most of its information in its element. Although it can be resolved to the family of
Function1, and so on, these resolutions don't bring any more information than
KSCallableReference. One use case for resolving function type references is dealing with the identity of the function's prototype.