kotlin-tooling-immutable-collections-0-5-x-migration

Par kotlin · kotlin-agent-skills

Migrez le code Kotlin (et Java) de kotlinx.collections.immutable 0.3.x / 0.4.x vers la dernière version 0.5.x. La branche 0.5.x renomme chaque méthode retournant une copie sur `PersistentList` / `PersistentMap` / `PersistentSet` / `PersistentCollection` vers une forme participiale conformément à KEEP-0459 (`add`→`adding`, `removeAt`→`removingAt`, `set`→`replacingAt`, `put`→`putting`, `clear`→`cleared`, …) et déprécie les anciens noms (WARNING, avec `ReplaceWith`). Procédure guidée par le compilateur : montez la version, recompilez, puis appliquez le renommage indiqué par chaque avertissement de dépréciation. À utiliser quand l'utilisateur mentionne kotlinx.collections.immutable 0.5.x, la migration de `PersistentList`, « Use adding() instead », KEEP-0459, ou constate des avertissements de dépréciation provenant de kotlinx.collections.immutable.

npx skills add https://github.com/kotlin/kotlin-agent-skills --skill kotlin-tooling-immutable-collections-0-5-x-migration

Migration kotlinx.collections.immutable 0.5.x

La ligne 0.5.x renomme chaque méthode retournant une copie sur les collections persistantes en une forme participiale (selon KEEP-0459) et déprécie les anciens noms au niveau WARNING avec un indice ReplaceWith. La migration est un simple renommage à chaque appel, compatible binaire et sémantiquement préservé — mêmes paramètres, même ordre, même type de retour ; seul le nom change.

Pilotez-la depuis le compilateur : relevez la version, recompilez, et corrigez chaque avertissement de dépréciation — l'avertissement nomme le remplacement. Source de vérité : 0.5.0-MIGRATION.md.

Quand cela s'applique

Vérifiez la version que le projet utilise actuellement :

  • 0.3.x ou 0.4.x (toute version antérieure à 0.5.0) → exécutez la migration ci-dessous.
  • Sur 0.5.x mais pas la dernière → réglez la version sur la dernière 0.5.x et arrêtez. Tous les numéros de version 0.5.x partagent les mêmes renommages, donc un bump dans la même ligne n'ajoute aucune dépréciation et ne nécessite pas de recompilation.
  • Sur la dernière 0.5.x, ou sur 0.6.x et versions ultérieures → rien à faire.

Migration

1. Trouvez la commande de compilation

Consultez README.md, CLAUDE.md, ou AGENTS.md pour voir comment le projet est compilé ; si ce n'est pas écrit, déduisez-le à partir des fichiers de compilation — Gradle (./gradlew), Maven (mvn, ou le wrapper ./mvnw), Bazel (un wrapper bazel), ou un script personnalisé. Enregistrez la commande de compilation (et la commande de test). Dans un projet multi-modules, vous n'avez besoin que des modules qui utilisent la bibliothèque, plus ceux que vous modifiez — pas une compilation de tout le dépôt.

2. Compilation de référence

Compilez sur la version actuelle et confirmez que c'est bon. Si cela ne se compile pas maintenant, vous ne pouvez pas distinguer les erreurs post-migration des erreurs préexistantes — obtenez d'abord une commande de compilation fonctionnelle.

3. Passez à la dernière 0.5.x

Trouvez où la version est épinglée — grep -rn kotlinx-collections-immutable sur les fichiers de compilation la trouve (catalogue de versions, script de compilation, gradle.properties, pom.xml, …) — et réglez-la sur la dernière 0.5.x sur Maven Central (un -beta convient). Si la compilation épingle les hashes des artefacts (p. ex. gradle/verification-metadata.xml), mettez-les à jour aussi — la solution la moins chère est de copier directement la somme de contrôle du nouvel artefact du message d'erreur de vérification des dépendances et d'ajouter uniquement cette entrée, plutôt que de régénérer tout le fichier de métadonnées. Le bump est compatible binaire ; l'ancien code continue de compiler avec des avertissements. (Si la dépendance ne se résout pas avec une erreur de version Kotlin metadata, le Kotlin du projet est trop ancien pour l'artefact 0.5.x — relevez d'abord Kotlin.)

4. Recompilez et corrigez les avertissements

Recompilez. Chaque méthode renommée porte @Deprecated(WARNING, ReplaceWith(...)), donc le compilateur émet un avertissement par call site nommant le remplacement (p. ex. « Use removingAll() instead »). Appliquez ce renommage. Répétez compile → correction jusqu'à ce qu'aucun avertissement de dépréciation kotlinx.collections.immutable ne subsiste. (Pour multiplateforme, une compilation cible unique surface les call sites partagés. Les anciennes dépréciations de fabrique telles que immutableListOfpersistentListOf apparaissent de la même manière — appliquez-les aussi.) Une recompilation qui échoue juste après le bump échoue sur ces dépréciations (plus, si les hashes sont épinglés, une erreur de vérification des dépendances ponctuelle) — continuez à appliquer les renommages que les avertissements nomment ; ne réexécutez pas les commandes de résolution des dépendances ou de régénération des métadonnées pour essayer de l'effacer.

