The API definition can be found here.
The diagram below is an overview of how Kotlin is modeled in KSP:
In KSP, references to types are designed to be resolved by processors
explicitly (with a few exceptions) because most of the cost of the
underlying API implementation is in resolution. When a type is referenced,
such as KSFunctionDeclaration.returnType
or KSAnnotation.annotationType
,
it is always a KSTypeReference
, which is a KSReferenceElement
with
annotations and modifiers.
interface KSFunctionDeclaration : ... {
val returnType: KSTypeReference?
...
}
interface KSTypeReference : KSAnnotated, KSModifierListOwner {
val type: KSReferenceElement
}
A KSTypeReference
can be resolved to a KSType
, which refers to a type in
Kotlin's type system.
A 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.
A KSReferenceElement
can be a KSClassifierReference
or
KSCallableReference
, which contains a lot of useful information without
the need for resolution. For example, KSClassifierReference
has
referencedName
, while KSCallableReference
has receiverType
,
functionArguments
, and returnType
.
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:
KSTypeReference -> .resolve() -> KSType -> .declaration -> KSDeclaration
Type resolution is costly and is therefore made explicit. 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 KSDeclaration
or KSType
.
Note that a KSTypeReference
pointing to a function type has most of its
information in its element. Although it can be resolved to the family of
Function0
, 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.