Reference
بِسْمِ ٱللَّهِ ٱلرَّحْمَـٰنِ ٱلرَّحِيمِ
Capabilities & Limits
What refac supports in each language, what a command costs, and where it stops.
This page gives you the whole picture on one screen. The language pages have the details.
What each language supports
| Language | Move file | Move folder | Rename symbol | Done by |
|---|---|---|---|---|
| TypeScript / JavaScript | Yes | Yes | Yes | Oxc parser and the TypeScript resolver via Bun for moves. The TypeScript 7 native language server for rename |
| Kotlin / Android | Yes | Yes | Yes | The JetBrains Kotlin language server, plus refac's own Android XML layer |
| Go | Yes | No | Yes | gopls |
| Rust | Yes, inside its folder | No | Yes | rust-analyzer. move-module moves a whole module and uses the embedded HIR |
| Python | Yes | No | Yes | Rope for moves, with Pyrefly as the fallback. basedpyright for rename |
| Dart | Yes | No | Yes | The Dart SDK analysis server |
| Markdown | Yes | Yes | n/a | Built in with a CommonMark parser. It also follows what other languages moved |
The language of a file comes from its extension, and a single move call may mix languages. A Rust module moves across folders with move-module, which is its own command.
Capabilities for every language
| Capability | Detail |
|---|---|
| Several moves in one call | Repeat the flags, or --batch FILE. Mixed-language calls are grouped and dispatched independently |
| Several renames in one call | rename --batch FILE, one language per batch, all or nothing |
| Preview | --dry-run on move, move-module, and rename |
| Machine-readable output | --json on move, move-module, rename, and doctor |
| Undo | Every write goes through a journal. A failed step puts every file back |
| Nothing stays running | A language server is started for the command and stopped when it ends |
What a command costs
| Language | Time to start | Memory while it runs |
|---|---|---|
| Go | 2 to 8 s | about 165 MB |
| Python | 1 to 2 s | about 160 MB |
| Dart | under 1 s | about 125 MB |
| Rust | 5 to 35 s | about 640 MB, growing with the project |
| Kotlin | about 24 s, 44 s the first time | 1.3 to 1.8 GB |
| TypeScript | its own engine | the helper is held to 4096 MiB (REFAC_TYPESCRIPT_MAX_RSS_MB) |
Measured on a small project, and a bigger project holds more. So put several moves into one move call and several renames of one project into one rename --batch call. A single Kotlin change is refused by default for this reason. See Cost and troubleshooting.
Key limits per language
| Language | Key limit |
|---|---|
| TypeScript / JavaScript | Callers must be in the tsconfig that --project-path points at. At most 30 source files per call, folder contents included. Aliases that are not in compilerOptions.paths and arbitrary path strings cannot be mapped. Project references are rejected. Rename needs a tsconfig that TypeScript 7 accepts, with no baseUrl and no node10 resolution |
| Kotlin / Android | Needs a Gradle project and the Kotlin language server. .java files, folders with Java, and moves between modules or source sets are refused. In a Multiplatform build, files that declare expect or actual are refused. A single change is refused unless --allow-single is given |
| Go | A move to another folder moves the whole package, and partial-package moves are not supported. It needs go.mod |
| Rust | A .rs file can only be renamed inside its folder. A module moves with move-module, which refuses unconventional layouts (inline modules, #[path]) and checks the workspace with Cargo afterwards. Cross-crate moves are not supported |
| Python | Rope does not trace imports through __init__.py re-exports, and namespace packages may see incomplete updates. Rename needs basedpyright, and special methods such as __init__ are refused |
| Dart | It needs dart pub get first. A move that would leave a package: import pointing at a missing file is refused. Folders are not supported |
| Markdown | A folder may hold only Markdown and assets. Wiki-links, MDX imports, front matter, and code blocks are not links to refac. Files ignored by .gitignore are not searched |
General limits
- Existing targets. TypeScript, Kotlin, and Markdown moves, and
move-module, refuse a target that already exists. For the other languages refac makes no such promise, so make sure the target path is free before you move. - What a server cannot see. Names inside strings and comments, reflection, build scripts, ProGuard rules, and generated code are not references. The
// Note:lines list what is likely to need a hand edit, with therg -wcommand that finds it. - Partial results. Each language group is all or nothing. Across groups it is not, so a failure in one group leaves the others moved and the report starts with
// Partly done:. - Platform. Linux. macOS and Windows are not targets.
- Verification. Run your tests and your build after a big change. They should inshallah pass, and
git diffshows exactly what refac wrote.