Spec-Zone.ru › Kotlin 1.9

Что нового в Kotlin 1.5.30

Выпущено: 24 августа 2021

Kotlin 1.5.30 предлагает обновления языка, включая предварительные версии будущих изменений, различные улучшения поддержки платформы и инструментария, а также новые функции стандартной библиотеки.

Вот некоторые основные улучшения:

  • Функциональные возможности языка, включая экспериментальные условные (sealed) when операторы, изменения в использовании требования opt-in и другие.

  • Поддержка Apple silicon

  • Бета-версия Kotlin/JS IR-бекенда

  • Улучшенная работа плагина Gradle

Вы также можете найти краткий обзор изменений в статье в блоге о выпуске и этом видео:

Функции языка

Kotlin 1.5.30 предоставляет предварительные версии будущих изменений языка и улучшения механизма opt-in и вывода типов:

  • Исчерпывающие операторы when для условных (sealed) и булевых объектов

  • Функции-подвески как супертипы

  • Требование opt-in для неявных использований экспериментальных API

  • Изменения в использовании аннотаций opt-in с различными целевыми объектами

  • Улучшения вывода типов для рекурсивных обобщенных типов

  • Устранение ограничений вывода типов для билдеров

Исчерпывающие операторы when для условных (sealed) и булевых объектов

Поддержка исчерпывающих операторов when для условных (sealed) типов находится на стадии эксперимента. Она может быть удалена или изменена в любое время. Требуется opt-in (см. подробности ниже), и вы должны использовать её только в оценочных целях. Мы будем признательны за ваши отзывы на YouTrack.

Оператор исчерпывающий when содержит ветви для всех возможных типов или значений его объекта, или для некоторых типов плюс else ветвь. Другими словами, он охватывает все возможные случаи.

Мы планируем вскоре запретить неисчерпывающие when операторы, чтобы сделать поведение согласованным с when выражениями. Для обеспечения плавной миграции, вы можете настроить компилятор на выдачу предупреждений о неисчерпывающих when операторах с условным (sealed) классом или булевым значением. Такие предупреждения будут отображаться по умолчанию в Kotlin 1.6 и в дальнейшем будут рассматриваться как ошибки.

Для перечислений (enums) уже выдаются предупреждения.

sealed class Mode {
    object ON : Mode()
    object OFF : Mode()
}

fun main() {
    val x: Mode = Mode.ON
    when (x) { 
        Mode.ON -> println("ON")
    }
// WARNING: Non exhaustive 'when' statements on sealed classes/interfaces 
// will be prohibited in 1.7, add an 'OFF' or 'else' branch instead

    val y: Boolean = true
    when (y) {  
        true -> println("true")
    }
// WARNING: Non exhaustive 'when' statements on Booleans will be prohibited 
// in 1.7, add a 'false' or 'else' branch instead
}

Чтобы включить эту функцию в Kotlin 1.5.30, используйте версию языка 1.6. Вы также можете изменить предупреждения на ошибки, включив постепенный режим.

kotlin {
    sourceSets.all {
        languageSettings.apply {
            languageVersion = "1.6"
            //progressiveMode = true // false by default
        }
    }
}
kotlin {
    sourceSets.all {
        languageSettings {
            languageVersion = '1.6'
            //progressiveMode = true // false by default
        }
    }
}

Функции-подвески как супертипы

Поддержка функций-подвесок в качестве супертипов находится на стадии эксперимента. Она может быть удалена или изменена в любое время. Требуется opt-in (см. подробности ниже), и вы должны использовать её только в оценочных целях. Мы будем признательны за ваши отзывы на YouTrack.

Kotlin 1.5.30 предоставляет предварительный просмотр возможности использования suspend функционального типа в качестве супертипа с некоторыми ограничениями.

class MyClass: suspend () -> Unit {
    override suspend fun invoke() { TODO() }
}

Используйте опцию компилятора -language-version 1.6, чтобы включить эту функцию:

kotlin {
    sourceSets.all {
        languageSettings.apply {
            languageVersion = "1.6"
        }
    }
}
kotlin {
    sourceSets.all {
        languageSettings {
            languageVersion = '1.6'
        }
    }
}

Функция имеет следующие ограничения:

  • Вы не можете смешивать обычный функциональный тип и suspend функциональный тип как супертип. Это связано с особенностями реализации suspend функциональных типов в JVM-бекенде. Они представлены в нём как обычные функциональные типы с маркером интерфейса. Из-за маркера интерфейса невозможно определить, какие из суперинтерфейсов являются подвешенными (suspending), а какие — обычными.

  • Вы не можете использовать несколько suspend функциональных супертипов. Если есть проверки типов, вы также не можете использовать несколько обычных функциональных супертипов.

