Что нового в 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's 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: возврат Swift's 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.
Теперь вы можете обмениваться исходным кодом между несколькими похожими целевыми платформами нативных приложений, которые повторно используют значительную часть общей логики и API сторонних библиотек. Данная технология обеспечит правильные зависимости по умолчанию и найдет доступный API в общем коде. Это устраняет сложную настройку сборки и необходимость использования обходных путей для получения поддержки IDE при совместном использовании наборов исходных файлов между целевыми платформами нативных приложений. Это также поможет предотвратить небезопасное использование API, предназначенного для другой платформы.
Эта технология будет полезна и разработчикам библиотек, так как иерархическая структура проекта позволяет им публиковать и использовать библиотеки с общим API для подмножества платформ.
По умолчанию библиотеки, опубликованные с иерархической структурой проекта, совместимы только с проектами, имеющими иерархическую структуру.
Улучшение совместного использования кода в вашем проекте
Без поддержки иерархической структуры нет прямого способа обмениваться кодом между некоторыми, но не всеми целевыми платформами Kotlin. Один популярный пример — обмен кодом между всеми целевыми платформами iOS и доступ к платформенно-специфическим зависимостям, например, Foundation.
Благодаря поддержке иерархической структуры проекта, теперь вы можете добиться этого «из коробки». В новой структуре наборы исходных файлов образуют иерархию. Вы можете использовать платформенно-специфические языковые функции и зависимости, доступные для каждой платформы, к которой компилируется данный набор исходных файлов.
Например, рассмотрим типичный проект multiplatform с двумя целевыми платформами — iosArm64 и iosX64 для устройств и симуляторов iOS. Kotlin-инструменты понимают, что у обеих платформ одинаковая функция, и позволяют вам получить доступ к этой функции из промежуточного набора исходных файлов, iosMain.

Цепочка инструментов Kotlin предоставляет правильные зависимости по умолчанию, такие как Kotlin/Native stdlib или нативные библиотеки. Кроме того, инструменты 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'
}
}
См. полную справку по плагину Kotlin CocoaPods Gradle DSL.
Kotlin/JS
Улучшения Kotlin/JS в версии 1.6.20 в основном касаются компилятора IR:
Ленивая инициализация свойств верхнего уровня по умолчанию (IR)
Улучшения экспорта и генерации деклараций TypeScript (IR и legacy бэкэнды)
Инкрементальная компиляция для библиотек разработки с использованием компилятора 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.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, вы использовали системную переменную -Dkotlin.compiler.execution.strategy для определения стратегии выполнения компилятора Kotlin. Эта переменная могла быть неудобной в некоторых случаях. 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. По умолчанию, 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–2023 JetBrains s.r.o. and Kotlin Programming Language contributors
Licensed under the Apache License, Version 2.0.
https://kotlinlang.org/docs/whatsnew1620.html