Auto Added by WPeMatico

kotlinx.serialization 1.0 released

We are happy to share with you the release of version 1.0 of our multiplatform serialization library, kotlinx.serialization. As the first stable version of the library, we can finally consider it production-ready!

Whether you are writing Android apps, using Kotlin Multiplatform Mobile, creating server-side services, or building web frontends with Kotlin/JS – kotlinx.serialization comes with a simple but powerful pure-Kotlin API, which makes it effortless to parse JSON into type-safe Kotlin objects, and vice versa. To celebrate this release, we want to provide a brief overview of some of the production-ready features which are provided with kotlinx.serialization 1.0, and see what sets our library apart from other solutions.

But before we dive in, we would like to invite you to our Kotlin 1.4 Online Event, where Leonid Startsev will talk in more detail about the past, current, and future of kotlinx.serialization. Don’t miss it!

Register for the Kotlin 1.4 Online Event

Serializing & deserializing your first Kotlin object with kotlinx.serialization

Generally, serialization is a task that comes up quite frequently in software projects. Mobile apps or web frontends are likely to consume APIs which return JSON as a plain-text format for objects. Server-side applications and backend services often need to accept and respond to requests which are formatted using JSON. And even if you are looking to persist information on disk, using JSON as a human-readable format is a popular choice.

As you can see, the process of (de)serializing Kotlin objects is one that you might encounter sooner or later in your project as well. Choosing kotlinx.serialization makes this whole process very straightforward: After adding the library to your project, turning a basic Kotlin object into its JSON representation and back is as simple as marking its class with the

@Serializable

annotation, and using the provided

encodeToString

and

decodeFromString<T>

extension functions on the

Json

object:

import kotlinx.serialization.*
import kotlinx.serialization.json.*

@Serializable
data class User(val name: String, val yearOfBirth: Int)

fun main() {
   // Serialization (Kotlin object to JSON string)

   val data = User("Louis", 1901)
   val string = Json.encodeToString(data)
   println(string) // {"name":"Louis","yearOfBirth":1901}

   // Deserialization (JSON string to Kotlin object)

   val obj = Json.decodeFromString<Account>(string)
   println(obj) // Account(name=Louis, yearOfBirth=1901)
}

Of course, kotlinx.serialization isn’t the only library you can use to perform such serialization-related tasks. In the JVM ecosystem, there are a number of other libraries to work with JSON. However, the most popular choices available are not necessarily Kotlin-first, and might not be available for Kotlin Multiplatform projects at all. Even beyond this, there are excellent reasons to choose kotlinx.serialization for your project.

Why choose kotlinx.serialization?

Several features and design choices included in kotlinx.serialization set it apart from other libraries, and generally help make it more enjoyable to use its functionality. Let’s take a closer look at a selection of them.

Kotlin through and through

Not only is kotlinx.serialization written in pure Kotlin, and available on all Kotlin Multiplatform targets, including Kotlin/Native and Kotlin/JS. Its serialization functionality is also built with the Kotlin type-system in mind. Whether you’re trying to serialize a

data class

with default initializers for its properties, a singleton

object

, or trying to deserialize a generic

List&lt;T&gt;

: kotlinx.serialization always behaves as you would expect. This is best seen when looking at a concrete example, which turns a list of complex project objects (described by a

data class

) into its JSON representation, and back:

@Serializable
data class Project(
   val name: String,
   val owner: Account,
   val group: String = "R&D"
)

@Serializable
data class Account(val userName: String)

val moonshot = Project("Moonshot", Account("Jane"))
val cleanup = Project("Cleanup", Account("Mike"), "Maintenance")

fun main() {
   val string = Json.encodeToString(listOf(moonshot, cleanup))
   println(string)
   // [{"name":"Moonshot","owner":{"userName":"Jane"}},{"name":"Cleanup","owner":{"userName":"Mike"},"group":"Maintenance"}]

   val projectCollection = Json.decodeFromString<List<Project>>(string)
   println(projectCollection)
   // [Project(name=Moonshot, owner=Account(userName=Jane), group=R&D), Project(name=Cleanup, owner=Account(userName=Mike), group=Maintenance)]
}

As you can see, even the type-safe deserialization of collections with generics is handled by kotlinx.serialization just as expected. This certainly isn’t the norm, because collections on the JVM are normally affected by type erasure. As such, other libraries would require you to use workarounds like using explicit type-tokens in this situation. Because kotlinx.serialization also integrates using a compiler plugin, its out-of-the-box behavior (which you can see with the

projectCollection

example) is already what you would expect – no workarounds required!

Because we want to make sure that you can catch as many possible issues before even starting your application for the first time, kotlinx.serialization also strives for compile-time safety. For example, not explicitly marking the

Account

class to be

@Serializable

in the example above would result in the compile-time error

Serializer has not been found for type 'Account'

, making it easy to pinpoint and fix the issue ahead of time instead of experiencing a crash.

Polymorphic serialization

kotlinx.serialization makes it possible to comfortably and securely deal with inheritance hierarchies of objects to serialize – a traditionally sensitive, but much-desired feature. Because the library is aware of Kotlin-specific type system concepts, the most straightforward way to use polymorphic serialization is to build a sealed class hierarchy, where all subclasses are explicitly marked as

@Serializable

. Because sealed class hierarchies are known at compile time, the kotlinx.serialization plugin can use this information, and the code required to serialize sub- and superclasses stays concise:

@Serializable
sealed class Message {
   abstract val content: String
}

@Serializable
data class BroadcastMessage(override val content: String) : Message()

@Serializable
data class DirectMessage(override val content: String, val recipient: String) : Message()

fun main() {
   val data: List<Message> = listOf(
       DirectMessage("Hey, Joe!", "Joe"),
       BroadcastMessage("Hey, all!")
   )
   val string = Json.encodeToString(data)
   println(string)
   // [{"type":"DirectMessage","content":"Hey, Joe!","recipient":"Joe"},{"type":"BroadcastMessage","content":"Hey, all!"}]

   val obj = Json.decodeFromString<List<Message>>(string)
   println(obj)
   // [DirectMessage(content=Hey, Joe!, recipient=Joe), BroadcastMessage(content=Hey, all!)]
}

As you can see with the string variable, kotlinx.serialization intelligently adds a type key to your JSON object containing information about the specific subtype – without you having to specify this behavior manually. When you’re in control of both client and server, this makes it possible for you to easily structure messages using inheritance relationships, without having to manually try and deduce subtypes on the other end.

While sealed classes are the most convenient way to use polymorphic serialization with kotlinx.serialization, and can already cover a large number of use cases, the library actually also offers functionality that goes beyond these closed hierarchies. To learn more about this functionality, check out the section on polymorphism in the guide.

Strong customizability

Especially when communicating with external systems and APIs, you might not be in full control over the exact shape in which you receive JSON-formatted messages. On the other hand, you might feel the need to adjust the output that kotlinx.serialization generates to make sure it is accepted by the remote you are communicating with.

Kotlinx.serialization comes with a rich configuration DSL which you can use to adjust the way it generally treats input and generates output, modifying general settings like enabling pretty-printing, lenient parsing, or ignoring unknown keys. For class- or object-specific settings, you can use annotations to customize their behavior, for example, to rename fields (

@SerialName

) or exclude them from the serialization process (

@Transient

). These annotations, among a number of others, are also covered in the guide. If your use case requires it, you can even provide completely custom serializers for specific types of objects.

Combining these features allows you to shape the behavior of the library to exactly match the requirements and specifications you have for your serialized format.

Framework integrations

While kotlinx.serialization with its concise interfaces can be used regardless of other libraries included in a project, a number of frameworks also provide direct integrations to use kotlinx.serialization. Here are some examples we want to highlight:

  • If you are using Ktor as a server-side framework, you can use the provided official integration with kotlinx.serialization together with content negotiation, making it possible to receive and respond with Kotlin objects directly for incoming and outgoing requests. The Ktor-Clients counterpart, which is available in Kotlin Multiplatform projects, also provides JSON payload processing via kotlinx.serialization.
  • Spring MVC has recently added support for kotlinx.serialization, and a similar integration has been proposed for Spring WebFlux, thanks to Sébastien Deleuze.
  • Http4k provides first class support for marshalling to and from HTTP messages using kotlinx.serialization.
  • Fuel provides an extension package to use kotlinx.serialization in your Android HTTP client.
  • If you are working with MongoDB, the KMongo library provides object mapping through kotlinx.serialization.
  • If you are using Retrofit 2 to turn your HTTP APIs into Kotlin interfaces, you can use the serialization converter by Jake Wharton to integrate with kotlinx.serialization.

We are very excited about the growing number of third-party projects which integrate directly with kotlinx.serialization – and now that our library has reached a production-ready state, we hope to see many more such integrations soon!

Multi-format future

With version 1.0, all functionality related to working with JSON is stable and production-ready – but kotlinx.serialization is not stopping there! Besides JSON, the team is working on additional support for the HOCON, ProtoBuf, CBOR, and Properties serialization formats. While these formats are still being designed and developed, and as such have varying degrees of stability and platform compatibility, you can already try them out. They are available as separate artifacts, which you can find in the guide together with a short description of the format’s state.

A number of community-maintained formats like BSON, XML, and YAML also exist alongside the formats the team is working on officially – but please note that these are created and maintained by members of the community, and as such may receive delayed updates by their maintainers.

Now that we have highlighted a number of features that make kotlinx.serialization comfortable to use, we hope you have a good idea why you might want to choose the library for your current (or next) project – which is a quick process!