Требование opt-in для неявных использований экспериментальных API

Механизм opt-in находится на стадии эксперимента. Он может быть изменён в любое время. Узнайте, как активировать opt-in. Используйте его только в оценочных целях. Мы будем признательны за ваши отзывы на YouTrack.

Автор библиотеки может пометить экспериментальный API как требующий opt-in, чтобы проинформировать пользователей о его экспериментальном статусе. Компилятор выводит предупреждение или ошибку, когда API используется и требует явного согласия для его подавления.

В Kotlin 1.5.30 компилятор рассматривает любую декларацию, содержащую экспериментальный тип в сигнатуре, как экспериментальную. То есть, он требует opt-in даже для неявных использований экспериментального API. Например, если тип возвращаемого значения функции помечен как экспериментальный элемент API, использование функции требует opt-in, даже если сама декларация явно не отмечена как требующая opt-in.

// Library code

@RequiresOptIn(message = "This API is experimental.")
@Retention(AnnotationRetention.BINARY)
@Target(AnnotationTarget.CLASS)
annotation class MyDateTime // Opt-in requirement annotation

@MyDateTime
class DateProvider // A class requiring opt-in

// Client code

// Warning: experimental API usage
fun createDateSource(): DateProvider { /* ... */ }

fun getDate(): Date {
    val dateSource = createDateSource() // Also warning: experimental API usage
    // ... 
}

Узнайте больше о требованиях opt-in.

Изменения в использовании аннотаций opt-in с различными целевыми объектами

Механизм opt-in находится на стадии эксперимента. Он может быть изменён в любое время. Узнайте, как активировать opt-in. Используйте его только в оценочных целях. Мы будем признательны за ваши отзывы на YouTrack.

Kotlin 1.5.30 вводит новые правила использования и объявления аннотаций opt-in на различных целевых объектах. Теперь компилятор выводит ошибку для случаев, которые сложно обработать во время компиляции. В Kotlin 1.5.30:

  • Запрещено помечать локальные переменные и параметры значений аннотациями opt-in на месте использования.

  • Разрешено помечать override только если и базовая декларация также помечена.

  • Запрещено помечать вспомогательные поля и геттеры. Вы можете вместо этого пометить базовое свойство.

  • Запрещено устанавливать TYPE и TYPE_PARAMETER целевые аннотации на этапе объявления аннотации opt-in.

Узнайте больше о требованиях opt-in.

Улучшения вывода типов для рекурсивных обобщенных типов

В Kotlin и Java вы можете определять рекурсивные обобщенные типы, которые ссылаются на себя в своих параметрах типа. В Kotlin 1.5.30 компилятор Kotlin может вывести аргумент типа, основываясь только на верхних границах соответствующего параметра типа, если это рекурсивный обобщенный тип. Это позволяет создавать различные паттерны с рекурсивными обобщенными типами, которые часто используются в Java для создания API-интерфейсов билдера.

// Kotlin 1.5.20
val containerA = PostgreSQLContainer<Nothing>(DockerImageName.parse("postgres:13-alpine")).apply {
    withDatabaseName("db")
    withUsername("user")
    withPassword("password")
    withInitScript("sql/schema.sql")
}

// Kotlin 1.5.30
val containerB = PostgreSQLContainer(DockerImageName.parse("postgres:13-alpine"))
    .withDatabaseName("db")
    .withUsername("user")
    .withPassword("password")
    .withInitScript("sql/schema.sql")

Вы можете включить эти улучшения, передав опции компилятора -Xself-upper-bound-inference или -language-version 1.6. Другие примеры вновь поддерживаемых случаев использования вы можете найти в этом билете YouTrack.

Устранение ограничений вывода для билдеров

Вывод билдера — это особый вид вывода типов, который позволяет вывести аргументы типа вызова на основе информации о типах из других вызовов внутри лямбда-аргумента. Это может быть полезно при вызове универсальных функций билдера, таких как buildList() или sequence(): buildList { add("string") }.

Внутри такого лямбда-аргумента ранее существовало ограничение на использование информации о типе, которую пытается вывести вывод билдера. Это означает, что вы можете только указать тип, но не получить его. Например, вы не могли вызвать get() внутри лямбда-аргумента buildList() без явного указания аргументов типа.

Kotlin 1.5.30 устраняет эти ограничения с помощью опции компилятора -Xunrestricted-builder-inference. Добавьте эту опцию, чтобы разрешить ранее запрещенные вызовы внутри лямбда-аргумента универсальных функций билдера:

@kotlin.ExperimentalStdlibApi
val list = buildList {
    add("a")
    add("b")
    set(1, null)
    val x = get(1)
    if (x != null) {
        removeAt(1)
    }
}

