Что нового в Kotlin 1.6.20
Дата выпуска: 4 апреля 2022 года
Kotlin 1.6.20 предоставляет предварительные версии будущих языковых функций, устанавливает иерархическую структуру в качестве значения по умолчанию для проектов multiplatform и вносит эволюционные улучшения в другие компоненты.
Также вы можете ознакомиться с кратким обзором изменений в этом видео:
Язык
В 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 задаче. Если у вас возникнут проблемы, пожалуйста, создайте новую задачу.
Определённо не-nullable типы
Для лучшей взаимозаменяемости при расширении дженериков Java-классов и интерфейсов, Kotlin 1.6.20 позволяет пометить дженерический параметр типа как определённо не-nullable на месте использования с новым синтаксисом T & Any. Синтаксическая форма происходит от записи пересекающихся типов и сейчас ограничена параметром типа с nullable верхними границами слева от & и не-nullable 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'
}
}
}
Узнайте больше об определённо не-nullable типах в 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
Улучшенная обработка ошибок во время импорта модулей cinterop
Обновление нового менеджера памяти
С 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, которое заставляет компилятор переводить Unit-возвращающие подчинённые функции в async Swift с типом возврата 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.
Для этого в части build.gradle(.kts) вашего проекта настройте блок исполняемого файла для вашей androidNative цели. Добавьте следующий параметр для бинарных файлов:
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). Ранее, если при работе с модулем Objective-C возникала ошибка (например, при возникновении ошибки компиляции в заголовке), вы получали неинформативное сообщение об ошибке, например, fatal error: could not build module $name. Мы расширили этот раздел инструмента cinterop, поэтому вы получите сообщение об ошибке с расширенным описанием.
Поддержка библиотек Xcode 13
Библиотеки, поставляемые с Xcode 13, полностью поддерживаются с данным релизом. Вы можете их использовать в любом месте своего кода Kotlin.
Kotlin Multiplatform
1.6.20 включает следующие заметные обновления для Kotlin Multiplatform:
Поддержка иерархической структуры теперь по умолчанию для всех новых проектов multiplatform
Плагин Kotlin CocoaPods Gradle получил несколько полезных функций для интеграции с CocoaPods
Поддержка иерархической структуры для проектов multiplatform
Kotlin 1.6.20 поставляется с поддержкой иерархической структуры, включенной по умолчанию. Начиная с ее введения в Kotlin 1.4.0, мы значительно улучшили интерфейс и сделали импорт в IDE стабильным.
Ранее существовало два способа добавления кода в проект multiplatform. Первый — вставить его в платформенно-специфический набор исходных файлов, ограниченный одной целью и непереиспользуемый другими платформами. Второй — использовать общий набор исходных файлов, используемый всеми платформами, которые в настоящее время поддерживаются Kotlin.
Теперь вы можете обмениваться исходным кодом между несколькими похожими целевыми платформами native, которые повторно используют много общей логики и API сторонних библиотек. Технология предоставит правильные зависимости по умолчанию и найдет доступный API в общем коде. Это устраняет сложную настройку сборки и необходимость использования обходных путей для получения поддержки IDE при обмене наборами исходных файлов между целевыми платформами native. Это также помогает предотвратить небезопасное использование API, предназначенного для другой платформы.
Эта технология также будет полезна авторам библиотек, так как иерархическая структура проекта позволяет им публиковать и использовать библиотеки с общими API для подмножества платформ.
По умолчанию библиотеки, опубликованные с иерархической структурой проекта, совместимы только с проектами с иерархической структурой. Узнайте больше о совместимости проекта и библиотеки.
Улучшенное совместное использование кода в вашем проекте
Без поддержки иерархической структуры нет простого способа совместного использования кода между некоторыми, но не всеми целями Kotlin. Один популярный пример — совместное использование кода между всеми целями iOS и доступ к специфичным для iOS зависимостям, таким как Foundation.
Благодаря поддержке иерархической структуры проекта, вы теперь можете добиться этого без дополнительных настроек. В новой структуре наборы исходных файлов образуют иерархию. Вы можете использовать платформенно-специфичные языковые функции и зависимости, доступные для каждой цели, к которой компилируется данный набор исходных файлов.
Например, рассмотрим типичный проект multiplatform с двумя целевыми платформами — iosArm64 и iosX64 для устройств и симуляторов iOS. Инструментарий Kotlin понимает, что обе цели имеют одинаковую функцию и позволяет получить доступ к этой функции из промежуточного набора исходных файлов, iosMain.