Adding kotlinx.serialization to your project

To start using kotlinx.serialization in your project, simply add the compiler plugin and runtime library to your project. In your

build.gradle(.kts)

, add the following entry to the

plugin

block:

plugins {
   kotlin("plugin.serialization") version "1.4.0"
}

Next, add the runtime library dependency to your dependencies block in your

build.gradle(.kts)

file. If you are working in a Kotlin Multiplatform project, it’s enough to add the dependency to your

common

target dependencies block – all platform-specific dependencies will automatically be added for you:

dependencies {
   implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.0.0")
}

At this point, you’re ready to start using kotlinx.serialization! Feel free to experiment with the samples included in this blog post, try one of your own use cases, or play around with the examples which accompany the guide.

Learning more & giving feedback

We hope you enjoyed this brief overview of kotlinx.serialization! To find out more information, including always up-to-date installation instructions, visit its home on GitHub. Be sure to check out the kotlinx.serialization guide, which contains detailed information about basic and advanced features of the library, and covers many of the topics mentioned in this blog post in more detail. If you run into any trouble using the library, you can seek help in the project’s issue tracker, or in the #serialization channel on the Kotlin Slack.

For an exclusive look behind the scenes and a more in-depth explanation of our serialization library, this is also a good time to invite you once more to the kotlinx.serialization talk by Leonid Startsev during the Kotlin 1.4 Online Event – we look forward to seeing you there!

Register for the Kotlin 1.4 Online Event

If you have previously used kotlinx.serialization, use the changelog and migration guide to find out what has changed and how to upgrade your projects to the stable release.

A thank you from the team

We want to say “thank you” to everyone who gave us feedback, submitted pull requests, used kotlinx.serialization pre-1.0, or contributed in any other way to the library. Your input was extremely valuable in helping the team deliver a robust, easy-to-use, Kotlin-first, multiplatform serialization library. The over 700 issues you reported before our first stable release helped squash bugs and iron out any wrinkles in the design before this first stable release. As we continue to evolve the project, we hope that we can count on your continued support and feedback to help us keep improving and innovating. So: Thank you, everyone – and have a nice Kotlin!

Continue Reading kotlinx.serialization 1.0 released

Dark Theme Is Now Available in Toolbox App 1.18.

It’s been a while since you made this wish, and now we’ve finally made it come true! We are happy to introduce the frequently requested feature – the Dark Theme. :tada:

Don’t have the Toolbox App yet? Click the link below to download the free Toolbox App and start working with the theme you like the most.

Download now

You shouldn’t wait any longer to see it in action. Just update your Toolbox App to version 1.18, if you haven’t set the Toolbox App to update automatically and select the Dark Theme in the “Appearance & Behavior” section of the Toolbox App Settings.

Dark Theme

Currently, the app offers two options – Light or Dark Theme – which you can change manually. Go to the Toolbox App Settings and choose the theme you like under the “Appearance & Behavior”.
Theme Settings

Bug Fixes 🛠

In the same release, we’ve fixed the following issues:

TBX-4898 – Generation of shell scripts on macOS for Android Studio 4.0 and 4.1 now works correctly.
TBX-4985 – Toolbox now correctly updates taskbar shortcuts on Windows.
TBX-5031, TBX-5066 – The uninstall process on Windows now works correctly.
TBX-5199 – Toolbox now updates Linux .desktop files if there is a broken symlink.
TBX-5233 – We’ve fixed a bug that caused Android Studio 4.1 not to start from the Toolbox App on macOS.

See the full list of fixed issues here.

As always, the Toolbox App team is happy to get your feedback! Leave us a message in our issue tracker or on Twitter by mentioning @JBToolbox.

Stay safe, and stay productive!
The Toolbox App team

Continue Reading Dark Theme Is Now Available in Toolbox App 1.18.

Kotlin Multiplatform Mobile goes Alpha

Kotlin Multiplatform Mobile (KMM) is an SDK that allows you to use the same business logic code in both iOS and Android applications. Today KMM goes Alpha, and you can start sharing business logic in your mobile apps with it right away. It includes the new KMM Plugin for Android Studio, which allows you to write, run, test, and debug shared code in the same IDE. Join such great teams as VMWare, Autodesk and Yandex who are sharing code in their mobile apps using Kotlin. It has never been so easy!

file

What is Kotlin Multiplatform Mobile?

Kotlin Multiplatform Mobile (KMM) is an SDK for cross-platform mobile development provided by JetBrains. It uses the multiplatform capabilities of Kotlin and includes various tools and features designed to make the end-to-end experience of building mobile cross-platform applications as enjoyable and efficient as possible.

The Android and iOS versions of an application often have a lot in common, but they can also differ significantly – especially in terms of their UI – from subtle variations in scrolling behavior to completely divergent navigation logic. At the same time, the application’s business logic, including such features as data management, analytics, and authentication, is often identical. That’s why it’s natural to share some parts of an application across platforms while keeping other parts completely separate.

With KMM, you can get this flexibility and retain the benefits of native programming. Use a single codebase for the business logic of iOS and Android apps and write platform-specific code only where it’s necessary, to implement a native UI or when working with platform-specific APIs.

file

KMM is seamlessly integrated with your mobile project. Shared code, written in Kotlin, is compiled to JVM bytecode with Kotlin/JVM and to native binaries with Kotlin/Native, so you can use your KMM business-logic modules just like any other regular mobile library.

Sharing Kotlin code between mobile platforms has already saved a lot of time and effort for many companies. Here are some inspiring stories:

  • Quizlet migrated their business logic from a shared JavaScript approach to KMM and drastically improved the performance of both their Android and iOS applications.
  • Fastwork introduced KMM for the domain and data layers of their application to share business logic and API service between mobile platforms, significantly boosting their team’s productivity.
  • Yandex.Disk started out by experimenting with the integration of a small feature, and when the experiment proved successful, they implemented their whole data synchronization logic in KMM.

The remarkable results achieved by these and many over teams have been a big part of our inspiration, and we hope that their stories will encourage you to start sharing code between mobile platforms with KMM.

Enjoy creating mobile apps with KMM

KMM is still quite new to the mobile development world, but we believe that it is a true game-changer. That’s why we allocated a separate team inside Kotlin to push KMM forward and provide the best developer experience for the creation of cross-platform mobile applications with Kotlin.

As a first step toward this, today we are happy to present to you the first preview of the KMM plugin for Android Studio along with the new KMM developer portal.

Let’s start our KMM Journey!

Work in a familiar environment

With the new KMM plugin, you can write, run, test, and debug shared code in Android Studio, without switching to other IDEs. To install it, select Preferences | Plugins, search for the Kotlin Multiplatform Mobile plugin in Marketplace, and press the Install button.

Configure a new application in a few clicks

With the New Kotlin Multiplatform Mobile Project wizard, you can create a ready-to-run mobile application project with a shared codebase in just a few clicks. To see how it works on both platforms, just select the run configuration you need and click the Run button.

file

The generated project will contain examples of how to connect to platform-specific API and basic test coverage. You can use this wizard to explore the basic features of KMM or as a scaffolding tool for your new KMM production application.

Follow this tutorial to install the plugin and create your first multiplatform application with the wizard.

Introduce KMM to your existing project in one step

You also can start your KMM journey right in your current project: the shared Kotlin code can be easily integrated into your existing code just like any other regular dependency. The New Kotlin Multiplatform Mobile Module wizard will help you add a new KMM module to your project, so you can use the code you’ve already written in Kotlin and refactor it to make it compatible with iOS.

Check out this guide to integrating KMM into existing projects to learn how to design the architecture of multiplatform projects and organize the migration to it.

Work with both platforms within one IDE

You no longer need to switch IDEs and have Xcode running to check that your code works correctly on both mobile platforms. With the new plugin, you get integration with your iOS device and simulator directly in Android Studio. This gives you the following capabilities:

  • Run and debug the iOS application on the simulator or a device with the predefined run configuration.
  • Run and debug common and iOS specific tests on the iOS simulator by simply clicking the gutter icon on a test class or method.

For both the application and tests you can set breakpoints and debug your code on iOS.

Integrate with the iOS ecosystem without any overhead

As mentioned above, KMM is seamlessly integrated with your mobile project. For Android, you can use Kotlin for every part of your project. At the same time, KMM provides tight integration with the iOS development process, because of Kotlin/Native’s interoperability with Objective-C/Swift, the integration with the CocoaPods dependency manager, and the ability to use platform-specific APIs with the expect/actual pattern.

Enjoy working with Kotlin from Swift code with Kotlin/Native

Kotlin/Native provides bidirectional interoperability with Objective-C/Swift. Kotlin modules can be fully used in Swift/Objective-C. You can use Objective-C frameworks and libraries in Kotlin code, as well as Swift libraries if their API is exported to Objective-C with

@objc

.

Learn more about Kotlin/Native’s interoperability with Swift/Objective-C.

Easily manage iOS dependencies

Kotlin/Native provides integration with the CocoaPods dependency manager. You can add dependencies on Pod libraries stored in the CocoaPods repository or locally, and you can also use multiplatform projects with native targets as a CocoaPods dependency (Kotlin Pod). Manage Pod dependencies directly in Android Studio and enjoy full coding support, including highlighting and completion.

This is how the typical KMM library configuration looks:

kotlin {
	android()
     ios()
    
     cocoapods {
         summary = "CocoaPods test library"
         homepage = "https://github.com/JetBrains/kotlin"
         pod("AFNetworking", "~> 4.0.0")
         podfile = project.file("../ios-app/Podfile")
     }
 }