@kotlin.ExperimentalStdlibApi
val map = buildMap {
    put("a", 1)
    put("b", 1.1)
    put("c", 2f)
}

Также вы можете включить эту функцию с помощью опции компилятора -language-version 1.6.

Kotlin/JVM

В Kotlin 1.5.30 Kotlin/JVM получает следующие функции:

  • Создание экземпляров аннотационных классов

  • Улучшенная конфигурация поддержки аннотаций нулевости

См. раздел Gradle для обновлений плагина Kotlin Gradle для платформы JVM.

Создание экземпляров аннотационных классов

Создание экземпляров аннотационных классов — Экспериментальная функция. Она может быть удалена или изменена в любое время. Требуется включение (см. подробности ниже), и её следует использовать только в оценочных целях. Мы будем рады получить ваши отзывы об этом на YouTrack.

С Kotlin 1.5.30 вы можете вызывать конструкторы классов аннотаций в произвольном коде, чтобы получить экземпляр. Эта функция охватывает те же случаи использования, что и Java-конвенция, которая позволяет реализовывать интерфейс аннотации.

annotation class InfoMarker(val info: String)

fun processInfo(marker: InfoMarker) = ...

fun main(args: Array<String>) {
    if (args.size != 0)
        processInfo(getAnnotationReflective(args))
    else
        processInfo(InfoMarker("default"))
}

Используйте опцию компилятора -language-version 1.6 для включения этой функции. Обратите внимание, что все текущие ограничения классов аннотаций, такие как ограничения на определение параметров, не являющихся val, или членов, отличных от вторичных конструкторов, остаются неизменными.

Дополнительную информацию о создании экземпляров аннотационных классов см. в этом KEEP

Улучшенная конфигурация поддержки аннотаций нулевости

Компилятор Kotlin может считывать различные типы аннотаций нулевости, чтобы получить информацию о нулевости из Java. Эта информация позволяет сообщать о несовпадениях нулевости в Kotlin при вызове Java-кода.

В Kotlin 1.5.30 можно указать, должен ли компилятор сообщать о несовпадениях нулевости на основе информации из конкретных типов аннотаций нулевости. Просто используйте опцию компилятора -Xnullability-annotations=@<package-name>:<report-level>. В аргументе укажите полное имя пакета аннотаций нулевости и один из этих уровней отчёта:

  • ignore, чтобы игнорировать несовпадения нулевости

  • warn, чтобы сообщать предупреждения

  • strict, чтобы сообщать об ошибках.

См. полный список поддерживаемых аннотаций нулевости вместе с их полными именами пакетов.

Вот пример, показывающий, как включить отчёт об ошибках для вновь поддерживаемых аннотаций нулевости RxJava 3: -Xnullability-annotations=@io.reactivex.rxjava3.annotations:strict. Обратите внимание, что все такие несовпадения нулевости по умолчанию являются предупреждениями.

Kotlin/Native

В Kotlin/Native произошли различные изменения и улучшения:

  • Поддержка Apple silicon

  • Улучшенный Kotlin DSL для плагина CocoaPods Gradle

  • Экспериментальная взаимозаменяемость с Swift 5.5 async/await

  • Улучшенное отображение Swift/Objective-C для объектов и компаньонов

  • Устаревание связи с DLL без библиотек импорта для целей MinGW

Поддержка Apple silicon

Kotlin 1.5.30 вводит поддержку Apple silicon.

Ранее компилятор и инструменты Kotlin/Native требовали среды перевода Rosetta для работы на хостах с Apple silicon. В Kotlin 1.5.30 среда перевода больше не требуется — компилятор и инструменты могут работать на оборудовании Apple silicon без дополнительных действий.

Мы также представили новые цели, которые позволяют коду Kotlin запускаться непосредственно на Apple silicon:

  • macosArm64

  • iosSimulatorArm64

  • watchosSimulatorArm64

  • tvosSimulatorArm64

Они доступны как на хостах на базе Intel, так и на хостах с Apple silicon. Все существующие цели также доступны на хостах с Apple silicon.

Обратите внимание, что в 1.5.30 мы предоставляем только базовую поддержку целей Apple silicon в плагине Gradle kotlin-multiplatform. В частности, новые цели симулятора не включены в ios, tvos и watchos сокращения целей. Узнайте, как использовать цели Apple silicon с сокращениями целей. Мы будем продолжать работу над улучшением пользовательского опыта с новыми целями.

Улучшенный Kotlin DSL для плагина CocoaPods Gradle

Новые параметры для фреймворков Kotlin/Native

