Kotlin 1.3.40 released

Posted on by

We’re happy to present the new release today, Kotlin 1.3.40. In addition to the quality and tooling improvements the main focus for this version has been on:

Gradle support for NPM, Yarn, and Webpack for Kotlin/JS

Test runner improvements for multiplatform projects

New type inference

Performance and interoperability improvements for Kotlin/Native

Also, new functions were added to the standard library in an experimental state.

You can find the complete list of changes in the change log. As always, we’re really grateful to our external contributors.

Let’s dive into the details!

Experimental functions in the standard library

We’ve added several new functions to the standard library in an experimental state. There are new common functions to encode/decode a byte/char array into a string in a UTF-8 encoding included:

ByteArray.decodeToString and String.encodeToByteArray

and CharArray.concatToString and String.toCharArray

Another experimental function capitalize has been added on the JVM which takes Locale object as a parameter.

You need to explicitly opt-in to use them: either annotate the use site with @UseExperimental(ExperimentalStdlibApi::class) or provide the compiler argument -Xuse-experimental=kotlin.ExperimentalStdlibApi .

The ExperimentalStdlibApi annotation was introduced in this release to indicate experimental API in the standard library. The behavior of such API can change based on your feedback, so there is no compatibility guarantee. You can find more about the experimental annotations in the documentation.

Accessing the reified type using reflection on JVM

Another experimental function added in this release is the typeOf function. At a glance, you can use it to construct an instance of KType for a given type:

val intType: KType = typeOf<Int>() println(String::length.returnType == intType) // true

The real benefit, however, comes when you use it to retrieve information about the reified generic type argument. When you call typeOf() with T being a reified generic type argument, typeOf returns the actual value of the type argument:

@UseExperimental(ExperimentalStdlibApi::class) inline fun <reified T> accessReifiedTypeArg() { val kType = typeOf<T>() println(kType.toString()) } fun main() { accessReifiedTypeArg<String>() // kotlin.String accessReifiedTypeArg<List<String>>() // kotlin.collections.List<kotlin.String> }

Currently, typeOf is only available in Kotlin/JVM, but in future versions, similar functions will be added to the other platforms: Kotlin/JS and Kotlin/Native.

Optimization for trimIndent and trimMargin

For better code formatting, multiline strings are usually used together with either trimIndent or trimMargin . Starting with this release, trimIndent and trimMargin calls are optimized by the compiler. Instead of calling the corresponding library functions, the compiler does the work itself and generates the trimmed string literals in the bytecode:

fun main() { println( """ |first |second """.trimMargin() ) // in the bytecode it is replaced with: println("first

second") }

Note that this optimization only works if the receiver function and the margin prefix are constant expressions, without any interpolated variables (like "$x" ).

As an optimization minBy and maxBy functions do not call the specified selector function any longer if the collection they were invoked on contains just one element. Beware if you relied on side effects from selector function.

Using External annotations in IntelliJ IDEA

If you use external nullability annotations for Java, the IDE can now give warnings for incorrect usages of annotated Java methods from Kotlin.

Imagine that your Java method is annotated with an external annotation. IntelliJ IDEA can show such an annotation, but it’s not present in the code:

The annotation is declared in a separate annotations.xml file:

<root> <item name="JavaClass java.lang.String nullableString()"> <annotation name="org.jetbrains.annotations.Nullable"/> </item> </root>

Starting from this release, you’ll get warnings for incorrect usages of this Java method from Kotlin:

Note that this is purely IDE functionality; the corresponding code is compiled without warnings by the Kotlin compiler. The compiler still infers that the type of nullableString is a platform type String! , but the IDE shows an additional warning.

Working on a New Type Inference Algorithm

We’ve been working on an improved algorithm for type inference. It fixes different corner-case problems and supports new scenarios: the whole list of fixed issues is quite impressive. In future versions of Kotlin, the new algorithm will replace the one currently in use and will become the default.

The backward compatibility when switching to the new algorithm is really important to us. So, we have switched it on by default only in the IDE for this release, to gather feedback from real-life examples. Note that it’s possible that the code works correctly in the IDE but isn’t supported by the compiler since different bugs related to type inference for complicated corner-cases were fixed. If you observe any inconsistent behavior when the code is red in the IDE but compiles fine with the Kotlin compiler or vice versa, please let us know by filing a new issue. If this mode doesn’t work well for your projects, you can switch it off by unselecting the checkbox Enable new type inference algorithm for IDE analysis in the Kotlin Compiler tab in Preferences (in Android Studio the option is located in a different place: Preferences | Kotlin Compiler).

We are looking forward to your feedback!

Multiplatform Projects (MPP)

Test runners for Kotlin/Native and Kotlin/JS now implement all Gradle Test runner APIs and behave in a way similar to the Kotlin/JVM test runner. Test failure reports with source code navigation will be printed into the console. A test report will be generated by Gradle too. Test filtering parameters are also supported via the standard Gradle parameter, e.g. --tests some.test.ClassName .

A combined test run report can be generated from Gradle to include all information in all test runs on all targets, including Kotlin/Native, Kotlin/JS, and Kotlin/JVM.

Kotlin/JS

Kotlin/JS incremental compilation performance has been improved. In particular, the compilation time of large projects and/or modules with lots of dependencies is reduced by up to 30% in some cases.

The most visible changes to Kotlin/JS in this release are from the tooling side. We are happy to introduce the updated Kotlin/JS plugin for Gradle, we’ve renamed it org.jetbrains.kotlin.js and it is now available on the Gradle plugin portal. Just use the plugins {} syntax in your build.gradle to enable it:

plugins { id("org.jetbrains.kotlin.js") version "1.3.40" }

or use the kotlin function in build.gradle.kts :

plugins { kotlin("js") version "1.3.40" }

We are working hard to port all the features of the kotlin-frontend-plugin plugin into our Kotlin/JS plugin and Kotlin/Multiplatform plugins. Some of the features are already included as experimental. We plan to deprecate the kotlin-frontend-plugin when this work is complete.

Experimental support for NPM and Webpack

Today, we are happy to share with you a few more experimental features to help simplify the development of JavaScript projects that use Node.js, NPM, Yarn, or Webpack. We’ve added helper tasks to both Kotlin/JS and Multiplatform Gradle plugins to simplify the integration. The plugin will generate a temporary package.json for your project, and it will download and use Yarn to manage the NPM dependencies and node_modules automatically. Webpack will be used behind the scenes to join all the dependencies and create browser-friendly scripts from your code.

The plugin attaches all your Kotlin/JS dependencies declared in a Gradle project to the automatically maintained node_modules folder. Adding an NPM dependency is now supported in Gradle scripts via the newly added npm function in the dependencies {} block of a JS SourceSet:

dependencies { implementation(npm("react", "16.8.3")) }

Yarn Workspaces are used for Multi-Project Gradle builds. A workspace is created per sub-project and configured under the root project’s build directory. This allows Yarn to reduce node_modules copies in sub-projects by extracting common dependencies to root node_modules .

Node.js and Browser Modes

Running or testing JavaScript projects has always depended on the environment. We’ve now added support for Node.js and browser execution environments. You may use nodejs {} or browser {} functions to configure the Kotlin target for both Kotlin/JS and Multiplatform Gradle plugins.

kotlin { //use js() for a multiplatform project target { nodejs() browser() } sourceSets["main"].dependencies { implementation(kotlin("stdlib-js")) implementation(npm("react", "16.8.3")) } }

The Gradle plugin will download and install (via Yarn, of course) all the required NPM dependencies, including a headless browser for Karma tests, to run the tests for your code. Mocha test framework will be used to run your tests in a Node.js environment. Test runners are integrated with Gradle and implement similar features as are available for Kotlin/JVM tests. For example, test failures are shown in the console, tests report will be generated, a test filter may be passed to the Gradle command line.

Sometimes it is hard to trace an error back to the point in the code to improve it, so we’ve added JavaScript source maps support to all these tasks in our Gradle plugin.

You may easily configure to run browser tests in different browsers. The plugin will configure NPM dependencies for the Karma test runner to make it happen. The following DSL can be used in Gradle:

kotlin { //use js() for multiplatform project target { browser { testTask { useKarma { useIe() useSafari() useFirefox() useChrome() useChromeCanary() useChromeHeadless() usePhantomJS() useOpera() } } } } }

A run task was also added to the Gradle plugin to execute the Kotlin/JS code in Node.js or Browser environments.

Note, the new Kotlin/JS build features are experimental and currently only supported on macOS and Linux. Windows support will be added later.

Kotlin/Native

Several improvements were added in the memory manager to improve the performance of Kotlin/Native applications. We’ve noticed nearly twice the performance boost to our benchmarks.

ARM x64 (ARM/AArch64) support is added for Linux targets. The CoreLocation framework is pre-imported and included out of the box on macOS. We’ve improved logging and error messages that are shown by the Kotlin/Native compiler.

FreezableAtomicReference is a new experimental class included in Kotlin/Native to help deal with multiple threads and concurrency. It behaves like an AtomicReference class, no matter if it is frozen or not.

kotlin-platform-native is now deprecated. Please migrate to the kotlin-multiplatform Gradle plugin. Check out the documentation for the migration guide and more info.

We’ve also removed the previously deprecated API in the kotlin-multiplatform Gradle plugin to configure Kotlin/Native targets. Starting from 1.3.40, the compilations.outputKinds is no longer supported, please use the binaries API instead.

Interop

Experimental generics support for Kotlin/Native produced frameworks is included. It adds type information for generic parameters to Kotlin/Native generic classes for Objective-C/Swift. The feature is disabled by default, to enable it, pass the -Xobjc-generics command line argument to the compiler or add these lines to the Gradle project configuration:

kotlin { iosX64 { binaries { framework { freeCompilerArgs.add("-Xobjc-generics") } } } }

In addition to this, the Kotlin type Unit will turn into Void in the produced frameworks. Kotlin/Native method names will not clash with Objective-C declarations, because we’ve improved the way method names are generated. Variadic Objective-C functions are now supported in the interop.

Nullable strings are now correctly supported in the C interop. We’ve fixed issues with the custom exception hook; now you can use the setUnhandledExceptionHook {} function in your code to catch unhandled Kotlin exceptions.

Tests in Kotlin/Native

We’ve added a separate binary type for Kotlin/Native test targets. Now it is easier to instruct the build to create a native tests executable:

kotlin.macosX64 { binaries { test("integration") { /* configuration if needed */ } } }

Kotlin/Native test runner is now integrated with Gradle and implements features similar to those available for Kotlin/JVM tests, for example, test failures are shown in the console, tests report will be generated, and you may pass a tests filter to the Gradle command line.

Now it’s easier to get the test binary via Gradle API using the binaries.getTest function. The old ways to find test executables, e.g., binaries.getExecutable("test", "DEBUG") , will not work anymore, please use the new API instead: binaries.getTest("DEBUG") .

How to update

As always, you can try Kotlin online at play.kotl.in.

In Maven, Gradle, and npm : Use 1.3.40 as the version for the compiler and the standard library. See the docs here.

: Use as the version for the compiler and the standard library. See the docs here. In IntelliJ IDEA and Android Studio : Update the Kotlin plugin to version 1.3.40. Use Tools | Kotlin | Configure Kotlin Plugin Updates and click the “Check for updates now” button.

and : Update the Kotlin plugin to version 1.3.40. Use Tools | Kotlin | Configure Kotlin Plugin Updates and click the “Check for updates now” button. In Eclipse : Install the plugin using Marketplace.

: Install the plugin using Marketplace. The command-line compiler can be downloaded from the Github release page.

If you run into any problems with the new release, you’re welcome to ask for help on the forums, on Slack (get an invite here), or to report issues in the issue tracker.

Let’s Kotlin!

External Contributions

We’re especially grateful to Kevin Galligan for his contribution of adding support of generics in Kotlin/Native produced frameworks.

We’d like to thank our external contributors whose pull requests were included in this release:

* Dimach

* Toshiaki Kameyama

* pyos

* Mark Punzalan

* Ivan Gavrilovic

* Ting-Yuan Huang

* Steven Schäfer

* Burak Eregar

* Dereck Bridie

* Jake Wharton

* Mads Ager

* Kirill Knize

* gcx11

* Austaon

* Ryan

* Jan Gerling

* Harry Billinis

* Georgios Andrianakis

* George Gastaldi

* Eduard Wolf

* Caleb Brinkman

* Wil

* Benjamin Orsini

* Yanis Batura

* ilgonmic

* Kenji Tomita

* Matthew Runo

* Kirill Rakhman

* Kevin Galligan

* Kevin Peek

* Kerooker

* Juan Chen

* Nikolay Kasyanov

* Jorge Antonio Díaz-Benito Soriano

* Pavel Nikitin

* Peter Xu

* Rene Groeschke

* Jiaxiang Chen