Connect the library to your iOS project as a Kotlin Pod by adding its name and path to the

Podfile

:

 use_frameworks!

 target 'ios-app' do
         pod 'kotlin_library', :path => '../kotlin-library'
 end

Learn more about CocoaPods integration.

Learn how to create better multiplatform mobile apps on the new Developer Portal

The new KMM Developer Portal is designed to make your journey more comfortable and productive, from your very first experience with KMM all the way through to using it in production.

The documentation section is your trusted resource when you are working with KMM. You will find content for all levels of expertise, from tutorials to get you started to more advanced development topics. It contains useful information about common tasks, like organizing networking and data storage layers and even organizing the development process around KMM.

Pick up new ideas about the benefits of using KMM in your application by learning from the first-hand experience of a variety of teams who are already using KMM in their products in the case studies section.

The power of the community

We are indebted to the following companies and independent developers whose investment of time, knowledge, and expertise were crucial for this release: Kevin Galligan, Alec Strong, Arkadii Ivanov, Ben Asher, John O’Reilly, Louis CAD, Kris Wong, Aleksey Mikhailov and and many other incredible engineers. Thank you for reporting issues on YouTrack, participating in product research and interviews, sharing stories about your experience using KMM, and creating incredible multiplatform libraries!

We also want to thank the teams who helped us create content for the new Developer Portal: Touchlab, IceRock, and Kodein Koders. Your work will help thousands of developers delve deeper into Kotlin Multiplatform Mobile and harness its full power.

You rock, folks!

Try it now

With all these cool features, we are happy to announce that KMM is now in Alpha. This means that the Kotlin team is fully committed to improving this technology and helping it evolve. It is also a signal that the product will develop quickly. We’ll listen to your feedback and provide fixes and improvements as soon as possible. Please help us increase the stability of KMM by reporting any issues you find via our tracker.

Going Alpha means that everything is ready for you to start using KMM to share business logic code between mobile platforms. You can create a new project or easily integrate a KMM module into existing ones. In both scenarios, the work can be done with minimal cost and you can always go back to fully native development. The community is growing fast, and you can influence the development of the whole ecosystem by participating in it.

So now is a great time to start using KMM!

To get the best experience of taking a deep dive into KMM and to discuss all the features you plan to explore, join the community of multiplatform enthusiasts in Slack (get invite here) and subscribe to the “kotlin-multiplatform” tag on Stack Overflow.

Though we try our best, we can’t guarantee a smooth migration just yet. However, we’ll try to avoid compatibility issues as much as possible by using feature flags and providing migration guides for new versions.

Share your feedback

This release is just the beginning of the journey, but we need your help along the way. We look forward to all your feedback, both bad and good. Become an inspiration for others by sharing your stories of using Kotlin Multiplatform Mobile, and please share any ideas you have about how we can improve KMM.

Let’s Kotlin!

Continue Reading Kotlin Multiplatform Mobile goes Alpha

JetBrains Toolbox 2020.2. Summary

All tools in the JetBrains Toolbox and included in the All Products Pack subscription have been updated to their new 2020.2 versions. Below you can read about what the updates bring to particular tools you use from the toolset, and you can update to the newest version via the Toolbox App or from the tool itself.

IntelliJ IDEA

IntelliJ IDEA 2020.2 lets you review and merge GitHub pull requests right from inside the IDE, quickly navigate between warnings and errors in a file through the new Inspections Widget, view the full list of issues in a current file with the Problems tool window, and get notified if your changes break other files. You can use Jakarta EE, and get better support for Quarkus, Micronaut, and OpenAPI.
WebStorm

WebStorm 2020.2 comes with a long-awaited option for using Prettier as the default formatter, best-in-class (now we can finally say so!) support for Vue, new intentions for JavaScript, full support for GitHub pull requests, and much more!
PyCharm

PyCharm 2020.2 comes out with a lot of improvements to increase your productivity and code quality. Now you can perform the full Pull Request workflow without leaving your IDE, using PyCharm’s newly designed UI. You can also easily catch exceptions in your code with the new preview window that will stop the code execution and point out the line of code that is generating the problem. Finally, changing method signatures and renaming classes have been made easier with the new in-place refactoring feature. Just type your changes in the editor, review it, and apply it to all its usages.
RubyMine

RubyMine 2020.2 introduces a new way to review problems in code, a whole host of new intention actions, support for the Liquid template language, full support for GitHub pull requests, and many more new features for Ruby, Rails, JS, and database tools.
ReSharper

ReSharper 2020.2 brings new inspections and quick-fixes for C#8 and nullable reference types, the much-awaited Code Cleanup on Save, and a revamped Unit Test Runner. Also, ReSharper C++ brings you to the next level of Unreal Engine development and comes with a lot of improvements for C++/CLI support, navigation, and code analysis.
Please note the new licensing for ReSharper covered in this blog post.
icon_AppCode

AppCode 2020.2 is here with initial Swift Package Manager support, speed improvements for code completion, navigation, and highlighting, the Change Signature refactoring for Swift, a brand new Problems view and inspection widget, full support for GitHub pull requests, and more!
PhpStorm

PhpStorm 2020.2 is a major update for the IDE. It brings support for PHP 8 Union Types, a new control flow engine for PHP, full GitHub pull requests workflow support inside the IDE, a brand-new Inspection Widget, OpenAPI support via a plugin, and more.
GoLand

GoLand 2020.2 includes new features for Go Modules, better presentation of possible problems and weak places in your code, new code inspections, new code editing features, such as the long-awaited Add Caret Per Selected Line, updates for version control including WSL2 support for Git on Windows, and more!
Rider

Rider 2020.2 delivers several highly requested features such as the Localization Manager to help you work with resources in your app or website, and Shader support in our Unity integration. We’ve completely reworked the Unit Test Runner and the debugger API to make them faster, more powerful, and more stable.
CLion

CLion 2020.2 covers a wider variety of C++ projects by adding Makefile projects and polishing CMake support. Thanks to better compliance with the C++20 standard, many reworked code analysis checks, and new unit testing abilities, writing high-quality modern C++ code has never been easier.
DataGrip

DataGrip 2020.2 brings a separate editor for cell values, DML preview in the data editor, Google BigQuery dialect, and more!

With these releases out, we’ve already started working on further improvements. This means that early access programs for 2020.3 should open very soon. Stay tuned!

Your JetBrains team

Continue Reading JetBrains Toolbox 2020.2. Summary

Kotlin 1.4 Released with a Focus on Quality and Performance

You can read this blog post in other languages:
日本語, Français, 한국어, Español, Português, Русский, 简体中文

Today we’re releasing Kotlin 1.4.0! Over the past years, we’ve been working hard on making Kotlin a programming language that is fun, enjoyable, and productive to work with. To continue our pursuit of this goal with this version of Kotlin, we put a lot of energy and effort into improving the performance and quality of Kotlin and its tooling. We are also excited to announce support for several new language features, including the long-awaited SAM conversions for Kotlin interfaces.

file

To help you get the most out of the changes and improvements introduced in Kotlin 1.4, we’re inviting all of you to the Kotlin 1.4 Online Event, where you will be able to enjoy four days of Kotlin talks, Q&As with the Kotlin team, and more – completely free.

Community and ecosystem

More than 5.8 million people have edited Kotlin code in the last 12 months, and the numbers are constantly growing:

file

We’re delighted to see how popular Kotlin is becoming! The numbers of active users – we’ll explain this metric in more detail in a future blog post – have been especially encouraging. Here, we are seeing a 1.5-fold increase over the previous year’s figures.

According to the StackOverflow Developer Survey 2020, Kotlin has climbed to 13th place among the most popular programming languages for professional developers, and we’re happy to see that Kotlin is one of the top 5 most loved languages.

Many companies have picked Kotlin as their language of choice, and are successfully using it on all platforms. We’re happy to see this tendency, and we’re tremendously grateful that so many of these companies have made case studies available for the community to read and learn from. Here are just a few amazing examples of software recently developed in Kotlin:

Our Kotlin communities are also growing rapidly. Over 30,000 Kotlin developers are now exchanging knowledge and supporting each other on Slack and Reddit, and more than 90,000 people follow our official Twitter account for tips, tricks, and announcements. With over 200 user groups worldwide, the Kotlin community is thriving and growing. We’re thankful to all of you for helping spread the word, sharing your knowledge, and supporting your fellow Kotlin developers. The warm, welcoming atmosphere you create is what makes exploring Kotlin together such a delightful experience. It wouldn’t be the same without you.

Kotlin 1.4 Online Event

We want to make sure that you have a great experience using Kotlin 1.4, and we want you to have a good idea of where we are taking the language next. This is why we are happy to invite all of you to our Kotlin 1.4 Online Event!

It consists of four days packed with knowledge about Kotlin and the future of the language and its ecosystem: We’ll discuss the new changes and improvements we made with Kotlin 1.4, and we’ll share our future plans for the language. Our Kotlin team members will answer your questions in daily Q&A sessions. Submit your questions in advance by tweeting them with the #kotlin14ask hashtag, or using this form.

The Kotlin 1.4 Online Event will be streamed on October 12–15, and you can register for free here:

Register for Kotlin 1.4 Online Event

We look forward to seeing all of you there!

Focusing on quality

Our main focus for this release was improving the overall development experience with Kotlin, including improved IDE performance and stability. Our goal is to make Kotlin users as productive as possible, and we focused on improving the things that are most important to users, so they feel even happier when using it!

