The New Kotlin K2 Compiler Is Beta for All Targets
The Kotlin team at JetBrains is continuing to stabilize the new K2 compiler, which will bring major performance improvements, speed up new language feature development, unify all platforms that Kotlin supports, and provide a better architecture for multiplatform projects.
With the 1.9.20 release, the new K2 compiler has reached the Beta stage for all platforms: JVM, Native, JS, and Wasm. This means that you can now try K2 in any Kotlin project.
The Kotlin team has ensured the quality of the new compiler by successfully compiling dozens of user and internal projects. A large number of users are also involved in the stabilization process, trying out the new K2 compiler in their projects and reporting any problems they find.
The Kotlin 1.9.20 release also brings K2 support in the kapt compiler plugin. Now, all essential Kotlin compiler plugins have K2 support. These include kapt, serialization, AtomicFU, Lombok, SAM with receiver, all-open, no-arg, jvm-abi-gen, Android Lint, and the Jetpack Compose compiler plugin. Kotlin Symbol Processing (KSP) with K2 support will be released within a week after Kotlin 1.9.20.
If you use any additional compiler plugins, check their documentation to see if they are compatible with K2.
The next stop is Kotlin 2.0
The next major version of Kotlin is 2.0.0, with the new K2 compiler as the default and stable for all targets.
To address any issues found as quickly as possible, we have planned a series of small, frequent Kotlin 2.0 stabilization releases. These releases will include Beta1, Beta2, Beta3, RC1, and RC2.
At the time of the Kotlin 2.0.0-RC1 release, we plan to ensure binary compatibility with code compiled by other versions of the Kotlin compilers and eliminate poisoning of binaries compiled with K2. This will enable you to use the new K2 compiler in production environments.
Get involved: shape Kotlin 2.0 and try the K2 compiler today
The K2 Compiler is on the verge of completing its stabilization process and becoming enabled by default in Kotlin 2.0. It is crucial that as many developers as possible give K2 a try and report any potential issues.
Your feedback will help us address any problems and ensure that K2 performs flawlessly, even in the most complex scenarios. Just a single compilation of your project using K2 can significantly contribute to reaching the Kotlin 2.0 milestone. Give K2 a try today!
If you already use IntelliJ IDEA 2023.1, 2023.2, the IDE will suggest updating Kotlin to 1.9.20 automatically. You can also update manually by following these instructions. IntelliJ IDEA 2023.3 will include the Kotlin 1.9.20 plugin.
For Android Studio Hedgehog (231) and Iguana (232), the Kotlin 1.9.20 plugin will be included in upcoming Android Studios updates. If you need the command-line compiler, download it from the GitHub release page.
If you already use IntelliJ IDEA (2021.3, 2022.1, 2022.2), your IDE will suggest updating Kotlin to 1.8.0 automatically. You can also update manually for these IDEs by following these instructions.
For IntelliJ IDEA 2022.3, the Kotlin plugin 1.8.0 will be delivered with upcoming IntelliJ IDEA updates.
For Android Studio Flamingo, the Kotlin plugin 1.8.0 is bundled into the latest Canary. For Android Studio Electric Eel, the IDE plugin will be delivered with the upcoming Android Studio updates.
If you need the command-line compiler, download it from the GitHub release page.
If you already use IntelliJ IDEA 213, 221, or 222, the IDE will suggest updating Kotlin to 1.7.20 automatically. You can also update manually by following these instructions.
For Android Studio Dolphin (213), Electric Eel (221), and Flamingo (222), the Kotlin plugin 1.7.20 will be delivered with upcoming Android Studios updates.
If you need the command-line compiler, download it from the GitHub release page.
Kotlin 1.7.0 has been released. It unveils the Alpha version of the new Kotlin/JVM K2 compiler, stabilizes language features, and brings performance improvements for the JVM, JS, and Native platforms.
Here is a list of the major updates in this version:
The new Kotlin К2 compiler is in Alpha now, and it offers serious performance improvements. It is available only for the JVM, and none of the compiler plugins, including kapt, work with it yet.
If you already use IntelliJ IDEA or Android Studio Chipmunk (212), your IDE will suggest updating Kotlin to 1.7.0 automatically. You can also update manually for these IDEs by following these instructions.
For Intellij IDEA 2022.2, and Android Studio Dolphin (213) or Android Studio Electric Eel (221), the Kotlin plugin 1.7.0 will be delivered with upcoming Intellij IDEA and Android Studios updates.
Make sure that you have also updated the kotlinx libraries to compatible versions and specified version 1.7.0 of Kotlin in the build scripts of your existing projects.
If you need the command-line compiler, download it from the GitHub release page.
Starting from 1.7.0, we’re updating our cadence terminology by changing “Milestone” to “Beta”. There are few reasons behind this decision:
We want the Kotlin builds terminology to be more aligned with the standard terminology of the software release cycle. To put it more precisely, “Beta” means we’re done adding new features to that specific version and are working on stabilization. Though the final changes will be implemented, including changes based on your feedback.
Some time ago, M-release compilers were producing “pre-release” code, which made these versions harder to test. This is no longer the case. We want to avoid any confusion and emphasize that trying out Kotlin Beta versions is a simple process and highly encouraged by the Kotlin team.
Last but not least, the term “Beta” itself is a call for feedback from the community. We use it to let you know we want you to share feedback with us.
Please evaluate Kotlin 1.7.0-Beta and share your feedback with us on YouTrack and Slack (for new Slack members: apply to be invited).
Changes to builder inference
Builder inference is a special kind of type inference that is useful when calling generic builder functions. It helps the compiler infer the type arguments of a call using the type information about other calls inside its lambda argument.
Kotlin 1.7.0-Beta includes further changes to builder inference. It brings us closer to builder inference stabilization and completion of one of the items on our roadmap.
With this release, builder inference is automatically activated if a regular type inference cannot get enough information about a type without specifying the -Xenable-builder-inference compiler option, which we introduced in version 1.6.0.
This means that now you can write your own builders that use builder type inference without applying any additional annotations or options. Learn how to write custom generic builders.
The return of the min() and max() collection functions
In Kotlin 1.4, we renamed the min() and max() collection functions to minOrNull() and maxOrNull(). These new names better reflect their behavior – returning null if the receiver collection is empty. It also helped to align the functions’ behavior with naming conventions used throughout the Kotlin collections API.
The same was true of minBy(), maxBy(), minWith(), and maxWith(), which all got their *OrNull() synonyms in Kotlin 1.4. Older functions affected by this change were gradually deprecated.
Kotlin 1.7.0-Beta reintroduces the original function names, but with a non-nullable return type. The renewed min(), max(), minBy(), maxBy(), minWith(), and maxWith() now strictly return the collection element or throw an exception.
fun main() {
val numbers = listOf<Int>()
println(numbers.maxOrNull()) // "null"
println(numbers.max()) // "Exception in… Collection is empty."
}
These types have been added to provide better interoperability when extending generic Java classes and interfaces.
Since Kotlin 1.6.20, you’ve been able to mark a generic type parameter as definitely non-nullable on the use site with the new syntax T & Any. The syntactic form comes from a notation of intersection types and is now limited to a type parameter with nullable upper bounds on the left side of & and non-nullable Any on the right side:
fun <T> elvisLike(x: T, y: T & Any): T & Any = x ?: y
fun main() {
elvisLike<String>("", "").length // OK
elvisLike<String>("", null).length // Error: 'null' cannot be a value of a non-null type
elvisLike<String?>(null, "").length // OK
elvisLike<String?>(null, null).length // Error: 'null' cannot be a value of a non-null type
}
Definitely non-nullable types are enabled by default in this Beta release. No additional steps are required.
Learn more about definitely non-nullable types in the KEEP.
Matching with Regex at a particular position
The Regex.matchAt() and Regex.matchesAt() functions, introduced in 1.5.30, are now Stable. They provide a way to check whether a regular expression has an exact match at a particular position in a String or CharSequence.
matchesAt() checks for a match and returns a boolean result:
fun main(){
val releaseText = "Kotlin 1.7.0 is on its way!"
// 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"
}
matchAt() returns the match if it’s found, or null if it isn’t:
fun main(){
val releaseText = "Kotlin 1.7.0 is on its way!"
val versionRegex = "\d[.]\d[.]\d+".toRegex()
println(versionRegex.matchAt(releaseText, 0)) // "null"
println(versionRegex.matchAt(releaseText, 7)?.value) // "1.7.0"
}
You can try the Alpha version of the new Kotlin/Native memory manager in Kotlin 1.7.0-Beta. This EAP release brings performance improvements to the new memory manager that will improve the developer experience.
The new memory manager eliminates the differences between the JVM and Native platforms. It provides a consistent developer experience in multiplatform projects. For example, you’ll have a much easier time creating new cross-platform mobile applications that work on both Android and iOS.
The new Kotlin/Native memory manager lifts restrictions on object-sharing between threads. It also provides leak-free concurrent programming primitives that are safe and don’t require any special management or annotations.
The new memory manager will become the default one in future versions, so we encourage you to try it now. Learn more about the new memory manager and explore demo projects, or jump right to the migration instructions to try it yourself.
Try using the new memory manager on your projects to see how it works and share your feedback in our issue tracker, YouTrack.
Support for named capturing groups in JS and Native
Since Kotlin 1.7.0-Beta, named capturing groups are supported not only on the JVM (1.8 and later) but on JS and Native as well.
To give a name to a capturing group, use the (?<name>group) syntax in your regular expression. To get the text matched by a group, call the newly introduced MatchGroupCollection.get() function and pass the group name.
Retrieve matched group value by name
Consider this example for matching city coordinates. To get a collection of groups matched by the regular expression, use groups. Compare retrieving a group’s contents by its number (index) and by its name using value:
fun main() {
val regex = "\b(?<city>[A-Za-z\s]+),\s(?<state>[A-Z]{2}):\s(?<areaCode>[0-9]{3})\b".toRegex()
val input = "Coordinates: Austin, TX: 123"
val match = regex.find(input)!!
println(match.groups["city"]?.value) // "Austin" — by name
println(match.groups[2]?.value) // "TX" — by number
}
Named backreferencing
You can now also use group names when backreferencing groups. Backreferences match the same text as previously matched by a capturing group. For this, use the k<name> syntax in your regular expression:
fun backRef() {
val regex = "(?<title>\w+), yes \k<title>".toRegex()
val match = regex.find("Do you copy? Sir, yes Sir!")!!
println(match.value) // "Sir, yes Sir"
println(match.groups["title"]?.value) // "Sir"
}
Named groups in replacement expressions
Finally, named group references can be used with replacement expressions. Consider the replace() function that substitutes all occurrences of the regular expression in the input with a replacement expression, and the replaceFirst() function that swaps the first match only.
Occurrences of ${name} in the replacement string are substituted with the subsequences corresponding to the captured groups with the specified name. Compare replacements in group reference by name and by index:
fun dateReplace() {
val dateRegex = Regex("(?<dd>\d{2})-(?<mm>\d{2})-(?<yyyy>\d{4})")
val input = "Date of birth: 27-04-2022"
println(dateRegex.replace(input, "${yyyy}-${mm}-${dd}")) // "Date of birth: 2022-04-27" — by name
println(dateRegex.replace(input, "$3-$2-$1")) // "Date of birth: 2022-04-27" — by number
}
Try new features and provide feedback
These new features are available in the 1.7.0 preview release, Kotlin 1.7.0-Beta. You can easily install it in your IntelliJ IDEA or Android Studio IDE.
Due to Android Studios plugins renaming (Beta), plug-in installation is available on top of 1.6.20+ versions.
Install Kotlin 1.7.0-Beta in any of the following ways:
If you use the Early Access Preview update channel, the IDE will suggest automatically updating to 1.7.0-Beta as soon as it becomes available.
If you use the Stable update channel, you can change the channel to Early Access Preview at any time by selecting Tools | Kotlin | Configure Kotlin Plugin Updates in your IDE. You’ll then be able to install the latest preview release. Check out these instructions for details.
You can always download the latest versions of these IDEs to get extensive support for Kotlin:
IntelliJ IDEA for developing Kotlin applications for a variety of platforms.
Android Studio for developing Android and cross-platform mobile applications.
Once you’ve installed 1.7.0-Beta, don’t forget to change the Kotlin version to 1.7.0-Beta in your build scripts.
Kotlin 1.6.20 has officially been released. It offers previews of future language features, makes the hierarchical structure the default for multiplatform projects, and brings performance improvements for the JVM, JS, and Native platforms.
In this blog post, you’ll find an overview of the following improvements, along with a complete list of the other evolutionary changes:
New support for defining context-dependent declarations in Kotlin/JVM, resulting from the prototype of context receivers.
With Kotlin 1.6.20, you are no longer limited to having one receiver. If you need more, you can make functions, properties, and classes context-dependent (or contextual) by adding context receivers to their declaration. A contextual declaration does the following:
It requires all declared context receivers to be present in a caller’s scope as implicit receivers.
It brings declared context receivers into its body scope as implicit receivers.
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()
}
}
To enable context receivers in your project, use the -Xcontext-receivers compiler option. You can find a detailed description of the feature and its syntax in the KEEP.
Please note that the implementation is a prototype:
With -Xcontext-receivers enabled, the compiler will produce pre-release binaries that cannot be used in production code.
The IDE support for context receivers is minimal for now.
Definitely non-nullable types
To provide better interoperability when extending generic Java classes and interfaces, Kotlin 1.6.20 allows you to mark a generic type parameter as definitely non-nullable on the use site with the new syntax T & Any. The syntactic form comes from a notation of intersection types and is now limited to a type parameter with nullable upper bounds on the left side of & and non-nullable Any on the right side:
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
}
Set the language version to 1.7 to enable the feature:
Learn more about definitely non-nullable types in the KEEP.
Please note that definitely non-nullable types are in Beta. They are almost stable, but migration steps may be required in the future. We’ll do our best to minimize any changes you have to make.
Support for parallel compilation of a single module in the JVM backend
In Kotlin 1.6.20, we added the experimental JVM IR backend mode to compile all the files in a module in parallel. Parallel compilation can reduce the total compilation time by up to 15%.
Enable the experimental parallel backend mode with the compiler option-Xbackend-threads. Use the following arguments for this option:
N is equal to the number of threads you want to use. It should not be greater than your number of CPU cores; otherwise, parallelization stops being effective because of switching context between threads
0 to use one thread for each CPU core
Gradle can run tasks in parallel, but this type of parallelization doesn’t help a lot when a project (or a major part of a project) is just one big task from Gradle’s perspective. If you have a very big monolithic module, use parallel compilation to compile more quickly. If your project consists of lots of small modules and has a build parallelized by Gradle, adding another layer of parallelization may hurt performance because of context switching.
Parallel compilation has some constraints:
It doesn’t work with kapt because kapt disables the IR backend.
It requires more JVM heap by design. The amount of heap is proportional to the number of threads.
Incremental compilation for development binaries with Kotlin/JS IR compiler
To make Kotlin/JS development with the IR compiler more efficient, we’re introducing a new incremental compilation mode.
When building development binaries with the compileDevelopmentExecutableKotlinJs Gradle task in this mode, the compiler caches the results of previous compilations on the module level. It uses the cached compilation results for unchanged source files during subsequent compilations, making them complete more quickly, especially with small changes. Note that this improvement exclusively targets the development process (shortening the edit-build-debug cycle) and doesn’t affect the building of production artifacts.
To enable incremental compilation for development binaries, add the following line to the project’s gradle.properties:
kotlin.incremental.js.ir=true // false by default
In our test projects, the new mode made incremental compilation up to 30% faster. However, the clean build in this mode became slower because of the need to create and populate the caches.
Kotlin/Native performance improvements
Kotlin 1.6.20 brings some performance updates and bug fixes that affect the LLVM IR that Kotlin generates. According to the benchmarks on our internal projects, we achieved the following performance boosts on average:
15% reduction in execution time
20% reduction in the code size of both release and debug binaries
26% reduction in the compilation time of release binaries
These changes also provide a 10% reduction in compilation time for a debug binary on a large internal project.
To achieve this, we’ve implemented static initialization for some of the compiler-generated synthetic objects, improved the way we structure LLVM IR for every function, and optimized the compiler caches.
Hierarchical structure support for multiplatform projects
Kotlin 1.4.0, we’ve significantly improved the frontend and made IDE import stable.
Previously, there were two ways to add code in a multiplatform project. The first was to insert it in a platform-specific source set, which is limited to one target and can’t be reused by other platforms. The second is to use a common source set shared across all the platforms that are currently supported by Kotlin.
Now you can share source code among several similar native targets that reuse a lot of the common logic and third-party APIs. The technology will provide the correct default dependencies and find the exact API available in the shared code. This eliminates a complex build setup and having to use workarounds to get IDE support for sharing source sets among native targets. It also helps prevent unsafe API usages meant for a different target.
The technology will come in handy for library authors too, as a hierarchical project structure allows them to publish and consume libraries with common APIs for a subset of targets. By default, libraries published with the hierarchical project structure are compatible only with hierarchical structure projects. Learn more about project-library compatibility.
Better code-sharing in your project
Without hierarchical structure support, there is no straightforward way to share code across some but not allKotlin targets. One popular example is sharing code across all iOS targets and having access to iOS-specific dependencies, like Foundation.
Thanks to the hierarchical project structure support, you can now achieve this out of the box. In the new structure, source sets form a hierarchy. You can use platform-specific language features and dependencies available for each target that a given source set compiles to.
For example, consider a typical multiplatform project with two targets — iosArm64 and iosX64 for iOS devices and simulators. The Kotlin tooling understands that both targets have the same function and allows you to access that function from the intermediate source set, iosMain.
The Kotlin toolchain provides the correct default dependencies, like Kotlin/Native stdlib or native libraries. Moreover, Kotlin tooling will try its best to find exactly the API surface area available in the shared code. This prevents such cases as, for example, the use of a macOS-specific function in code shared for Windows.
More opportunities for library authors
When a multiplatform library is published, the API of its intermediate source sets is now properly published alongside it, making it available for consumers. Again, the Kotlin toolchain will automatically figure out the API available in the consumer source set while carefully watching out for unsafe usages, like using an API meant for the JVM in JS code. Learn more about sharing code in libraries.
Configuration and setup
Starting with Kotlin 1.6.20, all your new multiplatform projects will have a hierarchical project structure. No additional setup is required.
If you’ve already turned it on manually, you can remove the deprecated options from gradle.properties:
You can download the latest versions of these IDEs to get extensive support for Kotlin:
IntelliJ IDEA – for developing Kotlin applications for various platforms.
Android Studio – for developing Android and cross-platform mobile applications.
Make sure that you have also updated the kotlinx libraries to compatible versions and specified version 1.6.20 of Kotlin in the build scripts of your existing projects.
If you need the command-line compiler, download it from the Github release page.
Kotlin 1.6.0 ist jetzt offiziell veröffentlicht – mit Stable-Status für abschließende when-Blöcke, dem Code-Coverage-Tool Kover und einem neuen Speichermanager für Kotlin/Native. Auch andere Neuerungen in der Sprache und den Standardbibliotheken, die in 1.5.30 veröffentlicht wurden, wurden in den Status Stable befördert. Vielen Dank für das Feedback, das Sie uns zukommen ließen. Wenn Sie diese neuen Features noch nicht ausprobiert haben – jetzt ist es höchste Zeit!
In diesem Blogbeitrag finden Sie einen Überblick über die folgenden Updates:
Neue Sprachmerkmale: versiegelte when-Anweisungen, suspendierende Funktionen und entsprechende Umwandlungen, Instanziierung von Annotationsklassen, verbesserte Typinferenz für reguläre und Builder-Typen.
Kotlin/JVM mit optimierten delegierten Eigenschaften und wiederholbaren Annotationen.
Kotlin/Native mit der Preview eines neuen Speichermodells, Xcode-13-Unterstützung, Kreuzkompilierung von Windows-Zielen, LLVM- und Linker-Updates, Leistungsupdates und einer einheitlichen Compiler-Plugin-ABI.
Optionale Deaktivierung des Herunterladens von Node.js und Yarn für Kotlin/JS.
Standardbibliothek mit neuen Funktionen für die Standardeingabe, stabiler typeOf()-Funktion, stabiler Duration-API und weiteren stabilen stdlib-Funktionen.
AbonnierenSie unser Blog, um keine Kotlin-Updates zu verpassen!
So führen Sie das Update durch
Wenn Sie IntelliJ IDEA oder Android Studio verwenden, haben Sie die Möglichkeit, automatisch auf die neue Kotlin-Version zu aktualisieren.
Wir haben Sprachmerkmale aus Kotlin 1.5.30 basierend auf Ihrem Feedback stabilisiert.
Abschließende (versiegelte) when-Anweisungen
Versiegeltes when ist eine lang erwartete Funktion des Kotlin-Compilers, die Sie warnt, wenn Ihre when-Anweisungen nicht abschließend sind, also nicht alle Möglichkeiten berücksichtigen. Dadurch wird Ihr Code sicherer, ohne eigene Funktionen für diesen Zweck schreiben zu müssen.
Kotlin hat when-Ausdrücke, die sich auf versiegelte Klassen, Enums und boolesche Typen bezogen, schon immer auf Vollständigkeit überprüft. Dies ist nützlich, wenn Sie Ihre Domäne mit diesen algebraischen Datentypen abbilden. Sie könnten beispielsweise in Ihrer App unterschiedliche Kontaktpräferenzen der Benutzer*innen als versiegelte Klassenhierarchie modellieren:
sealed class Contact {
data class PhoneCall(val number: String) : Contact()
data class TextMessage(val number: String) : Contact()
data class InstantMessage(val type: IMType, val user: String) : Contact()
}
Wenn Sie nun einen Ausdruck schreiben, der abhängig von der Kontakteinstellung ein unterschiedliches Ergebnis zurückgibt, meldet der Compiler einen Fehler, wenn Sie vergessen haben, alle Typen zu berücksichtigen, die in Ihrer App möglich sind:
fun Rates.computeMessageCost(contact: Contact): Cost =
when (contact) { // ERROR: 'when' expression must be exhaustive
is Contact.PhoneCall -> phoneCallCost
is Contact.TextMessage -> textMessageCost
}
Dies ist eine große Hilfe sowohl beim Schreiben des Codes als auch bei der späteren Wartung. Wenn Sie später eine weitere Kontaktoption hinzufügen, können Sie sich darauf verlassen, dass der Compiler Sie daran erinnert, die verschiedenen Kontaktpräferenzen überall in Ihrem Code zu berücksichtigen.
Vor Kotlin 1.6 wurde jedoch die when-Anweisung im folgenden Code erfolgreich kompiliert, obwohl versäumt wurde, den Versand einer Nachricht per Instant Messaging zu implementieren:
fun sendAnnouncement(contact: Contact, announcement: Announcement) {
when (contact) {
is Contact.PhoneCall -> schedulePhoneCall(contact.number, announcement)
is Contact.TextMessage -> sendTextMessage(contact.number, announcement)
}
}
Das Problem wurde nur von einer nachrangigen IDE-Inspektion gemeldet, ohne irgendwelche Meldungen vom Compiler. Ab Kotlin 1.6 wird die folgende Compiler-Warnung ausgegeben:
Non-exhaustive 'when' statements on sealed class/interface will be prohibited in 1.7. Add an 'is InstantMessage' branch or 'else' branch instead.
In Kotlin 1.7 wird dies als Fehler gewertet, damit solche Fälle nicht übersehen werden können. Im Ticket KT-47709 finden Sie eine genauere Erläuterung der Änderung und ihrer Auswirkungen.
Suspendierende Funktionen als Supertypen
Kotlin 1.6 stabilisiert die Unterstützung für die Implementierung von suspend-Funktionstypen als Superschnittstellen. Dies war eines der fehlenden Puzzleteile beim Design der Kotlin-Coroutinen.
Bei der Gestaltung von Kotlin-APIs ist es idiomatisch, Funktionstypen zu akzeptieren, wenn das Verhalten von Bibliotheksfunktionen anpassbar sein soll. Beispielsweise verfügt die Schnittstelle Job der API kotlinx.coroutines über eine Memberfunktion, die ungefähr so aussieht:
fun invokeOnCompletion(handler: () -> Unit)
Sie können diese Funktion bequem mit Lambdas wie nachAbschlussAufrufen { etwasTun() } verwenden. Wenn Sie eine Klasse haben, die auf den Abschluss reagieren soll, können Sie Ihren Code vereinfachen und optimieren, indem Sie den Funktionstyp () -> Unit direkt in Ihrer Klasse implementieren, sodass Sie keine zusätzliche Lambdafunktion benötigen:
class MyCompletionHandler : () -> Unit {
override fun invoke() { doSomething() }
}
Ab Kotlin 1.6 ist diese Optimierung mit suspendierenden Funktionen möglich. Nehmen wir an, Ihre API akzeptiert suspendierende Funktionstypen wie diese:
public fun launchOnClick(action: suspend () -> Unit) {}
In diesem Fall sind Sie nicht mehr darauf beschränkt, Lambdas und Referenzen auf suspendierende Funktionen an diesen Code zu übergeben. Sie können die entsprechenden suspendierenden Funktionstypen auch in einer Klasse implementieren:
class MyClickAction : suspend () -> Unit {
override suspend fun invoke() { doSomething() }
}
Umwandlungen in suspendierende Typen
Kotlin 1.6 befördert die Umwandlungen von regulären zu suspendierenden Funktionstypen in den stabilen Status. Wenn bei einem Parameter ein suspendierender Typ erwartet wird, können Sie jetzt einen geeigneten regulären Funktionstyp übergeben. Der Compiler führt die Umwandlung automatisch durch.
Dadurch wird eine kleine, aber störende Inkonsistenz beim Zusammenspiel zwischen regulären und suspendierenden Funktionen in Kotlin behoben. Wenn Sie eine Funktion höherer Ordnung haben, die eine suspendierende Funktion akzeptiert (Beispiel: ein collect-Aufruf auf einem Kotlin-Flow), müssen Sie zum Aufrufen nicht unbedingt ein Lambda wie im folgenden Code verwenden:
flow.collect { processItem(it) }
fun processItem(item: Item) { /* ... */ }
Stattdessen könnte es praktischer sein, eine Referenz auf die Funktion processItem an den collect-Aufruf zu übergeben – die Wirkung ist identisch.
flow.collect(::processItem)
Sie könnten dann eine Referenz auf Ihre Verarbeitungsfunktion in eine Variable extrahieren, um das Verhalten in Ihrem Code entsprechend anzupassen. Allerdings funktionierte dies in den Kotlin-Versionen vor 1.6 nicht. Dies liegt daran, dass Sie eine reguläre Funktion als Parameter übergeben, wo ein suspendierender Typ erwartet wird:
val processingFunction = ::processItem
flow.collect(processingFunction) // ERROR: Type mismatch
Der obige Code wird in Kotlin 1.6 einwandfrei kompiliert und funktioniert auch wie erwartet.
Verbesserte Typinferenz für rekursive generische Typen
Ab 1.6.0 kann der Kotlin-Compiler standardmäßig ein Typargument basierend nur auf den oberen Grenzen des entsprechenden Typparameters ableiten, wenn dieser ein rekursiver generischer Typ ist. Dies ermöglicht verschiedene Patterns mit rekursiven generischen Typen, die in Java häufig für Builder-APIs verwendet werden.
// Vor 1.5.30
val containerA = PostgreSQLContainer<nothing>(DockerImageName.parse("postgres:13-alpine")).apply {
withDatabaseName("db")
withUsername("user")
withPassword("password")
withInitScript("sql/schema.sql")
}
// Mit Compileroption in 1.5.30 oder standardmäßig ab 1.6.0
val containerB = PostgreSQLContainer(DockerImageName.parse("postgres:13-alpine"))
.withDatabaseName("db")
.withUsername("user")
.withPassword("password")
.withInitScript("sql/schema.sql")
Verbesserte Builder-Inferenz
In Kotlin 1.5.30 wurde die Compileroption -Xunrestricted-builder-inference eingeführt, um innerhalb von Builder-Lambdas auf Typinformationen über einen Builder-Aufruf zugreifen zu können. Konkret bedeutet dies die Möglichkeit, Aufrufe zu tätigen, die eine Instanz eines noch nicht bekannten Typs zurückgeben, z. B. get() in einem buildList()-Lambda.
Ab 1.6.0 müssen Sie nicht die Option -Xunrestricted-builder-inference angeben, um diese bisher unzulässigen Aufrufe zu tätigen. Mit der Compileroption -Xenable-builder-inference können Sie jetzt ohne Verwendung der Annotation @BuilderInference Ihre eigenen generischen Builder schreiben und Builder-Inferenzen automatisch aktivieren, wenn die reguläre Typinferenz keine Typinformationen ergibt.
Längere Unterstützung früherer API-Versionen
Ab Kotlin 1.6.0 können Sie bei der Entwicklung außer der aktuellen stabilen API-Version drei frühere Versionen (anstelle der bisherigen zwei) verwenden. Derzeit stehen Ihnen also die API-Versionen 1.3, 1.4, 1.5 und 1.6 zur Verfügung.
Kotlin/JVM
Wiederholbare Annotationen mit Laufzeiterhaltung.Wie Java 8 kennt auch Kotlin wiederholbare Annotationen. Ab Kotlin 1.6 ist diese Funktion Java-kompatibel. @kotlin.annotation.Repeatable akzeptiert jetzt jede Retention-Angabe und macht die Annotation sowohl in Kotlin als auch in Java wiederholbar. Außerdem werden wiederholbare Java-Annotationen jetzt auch auf Kotlin-Seite unterstützt.
Kotlin/Native
Ab sofort können Sie die experimentelle Version des neuen Kotlin/Native-Speichermanagers ausprobieren. Mit diesem Feature kommen wir unserem Ziel einer konsistenten Entwicklererfahrung bei Multiplattform-Projekten näher. Der neue Speichermanager hebt die bestehenden Beschränkungen für die gemeinsame Objektnutzung zwischen Threads auf und bietet Primitive für die nebenläufige Programmierung, die sicher sind, Lecks vermeiden und keine spezielle Verwaltung oder Annotationen von Seiten des Entwicklungsteams erfordern.
Sie können Xcode unbesorgt aktualisieren und an Ihren Kotlin-Projekten weiterarbeiten, da Kotlin/Native jetzt Xcode 13 unterstützt.
Kompilieren von Windows-Zielen auf beliebigen Hosts. Sie können die Windows-Ziele mingwX64 und mingwX86 auf jedem Host kompilieren, der Kotlin/Native unterstützt.
Wir haben die LLVM-Abhängigkeit, die Kotlin/Native unter der Haube verwendet, überarbeitet. Neben einer auf 11.1.0 aktualisierten LLVM-Version und einer verringerten Größe der Abhängigkeiten bietet dies einige weitere Vorteile.
Vereinheitlichung der Compiler-Plugin-ABI mit den JVM- und JS-IR-Backends. Jetzt kann das Gradle-Plugin für Kotlin Multiplatform das einbettbare Compiler-Jar, das für die JVM- und JS-IR-Backends verwendet wird, auch für Kotlin/Native verwenden. Sie können jetzt dieselben Compiler-Plugin-Artefakte für die Native-Plattform und andere unterstützte Plattformen verwenden.
Kotlin/JS
Für Buildvorgänge auf einem Server ohne Internetverbindung können Sie jetzt das Herunterladen von Node.js und Yarn für Kotlin/JS-Projekte deaktivieren und die auf dem Host vorinstallierten Instanzen verwenden.
Kover
Die genaue Ermittlung der Code-Coverage war vom ersten Kotlin-Release an eine Herausforderung. Einige großartige Tools wie JaCoCo verarbeiten Kotlin-Code, sind jedoch nicht vollständig in unsere Gradle-Toolchain und unsere Multiplattform-Projekte integriert. In dieser Kotlin-Version haben wir begonnen, dieses Problem anzupacken. Unser neues Gradle-Plugin Kover ermittelt die Code-Coverage von Kotlin-Code, der mit dem Kotlin/JVM-Compiler kompiliert wurde. Das Tool befindet es sich in einer frühen Entwicklungsphase und gilt als experimentell – wir freuen uns auf Ihr Feedback in GitHub.
Regex-Funktion zum Aufteilen von Zeichenfolgen in Sequenzen
Außerdem können Sie jetzt compareTo mit Infixnotation verwenden, und wir haben an der Konsistenz zwischen den replace()-Funktionen in JVM und JS gearbeitet.
Neue Funktionen für die Standardeingabe
In Kotlin 1.6.0 ist der Nicht-Null-Assertion-Operator !! nach dem Lesen einer Zeile von der Standardeingabe nicht mehr erforderlich. Dies vereinfacht den Einstieg für Neulinge und erleichtert das Unterrichten von Kotlin.
Wir bieten die folgenden neuen Möglichkeiten für das Lesen von der Konsole:
readln() löst eine Ausnahme aus, wenn das Dateiende erreicht wurde. Sie können diese Funktion verwenden, statt das Ergebnis von readLine() mit dem Operator !! auf null zu überprüfen.
Die neue Funktion readlnOrNull() ist eine Alternative, die null zurückgibt. Sie verhält sich also wie bisher readLine() – nur dass die Funktion jetzt einen passenderen Namen hat.
Diese Funktionen sind für JVM und Native verfügbar. Sie sind analog zu println() benannt – für Neueinsteiger*innen ist dies besonders hilfreich.
fun main() {
println("Input two integer numbers each on a separate line")
val num1 = readln().toInt()
val num2 = readln().toInt()
println("The sum of $num1 and $num2 is ${num1 + num2}")
}
Stabile Duration-API
Mithilfe Ihres Feedbacks haben wir die API für Zeiträume stabilisiert und den entsprechenden Roadmap-Eintrag geschlossen.
Die days-Komponente der Funktion toComponents ist jetzt vom Typ Long statt Int, um das Abschneiden von Werten zu vermeiden.
Die Enum DurationUnitist kein Typalias mehr. Es gibt keine Fälle, in denen es als Typalias für Java.util.concurrent.TimeUnit in der JVM verwendet wird.
Als Wunsch der Community sind Erweiterungseigenschaften wie Int.seconds wieder da. Um ihre Anwendbarkeit einzuschränken, sind sie nur im Companion-Objekt der Klasse Duration verfügbar.
import kotlin.time.Duration.Companion.seconds
fun main() {
//sampleStart
val duration = 5000.seconds
println("There are ${duration.inWholeMinutes} minutes in ${duration.inWholeHours} hours")
//sampleEnd
}
Stabiles typeOf()
In Kotlin 1.6.0 hat typeOf() den Status Stable. Der entsprechende Roadmap-Eintrag wurde geschlossen. Seit 1.3.40 war typeOf() auf der JVM-Plattform als experimentelle API verfügbar. Jetzt ist die Funktion auf jeder Kotlin-Plattform verfügbar und gibt einen beliebigen Kotlin-Typ, den der Compiler ableiten kann, als KType zurück.
inline fun <reified T> renderType(): String {
val type = typeOf<T>()
return type.toString()
}
fun main() {
val fromExplicitType = typeOf<Int>()
val fromReifiedType = renderType<List<Int>>()
}
Stabile Collection-Builder
Kotlin 1.6.0 befördert Collection-Builder-Funktionen wie buildMap(), buildList() und buildSet() in den Stable-Status. Von den Buildern zurückgegebene Collections sind jetzt im schreibgeschützten Zustand serialisierbar.
Stabile Bitrotation für Ganzzahlen
Die Funktionen rotateLeft() und rotateRight(), die die binäre Darstellung einer Zahl um die angegebene Anzahl von Bits nach links oder rechts rotieren, haben ab Kotlin 1.6.0 den Status Stable.
fun main() {
//sampleStart
val number: Short = 0b10001
println(number.rotateRight(2).toString(radix = 2)) // 100000000000100
println(number.rotateLeft(2).toString(radix = 2)) // 1000100
//sampleEnd
}
Stabile Regex-Funktion zum Aufteilen von Zeichenfolgen in Sequenzen
Eine weitere seit Kotlin 1.6.0 stabile Funktion ist splitToSequence() zum Aufteilen einer Zeichenfolge in eine Sequenz mithilfe eines regulären Ausdrucks.
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
}
CompareTo in Infixnotation
Die Funktion Comparable.compareTo zum Vergleichen von zwei Objekten kann jetzt in Infixnotation aufgerufen werden:
class WrappedText(val text: String) : Comparable<WrappedText> {
override fun compareTo(other: WrappedText): Int =
this.text compareTo other.text
}
Einheitlichkeit zwischen JVM und JS bei replace() und replaceFirst()
Vor Kotlin 1.6.0 verhielten sich die Regex-Funktionen replace() und replaceFirst() auf JVM und JS unterschiedlich, wenn die Ersetzungszeichenfolge eine Gruppenreferenz enthielt. Das Verhalten von Kotlin/JS wurde an das Verhalten der JVM angepasst.
Kompatibilität
Wie bei allen Feature-Releases werden mit Kotlin 1.6.0 einige Deprecation-Zyklen für zuvor angekündigte Änderungen abgeschlossen. Alle diese Fälle wurden vom Sprachkomitee sorgfältig geprüft und sind im Kompatibilitätsleitfaden für Kotlin 1.6 aufgeführt. Sie können diese Änderungen auch in YouTrack einsehen.
Installation von Kotlin 1.6.0
Wenn Sie IntelliJ IDEA oder Android Studio verwenden, schlägt Ihnen die IDE automatisch die Aktualisierung auf Kotlin 1.6.0 vor. Alternativ ist auch eine manuelle Aktualisierung gemäß dieser Anleitung möglich.
Sie können die neuesten Versionen dieser IDEs herunterladen, um eine umfassende Kotlin-Unterstützung zu erhalten:
IntelliJ IDEA – zur Entwicklung von Kotlin-Anwendungen für verschiedene Plattformen.
Android Studio – zur Entwicklung von Android-Apps und plattformübergreifenden Mobilanwendungen.
Achten Sie darauf, auch die kotlinx-Bibliotheken auf die kompatiblen Versionen zu aktualisieren und die Kotlin-Version 1.6.0 in den Build-Skripten Ihrer bestehenden Projekte anzugeben.
Den Befehlszeilen-Compiler können Sie bei Bedarf von der GitHub-Release-Seite herunterladen.
Melden Sie Probleme in unserem Issue-Tracker, YouTrack.
Bleiben Sie stets auf dem neuesten Stand der Kotlin-Entwicklung! Abonnieren Sie unsere Kotlin-Updates, indem Sie das Formular rechts neben diesem Beitrag ausfüllen.
Enjoy a better debugging experience, improved IDE performance, new editor inline hints for ranges and chain calls, and more improvements for Kotlin in IntelliJ IDEA 2021.3:
IntelliJ IDEA 2021.3 brings an improved debugger that works better with inline functions, has a smarter Step Into action, and works faster with coroutines.
Inline stack frames
The debugger can now detect Kotlin inline functions and show inline function calls in the stack trace panel. You can navigate to these calls and inspect and evaluate the variables of each frame.
Smart Step Into
The latest IntelliJ IDEA comes with the new Smart Stepinto action, which makes the debugging process more predictable. It allows you to stop at any child function when one line of Kotlin code calls several methods.
When you find yourself at a line with more than one method call, just click the Step Into button located in the top pane of the Debug tool window, or use the F7 shortcut. The IDE will then highlight the places where you can step into the code, and you’ll be able to select the line you want by clicking on it.
This feature is available by default. If you want to disable this default behavior for the Step Into action, go to Preferences / Settings | Build, Execution, Deployment | Debugger | Stepping | Kotlin and deselect the Always do smart step into checkbox. If you do so, the Smart Step Into action will still be available via the ⇧ F7 shortcut on macOS or Shift+F7 on Windows and Linux.
Coroutines debugger speed-up
The Coroutine debugger now calculates information about coroutines much faster. We did some research and found a way to optimize calls to JVM Debugger. Now the coroutine panel will load instantly, even if there are a lot of coroutines. Thanks to this change, it has become much more comfortable to use the coroutine debugger in sessions with a remote client.
Performance improvements
IntelliJ IDEA 2021.3 brings some major performance improvements for Kotlin. Besides a bunch of fixes for freezes and IDE slowdowns, it also comes with a compiler reference index, which significantly improves the speed of the “Find Usages” action and a built-in cache recovery troubleshooting tool designed to solve problems related to cache inconsistencies without requiring complete cache invalidation.
Compiler Reference Index
The new compiler index reference allows you to find declaration usages much faster. Using the information from the compiler, the search is performed only in files that actually use the declaration you are looking for, and not in all possible files. The more common the declaration name, the more effective the optimization is. The new compiler index reference also improves the search for declarations that have implicit calls (like Data Classes, as they generate `componentN` functions that are used in destructive declaration). Here’s an example of how this new feature improves the performance of “Find Usages” with and without a compiler index for an IntelliJ-community project on a Linux agent for different declarations:
The Compiler Reference Index feature is available for Maven and IntelliJ built-in build systems.
Cache recovery
Cache recovery is a useful built-in troubleshooting tool that has been introduced to solve problems related to cache inconsistencies without requiring complete cache invalidation when possible. The new Run Guided Cache Recovery… action offers two main advantages compared to Invalidate Caches: Run Guided Cache Recovery… : it can be performed per project, and it’s faster.
The action consists of a sequence of several actions, with the ability to stop after each of them. Each action will take less time than reindexing and will not lead to the loss of caches for other projects. The final action – Invalidate Caches and Restart – will reboot the IDE. After each action is performed, the user will be shown a notification with the option to abort the cache recovery process or perform the next step. The action can be invoked right from the main menu.
Editor inline hints
IntelliJ IDEA 2021.3 comes with new editor inline hints for ranges, chain calls, and VCS changes.
Inline hints for ranges
With the new IntelliJ IDEA it has become much easier to interpret range bounds, as it comes with new inline hints that explain with plain mathematical signs what the words or symbols used for the ranges mean:
This feature is enabled by default. If you want to switch it off, right-click on a hint and select Disable ‘Ranges’ hints type or go to Preferences / Settings | Editor | Inline hints | Kotlin | Ranges and deselect the Show ranges checkbox there.
Chain calls
IntelliJ IDEA 2021.3 displays type hints for long method chains. Previously, these hints were available only for Java, but now they work with Kotlin as well. It is especially useful to see the type of each call as a type hint for long method chains with generics. For simple builders where the type is obvious, the IDE will hide the type hint.
New refactorings and improved inspections and intentions
IntelliJ IDEA 2021.3 comes with a new extract constant refactoring, and Constant conditions inspection. It also brings an improved Possibly blocking call in non-blocking context inspection and improved intention preview.
Extract constant refactoring
A new refactoring allows you to extract constants in Kotlin. To use it, put the caret on a string and press ⌥⌘C on macOS or Ctrl+Alt+C on Windows and Linux.
Constant conditions inspection
With the help of new Constant conditions inspection, IntelliJ IDEA can report non-trivial conditions and values that are statically known to be always true, false, null, or zero. This inspection tracks and warns you about bugs that should be fixed and redundant code.
You can find this inspection in Preferences / Settings | Editor | Inspections | Kotlin | Probable bugs.
Improved intention preview
IntelliJ IDEA 2021.3 comes with an improved intention preview. Now it:
works for more intention actions and quick-fixes in Kotlin.
displays informative HTML descriptions for intention actions which are impossible to show a preview for.
partially shows the possible outcomes for an action that modifies several files.
Improved Possibly blocking call in non-blocking context inspection
The Possibly blocking call in non-blocking context inspection warns you if you use a coroutine in the wrong context. The new IntelliJ IDEA comes with an improved version of this inspection that covers more cases so you can customize to work better in your particular environment. It is now possible for the inspection to prompt you about the problem and offer a context-dependent quick-fix.
More features
IntelliJ IDEA 2021.3 also brings more IDE features that improve the Kotlin experience. You can read more about them in the related IntelliJ IDEA EAP blog posts:
Kotlin 1.6.0 is now officially released with Stable exhaustive whens, Kover, and a new memory manager for Kotlin/Native. Other language and standard library features released in 1.5.30 became Stable as well. Thanks for the feedback you’ve shared with us. If you still haven’t tried these new features out, now is the time!
In this blog post, you can find an overview of the following updates:
Language features with sealed when statements, suspending functions and suspend conversions, instantiation of annotation classes, improved regular type inference and builder type inference.
Kotlin/JVM with optimized delegated properties and repeatable annotations.
Kotlin/Native with a preview of a new memory model, Xcode 13 support, a cross-compilation of Windows targets, LLVM and linker updates, performance updates, and unified compiler plugin ABI.
Option to disable downloading of Node.js and Yarn for Kotlin/JS.
We stabilized features from Kotlin 1.5.30 based on your feedback.
Sealed (exhaustive) when statements
Sealed when is a long-awaited feature that makes the Kotlin compiler warn you if your when statements are not exhaustive. This makes your code safer without having to introduce your own functions.
Kotlin has always been exhaustive in checking whenexpressions for sealed classes, enums, and Boolean types. It is useful when you model your domain with those algebraic data types. For example, you might have different contract preferences for users of your app modeled as a sealed class hierarchy:
sealed class Contact {
data class PhoneCall(val number: String) : Contact()
data class TextMessage(val number: String) : Contact()
data class InstantMessage(val type: IMType, val user: String) : Contact()
}
Now, if you write an expression that returns a different result based on different contact preference, the compiler will flag an error if you forget to handle all of the types you have in your app:
fun Rates.computeMessageCost(contact: Contact): Cost =
when (contact) { // ERROR: 'when' expression must be exhaustive
is Contact.PhoneCall -> phoneCallCost
is Contact.TextMessage -> textMessageCost
}
This is a great help, both in writing code and for future maintenance. If you add a different type of contact preference later, you know that the compiler will make sure you have not forgotten to handle the different types of contact preferences all around your code.
However, before Kotlin 1.6, the following code that uses whenstatements successfully compiles, even though it totally forgets to handle sending an announcement to your users via instant message:
fun sendAnnouncement(contact: Contact, announcement: Announcement) {
when (contact) {
is Contact.PhoneCall -> schedulePhoneCall(contact.number, announcement)
is Contact.TextMessage -> sendTextMessage(contact.number, announcement)
}
}
Only a weak IDE inspection was reported, without any messages from the compiler. Starting from Kotlin 1.6, it produces the following compiler warning:
Non-exhaustive 'when' statements on sealed class/interface will be prohibited in 1.7. Add an 'is InstantMessage' branch or 'else' branch instead.
In Kotlin 1.7 it will become an error, leaving no chance to accidentally forget it. Please see KT-47709 for a more detailed explanation of the change and its effects.
Suspending functions as supertypes
Kotlin 1.6 stabilizes support for implementing suspend functional types as super interfaces. It was one of the missing pieces in the Kotlin coroutines design.
When you design Kotlin APIs, it is idiomatic to accept functional types when you need to customize the behavior of various library functions. For example, kotlinx.coroutines API has a member function in its Job interface that looks similar to this:
fun invokeOnCompletion(handler: () -> Unit)
You can conveniently use this function with lambdas like invokeOnCompletion { doSomething() }. If you have a class that you wanted to handle the completion with, you can streamline and optimize your code by implementing the functional type () -> Unit directly in your class without creating an additional lambda:
class MyCompletionHandler : () -> Unit {
override fun invoke() { doSomething() }
}
Starting from Kotlin 1.6 this optimization is possible with suspending functions. If your APIs accept suspending functional types, like this:
public fun launchOnClick(action: suspend () -> Unit) {}
… then you are not limited to passing lambdas and suspending function references to this code anymore. You can implement the corresponding suspending functional types in a class, too:
class MyClickAction : suspend () -> Unit {
override suspend fun invoke() { doSomething() }
}
Suspend conversions
Kotlin 1.6 stabilizes conversions from regular to suspending functional types. You can now pass any expression of a suitable regular functional type where suspending is expected as a parameter. The compiler will perform a conversion automatically.
This fixes a small but annoying inconsistency in the interaction between regular and suspending functions in Kotlin. In you have a higher-order function that accepts a suspending function, like a collect call on a Kotlin Flow, then instead of using a lambda to call it, like this:
flow.collect { processItem(it) }
fun processItem(item: Item) { /* ... */ }
… you might find it convenient to pass a reference to the processItem function to the collect call to the same effect:
flow.collect(::processItem)
You would then extract a reference to your processing function into a variable in order to customize the behavior in your code. However, that didn’t work in Kotlin versions prior to 1.6. This is because you have a regular function that is being passed as a parameter of a suspending type:
val processingFunction = ::processItem
flow.collect(processingFunction) // ERROR: Type mismatch
In Kotlin 1.6, the above code compiles and works, too.
Improved type inference for recursive generic types
From 1.6.0, the Kotlin compiler can infer a type argument based only on the upper bounds of the corresponding type parameter if it is a recursive generic by default. This makes it possible to create various patterns with recursive generic types that are often used in Java to make builder APIs.
// Before 1.5.30
val containerA = PostgreSQLContainer<nothing>(DockerImageName.parse("postgres:13-alpine")).apply {
withDatabaseName("db")
withUsername("user")
withPassword("password")
withInitScript("sql/schema.sql")
}
// With compiler option in 1.5.30 or by default starting with 1.6.0
val containerB = PostgreSQLContainer(DockerImageName.parse("postgres:13-alpine"))
.withDatabaseName("db")
.withUsername("user")
.withPassword("password")
.withInitScript("sql/schema.sql")
Builder inference improvements
Kotlin 1.5.30 introduced the -Xunrestricted-builder-inference compiler option, which made type information about a builder call available to get inside builder lambdas. Namely, it introduced the ability of making calls that return an instance of a not yet inferred type, such as get() inside a buildList() lambda.
Starting with 1.6.0, you don’t need to specify -Xunrestricted-builder-inference to make previously prohibited calls. With the -Xenable-builder-inference compiler option, you can now also write your own generic builders without applying the @BuilderInference annotation and automatically enable builder inference if regular type inference cannot resolve type information.
Supporting previous API versions for a longer period
Starting with Kotlin 1.6.0, you can now develop using three previous API versions instead of two (along with the current stable one). Currently, this includes API versions 1.3, 1.4, 1.5, and 1.6.
Kotlin/JVM
Repeatable annotations with runtime retention.Kotlin, like Java 8, has repeatable annotations. With Kotlin 1.6, the feature is compatible with Java, and @kotlin.annotation.Repeatable now accepts any retention and makes the annotation repeatable both in Kotlin and Java. Java repeatable annotations are now also supported from the Kotlin side.
Kotlin/Native
Now you can try the Experimental version of the new Kotlin/Native memory manager. With this feature we are moving closer to providing a consistent developer experience in multiplatform projects. This means that the new memory manager lifts the existing restrictions on object sharing between threads and provides fully leak-free concurrent programming primitives that are safe and don’t require any special management or annotations from the developers.
You can freely update your Xcode and continue working on your Kotlin projects, as Kotlin/Native now supports Xcode 13.
Compilation of Windows targets on any host. You can compile Windows targets mingwX64 and mingwX86 on any host that supports Kotlin/Native.
We’ve reworked the LLVM dependency that Kotlin/Native uses under the hood. This brings some benefits along with an updated LLVM version to 11.1.0 and decreased dependency size.
Unified compiler plugin ABI with JVM and JS IR backends. Now, the Kotlin Multiplatform Gradle plugin is able to use the embeddable compiler jar – the one used for JVM and JS IR backends – for Kotlin/Native. You can now use the same compiler plugin artifacts for Native and other supported platforms.
Kotlin/JS
For building on a server without internet connectivity, you can now disable downloading Node.js and Yarn for Kotlin/JS projects and use the instances already installed on the host.
Kover
Since the first release, precise measurement of code coverage has been a challenge. Some great tools like JaCoCo work with Kotlin code, but they are not fully integrated with our Gradle toolchain and multiplatform projects. In this Kotlin release, we have started to fix this issue. Meet Kover, our new Gradle plugin that measures code coverage for Kotlin code built with the Kotlin/JVM compiler. Now it is in the early development stage and is experimental – we would appreciate your feedback on it in GitHub.
Regex function for splitting a string into a sequence
We’ve also added the ability to call compareTo in infix notation and invested in providing a consistent experience with replace() functions on JVM and JS.
New functions for standard input
In Kotlin 1.6.0, we got rid of the need to use the not-null assertion operator !! after reading a line from the standard input in order to improve the experience for newcomers and simplify teaching Kotlin.
We provide new functions for reading from the console with the following experience:
readln() throws an exception when EOF has been reached. Use this function instead of checking the result of readLine() for null with the !! operator.
The new readlnOrNull() is a null-returning alternative. It behaves in the same way as the former readLine() but has a more representative name.
These functions are now available for JVM and Native. The naming convention for these functions is now consistent with the println() counterpart, which is especially important for newcomers.
fun main() {
println("Input two integer numbers each on a separate line")
val num1 = readln().toInt()
val num2 = readln().toInt()
println("The sum of $num1 and $num2 is ${num1 + num2}")
}
The days component of the toComponents function now has the Long type instead of Int to avoid cutting off values.
The DurationUnitenum is now not a type alias. There are no cases of using it as a type alias for java.util.concurrent.TimeUnit on JVM.
In response to community feedback, we’re bringing back extension properties like Int.seconds. To limit their applicability, they are available only in the Companion of the Duration class.
import kotlin.time.Duration.Companion.seconds
fun main() {
//sampleStart
val duration = 5000.seconds
println("There are ${duration.inWholeMinutes} minutes in ${duration.inWholeHours} hours")
//sampleEnd
}
Stable typeOf()
Kotlin 1.6.0 brings StabletypeOf() and closes the corresponding roadmap item. Since 1.3.40, typeOf() has been available on the JVM platform as an experimental API, and now you can use it on any Kotlin platform and get a KType representation of any Kotlin type that the compiler can infer.
inline fun <reified T> renderType(): String {
val type = typeOf<T>()
return type.toString()
}
fun main() {
val fromExplicitType = typeOf<Int>()
val fromReifiedType = renderType<List<Int>>()
}
Stable collection builders
Kotlin 1.6.0 promotes collection builder functions – buildMap(), buildList(), and buildSet()– to Stable. Collections returned by the builders are now serializable in their read-only state.
Stable bit rotation operations for integers
In Kotlin 1.6.0, the rotateLeft() and rotateRight() functions, which rotate the binary representation of the number left or right by the specified number of bits, became Stable.
fun main() {
//sampleStart
val number: Short = 0b10001
println(number.rotateRight(2).toString(radix = 2)) // 100000000000100
println(number.rotateLeft(2).toString(radix = 2)) // 1000100
//sampleEnd
}
Stable Regex function for splitting a string into a sequence
Kotlin 1.6.0 also stabilizes splitToSequence() – a function for regular expressions that splits a string into a sequence.
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
}
compareTo in infix notation
We’ve added the ability to call the Comparable.compareTo function in infix notation to compare two objects for order:
class WrappedText(val text: String) : Comparable<WrappedText> {
override fun compareTo(other: WrappedText): Int =
this.text compareTo other.text
}
Consistent replace() and replaceFirst() on JVM and JS
Before Kotlin 1.6.0, the replace() and replaceFirst() Regex functions behaved differently on JVM and JS when the replacement string contained a group reference. The behavior on Kotlin/JS is now consistent with that on JVM.
Compatibility
As with all feature releases, some deprecation cycles of previously announced changes are coming to an end with Kotlin 1.6.0. All of these cases were carefully reviewed by the language committee and are listed in the Compatibility Guide for Kotlin 1.6. You can also explore these changes on YouTrack.
How to install Kotlin 1.6.0
If you’re using IntelliJ IDEA or Android Studio, your IDE will suggest updating Kotlin to 1.6.0 automatically. Alternatively, you can update manually by following these instructions.
You can download the latest versions of these IDEs to get extensive support for Kotlin:
IntelliJ IDEA – for developing Kotlin applications for various platforms.
Android Studio – for developing Android and cross-platform mobile applications.
Make sure that you have also updated the kotlinx libraries to the compatible versions and specified Kotlin 1.6.0 in the build scripts of your existing projects.
If you need the command-line compiler, download it from the Github release page.
Since Kotlin 1.5.30 is the last incremental release before Kotlin 1.6.0, it includes many experimental language and standard library features that we are planning to release in Kotlin 1.6.0. Give them a try and share your feedback with us, you can really influence the final result! These experimental features include sealed when statements, changes to opt-in requirements, instantiation of annotation classes, improvements to the Duration and Regex stdlib APIs, and more.
With Kotlin 1.5.30, you can also enjoy native support for Apple silicon, the promotion of the Kotlin/JS IR backend to Beta, the ability to use custom cinterop libraries in the shared native code of multiplatform applications, support for Java toolchains provided by the Kotlin Gradle plugin, and much more.
This blog post provides an overview of the updates in this release:
Language improvements, including sealed when statements, support for suspend functions as supertypes, and changes to opt-in requirements.
Multiplatform improvements, including the ability to use custom cinterop libraries in shared native code and support for XCFrameworks as an output format.
Kotlin/JVM improvements, including instantiation of annotation classes and improved configuration of nullability annotation support.
Kotlin/Native improvements, including native support for Apple silicon and an improved Kotlin DSL for the CocoaPods Gradle plugin.
Kotlin/JS IR improvements, including the promotion of the JS IR backend to Beta and a better debugging experience for the new backend.
Gradle improvements, including support for Java toolchains and easier ways to explicitly set the Kotlin daemon’s JVM arguments.
Stay up to date with information about the latest Kotlin features! Subscribe to receive Kotlin updates by filling out the form to the right of this post.
Language
The Kotlin roadmap includes adding support for sealed when statements, releasing opt-in annotations, improving type inference, and stabilizing builder inference.
Kotlin 1.5.30 takes a step down this road by providing a preview of these features, whose release is planned for 1.6.0.
Sealed when statements
Sealed when is a long awaited feature with more than 280 votes in YouTrack. If you enable this feature in 1.5.30, the Kotlin compiler will warn if one of your when statements is not exhaustive. This will make your code safer without you having to introduce your own functions.
Kotlin 1.5.30 provides a preview of an ability to use suspend functional types as super interfaces, although it has some limitations. It’s one of the missing pieces in the Kotlin coroutines design.
class MyClass: suspend () -> Unit {
override suspend fun invoke() { TODO() }
}
Presents new rules for using and declaring opt-in requirement annotations on different targets.
Requires opt-in even for implicit usages of an experimental API. For example, if the function’s return type is marked as an experimental API element, a usage of the function requires you to opt-in even if the declaration is not marked as requiring an opt-in explicitly.
// 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
// ...
}
Improvements to type inference on recursive generic types
With type inference on recursive generic types enabled, the Kotlin 1.5.30 compiler can infer a type argument based only on the upper bounds of the corresponding type parameter if it is a recursive generic. This makes it possible to create various patterns with recursive generic types that are often used in Java to make builder APIs.
With eliminating builder inference restrictions enabled, Kotlin 1.5.30 removes a builder inference restriction. Not only can you specify the type information that builder inference can infer, but you can also use the get function on it. For example, you can call get() inside a lambda argument of buildList() without explicitly specified type arguments.
Kotlin Multiplatform
Kotlin 1.5.30 includes the following improvements for Kotlin Multiplatform:
Support for XCFrameworks as an output format for all Kotlin Multiplatform projects. XCFrameworks help gather logic for all the target platforms and architectures in a single bundle and don’t require removing unnecessary architectures before publishing the application to AppStore.
New default publishing setup for Android artifacts. This setup will be compatible with any build type (like debug or release) by default. Before 1.5.30, the metadata generated by the maven-publish Gradle plugin when publishing a multiplatform library for Android included the build type attribute for every published Android variant. This made it compatible only with the same build type used by the library consumer.
Kotlin/JVM
With Kotlin 1.5.30, Kotlin/JVM gets the following updates:
Instantiation of annotation classes. If you enable this feature, you can call constructors of annotation classes in arbitrary code to obtain a resulting instance. This feature covers the same use cases as the Java convention, which enables the implementation of an annotation interface. Learn more about instantiation of annotation classes in this KEEP.
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"))
}
Kotlin/Native
Kotlin 1.5.30 provides the following improvements for Kotlin/Native:
Native support for Apple silicon. You can now build applications on Apple silicon hardware for all targets that are supported on Intel-based Macs, without having to use the Rosetta translation environment. New targets introduced in 1.5.30 – macosArm64, iosSimulatorArm64, watchosSimulatorArm64, and tvosSimulatorArm64 – make it possible to run Kotlin code on Apple silicon natively.
Improved Kotlin DSL for the CocoaPods Gradle plugin. Kotlin 1.5.30 improves CocoaPods configuration by providing a new DSL format for frameworks that is identical to a framework definition for Apple targets. You can define whether it is a static or dynamic type, enable the explicit export of dependencies and the Bitcode embedding, and configure other options.
Deprecation of linkage to DLLs without import libraries for MinGW (Windows). This deprecation is the result of the switch to the LLD linker, which has better performance and other improvements. Feel free to share your thoughts and concerns about the transition to the LLD linker in this YouTrack issue.
Support for Java toolchains. Gradle 6.7 introduced support for Java toolchains, which make it easy to select a JDK for project compilation. Just declare the version you need in the build script and Gradle does the rest, finding it on your host machine or even downloading and installing it if it’s not there yet. The Kotlin Gradle plugin supports Java toolchains for Kotlin/JVM compilation tasks. For Gradle versions 6.1-6.6, set a JDK home with the UsesKotlinJavaToolchain interface.
Easier ways to explicitly specify Kotlin daemon JVM arguments. If nothing is specified for the Kotlin daemon, it inherits arguments from the Gradle daemon. You can now also specify arguments for a specific task, as well as for the Kotlin extension, as a single line in build.gradle.kts or gradle.properties.
Kotlin 1.5.30 provides a preview of API improvements. The output of Duration.toString() is now more readable. For example, Duration.minutes(920).toString() produces 15h 20m instead of the previous 920m.
A negative duration is now prefixed with a minus sign (-), and it is surrounded by parentheses if it consists of multiple components: -12m and -(1h 30m).
parse() parses Duration objects from strings formatted as Duration’s toString() or from strings representing ISO 8601 durations (such as toIsoString() outputs).
parseIsoString() parses Duration objects from strings representing ISO 8601 durations.
*OrNull() counterparts for both functions.
import kotlin.time.Duration
import kotlin.time.ExperimentalTime
@ExperimentalTime
fun main() {
//sampleStart
val isoFormatString = "PT1H30M"
val defaultFormatString = "1h 30m"
println(Duration.parse(isoFormatString)) // "1h 30m"
println(Duration.parse(defaultFormatString)) // "1h 30m"
//sampleEnd
}
Regex API improvements
Kotlin 1.5.30 provides new experimental functions for regular expressions:
matchesAt() checks whether a regex has a match in the specified position of a String.
matchAt() returns the match if one is found.
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
}
splitToSequence() is a lazy counterpart of split(). It splits the string around matches of the given regex, but returns the result as a Sequence. A similar function has also been added to CharSequence.
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
}
You can download the latest versions of these IDEs to get extensive support for Kotlin:
IntelliJ IDEA – for developing Kotlin applications for various platforms.
Android Studio – for developing Android and cross-platform mobile applications.
Make sure that you have also updated the kotlinx libraries to compatible versions and specified version 1.5.30 of Kotlin in the build scripts of your existing projects.
If you need the command-line compiler, download it from the Github release page.
Stay up to date with information about the latest Kotlin features! Subscribe to receive Kotlin updates by filling out the form to the right of this post.
Since Kotlin 1.5.30 is the last incremental release before Kotlin 1.6.0, it includes many experimental language and standard library features that we are planning to release in Kotlin 1.6.0. Give them a try and share your feedback with us, you can really influence the final result! These experimental features include sealed when statements, changes to opt-in requirements, instantiation of annotation classes, improvements to the Duration and Regex stdlib APIs, and more.
With Kotlin 1.5.30, you can also enjoy native support for Apple silicon, the promotion of the Kotlin/JS IR backend to Beta, the ability to use custom cinterop libraries in the shared native code of multiplatform applications, support for Java toolchains provided by the Kotlin Gradle plugin, and much more.
This blog post provides an overview of the updates in this release:
Language improvements, including sealed when statements, support for suspend functions as supertypes, and changes to opt-in requirements.
Multiplatform improvements, including the ability to use custom cinterop libraries in shared native code and support for XCFrameworks as an output format.
Kotlin/JVM improvements, including instantiation of annotation classes and improved configuration of nullability annotation support.
Kotlin/Native improvements, including native support for Apple silicon and an improved Kotlin DSL for the CocoaPods Gradle plugin.
Kotlin/JS IR improvements, including the promotion of the JS IR backend to Beta and a better debugging experience for the new backend.
Gradle improvements, including support for Java toolchains and easier ways to explicitly set the Kotlin daemon’s JVM arguments.
Stay up to date with information about the latest Kotlin features! Subscribe to receive Kotlin updates by filling out the form to the right of this post.
Language
The Kotlin roadmap includes adding support for sealed when statements, releasing opt-in annotations, improving type inference, and stabilizing builder inference.
Kotlin 1.5.30 takes a step down this road by providing a preview of these features, whose release is planned for 1.6.0.
Sealed when statements
Sealed when is a long awaited feature with more than 280 votes in YouTrack. If you enable this feature in 1.5.30, the Kotlin compiler will warn if one of your when statements is not exhaustive. This will make your code safer without you having to introduce your own functions.
Kotlin 1.5.30 provides a preview of an ability to use suspend functional types as super interfaces, although it has some limitations. It’s one of the missing pieces in the Kotlin coroutines design.
class MyClass: suspend () -> Unit {
override suspend fun invoke() { TODO() }
}
Presents new rules for using and declaring opt-in requirement annotations on different targets.
Requires opt-in even for implicit usages of an experimental API. For example, if the function’s return type is marked as an experimental API element, a usage of the function requires you to opt-in even if the declaration is not marked as requiring an opt-in explicitly.
// 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
// ...
}
Improvements to type inference on recursive generic types
With type inference on recursive generic types enabled, the Kotlin 1.5.30 compiler can infer a type argument based only on the upper bounds of the corresponding type parameter if it is a recursive generic. This makes it possible to create various patterns with recursive generic types that are often used in Java to make builder APIs.
With eliminating builder inference restrictions enabled, Kotlin 1.5.30 removes a builder inference restriction. Not only can you specify the type information that builder inference can infer, but you can also use the get function on it. For example, you can call get() inside a lambda argument of buildList() without explicitly specified type arguments.
Kotlin Multiplatform
Kotlin 1.5.30 includes the following improvements for Kotlin Multiplatform:
Support for XCFrameworks as an output format for all Kotlin Multiplatform projects. XCFrameworks help gather logic for all the target platforms and architectures in a single bundle and don’t require removing unnecessary architectures before publishing the application to AppStore.
New default publishing setup for Android artifacts. This setup will be compatible with any build type (like debug or release) by default. Before 1.5.30, the metadata generated by the maven-publish Gradle plugin when publishing a multiplatform library for Android included the build type attribute for every published Android variant. This made it compatible only with the same build type used by the library consumer.
Kotlin/JVM
With Kotlin 1.5.30, Kotlin/JVM gets the following updates:
Instantiation of annotation classes. If you enable this feature, you can call constructors of annotation classes in arbitrary code to obtain a resulting instance. This feature covers the same use cases as the Java convention, which enables the implementation of an annotation interface. Learn more about instantiation of annotation classes in this KEEP.
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"))
}
Kotlin/Native
Kotlin 1.5.30 provides the following improvements for Kotlin/Native:
Native support for Apple silicon. You can now build applications on Apple silicon hardware for all targets that are supported on Intel-based Macs, without having to use the Rosetta translation environment. New targets introduced in 1.5.30 – macosArm64, iosSimulatorArm64, watchosSimulatorArm64, and tvosSimulatorArm64 – make it possible to run Kotlin code on Apple silicon natively.
Improved Kotlin DSL for the CocoaPods Gradle plugin. Kotlin 1.5.30 improves CocoaPods configuration by providing a new DSL format for frameworks that is identical to a framework definition for Apple targets. You can define whether it is a static or dynamic type, enable the explicit export of dependencies and the Bitcode embedding, and configure other options.
Deprecation of linkage to DLLs without import libraries for MinGW (Windows). This deprecation is the result of the switch to the LLD linker, which has better performance and other improvements. Feel free to share your thoughts and concerns about the transition to the LLD linker in this YouTrack issue.
Support for Java toolchains. Gradle 6.7 introduced support for Java toolchains, which make it easy to select a JDK for project compilation. Just declare the version you need in the build script and Gradle does the rest, finding it on your host machine or even downloading and installing it if it’s not there yet. The Kotlin Gradle plugin supports Java toolchains for Kotlin/JVM compilation tasks. For Gradle versions 6.1-6.6, set a JDK home with the UsesKotlinJavaToolchain interface.
Easier ways to explicitly specify Kotlin daemon JVM arguments. If nothing is specified for the Kotlin daemon, it inherits arguments from the Gradle daemon. You can now also specify arguments for a specific task, as well as for the Kotlin extension, as a single line in build.gradle.kts or gradle.properties.
Kotlin 1.5.30 provides a preview of API improvements. The output of Duration.toString() is now more readable. For example, Duration.minutes(920).toString() produces 15h 20m instead of the previous 920m.
A negative duration is now prefixed with a minus sign (-), and it is surrounded by parentheses if it consists of multiple components: -12m and -(1h 30m).
parse() parses Duration objects from strings formatted as Duration’s toString() or from strings representing ISO 8601 durations (such as toIsoString() outputs).
parseIsoString() parses Duration objects from strings representing ISO 8601 durations.
*OrNull() counterparts for both functions.
import kotlin.time.Duration
import kotlin.time.ExperimentalTime
@ExperimentalTime
fun main() {
//sampleStart
val isoFormatString = "PT1H30M"
val defaultFormatString = "1h 30m"
println(Duration.parse(isoFormatString)) // "1h 30m"
println(Duration.parse(defaultFormatString)) // "1h 30m"
//sampleEnd
}
Regex API improvements
Kotlin 1.5.30 provides new experimental functions for regular expressions:
matchesAt() checks whether a regex has a match in the specified position of a String.
matchAt() returns the match if one is found.
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
}
splitToSequence() is a lazy counterpart of split(). It splits the string around matches of the given regex, but returns the result as a Sequence. A similar function has also been added to CharSequence.
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
}
You can download the latest versions of these IDEs to get extensive support for Kotlin:
IntelliJ IDEA – for developing Kotlin applications for various platforms.
Android Studio – for developing Android and cross-platform mobile applications.
Make sure that you have also updated the kotlinx libraries to compatible versions and specified version 1.5.30 of Kotlin in the build scripts of your existing projects.
If you need the command-line compiler, download it from the Github release page.
Stay up to date with information about the latest Kotlin features! Subscribe to receive Kotlin updates by filling out the form to the right of this post.
Enjoy improved performance, a better coroutines debugging experience, WSL 2 and Run Targets support, and more improvements for Kotlin in IntelliJ IDEA 2021.2:
IntelliJ IDEA 2021.2 brings some major performance improvements for Kotlin.
Faster test files analysis
Now you can run tests before code analysis finishes. The Run test icon appears in the gutter as soon as you open the file and you can run your test immediately.
Run and debug your code before the IDE finishes indexing
The indexing process in the IDE and running code are now autonomous from each other. You can run or debug the project right away without waiting for the IDE to finish its work.
Improved speed of rename refactoring
Rename refactoring for particular cases, like for fields with common names nameor id, became faster. Check out this YouTrack issue for more details.
Shared indexes for new Spring Boot projects
Shared indexes help you to prevent situations where you open a project and need to wait for indexing to finish. In the previous version of IntelliJ IDEA you can download the JDK shared indexes that save time during every project import. Now shared indexes are available for Spring Boot projects. Learn more about how to download and use shared indexes in the IntelliJ IDEA documentation.
Better debugging experience
IntelliJ IDEA 2021.2 brings useful improvements and updates to the coroutine agent in the debugger.
Evaluate suspend functions
Now you can evaluate suspend function calls during the debugging process. You can put a breakpoint and evaluate the suspend function:
Look through these YouTrack tickets for more details: KT-27974, KT-31701.
Preserving variables after suspension points
Previously, when local variables were not used after passing a suspension point, you couldn’t see their values in the Local Variable table. This helped avoid memory leaks, but as a side effect such variables disappeared in the Variables view of the Debugger tool window. Now you can see the values of such variables for common cases. IntelliJ IDEA also handles other specific cases properly and notifies you when it is impossible to obtain the value.
For example, when you debug through the following code, the debugger shows the message that the x1, x2, x3variables have been optimized out:
Run, debug, and test your code in different remote environments without leaving the IDE.
Kotlin plugin in the IntelliJ IDEA repository
The Kotlin plugin code has been moved to the IntelliJ IDEA repository. That means that every stable IDE release improves your Kotlin experience and brings you more debugging, refactoring, and IDE-related features.
The EAP version of Kotlin works only with the stable version of the IDE. That means that you can’t install the Kotlin EAP version to the EAP IDEA release.
The Kotlin plugin is based on the previous stable version of the Kotlin compiler. You can still update the Kotlin version in your project, but some IDE-related features might not be available. We are working on stabilizing the process so that the next versions of the plugin will be based on the latest stable version of the compiler.
IntelliJ IDEA 2021.2 also brings more IDE features that improve the Kotlin experience.
Automatic ML code completion
Kotlin code completion works based on a machine learning mechanism by default. Code suggestions are prioritized more carefully as IntelliJ IDEA considers the choices of thousands of real users in similar situations. You can configure ML-assisted completion in Preferences/Settings | Editor | Code Completion.
Clickable inlay hints
Now you can click the type in the inlay hint and look through the declaration of the type, including generics types. Just hold Cmd + click the type in the hint:
You can customize the inlay hints’ appearance in Preferences | Editor | Inlay hints | Kotlin.
Package Search integration
Package Search now works with build.gradle.ktsfiles. This feature allows you to upgrade, downgrade, and remove existing dependencies. You can use it to find new dependencies and add them automatically. Package Search will add the required repositories to your build script if they’re missing.
Advanced settings
There is a new node Advanced Settings in the Preferences | Settings window. It contains some use-case-specific options conveniently grouped by the IDE tool. For example, you can add a left margin in Distraction-free mode, or set the maximum number of recent projects which are displayed in the File | Open Recent menu.
Quick access to Eclipse projects
IntelliJ IDEA detects existing Eclipse projects automatically and adds them to the Welcome screen. To try this feature, select Open existing Eclipse projects on your first IDE launch.
See also
What’s new in IntelliJ IDEA 2021.2 – docs and video
What’s new for Kotlin in IntelliJ IDEA 2021.1 – blog post