Kotlin guide done. (20.10.26)
This commit is contained in:
@@ -0,0 +1,205 @@
|
||||
---
|
||||
title: Инструментарий
|
||||
description: Обзор инструментов Kotlin — компилятор, сборка, кодогенерация, статический анализ — и как они складываются в проект
|
||||
tags:
|
||||
- kotlin
|
||||
- tooling
|
||||
---
|
||||
|
||||
Язык - это половина дела. Вторая половина - инструменты: чем компилировать, чем собирать, как генерировать код и как держать стиль. В Kotlin эти роли распределены между четырьмя слоями.
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A["исходники .kt"] --> B["компилятор K2<br/>kotlinc"]
|
||||
B --> C[".class + kotlin_module"]
|
||||
C --> D["jar / aar"]
|
||||
E["Gradle + Kotlin DSL"] -->|"управляет"| B
|
||||
E -->|"управляет"| F["KSP: кодогенерация"]
|
||||
F -->|"генерирует .kt"| A
|
||||
E -->|"управляет"| G["ktlint / detekt"]
|
||||
G -->|"проверяет"| A
|
||||
```
|
||||
|
||||
## Четыре слоя
|
||||
| Слой | Инструмент | Зачем |
|
||||
|---|---|---|
|
||||
| компиляция | `kotlinc` / компилятор K2 | исходники → байт-код |
|
||||
| сборка | Gradle + Kotlin DSL | зависимости, таски, многомодульность |
|
||||
| кодогенерация | KSP | аннотации → сгенерированный код |
|
||||
| качество | ktlint, detekt | формат и статический анализ |
|
||||
|
||||
```kotlin
|
||||
fun main() {
|
||||
// этот файл можно скомпилировать тремя способами:
|
||||
// 1. kotlinc Main.kt -include-runtime -d app.jar
|
||||
// 2. gradle build (с build.gradle.kts)
|
||||
// 3. kotlinc -script Main.main.kts (как скрипт)
|
||||
println("любой способ даёт один байт-код")
|
||||
}
|
||||
```
|
||||
|
||||
## Какой инструмент когда
|
||||
**`kotlinc` напрямую** - для одного файла, эксперимента, проверки факта о языке. Не масштабируется: нет управления зависимостями.
|
||||
|
||||
**Gradle** - стандарт для всего остального. Kotlin DSL (`build.gradle.kts`) - это Kotlin-код, поэтому работает автодополнение и проверка типов. Подробнее: [Gradle и Kotlin DSL](Gradle%20и%20Kotlin%20DSL.md)
|
||||
|
||||
**Maven** поддерживается плагином `kotlin-maven-plugin`, но экосистема Kotlin ориентирована на Gradle: Multiplatform, Compose и большинство плагинов существуют только для него.
|
||||
|
||||
**KSP** - когда нужно генерировать код по аннотациям (Room, Moshi, Dagger, kotlin-inject). Заменил `kapt`, который работал через Java-стабы и был в разы медленнее. Подробнее: [KSP](KSP.md)
|
||||
|
||||
## Минимальный проект
|
||||
```kotlin
|
||||
// build.gradle.kts
|
||||
plugins {
|
||||
kotlin("jvm") version "2.4.0"
|
||||
application
|
||||
}
|
||||
|
||||
repositories { mavenCentral() }
|
||||
|
||||
dependencies {
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.11.0")
|
||||
testImplementation(kotlin("test"))
|
||||
}
|
||||
|
||||
kotlin {
|
||||
jvmToolchain(21)
|
||||
}
|
||||
|
||||
application {
|
||||
mainClass.set("com.example.MainKt")
|
||||
}
|
||||
|
||||
tasks.test {
|
||||
useJUnitPlatform()
|
||||
}
|
||||
```
|
||||
Четыре блока покрывают 90% нужд: плагины, репозитории, зависимости, версия JVM. Остальное - настройка под конкретную задачу.
|
||||
|
||||
## Структура каталогов
|
||||
```
|
||||
project/
|
||||
├── build.gradle.kts # сборка модуля
|
||||
├── settings.gradle.kts # список модулей
|
||||
├── gradle.properties # флаги Gradle и JVM
|
||||
├── gradle/
|
||||
│ ├── libs.versions.toml # version catalog
|
||||
│ └── wrapper/ # gradle-wrapper.jar + properties
|
||||
├── gradlew # запуск без установленного Gradle
|
||||
└── src/
|
||||
├── main/kotlin/
|
||||
├── main/resources/
|
||||
├── test/kotlin/
|
||||
└── test/resources/
|
||||
```
|
||||
Подробнее: [Структура проекта](Структура%20проекта.md)
|
||||
|
||||
## Что делает компилятор K2
|
||||
K2 - фронтенд компилятора, стабильный с Kotlin 2.0 и единственный в 2.x. Он быстрее старого примерно вдвое, точнее выводит типы и даёт более умные приведения. Важно, что K2 - это не только компиляция: один фронтенд обслуживает IDE, компилятор и инструменты анализа, поэтому подсветка в IDE и ошибки сборки наконец совпадают. Подробнее: [Компилятор K2](Компилятор%20K2.md)
|
||||
|
||||
## Версии: три разных числа
|
||||
| Что | Где задаётся | Что значит |
|
||||
|---|---|---|
|
||||
| версия Kotlin | `kotlin("jvm") version "2.4.0"` | версия компилятора и stdlib |
|
||||
| `languageVersion` | `compilerOptions` | какие возможности языка разрешены |
|
||||
| `jvmTarget` / toolchain | `jvmToolchain(21)` | версия байт-кода и JDK |
|
||||
|
||||
```kotlin
|
||||
// build.gradle.kts
|
||||
plugins { kotlin("jvm") version "2.4.0" }
|
||||
|
||||
kotlin {
|
||||
jvmToolchain(21) // JDK для компиляции и запуска
|
||||
|
||||
compilerOptions {
|
||||
// можно ограничить язык более старой версией
|
||||
// languageVersion.set(KotlinVersion.KOTLIN_2_1)
|
||||
allWarningsAsErrors.set(false)
|
||||
}
|
||||
}
|
||||
```
|
||||
Частая ошибка - считать их одним. Можно компилировать Kotlin 2.4 компилятором, ограничив язык версией 2.1 (для совместимости с библиотекой), и выдавать байт-код для JVM 8.
|
||||
|
||||
## Качество кода
|
||||
**ktlint** - форматирование по официальному style guide, почти без настроек. **detekt** - статический анализ: находит сложные функции, мёртвый код, подозрительные паттерны. Они дополняют друг друга: первый про форму, второй про смысл. Подробнее: [Линтеры и формат](Линтеры%20и%20формат.md)
|
||||
|
||||
## Карта раздела
|
||||
| Заметка | О чём |
|
||||
|---|---|
|
||||
| [kotlinc](kotlinc.md) | CLI, скрипты, REPL, ключевые флаги |
|
||||
| [Gradle и Kotlin DSL](Gradle%20и%20Kotlin%20DSL.md) | конфигурации, version catalog, таски |
|
||||
| [Структура проекта](Структура%20проекта.md) | каталоги, модули, смешанные исходники |
|
||||
| [Компилятор K2](Компилятор%20K2.md) | фазы, что изменилось, флаги |
|
||||
| [KSP](KSP.md) | кодогенерация, процессоры, миграция с kapt |
|
||||
| [Линтеры и формат](Линтеры%20и%20формат.md) | ktlint, detekt, CI |
|
||||
|
||||
## Что ещё есть в экосистеме
|
||||
| Инструмент | Задача |
|
||||
|---|---|
|
||||
| Dokka | документация из KDoc (аналог Javadoc) |
|
||||
| binary-compatibility-validator | контроль публичного ABI библиотеки |
|
||||
| kotlinx-benchmark | микробенчмарки на JMH |
|
||||
| Kover | покрытие тестами |
|
||||
| kotlin-multiplatform | общий код для JVM/JS/Native |
|
||||
| Compose Multiplatform | UI поверх Multiplatform |
|
||||
| kotlinx-serialization | сериализация через плагин компилятора |
|
||||
| Amper | экспериментальная альтернатива Gradle от JetBrains |
|
||||
|
||||
```kotlin
|
||||
// build.gradle.kts с типичным набором для библиотеки
|
||||
plugins {
|
||||
kotlin("jvm") version "2.4.0"
|
||||
kotlin("plugin.serialization") version "2.4.0"
|
||||
id("org.jetbrains.dokka") version "2.0.0"
|
||||
id("org.jetbrains.kotlinx.binary-compatibility-validator") version "0.17.0"
|
||||
id("io.gitlab.arturbosch.detekt") version "1.23.8"
|
||||
}
|
||||
|
||||
repositories { mavenCentral() }
|
||||
|
||||
dependencies {
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.9.0")
|
||||
testImplementation(kotlin("test"))
|
||||
}
|
||||
```
|
||||
Обратите внимание: `kotlinx-serialization` - это плагин компилятора, а не библиотека рефлексии. Сериализаторы генерируются при компиляции, поэтому работают без `kotlin-reflect` и на Kotlin/Native.
|
||||
|
||||
> [!info] Отличия от Java
|
||||
> | Java | Kotlin |
|
||||
> |---|---|
|
||||
> | `javac` | `kotlinc` (K2) |
|
||||
> | Maven или Gradle (Groovy) | Gradle + Kotlin DSL |
|
||||
> | annotation processing (APT) | KSP |
|
||||
> | Checkstyle, SpotBugs, PMD | ktlint, detekt |
|
||||
> | Javadoc | Dokka (KDoc) |
|
||||
> | Lombok | возможности языка (`data class`, свойства) |
|
||||
> | один таргет - JVM | JVM, JS, Native, Wasm |
|
||||
>
|
||||
> **Gradle в Kotlin-проектах не альтернатива, а стандарт.** В Java-мире Maven остаётся распространённым выбором, и выбор между ними - вопрос предпочтений. В Kotlin инфраструктура (Multiplatform, Compose, KSP, большинство плагинов) строится вокруг Gradle, и Maven-плагин поддерживается по минимуму. Это сужает выбор, но концентрирует усилия.
|
||||
>
|
||||
> **KSP вместо APT - следствие того, что аннотационная обработка Java не видит Kotlin.** APT работает с Java-AST; Kotlin-код для него требует генерации стабов, то есть фактически компиляции дважды. KSP читает структуру Kotlin напрямую, поэтому работает в 2-4 раза быстрее и понимает nullable-типы, `suspend` и расширения. Цена - процессоры нужно писать заново: API другой.
|
||||
>
|
||||
> **Lombok не нужен.** Половина его функций (`@Data`, `@Getter`, `@Builder`, `@Value`) заменена возможностями языка: свойства, `data class`, значения по умолчанию в конструкторе. Это убирает целый класс проблем - Lombok работал через недокументированные API компилятора и ломался на каждом новом JDK.
|
||||
>
|
||||
> **Одна система сборки обслуживает несколько платформ.** Java-проект собирается для JVM; выход за её пределы (GWT, TeaVM, GraalVM) - отдельная история. В Kotlin JS, Native и Wasm - полноправные таргеты в том же `build.gradle.kts`, с общим исходным кодом. Цена - сложность конфигурации Multiplatform-проекта заметно выше.
|
||||
>
|
||||
> Сравнить: [JVM](../../Программирование%20на%20Java/JVM/JVM.md)
|
||||
|
||||
> [!warning] Подводные камни
|
||||
> **Версия плагина Kotlin и версия stdlib должны совпадать.** Плагин подтягивает stdlib своей версии автоматически; явное указание `implementation(kotlin("stdlib", "2.3.0"))` при плагине 2.4.0 даёт конфликт и предупреждение. Не указывайте stdlib вручную вообще.
|
||||
>
|
||||
> **`jvmTarget` без toolchain ломается на другом JDK.** Если локально JDK 21, а в CI - 17, сборка с `jvmTarget = "21"` упадёт. `jvmToolchain(21)` решает: Gradle сам скачает нужный JDK.
|
||||
>
|
||||
> **`jvmTarget` Kotlin и `targetCompatibility` Java должны совпадать.** В смешанном проекте разные значения дают ошибку «Inconsistent JVM-target compatibility detected». `jvmToolchain` настраивает оба.
|
||||
>
|
||||
> **Значение по умолчанию `jvmTarget` - 1.8.** Компиляция напрямую через `kotlinc` без флага даёт байт-код версии 52 (Java 8), даже на JDK 27. Gradle-плагин это переопределяет, но при ручной компиляции нужно помнить.
|
||||
>
|
||||
> **kapt и KSP в одном проекте замедляют сборку.** Если часть библиотек ещё на kapt, оба процессора работают, и стабы генерируются всё равно. Миграцию стоит делать целиком.
|
||||
>
|
||||
> **Gradle без `gradlew` - источник расхождений.** Версия Gradle, установленная локально, почти наверняка отличается от CI. Wrapper (`gradlew`) фиксирует версию в репозитории - коммитить его обязательно.
|
||||
>
|
||||
> **`kotlin.incremental` может давать ложные сборки.** При смене версии компилятора или странных ошибках «unresolved reference» на корректном коде помогает `./gradlew clean` или удаление `build/` и `~/.gradle/caches/build-cache-1`.
|
||||
>
|
||||
> **Плагины компилятора фиксируют версию Kotlin.** `kotlin("plugin.serialization") version "2.4.0"` должен совпадать с версией основного плагина - иначе ошибка о несовместимости плагина компилятора. Используйте version catalog, чтобы версия была в одном месте.
|
||||
|
||||
Далее: [kotlinc](kotlinc.md)
|
||||
Reference in New Issue
Block a user