We’ve reviewed and fixed more than 60 performance issues, including many that were causing IDE freezes or memory leaks. During the EAP phase for Kotlin 1.4.0, we gathered a lot of positive feedback indicating that the overall experience is now much more enjoyable!

When you are working with a project and open a large Kotlin file for the first time, you now see its content with highlighting much sooner. In most cases, highlighting is now 1.5-4 times faster:

We have also significantly improved the time it takes for autocomplete suggestions to appear. The following graph shows an overview of the average autocomplete response times that Kotlin users experience. The number of cases in which completion takes more than 500 ms has been cut nearly in half:

file

Note that these latest changes, including the code highlighting speed-up, require IntelliJ IDEA 2020.1+ and Android Studio 4.1+.

Performance improvements are an ongoing process, and we have many more enhancements planned, like continuing to work on eliminating freezing and making typing smoother. We’ve already started integration with the new experimental Kotlin compiler frontend that will make the IDE a lot faster. This is a huge task that requires many parts of the plugin to be rewritten, but it will boost performance in many areas of the IDE, including code completion, syntax highlighting, and compiler error reporting.

New IDE functionality

Our mission at JetBrains is to make software development a more productive and enjoyable experience, so we naturally want to make sure that the tooling surrounding Kotlin is excellent and makes coding Kotlin as easy as possible.

To make it easier for you to work with coroutines, and especially to pinpoint bugs in your concurrent applications, we’ve introduced the Coroutine Debugger. We’re going to expand on its initial feature set to provide the functionality most needed by the community, so please share your feedback with us using one of our channels or in the comments section below.

We are also introducing a new flexible Kotlin Project Wizard. This new wizard provides a single place for you to create and configure Kotlin projects of different types, making it easy to get started even with more complex structures such as multiplatform projects.

More than 40 new quick-fixes, intentions, and inspections have been added with Kotlin 1.4.0, and will be available exactly when you need them – when you modify your code, and press Alt+Enter to see what’s available in your specific context.

New compiler

For quite some time now, we’ve been working on a new Kotlin compiler that will advance the evolution of Kotlin in terms of performance and extensibility. The main goals for the new compiler are that it should be really fast, unify all the platforms that Kotlin supports, and provide an API for compiler extensions. We’re introducing new parts step by step, so that they reach the user as soon as possible. With Kotlin 1.4.0, we’re releasing several parts from this ongoing effort:

We’re actively working on a new frontend implementation, which will provide the biggest performance increase in the compiler pipeline. The frontend is the part of the compiler that parses the code, resolves names, performs type checking, and more, so it affects the IDE performance as well. A preview of it will be available in future releases, stay tuned!

Language features

Kotlin 1.4 comes with many new features:

Library improvements

Our general priority for the standard library is to improve consistency, both across different platforms and among the operations themselves. In this release, the Kotlin standard library gets new collection operators, delegated properties improvements, the double-ended queue implementation

ArrayDeque

, and much more.

You can use the standard library in “common” code – the code shared between different platforms, be they Android & iOS or JVM & JS. We’re gradually extending the common library and adding or moving missing functionality to it.

It is also no longer necessary to declare a dependency on the

stdlib

in any Gradle Kotlin project, whether you are targeting a single platform or working in a multiplatform project. Starting with Kotlin 1.4.0, this dependency is added by default.

We’re working on other parts of the Kotlin ecosystem:

Kotlin/JVM

We encourage you to try out the new Alpha Kotlin/JVM backend for your regular projects and share your feedback! Along with unifying the compiler pipelines, this effort will help us bring compiler extensions like Jetpack Compose to the Kotlin community more quickly.

Language features specific to Kotlin/JVM:

Kotlin/JS

Kotlin 1.4.0 comes with a new Gradle DSL and an Alpha version of the new Kotlin/JS compiler backend, among other features.

  • The new Gradle DSL adds support for configuring CSS and style loaders from the DSL, it includes various improvements related to npm dependency management and improves control over the Dukat integration.
  • The new Kotlin/JS compiler backend gives a taste of the future for Kotlin/JS. It includes optimizations and features such as the automatic generation of TypeScript definitions from Kotlin code, smaller binaries and bundles, a modernized way to expose Kotlin functionality to JavaScript, and more.

Kotlin/Native

Kotlin/Native got a significant number of new features and improvements, including:

The current automatic memory management implementation in Kotlin/Native has limitations when it comes to concurrency and we are working on a replacement for it.

An important focus for Kotlin/Native is making it seamless for Kotlin Multiplatform Mobile, but it’s not limited to this.

Kotlin Multiplatform

Making Kotlin a great multiplatform solution is one of our top priorities. We promised some important improvements at KotlinConf, and we’re happy to report on what we’ve delivered:

We’re working on an Android Studio plugin for running, testing, and debugging Kotlin code on iOS devices and simulators. The first public preview is going to be released very soon, so please stay tuned.

We’re soon going to release a bunch of materials created with the help of Kotlin community members explaining how you can use Kotlin Multiplatform Mobile (KMM) technology to target specifically mobile use-cases in which code is shared between Android and iOS.

Despite the major focus now being on mobile targets, the Web target for Kotlin Multiplatform is already actively used by JetBrains to build and ship JetBrains Space. Web target continues to be an important strategic investment for Kotlin.

More details

You can find detailed descriptions of new features on the Kotlin 1.4 What’s New page and documentation, and read more about migrating to Kotlin 1.4.

As in all major releases, some deprecation cycles of previously announced changes are coming to an end with Kotlin 1.4. All of these cases were carefully reviewed by the language committee and are listed in the Compatibility Guide for Kotlin 1.4.

How to help us improve Kotlin

The Kotlin plugin in IntelliJ IDEA and Android Studio can collect anonymized statistics about how you use its functionality. We kindly ask you to opt in to these statistics!

This anonymous data greatly helps us understand our users better, see what works, what is causing difficulties, and where we should direct our focus. To enable statistics, go to Preferences, open Appearance & Behaviour | System Settings | Data Sharing and activate the Send usage statistics checkbox.

Top issue reporters since Kotlin 1.3

We’d like to thank all the members of the community who helped us make this release better by reporting issues to YouTrack! We’ve made a list of the top 20 reporters and would like to thank them specifically:

Igor Wojda (145 issues); Louis CAD (87 issues); Marc Knaup (86 issues); AndroidDeveloperLB (83 issues); Robert Stoll (68 issues); Morgan Bartholomew (62 issues); Victor Turansky (54 issues); Guan Tianyi (51 issues); Scott Pierce (38 issues); Andreas Malik (37 issues); Steven Schäfer (37 issues); Björn Kautler (36 issues); Róbert Papp (34 issues); Toshiaki Kameyama (30 issues); Nicholas Bilyk (29 issues); Michael Bailey (26 issues); Jake Wharton (25 issues); Lamberto Basti (24 issues); Serge Pro (23 issues); Egor Andreevici (21 issues).

Start using Kotlin 1.4 right now

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

In Gradle and Maven, use 1.4.0 as the compiler version. See the docs for Gradle and for Maven.

IntelliJ IDEA and Android Studio automatically prompt you to update the Kotlin plugin to version 1.4.0. You can also open Preferences | Plugins and update the Kotlin plugin manually.

The command-line compiler can be downloaded from the GitHub release page.

You can use the following versions of the libraries published together with this release:

The versions of libraries from

kotlin-wrappers

(

kotlin-react

etc.) can be found in the corresponding repository.

The latest IDE performance improvements, including the code highlighting speed-up, require IntelliJ IDEA 2020.1+ and Android Studio 4.1+.

If you run into any problems with the new release, you can find help on Slack (get an invite here) and report issues in our YouTrack.

Thank you!

We’re really grateful to everyone who has tried out and given us feedback on the Kotlin EAPs and experimental features. We are developing the Kotlin language together with you, and making many design decisions based on your invaluable input. Keeping this fast and effective feedback loop going with the community is really important to help Kotlin become the best it can be!

We want to say a big thank you to all our external contributors whose pull requests were included in this release. You helped us make this release happen!

We’re grateful to all members of our community who are creating so many amazing things with Kotlin. Kotlin 1.4: One for all!

Continue Reading Kotlin 1.4 Released with a Focus on Quality and Performance

Kotlin 1.4.0-RC: Debugging coroutines

We continue to highlight the upcoming changes in 1.4 release. In this blogpost, we want to describe a couple of important features related to coroutines:

  • New functionality to conveniently debug coroutines
  • The ability to define deep recursive functions

These changes are already available for you to try in the 1.4.0-RC release!

Let’s dive into details.

Debugging coroutines

Coroutines are great for asynchronous programming (but not only for that), and many people already use them or are starting to use them. When you write code with coroutines, however, trying to debug them can be a real pain. Coroutines jump between threads. It can be difficult to understand what a specific coroutine is doing or to check its context. And in some cases, tracking steps over breakpoints simply doesn’t work. As a result, you have to rely on logging or mental effort to debug the code with coroutines. To address this issue, we’re introducing new functionality in the Kotlin plugin that aims to make debugging coroutines much more convenient.

The Debug Tool Window now contains a new Coroutines tab. It is visible by default, and you can switch it on and off:

In this tab, you can find information about both currently running and suspended coroutines. The coroutines are grouped by the dispatcher they are running on. If you started a coroutine with a custom name, you can find it by this name in the Tool Window. In the following example, you can see that the main coroutine is running (we’ve stopped on a breakpoint inside it), and the other four coroutines are suspended:

import kotlinx.coroutines.*

