Kotlin
A concise multiplatform language developed by JetBrains
Kotlin 1.3.40 released
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
andString.encodeToByteArray
CharArray.concatToString
andString.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 {#type-of}
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:
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:
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:
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 {#new-type-inference}
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:
or use the kotlin
function in build.gradle.kts
:
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:
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.
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:
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:
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/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. - 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.
- In Eclipse: 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