Kotlin 1.5.30 представляет улучшенный DSL плагина CocoaPods Gradle для фреймворков Kotlin/Native. В дополнение к имени фреймворка вы можете указать другие параметры в конфигурации Pod:

  • Укажите динамическую или статическую версию фреймворка

  • Явно включите зависимости для экспорта

  • Включите встраивание Bitcode

Чтобы использовать новый DSL, обновите свой проект до Kotlin 1.5.30 и укажите параметры в разделе cocoapods вашего файла build.gradle(.kts):

cocoapods {
    frameworkName = "MyFramework" // This property is deprecated 
    // and will be removed in future versions
    // New DSL for framework configuration:
    framework {
        // All Framework properties are supported
        // Framework name configuration. Use this property instead of 
        // deprecated 'frameworkName'
        baseName = "MyFramework"
        // Dynamic framework support
        isStatic = false
        // Dependency export
        export(project(":anotherKMMModule"))
        transitiveExport = false // This is default.
        // Bitcode embedding
        embedBitcode(BITCODE)
    }
}

Поддержка пользовательских имен для конфигурации Xcode

Плагин Kotlin CocoaPods Gradle поддерживает пользовательские имена в конфигурации сборки Xcode. Это также поможет вам, если вы используете специальные имена для конфигурации сборки в Xcode, например Staging.

Чтобы указать пользовательское имя, используйте параметр xcodeConfigurationToNativeBuildType в разделе cocoapods вашего файла build.gradle(.kts):

cocoapods {
    // Maps custom Xcode configuration to NativeBuildType
    xcodeConfigurationToNativeBuildType["CUSTOM_DEBUG"] = NativeBuildType.DEBUG
    xcodeConfigurationToNativeBuildType["CUSTOM_RELEASE"] = NativeBuildType.RELEASE
}

Этот параметр не будет отображаться в файле Podspec. При запуске Xcode процесса сборки Gradle плагин Kotlin CocoaPods Gradle выберет необходимый тип нативной сборки.

Нет необходимости объявлять конфигурации Debug и Release, так как они поддерживаются по умолчанию.

Экспериментальная взаимозаменяемость с Swift 5.5 async/await

Взаимозаменяемость с конкурентностью Swift async/await является Экспериментальной. Она может быть удалена или изменена в любое время. Ее следует использовать только в оценочных целях. Мы будем признательны за ваши отзывы по этому поводу в YouTrack.

Мы добавили поддержку вызова приостанавливающих функций Kotlin из Objective-C и Swift в 1.4.0, а теперь мы улучшаем ее, чтобы соответствовать новой функции Swift 5.5 — конкурентность с async и await модификаторами.

Компилятор Kotlin/Native теперь генерирует атрибут _Nullable_result в сгенерированных заголовках Objective-C для приостанавливающих функций с типом возвращаемого значения nullable. Это позволяет вызывать их из Swift как функции async с соответствующей nullable.

Обратите внимание, что эта функция экспериментальная и может быть изменена в будущем как в Kotlin, так и в Swift. Пока мы предлагаем предварительный просмотр этой функции с определенными ограничениями и с нетерпением ждем ваших отзывов. Узнайте больше о ее текущем состоянии и оставьте свои отзывы в этом вопросе YouTrack.

Улучшенное отображение Swift/Objective-C для объектов и компаньонов

Доступ к объектам и компаньонам теперь можно получить более интуитивно для разработчиков native iOS. Например, если у вас есть следующие объекты в Kotlin:

object MyObject {
    val x = "Some value"
}

class MyClass {
    companion object {
        val x = "Some value"
    }
}

Для доступа к ним в Swift вы можете использовать свойства shared и companion:

MyObject.shared
MyObject.shared.x
MyClass.companion
MyClass.Companion.shared

Узнайте больше о взаимозаменяемости Swift/Objective-C.

Устаревание связи с DLL без библиотек импорта для целей MinGW

LLD — это линковщик из проекта LLVM, который мы планируем использовать в Kotlin/Native для целей MinGW из-за его преимуществ перед стандартным ld.bfd — прежде всего, его лучшей производительности.

Однако последняя стабильная версия LLD не поддерживает прямую связь с DLL для целей MinGW (Windows). Для такой связи необходимо использовать библиотеки импорта. Хотя они не нужны с Kotlin/Native 1.5.30, мы добавляем предупреждение, чтобы проинформировать вас о том, что такое использование несовместимо с LLD, который станет стандартным линковщиком для MinGW в будущем.

Пожалуйста, поделитесь своими мыслями и опасениями по поводу перехода к линковщику LLD в этом вопросе YouTrack.

END_OF_DOCUMENT_MARKER

Kotlin Multiplatform

1.5.30 принесла следующие заметные обновления для Kotlin Multiplatform:

  • Возможность использования пользовательских cinterop библиотек в общем нативном коде

  • Поддержка XCFrameworks

  • Новая настройка публикации по умолчанию для артефактов Android