fun main() = runBlocking {
   repeat(4) {
       launch(Dispatchers.Default + CoroutineName("Default-${'a' + it}")) {
           delay(100)
           val name = coroutineContext[CoroutineName.Key]?.name
           println("I'm '$name' coroutine")
       }
   }
   delay(50)
   // breakpoint
   println("I'm the main coroutine")
}

With the new functionality, you can check the state of each coroutine and see the values of local and captured variables. This also works for suspended coroutines!

In this example, we check the values of the local variables of suspended coroutines:

import kotlinx.coroutines.*

fun main() = runBlocking<Unit> {
   launch {
       val a = 3
       delay(300)
       println(a)
   }
   launch {
       val b = 2
       delay(200)
       println(b)
   }
   launch {
       val c = 1
       delay(100)
       // breakpoint here:
       println(c)
   }
}

Choose a suspended coroutine (click

invokeSuspend

to see its state on that point) and the

Variables

tab will show you the state of the local variables:

You can now see a full coroutine creation stack, as well as a call stack inside the coroutine:

Use the ‘Get Coroutines Dump’ option to get a full report containing the state of each coroutine and its stack:

At the moment, the coroutines dump is still rather simple, but we’re going to make it more readable and helpful in future versions.

Note that to make the debugger stop at a given breakpoint inside a coroutine, this breakpoint should have the “Suspend: All” option chosen for it:

To try this new functionality for debugging coroutines, you need to use the latest version of kotlinx.coroutines, 1.3.8-1.4.0-rc, and the latest version of the Kotlin plugin (e.g. 1.4.0-rc-release-IJ2020.1-2).

The functionality is available only for Kotlin/JVM. If you encounter any problems (please don’t forget to share the details with us!), you can switch it off by opening Build, Execution, Deployment | Debugger | Data Views | Kotlin in Preferences and choosing Disable coroutines agent. For now, we’re releasing this functionality for debugging coroutines in the experimental state, and we’re looking forward to your feedback!

Defining deep recursive functions using coroutines

In Kotlin 1.4, you can define recursive functions and invoke them even when the call depth is greater than 100,000, using the standard library support based on coroutines!

Let’s first look at an ordinary recursive function, whose usage results in a

StackOverflowError

when the recursion depth gets too high. After that, we’ll discuss how you can fix the problem and rewrite the function using the Kotlin standard library.

We’ll use a simple binary tree, where each

Tree

node has a reference to its

left

and

right

children:

class Tree(val left: Tree?, val right: Tree?)

The depth of the tree is the length of the longest path from its root to its child nodes. It can be computed using the following recursive function:

fun depth(t: Tree?): Int =
   if (t == null) 0 else maxOf(
       depth(t.left),
       depth(t.right)
   ) + 1

The tree depth is the maximum of the depths of the left and right children increased by one. When the tree is empty it’s zero.

This function works fine when the recursion depth is small:

class Tree(val left: Tree?, val right: Tree?)

fun depth(t: Tree?): Int =
   if (t == null) 0 else maxOf(
       depth(t.left),
       depth(t.right)
   ) + 1

fun main() {
//sampleStart
    val tree = Tree(Tree(Tree(null, null), null), null)
    println(depth(tree)) // 3
//sampleEnd
}

However, if you create a tree with a depth greater than 100,000, which in practice is not so uncommon, you’ll get

StackOverflowError

as a result:

class Tree(val left: Tree?, val right: Tree?)

fun depth(t: Tree?): Int =
   if (t == null) 0 else maxOf(
       depth(t.left),
       depth(t.right)
   ) + 1
//sampleStart
fun main() {
   val n = 100_000
   val deepTree = generateSequence(Tree(null, null)) { prev ->
       Tree(prev, null)
   }.take(n).last()

   println(depth(deepTree))
}
/*
Exception in thread "main" java.lang.StackOverflowError
  at FileKt.depth(File.kt:5)
  ...
*/
//sampleEnd

The problem is that the call stack gets too large. To solve this issue, you can use a VM option to increase the maximum stack size. However, while this might work for specific use cases, it’s not a practical solution for the general case.

Alternatively, you can rewrite the code and store results for intermediate calls by hand in the heap rather than on the stack. This solution works in most cases and is common in other languages. However, the resulting code becomes non-trivial and complicated, and the beauty and simplicity of the initial function are lost. You can find an example here.

Kotlin now provides a clean way to solve this problem based on the coroutines machinery.

The Kotlin library now includes the definition

DeepRecursiveFunction

, which models recursive calls using the suspension mechanism:

class Tree(val left: Tree?, val right: Tree?)

@OptIn(ExperimentalStdlibApi::class)
val depthFunction = DeepRecursiveFunction<Tree?, Int> { t ->
   if (t == null) 0 else maxOf(
       callRecursive(t.left),
       callRecursive(t.right)
   ) + 1
}

@OptIn(ExperimentalStdlibApi::class)
fun depth(t: Tree) = depthFunction(t)

fun main() {
   val n = 100_000
   val deepTree = generateSequence(Tree(null, null)) { prev ->
       Tree(prev, null)
   }.take(n).last()

   println(depth(deepTree)) // 100000
}

You can compare the two versions, the initial one and the one using

DeepRecursiveFunction

, to make sure that the logic remains the same. Your new function now becomes a variable of type

DeepRecursiveFunction

, which you can call using the ‘invoke’ convention as

depthFunction(t)

. The function body now becomes the body of the lambda argument of

DeepRecursiveFunction

, and the recursive call is replaced with

callRecursive

. These changes are straightforward and easy to make. Note that while the new

depth

function uses coroutines under the hood, it is not itself a

suspend

function.

Understanding how

DeepRecursiveFunction

is implemented is interesting, but it is not necessary in order for you to use it and benefit from it. You can find the implementation details described in this blog post.

DeepRecursiveFunction

is a part of the Kotlin standard library, not part of the

kotlinx.coroutines

library, since it’s not about asynchronous programming. At the moment this API is still experimental, so we’re looking forward to your feedback!

How to try it

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

In IntelliJ IDEA and Android Studio, you can update the Kotlin Plugin to version 1.4.0-RC. See how to do this.

If you want to work on existing projects that were created before installing the preview version, you need to configure your build for the preview version in Gradle or Maven. Note that unlike the previous preview versions, Kotlin 1.4.0-RC is also available directly from Maven Central. This means you won’t have to manually add the

kotlin-eap

repository to your build files.

You can download the command-line compiler from the Github release page.

Share your feedback

We’ll be very thankful if you find and report bugs to our issue tracker. We’ll try to fix all the important issues before the final release, which means you won’t need to wait until the next Kotlin release for your issues to be addressed.

You are also welcome to join the #eap channel in Kotlin Slack (get an invite here). In this channel, you can ask questions, participate in discussions, and get notifications about new preview builds.

Let’s Kotlin!

Continue Reading Kotlin 1.4.0-RC: Debugging coroutines

Kotlin 1.4.0-RC Released

We’re almost there! We’re happy to unveil Kotlin 1.4.0-RC – the release candidate for the next major version of our programming language. Read on to learn about what has changed in Kotlin 1.4.0-RC, and make sure to try its new features before they are officially released with Kotlin 1.4.0.

A special thanks to everyone who tried our milestone releases (1.4-M1, 1.4-M2, and 1.4-M3), shared their feedback, and helped us improve this version of Kotlin!

This post highlights the new features and key improvements that are available in Kotlin 1.4.0-RC:

Improved *.gradle.kts IDE support

We significantly improved the IDE support for Gradle Kotlin DSL scripts (*.gradle.kts files) in Kotlin 1.3.70, and we’ve continued to improve it for Kotlin 1.4.0-RC. Here is what this new version brings:

Loading script configuration explicitly for better performance

Previously, when you added a new plugin to the

buildscript

or

plugins

block of your

build.gradle.kts

, the new script configuration was loaded automatically in the background. Then, after it was applied, you could use code assistance for the newly added plugin.

To improve performance, we’ve removed this automatic behavior of applying changes to the script configuration upon typing. For Gradle 6.0 and above, you need to explicitly apply changes to the configurations by clicking Load Gradle Changes or by reimporting the Gradle project.

In earlier versions of Gradle, you need to manually load the script configuration by clicking Load Configuration in the editor.

We’ve added one more action in IntelliJ IDEA 2020.1 with Gradle 6.0+, Load Script Configurations, which loads changes to the script configurations without updating the whole project. This takes much less time than reimporting the whole project.

Better error reporting

Previously you could only see errors from the Gradle Daemon (a process that runs in the background and is responsible for all Gradle-related tasks and activities) in separate log files. Now if you use Gradle 6.0 or above, the Gradle Daemon returns all the information about errors directly and shows it in the Build tool window. This saves you both time and effort.

Less boilerplate in your project’s configuration

With improvements to the Kotlin Gradle plugin, you can write less code in your Gradle build files: one of the most common scenarios is now enabled by default.

Making the standard library a default dependency

An overwhelming majority of projects require the Kotlin standard library. Starting from 1.4.0-RC, you no longer need to declare a dependency on

stdlib

in each source set manually — it will now be added by default. The automatically added version of the standard library will be the same as the version of the Kotlin Gradle plugin, since they have the same versioning.

This is how a typical multiplatform project configuration with Android, iOS, and JavaScript targets looked before 1.4:

...

android()
ios()
js()

