Kotlin 1.6.20 est disponible
Un aperçu des nouveautés et améliorations du langage de programmation

Kotlin 1.6.20 est officiellement disponible. Cette version offre un aperçu des futures fonctionnalités du langage, active par défaut la structure hiérarchique pour les projets multiplateformes et apporte des améliorations de performances pour les plateformes Kotlin JVM, JS et Native.

Nous présentons ici les principales nouveautés et améliorations incluant :

  • Un nouveau support pour la définition de déclarations dépendantes du contexte dans Kotlin/JVM, résultant du prototype de récepteurs de contexte.
  • Une meilleure interopérabilité avec les classes et interfaces Java génériques, grâce à des types définitivement non nullables.
  • Un temps de construction plus court grâce à la compilation parallèle d'un seul module dans le backend JVM IR.
  • Une expérience de développement plus rapide, grâce à la compilation incrémentielle dans Kotlin/JS IR.
  • Des améliorations des performances de Kotlin/Native.
  • Un partage de code simplifié grâce à la structure hiérarchique des projets multiplateformes.


Prototype de récepteurs de contexte pour Kotlin/JVM

Avec Kotlin 1.6.20, vous n'êtes plus limité à un seul récepteur. Si vous avez besoin de plus, vous pouvez rendre les fonctions, les propriétés et les classes dépendantes du contexte (ou contextuelles) en ajoutant des récepteurs de contexte à leur déclaration. Une déclaration contextuelle effectue les opérations suivantes :

  • Elle exige que tous les récepteurs de contexte déclarés soient présents dans la portée d'un appelant en tant que récepteurs implicites.
  • Elle apporte les récepteurs de contexte déclarés dans sa portée de corps en tant que récepteurs implicites.

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
interface LoggingContext {
    val log: Logger // This context provides a reference to a logger 
}

context(LoggingContext)
fun startBusinessOperation() {
    // You can access the log property since LoggingContext is an implicit receiver
    log.info("Operation has started")
}

fun test(loggingContext: LoggingContext) {
    with(loggingContext) {
        // You need to have LoggingContext in a scope as an implicit receiver
        // to call startBusinessOperation()
        startBusinessOperation()
    }
}

Pour activer les récepteurs de contexte dans votre projet, utilisez l'option de compilateur -Xcontext-receivers. Veuillez noter que l'implémentation est un prototype :

  • avec -Xcontext-receivers activé, le compilateur produira des binaires de préversion qui ne peuvent pas être utilisés dans le code de production ;
  • le support EDI pour les récepteurs de contexte est actuellement minimal.

Types définitivement non nullables

Pour fournir une meilleure interopérabilité lors de l'extension des classes et des interfaces Java génériques, Kotlin 1.6.20 vous permet de marquer un paramètre de type générique comme définitivement non nullable sur le lieu d'utilisation avec la nouvelle syntaxe T & Any. La forme syntaxique provient d'une notation des types d'intersection et est maintenant limitée à un paramètre de type avec des bornes supérieures nullables à gauche de & et un Any non nullable à droite :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
fun <T> elvisLike(x: T, y: T & Any): T & Any = x ?: y

fun main() {
   // OK
   elvisLike<String>("", "").length
   // Error: 'null' cannot be a value of a non-null type
   elvisLike<String>("", null).length

   // OK
   elvisLike<String?>(null, "").length
   // Error: 'null' cannot be a value of a non-null type
   elvisLike<String?>(null, null).length
}

Définissez la version du langage sur 1.7 pour activer la fonctionnalité :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
kotlin {
   sourceSets.all {
       languageSettings.apply {
           languageVersion = "1.7"
       }
   }
}

Veuillez noter que les types définitivement non nullables sont en version bêta. Ils sont presque stables, mais des actions pourraient être nécessaires à l'avenir pour la migration. JetBrains promet cependant de faire de son mieux pour minimiser les modifications que vous devriez apporter.

Prise en charge de la compilation parallèle d'un seul module dans le backend JVM

