feat: warn about non-import references to moved files

The import graph only rewrites import/export-from/require. Files are
also named from markdown links, package.json fields, jest.mock strings
and tsconfig file lists, and a move that dangles those must not pass
silently. mv now scans text formats plus source strings for the moved
paths, module names and old specifier forms (word-boundary matched,
lockfiles/hidden dirs skipped) and reports each occurrence once per
line on stderr and as non_import_refs[] in --json (dry-run included).
References are never edited; exit codes are unchanged.

Also moves normalize_scope into Index (its only consumer) and the
Change/ChangedFile JSON structs into output where they are built, to
stay inside the 250-line-per-file budget.
This commit is contained in:
loki5512344 2026-09-15 19:48:18 +02:00
parent b1af375763
commit 1ddf79b508
Signed by: boba
GPG key ID: 253067914055423B
21 changed files with 557 additions and 81 deletions

View file

@ -165,15 +165,13 @@ $ jmove mv lib/sum.ts utils/sum.ts --dry-run --json
"would_move": "lib/sum.ts",
"target": "utils/sum.ts",
"would_update": 1,
"affected_files": [
"app.ts"
],
"affected_files": ["app.ts"],
"would_move_via": "fs",
"diff": "--- app.ts\n+++ app.ts\n@@ -1,4 +1,4 @@\n-import { sum } from \"./lib/sum\";\n+import { sum } from \"./utils/sum\";\n..."
}
```
Review `affected_files`; abort and ask the user if the blast radius is
Review `affected_files` and `non_import_refs`; abort and ask the user if the blast radius is
unexpected.
### 2. Apply
@ -188,25 +186,26 @@ $ jmove mv lib/sum.ts utils/sum.ts --json
"changed_files": [
{
"path": "app.ts",
"changes": [
{
"line": 1,
"old": "./lib/sum",
"new": "./utils/sum"
}
]
"changes": [{ "line": 1, "old": "./lib/sum", "new": "./utils/sum" }]
}
],
"moved": 1,
"updated_imports": 1,
"moved_via": "fs"
"moved_via": "fs",
"non_import_refs": [
{ "file": "README.md", "line": 1, "token": "lib/sum.ts",
"kind": "path", "text": "Use [sum](./lib/sum.ts) via `lib/sum`." }
]
}
```
`changed_files[].changes[]` lists every rewritten specifier with its
1-based line; `moved` and `updated_imports` are the counters,
`moved_via` tells whether the rename went through git (`"git"`, staged)
or the plain filesystem (`"fs"`).
or the plain filesystem (`"fs"`). `non_import_refs` (omitted when empty,
also present in dry-run) names references the import graph cannot see —
markdown links, `package.json` fields, `jest.mock` strings. jmove never
edits those; report them to the user.
### 3. Verify

View file

@ -47,6 +47,13 @@ while the new file stays inside the mapped tree and falls back to a
relative specifier otherwise. `extends` chains and 2nd+ candidate lists
are not followed (v1); an invalid tsconfig silently means "no aliases".
Non-import references: before writing, `mv` scans markdown/config/text
files and source strings for mentions of moved paths and old specifiers.
Such references are never rewritten (each format has its own semantics);
they are reported as `non_import_refs[]` (`file`, `line`, `token`, `kind`,
`text`) in `mv --json` — dry-run included — and on stderr for humans.
Exit code never changes; surface the list to the user.
### check — find broken imports and Java layout errors
```