sourceSets {
    commonMain {
        dependencies {
            implementation("org.jetbrains.kotlin:kotlin-stdlib-common")
            implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core-common:1.3.6")
        }
    }
   
    androidMain {
        dependencies {
            implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
            implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.6")
        }
    }

    jsMain {
        dependencies {
            implementation("org.jetbrains.kotlin:kotlin-stdlib-js")
            implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core-js:1.3.6")
        }
    }

    iosMain {
        dependencies {
            implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core-native:1.3.6")
        }
    }
}

...

Now, you don’t need to explicitly declare a dependency on the standard library at all, and with hierarchical project structure support, announced in 1.4-M2, you have to specify other dependencies only once. So your Gradle build file will become much more concise and easy to read:

...

android()
ios()
js()

sourceSets {
    commonMain {
        dependencies {
            implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.6")
        }
    }
}

...

For platform source sets and backend-shared source sets, the corresponding standard library will be added, while a common standard library will be added to the rest. The Kotlin Gradle plugin will select the appropriate JVM standard library depending on the

kotlinOptions.jvmTarget

setting.

If you declare a standard library dependency explicitly (for example, if you need a different version), the Kotlin Gradle plugin won’t override it or add a second standard library. And if you do not need a standard library at all, you can add the opt-out flag to the Gradle properties:

kotlin.stdlib.default.dependency=false

Kotlin/Native

Simplified management of CocoaPods dependencies

Previously, once you integrated your project with the dependency manager CocoaPods, you could build an iOS, macOS, watchOS, or tvOS part of your project only in Xcode, separate from other parts of your multiplatform project. These other parts could be built in IntelliJ IDEA.

Moreover, every time you added a dependency on an Objective-C library stored in CocoaPods (Pod library), you had to switch from IntelliJ IDEA to Xcode, run the task

pod install

, and run the Xcode build there.

Now you can manage Pod dependencies right in IntelliJ IDEA while enjoying the benefits it provides for working with code, such as code highlighting and completion. You can also build the whole Kotlin project with Gradle, without having to switch to Xcode. This means you only have to go to Xcode when you need to write Swift/Objective-C code or run your application on a simulator or device.

Now you can also work with Pod libraries stored locally.

Depending on your needs, you can add dependencies between:

  • A Kotlin project and Pod libraries from the CocoaPods repository.
  • A Kotlin project and Pod libraries stored locally.
  • A Kotlin Pod (Kotlin project used as a CocoaPods dependency) and an Xcode project with one or more targets.

Complete the initial configuration, and when you add a new dependency to CocoaPods, just re-import the project in IntelliJ IDEA. The new dependency will be added automatically. No additional steps are required.

Below you can find instructions on how to add dependencies on Pod libraries from the CocoaPods repository. The Kotlin 1.4 documentation will cover all scenarios.

How to use the CocoaPods integration

Install the CocoaPods dependency manager and plugin
  1. Install the
    cocoapods

    dependency manager (

    sudo gem install cocoapods

    ).

  2. Install the
    cocoapods-generate

    plugin (

    sudo gem install cocoapods-generate

    ).

  3. In the
    build.gradle(.kts)

    file of your project, apply the CocoaPods plugin with

    kotlin("native.cocoapods")

    :

    plugins {
       kotlin("multiplatform") version "1.4.0-rc"
       kotlin("native.cocoapods") version "1.4.0-rc"
    }
    
Add dependencies on Pod libraries from the CocoaPods repository
  1. Add dependencies on Pod libraries that you want to use from the CocoaPods repository with

    pod()

    .
    You can also add dependencies as subspecs.

    kotlin {
        ios()
    
        cocoapods {
            summary = "CocoaPods test library"
            homepage = "https://github.com/JetBrains/kotlin"
            pod("AFNetworking", "~> 4.0.0")
    
            //Remote Pod added as a subspec
            pod("SDWebImage/MapKit")
        }
    }
    
  2. Re-import the project.
    To use dependencies from Kotlin code, import the packages:

    import cocoapods.AFNetworking.*
    import cocoapods.SDWebImage.*
    

We’re also happy to share a sample project with you that demonstrates how to add dependencies on Pod libraries stored both remotely in the CocoaPods repository and locally.

Generate release .dSYMs on Apple targets by default

Debugging an iOS application crash sometimes involves analyzing crash reports, and crash reports generally require symbolication to become properly readable. To symbolicate addresses in Kotlin, the .dSYM bundle for Kotlin code is required. Starting with 1.4-M3, the Kotlin/Native compiler produces .dSYMs for release binaries on Darwin platforms by default. This can be disabled with the

-Xadd-light-debug=disable

compiler flag. On other platforms, this option is disabled by default. To toggle this option in Gradle, use:

kotlin {
    targets.withType<org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget> {
        binaries.all {
            freeCompilerArgs += "-Xadd-light-debug={enable|disable}"
        }
    }
}

Performance improvements

We continue to focus on optimizing the overall performance of the Kotlin/Native development process:

  • In 1.3.70 we introduced two new features for improving the performance of Kotlin/Native compilation: caching project dependencies and running the compiler from the Gradle daemon. Thanks to your feedback, we’ve managed to fix numerous issues and improve the overall stability of these features, and we will continue to do so.
  • There are also some runtime performance improvements as well. Overall runtime performance has improved because of optimizations in GC. This improvement will be especially apparent in projects with a large number of long-lived objects.
    HashMap

    and

    HashSet

    collections now work faster by escaping redundant boxing.

Kotlin/JS

With Kotlin 1.4.0-RC, we are making the

@JsExport

annotation compatible with the default compiler backend. We are also providing more robust and fine-grained control over npm dependency management and the Dukat integration for Gradle projects, refining our support for CSS, and offering a first look at our integration with the Node.js APIs, among other things.

@JsExport

annotation for default compiler backend

In the previous milestones for Kotlin 1.4, we introduced the

@JsExport

annotation, which is used to make a top-level declaration available from JavaScript or TypeScript when using the new IR compiler backend. Starting with Kotlin 1.4-M3, it is now also possible to use this annotation with the current default compiler backend. Annotating a top-level declaration with

@JsExport

when using the current default compiler backend turns off name mangling for the declaration. Having this annotation in both compiler backends allows you to transition between them without having to adjust your logic for exporting top-level declarations. Please note that the generation of TypeScript definitions is still only available when using the new IR compiler backend.

Changes to npm dependency management

Explicit version requirement for dependency declarations

Declaring dependencies on npm packages without specifying a version number makes it harder to reliably manage the packages you use. This is why you are required from now on to explicitly specify a version or version range based on npm’s semver syntax for dependencies. The Gradle DSL now also supports multiple ranges for dependencies, allowing you to pinpoint exactly which versions you want to accept in your project, for example:

