$npx -y skills add Kotlin/kotlin-agent-skills --skill kotlin-tooling-immutable-collections-0-5-x-migrationMigrate Kotlin (and Java) code from kotlinx.collections.immutable 0.3.x / 0.4.x to the latest 0.5.x. The 0.5.x line renames every copy-returning method on PersistentList / PersistentMap / PersistentSet / PersistentCollection to a participial form per KEEP-0459 (add→adding, remove
| 1 | # kotlinx.collections.immutable 0.5.x Migration |
| 2 | |
| 3 | The 0.5.x line renames every copy-returning method on the persistent collections to a |
| 4 | participial form (per [KEEP-0459]) and deprecates the old names at `WARNING` level with a |
| 5 | `ReplaceWith` hint. Migrating is a mechanical, binary-compatible, semantics-preserving |
| 6 | call-site rename — same parameters, order, and return type; only the name changes. |
| 7 | |
| 8 | Drive it from the compiler: bump the version, recompile, and fix each deprecation warning — |
| 9 | the warning names the replacement. Source of truth: [`0.5.0-MIGRATION.md`]. |
| 10 | |
| 11 | ## When it applies |
| 12 | |
| 13 | Check the version the project currently uses: |
| 14 | |
| 15 | - **0.3.x or 0.4.x** (any pre-0.5.0) → run the migration below. |
| 16 | - **On 0.5.x but not the latest** → set the version to the latest 0.5.x and stop. All 0.5.x |
| 17 | releases share the same renames, so a within-line bump adds no new deprecations and needs |
| 18 | no recompile. |
| 19 | - **On the latest 0.5.x, or on 0.6.x and later** → nothing to do. |
| 20 | |
| 21 | ## Migration |
| 22 | |
| 23 | ### 1. Find the build command |
| 24 | |
| 25 | Check `README.md`, `CLAUDE.md`, or `AGENTS.md` for how the project builds; if it isn't |
| 26 | written down, infer it from the build files — Gradle (`./gradlew`), Maven (`mvn`, or the |
| 27 | `./mvnw` wrapper), Bazel |
| 28 | (a `bazel` wrapper), or a custom script. Record the compile command (and the test command). |
| 29 | In a multi-module project you only need the modules that use the library, plus any you |
| 30 | change — not a whole-repo build. |
| 31 | |
| 32 | ### 2. Baseline compile |
| 33 | |
| 34 | Compile on the current version and confirm it's green. If it doesn't build now, you can't |
| 35 | tell post-migration errors from pre-existing ones — get a working compile command first. |
| 36 | |
| 37 | ### 3. Bump to the latest 0.5.x |
| 38 | |
| 39 | Find where the version is pinned — `grep -rn kotlinx-collections-immutable` across the build |
| 40 | files finds it (version catalog, build script, `gradle.properties`, `pom.xml`, …) — and set |
| 41 | it to the latest 0.5.x on [Maven Central] (a `-beta` is fine). If the build pins artifact |
| 42 | hashes (e.g. `gradle/verification-metadata.xml`), update those too — the cheapest fix is to |
| 43 | copy the new artifact's checksum straight from the dependency-verification failure message |
| 44 | and add just that one entry, rather than regenerating the whole metadata file. The bump is |
| 45 | binary-compatible; old code keeps compiling with warnings. (If the dependency fails to |
| 46 | resolve with a Kotlin metadata-version error, the project's Kotlin is too old for the 0.5.x |
| 47 | artifact — bump Kotlin first.) |
| 48 | |
| 49 | ### 4. Recompile and fix the warnings |
| 50 | |
| 51 | Recompile. Each renamed method carries `@Deprecated(WARNING, ReplaceWith(...))`, so the |
| 52 | compiler emits one warning per call site naming the replacement (e.g. *"Use removingAll() |
| 53 | instead"*). Apply that rename. Repeat compile → fix until no `kotlinx.collections.immutable` |
| 54 | deprecation warnings remain. (For multiplatform, one target compile surfaces the shared call |
| 55 | sites. Pre-existing factory deprecations such as `immutableListOf` → `persistentListOf` |
| 56 | appear the same way — apply those too.) A recompile that fails right after the bump is |
| 57 | failing *on these deprecations* (plus, if hashes are pinned, a one-time dependency-verification |
| 58 | error) — keep applying the renames the warnings name; don't re-run dependency-resolution or |
| 59 | metadata-regeneration commands to try to clear it. |
| 60 | |
| 61 | **Trust the compiler — never find/replace by name.** The same method names exist on |
| 62 | `MutableList` / `MutableMap` / `MutableSet` and on the `.Builder` types, which mutate in |
| 63 | place and are *not* deprecated. Only the sites the compiler flags (receiver statically |
| 64 | `Persistent*`) get renamed; if it didn't flag it, leave it. |
| 65 | |
| 66 | **An `Unresolved reference` after a rename means the participial name isn't on that |
| 67 | receiver — you've split a rename.** A rename only compiles if the *declaration* and *every* |
| 68 | call site move together. The library already did that for the kotlinx types, so renaming |
| 69 | their call sites just works — but it doesn't hold for anything else that merely shares the |
| 70 | names. When a renamed call won't resolve, there are two cases: |
| 71 | |
| 72 | - The receiver is unrelated to this library (a `Mutable*`, a `.Builder`, a same-named method |
| 73 | on some other type) — the rename was wrong; revert that site. |