---
title: "KSP (Kotlin Symbol Processing): Guia Completo | Kotlin Brasil"
url: "https://kotlin.dev.br/blog/kotlin-ksp-guia-completo/"
markdown_url: "https://kotlin.dev.br/blog/kotlin-ksp-guia-completo.MD"
description: "Aprenda KSP em Kotlin: substitua o kapt, ganhe performance no build e crie processadores. Guia prático com exemplos e migração."
date: "2026-03-27"
author: "Karina Melo"
---

# KSP (Kotlin Symbol Processing): Guia Completo | Kotlin Brasil

Aprenda KSP em Kotlin: substitua o kapt, ganhe performance no build e crie processadores. Guia prático com exemplos e migração.


Se o build do seu projeto Kotlin demora mais do que deveria, há uma boa chance de que o **kapt** (Kotlin Annotation Processing Tool) seja o vilão. A boa notícia é que o **KSP — Kotlin Symbol Processing** — chegou para substituí-lo com ganhos reais de performance e uma API muito mais amigável. Neste guia, vamos explorar tudo sobre KSP: o que é, como configurar, como migrar do kapt e até como criar seu próprio processador.

## O que é KSP?

KSP é uma API desenvolvida pelo Google para processar símbolos Kotlin em tempo de compilação. Diferente do kapt, que precisa gerar stubs Java para funcionar, o KSP trabalha diretamente com a árvore de símbolos do compilador Kotlin. Isso significa:

- **Builds até 2x mais rápidos** — sem a etapa de geração de stubs Java
- **API nativa em Kotlin** — trabalha com tipos Kotlin diretamente (nullable, extension functions, etc.)
- **Multiplatform ready** — funciona com Kotlin Multiplatform, diferente do kapt que é JVM-only
- **Incrementalidade** — KSP suporta processamento incremental out-of-the-box

## KSP vs kapt: Comparação de Performance

A diferença de performance é significativa. Em benchmarks do próprio Google com projetos reais:

| Métrica | kapt | KSP | Melhoria |
|---|---|---|---|
| Build limpo | 120s | 65s | ~45% mais rápido |
| Build incremental | 40s | 18s | ~55% mais rápido |
| Uso de memória | Alto | Moderado | ~30% menos |

O motivo principal é simples: kapt precisa rodar o compilador Java (javac) sobre stubs gerados, enquanto KSP pula essa etapa completamente. Se você usa [Gradle no seu projeto Kotlin](/tutoriais/kotlin-gradle-tutorial/), a migração para KSP é uma das otimizações com melhor custo-benefício.

## Configurando KSP no Projeto

### Passo 1: Adicionar o plugin KSP

No seu `build.gradle.kts` do projeto raiz:

```kotlin
plugins {
    id("com.google.devtools.ksp") version "2.1.10-1.0.29" apply false
}
```

### Passo 2: Aplicar no módulo

No `build.gradle.kts` do módulo:

```kotlin
plugins {
    id("org.jetbrains.kotlin.jvm")
    id("com.google.devtools.ksp")
}

dependencies {
    // Exemplo com Room
    implementation("androidx.room:room-runtime:2.7.0")
    ksp("androidx.room:room-compiler:2.7.0")

    // Exemplo com Moshi
    implementation("com.squareup.moshi:moshi:1.15.2")
    ksp("com.squareup.moshi:moshi-kotlin-codegen:1.15.2")
}
```

Note que onde antes usávamos `kapt(...)`, agora usamos `ksp(...)`. A mudança na configuração é mínima.

### Passo 3: Configurar argumentos do KSP (opcional)

```kotlin
ksp {
    arg("room.schemaLocation", "$projectDir/schemas")
    arg("room.incremental", "true")
    arg("room.generateKotlin", "true")
}
```

## Migrando do kapt para KSP

A migração é geralmente simples, mas exige atenção. Aqui está o checklist:

**1. Verifique se suas bibliotecas suportam KSP:**

| Biblioteca | Suporte KSP | Desde |
|---|---|---|
| Room | ✅ | 2.4.0 |
| Moshi | ✅ | 1.13.0 |
| Hilt/Dagger | ✅ | 2.48 |
| Glide | ✅ | 4.14.0 |
| Koin Annotations | ✅ | 1.1.0 |
| MapStruct | ⚠️ Parcial | — |

**2. Substitua as dependências:**

```kotlin
// Antes (kapt)
plugins {
    kotlin("kapt")
}
dependencies {
    kapt("androidx.room:room-compiler:2.7.0")
}

// Depois (KSP)
plugins {
    id("com.google.devtools.ksp")
}
dependencies {
    ksp("androidx.room:room-compiler:2.7.0")
}
```

**3. Remova o plugin kapt** se nenhuma outra dependência precisar dele:

```kotlin
// Remova esta linha do plugins {}
kotlin("kapt")
```

**4. Limpe e rebuild:**

```bash
./gradlew clean build
```

Se você está migrando um projeto [Spring Boot com Kotlin](/blog/kotlin-spring-boot/), atenção: o Dagger/Hilt já suporta KSP, mas verifique a compatibilidade com o Spring annotation processing.

## Bibliotecas Populares com Suporte KSP

### Room (Android)

Room foi uma das primeiras bibliotecas a adotar KSP. Com a flag `room.generateKotlin = true`, o código gerado é Kotlin puro:

```kotlin
@Database(entities = [User::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
    abstract fun userDao(): UserDao
}

@Entity
data class User(
    @PrimaryKey val id: Int,
    val name: String,
    val email: String
)

@Dao
interface UserDao {
    @Query("SELECT * FROM user")
    suspend fun getAll(): List<User>

    @Insert
    suspend fun insert(user: User)
}
```