JetBrains poursuit son travail sur l'amélioration du temps de compilation du nouveau backend JVM IR. Dans Kotlin 1.6.20, l'éditeur de logiciels pour développeurs a ajouté en mode expérimental le backend JVM IR pour compiler tous les fichiers d'un module en parallèle. La compilation parallèle peut réduire le temps total de compilation jusqu'à 15 %.

Activez le mode backend parallèle expérimental avec l'option de compilateur -Xbackend-threads. Utilisez les arguments suivants pour cette option :

  • N est égal au nombre de threads que vous souhaitez utiliser. Il ne doit pas être supérieur à votre nombre de cœurs de processeur ; sinon, la parallélisation cesse d'être efficace en raison du changement de contexte entre les threads ;
  • 0 pour utiliser un thread pour chaque cœur de CPU.

Cette parallélisation n'est utile que lorsque la construction du projet n'est pas suffisamment parallélisée par un outil de build tel que Gradle. Par exemple, si vous avez un très gros module monolithique, ajouter l'option de compilateur -Xbackend-threads à ce module peut aider. Mais si un projet se compose de nombreux petits modules et a une construction parallélisée, l'ajout d'une autre couche de parallélisation peut nuire aux performances en raison du changement de contexte.

Notez que la compilation parallèle expérimentale ne fonctionne pas avec kapt car kapt désactive le backend IR. Notez également que la compilation parallèle nécessite plus de tas JVM par conception. La quantité de tas est proportionnelle au nombre de threads.

Compilation incrémentale pour les binaires de développement avec le compilateur Kotlin/JS IR

Pour rendre le développement Kotlin/JS avec le compilateur IR plus efficace, JetBrains introduit le nouveau mode de compilation incrémentielle.

Lors de la création de fichiers binaires de développement avec la tâche Gradle compileDevelopmentExecutableKotlinJs dans ce mode, le compilateur met en cache les résultats des compilations précédentes au niveau du module. Il utilise les résultats de compilation mis en cache pour les fichiers source inchangés lors des compilations suivantes, ce qui les rend plus rapides, en particulier avec de petites modifications. Notez que cette amélioration cible exclusivement le processus de développement (raccourcissement du cycle edit-build-debug) et n'affecte pas la construction des artefacts de production.

Pour activer la compilation incrémentielle pour les binaires de développement, ajoutez la ligne suivante au gradle.properties du projet :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
kotlin.incremental.js.ir=true // false by default

Améliorations des performances de Kotlin/Native

Cette version 1.6.20 de Kotlin apporte des mises à jour de performances et des corrections de bogues qui affectent le LLVM IR généré par Kotlin. Selon les benchmarks sur des projets internes, JetBrains a réalisé en moyenne les gains de performance suivants :

  • 15 % de réduction du temps d'exécution ;
  • réduction de 20 % de la taille du code des binaires release et debug ;
  • réduction de 26 % du temps de compilation des binaires release.

Ces modifications ont également permis de réduire de 10 % le temps de compilation d'un binaire debug sur un grand projet interne de JetBrains.

Pour y parvenir, JetBrains a implémenté une initialisation statique pour certains des objets synthétiques générés par le compilateur, amélioré la façon dont elle structure LLVM IR pour chaque fonction et optimisé les caches du compilateur.

Prise en charge de la structure hiérarchique pour les projets multiplateformes

Kotlin 1.6.20 arrive avec la prise en charge de la structure hiérarchique activée par défaut. Depuis son introduction dans Kotlin 1.4.0, JetBrains a considérablement amélioré la stabilité de l'interface, entre autres.

Vous pouvez désormais partager le code source entre plusieurs cibles natives similaires. La technologie fournira des dépendances par défaut correctes et trouvera l'API exacte disponible dans le code partagé. Cela élimine une configuration de build complexe et des solutions de contournement pour obtenir la prise en charge de l'EDI pour le partage des ensembles de sources entre les cibles natives. Cela aide également à empêcher les utilisations d'API non sécurisées destinées à une cible différente.

