# KSP Processor Configuration

Generate JSON schemas at compile time with zero runtime overhead using the `kt-schema` KSP processor.

## Setup

Configure the KSP processor with the Google KSP Gradle plugin.

### Google KSP gradle plugin

Add the [Google KSP plugin](https://kotlinlang.org/docs/ksp-quickstart.html) (2.3.1 or newer) and processor
dependency to your project.

#### Multiplatform projects

```kotlin
plugins {
    kotlin("multiplatform")
    id("com.google.devtools.ksp") version "<ksp-version>"
}

dependencies {
    add("kspCommonMainMetadata", "me.kpavlov.kt.schema:kt-schema-ksp:<version>")
    implementation("me.kpavlov.kt.schema:kt-schema-annotations:<version>")
}

kotlin {
    sourceSets.commonMain.kotlin.srcDir("build/generated/ksp/metadata/commonMain/kotlin")
}

// Ensure KSP runs before compilation
tasks.withType<org.jetbrains.kotlin.gradle.dsl.KotlinCompile<*>>().all {
    if (name != "kspCommonMainKotlinMetadata") dependsOn("kspCommonMainKotlinMetadata")
}

ksp {
    arg("me.kpavlov.kt.schema.rootPackage", "com.example")
}
```

Check out an [example project](https://github.com/kpavlov/kt-schema/tree/main/examples/gradle-google-ksp).

#### JVM-only projects

```kotlin
plugins {
    kotlin("jvm")
    id("com.google.devtools.ksp") version "<ksp-version>"
}

dependencies {
    ksp("me.kpavlov.kt.schema:kt-schema-ksp:<version>")
    implementation("me.kpavlov.kt.schema:kt-schema-annotations:<version>")
}

sourceSets.main.kotlin.srcDir("build/generated/ksp/main/kotlin")
```

## Configuration options

Options can be set globally in your build configuration or overridden per-class via `@Schema`.

### Options reference

| Option             | Type      | Default | Description                                                                        |
|:-------------------|:----------|:--------|:-----------------------------------------------------------------------------------|
| `enabled`          | `Boolean` | `true`  | Enable or disable schema generation.                                               |
| `rootPackage`      | `String`  | `null`  | Limit processing to this package and its subpackages. Improves build performance.  |
| `include`          | `String`  | `null`  | Comma- or semicolon-separated glob patterns. Only matching symbols are processed.  |
| `exclude`          | `String`  | `null`  | Comma- or semicolon-separated glob patterns. Matching symbols are always skipped.  |
| `withSchemaObject` | `Boolean` | `false` | Generate `jsonSchema: JsonObject` property. Requires `kotlinx-serialization-json`. |
| `visibility`       | `String`  | `""`    | Visibility modifier for generated extensions (`public`, `internal`, etc.).         |
| `config`           | `String`  | `null`  | Schema flavour: `strict`, `lenient`, `openapi` or a `JsonSchemaConfig` class name. Unset: classes use `strict`, functions use the function-calling default. See [Schema configuration](https://kpavlov.github.io/kt-schema/configuration/index.md#schema-configuration). |

### Filtering by class/function name

Use `me.kpavlov.kt.schema.include` and `me.kpavlov.kt.schema.exclude` to control exactly which annotated classes 
and functions get schemas generated — without touching the annotations themselves. 
Both options accept a comma- or semicolon-separated list of glob patterns matched against the fully qualified name.

**Glob syntax:**

| Pattern | Matches                                                             |
|:--------|:--------------------------------------------------------------------|
| `*`     | Any sequence of characters within a single package segment (no `.`) |
| `**`    | Any sequence of characters across package segments (including `.`)  |
| `?`     | Any single character (no `.`)                                       |

**Rules:**
- If `include` is set, only symbols matching at least one pattern are processed.
  Symbols without a qualified name (e.g. local or anonymous declarations) are excluded when any include pattern is present.
- `exclude` is applied after `include` — a symbol matching any exclude pattern is always skipped.
- Both options apply to classes and functions, and work alongside `rootPackage`; the root package filter runs first.

#### Google KSP plugin

```kotlin
ksp {
    arg("me.kpavlov.kt.schema.include", "com.example.api.**, com.example.dto.**")
    arg("me.kpavlov.kt.schema.exclude", "**.internal.**, **.*Internal")
}
```

> [!TIP]
> For large projects, combine `rootPackage` with `include` for maximum build performance:
> `rootPackage` narrows the KSP symbol scan, then `include` filters the remaining candidates.

### Option priority

1. **Annotation Parameter** (highest) — `@Schema(withSchemaObject = true)`
2. **KSP Argument** — Global processor options passed through the Gradle `ksp { arg(...) }` block
3. **Default Value** (lowest)

> [!TIP]
> Use an empty string `visibility.set("")` (default) for Multiplatform projects targeting Native
> to avoid "redundant visibility modifier" warnings.

## Generated Code

For each `@Schema`-annotated class, the processor generates extension properties:

```kotlin
@Schema(withSchemaObject = true)
data class User(val name: String)
```

Access generated extensions
```kotlin
val jsonString: String = User::class.jsonSchemaString
val jsonObject: JsonObject = User::class.jsonSchema
```

For each `@Schema`-annotated function, the processor generates additional top-level or extension function:


```kotlin
@Schema(withSchemaObject = true)
internal fun calculateArea(shape: Shape): Double = TODO("only signature matters")
```

Access generated functions:
```kotlin
val functionCallSchemaString: String = calculateAreaJsonSchemaString() // <function name> + "jsonSchemaString()" 
val functionCallSchema: JsonObject = calculateAreaJsonSchema() // <function name> + "jsonSchema()" 
```

A parameter with a Kotlin default value (e.g. `unit: String = "celsius"`) is optional: with the `lenient`, `openapi`
or a custom non-strict `config` it is left out of `required`. The default `strict` config requires every parameter,
as OpenAI strict mode demands. KSP reports only that a default exists, not its value, so no `default` is emitted.

Jakarta Bean Validation annotations on properties and function parameters (`@Min(1) quantity: Int`) become JSON Schema
keywords. See the [Validation Constraints guide](https://kpavlov.github.io/kt-schema/constraints/index.md).

## See Also

- [Serialization-Based Generator](https://kpavlov.github.io/kt-schema/serializable/index.md) — Runtime generation for any `@Serializable` class (no KSP required)
- [Annotation Reference](https://kpavlov.github.io/kt-schema/generated/index.md#using-schema-and-description-annotations) — `@Schema` and `@Description` usage
- [Runtime Schema Generation](https://kpavlov.github.io/kt-schema/reflection/index.md) — Alternative using Reflection (JVM only)
- [Function Calling Schemas](https://kpavlov.github.io/kt-schema/function-calling/index.md) — Generate LLM function schemas
- [JSON Schema DSL](https://github.com/kpavlov/kt-schema/blob/main/kt-schema-json/README.md) — Manual schema construction