Возможность использования пользовательских библиотек cinterop в общем нативном коде

Kotlin Multiplatform предоставляет возможность использовать платформозависимые библиотеки межплатформенного взаимодействия в общих наборах исходного кода. До версии 1.5.30 это работало только с платформенными библиотеками, поставляемыми с дистрибутивом Kotlin/Native. Начиная с 1.5.30, вы можете использовать свои пользовательские cinterop библиотеки. Чтобы включить эту функцию, добавьте свойство kotlin.mpp.enableCInteropCommonization=true в свой gradle.properties:

kotlin.mpp.enableGranularSourceSetsMetadata=true
kotlin.native.enableDependencyPropagation=false
kotlin.mpp.enableCInteropCommonization=true

Поддержка XCFrameworks

Все проекты Kotlin Multiplatform теперь могут иметь XCFrameworks в качестве формата выходных данных. Apple представила XCFrameworks как замену универсальным (fat) фреймворкам. С помощью XCFrameworks вы:

  • Можете объединить логику для всех целевых платформ и архитектур в одном пакете.

  • Не нужно удалять все ненужные архитектуры перед публикацией приложения в App Store.

XCFrameworks полезно, если вы хотите использовать свой Kotlin фреймворк для устройств и симуляторов на Apple M1.

Чтобы использовать XCFrameworks, обновите свой скрипт build.gradle(.kts):

import org.jetbrains.kotlin.gradle.plugin.mpp.apple.XCFramework

plugins {
    kotlin("multiplatform")
}

kotlin {
    val xcf = XCFramework()
  
    ios {
        binaries.framework {
            baseName = "shared"
            xcf.add(this)
        }
    }
    watchos {
        binaries.framework {
            baseName = "shared"
            xcf.add(this)
        }
    }
    tvos {
        binaries.framework {
            baseName = "shared"
            xcf.add(this)
        }
    }
}
import org.jetbrains.kotlin.gradle.plugin.mpp.apple.XCFrameworkConfig

plugins {
    id 'org.jetbrains.kotlin.multiplatform'
}

kotlin {
    def xcf = new XCFrameworkConfig(project)

    ios {
        binaries.framework {
            baseName = "shared"
            xcf.add(it)
        }
    }
    watchos {
        binaries.framework {
            baseName = "shared"
            xcf.add(it)
        }
    }
    tvos {
        binaries.framework {
            baseName = "shared"
            xcf.add(it)
        }
    }
}

При объявлении XCFrameworks будут зарегистрированы новые задачи Gradle:

  • assembleXCFramework

  • assembleDebugXCFramework (дополнительный артефакт отладки, содержащий dSYMs)

  • assembleReleaseXCFramework

Дополнительную информацию о XCFrameworks можно найти в этом видео WWDC.

Новая настройка публикации по умолчанию для артефактов Android

Используя плагин Gradle maven-publish, вы можете опубликовать свою многоплатформенную библиотеку для целевой платформы Android, указав имена вариантов Android в скрипте сборки. Плагин Kotlin Gradle сгенерирует публикации автоматически.

До версии 1.5.30 сгенерированный метаданные публикации metadata включал атрибуты типа сборки для каждого опубликованного варианта Android, что делало его совместимым только с тем же типом сборки, используемым потребителем библиотеки. Kotlin 1.5.30 вводит новую настройку публикации по умолчанию:

  • Если все варианты Android, которые проект публикует, имеют одинаковый атрибут типа сборки, опубликованные варианты не будут содержать атрибут типа сборки и будут совместимы с любым типом сборки.

  • Если опубликованные варианты имеют разные атрибуты типа сборки, будут опубликованы только те, которые имеют значение release, без атрибута типа сборки. Это делает версии релизов совместимыми с любым типом сборки на стороне потребителя, в то время как нерелизные варианты будут совместимы только с соответствующими типами сборок потребителя.

Чтобы отказаться от этого и сохранить атрибуты типа сборки для всех вариантов, можно установить это свойство Gradle: kotlin.android.buildTypeAttribute.keep=true.

Kotlin/JS

В Kotlin/JS с версией 1.5.30 два основных улучшения:

  • Бета-версия компилятора JavaScript IR для Kotlin/JS

  • Улучшенный опыт отладки для приложений с Kotlin/JS IR backend

Бета-версия компилятора JavaScript IR для Kotlin/JS

Основанный на IR компилятор для Kotlin/JS, который был представлен в 1.4.0 в Альфа-версии, достиг бета-стадии.

Ранее мы опубликовали руководство по миграции на JS IR backend, чтобы помочь вам мигрировать ваши проекты на новый backend. Теперь мы хотим представить плагин IDE Kotlin/JS Inspection Pack, который отображает необходимые изменения непосредственно в IntelliJ IDEA.