### Moshi (Serialização JSON)

Moshi com KSP gera adaptadores JSON sem reflection:

```kotlin
@JsonClass(generateAdapter = true)
data class ApiResponse(
    @Json(name = "status_code") val statusCode: Int,
    val message: String,
    val data: List<Item>
)
```

## Criando um Processador KSP Simples

Vamos criar um processador que gera automaticamente um método `toMap()` para data classes anotadas. Isso é útil para entender como KSP funciona por dentro — e é o tipo de conhecimento que impressiona em [entrevistas técnicas de Kotlin](/blog/entrevista-kotlin-perguntas/).

### Passo 1: Definir a anotação

```kotlin
// annotations/src/main/kotlin/ToMap.kt
@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.SOURCE)
annotation class ToMap
```

### Passo 2: Criar o processador

```kotlin
// processor/src/main/kotlin/ToMapProcessor.kt
class ToMapProcessor(
    private val codeGenerator: CodeGenerator,
    private val logger: KSPLogger
) : SymbolProcessor {

    override fun process(resolver: Resolver): List<KSAnnotated> {
        val symbols = resolver
            .getSymbolsWithAnnotation("com.example.ToMap")
            .filterIsInstance<KSClassDeclaration>()

        symbols.forEach { classDeclaration ->
            if (classDeclaration.classKind != ClassKind.CLASS) {
                logger.error("@ToMap só pode ser aplicado em classes", classDeclaration)
                return@forEach
            }
            generateToMap(classDeclaration)
        }

        return emptyList()
    }

    private fun generateToMap(classDecl: KSClassDeclaration) {
        val className = classDecl.simpleName.asString()
        val packageName = classDecl.packageName.asString()
        val properties = classDecl.getAllProperties()

        val file = codeGenerator.createNewFile(
            Dependencies(true, classDecl.containingFile!!),
            packageName,
            "${className}Extensions"
        )

        file.bufferedWriter().use { writer ->
            writer.write("package $packageName\n\n")
            writer.write("fun $className.toMap(): Map<String, Any?> = mapOf(\n")

            properties.forEach { prop ->
                val propName = prop.simpleName.asString()
                writer.write("    \"$propName\" to this.$propName,\n")
            }

            writer.write(")\n")
        }
    }
}

class ToMapProcessorProvider : SymbolProcessorProvider {
    override fun create(environment: SymbolProcessorEnvironment): SymbolProcessor {
        return ToMapProcessor(environment.codeGenerator, environment.logger)
    }
}
```

### Passo 3: Usar a anotação

```kotlin
@ToMap
data class Product(
    val id: Long,
    val name: String,
    val price: Double
)

// Código gerado automaticamente pelo KSP:
// fun Product.toMap(): Map<String, Any?> = mapOf(
//     "id" to this.id,
//     "name" to this.name,
//     "price" to this.price,
// )

fun main() {
    val product = Product(1, "Kotlin in Action", 49.90)
    println(product.toMap())
    // {id=1, name=Kotlin in Action, price=49.9}
}
```

Essa abordagem com [extension functions](/blog/extension-functions-kotlin/) geradas por KSP é um padrão poderoso que combina bem com [DSLs em Kotlin](/blog/kotlin-dsl/).

## Dicas e Boas Práticas

1. **Sempre prefira KSP ao kapt** em projetos novos — não há razão para usar kapt em 2026
2. **Use processamento incremental** — KSP suporta nativamente, mas certifique-se de declarar as dependências corretas no `Dependencies(...)`
3. **Teste seus processadores** — use a biblioteca `com.google.devtools.ksp:symbol-processing-api` para testes unitários
4. **Evite misturar kapt e KSP** no mesmo módulo — funciona, mas perde parte dos ganhos de performance
5. **Monitore os tempos de build** — use `./gradlew --scan` para verificar se a migração realmente melhorou

## Quando Ainda Usar kapt?

Existem raros cenários onde o kapt ainda é necessário:

- Bibliotecas Java-only que não migraram para KSP (cada vez mais raro)
- Processadores que dependem de APIs específicas do `javax.annotation.processing`
- Projetos legados em fase de migração gradual

Mas a tendência é clara: o kapt está em modo de manutenção e o KSP é o futuro. Se você está construindo [APIs com Ktor](/blog/ktor-criando-apis-kotlin/) ou projetos [Kotlin Multiplatform](/blog/kotlin-multiplatform/), KSP é a escolha natural.

## Conclusão

KSP não é apenas uma melhoria incremental sobre o kapt — é uma mudança de paradigma no processamento de anotações em Kotlin. Com builds mais rápidos, uma API Kotlin-native e suporte a multiplatform, não há motivo para não migrar. Se você quer mergulhar mais fundo no ecossistema Kotlin, explore nossos guias de [design patterns](/blog/kotlin-design-patterns/) e [testes com JUnit5 e MockK](/blog/kotlin-testes-junit5-mockk-guia/).

Para quem vem de outras linguagens, vale comparar a abordagem de geração de código do Kotlin com as <a href="https://rustlang.com.br/" target="_blank" rel="noopener" onclick="umami.track('portfolio-site-click', { destination: 'rustlang.com.br' })">macros procedurais do Rust</a> ou os <a href="https://golang.com.br/" target="_blank" rel="noopener" onclick="umami.track('portfolio-site-click', { destination: 'golang.com.br' })">geradores de código em Go com go generate</a>. Já em <a href="https://python.dev.br/" target="_blank" rel="noopener" onclick="umami.track('portfolio-site-click', { destination: 'python.dev.br' })">Python, metaclasses e decorators</a> cumprem um papel semelhante ao KSP para geração dinâmica de código.
