Что нового в Kotlin 1.6.20
В Kotlin 1.6.20 представлены предварительные версии будущих возможностей языка, иерархическая структура используется по умолчанию в мультиплатформенных проектах, а также внесены эволюционные улучшения в другие компоненты.
Краткий обзор изменений также можно посмотреть в этом видео:
Язык
В Kotlin 1.6.20 можно попробовать две новые возможности языка:
Прототип контекстных получателей для Kotlin/JVM
В Kotlin 1.6.20 вы больше не ограничены одним получателем. Если вам нужно больше, вы можете сделать функции, свойства и классы зависимыми от контекста (или контекстными), добавив контекстные получатели в их объявления. Контекстное объявление выполняет следующие действия:
Оно требует, чтобы все объявленные контекстные получатели присутствовали в области видимости вызывающего кода в качестве неявных получателей.
Оно добавляет объявленные контекстные получатели в область видимости тела в качестве неявных получателей.
interface LoggingContext {
val log: Logger // This context provides a reference to a logger
}
context(LoggingContext)
fun startBusinessOperation() {
// You can access the log property since LoggingContext is an implicit receiver
log.info("Operation has started")
}
fun test(loggingContext: LoggingContext) {
with(loggingContext) {
// You need to have LoggingContext in a scope as an implicit receiver
// to call startBusinessOperation()
startBusinessOperation()
}
}
Чтобы включить контекстные получатели в проекте, используйте параметр компилятора -Xcontext-receivers. Подробное описание этой возможности и её синтаксиса см. в KEEP.
Обратите внимание, что эта реализация является прототипом:
Если включить
-Xcontext-receivers, компилятор будет создавать предварительные бинарные файлы, которые нельзя использовать в производственном кодеНа данный момент поддержка контекстных получателей в IDE минимальна
Попробуйте эту возможность в учебных проектах и поделитесь с нами своими мыслями и опытом в этой задаче YouTrack. Если вы столкнётесь с проблемами, создайте новую задачу.
Определённо не допускающие null типы
Для обеспечения лучшей совместимости при расширении обобщённых классов и интерфейсов Java в Kotlin 1.6.20 можно пометить параметр обобщённого типа как определённо не допускающий null в месте использования с помощью нового синтаксиса T & Any. Эта синтаксическая форма основана на обозначении типов-пересечений и теперь применяется только к параметру типа с допускаемыми null верхними границами слева от & и не допускающим null Any справа:
fun <T> elvisLike(x: T, y: T & Any): T & Any = x ?: y
fun main() {
// OK
elvisLike<String>("", "").length
// Error: 'null' cannot be a value of a non-null type
elvisLike<String>("", null).length
// OK
elvisLike<String?>(null, "").length
// Error: 'null' cannot be a value of a non-null type
elvisLike<String?>(null, null).length
}
Чтобы включить эту возможность, установите версию языка 1.7:
kotlin {
sourceSets.all {
languageSettings.apply {
languageVersion = "1.7"
}
}
}
kotlin {
sourceSets.all {
languageSettings {
languageVersion = '1.7'
}
}
}
Подробнее об определённо не допускающих null типах см. в KEEP.
Kotlin/JVM
В Kotlin 1.6.20 появились:
Улучшения совместимости методов по умолчанию в интерфейсах JVM: новая аннотация
@JvmDefaultWithCompatibilityдля интерфейсов и изменения совместимости в режимах-Xjvm-defaultПоддержка параллельной компиляции одного модуля в бэкенде JVM
Новая аннотация @JvmDefaultWithCompatibility для интерфейсов
В Kotlin 1.6.20 появилась новая аннотация @JvmDefaultWithCompatibility: используйте её вместе с параметром компилятора -Xjvm-default=all, чтобы создавать метод по умолчанию в интерфейсе JVM для любого неабстрактного члена любого интерфейса Kotlin.
Если существуют клиенты, использующие ваши интерфейсы Kotlin, скомпилированные без параметра -Xjvm-default=all, их бинарные файлы могут быть несовместимы с кодом, скомпилированным с этим параметром. До Kotlin 1.6.20, чтобы избежать этой проблемы совместимости, рекомендуемым подходом было использовать режим -Xjvm-default=all-compatibility, а также аннотацию @JvmDefaultWithoutCompatibility для интерфейсов, которым не требовался такой тип совместимости.
У этого подхода были некоторые недостатки:
Можно было легко забыть добавить аннотацию при добавлении нового интерфейса.
Обычно в непубличных частях кода интерфейсов больше, чем в публичном API, поэтому в итоге эту аннотацию приходилось использовать во многих местах кода.
Теперь можно использовать режим -Xjvm-default=all и помечать интерфейсы аннотацией @JvmDefaultWithCompatibility. Это позволяет один раз добавить эту аннотацию ко всем интерфейсам публичного API, а для нового непубличного кода аннотации не понадобятся.
Оставьте отзыв о новой аннотации в этой задаче YouTrack.
Изменения совместимости в режимах -Xjvm-default
В Kotlin 1.6.20 добавлена возможность компилировать модули в режиме по умолчанию (параметр компилятора -Xjvm-default=disable) с модулями, скомпилированными в режимах -Xjvm-default=all или -Xjvm-default=all-compatibility. Как и прежде, компиляция также будет успешной, если все модули используют режимы -Xjvm-default=all или -Xjvm-default=all-compatibility. Оставить отзыв можно в этой задаче YouTrack.
В Kotlin 1.6.20 режимы compatibility и enable параметра компилятора -Xjvm-default объявлены устаревшими. В описания других режимов внесены изменения, касающиеся совместимости, но общая логика осталась прежней. Ознакомьтесь с обновлёнными описаниями.
Дополнительную информацию о методах по умолчанию при взаимодействии с Java см. в документации по взаимодействию и этой записи в блоге.
Поддержка параллельной компиляции одного модуля в бэкенде JVM
Мы продолжаем работу над тем, чтобы ускорить компиляцию в новом бэкенде JVM IR. В Kotlin 1.6.20 мы добавили экспериментальный режим бэкенда JVM IR, который компилирует все файлы модуля параллельно. Параллельная компиляция может сократить общее время компиляции до 15%.
Включите экспериментальный режим параллельного бэкенда с помощью параметра компилятора -Xbackend-threads. Для этого параметра используйте следующие аргументы:
N— количество потоков, которое вы хотите использовать. Оно не должно превышать количество ядер процессора; иначе параллелизация теряет эффективность из-за переключения контекста между потоками0— использовать отдельный поток для каждого ядра процессора
Gradle может выполнять задачи параллельно, но такой вид параллелизации не сильно помогает, если с точки зрения Gradle проект (или его значительная часть) представляет собой одну большую задачу. Если у вас очень большой монолитный модуль, используйте параллельную компиляцию, чтобы ускорить её. Если проект состоит из множества небольших модулей и сборка распараллелена средствами Gradle, дополнительный уровень параллелизации может снизить производительность из-за переключения контекста.
Поддержка ссылок на конструкторы функциональных интерфейсов
Поддержка ссылок на вызываемые объекты для конструкторов функциональных интерфейсов позволяет перейти с интерфейса с функцией-конструктором на функциональный интерфейс без нарушения совместимости исходного кода.
Рассмотрим следующий код:
interface Printer {
fun print()
}
fun Printer(block: () -> Unit): Printer = object : Printer { override fun print() = block() }
Если включить поддержку ссылок на конструкторы функциональных интерфейсов, этот код можно заменить одним лишь объявлением функционального интерфейса:
fun interface Printer {
fun print()
}
Его конструктор будет создан неявно, и любой код, использующий ссылку на функцию ::Printer, скомпилируется. Например:
documentsStorage.addPrinter(::Printer)
Сохраните бинарную совместимость, пометив устаревшую функцию Printer аннотацией @Deprecated с параметром DeprecationLevel.HIDDEN:
@Deprecated(message = "Your message about the deprecation", level = DeprecationLevel.HIDDEN)
fun Printer(...) {...}
Используйте параметр компилятора -XXLanguage:+KotlinFunInterfaceConstructorReference, чтобы включить эту возможность.
Kotlin/Native
В Kotlin/Native 1.6.20 продолжается разработка новых компонентов. Мы сделали ещё один шаг к единообразию работы с Kotlin на других платформах:
Параллельная реализация фазы очистки в новом менеджере памяти
Взаимодействие со Swift async/await: возврат Swift Void вместо KotlinUnit
Обновление нового менеджера памяти
В Kotlin 1.6.20 можно попробовать альфа-версию нового менеджера памяти Kotlin/Native. Он устраняет различия между платформами JVM и Native, обеспечивая единообразный опыт разработки в мультиплатформенных проектах. Например, вам будет гораздо проще создавать новые кроссплатформенные мобильные приложения для Android и iOS.
Новый менеджер памяти Kotlin/Native снимает ограничения на совместное использование объектов между потоками. Он также предоставляет безопасные примитивы для параллельного программирования, не допускающие утечек памяти и не требующие особого управления или аннотаций.
В будущих версиях новый менеджер памяти станет стандартным, поэтому мы рекомендуем попробовать его уже сейчас. Подробнее о новом менеджере памяти и демонстрационных проектах читайте в нашей публикации в блоге или сразу перейдите к инструкциям по миграции, чтобы попробовать его самостоятельно.
Попробуйте новый менеджер памяти в своих проектах и расскажите, как он работает, в нашем трекере задач YouTrack.
Параллельная реализация фазы очистки в новом менеджере памяти
Если вы уже перешли на наш новый менеджер памяти, представленный в Kotlin 1.6, вы могли заметить значительное сокращение времени выполнения: наши тесты производительности показывают среднее улучшение на 35%. Начиная с версии 1.6.20 в новом менеджере памяти также доступна параллельная реализация фазы очистки. Это должно повысить производительность и сократить продолжительность пауз сборщика мусора.
Чтобы включить эту функцию для нового менеджера памяти Kotlin/Native, передайте следующий параметр компилятора:
-Xgc=cms
Поделитесь отзывами о производительности нового менеджера памяти в этой задаче в YouTrack.
Создание экземпляров классов аннотаций
В Kotlin 1.6.0 создание экземпляров классов аннотаций стало стабильным для Kotlin/JVM и Kotlin/JS. В версии 1.6.20 добавлена поддержка Kotlin/Native.
Подробнее о создании экземпляров классов аннотаций.
Взаимодействие со Swift async/await: возврат Void вместо KotlinUnit
Мы продолжили работу над экспериментальным взаимодействием со Swift async/await (доступно начиная со Swift 5.5). В Kotlin 1.6.20 изменился способ работы с функциями suspend с возвращаемым типом Unit.
Ранее такие функции представлялись в Swift как функции async, возвращающие KotlinUnit. Однако их правильный возвращаемый тип — Void, как и у несуспендируемых функций.
Чтобы не нарушать существующий код, мы добавляем свойство Gradle, которое позволяет компилятору преобразовывать suspend-функции, возвращающие Unit, в функции Swift async с возвращаемым типом Void:
# gradle.properties kotlin.native.binary.unitSuspendFunctionObjCExport=proper
В будущих выпусках Kotlin мы планируем сделать это поведение стандартным.
Более информативные трассировки стека с libbacktrace
Теперь Kotlin/Native может создавать подробные трассировки стека с указанием файлов и номеров строк, что упрощает отладку linux* (за исключением linuxMips32 и linuxMipsel32) и целевых платформ androidNative*.
Эта функция использует библиотеку libbacktrace. Посмотрите на пример ниже, чтобы увидеть разницу:
fun main() = bar()
fun bar() = baz()
inline fun baz() {
error("")
}
До версии 1.6.20:
Версия 1.6.20 с libbacktrace:
На целевых платформах Apple, где трассировки стека уже содержали расположение файлов и номера строк, libbacktrace предоставляет более подробную информацию о вызовах встроенных функций:
До версии 1.6.20:
Версия 1.6.20 с libbacktrace:
Чтобы получать более информативные трассировки стека с libbacktrace, добавьте следующую строку в gradle.properties:
# gradle.properties kotlin.native.binary.sourceInfoType=libbacktrace
Расскажите, насколько удобно вам отлаживать Kotlin/Native с libbacktrace, в этой задаче в YouTrack.
Поддержка автономных исполняемых файлов Android
Раньше Android Native исполняемые файлы в Kotlin/Native на самом деле не были исполняемыми файлами, а представляли собой разделяемые библиотеки, которые можно было использовать как NativeActivity. Теперь можно создавать стандартные исполняемые файлы для целевых платформ Android Native.
Для этого настройте блок executable целевой платформы androidNative в части build.gradle(.kts) вашего проекта. Добавьте следующий параметр для двоичного файла:
kotlin {
androidNativeX64("android") {
binaries {
executable {
binaryOptions["androidProgramType"] = "standalone"
}
}
}
}
Обратите внимание: в Kotlin 1.7.0 эта функция станет стандартной. Чтобы сохранить текущее поведение, используйте следующую настройку:
binaryOptions["androidProgramType"] = "nativeActivity"
Благодарим Mattia Iavarone за реализацию!
Повышение производительности
Мы активно работаем над Kotlin/Native, чтобы ускорить процесс компиляции и улучшить ваш опыт разработки.
В Kotlin 1.6.20 появились обновления производительности и исправления ошибок, влияющие на LLVM IR, генерируемый Kotlin. Согласно результатам тестирования наших внутренних проектов, среднее повышение производительности составило:
сокращение времени выполнения на 15%
сокращение размера кода на 20% как для выпускных, так и для отладочных двоичных файлов
сокращение времени компиляции выпускных двоичных файлов на 26%
Эти изменения также позволяют сократить время компиляции отладочного двоичного файла на 10% в крупном внутреннем проекте.
Для этого мы реализовали статическую инициализацию некоторых синтетических объектов, созданных компилятором, улучшили структуру LLVM IR для каждой функции и оптимизировали кэши компилятора.
Улучшена обработка ошибок при импорте модулей cinterop
В этом выпуске улучшена обработка ошибок, возникающих при импорте модуля Objective-C с помощью инструмента cinterop (как это обычно происходит с CocoaPods pod). Раньше при возникновении ошибки во время работы с модулем Objective-C (например, при ошибке компиляции заголовка) отображалось малоинформативное сообщение, например fatal error: could not build module $name. Мы доработали эту часть инструмента cinterop, поэтому теперь сообщение об ошибке содержит подробное описание.
Поддержка библиотек Xcode 13
В этом выпуске обеспечена полная поддержка библиотек, поставляемых с Xcode 13. Их можно использовать в любом месте кода Kotlin.
Kotlin Multiplatform
В версии 1.6.20 появились следующие важные обновления Kotlin Multiplatform:
Иерархическая структура теперь используется по умолчанию во всех новых мультиплатформенных проектах
В плагин Kotlin CocoaPods Gradle добавлено несколько полезных функций для интеграции с CocoaPods
Поддержка иерархической структуры в мультиплатформенных проектах
В Kotlin 1.6.20 поддержка иерархической структуры включена по умолчанию. С момента её появления в Kotlin 1.4.0 мы значительно улучшили frontend и обеспечили стабильный импорт в IDE.
Ранее код в мультиплатформенном проекте можно было добавить двумя способами. Первый — поместить его в набор исходного кода для конкретной платформы, который ограничен одной целевой платформой и не может использоваться повторно на других платформах. Второй — использовать общий набор исходного кода, доступный всем платформам, поддерживаемым Kotlin.
Теперь можно совместно использовать исходный код для нескольких схожих целевых платформ Native, использующих многие общие компоненты логики и сторонние API. Технология автоматически добавит правильные зависимости и определит точный набор API, доступный в общем коде. Это избавляет от сложной настройки сборки и обходных решений для поддержки совместного использования наборов исходного кода между целевыми платформами Native в IDE. Кроме того, это помогает предотвратить небезопасное использование API, предназначенных для другой целевой платформы.
Эта технология будет полезна и авторам библиотек: иерархическая структура проекта позволяет им публиковать и использовать библиотеки с общими API для подмножества целевых платформ.
По умолчанию библиотеки, опубликованные с иерархической структурой проекта, совместимы только с проектами, использующими иерархическую структуру.
Удобное совместное использование кода в проекте
Без поддержки иерархической структуры нет простого способа совместно использовать код для некоторых, но не всех целевых платформ Kotlin. Один из популярных примеров — совместное использование кода всеми целевыми платформами iOS с доступом к специфичным для iOS зависимостям, например Foundation.
Благодаря поддержке иерархической структуры проекта теперь это можно сделать без дополнительных настроек. В новой структуре наборы исходного кода образуют иерархию. Можно использовать специфичные для платформы языковые возможности и зависимости, доступные для каждой целевой платформы, для которой компилируется данный набор исходного кода.
Например, рассмотрим типичный мультиплатформенный проект с двумя целевыми платформами — iosArm64 и iosX64 для устройств и симуляторов iOS. Инструменты Kotlin распознают, что обе целевые платформы содержат одну и ту же функцию, и позволяют обращаться к ней из промежуточного набора исходного кода iosMain.