Faites confiance au compilateur — ne trouvez/remplacez jamais par nom. Les mêmes noms de méthode existent sur MutableList / MutableMap / MutableSet et sur les types .Builder, qui mutent sur place et ne sont pas dépréciés. Seuls les sites que le compilateur signale (récepteur statiquement Persistent*) sont renommés ; s'il ne l'a pas signalé, laissez-le.

Une Unresolved reference après un renommage signifie que le nom participial n'existe pas sur ce récepteur — vous avez scindé un renommage. Un renommage ne se compile que si la déclaration et chaque call site se déplacent ensemble. La bibliothèque l'a déjà fait pour les types kotlinx, donc renommer leurs call sites fonctionne simplement — mais cela ne s'applique pas à quoi que ce soit d'autre qui partage simplement les noms. Quand un call renommé ne se résout pas, il y a deux cas :

  • Le récepteur n'est pas lié à cette bibliothèque (un Mutable*, un .Builder, une méthode de même nom sur un autre type) — le renommage était mauvais ; annulez ce site.
  • Le récepteur est un type de projet que la base de code elle-même migre — il implémente un Persistent*, ou c'est le propre wrapper du projet dont les méthodes reflètent ces noms et sont renommées pour correspondre. Le renommage est correct mais à moitié terminé : renommez aussi la déclaration et ses autres appelants, afin que l'appel se résolve. (Les overrides dépréciés sur un implémenteur sont l'étape 5.)

Décidez par le type déclaré du récepteur, jamais par le nom de la méthode — un champ nommé Persistent* peut contenir un autre type. Cela importe surtout quand vous ne pouvez pas compter sur une recompilation rapide et que vous renommez en lisant la source.

Appelants Java. La recompilation ne les signale que si la compilation signale les avertissements de dépréciation javac (-Xlint:deprecation, généralement désactivé). Si ce n'est pas le cas, grep les fichiers .java qui importent la bibliothèque pour les anciens noms et renommez les appels dont le récepteur est un type Persistent*.

Après les renommages, le compilateur peut signaler certains @Suppress("DEPRECATION") comme sans effet — supprimez-les (relisez d'abord la région, au cas où elle couvrirait encore quelque chose d'autre).

5. Implémenteurs personnalisés

Si le projet contient des classes qui implémentent PersistentList / PersistentMap / PersistentSet / PersistentCollection, leurs overrides dépréciés doivent aussi être migrés. Trouvez-les :

grep -rnE --include='*.kt' \
  '(class|object|interface)\s+\w[^:]*:\s*[^{]*\b(PersistentList|PersistentMap|PersistentSet|PersistentCollection)\s*<' .

Sur Windows PowerShell, Select-String est l'équivalent de grep :

Get-ChildItem -Recurse -Filter *.kt |
  Select-String '(class|object|interface)\s+\w[^:]*:\s*[^{]*\b(PersistentList|PersistentMap|PersistentSet|PersistentCollection)\s*<'

(Confirmez qu'une correspondance liste vraiment l'interface comme supertype, et non juste un type de champ ou un argument de type.) Pour chacune, déplacez l'implémentation vers la nouvelle méthode participiale et faites l'override déprécié déléguer à celle-ci :

override fun adding(element: E): MyList<E> = /* real implementation */

@Suppress("OVERRIDE_DEPRECATION")
override fun add(element: E): MyList<E> = adding(element)

Si les méthodes participiales s'appellent les unes les autres, routez ces appels par les homologues participiaux, pas les noms dépréciés. (Ajoutez "DEPRECATION" à la suppression uniquement quand un corps d'override appelle encore un membre déprécié.) Faire cela maintenant importe : à 0.6.0, les anciens noms deviennent des erreurs de compilation, et à 0.7.0, ils sont supprimés. Consultez 0.5.0-MIGRATION.md pour les conseils d'implémenteur en amont.

6. Exécutez les étapes de suivi documentées

Faites-le après les renommages compilés proprement, afin que si vous manquez de temps le travail de call-site soit déjà fait. Certains projets documentent les étapes à exécuter après un changement de dépendance que le compilateur ne surface pas — le plus souvent la régénération des métadonnées de vérification des dépendances (les hashes gradle/verification-metadata.xml de l'étape 3). Généralement, la correction d'entrée unique de l'étape 3 est tout ce dont vous avez besoin ; ne basculez vers la procédure de régénération complète documentée du projet (dans README.md / CONTRIBUTING.md / CLAUDE.md / AGENTS.md) que si cette seule entrée n'est pas suffisante. Exécutez-la une seule fois — un --write-verification-metadata / "resolve all dependencies" complet repasse sur tout le graphe et est lent, et la répétition change rarement l'issue. Puis reconfirmez que la compilation est propre.

Référence des renommages

  • PersistentCollectionaddadding, addAlladdingAll, removeremoving, removeAllremovingAll, retainAllretainingAll, clearcleared
  • PersistentList (les ci-dessus, plus) — add(i, e)addingAt, addAll(i, c)addingAllAt, set(i, e)replacingAt, removeAtremovingAt
  • PersistentMapputputting, putAllputtingAll, remove(k)removing, remove(k, v)removing, clearcleared

Les Builders (PersistentList.Builder, etc.) ne sont pas renommés — ils mutent sur place, donc leurs noms impératifs restent.

Liens

Skills similaires