Цепочка инструментов Kotlin обеспечивает правильные зависимости по умолчанию, такие как Kotlin/Native stdlib или native библиотеки. Кроме того, инструментарий Kotlin постарается найти именно область доступного API в общем коде. Это предотвращает такие случаи, как, например, использование функции, специфичной для macOS, в коде, используемом для Windows.
Больше возможностей для авторов библиотек
При публикации библиотеки multiplatform API её промежуточных наборов исходных файлов теперь публикуется вместе с ней, делая его доступным для потребителей. Снова, цепочка инструментов Kotlin автоматически определит API, доступный в наборе исходных файлов потребителя, внимательно следя за небезопасным использованием, например, использованием API, предназначенного для JVM, в коде JS. Узнайте больше о совместном использовании кода в библиотеках.
Настройка и настройка
Начиная с Kotlin 1.6.20, все ваши новые проекты multiplatform будут иметь иерархическую структуру проекта. Дополнительная настройка не требуется.
-
Если вы уже включили её вручную, вы можете удалить устаревшие параметры из
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
Для упрощения интеграции CocoaPods, Kotlin 1.6.20 предоставляет следующие функции:
-
Плагин CocoaPods теперь имеет задачи, которые строят XCFrameworks со всеми зарегистрированными целями и генерируют файл Podspec. Это может быть полезно, если вы не хотите интегрироваться с Xcode напрямую, но хотите создать артефакты и развернуть их в ваш локальный репозиторий CocoaPods.
Узнайте больше о создании XCFrameworks.
-
Если вы используете интеграцию 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
Для повышения эффективности разработки Kotlin/JS с компилятором IR мы ввели новый режим инкрементальной компиляции.
При построении библиотек разработки с задачей compileDevelopmentExecutableKotlinJs Gradle в этом режиме компилятор кеширует результаты предыдущих компиляций на уровне модуля. Он использует кэшированные результаты компиляции для неизменённых исходных файлов во время последующих компиляций, что ускоряет их выполнение, особенно при небольших изменениях. Обратите внимание, что это улучшение исключительно для процесса разработки (ускорение цикла редактирование-сборка-отладка) и не влияет на построение продукционных артефактов.
Для включения инкрементальной компиляции для библиотек разработки добавьте следующую строку в файл конфигурации проекта 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 вводит несколько функций для повышения безопасности вашего кода:
Использование относительных путей в klibs
Библиотека в формате 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 и его содержимое в систему управления версиями. Добавление lock-файлов в систему управления версиями — рекомендуемая практика, так как это гарантирует, что ваше приложение будет собираться с одним и тем же деревом зависимостей на всех машинах, независимо от того, являются ли это рабочие среды на других машинах или службы CI/CD. Lock-файлы также предотвращают неявное обновление зависимостей npm при выгрузке проекта на новую машину, что является проблемой безопасности.
Инструменты, такие как Dependabot, также могут анализировать файлы yarn.lock ваших проектов Kotlin/JS и предоставлять предупреждения, если какой-либо зависимый пакет npm скомпрометирован.
При необходимости вы можете изменить имя каталога и lock-файла в файле сборки:
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 Plugin:
Новые свойства
kotlin.compiler.execution.strategyиcompilerExecutionStrategyдля определения стратегии выполнения компилятора KotlinУстаревание опций
kapt.use.worker.api,kotlin.experimental.coroutines, иkotlin.coroutines
Свойства для определения стратегии выполнения компилятора Kotlin
До Kotlin 1.6.20 вы использовали системную переменную -Dkotlin.compiler.execution.strategy для определения стратегии выполнения компилятора Kotlin. В некоторых случаях эта переменная могла быть неудобной. Kotlin 1.6.20 вводит свойство Gradle с таким же именем, kotlin.compiler.execution.strategy, и свойство задачи compile 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. По умолчанию kapt использует рабочие процессы Gradle с версии 1.3.70, и мы рекомендуем придерживаться этого метода.Мы собираемся удалить опцию
kapt.use.worker.apiв будущих версиях. -
Мы устарели опцию Gradle DSL
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 plugin.
© 2010–2023 JetBrains s.r.o. and Kotlin Programming Language contributors
Licensed under the Apache License, Version 2.0.
https://kotlinlang.org/docs/whatsnew1620.html