Инструментарий Kotlin автоматически добавляет правильные зависимости, например Kotlin/Native stdlib или библиотеки Native. Кроме того, инструменты Kotlin постараются точно определить набор API, доступный в общем коде. Это помогает избежать, например, использования специфичной для macOS функции в коде, предназначенном для Windows.
Больше возможностей для авторов библиотек
При публикации мультиплатформенной библиотеки API её промежуточных наборов исходного кода теперь публикуется вместе с ней и становится доступным пользователям. Инструментарий Kotlin автоматически определит API, доступный в наборе исходного кода проекта-потребителя, и проследит за тем, чтобы не использовались небезопасные возможности, например API для JVM в коде JS. Подробнее о совместном использовании кода в библиотеках.
Настройка
Начиная с Kotlin 1.6.20, во всех новых мультиплатформенных проектах будет использоваться иерархическая структура. Дополнительная настройка не требуется.
-
Если вы уже включили её вручную, можно удалить устаревшие параметры из
gradle.properties:# gradle.properties kotlin.mpp.enableGranularSourceSetsMetadata=true kotlin.native.enableDependencyPropagation=false // or 'true', depending on your previous setup
Для Kotlin 1.6.20 рекомендуем использовать Android Studio 2021.1.1 (Bumblebee) или более позднюю версию, чтобы получить наилучший результат.
-
Вы также можете отказаться от этой возможности. Чтобы отключить поддержку иерархической структуры, задайте следующие параметры в
gradle.properties:# gradle.properties kotlin.mpp.hierarchicalStructureSupport=false
Оставьте отзыв
Это важное изменение для всей экосистемы. Будем признательны за ваши отзывы — они помогут сделать её ещё лучше.
Попробуйте новую возможность и сообщите о возникших трудностях в наш трекер задач.
Плагин Kotlin CocoaPods Gradle
В Kotlin 1.6.20 появились следующие возможности, упрощающие интеграцию с CocoaPods:
-
Теперь плагин CocoaPods включает задачи для сборки XCFramework со всеми зарегистрированными целевыми платформами и создания файла Podspec. Это пригодится, если вы не хотите интегрироваться непосредственно с Xcode, но хотите собрать артефакты и развернуть их в локальном репозитории CocoaPods.
Подробнее о сборке XCFramework.
-
Если вы используете в своих проектах интеграцию с CocoaPods, то, вероятно, уже задаёте требуемую версию Pod для всего проекта Gradle. Теперь у вас больше вариантов:
Указать версию Pod непосредственно в блоке
cocoapodsПродолжить использовать версию проекта Gradle
Если ни одно из этих свойств не настроено, возникнет ошибка.
Теперь имя CocoaPod можно настроить в блоке
cocoapods, не меняя имя всего проекта Gradle.В плагине CocoaPods появилось новое свойство
extraSpecAttributes, которое позволяет настраивать свойства файла Podspec, ранее заданные жёстко, напримерlibrariesилиvendored_frameworks.
kotlin {
cocoapods {
version = "1.0"
name = "MyCocoaPod"
extraSpecAttributes["social_media_url"] = 'https://twitter.com/kotlin'
extraSpecAttributes["vendored_frameworks"] = 'CustomFramework.xcframework'
extraSpecAttributes["libraries"] = 'xml'
}
}
См. полный справочник DSL плагина Kotlin CocoaPods Gradle.
Kotlin/JS
Улучшения Kotlin/JS в версии 1.6.20 в основном затрагивают компилятор IR:
Инкрементальная компиляция для бинарных файлов разработки (IR)
Ленивая инициализация свойств верхнего уровня по умолчанию (IR)
Инкрементальная компиляция бинарных файлов разработки с компилятором IR
Чтобы сделать разработку на Kotlin/JS с компилятором IR эффективнее, мы добавляем новый режим инкрементальной компиляции.
При сборке бинарных файлов разработки с помощью задачи Gradle compileDevelopmentExecutableKotlinJs в этом режиме компилятор кэширует результаты предыдущих компиляций на уровне модуля. При последующих компиляциях он использует кэшированные результаты для неизменённых исходных файлов, благодаря чему сборка выполняется быстрее, особенно при небольших изменениях. Обратите внимание: это улучшение предназначено исключительно для процесса разработки (сокращения цикла «редактирование — сборка — отладка») и не влияет на сборку производственных артефактов.
Чтобы включить инкрементальную компиляцию бинарных файлов разработки, добавьте следующую строку в gradle.properties проекта:
# gradle.properties kotlin.incremental.js.ir=true // false by default
В наших тестовых проектах новый режим ускорил инкрементальную компиляцию на 30%. Однако чистая сборка в этом режиме стала медленнее из-за необходимости создавать и заполнять кэши.
Расскажите, что вы думаете об использовании инкрементальной компиляции в своих проектах Kotlin/JS, в этой задаче YouTrack.
Ленивая инициализация свойств верхнего уровня по умолчанию с компилятором IR
В Kotlin 1.4.30 мы представили прототип ленивой инициализации свойств верхнего уровня в компиляторе JS IR. Поскольку при запуске приложения больше не нужно инициализировать все свойства, ленивая инициализация сокращает время запуска. Наши измерения показали ускорение примерно на 10% в реальном приложении Kotlin/JS.
Теперь, после доработки и надлежащего тестирования этого механизма, мы делаем ленивую инициализацию свойств верхнего уровня поведением по умолчанию в компиляторе IR.
// lazy initialization
val a = run {
val result = // intensive computations
println(result)
result
} // run is executed upon the first usage of the variable
Если по какой-либо причине вам нужно инициализировать свойство без задержки (при запуске приложения), пометьте его аннотацией @EagerInitialization.
Отдельные JS-файлы для модулей проекта по умолчанию с компилятором IR
Ранее компилятор JS IR предоставлял возможность создавать отдельные файлы .js для модулей проекта. Это было альтернативой варианту по умолчанию — единому файлу .js для всего проекта. Такой файл может быть слишком большим и неудобным в использовании: каждый раз, когда вы хотите использовать функцию из своего проекта, вам приходится подключать весь JS-файл в качестве зависимости. Несколько файлов обеспечивают большую гибкость и уменьшают размер таких зависимостей. Эта возможность была доступна с параметром компилятора -Xir-per-module.
Начиная с версии 1.6.20 компилятор JS IR по умолчанию создаёт отдельные файлы .js для модулей проекта.
Компиляция проекта в один файл .js теперь доступна с помощью следующего свойства Gradle:
# gradle.properties kotlin.js.ir.output.granularity=whole-program // `per-module` is the default
В предыдущих выпусках экспериментальный режим для каждого модуля (доступный с помощью флага -Xir-per-module=true) вызывал функции main() в каждом модуле. Это не соответствовало обычному режиму с одним файлом .js. Начиная с версии 1.6.20 функция main() в обоих случаях будет вызываться только в главном модуле. Если вам нужно выполнить код при загрузке модуля, можно использовать свойства верхнего уровня с аннотацией @EagerInitialization. См. раздел Ленивая инициализация свойств верхнего уровня по умолчанию (IR).
Оптимизация класса Char
Теперь класс Char обрабатывается компилятором Kotlin/JS без создания обёртки (как и inline-классы). Это ускоряет операции с символами в коде Kotlin/JS.
Помимо повышения производительности, это меняет способ экспорта Char в JavaScript: теперь он преобразуется в Number.
Улучшения экспорта и генерации объявлений TypeScript
В Kotlin 1.6.20 внесено несколько исправлений и улучшений в механизм экспорта (аннотация @JsExport), включая генерацию объявлений TypeScript (.d.ts). Мы добавили возможность экспортировать интерфейсы и перечисления, а также исправили поведение экспорта в некоторых особых случаях, о которых нам сообщали ранее. Подробнее см. в списке улучшений экспорта в YouTrack.
Подробнее об использовании кода Kotlin из JavaScript.
Гарантии @AfterTest для асинхронных тестов
В Kotlin 1.6.20 функции @AfterTest корректно работают с асинхронными тестами в Kotlin/JS. Если тип возвращаемого значения тестовой функции статически определён как Promise, компилятор теперь планирует выполнение функции @AfterTest в соответствующем обработчике then().
Безопасность
В Kotlin 1.6.20 добавлено несколько возможностей для повышения безопасности вашего кода:
Использование относительных путей в klib
Библиотека в формате klib содержит сериализованное представление IR исходных файлов, включая пути к ним, необходимые для создания корректной отладочной информации. До Kotlin 1.6.20 пути к файлам сохранялись как абсолютные. Поскольку автор библиотеки может не захотеть раскрывать абсолютные пути, в версии 1.6.20 появилась альтернативная возможность.
Если вы публикуете klib и хотите использовать в артефакте только относительные пути к исходным файлам, теперь можно передать параметр компилятора -Xklib-relative-path-base с одним или несколькими базовыми путями к исходным файлам:
tasks.withType(org.jetbrains.kotlin.gradle.dsl.KotlinCompile::class).configureEach {
// $base is a base path of source files
kotlinOptions.freeCompilerArgs += "-Xklib-relative-path-base=$base"
}
tasks.withType(org.jetbrains.kotlin.gradle.dsl.KotlinCompile).configureEach {
kotlinOptions {
// $base is a base path of source files
freeCompilerArgs += "-Xklib-relative-path-base=$base"
}
}
Сохранение yarn.lock для проектов Kotlin/JS на Gradle
Плагин Kotlin/JS для Gradle теперь позволяет сохранять файл yarn.lock, благодаря чему можно фиксировать версии зависимостей npm для проекта без дополнительной настройки Gradle. Эта возможность меняет структуру проекта по умолчанию: в корень проекта добавляется автоматически созданный каталог kotlin-js-store, содержащий файл yarn.lock.
Мы настоятельно рекомендуем добавлять каталог kotlin-js-store и его содержимое в систему контроля версий. Добавление файлов блокировки в систему контроля версий — это рекомендуемая практика, поскольку она гарантирует, что приложение будет собираться с одним и тем же деревом зависимостей на всех компьютерах, будь то среды разработки на других компьютерах или службы CI/CD. Файлы блокировки также предотвращают незаметное обновление зависимостей npm при извлечении проекта на новый компьютер, что представляет собой угрозу безопасности.
Такие инструменты, как Dependabot, также могут анализировать файлы yarn.lock проектов Kotlin/JS и предупреждать вас, если какой-либо используемый пакет npm скомпрометирован.
При необходимости можно изменить имена каталога и файла блокировки в скрипте сборки:
rootProject.plugins.withType<org.jetbrains.kotlin.gradle.targets.js.yarn.YarnPlugin> {
rootProject.the<org.jetbrains.kotlin.gradle.targets.js.yarn.YarnRootExtension>().lockFileDirectory =
project.rootDir.resolve("my-kotlin-js-store")
rootProject.the<org.jetbrains.kotlin.gradle.targets.js.yarn.YarnRootExtension>().lockFileName = "my-yarn.lock"
}
rootProject.plugins.withType(org.jetbrains.kotlin.gradle.targets.js.yarn.YarnPlugin) {
rootProject.extensions.getByType(org.jetbrains.kotlin.gradle.targets.js.yarn.YarnRootExtension).lockFileDirectory =
file("my-kotlin-js-store")
rootProject.extensions.getByType(org.jetbrains.kotlin.gradle.targets.js.yarn.YarnRootExtension).lockFileName = 'my-yarn.lock'
}
Установка зависимостей npm с --ignore-scripts по умолчанию
Теперь плагин Kotlin/JS для Gradle по умолчанию запрещает выполнение скриптов жизненного цикла во время установки зависимостей npm. Это изменение направлено на снижение вероятности выполнения вредоносного кода из скомпрометированных пакетов npm.
Чтобы вернуться к прежней конфигурации, можно явно разрешить выполнение скриптов жизненного цикла, добавив следующие строки в build.gradle(.kts):
rootProject.plugins.withType<org.jetbrains.kotlin.gradle.targets.js.yarn.YarnPlugin> {
rootProject.the<org.jetbrains.kotlin.gradle.targets.js.yarn.YarnRootExtension>().ignoreScripts = false
}
rootProject.plugins.withType(org.jetbrains.kotlin.gradle.targets.js.yarn.YarnPlugin) {
rootProject.extensions.getByType(org.jetbrains.kotlin.gradle.targets.js.yarn.YarnRootExtension).ignoreScripts = false
}
Подробнее о зависимостях npm проекта Kotlin/JS на Gradle.
Gradle
В Kotlin 1.6.20 внесены следующие изменения в плагин Kotlin для Gradle:
Новые свойства
kotlin.compiler.execution.strategyиcompilerExecutionStrategyдля задания стратегии выполнения компилятора KotlinУстаревание параметров
kapt.use.worker.api,kotlin.experimental.coroutinesиkotlin.coroutines
Свойства для задания стратегии выполнения компилятора Kotlin
До Kotlin 1.6.20 для задания стратегии выполнения компилятора Kotlin использовалось системное свойство -Dkotlin.compiler.execution.strategy. В некоторых случаях это свойство могло быть неудобным. В Kotlin 1.6.20 появилось свойство Gradle с тем же именем, kotlin.compiler.execution.strategy, и свойство задачи компиляции compilerExecutionStrategy.
Системное свойство по-прежнему работает, но в будущих выпусках будет удалено.
Текущий приоритет свойств выглядит следующим образом:
Свойство задачи
compilerExecutionStrategyимеет приоритет над системным свойством и свойством Gradlekotlin.compiler.execution.strategy.Свойство Gradle имеет приоритет над системным свойством.
Для этих свойств можно задать одну из трёх стратегий выполнения компилятора:
Стратегия |
Где выполняется компилятор Kotlin |
Инкрементальная компиляция |
Другие характеристики |
|---|---|---|---|
Демон |
В отдельном процессе демона |
Да |
Стратегия по умолчанию. Может использоваться совместно разными демонами Gradle |
В процессе |
В процессе демона Gradle |
Нет |
Может использовать кучу совместно с демоном Gradle |
Вне процесса |
В отдельном процессе для каждого вызова |
Нет |
— |
Соответственно, допустимые значения для свойств kotlin.compiler.execution.strategy (как системного, так и Gradle) следующие:
daemon(по умолчанию)in-processout-of-process
Используйте свойство Gradle kotlin.compiler.execution.strategy в gradle.properties:
# gradle.properties kotlin.compiler.execution.strategy=out-of-process
Допустимые значения для свойства задачи compilerExecutionStrategy:
org.jetbrains.kotlin.gradle.tasks.KotlinCompilerExecutionStrategy.DAEMON(по умолчанию)org.jetbrains.kotlin.gradle.tasks.KotlinCompilerExecutionStrategy.IN_PROCESSorg.jetbrains.kotlin.gradle.tasks.KotlinCompilerExecutionStrategy.OUT_OF_PROCESS
Используйте свойство задачи compilerExecutionStrategy в скрипте сборки build.gradle.kts:
import org.jetbrains.kotlin.gradle.dsl.KotlinCompile
import org.jetbrains.kotlin.gradle.tasks.KotlinCompilerExecutionStrategy
// ...
tasks.withType<KotlinCompile>().configureEach {
compilerExecutionStrategy.set(KotlinCompilerExecutionStrategy.IN_PROCESS)
}
Оставьте свой отзыв в этой задаче YouTrack.
Устаревание параметров сборки для kapt и корутин
В Kotlin 1.6.20 изменены уровни устаревания следующих свойств:
-
Мы объявили устаревшей возможность запускать kapt через демон Kotlin с помощью
kapt.use.worker.api— теперь об этом выводится предупреждение в журнал Gradle. Начиная с версии 1.3.70 по умолчанию kapt использует рабочие процессы Gradle, и мы рекомендуем пользоваться именно этим способом.В будущих выпусках мы собираемся удалить параметр
kapt.use.worker.api. -
Мы объявили устаревшими параметр DSL Gradle
kotlin.experimental.coroutinesи свойствоkotlin.coroutines, используемое вgradle.properties. Просто используйте приостанавливаемые функции или добавьте зависимостьkotlinx.coroutinesв файлbuild.gradle(.kts).Подробнее о корутинах см. в руководстве по корутинам.
Удаление параметра сборки kotlin.parallel.tasks.in.project
В Kotlin 1.5.20 мы объявили параметр сборки kotlin.parallel.tasks.in.project устаревшим. Этот параметр удалён в Kotlin 1.6.20.
В зависимости от проекта параллельная компиляция в демоне Kotlin может потребовать больше памяти. Чтобы уменьшить потребление памяти, увеличьте размер кучи для демона Kotlin.
Подробнее о поддерживаемых в настоящее время параметрах компилятора в плагине Kotlin для Gradle.
© 2010–2026 JetBrains s.r.o. and Kotlin Programming Language contributors
Licensed under the Apache License, Version 2.0.
https://kotlinlang.org/docs/whatsnew1620.html