dependencies {
    implementation(npm("react", "> 14.0.0 <=16.9.0))
}

Additional types of npm dependencies

Besides regular dependencies from npm, which you can specify using

npm(...)

inside your

dependencies

block, there are now three more types of dependencies that you can use:

To learn more about when each type of dependency can best be used, have a look at the official documentation linked from npm.

Automatic inclusion and resolution of transitive npm dependencies

Previously, if you depended on a library whose author did not manually add a

package.json

file to its artifacts, you would sometimes be required to manually import its npm dependencies. This was the case for

kotlinx.serialization

, for example, which required you to include

text-encoding

and

abort-controller

as dependencies in your Gradle build file for the package to work on Kotlin/JS.

Now the Gradle plugin automatically generates

package.json

files for libraries, and includes them in the

jar

or

klib

artifacts. When including a library of this sort, the file is automatically parsed and the required dependencies are automatically included, removing the need to add them to your Gradle build file manually.

Adjustments for CSS support

With Kotlin 1.4-M2, we introduced support for webpack’s CSS and style loaders directly from Gradle via

cssSettings

. In order to more closely reflect its actual tasks and effects, we have since renamed the configuration parameter to

cssSupport

. Going forward, the Gradle plugin no longer enables CSS support by default – a setting we had experimented with in 1.4-M2. We hope that this change will prevent confusion for those who include their own settings for how style sheets should be handled (for example by using Sass or Less loaders). In these situations, it would not be immediately obvious that a project’s default configuration already injects some CSS settings that could lead to a conflict.

To turn on CSS support in your project, set the

cssSupport.enabled

flag in your Gradle build file for

webpackTask

,

runTask

, and

testTask

. When creating a new project using the wizards included in IntelliJ IDEA, these settings will automatically be included in the generated

build.gradle(.kts)

file:

webpackTask {
   cssSupport.enabled = true
}
runTask {
   cssSupport.enabled = true
}
testTask {
   useKarma {
      // . . .
      webpackConfig.cssSupport.enabled = true
   }
}

We realize that having to adjust these settings individually for each task is not very convenient. We are looking at adding a central point of configuration for

cssSupport

in the plugin’s DSL (you can follow our progress here).

Improvements for Dukat integration

The Kotlin/JS Gradle plugin adds more fine-grained control to its integration with Dukat, the tool for automatically converting TypeScript declaration files (

.d.ts

) into Kotlin external declarations. You now have two different ways to select if and when Dukat should generate declarations:

Generating external declarations at build time

The npm dependency function now takes a third parameter after the package name and version:

generateExternals

. This allows you to individually control whether Dukat should generate declarations for a specific dependency, like so:

dependencies {
  implementation(npm("decamelize", "4.0.0", generateExternals = true))
}

You can use the

kotlin.js.generate.externals

flag (formerly named

kotlin.js.experimental.generateKotlinExternals

while it was still experimental) in your gradle.properties file to set the generator’s behavior for all npm dependencies simultaneously. As usual, individual explicit settings take precedence over this general flag.

Manually generating external declarations via Gradle task

If you want to have full control over the declarations generated by Dukat, if you want to apply manual adjustments, or if you’re running into trouble with the auto-generated externals, you can also trigger the creation of the declarations for all your npm dependencies manually using the

generateExternals

Gradle task. This will generate declarations in a directory titled

externals

in your project root. Here, you can review the generated code and copy any parts you would like to use to your source directories. (Please be advised that manually providing external declarations in your source folder and enabling the generation of external declarations at build time for the same dependency can result in resolution issues.)

Migration preparation for kotlin.dom and kotlin.browser to separate artifacts

In order to evolve our browser and DOM bindings for Kotlin/JS faster and decouple them from the release cycle of the language itself, we are deprecating the current APIs located in the

kotlin.dom

and

kotlin.browser

packages. We provide replacements for these APIs in the

kotlinx.dom

and

kotlinx.browser

packages, which will be extracted to separate artifacts in a future release. Migrating to these new APIs is straightforward. Simply adjust the imports used in your project to point to these new kotlinx packages. Quick-fixes in IntelliJ IDEA, accessible via Alt-Enter, can help with this migration.

Preview: kotlinx-nodejs

We are excited to share a preview of our official bindings for the Node.js APIs

kotlinx-nodejs

. While it has been possible to target Node.js with Kotlin for a long time, the full potential of the target is unlocked when you have typesafe access to its API. You can check out the

kotlinx-nodejs

bindings on GitHub.

To add

kotlinx-nodejs

to your project, make sure

jcenter()

is added to your repositories. You can then simply add a dependency on the artifact:

dependencies {
    // . . .
    implementation("org.jetbrains.kotlinx:kotlinx-nodejs:0.0.4")
}

After loading the Gradle changes, you can then experiment with the API provided by Node.js, for example by making use of their DNS resolution package:

fun main() {
    dns.lookup("example.org") { err, address, family ->
        console.log("address: $address, family IPv$family")
    }
}

Especially because this is still a preview version, we encourage you to give kotlinx-nodejs a try and report any issues you encounter in the repository’s issue tracker.

Deprecation of kotlin2js and kotlin-dce-js Gradle plugins

Starting with Kotlin 1.4, the old Gradle plugins for targeting JavaScript with Kotlin (

kotlin2js

and

kotlin-dce-js

) will be officially deprecated in favor of the

kotlin.js

Gradle plugin.
Key functionality that was available in these plugins, alongside the

kotlin-frontend-plugin

(which was already deprecated previously) has been condensed into the new plugin, allowing you to configure your Kotlin/JS target using a unified DSL that is also compatible with Kotlin/Multiplatform projects.

Since Kotlin 1.3.70, dead code elimination (DCE) has been applied automatically when using the

browserProductionRun

and

browserProductionWebpack

tasks, which run and create optimized bundles of your program. (Please note that dead code elimination is currently only available when targeting the browser for production output, not for Node.js or tests. But if you have additional use cases you’d like to see addressed, feel free to share them with us on YouTrack)

Additional quality-of-life improvements and notable fixes

  • We have added more compiler errors for prohibited usages of the
    @JsExport

    annotation to highlight such problems.

  • When using the IR compiler backend, we have enabled a new strategy that includes incremental compilation for
    klib

    s, which is one of many steps we are taking to improve compilation time.

  • The configuration for the webpack development server has been adjusted, preventing errors like
    ENOENT: no such file or directory

    when using the hot reload functionality.

Evolving the Kotlin Standard Library API

Kotlin 1.4 is a feature release in terms of Kotlin’s evolution, so it brings a lot of new features that you already know about from previous blog posts. However, another important aspect of a feature release is that it includes significant evolutionary changes in the existing API. Here’s a brief overview of the changes you can expect with the 1.4 release.

Stabilization of the experimental API

In order to ship the new things you want to see in Kotlin libraries as fast as possible, we provide experimental versions of them. This status indicates that work on the API is still in progress and that it could be changed incompatibly in the future. When you try to use the experimental API, the compiler warns you about its status and requires an opt-in (

@OptIn

annotation).

In feature releases, experimental APIs can be promoted to stable. At this point, we guarantee that their form and behavior won’t change suddenly (changes are only possible with a proper deprecation cycle). Once an API is officially stable, you can use the API safely without warnings or opt-ins.

With 1.4, we are promoting a number of experimental functions in the Kotlin libraries to stable. Here are some examples, along with versions in which they were introduced:

More API functions and classes are becoming stable in 1.4. Starting from this version (1.4.0-RC), using them in your project won’t require the

@OptIn

annotations.

Deprecation cycles

Feature releases also involve taking the next steps in existing deprecation cycles. While in incremental releases we only start new deprecation cycles with the

WARNING

level, in feature releases we tighten them to

ERROR

. In turn, API elements that already have the

ERROR

level can be completely hidden from new uses in code and only remain in binary form to preserve compatibility for already compiled code. Together, these steps ensure the gradual removal of deprecated API elements.

If your code uses API elements with a deprecation level of

WARNING

, the compiler warns you about such usages. When you update to Kotlin 1.4.0-RC, some of these warnings will turn into errors. Use the IDE prompts to properly replace erroneous usages with the provided alternatives and make sure that your code compiles again.

Detailed information about breaking changes in the Kotlin Standard Library API can be found in the Compatibility Guide for Kotlin 1.4.

Scripting

We skipped this section in a couple of previous blog posts, but we haven’t stopped working on Kotlin scripting to make it more stable, faster, and easier to use in 1.4. In the RC version, you can already observe better performance along with numerous fixes and functional improvements.

Artifacts renaming

In order to avoid confusion about artifact names, we’ve renamed

kotlin-scripting-jsr223-embeddable

and

kotlin-scripting-jvm-host-embeddable

to just

kotlin-scripting-jsr223

and

kotlin-scripting-jvm-host

(without

-embeddable

). These artifacts depend on the

kotlin-compiler-embeddable

artifact, which shades the bundled third-party libraries to avoid usage conflicts. With this renaming, we’re making the usage of

kotlin-compiler-embeddable

(which is safer in general) the default for scripting artifacts.
If, for some reason, you need artifacts that depend on the unshaded

kotlin-compiler

, use the artifact versions with the

-unshaded

suffix, such as

kotlin-scripting-jsr223-unshaded

. Note that this renaming affects only the scripting artifacts that are supposed to be used directly; names of other artifacts remain unchanged.

CLion IDE plugin is now deprecated

We’ve launched a deprecation cycle for the CLion IDE plugin. Originally it was intended to be used to debug Kotlin/Native executables. Now this capability is available in IntelliJ IDEA Ultimate. We’ll stop publishing the CLion IDE plugin after the 1.4 release. Please contact us if this deprecation causes any problems. We will do our best to help you to solve them.

Compatibility

As in all major releases, some deprecation cycles of previously announced changes are coming to an end with Kotlin 1.4. All of these cases were carefully reviewed by the language committee and are listed in the Compatibility Guide for Kotlin 1.4. You can also explore these changes on YouTrack.

Release candidate notes

Now that we’ve reached the final release candidate for Kotlin 1.4, it is time for you to start compiling and publishing! Unlike previous milestone releases, binaries created with Kotlin 1.4.0-RC are guaranteed to be compatible with Kotlin 1.4.0.

How to try the latest features

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

In IntelliJ IDEA and Android Studio, you can update the Kotlin Plugin to version 1.4.0-RC. See how to do this.

If you want to work on existing projects that were created before installing the preview version, you need to configure your build for the preview version in Gradle or Maven. Note that unlike the previous preview versions, Kotlin 1.4.0-RC is also available directly from Maven Central. This means you won’t have to manually add the

kotlin-eap

repository to your build files.

You can download the command-line compiler from the GitHub release page.

You can use the following versions of the libraries published together with this release:

The release details and the list of compatible libraries are also available here.

Share your feedback


We’ll be very thankful if you find and report bugs to our issue tracker. We’ll try to fix all the important issues before the final release, which means you won’t need to wait until the next Kotlin release for your issues to be addressed.

You are also welcome to join the #eap channel in Kotlin Slack (get an invite here). In this channel, you can ask questions, participate in discussions, and get notifications about new preview builds.

Let’s Kotlin!

External contributions


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

Continue Reading Kotlin 1.4.0-RC Released

Kotlin 1.4-M3: Generating Default Methods in Interfaces

In Kotlin 1.4, we’re adding new experimental ways for generating default methods in interfaces in the bytecode for the Java 8 target. Later, we’re going to be deprecating the

@JvmDefault

annotation in favor of generating all the method bodies in interfaces directly when the code is compiled in a special mode. Read more details of how it currently works and what will change, below.

In Kotlin, you can define methods with bodies in interfaces. It works if your code runs on Java 6 or 7, even before support for the default methods appeared on the JVM.

interface Alien {
   fun speak() = "Wubba lubba dub dub"
}

class BirdPerson : Alien

To make it work for older Java versions, the Kotlin compiler generates an additional class that contains an implementation of a default method as a static member. This is what the generated code looks like under the hood, at the bytecode level:

public interface Alien {
  String speak();

  public static final class DefaultImpls {
     public static String speak(Alien obj) {
        return "Wubba lubba dub dub";
     }
  }
}
public final class BirdPerson implements Alien {
  public String speak() {
    return Alien.DefaultImpls.speak(this);
  }
}

The Kotlin compiler generates the

DefaultImpls

class with the

speak

method. This method contains the default implementation. It takes an instance of an interface as a parameter and interprets it as

this

(in case you call other members of this interface inside). The class

BirdPerson

implementing the interface contains the same method, which only delegates to the implementation in

DefaultImpls

passing an actual

this

as an argument.

In Kotlin 1.2, we added experimental support for

@JvmDefault

annotation that works if your code targets Java 8. You can annotate each interface method having default implementation with

@JvmDefault

in order to get the default implementation generated in the bytecode:

interface Alien {
   @JvmDefault
   fun speak() = "Wubba lubba dub dub"
}

class BirdPerson : Alien

That only works in a special compiler mode: you can only use it when you specify the

-Xjvm-default

compiler argument.

The

@JvmDefault

annotation is going to be deprecated later. There’s no need to annotate each member with it; most probably you had to annotate all the interface methods with bodies, and it was quite verbose.

Eventually, we want to generate method bodies in interfaces by default when your code targets Java 8 or higher. It’s not easy to quickly make this change: we want to make sure you don’t have problems when you mix the libraries or modules of your application that are compiled with different Kotlin versions and different modes. The Kotlin compiler for future versions will continue to “understand” the old scheme of default methods, but we’ll slowly migrate to the new scheme.

New modes for generating default methods in interfaces

If your code targets Java 8 and you want to generate default methods in interfaces, you can use one of two new modes in Kotlin 1.4:

-Xjvm-default=all

or

-Xjvm-default=all-compatibility

.

In

all

mode, you only have default methods generated by the compiler, no more

DefaultImpls

objects, and no need to additionally annotate separate methods. This is the generated code for our initial sample:

// -Xjvm-default=all
public interface Alien {
  default String speak() {
     return "Wubba lubba dub dub";
 }
}
public final class BirdPerson implements Alien {}

Note that class

BirdPerson

implementing the interface doesn’t contain the

speak

method: it automatically reuses the “super” implementation thanks to the JVM support.

The Kotlin compiler of the newer versions will “understand” the old scheme. If your class compiled with the new scheme implements an interface compiled with the old scheme (with

DefaultImpls

), the compiler will recognize this and generate a hidden method in the class that delegates to the corresponding

DefaultImpls

method, as before.

The only problem that may arise is if you recompile your old code with the default method implementation and some other code depends on it, which you don’t recompile. In this case, use the

all-compatibility

mode. Then both default method bodies and

DefaultImpls

classes are generated:

// -Xjvm-default=all-compatibility
public interface Alien {
  default String speak() {
     return "Wubba lubba dub dub";
  }

  public static final class DefaultImpls {
     public static String speak(Alien obj) {
        // Calling the default method from the interface:
        return obj.$default$speak();
     }
  }
}
public final class BirdPerson implements Alien {}

Inside

DefaultImpls

the Kotlin compiler calls specifically the default method defined in the interface. (To make it a non-virtual call, the compiler makes a special trick: it generates an additional synthetic method inside an interface and calls it instead.)

With

all-compatibility

mode you don’t need to recompile the classes that already use your interface; they continue to work correctly:

public final class Moopian implements Alien {
  public String speak() {
    return Alien.DefaultImpls.speak(this);
  }
}

all-compatibility

mode guarantees binary compatibility for Kotlin clients but generates more methods and classes in the bytecode.

Fixing an issue with delegates

Before, it was a bit confusing to use an interface with

@JvmDefault

methods together with the “implementation by delegation” feature. If you used an interface with

@JvmDefault

as a delegate, the default method implementations were called even if the actual delegate type provided its own implementation:

interface Producer {
   fun produce() = "in interface"
}

class ProducerImpl : Producer {
   override fun produce() = "in class"
}

class DelegatedProducer(val p: Producer) : Producer by p

fun main() {
   val prod = ProducerImpl()
   // prints "in interface" if 'produce()' is annotated with @JvmDefault
   // prints "in class" in new jvm-default modes
   println(DelegatedProducer(prod).produce())
}

With the new jvm-default modes, it works as you would expect: the overridden version of

produce

is called when you delegate your implementation to the

ProducerImpl

class.

@JvmDefaultWithoutCompatibility

If you compile your code with

all-compatibility

mode and add a new interface, you can annotate it with the

@JvmDefaultWithoutCompatibility

annotation. It turns on “no compatibility mode” (

-Xjvm-default=all

) for this specific class. This way, no

DefaultImpls

objects will be generated. Since you’ve just added a new interface, there’s no code that calls it via the old scheme, and nothing can break.

To be precise, in

all-compatibility

mode you can use

@JvmDefaultWithoutCompatibility

to annotate all interfaces which aren’t a part of the public API (more correct is to consider public binary interface, and to say ABI), and therefore aren’t used by the existing clients.

More about all-compatibility mode for library authors

The

all-compatibility

mode is designed specifically for library authors to allow them to switch to the new scheme gradually and guarantee the binary compatibility for the library. And so, the following details and compatibility issues are aimed mainly at library authors.

Guaranteeing the binary compatibility between the new and old schemes is not totally “seamless”.
To prevent compatibility issues that might arise, the compiler reports an error in specific corner cases, while the

@JvmDefaultWithoutCompatibility

annotation suppresses this error. The following section describes the reasons for it and the use cases.

Consider a class that inherits from a generic interface:

interface LibGeneric<T> {
   fun foo(p: T): T = p
}

open class LibString : LibGeneric<String>

In

-Xjvm-default=all-compatibility

mode, the Kotlin compiler generates an error. Let’s first see why and then discuss how you can fix it.

Under the hood, to make such code work with

DefaultImpls

scheme, the Kotlin compiler of the previous version (or without using any

-Xjvm-default

flags) generates an additional method with the specialized signature in the class:

open class LibString {
   // Generated implicitly:
   fun foo(String): String { ... }
}

Sometimes, this specialized method is called in the generated bytecode. In pure Kotlin, it happens only in rare cases when your

LibString

class is open and you call

foo

from a subclass of

LibString

via

super.foo()

. In mixed projects, if you use this code from Java, the specialized version gets called every time you call

foo

on a

LibString

instance!

Without such override, you could easily break the binary compatibility: if you recompiled your

LibString

class with the new

all-compatibility

mode, and run it against the old binaries, you could get a

NoSuchMethodError

error!

The goal of

all-compatibility

mode is to guarantee binary compatibility at least for the Kotlin clients. That’s why having unexpected NoSuchMethodError errors is unacceptable. In order to prevent this, the Kotlin compiler could potentially generate the same hidden specialized method as before, however, it would cause problems when updating from

all-compatibility

to

all

mode, and it would also have issues with using default methods in diamond hierarchies. Generating such auxiliary implicit methods was necessary with the

DefaultImpls

scheme but is not needed when

default

methods are supported on the JVM level and can cause more confusion (for more details see Appendix: why we don’t like implicit methods).

We decided to prevent this binary compatibility problem by making your choice explicit.

Fixing the compiler error

One option you have is to provide an explicit override:

interface LibGeneric<T> {
   fun foo(p: T): T = p
}

open class LibString : LibGeneric<String> {
   override fun foo(p: String): String = super.foo(p)
}

Yes, it’s a bit of verbosity but for a good reason! If this code can be used from subclasses in Kotlin or from Java, adding explicit override guarantees that the older binaries will continue to work with new versions of your library compiled in

all-compatibility

mode.

Another option is to annotate your class with the

@JvmDefaultWithoutCompatibility

annotation. It turns on “no compatibility mode” for this specific class. Then an explicit override method is not required and no implicit methods are generated:

interface LibGeneric<T> {
   fun foo(p: T): T = p
}

@JvmDefaultWithoutCompatibility
open class LibString : LibGeneric<String> {
    // no implicit member
}

Appendix: Why we don’t like implicit methods

Why don’t we generate hidden methods like in the old scheme? Consider the following diagram which represents a diamond hierarchy – the Java class

JavaClass

implements the Kotlin

Base

interface both through extending

KotlinClass

and implementing

Derived

interface:

Let’s imagine that Kotlin continues to generate implicit overrides (as was necessary before with the

DefaultImpls

scheme). Then the code

JavaClass().foo()

prints

0

and not

42

! That becomes a new puzzler: there are only two methods (returning

0

and returning

42

) and it’s really confusing why the method from the base class is called and not the more specific one from

Derived

. When you take into consideration an implicit method from

KotlinClass

, the result makes sense. But we really want to avoid such puzzlers by not generating the implicit methods in the first place – and rather force developers to provide explicit methods when it’s necessary for compatibility reasons.

Conclusion

If you used the

@JvmDefault

annotation before, you can safely remove it and use one of the new modes. If you already used

-Xjvm-default=enable

, which generated only the default method implementations, you can now replace it with

-Xjvm-default=all

.

So far this support remains experimental but we’re going to switch the default mode continuously first to

all-compatibility

and then to

all

in the future major Kotlin versions. If no

-Xjvm-default

is specified now, the generated code will continue to use

DefaultImpls

.

How to try it

You can already try these new modes with Kotlin 1.4-M3 version. See here how to update the Kotlin Plugin to it.

Share your feedback

We’re grateful for all your bug reports in our issue tracker, and we’ll do our best to fix all the most important issues before the final release.

You are also welcome to join the #eap channel in our Kotlin Slack (get an invite here). In this channel, you can ask questions, participate in discussions, and get notifications of new preview builds.

Let’s Kotlin!

Continue Reading Kotlin 1.4-M3: Generating Default Methods in Interfaces

End of content

No more pages to load