Skip to content

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

Migrate 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,

From plugin
kotlin-agent-skills
1k10 skills
Install
$ npx -y skills add kotlin/kotlin-agent-skills --skill kotlin-tooling-immutable-collections-0-5-x-migration --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/kotlin-tooling-immutable-collections-0-5-x-migration

Context preview

The summary Claude sees to decide when to auto-load this skill.

Migrate 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,

SKILL.md

kotlin-tooling-immutable-collections-0-5-x-migration.SKILL.md
name: kotlin-tooling-immutable-collections-0-5-x-migration
description: >
  Migrate 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, removeAt→removingAt, set→replacingAt, put→putting, clear→cleared, …) and
  deprecates the old names (WARNING, with ReplaceWith). Driven by the compiler: bump the
  version, recompile, and apply the rename each deprecation warning names. Use when the user
  mentions kotlinx.collections.immutable 0.5.x, PersistentList migration, "Use adding()
  instead", KEEP-0459, or sees deprecation warnings from kotlinx.collections.immutable.
license: Apache-2.0
metadata:
  author: JetBrains
  version: "2.4.0"

kotlinx.collections.immutable 0.5.x Migration

The 0.5.x line renames every copy-returning method on the persistent collections to a participial form (per [KEEP-0459]) and deprecates the old names at `WARNING` level with a `ReplaceWith` hint. Migrating is a mechanical, binary-compatible, semantics-preserving call-site rename — same parameters, order, and return type; only the name changes.

Drive it from the compiler: bump the version, recompile, and fix each deprecation warning — the warning names the replacement. Source of truth: [`0.5.0-MIGRATION.md`].

When it applies

Check the version the project currently uses:

  • **0.3.x or 0.4.x** (any pre-0.5.0) → run the migration below.
  • **On 0.5.x but not the latest** → set the version to the latest 0.5.x and stop. All 0.5.x

releases share the same renames, so a within-line bump adds no new deprecations and needs no recompile.

  • **On the latest 0.5.x, or on 0.6.x and later** → nothing to do.

Migration

1. Find the build command

Check `README.md`, `CLAUDE.md`, or `AGENTS.md` for how the project builds; if it isn't written down, infer it from the build files — Gradle (`./gradlew`), Maven (`mvn`, or the `./mvnw` wrapper), Bazel (a `bazel` wrapper), or a custom script. Record the compile command (and the test command). In a multi-module project you only need the modules that use the library, plus any you change — not a whole-repo build.

2. Baseline compile

Compile on the current version and confirm it's green. If it doesn't build now, you can't tell post-migration errors from pre-existing ones — get a working compile command first.

3. Bump to the latest 0.5.x

Find where the version is pinned — `grep -rn kotlinx-collections-immutable` across the build files finds it (version catalog, build script, `gradle.properties`, `pom.xml`, …) — and set it to the latest 0.5.x on [Maven Central] (a `-beta` is fine). If the build pins artifact hashes (e.g. `gradle/verification-metadata.xml`), update those too — the cheapest fix is to copy the new artifact's checksum straight from the dependency-verification failure message and add just that one entry, rather than regenerating the whole metadata file. The bump is binary-compatible; old code keeps compiling with warnings. (If the dependency fails to resolve with a Kotlin metadata-version error, the project's Kotlin is too old for the 0.5.x artifact — bump Kotlin first.)

4. Recompile and fix the warnings

Recompile. Each renamed method carries `@Deprecated(WARNING, ReplaceWith(...))`, so the compiler emits one warning per call site naming the replacement (e.g. *"Use removingAll() instead"*). Apply that rename. Repeat compile → fix until no `kotlinx.collections.immutable` deprecation warnings remain. (For multiplatform, one target compile surfaces the shared call sites. Pre-existing factory deprecations such as `immutableListOf` → `persistentListOf` appear the same way — apply those too.) A recompile that fails right after the bump is failing *on these deprecations* (plus, if hashes are pinned, a one-time dependency-verification error) — keep applying the renames the warnings name; don't re-run dependency-resolution or metadata-regeneration commands to try to clear it.

**Trust the compiler — never find/replace by name.** The same method names exist on `MutableList` / `MutableMap` / `MutableSet` and on the `.Builder` types, which mutate in place and are *not* deprecated. Only the sites the compiler flags (receiver statically `Persistent*`) get renamed; if it didn't flag it, leave it.

**An `Unresolved reference` after a rename means the participial name isn't on that receiver — you've split a rename.** A rename only compiles if the *declaration* and *every* call site move together. The library already did that for the kotlinx types, so renaming their call sites just works — but it doesn't hold for anything else that merely shares the names. When a renamed call won't resolve, there are two cases:

  • The receiver is unrelated to this library (a `Mutable*`, a `.Builder`, a same-named method

on some other type) — the rename was wrong; revert that site.

  • The receiver is a project type the codebase is itself migrating — it implements a

`Persistent*`, or it's the project's own wrapper whose methods echo these names and get renamed to match. The rename is right but *half-done*: rename the declaration and its other callers too, so the call resolves. (Deprecated overrides on an implementer are step 5.)

Decide by the receiver's *declared* type, never the method name — a `Persistent*`-named field may hold another type. This matters most when you can't lean on a fast recompile and are renaming from reading the source.

**Java callers.** The recompile flags them only if the build reports javac deprecation warnings (`-Xlint:deprecation`, usually off). If it doesn't, grep the `.java` files that import the library for the old names and rename the calls whose receiver is a `Persistent*` type.

After the renames, the compiler may report some `@Suppress("DEPRECATION")` as having no effect — remove those (re-read the region first, in case

Read more
Ships withkotlin-agent-skills

A collection of AI agent skills useful for projects using the Kotlin language. Skills are following the Agent Skills standard, see agentskills.io for more information.

Get the whole plugin, auto-invoked

Other skills on kotlin-agent-skills.