blob: 87fdfe7c594b4a69025d34d4ed8ca56fb7e03392 [file] [view]
# KSP Hello World Example
This project is a minimal, self-contained KSP project.
It configures KSP via its Gradle plugin as one would normally do,
in the hopes of providing an example that a new user can read and learn from.
The project has three subprojects:
- `annotations`: This subproject defines the `HelloWorld` annotation. By keeping annotations in a separate
module, we avoid leaking the processor's implementation or the KSP API to the app's runtime.
- `processor`: This subproject defines a minimal processor that selects functions annotated with
`HelloWorld` and generates a function that prints a message.
- `app`: This subproject defines a single `main` that calls the generated function.
The `main` function is annotated with `HelloWorld` to trigger the processor.
## Key Concepts
While this is a minimal example, it demonstrates several core KSP mechanisms that are essential to
understand:
### Selecting Functions to Process
The processor's entry point is the `process` method, which receives a `Resolver`.
The `Resolver` type is the primary tool for querying the KSP's view of the source code.
In `HelloWorldProcessor.kt`, we use:
- `resolver.getSymbolsWithAnnotation(...)`: To find all symbols annotated with our fully qualified
annotation name (`com.example.annotations.HelloWorld`).
- `.filterIsInstance<KSFunctionDeclaration>()`: Since our processor is designed to work on
functions, we filter the results to ensure we are only dealing with function declarations.
Once filtered, we use the **Visitor Pattern** (`it.accept(HelloWorldVisitor(), Unit)`) to perform the actual code generation. This is the recommended way to traverse the KSP AST (Abstract Syntax Tree).
Note the file in `processor/src/main/resources/META-INF/services/`.
It contains the fully qualified name of the `SymbolProcessorProvider` implementation.
Without this, KSP will not know your processor exists.
### Generating Code
Using the selected function in the `HelloWorldVisitor`, we can create a new file and write directly
to it like any other output stream.
### Dependency Management
In `app/build.gradle.kts`, notice how the dependencies are split:
- `implementation(project(":annotations"))`: Gives the app access to the `HelloWorld` annotation
definition.
- `ksp(project(":processor"))`: Tells the KSP plugin to run the processor during compilation.
The separation ensures the processor's code only exists during the build phase and isn't bundled
into your final application.
Note in `processor/build.gradle.kts` that the processor also depends on the annotations project with
`implementation(project(":annotations"))`.
### Inspecting Generated Code
You can find the source code generated by this processor in the build directory of the app:
`app/build/generated/ksp/main/kotlin/GeneratedHelloWorld.kt`
## Further Reading
Visit the [KSP documentation](https://kotlinlang.org/docs/ksp-overview.html) for more information.