Улучшенный опыт отладки для приложений с Kotlin/JS IR backend

Kotlin 1.5.30 добавляет генерацию карт исходного кода JavaScript для Kotlin/JS IR backend. Это улучшит опыт отладки Kotlin/JS при включенном IR backend, с полной поддержкой отладки, включая точки останова, пошаговое выполнение и читаемые трассировки стека с правильными ссылками на исходный код.

Узнайте, как отлаживать Kotlin/JS в браузере или IntelliJ IDEA Ultimate.

Gradle

В рамках нашей миссии по улучшению пользовательского опыта Kotlin Gradle плагина, мы реализовали следующие функции:

  • Поддержка Java инструмент-цепочек, которая включает в себя возможность указать домашний каталог JDK с помощью интерфейса UsesKotlinJavaToolchain для более старых версий Gradle

  • Более простой способ явного указания аргументов JVM для Kotlin демона

Поддержка Java инструмент-цепочек

Gradle 6.7 представил функцию "Поддержка Java инструмент-цепочек". Используя эту функцию, вы можете:

  • Выполнять компиляции, тесты и исполняемые файлы, используя JDK и JRE, отличные от тех, которые использует Gradle.

  • Компилировать и тестировать код с невыпущенной версией языка.

С поддержкой инструмент-цепочек Gradle может автоматически обнаруживать локальные JDK и устанавливать недостающие JDK, необходимые Gradle для сборки. Теперь сам Gradle может работать с любым JDK и по-прежнему использовать функцию кэширования сборки.

Kotlin Gradle плагин поддерживает Java инструмент-цепочки для задач компиляции Kotlin/JVM. Java инструмент-цепь:

  • Устанавливает значение параметра jdkHome, доступного для целей JVM.

    Возможность установить параметр jdkHome напрямую устарела.

  • Устанавливает значение kotlinOptions.jvmTarget на версию JDK инструмент-цепи, если пользователь явно не установил параметр jvmTarget. Если инструмент-цепь не настроен, поле jvmTarget использует значение по умолчанию. Подробнее об совместимости JVM цели.

  • Влияет на то, на каких JDK kapt worker выполняются.

Используйте следующий код для установки инструмент-цепи. Замените <MAJOR_JDK_VERSION> на версию JDK, которую вы хотите использовать:

kotlin {
    jvmToolchain {
        (this as JavaToolchainSpec).languageVersion.set(JavaLanguageVersion.of(<MAJOR_JDK_VERSION>)) // "8"
    }
}
kotlin {
    jvmToolchain {
        languageVersion.set(JavaLanguageVersion.of(<MAJOR_JDK_VERSION>)) // "8"
    }
}

Обратите внимание, что установка инструмент-цепи через расширение kotlin также обновит инструмент-цепь для задач компиляции Java.

Вы можете установить инструмент-цепь через расширение java, и задачи компиляции Kotlin будут использовать его:

java {
    toolchain {
        languageVersion.set(JavaLanguageVersion.of(<MAJOR_JDK_VERSION>)) // "8"
    }
}

Дополнительную информацию о настройке любой версии JDK для задач KotlinCompile см. в документации по установке версии JDK с помощью Task DSL.

Для версий Gradle от 6.1 до 6.6, используйте интерфейс UsesKotlinJavaToolchain для установки домашнего каталога JDK.

Возможность указать домашний каталог JDK с интерфейсом UsesKotlinJavaToolchain

Все задачи Kotlin, которые поддерживают установку JDK через kotlinOptions, теперь реализуют интерфейс UsesKotlinJavaToolchain. Для установки домашнего каталога JDK укажите путь к вашему JDK и замените <JDK_VERSION> на этот путь:

project.tasks
    .withType<UsesKotlinJavaToolchain>()
    .configureEach {
        it.kotlinJavaToolchain.jdk.use(
            "/path/to/local/jdk",
            JavaVersion.<LOCAL_JDK_VERSION>
        )
    }
project.tasks
    .withType(UsesKotlinJavaToolchain.class)
    .configureEach {
        it.kotlinJavaToolchain.jdk.use(
            '/path/to/local/jdk',
            JavaVersion.<LOCAL_JDK_VERSION>
        )
    }

Используйте интерфейс UsesKotlinJavaToolchain для версий Gradle от 6.1 до 6.6. Начиная с Gradle 6.7, используйте Java инструмент-цепочки.

При использовании этой функции обратите внимание, что kapt задачи worker будут использовать только режим изоляции процесса, а свойство kapt.workers.isolation будет игнорироваться.

Более простой способ явного указания аргументов JVM для Kotlin демона