La technologie sera également utile aux auteurs de bibliothèques. Une structure de projet hiérarchique vous permet de publier et d'utiliser des bibliothèques avec des API communes pour un sous-ensemble de cibles. Par défaut, les bibliothèques publiées avec la structure de projet hiérarchique ne sont compatibles qu'avec les projets de structure hiérarchique.

Meilleur partage de code dans votre projet

Sans prise en charge de la structure hiérarchique, il n'existe aucun moyen simple de partager du code entre certaines cibles Kotlin, mais pas toutes. Un exemple particulier qui est populaire est de partager du code sur toutes les cibles iOS et avoir accès à des dépendances spécifiques à iOS, comme Foundation.

Grâce à la prise en charge de la structure de projet hiérarchique, vous pouvez désormais y parvenir immédiatement. Dans la nouvelle structure, les ensembles de sources forment une hiérarchie. Vous pouvez utiliser les fonctionnalités et les dépendances de langage spécifiques à la plateforme pour chaque cible de compilation d'un ensemble de sources.

Par exemple, considérons un projet multiplateforme typique avec deux cibles - iosArm64 et iosX64 pour les appareils et simulateurs iOS. La chaîne d'outils Kotlin comprend que les deux cibles ont la même fonction et vous permet d'accéder à cette fonction à partir de l'ensemble source intermédiaire, iosMain.


La chaîne d'outils Kotlin fournit les dépendances par défaut correctes, comme la stdlib Kotlin/Native ou les bibliothèques natives. De plus, les outils Kotlin feront de leur mieux pour trouver exactement la surface d'API disponible dans le code partagé. Cela évite des cas tels que, par exemple, l'utilisation d'une fonction spécifique à macOS dans le code partagé pour Windows.

Plus d'opportunités pour les auteurs de bibliothèques

Lorsqu'une bibliothèque multiplateforme est publiée, l'API de ses sources intermédiaires est désormais correctement publiée avec elle, ce qui la rend disponible pour les consommateurs. Encore une fois, la chaîne d'outils Kotlin déterminera automatiquement l'API disponible dans l'ensemble source consommateur tout en surveillant attentivement les utilisations dangereuses, comme l'utilisation d'une API destinée à la JVM dans le code JS.

Configuration et installation

À partir de Kotlin 1.6.20, tous vos nouveaux projets multiplateformes auront une structure de projet hiérarchique. Aucune configuration supplémentaire n'est requise.

Si vous l'avez déjà activé manuellement, vous pouvez supprimer l'option obsolète à partir de gradle.properties :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
kotlin.mpp.enableGranularSourceSetsMetadata=true
kotlin.native.enableDependencyPropagation=true

Pour Kotlin 1.6.20, JetBrains vous recommande d'utiliser Android Studio 2021.1.1 (Bumblebee) ou version ultérieure pour obtenir la meilleure expérience.

Vous pouvez également désactiver la prise en charge de la structure hiérarchique, en définissant les options suivantes dans gradle.properties :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
kotlin.mpp.hierarchicalStructureSupport=false

Comment installer Kotlin 1.6.20

Si vous utilisez IntelliJ IDEA ou Android Studio, votre EDI vous donnera la possibilité de passer automatiquement à la nouvelle version de Kotlin dès qu'elle sera disponible. Vous pouvez toujours télécharger les dernières versions de ces EDI pour obtenir une prise en charge étendue de Kotlin :

  • IntelliJ IDEA pour développer des applications Kotlin pour différentes plateformes.
  • Android Studio pour le développement d'applications mobiles Android et multiplateformes.

Assurez-vous d'avoir également mis à jour les bibliothèques kotlinx vers des versions compatibles et spécifié la version 1.6.20 de Kotlin dans les scripts de construction de vos projets existants.

Si vous avez besoin du compilateur en ligne de commande, vous pouvez le télécharger à partir de la page de GitHub de Kotlin.

Installer le plugin Kotlin pour IntelliJ IDEA ou Android Studio