Что нового в Kotlin 2.1.20
Вышел Kotlin 2.1.20! Вот основные нововведения:
Обновления компилятора K2: обновления новых плагинов kapt и Lombok
Kotlin Multiplatform: новый DSL на замену плагину Application в Gradle
Kotlin/Native: поддержка Xcode 16.3 и новая оптимизация встраивания
Kotlin/Wasm: пользовательские форматтеры по умолчанию, поддержка DWARF и переход на Provider API
Поддержка Gradle: совместимость с Isolated Projects в Gradle и пользовательскими вариантами публикации
Стандартная библиотека: общие атомарные типы, улучшенная поддержка UUID и новые возможности отслеживания времени
Компилятор Compose: смягчение ограничений для функций
@Composableи другие обновленияДокументация: важные улучшения документации Kotlin
Поддержка IDE
Плагины Kotlin с поддержкой версии 2.1.20 включены в последние версии IntelliJ IDEA и Android Studio. Обновлять плагин Kotlin в IDE не нужно. Достаточно изменить версию Kotlin на 2.1.20 в сценариях сборки.
Подробнее см. в разделе Обновление до новой версии.
Загрузка исходного кода артефактов Kotlin в проектах с поддержкой OSGi
Исходный код всех зависимостей библиотеки kotlin-osgi-bundle теперь включен в ее дистрибутив. Благодаря этому IntelliJ IDEA может загружать эти исходные файлы, чтобы предоставлять документацию для символов Kotlin и улучшить отладку.
Компилятор Kotlin K2
Мы продолжаем улучшать поддержку плагинов для нового компилятора Kotlin K2. В этом выпуске обновлены новые плагины kapt и Lombok.
Новый плагин kapt, включенный по умолчанию
Начиная с Kotlin 2.1.20, реализация плагина компилятора kapt для K2 включена по умолчанию во всех проектах.
Команда JetBrains выпустила новую реализацию плагина kapt для компилятора K2 еще в Kotlin 1.9.20. С тех пор мы продолжили развивать внутреннюю реализацию K2 kapt и приблизили ее поведение к версии K1, значительно повысив при этом производительность.
Если при использовании kapt с компилятором K2 возникнут проблемы, можно временно вернуться к предыдущей реализации плагина.
Для этого добавьте следующий параметр в файл gradle.properties вашего проекта:
kapt.use.k2=false
Сообщайте о любых проблемах в нашем трекере задач.
Плагин компилятора Lombok: поддержка @SuperBuilder и обновления @Builder
Плагин компилятора Kotlin Lombok теперь поддерживает аннотацию @SuperBuilder, упрощая создание билдеров для иерархий классов. Раньше разработчикам, использующим Lombok в Kotlin, приходилось вручную определять билдеры при работе с наследованием. С @SuperBuilder билдер автоматически наследует поля суперкласса, позволяя инициализировать их при создании объекта.
Кроме того, это обновление включает несколько улучшений и исправлений ошибок:
Аннотацию
@Builderтеперь можно использовать с конструкторами, что позволяет гибче создавать объекты. Подробнее см. в соответствующей задаче YouTrack.Исправлено несколько проблем, связанных с генерацией кода Lombok в Kotlin, что улучшило общую совместимость. Подробнее см. в списке изменений на GitHub.
Подробнее об аннотации @SuperBuilder см. в официальной документации Lombok.
Kotlin Multiplatform: новый DSL на замену плагину Application в Gradle
Начиная с Gradle 8.7, плагин Application больше не совместим с плагином Kotlin Multiplatform для Gradle. В Kotlin 2.1.20 представлен экспериментальный DSL с аналогичными возможностями. Новый блок executable {} настраивает задачи выполнения и дистрибутивы Gradle для целей JVM.
Перед блоком executable {} в сценарии сборки добавьте следующую аннотацию @OptIn:
@OptIn(ExperimentalKotlinGradlePluginApi::class)
Например:
kotlin {
jvm {
@OptIn(ExperimentalKotlinGradlePluginApi::class)
binaries {
// Configures a JavaExec task named "runJvm" and a Gradle distribution for the "main" compilation in this target
executable {
mainClass.set("foo.MainKt")
}
// Configures a JavaExec task named "runJvmAnother" and a Gradle distribution for the "main" compilation
executable(KotlinCompilation.MAIN_COMPILATION_NAME, "another") {
// Set a different class
mainClass.set("foo.MainAnotherKt")
}
// Configures a JavaExec task named "runJvmTest" and a Gradle distribution for the "test" compilation
executable(KotlinCompilation.TEST_COMPILATION_NAME) {
mainClass.set("foo.MainTestKt")
}
// Configures a JavaExec task named "runJvmTestAnother" and a Gradle distribution for the "test" compilation
executable(KotlinCompilation.TEST_COMPILATION_NAME, "another") {
mainClass.set("foo.MainAnotherTestKt")
}
}
}
}
В этом примере плагин Distribution из Gradle применяется в первом блоке executable {}.
Если возникнут проблемы, сообщите о них в нашем трекере задач или напишите в наш публичный канал Slack.
Kotlin/Native
Поддержка Xcode 16.3
Начиная с Kotlin 2.1.21, компилятор Kotlin/Native поддерживает Xcode 16.3 — последнюю стабильную версию Xcode. Обновите Xcode и продолжайте работу над проектами Kotlin для операционных систем Apple.
В выпуске 2.1.21 также исправлена связанная проблема cinterop, вызывавшая сбои компиляции в проектах Kotlin Multiplatform.
Новая оптимизация встраивания
В Kotlin 2.1.20 добавлен новый этап оптимизации встраивания, который выполняется перед этапом генерации кода.
Новый этап встраивания в компиляторе Kotlin/Native должен работать эффективнее стандартного встраивателя LLVM и повышать производительность сгенерированного кода во время выполнения.
Новый этап встраивания пока является экспериментальным. Чтобы попробовать его, используйте следующий параметр компилятора:
-Xbinary=preCodegenInlineThreshold=40
Наши эксперименты показывают, что порог в 40 токенов (единиц кода, анализируемых компилятором) обеспечивает разумный компромисс для оптимизации компиляции. Согласно результатам тестирования, это повышает общую производительность на 9,5%. Разумеется, можно попробовать и другие значения.
Если размер бинарного файла или время компиляции увеличатся, сообщите об этом через YouTrack.
Kotlin/Wasm
В этом выпуске улучшены отладка Kotlin/Wasm и работа со свойствами. В сборках для разработки пользовательские форматтеры работают сразу после установки, а отладка с DWARF упрощает анализ кода. Кроме того, Provider API упрощает работу со свойствами в Kotlin/Wasm и Kotlin/JS.
Пользовательские форматтеры включены по умолчанию
Раньше для улучшения отладки кода Kotlin/Wasm в браузерах требовалось вручную настроить пользовательские форматтеры.
В этом выпуске пользовательские форматтеры включены по умолчанию в сборках для разработки, поэтому дополнительная настройка Gradle не требуется.
Чтобы воспользоваться этой возможностью, нужно лишь убедиться, что пользовательские форматтеры включены в инструментах разработчика вашего браузера:
-
В Chrome DevTools флажок пользовательских форматтеров находится в разделе Настройки | Параметры | Консоль:

-
В Firefox DevTools флажок пользовательских форматтеров находится в разделе Настройки | Дополнительные настройки:
Это изменение в первую очередь касается сборок Kotlin/Wasm для разработки. Если у вас есть особые требования к сборкам для выпуска, соответствующим образом измените конфигурацию Gradle. Для этого добавьте следующий параметр компилятора в блок wasmJs {}:
// build.gradle.kts
kotlin {
wasmJs {
// ...
compilerOptions {
freeCompilerArgs.add("-Xwasm-debugger-custom-formatters")
}
}
}
Поддержка DWARF для отладки кода Kotlin/Wasm
В Kotlin 2.1.20 добавлена поддержка DWARF (отладки с произвольным форматом записей) в Kotlin/Wasm.
Теперь компилятор Kotlin/Wasm может включать данные DWARF в сгенерированный бинарный файл WebAssembly (Wasm). Многие отладчики и виртуальные машины могут считывать эти данные и предоставлять сведения о скомпилированном коде.
DWARF особенно полезен для отладки приложений Kotlin/Wasm в автономных виртуальных машинах Wasm. Для использования этой возможности виртуальная машина Wasm и отладчик должны поддерживать DWARF.
Благодаря поддержке DWARF можно пошагово выполнять приложения Kotlin/Wasm, проверять значения переменных и получать сведения о коде. Чтобы включить эту возможность, используйте следующий параметр компилятора:
-Xwasm-generate-dwarf
Переход свойств Kotlin/Wasm и Kotlin/JS на Provider API
Раньше свойства в расширениях Kotlin/Wasm и Kotlin/JS были изменяемыми (var), и им напрямую присваивались значения в сценариях сборки:
the<NodeJsExtension>().version = "2.0.0"
Теперь свойства предоставляются через Provider API, и для присваивания значений необходимо использовать функцию .set():
the<NodeJsEnvSpec>().version.set("2.0.0")
Provider API обеспечивает отложенное вычисление значений и корректную интеграцию с зависимостями задач, повышая производительность сборки.
В связи с этим прямое присваивание свойств объявлено устаревшим; вместо него следует использовать классы *EnvSpec, например NodeJsEnvSpec и YarnRootEnvSpec.
Кроме того, удалено несколько задач-псевдонимов, чтобы избежать путаницы:
Устаревшая задача |
Замена |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Если в сценариях сборки используются только Kotlin/JS или Kotlin/Wasm, никаких действий не требуется: Gradle автоматически обрабатывает присваивания.
Однако если вы разрабатываете плагин на основе Kotlin Gradle Plugin и он не применяет kotlin-dsl, необходимо обновить присваивание свойств и использовать функцию .set().
Gradle
Kotlin 2.1.20 полностью совместим с Gradle начиная с версии 7.6.3 и заканчивая 8.11. Также можно использовать более новые версии Gradle, вплоть до последнего выпуска. Однако учтите, что это может привести к предупреждениям об устаревших возможностях, а некоторые новые функции Gradle могут не работать.
Эта версия Kotlin обеспечивает совместимость плагинов Kotlin Gradle с Isolated Projects в Gradle, а также поддерживает пользовательские варианты публикации Gradle.
Плагины Kotlin Gradle совместимы с Isolated Projects в Gradle
Начиная с Kotlin 2.1.0, в проектах можно было предварительно опробовать функцию Isolated Projects в Gradle.
Раньше перед использованием этой функции требовалось настроить плагин Kotlin Gradle, чтобы обеспечить совместимость проекта с Isolated Projects. В Kotlin 2.1.20 этот дополнительный шаг больше не нужен.
Теперь, чтобы включить Isolated Projects, достаточно задать системное свойство.
Функция Isolated Projects в Gradle поддерживается плагинами Kotlin Gradle как в многоплатформенных проектах, так и в проектах только с целевой платформой JVM или Android.
В частности, если после обновления в многоплатформенном проекте возникнут проблемы со сборкой Gradle, можно отключить новое поведение плагина Kotlin Gradle, добавив:
kotlin.kmp.isolated-projects.support=disable
Однако при использовании этого свойства Gradle в многоплатформенном проекте функция Isolated Projects будет недоступна.
Расскажите о своем опыте использования этой возможности в YouTrack.
Поддержка добавления пользовательских вариантов публикации Gradle
В Kotlin 2.1.20 добавлена поддержка пользовательских вариантов публикации Gradle. Эта возможность доступна для многоплатформенных проектов и проектов для JVM.
Эта возможность является экспериментальной. Чтобы включить ее, используйте аннотацию @OptIn(ExperimentalKotlinGradlePluginApi::class).
Чтобы добавить пользовательский вариант публикации Gradle, вызовите функцию adhocSoftwareComponent(), которая возвращает экземпляр AdhocComponentWithVariants, который можно настроить с помощью Kotlin DSL:
plugins {
// Only JVM and Multiplatform are supported
kotlin("jvm")
// or
kotlin("multiplatform")
}
kotlin {
@OptIn(ExperimentalKotlinGradlePluginApi::class)
publishing {
// Returns an instance of AdhocSoftwareComponent
adhocSoftwareComponent()
// Alternatively, you can configure AdhocSoftwareComponent in the DSL block as follows
adhocSoftwareComponent {
// Add your custom variants here using the AdhocSoftwareComponent API
}
}
}
Стандартная библиотека
В этом выпуске в стандартную библиотеку добавлены новые экспериментальные возможности: общие атомарные типы, улучшенная поддержка UUID и новые функции отслеживания времени.
Общие атомарные типы
В Kotlin 2.1.20 в пакет kotlin.concurrent.atomics стандартной библиотеки добавлены общие атомарные типы, позволяющие использовать общий платформонезависимый код для потокобезопасных операций. Это упрощает разработку проектов Kotlin Multiplatform, поскольку больше не нужно дублировать логику, связанную с атомарными типами, в разных наборах исходного кода.
Пакет kotlin.concurrent.atomics и его свойства являются экспериментальными. Чтобы включить их, используйте аннотацию @OptIn(ExperimentalAtomicApi::class) или параметр компилятора -opt-in=kotlin.ExperimentalAtomicApi.
Вот пример использования AtomicInt для безопасного подсчета обработанных элементов в нескольких потоках:
// Imports the necessary libraries
import kotlin.concurrent.atomics.*
import kotlinx.coroutines.*
//sampleStart
@OptIn(ExperimentalAtomicApi::class)
suspend fun main() {
// Initializes the atomic counter for processed items
var processedItems = AtomicInt(0)
val totalItems = 100
val items = List(totalItems) { "item$it" }
// Splits the items into chunks for processing by multiple coroutines
val chunkSize = 20
val itemChunks = items.chunked(chunkSize)
coroutineScope {
for (chunk in itemChunks) {
launch {
for (item in chunk) {
println("Processing $item in thread ${Thread.currentThread()}")
processedItems += 1 // Increment counter atomically
}
}
}
}
//sampleEnd
// Prints the total number of processed items
println("Total processed items: ${processedItems.load()}")
}
Для обеспечения бесшовного взаимодействия атомарных типов Kotlin с атомарными типами Java java.util.concurrent.atomic API предоставляет функции-расширения .asJavaAtomic() и .asKotlinAtomic(). В JVM атомарные типы Kotlin и Java во время выполнения являются одним и тем же типом, поэтому их можно преобразовывать друг в друга без дополнительных затрат.
Вот пример совместного использования атомарных типов Kotlin и Java:
// Imports the necessary libraries
import kotlin.concurrent.atomics.*
import java.util.concurrent.atomic.*
//sampleStart
@OptIn(ExperimentalAtomicApi::class)
fun main() {
// Converts Kotlin's AtomicInt to Java's AtomicInteger
val kotlinAtomic = AtomicInt(42)
val javaAtomic: AtomicInteger = kotlinAtomic.asJavaAtomic()
println("Java atomic value: ${javaAtomic.get()}")
// Java atomic value: 42
// Converts Java's AtomicInteger back to Kotlin's AtomicInt
val kotlinAgain: AtomicInt = javaAtomic.asKotlinAtomic()
println("Kotlin atomic value: ${kotlinAgain.load()}")
// Kotlin atomic value: 42
}
//sampleEnd
Изменения в разборе, форматировании и сравнении UUID
Команда JetBrains продолжает улучшать поддержку UUID, добавленных в стандартную библиотеку в версии 2.0.20.
Раньше функция parse() принимала UUID только в формате с шестнадцатеричными символами и дефисами. В Kotlin 2.1.20 функцию parse() можно использовать для обоих форматов: с шестнадцатеричными символами и дефисами и обычного шестнадцатеричного (без дефисов).
В этом выпуске также добавлены функции для операций с форматом, содержащим шестнадцатеричные символы и дефисы:
parseHexDash()разбирает UUID из формата с шестнадцатеричными символами и дефисами.toHexDashString()преобразуетUuidвStringв формате с шестнадцатеричными символами и дефисами (повторяя функциональностьtoString()).
Эти функции работают аналогично parseHex() и toHexString(), которые были добавлены ранее для шестнадцатеричного формата. Явные названия функций разбора и форматирования должны сделать код понятнее и упростить работу с UUID.
UUID в Kotlin теперь Comparable. Начиная с Kotlin 2.1.20, значения типа Uuid можно напрямую сравнивать и сортировать. Благодаря этому можно использовать операторы < и >, а также расширения стандартной библиотеки, доступные только для типов Comparable или их коллекций (например, sorted()). Кроме того, UUID можно передавать в любые функции и API, требующие интерфейс Comparable.
Обратите внимание: поддержка UUID в стандартной библиотеке все еще является экспериментальной. Чтобы включить ее, используйте аннотацию @OptIn(ExperimentalUuidApi::class) или параметр компилятора -opt-in=kotlin.uuid.ExperimentalUuidApi:
import kotlin.uuid.ExperimentalUuidApi
import kotlin.uuid.Uuid
//sampleStart
@OptIn(ExperimentalUuidApi::class)
fun main() {
// parse() accepts a UUID in a plain hexadecimal format
val uuid = Uuid.parse("550e8400e29b41d4a716446655440000")
// Converts it to the hex-and-dash format
val hexDashFormat = uuid.toHexDashString()
// Outputs the UUID in the hex-and-dash format
println(hexDashFormat)
// Outputs UUIDs in ascending order
println(
listOf(
uuid,
Uuid.parse("780e8400e29b41d4a716446655440005"),
Uuid.parse("5ab88400e29b41d4a716446655440076")
).sorted()
)
}
//sampleEnd
Новые возможности отслеживания времени
Начиная с Kotlin 2.1.20, стандартная библиотека позволяет представлять момент времени. Раньше эта возможность была доступна только в kotlinx-datetime — официальной библиотеке Kotlin.
Интерфейс kotlinx.datetime.Clock добавлен в стандартную библиотеку под именем kotlin.time.Clock, а класс kotlinx.datetime.Instant — под именем kotlin.time.Instant. Эти понятия естественно дополняют пакет time стандартной библиотеки, поскольку они связаны только с моментами времени, тогда как более сложные возможности для работы с календарями и часовыми поясами по-прежнему доступны в kotlinx-datetime.
Instant и Clock полезны, когда нужно точно отслеживать время без учета часовых поясов и дат. Например, их можно использовать для регистрации событий с временными метками, измерения длительности между двумя моментами времени и получения текущего момента для системных процессов.
Для взаимодействия с другими языками доступны дополнительные функции преобразования:
.toKotlinInstant()преобразует значение времени в экземплярkotlin.time.Instant..toJavaInstant()преобразует значениеkotlin.time.Instantв значениеjava.time.Instant.Instant.toJSDate()преобразует значениеkotlin.time.Instantв экземпляр класса JSDate. Это преобразование не является точным: в JS для представления дат используется точность до миллисекунд, тогда как Kotlin поддерживает точность до наносекунд.
Новые возможности работы со временем в стандартной библиотеке все еще являются экспериментальными. Чтобы включить их, используйте аннотацию @OptIn(ExperimentalTime::class):
import kotlin.time.*
@OptIn(ExperimentalTime::class)
fun main() {
// Get the current moment in time
val currentInstant = Clock.System.now()
println("Current time: $currentInstant")
// Find the difference between two moments in time
val pastInstant = Instant.parse("2023-01-01T00:00:00Z")
val duration = currentInstant - pastInstant
println("Time elapsed since 2023-01-01: $duration")
}
Подробнее о реализации см. в предложении KEEP.
Компилятор Compose
В версии 2.1.20 компилятор Compose ослабляет некоторые ограничения на функции @Composable, введенные в предыдущих выпусках. Кроме того, для плагина компилятора Compose Gradle по умолчанию включен сбор информации об исходном коде, что позволяет обеспечить одинаковое поведение на всех платформах и Android.
Поддержка параметров со значениями по умолчанию в открытых функциях @Composable
Ранее компилятор запрещал использовать параметры со значениями по умолчанию в открытых функциях @Composable из-за некорректного результата компиляции, который приводил к сбоям во время выполнения. Теперь основная проблема устранена, и параметры со значениями по умолчанию полностью поддерживаются при использовании Kotlin 2.1.20 или более новой версии.
Компилятор Compose разрешал использовать параметры со значениями по умолчанию в открытых функциях до версии 1.5.8, поэтому поддержка зависит от конфигурации проекта:
Если открытая компонуемая функция компилируется с помощью Kotlin версии 2.1.20 или более новой, компилятор создает корректные обертки для параметров со значениями по умолчанию. Сюда входят обертки, совместимые с бинарными файлами, созданными до версии 1.5.8, а значит, использовать эту открытую функцию смогут и нижестоящие библиотеки.
Если открытая компонуемая функция компилируется с помощью версии Kotlin ниже 2.1.20, Compose использует режим совместимости, который может привести к сбоям во время выполнения. При использовании режима совместимости компилятор выдает предупреждение о возможных проблемах.
Переопределенным функциям разрешено быть перезапускаемыми в final-классах
Виртуальные функции (переопределения open и abstract, включая интерфейсы) с выпуском 2.1.0 были принудительно сделаны неперезапускаемыми. Теперь это ограничение снято для функций, которые являются членами final-классов или сами являются final, — они будут перезапускаться или пропускаться, как обычно.
После обновления до Kotlin 2.1.20 вы можете заметить изменения в поведении затронутых функций. Чтобы сохранить неперезапускаемую логику из предыдущей версии, добавьте к функции аннотацию @NonRestartableComposable.
ComposableSingletons удален из общедоступного API
ComposableSingletons — это класс, который компилятор Compose создает при оптимизации лямбд @Composable. Лямбды, не захватывающие параметры, выделяются один раз и кэшируются в свойстве класса, что позволяет сократить количество выделений памяти во время выполнения. Класс создается с внутренней видимостью и предназначен только для оптимизации лямбд в пределах единицы компиляции (обычно файла).
Однако эта оптимизация также применялась к телам функций inline, из-за чего экземпляры лямбд-одиночек попадали в общедоступный API. Чтобы решить эту проблему, начиная с версии 2.1.20 лямбды @Composable больше не оптимизируются до одиночек внутри inline-функций. При этом компилятор Compose продолжит генерировать классы-одиночки и лямбды для inline-функций, чтобы обеспечить бинарную совместимость модулей, скомпилированных по прежней модели.
Сбор информации об исходном коде включен по умолчанию
В плагине компилятора Compose Gradle уже включена по умолчанию функция сбора информации об исходном коде для Android. Начиная с Kotlin 2.1.20 эта функция будет включена по умолчанию на всех платформах.
Проверьте, не задаете ли вы этот параметр с помощью freeCompilerArgs. Этот способ может привести к сбою сборки при одновременном использовании плагина, поскольку параметр фактически задается дважды.
Несовместимые изменения и устаревшие элементы
Чтобы подготовить Kotlin Multiplatform к предстоящим изменениям в Gradle, мы постепенно отказываемся от функции
withJava(). Теперь наборы исходного кода Java создаются по умолчанию. Если вы используете плагин Gradle Java test fixtures, сразу обновитесь до Kotlin 2.1.21, чтобы избежать проблем совместимости.Команда JetBrains продолжает процесс отказа от плагина
kotlin-android-extensions. При попытке использовать его в проекте теперь возникает ошибка конфигурации, и код плагина не выполняется.Устаревшее свойство
kotlin.incremental.classpath.snapshot.enabledудалено из плагина Kotlin Gradle. Раньше это свойство позволяло использовать встроенный снимок ABI для JVM в качестве резервного варианта. Теперь плагин использует другие методы для обнаружения и предотвращения ненужной повторной компиляции, поэтому это свойство больше не нужно.
Обновления документации
В документации Kotlin появились заметные изменения:
Обновленные и новые страницы
Дорожная карта Kotlin — ознакомьтесь с обновленным списком приоритетов развития языка и экосистемы Kotlin.
Страница Рекомендации по работе с Gradle — узнайте о важных рекомендациях по оптимизации сборок Gradle и повышению производительности.
Compose Multiplatform и Jetpack Compose — обзор взаимосвязи между двумя UI-фреймворками.
Kotlin Multiplatform и Flutter — сравнение двух популярных кроссплатформенных фреймворков.
Взаимодействие с C — подробнее о взаимодействии Kotlin с C.
Числа — узнайте о различных типах Kotlin для представления чисел.
Новые и обновленные руководства
Публикация библиотеки в Maven Central — узнайте, как публиковать артефакты библиотек KMP в самом популярном репозитории Maven.
Kotlin/Native в виде динамической библиотеки — создайте динамическую библиотеку Kotlin.
Kotlin/Native в виде фреймворка Apple — создайте собственный фреймворк и используйте код Kotlin/Native в приложениях Swift/Objective-C для macOS и iOS.
Как обновиться до Kotlin 2.1.20
Начиная с IntelliJ IDEA 2023.3 и Android Studio Iguana (2023.2.1) Canary 15, плагин Kotlin распространяется как встроенный плагин, включенный в IDE. Это значит, что установить плагин из JetBrains Marketplace больше нельзя.
Чтобы обновиться до новой версии Kotlin, измените версию Kotlin на 2.1.20 в скриптах сборки.
© 2010–2026 JetBrains s.r.o. and Kotlin Programming Language contributors
Licensed under the Apache License, Version 2.0.
https://kotlinlang.org/docs/whatsnew2120.html