В Kotlin 1.5.30 появилась новая логика для аргументов JVM Kotlin демона. Каждый из параметров в нижеследующем списке переопределяет предыдущие:

  • Если ничего не указано, Kotlin демон наследует аргументы от Gradle демона (как и раньше). Например, в файле gradle.properties:

    org.gradle.jvmargs=-Xmx1500m -Xms=500m
    
  • Если аргументы JVM Gradle демона имеют системную переменную kotlin.daemon.jvm.options, используйте её как и раньше:

    org.gradle.jvmargs=-Dkotlin.daemon.jvm.options=-Xmx1500m -Xms=500m
    
  • Вы можете добавить свойство kotlin.daemon.jvmargs в файл gradle.properties:

    kotlin.daemon.jvmargs=-Xmx1500m -Xms=500m
    
  • Вы можете указать аргументы в расширении kotlin:

    kotlin {
        kotlinDaemonJvmArgs = listOf("-Xmx486m", "-Xms256m", "-XX:+UseParallelGC")
    }
    
    kotlin {
        kotlinDaemonJvmArgs = ["-Xmx486m", "-Xms256m", "-XX:+UseParallelGC"]
    }
    
  • Вы можете указать аргументы для конкретной задачи:

    tasks
        .matching { it.name == "compileKotlin" && it is CompileUsingKotlinDaemon }
        .configureEach {
            (this as CompileUsingKotlinDaemon).kotlinDaemonJvmArguments.set(listOf("-Xmx486m", "-Xms256m", "-XX:+UseParallelGC"))
        }
    
    tasks
        .matching {
            it.name == "compileKotlin" && it instanceof CompileUsingKotlinDaemon
        }
        .configureEach {
            kotlinDaemonJvmArguments.set(["-Xmx1g", "-Xms512m"])
        }
    

    В этом случае новый экземпляр Kotlin демона может запуститься при выполнении задачи. Подробнее о взаимодействии Kotlin демона с аргументами JVM.

Дополнительную информацию о Kotlin демоне см. в документации о Kotlin демоне и его использовании с Gradle.

Стандартная библиотека

Kotlin 1.5.30 добавляет улучшения в стандартную библиотеку для Duration и Regex API:

  • Изменение вывода Duration.toString()

  • Парсинг Duration из строки

  • Сопоставление с регулярным выражением в определенной позиции

  • Разбиение регулярного выражения на последовательность

Изменение вывода Duration.toString()

API Duration находится в стадии Экспериментальной разработки. Он может быть удалён или изменён в любое время. Используйте его только для оценочных целей. Мы ценим ваш отзыв о нём на YouTrack.

До Kotlin 1.5.30 функция Duration.toString() возвращала строковое представление своего аргумента, выраженного в единицах, которые давали наиболее компактное и читаемое числовое значение. Отныне она будет возвращать строковое значение, выраженное как комбинацию числовых компонентов, каждый в своих собственных единицах. Каждый компонент — это число, за которым следует сокращённое имя единицы: d, h, m, s. Например:

Пример вызова функции

Предыдущий вывод

Текущий вывод

Duration.days(45).toString()

45.0d

45d

Duration.days(1.5).toString()

36.0h

1d 12h

Duration.minutes(1230).toString()

20.5h

20h 30m

Duration.minutes(2415).toString()

40.3h

1d 16h 15m

Duration.minutes(920).toString()

920m

15h 20m

Duration.seconds(1.546).toString()

1.55s

1.546s

Duration.milliseconds(25.12).toString()

25.1ms

25.12ms

Также изменён способ представления отрицательных продолжительностей. Отрицательная продолжительность предваряется знаком минус (-), а если она состоит из нескольких компонентов, то заключается в скобки: -12m и -(1h 30m).

Обратите внимание, что малые продолжительности менее одной секунды представлены как одно число с одной из единиц долей секунды. Например, ms (миллисекунды), us (микросекунды) или ns (наносекунды): 140.884ms, 500us, 24ns. Научная запись больше не используется для их представления.

Если вы хотите выразить продолжительность в одной единице, используйте перегруженную функцию Duration.toString(unit, decimals).

В определенных случаях, включая сериализацию и обмен данными, рекомендуется использовать Duration.toIsoString(). Duration.toIsoString() использует более строгий формат ISO-8601 вместо Duration.toString().

Парсинг Duration из строки

API Duration находится в стадии Экспериментальной разработки. Он может быть удалён или изменён в любое время. Используйте его только для оценочных целей. Мы ценим ваш отзыв о нём на этом вопросе.

