Что нового в Kotlin 1.6.20
Дата выхода: 4 апреля 2022 года
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. Синтаксическая форма происходит от записи пересечения типов и теперь ограничена параметром типа с 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'
}
}
}
Узнайте больше об однозначно не-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 interop, см. документацию по взаимосвязи взаимодействия и эту статью блога.
Поддержка параллельной компиляции одного модуля в JVM бекенде
Мы продолжаем работу над улучшением времени компиляции нового JVM IR бекенда. В Kotlin 1.6.20 мы добавили экспериментальный режим JVM IR бекенда для параллельной компиляции всех файлов в модуле. Параллельная компиляция может сократить общее время компиляции до 15%.
Включите экспериментальный параллельный режим бекенда с помощью опции компилятора опции компилятора -Xbackend-threads. Используйте следующие аргументы для этой опции:
N— количество потоков, которые вы хотите использовать. Оно не должно превышать количество ядер процессора; в противном случае, параллелизация перестаёт быть эффективной из-за переключения контекста между потоками0для использования отдельного потока для каждого ядра процессора
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: возврат 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, которое заставляет компилятор переводить 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 в 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.
Теперь вы можете обмениваться исходным кодом между несколькими похожими целевыми устройствами, которые повторно используют большое количество общей логики и API сторонних библиотек. Технология предоставит правильные зависимости по умолчанию и найдет точный API, доступный в общем коде. Это устраняет сложную настройку сборки и необходимость использовать обходные пути для получения поддержки IDE для обмена наборами исходных файлов между целевыми устройствами. Это также помогает предотвратить небезопасное использование API, предназначенного для другого целевого устройства.
Эта технология также пригодится авторам библиотек, поскольку иерархическая структура проекта позволяет им публиковать и использовать библиотеки с общими API для подмножества целевых устройств.
По умолчанию библиотеки, опубликованные с иерархической структурой проекта, совместимы только с проектами, имеющими иерархическую структуру. Узнайте больше о совместимости проекта с библиотекой.
Улучшение обмена кодом в вашем проекте
Без поддержки иерархической структуры нет прямого способа обмениваться кодом между некоторыми, но не всеми целями Kotlin. Один из популярных примеров — обмен кодом между всеми целевыми устройствами iOS и доступ к специфичным для iOS зависимостям, например Foundation.
Благодаря поддержке иерархической структуры проекта, теперь вы можете добиться этого непосредственно. В новой структуре наборы исходных файлов образуют иерархию. Вы можете использовать специфичные для платформы языковые функции и зависимости, доступные для каждого целевого устройства, к которому компилируется данный набор исходных файлов.
Например, рассмотрим типичный проект multiplatform с двумя целевыми устройствами — iosArm64 и iosX64 для устройств и симуляторов iOS. Инструментарий Kotlin понимает, что у обоих целевых устройств есть та же функция, и позволяет вам получить доступ к этой функции из промежуточного набора исходных файлов, iosMain.

Цепочка инструментов Kotlin предоставляет правильные зависимости по умолчанию, такие как Kotlin/Native stdlib или родные библиотеки. Кроме того, инструменты Kotlin будут стараться найти точно такую поверхность API, которая доступна в общем коде. Это предотвращает такие случаи, как, например, использование функции, специфичной для macOS, в коде, общем для Windows.
Больше возможностей для авторов библиотек
При публикации многоплатформенной библиотеки 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)
Улучшения экспорта (как для 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 classes). Это ускоряет операции с символами в коде 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.tasks.KotlinCompile::class).configureEach {
// $base is a base path of source files
kotlinOptions.freeCompilerArgs += "-Xklib-relative-path-base=$base"
}
tasks.withType(org.jetbrains.kotlin.gradle.tasks.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's) являются:
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 buildscript:
import org.jetbrains.kotlin.gradle.tasks.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 плагине.
© 2010–2022 JetBrains s.r.o. and Kotlin Programming Language contributors
Licensed under the Apache License, Version 2.0.
https://kotlinlang.org/docs/whatsnew1620.html