Что нового в Kotlin 2.4.20
Вышел Kotlin 2.4.20! Вот основные нововведения этого выпуска:
Стандартная библиотека: Поддержка восстановления трассировки стека корутин, новые функции для проверки равенства и уникальности элементов коллекций, а также новые перегрузки функций проверки утверждений
kotlin.testGradle: Поддержка Gradle 9.7.0 и улучшенная отчетность в Problems API
API инструментов сборки: Поддержка новых целевых платформ: Kotlin/JS, Kotlin/Wasm и метаданных Kotlin
Компилятор Kotlin: Команда запуска
kotlinrи отдельный нативный образ
Обновление до Kotlin 2.4.20
Последняя версия Kotlin включена в последние версии IntelliJ IDEA и Android Studio.
Чтобы обновиться до новой версии Kotlin, убедитесь, что ваша IDE обновлена до последней версии, и измените версию Kotlin на 2.4.20 в сценариях сборки.
Новые возможности
В Kotlin 2.2.20 появилась экспериментальная поддержка компиляции выражений when с помощью invokedynamic в JVM 21 и более поздних версиях.
В Kotlin 2.4.20 эта возможность получила статус стабильной и включена по умолчанию.
Подробнее см. в документации.
Новые возможности
В этом выпуске доступны следующие предварительные возможности, в том числе имеющие статус бета-версии, альфа-версии и экспериментальный:
Стандартная библиотека: поддержка восстановления трассировки стека корутин
Стандартная библиотека: новые функции для проверки равенства и уникальности элементов коллекций
Стандартная библиотека: новые перегрузки функций проверки утверждений
kotlin.testKotlin/Native: улучшенная инкрементальная компиляция артефактов
klibKotlin/JS: поддержка экспорта приостанавливающих лямбд в виде асинхронных функций
API инструментов сборки: поддержка Kotlin/JS, Kotlin/Wasm и метаданных Kotlin
Стандартная библиотека
В Kotlin 2.4.20 добавлена поддержка восстановления трассировки стека корутин, представлены новые функции для проверки равенства и уникальности элементов коллекций, а также новые перегрузки функций проверки утверждений kotlin.test.
Поддержка восстановления трассировки стека корутин
В Kotlin 2.4.20 в стандартную библиотеку добавлен интерфейс StackTraceRecoverable. Это улучшает интеграцию с библиотекой kotlinx.coroutines, поскольку позволяет определять способ создания новых экземпляров исключений для восстановления трассировки стека без добавления зависимости от kotlinx.coroutines.
Восстановление трассировки стека помогает отлаживать ситуации, когда одна корутина выбрасывает исключение, а другая повторно его выбрасывает. Благодаря ему можно увидеть, где возникло исключение и где другая корутина выбрасывает его повторно.
Библиотека kotlinx.coroutines выполняет восстановление трассировки стека, создавая новый экземпляр исключения с дополнительной информацией о трассировке стека корутины. Это происходит автоматически для исключений с конструкторами, принимающими только сообщение об исключении, причину, и то и другое либо не принимающими аргументов.
Если конструктор исключения требует дополнительных аргументов, например номера строки или кода ошибки, реализуйте интерфейс StackTraceRecoverable, чтобы определить, как библиотека kotlinx.coroutines создает новый экземпляр этого исключения.
Для реализации интерфейса переопределите функцию copyForStackTraceRecovery(). В переопределении верните новый экземпляр исключения для восстановления трассировки стека или null, если вы не хотите, чтобы библиотека kotlinx.coroutines копировала исключение.
Эти API являются экспериментальными, и для их использования требуется opt-in с помощью аннотации @OptIn(ExperimentalStdlibCoroutineSupportApi::class).
Ниже приведен пример пользовательского исключения, которое сохраняет свойство line при создании нового экземпляра для восстановления трассировки стека:
import kotlin.coroutines.ExperimentalStdlibCoroutineSupportApi
import kotlin.coroutines.debug.StackTraceRecoverable
@OptIn(ExperimentalStdlibCoroutineSupportApi::class)
class FileEditException
// The implementation requires a private constructor
// to pass the cause to the IllegalStateException constructor
private constructor(
val line: Int,
private val detail: String,
cause: Throwable?,
) : IllegalStateException("When editing line $line: $detail", cause),
// Implements StackTraceRecoverable for stack trace recovery
StackTraceRecoverable<FileEditException> {
constructor(line: Int, detail: String) : this(line, detail, null)
// Copies the line number and message details
override fun copyForStackTraceRecovery(): FileEditException =
FileEditException(line, detail, this)
}
fun main() {
val original = FileEditException(15, "Unexpected token")
// Normally, you don't need to call this function directly unless you're testing its behavior
// The kotlinx.coroutines library invokes it automatically during stack trace recovery
val copy = original.copyForStackTraceRecovery()
println(copy.message)
// When editing line 15: Unexpected token
println(copy.cause == original)
// true
}
Подробнее см. в KEEP, посвященном этой возможности.
Будем благодарны за ваши отзывы в YouTrack.
Новые функции для проверки равенства и уникальности элементов коллекций
До Kotlin 2.4.20 для проверки того, что все элементы коллекции различны или равны, приходилось использовать неэффективные шаблоны кода.
В Kotlin 2.4.20 появились экспериментальные функции, решающие эту задачу:
Функция |
Проверка |
|---|---|
Все значения в коллекции уникальны. |
|
У каждого объекта уникальное значение выбранного свойства. |
|
Все значения в коллекции одинаковы. |
|
У всех объектов одинаковое значение выбранного свойства. |
Эти функции можно использовать с коллекциями, последовательностями и массивами. Они сравнивают элементы с помощью структурного равенства, как и другие операции с коллекциями.
Эти функции являются экспериментальными, и для их использования требуется opt-in с помощью аннотации @OptIn(ExperimentalStdlibApi::class) или параметра компилятора -opt-in=kotlin.ExperimentalStdlibApi:
@OptIn(ExperimentalStdlibApi::class)
fun main() {
data class Response(
val participantId: String,
val answer: String,
val responseDate: String
)
val responses = listOf(
Response("P001", "Yes", "2026-07-21"),
Response("P002", "Maybe", "2026-07-21"),
Response("P003", "No", "2026-07-21")
)
// Checks if all participants gave the same answer
println(responses.allEqualBy { it.answer })
// false
// Checks for duplicate participants
println(responses.allDistinctBy { it.participantId })
// true
// Checks if all responses were submitted on the same date
println(responses.allEqualBy { it.responseDate })
// true
val answers = responses.map { it.answer }
// Checks if answers are identical
println(answers.allEqual())
// false
// Checks if answers are distinct
println(answers.allDistinct())
// true
}
Будем благодарны за ваши отзывы в KEEP.
Новые перегрузки функций проверки утверждений kotlin.test
В Kotlin 2.4.20 добавлены новые перегрузки функций проверки утверждений kotlin.test. Они принимают лямбду, которая формирует сообщения об ошибках по запросу — только если проверка утверждения завершилась неудачно.
Ранее функции проверки утверждений kotlin.test, такие как assertTrue() или assertEquals(), принимали только заранее сформированные сообщения об ошибках, которые создавались при каждой проверке, даже если она проходила успешно и сообщение фактически не использовалось.
Новые перегрузки приводят API kotlin.test в соответствие с JUnit 5 и принимают поставщик сообщения в виде лямбды, а не обычную строку. Это повышает производительность, особенно для плагина компилятора Power-assert, который формирует подробные сообщения об ошибках для проверок утверждений.
Новые перегрузки доступны для следующих функций проверки утверждений:
Функция |
Описание |
|---|---|
Проверяет, является ли значение |
|
Проверяет, равны ли значения. |
|
Проверяет, ссылаются ли значения на один и тот же экземпляр. |
|
Проверяет, соответствует ли значение указанному типу. Для |
|
Проверяет, является ли значение |
|
Проверяет, присутствует ли элемент (ключ, символ, подстрока или регулярное выражение) в коллекции, массиве, последовательности, диапазоне или карте. |
|
Проверяет, содержат ли коллекции, последовательности или массивы равные элементы в одинаковом порядке. |
Чтобы использовать новый API, явно включите opt-in с помощью аннотации @OptIn(ExperimentalKotlinTestApi::class):
import kotlin.test.ExperimentalKotlinTestApi
import kotlin.test.assertEquals
import kotlin.test.assertTrue
@OptIn(ExperimentalKotlinTestApi::class)
fun testValues(actual: Int, expected: Int, items: List<String>) {
// The message is built only if the assertion fails
assertTrue(actual > 0) { "Expected a positive value but got $actual" }
// Avoids formatting the list unless the assertion fails
assertEquals(expected, actual) { "Unexpected value for items: ${items.joinToString()}" }
}
Подробнее см. в KEEP, посвященном этой возможности.
Kotlin/Native
В Kotlin 2.4.20 появилась автоматическая генерация файлов Package.swift для зависимостей SwiftPM в проектах Kotlin Multiplatform, новые возможности экспорта Swift, включая поддержку запечатанных классов и межъязыкового наследования, а также улучшенная инкрементальная компиляция.
Автоматическая генерация Package.swift для зависимостей SwiftPM
При экспорте XCFramework, зависящего от пакетов SwiftPM, необходимо опубликовать результирующий пакет SwiftPM, чтобы он корректно разрешался. Для этого задача Gradle assembleSharedXCFramework теперь создает файл Package.swift, который распространяется вместе с XCFramework.
Подробнее см. на странице экспорта SwiftPM.
Новые возможности экспорта Swift
Запечатанные классы
В Kotlin 2.4.20 добавлена поддержка запечатанных классов и интерфейсов в экспорте Swift.
Раньше для каждого оператора switch, проверяющего запечатанный тип, требовалось писать ветку default. Теперь запечатанные иерархии, объявленные в Kotlin, преобразуются в перечисления Swift, что позволяет использовать исчерпывающие операторы switch с полной автоподстановкой в Xcode.
Экспорт Swift генерирует метод sealedType() для каждого запечатанного типа. Этот метод возвращает перечисление Swift, варианты которого соответствуют непосредственным подклассам запечатанной иерархии. Эти вызовы можно вкладывать, чтобы сопоставлять более глубокие уровни иерархии.
Например, объявите в Kotlin запечатанный интерфейс с иерархией классов:
// Kotlin
sealed interface Shape
class Circle : Shape {
override fun toString(): String = "Circle"
}
class Rectangle : Shape {
override fun toString(): String = "Rectangle"
}
fun createCircle(): Shape = Circle()
В Swift можно использовать исчерпывающий switch без ветки default:
// Swift
let shape = createCircle()
let name = switch shape.sealedType() {
case let .circle(type): "It's a \(type.value)"
case let .rectangle(type): "It's a \(type.value)"
}
// name == "It's a Circle"
Поскольку switch является исчерпывающим, компилятор предупредит вас, если в запечатанную иерархию будет добавлен новый подкласс. Так вы сможете сразу обработать его, не полагаясь на ветку default.
Межъязыковое наследование в экспорте Swift
В Kotlin 2.4.20 появилась поддержка межъязыкового наследования в экспорте Swift.
Распространенный вариант использования этой возможности — шаблон обратного импорта, при котором контракт определяется в Kotlin, а платформозависимые реализации предоставляются на стороне Swift. Это особенно полезно, если нужно использовать библиотеки на чистом Swift, которые нельзя напрямую импортировать в Kotlin.
Чтобы реализовать этот шаблон, объявите суперкласс Kotlin, от которого будет наследоваться реализация Swift, и интерфейс Kotlin. Затем реализуйте этот интерфейс в Swift и передайте объект Swift функциям Kotlin, принимающим этот интерфейс. Например, для библиотеки CryptoKit:
-
На стороне Kotlin объявите интерфейс, функцию, принимающую его, и базовый класс
open:// Kotlin interface CryptoProvider { fun hashMD5(input: String): String } fun processHash(provider: CryptoProvider, input: String): String = provider.hashMD5(input) open class SwiftBase -
На стороне Swift унаследуйтесь от экспортированного класса
SwiftBase, реализуйте интерфейс с помощью библиотеки на чистом Swift и передайте объект обратно в Kotlin:// Swift import CryptoKit final class IosCryptoProvider: SwiftBase, CryptoProvider { func hashMD5(input: String) -> String { guard let data = input.data(using: .utf8) else { return "failed" } return Insecure.MD5.hash(data: data).description } } let provider = IosCryptoProvider() // Calls the Kotlin function, which calls hashMD5() back in Swift print(processHash(provider: provider, input: "Hello, world!"))
Получив объект Swift, Kotlin обрабатывает его как реализацию обычного интерфейса и напрямую вызывает код Swift.
Подробнее об экспорте Swift см. в нашей документации.
Улучшенная инкрементальная компиляция артефактов klib
В Kotlin 2.4.20 улучшена стабильность инкрементальной компиляции артефактов klib, которая теперь имеет бета-статус.
Эта оптимизация впервые появилась в Kotlin 1.9.20 и, как показала практика, значительно сокращает время компиляции отладочных сборок. С тех пор мы исправили ряд ошибок и повысили производительность.
Чтобы опробовать инкрементальную компиляцию, добавьте следующий параметр в файл gradle.properties:
kotlin.incremental.native=true
Мы активно собираем отзывы и планируем включить инкрементальную компиляцию по умолчанию для всех проектов в следующих выпусках Kotlin. Если вы столкнетесь с проблемами, сообщите о них в нашем трекере задач.
Kotlin/Wasm
В Kotlin 2.4.20 изменен способ обработки вызовов require() верхнего уровня в объявлениях @JsFun в Kotlin/Wasm, порядок инициализации объектов-компаньонов приведен в соответствие с JVM, уменьшен размер бинарных файлов для функциональных интерфейсов, добавлены новые режимы компиляции и поддержка Wasmtime в качестве среды выполнения для целевой платформы wasmWasi в плагине Kotlin Gradle.
Изменения в вызовах require() верхнего уровня в объявлениях @JsFun
Теперь Kotlin/Wasm выдает ошибку, если в объявлении @JsFun используется функция require() верхнего уровня.
Ранее компилятор генерировал переменную require в файле import-object.mjs, что позволяло объявлениям @JsFun вызывать require().
Такое поведение непреднамеренно раскрывало детали реализации компилятора. Чтобы помочь перейти на новый подход, Kotlin/Wasm удаляет это сгенерированное объявление require, а компилятор теперь сообщает об ошибках при таких вызовах. Например:
// Reports an error
@JsFun("(mod) => require(mod)")
external fun loadModule(mod: String): JsAny
Чтобы подготовиться к этому изменению, замените вызовы require() верхнего уровня в объявлениях @JsFun аннотацией @JsModule:
@JsModule("module")
external val module: Module
external interface Module {
// Defines the expected module members
}
Для динамической загрузки модулей используйте выражение import(). Добавьте магический комментарий /* webpackIgnore: true */, чтобы webpack не анализировал динамический импорт:
@JsFun("""
((module) => () => module)(
await import(/* webpackIgnore: true */ "module")
)
""")
private external fun loadModuleDynamically(): JsAny?
Вы также можете использовать выражение import() условно. Например, можно загружать модуль только при запуске в Node.js:
@JsFun("""
((module) => () => module)(
((typeof process !== "undefined") && (process.release.name === "node"))
? await import(/* webpackIgnore: true */ "module")
: null
)
""")
private external fun loadNodeModule(): JsAny?
Если ваш проект зависит от библиотек, которым требуется функция require() верхнего уровня, добавьте ее как свойство globalThis в качестве обходного решения:
@JsFun("""
((module) => {
globalThis.require = module.default.createRequire(import.meta.url)
return () => {}
})(await import("node:module"))
""")
external fun defineRequire()
Если у вас возникнут проблемы, поделитесь отзывами в нашем трекере задач.
Улучшенный порядок инициализации объектов-компаньонов
Теперь Kotlin/Wasm инициализирует объекты-компаньоны суперклассов перед объектами-компаньонами подклассов, как и JVM. Ранее порядок инициализации мог быть обратным, что приводило к несогласованному поведению на разных платформах.
Это изменение повышает согласованность кроссплатформенного поведения и уменьшает различия в инициализации классов на разных платформах. Оно также обеспечивает корректную обработку инициализации объектов-компаньонов в глубоких иерархиях наследования, в том числе в случаях, когда промежуточные классы не объявляют объекты-компаньоны.
Поддержка Wasmtime в плагине Kotlin Gradle
В Kotlin 2.4.20 добавлена поддержка Wasmtime в качестве среды выполнения для целевой платформы wasmWasi в плагине Kotlin Gradle.
Ранее целевая платформа wasmWasi поддерживала только среду выполнения Node.js, для которой требовался загрузчик JavaScript для запуска приложений WASI. Благодаря поддержке Wasmtime теперь можно запускать приложения Kotlin/Wasm в автономной среде выполнения WebAssembly.
Чтобы использовать Wasmtime в качестве среды выполнения для целевой платформы wasmWasi, добавьте wasmtime() в файл сборки Gradle:
kotlin {
wasmWasi {
wasmtime()
}
}
Будем благодарны за ваши отзывы в YouTrack.
Новые режимы компиляции
В Kotlin 2.4.20 добавлена поддержка выбора режима компиляции Kotlin/Wasm, включая новые многомодульные режимы. Ранее компилятор использовал монолитный режим компиляции, в котором проект и его зависимости компилируются вместе и создается один бинарный файл. Это позволяет компилятору удалять неиспользуемый код и формировать выходные данные минимального размера.
Теперь можно выбрать один из следующих режимов компиляции:
Режим компиляции |
Компиляция |
Результат |
Поведение оптимизации |
|---|---|---|---|
|
Компилирует проект и его зависимости вместе. |
Один бинарный файл |
Удаляет недостижимые объявления и применяет оптимизации ко всей программе, включая зависимости. |
|
Компилирует каждый модуль отдельно и перекомпилирует только изменившиеся модули. |
Отдельный независимый бинарный файл для каждого модуля |
Не применяет межмодульные оптимизации, в результате чего бинарные файлы получаются больше. |
|
Обрабатывает все модули за один запуск и перекомпилирует только изменившиеся модули. |
Отдельные бинарные файлы, зависящие друг от друга |
Удаляет недостижимые объявления, но оптимизирует каждый бинарный файл Wasm независимо. |
Чтобы выбрать режим компиляции, добавьте свойство kotlin.wasm.compilationMode в файл gradle.properties:
kotlin.wasm.compilationMode=multimodule-open-world
Также можно настроить Kotlin/Wasm так, чтобы в сборках для разработки использовалась многомодульная компиляция с замкнутым миром, а в сборках для выпуска — монолитная компиляция. Это сокращает время перекомпиляции при разработке и обеспечивает минимальный размер выходных данных в сборках для выпуска.
Чтобы использовать эту конфигурацию, добавьте следующее свойство в файл gradle.properties:
kotlin.wasm.compilationMode=multimodule-closed-world-only-in-dev
Будем благодарны за ваши отзывы в YouTrack.
Уменьшение размера бинарных файлов для лямбд и функциональных интерфейсов
В Kotlin 2.4.20 изменен способ компиляции лямбд и функциональных интерфейсов в Kotlin/Wasm. Вместо генерации отдельных анонимных классов компилятор теперь генерирует функции и использует общие базовые классы.
Тесты приложения KotlinConf показывают, что это изменение уменьшает размер бинарного файла Wasm примерно на 5–10%.
Поскольку изменение добавляет больше динамических вызовов, оно может повлиять на производительность во время выполнения. Если у вас возникнут проблемы, сообщите о них в нашем трекере задач.
Kotlin/JS
В Kotlin 2.4.20 улучшена возможность экспорта классов данных, добавлен новый экспериментальный DSL для тестирования в браузере и поддержка экспорта приостанавливаемых лямбд в виде асинхронных функций JavaScript.
Единообразная возможность экспорта синтетических функций в экспортируемых классах данных
В Kotlin 2.4.20 исправлена проблема, из-за которой аннотация @JsExport.Ignore не применялась должным образом к свойствам классов данных.
Ранее, если класс данных был помечен аннотацией @JsExport, компилятор всё равно выводил предупреждения о возможности экспорта класса данных из-за автоматически генерируемых функций copy() и componentN(). Это происходило, даже если конструктор и свойства явно помечались как игнорируемые с помощью @JsExport.Ignore.
Рассмотрим, например, класс данных Session, экспортируемый в JavaScript и содержащий ссылку на внутренний тип DatabaseConnection, который не предназначен для экспорта:
// Kotlin
// An internal type that isn't exported to JavaScript
class DatabaseConnection
@JsExport
data class Session @JsExport.Ignore constructor(
val userId: String,
@JsExport.Ignore val connection: DatabaseConnection,
)
Теперь, после исправления проблемы, компилятор учитывает аннотации @JsExport.Ignore, поэтому синтетические функции copy() и componentN() класса Session больше не вызывают предупреждений о неэкспортируемом типе DatabaseConnection. Это соответствует правилам видимости, введённым аннотациями @ConsistentCopyVisibility и @ExposedCopyVisibility.
Новый DSL для тестирования в браузере
В Kotlin 2.4.20 появился новый экспериментальный DSL для запуска тестов Kotlin/JS в браузере.
Сейчас плагин Kotlin Gradle использует Karma в качестве средства запуска браузеров для тестирования JavaScript в разных браузерах. Проект Karma уже два года как объявлен устаревшим, поэтому мы начали изучать альтернативные способы поддержки тестирования в браузере.
Новый DSL предназначен для замены Karma в качестве средства управления различными инструментами и включает:
Playwright в качестве драйвера браузера и менеджера дистрибутивов с поддержкой браузерных движков Chromium, Firefox и WebKit (Safari).
Mocha в качестве средства запуска тестов.
webpack в качестве сборщика (в будущих выпусках его заменит Vite).
Чтобы попробовать новый DSL для тестирования в браузере, добавьте блок opt-in test {} в browser {} для целевой платформы Kotlin/JS:
import org.jetbrains.kotlin.gradle.ExperimentalJsTestDsl
import kotlin.time.Duration.Companion.seconds
kotlin {
js {
browser {
// Add and configure the new test {} block
@OptIn(ExperimentalJsTestDsl::class)
test {
// Configure default timeout for all runners
timeout = 2.seconds
// Configure headless mode using Gradle providers
headless = providers
.environmentVariable("IS_IN_CI")
.map { it.toBoolean() }
.orElse(false)
// Enable and configure Chromium test runner
chromium {
// Override the common timeout option
timeout = 5.seconds
// Add extra launch arguments
launchArgs.add("--no-sandbox")
}
// Enable Firefox test runner
firefox()
// Enable WebKit test runner
webkit()
// Enable and configure an additional WebKit test runner
webkit("noheadless") {
// Set up custom options
headless = false
}
}
}
}
}
Новый DSL для тестирования в браузере активно разрабатывается. Будем признательны за ваши отзывы в YouTrack.
Подробнее см. в разделе Запуск тестов в Kotlin/JS.
Поддержка экспорта приостанавливаемых лямбд в виде асинхронных функций
В Kotlin 2.4.20 теперь можно экспортировать лямбда-выражения с приостановкой в виде функций JavaScript async.
Ранее не существовало способа экспортировать из библиотек Kotlin/JS объявления, содержащие приостанавливаемые лямбды. Теперь компилятор Kotlin автоматически обрабатывает взаимодействие между функциями Kotlin suspend и встроенной моделью JavaScript async/await, что полезно для проектов, сочетающих Kotlin и TypeScript.
Чтобы включить эту функцию, добавьте следующий параметр компилятора в файл build.gradle.kts:
kotlin {
js {
compilations.all {
compileTaskProvider.configure {
compilerOptions {
freeCompilerArgs.add("-Xsuspend-lambda-exporting")
}
}
}
}
}
Затем пометьте соответствующие объявления аннотацией @JsExport:
// Kotlin
@JsExport
class TaskRunner {
suspend fun runTask(task: suspend () -> String): String {
return task()
}
}
В TypeScript приостанавливаемая лямбда выглядит как обычная функция async:
// TypeScript
import { TaskRunner } from "..."
const runner = new TaskRunner();
const result = await runner.runTask(async () => "done");
console.log(result); // "done"
Подробнее об аннотации @JsExport см. в документации.
Gradle
Kotlin 2.4.20 полностью совместим с Gradle версий от 7.6.3 до 9.7.0. Также можно использовать более поздние версии Gradle, вплоть до самой новой. Однако обратите внимание: это может привести к предупреждениям об устаревании, а некоторые новые функции Gradle могут не работать.
В Kotlin 2.4.20 также улучшена интеграция с Problems API.
Улучшенная отправка данных в Problems API
Kotlin 2.2.0 стал первым выпуском, в котором плагин Kotlin Gradle (KGP) интегрировали с Problems API Gradle. В Kotlin 2.4.0 добавлена поддержка передачи сообщений компилятора в Problems API для Kotlin/JVM.
В Kotlin 2.4.20 в сведения, передаваемые компилятором в Problems API, добавлены идентификаторы диагностики компилятора. Диагностические сообщения также группируются по этим идентификаторам, что упрощает определение источника проблем компиляции.
Начиная с Gradle 8.6, KGP включает эту интеграцию по умолчанию. Поскольку API продолжает развиваться, используйте последнюю версию Gradle, чтобы воспользоваться новейшими улучшениями.
Build tools API
В Kotlin 2.4.20 добавлена экспериментальная поддержка Kotlin/JS, Kotlin/Wasm и метаданных Kotlin в build tools API.
Поддержка Kotlin/JS, Kotlin/Wasm и метаданных Kotlin
В Kotlin 2.2.0 build tools API (BTA) стал доступен для Kotlin/JVM. В Kotlin 2.4.20 сделан следующий шаг к стабилизации BTA — добавлена поддержка новых целевых платформ: Kotlin/JS, Kotlin/Wasm и метаданных Kotlin.
Это обеспечивает более согласованное взаимодействие плагина Kotlin Gradle с компилятором. В некоторых случаях вы также можете воспользоваться более быстрой и стабильной компиляцией.
BTA — это универсальный API, выступающий уровнем абстракции между системами сборки и экосистемой компилятора Kotlin. Он помогает поддерживать функции Kotlin и совместимость с компилятором Kotlin в доступных инструментах сборки.
В Kotlin 2.4.20 BTA доступен для новых целевых платформ по opt-in. Чтобы попробовать его, добавьте соответствующие свойства в файл gradle.properties:
kotlin.wasm.runViaBuildToolsApi=true kotlin.js.runViaBuildToolsApi=true kotlin.metadata.runViaBuildToolsApi=true
Начиная с Kotlin 2.5.0, мы планируем включить BTA по умолчанию для Kotlin/JS, Kotlin/Wasm и метаданных Kotlin.
Если вас интересует предложение BTA или вы хотите поделиться отзывом, ознакомьтесь с этим документом KEEP.
Компилятор Kotlin
В Kotlin 2.4.20 обновлена информация об изменении команды запуска Kotlin, kotlinr, и представлен экспериментальный нативный образ компилятора Kotlin.
Команда запуска Kotlin изменена с kotlin на kotlinr
Команда kotlinr заменяет kotlin в качестве команды запуска Kotlin, чтобы избежать конфликта имён с командой kotlin в Kotlin Toolchain. Средство запуска Kotlin также предупреждает об использовании команды kotlin и рекомендует вместо неё kotlinr.
Нативный образ
В Kotlin 2.4.20 представлен первый экспериментальный выпуск нативного образа компилятора Kotlin. Нативный образ может полностью заменить стандартный инструмент командной строки kotlinc и при этом обеспечивает более быстрый запуск и высокую производительность.
Чтобы попробовать нативный образ, скачайте сборку со страницы выпусков GitHub.
В нативный образ также входят следующие плагины компилятора, которые можно использовать с параметрами CLI -Xplugin или -Xcompiler-plugin:
Подробнее о нативном образе компилятора Kotlin см. в файле README.
Несовместимые изменения и устаревшие функции
В этом разделе описаны важные несовместимые изменения и устаревшие функции. Полный обзор см. в руководстве по совместимости.
Поскольку Apple прекращает поддержку 32-разрядных целевых платформ watchOS, целевая платформа
watchosArm32Kotlin/Native теперь объявлена устаревшей. Её планируется удалить в Kotlin 2.5.0, чтобы обеспечить совместимость с Xcode 27.Начиная с Kotlin 2.4.20, компилятор Kotlin/Native запрещает атомарные операции AtomicFU внутри встроенной функции
publicили внутри встроенной функцииinternal, вызываемой из другого файла.-
В Kotlin 2.4.20 обновлена зависимость webpack в npm до версии 5.108.1. Это может повлиять на ваш проект двумя способами:
webpack заменил встроенную зависимость минификатора с
terser-webpack-pluginна более универсальныйminimizer-webpack-plugin. Terser остаётся минификатором JavaScript по умолчанию, но если ваш проект напрямую настраивает или используетterser-webpack-plugin, возможно, потребуется обновить его конфигурацию.При определении типа модуля JavaScript-файла webpack больше не игнорирует
import.meta. Еслиimport.metaприсутствует, webpack считает файл ES-модулем, что может нарушить работу файлов, в которых также используются конструкции CommonJS. Для Kotlin/JS можно настроить целевую платформу для использования ES-модулей с помощью DSL GradleuseEsModules(). В большинстве случаев Kotlin/Wasm должен работать без дополнительной настройки. Если при работе с Kotlin/Wasm возникает ошибкаimport.meta, проверьте, используют ли исходный код проекта или прямая либо транзитивная зависимостьimport.meta. При необходимости обновите собственный код. Если проблема вызвана зависимостью, обновите её до совместимой версии, если такая доступна, или сообщите о проблеме сопровождающим библиотеки.
Начиная с Kotlin 2.4.20, в Kotlin/Wasm объявлен устаревшим генерируемый API JavaScript
wasmExports. Компилятор запрещает доступ ко всем экспортам, кромеwasmExports.memory, который временно остаётся доступен с предупреждением. Используйте свойствоkotlin.wasm.unsafe.wasmMemoryдля доступа к объектуWebAssembly.Memoryмодуля.
Обновления документации
После предыдущего выпуска мы создали новые страницы и руководства для документации экосистемы Kotlin и обновили существующие материалы:
Настройка конвейера поставки для iOS — настройте непрерывную поставку приложения Kotlin Multiplatform для iOS с помощью TeamCity.
-
Обновления Compose Multiplatform:
Всплывающие окна — узнайте, как создавать и настраивать всплывающие окна в Compose Multiplatform.
API окон и диалогов, версия 2 — познакомьтесь с новым API для управления окнами и диалогами рабочего стола в Compose Multiplatform.
Системный трей и уведомления — узнайте, как добавить значок приложения в системный трей и отправлять системные уведомления в Compose Multiplatform для рабочего стола.
Строка меню — узнайте, как создать строку меню для отдельного окна в Compose Multiplatform для рабочего стола.
Перетаскивание — обрабатывайте данные, специфичные для платформы, при реализации перетаскивания в Compose Multiplatform.
Альтернатива UIKit для Liquid Glass — познакомьтесь с альтернативным подходом к Liquid Glass, использующим навигацию UIKit вместо SwiftUI.
MCP-сервер для ИИ-агентов — узнайте, как использовать MCP-сервер в Compose Hot Reload для интеграции ИИ-агентов в процесс разработки.
Кэширование с Spring — узнайте, как добавить кэширование в приложение Spring, используя новые примеры на Kotlin.
Плагин Exposed для IntelliJ IDEA — узнайте, как работать с Exposed в IntelliJ IDEA, используя автодополнение кода, проверки с учётом базы данных и живые шаблоны.
Сериализация Kotlin — узнайте, как сериализовать данные Kotlin, настраивать структуру JSON и представление типов, а также работать с более сложными сценариями сериализации.
Flow и операторы Flow — узнайте, как создавать и собирать холодные и горячие потоки, обрабатывать исключения и использовать широкий спектр операторов Flow.
Отладка корутин — узнайте, как отлаживать корутины на JVM с помощью режима отладки, восстановления трассировки стека и агента отладки.
Lincheck — узнайте, как в Lincheck работает проверка модели, как использовать параметры выполнения операций и как проверять результаты тестов.
Плагин компилятора kapt — узнайте, как настроить плагин компилятора kapt в Gradle, Maven и компиляторе командной строки.
Инструменты контроля качества кода в проектах Kotlin — познакомьтесь с инструментами для анализа байт-кода JVM и кода Kotlin.
Плагин Power-assert для Maven — узнайте, как использовать плагин Power-assert, чтобы получать более подробные сообщения о сбоях тестов.
Многоэтапная обработка с KSP — изучите работу KSP в нескольких циклах обработки, включая сгенерированные файлы, отложенные символы и проверку.
Неназываемые типы — узнайте о платформенных типах, захваченных типах и пересекающихся типах в Kotlin.
Псевдонимы типов — узнайте об области видимости и видимости псевдонимов типов.
Выражения this — узнайте, как разрешается неявный
thisи когда следует явно использоватьthisдля ссылки на получателя.Строки — узнайте о строковых шаблонах, распространённых операциях со строками, создании строк и преобразовании типов.
Пакеты и импорты — узнайте, как организовать код Kotlin с помощью пакетов и импортов.
© 2010–2026 JetBrains s.r.o. and Kotlin Programming Language contributors
Licensed under the Apache License, Version 2.0.
https://kotlinlang.org/docs/whatsnew2420.html