В Kotlin 1.5.30 появились новые функции в API Duration:

  • parse(), которая поддерживает парсинг вывода функций:

    • toString().

    • toString(unit, decimals).

    • toIsoString().

  • parseIsoString(), которая парсит только формат, созданный функцией toIsoString().

  • parseOrNull() и parseIsoStringOrNull(), которые ведут себя подобно функциям выше, но возвращают null вместо того, чтобы выбрасывать IllegalArgumentException при некорректном формате продолжительности.

Вот несколько примеров использования parse() и parseOrNull():

import kotlin.time.Duration
import kotlin.time.ExperimentalTime

@ExperimentalTime
fun main() {
//sampleStart
    val isoFormatString = "PT1H30M"
    val defaultFormatString = "1h 30m"
    val singleUnitFormatString = "1.5h"
    val invalidFormatString = "1 hour 30 minutes"
    println(Duration.parse(isoFormatString)) // "1h 30m"
    println(Duration.parse(defaultFormatString)) // "1h 30m"
    println(Duration.parse(singleUnitFormatString)) // "1h 30m"
    //println(Duration.parse(invalidFormatString)) // throws exception
    println(Duration.parseOrNull(invalidFormatString)) // "null"
//sampleEnd
}

И вот несколько примеров использования parseIsoString() и parseIsoStringOrNull():

import kotlin.time.Duration
import kotlin.time.ExperimentalTime

@ExperimentalTime
fun main() {
//sampleStart
    val isoFormatString = "PT1H30M"
    val defaultFormatString = "1h 30m"
    println(Duration.parseIsoString(isoFormatString)) // "1h 30m"
    //println(Duration.parseIsoString(defaultFormatString)) // throws exception
    println(Duration.parseIsoStringOrNull(defaultFormatString)) // "null"
//sampleEnd
}

Сопоставление с регулярным выражением в определенной позиции

Функции Regex.matchAt() и Regex.matchesAt() находятся в стадии экспериментальной разработки. Они могут быть удалены или изменены в любое время. Используйте их только для оценочных целей. Мы будем признательны за обратную связь на YouTrack.

Новые функции Regex.matchAt() и Regex.matchesAt() позволяют проверить, есть ли точное совпадение регулярного выражения в определенной позиции в String или CharSequence.

Regex.matchAt() возвращает логическое значение:

fun main(){
//sampleStart
    val releaseText = "Kotlin 1.5.30 is released!"
    // regular expression: one digit, dot, one digit, dot, one or more digits
    val versionRegex = "\\d[.]\\d[.]\\d+".toRegex()
    println(versionRegex.matchesAt(releaseText, 0)) // "false"
    println(versionRegex.matchesAt(releaseText, 7)) // "true"
//sampleEnd
}

matchAt() возвращает совпадение, если оно найдено, или null, если нет:

fun main(){
//sampleStart
    val releaseText = "Kotlin 1.5.30 is released!"
    val versionRegex = "\\d[.]\\d[.]\\d+".toRegex()
    println(versionRegex.matchAt(releaseText, 0)) // "null"
    println(versionRegex.matchAt(releaseText, 7)?.value) // "1.5.30"
//sampleEnd
}

Разбиение регулярного выражения на последовательность

Функции Regex.splitToSequence() и CharSequence.splitToSequence(Regex) находятся в стадии экспериментальной разработки. Они могут быть удалены или изменены в любое время. Мы будем признательны за обратную связь на YouTrack.

Новая функция Regex.splitToSequence() — это ленивый аналог split(). Она разбивает строку по совпадениям с заданным регулярным выражением, но возвращает результат в виде последовательности, чтобы все операции с этим результатом выполнялись лениво.

fun main(){
//sampleStart
    val colorsText = "green, red , brown&blue, orange, pink&green"
    val regex = "[,\\s]+".toRegex()
    val mixedColor = regex.splitToSequence(colorsText)
        .onEach { println(it) }
        .firstOrNull { it.contains('&') }
    println(mixedColor) // "brown&blue"
//sampleEnd
}

Аналогичная функция была также добавлена в CharSequence:

    val mixedColor = colorsText.splitToSequence(regex)

Сериализация 1.3.0-RC

kotlinx.serialization 1.3.0-RC доступна с новыми возможностями JSON-сериализации:

  • Сериализация потоков ввода-вывода Java

  • Управление значениями по умолчанию на уровне свойств

  • Опция исключения нулевых значений из сериализации

  • Настраиваемые дискриминаторы классов в полиморфной сериализации

Узнайте больше в блоге изменений.

Последнее изменение: 14 июля 2023
Что нового в Kotlin 1.6.0 Что нового в Kotlin 1.5.20

© 2010–2023 JetBrains s.r.o. and Kotlin Programming Language contributors
Licensed under the Apache License, Version 2.0.
https://kotlinlang.org/docs/whatsnew1530.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API