بِسْمِ ٱللَّهِ ٱلرَّحْمَـٰنِ ٱلرَّحِيمِ
Kotlin / Android
Move Kotlin files and folders to another package and rename Kotlin symbols, with Java callers and Android XML kept in step.
Kotlin has two operations. Moves take a file or a folder to another package and rewrite the package line, every import, and the code that used its old package without an import. Rename changes a variable, property, function, class, or member and every reference to it, Java callers included.
The JetBrains Kotlin language server does the semantic work. It is IntelliJ without its window. refac wraps it with planning, verification, an undo log, and an Android layer for the parts the server never touches: the manifest, layouts, navigation graphs, and the implicit R and BuildConfig.
This section answers what you need to set up, how to run a first move, and what a Kotlin command costs.
What you need
| Need | Detail |
|---|---|
| A Gradle project | --project-path is the Gradle root, the folder with settings.gradle or settings.gradle.kts, not a module folder |
| JDK 17 or newer | On your PATH, for the Gradle import that the server runs |
| The Kotlin language server | REFAC_KOTLIN_SERVER names its folder. refac never downloads it and never guesses |
| An Android SDK | Android projects only: ANDROID_HOME or local.properties, as for any Gradle build |
Install the server
refac doctor kotlin prints the exact steps for the build refac was verified against: a download link, a checksum, where to unpack it, and the export line. The shape is this:
curl -LO <download link printed by refac doctor kotlin>
echo "<checksum> <archive>" | sha256sum -c -
mkdir -p ~/.local/share/refac
tar -xzf <archive> -C ~/.local/share/refac
export REFAC_KOTLIN_SERVER=~/.local/share/refac/<unpacked folder>Put the export line in the shell profile of whoever runs refac, an agent's environment included. The folder may be anywhere, but it must hold bin/intellij-server and a build.txt that starts with ILS-. The server is a large download, about 1.2 GB unpacked. When the variable is right, refac doctor kotlin prints [ready] with the build it found, and then you can inshallah start moving files.
A first move
Kotlin changes are made in one call, because every Kotlin command pays the server start (see Cost). Collect the files first:
refac move --project-path /path/to/gradle/root \
--source-path app/src/main/kotlin/com/example/util/Helper.kt \
--source-path app/src/main/kotlin/com/example/util/Format.kt \
--target-path app/src/main/kotlin/com/example/common/Helper.kt \
--target-path app/src/main/kotlin/com/example/common/Format.ktThe package line of both files, every import of them in Kotlin and Java, and the usages that relied on a shared package follow. A list in a file works as well, with --batch moves.json. A folder is one change that already moves all its files in one start, so it can be moved on its own.
After the move, run the project's Gradle build. It should inshallah compile without a single edit by hand, and the // Note: lines of the output name the few places refac does not edit.
Cost
Every Kotlin command starts the language server and imports the Gradle build, however few files it changes.
- First call on a machine: about 44 seconds. The server indexes the JDK and the Kotlin libraries once.
- Later calls: about 24 seconds. refac keeps the index (110 to 160 MB) in
~/.cache/refac, so later starts will inshallah be much faster than the first. - Memory while it runs: 1.3 to 1.8 GB on a small project, more on a big one.
- After the command: nothing stays running, the Gradle daemon included.
That is why a single Kotlin move or rename is refused by default and why you put every change into one call. The options, and what to do when you have to run single changes, are on Cost and troubleshooting.
What is covered
- Moves of
.ktfiles and folders: the package line, imports, usages, Java callers, and Android XML. See Moves. - Rename of any Kotlin symbol, with the proof that the program keeps its meaning. See Rename.
- Android and Kotlin Multiplatform projects. See Android and Multiplatform.
What is refused
Each of these stops the command before anything is changed:
- A
.javafile, or a folder that contains Java sources. - A move between Gradle modules or between source sets, such as
src/maintosrc/test. - A source or target that is not inside a source root, or that is a source root itself.
- In a Multiplatform build, a file that declares
expectoractual.