Commit graph

5 commits

Author SHA1 Message Date
1ddf79b508
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.
2026-09-15 19:48:18 +02:00
b1af375763
feat: tsconfig compilerOptions.paths — aliased bare specifiers join the graph and follow moves
- index/tsconfig: JSONC sanitize (comments, trailing commas), baseUrl +
  star/exact path keys, first candidate only, longest-prefix wins; invalid
  or missing tsconfig silently means no aliases
- resolution pass: '.'-prefixed specifiers resolve relatively as before,
  bare ones go through the alias table and join the importer graph
- planner: remap keeps the alias shape while the moved file stays inside
  the mapped tree (morphological, since destinations do not exist yet),
  exact keys keep meaning only while still resolving to the target;
  otherwise the previous relative rewrite applies unchanged
- resolve_base extracted from resolve_module (shared extension/index
  guessing); MODULE_EXTS is the exact inverse for remapping
- e2e: @utils/str.ts -> @utils/text.ts inside alias, -> ./core/text.ts
  when leaving it, @cfg falls back to ./settings; check passes on aliases
2026-09-15 19:17:06 +02:00
7c8498bc2a
feat(ts): ts/unused-import rule — whole-statement delete of dead TS/JS imports
- binds names via tree-sitter (default, namespace, named + alias, type-only),
  keeps a statement when ANY bound name occurs outside it (word scan over
  comments/strings included): under-delete is the safe direction, mirroring
  the Java rule's asymmetry
- ESM caveat encoded in the policy: mixed live/dead statements are not
  touched — removing a specifier would still drop the module's side effects
- side-effect imports and 'export .. from' re-exports are never candidates
- parser/ts became a folder (mod/extract/unused_imports) to keep the
  4-entries-per-module rule; word_occurs shared via crate::parser
- java/rules/unused_imports now reuses the shared word scanner (DRY)
2026-09-15 17:07:46 +02:00
4f91cf4387
test: force-track the node_modules fixture file the fixture .gitignore hid from git; run all test binaries with --no-fail-fast 2026-09-15 16:14:42 +02:00
55670030c3
feat: MVP — move files, rewrite imports, atomically
- core: gitignore-aware index (ignore crate), forward/reverse import graph,
  relative-specifier math, pure-data move plans
- apply: rewrite-first + rename-last with fsync, temp+rename, full rollback
  (incl. stale-plan detection before any write); unified diff for dry-run
- cli: mv + check commands, human output, --json envelope with stable error
  codes (SOURCE_NOT_FOUND, TARGET_EXISTS, ...) and hints; exit codes 0/1/2
- parser/core split into submodules to keep files <=250 lines
- tests: 37 unit + 10 e2e + 2 doctests; fixtures tests/typescript/{basic,normal,complex}
- docs: SKILL.md synced (no --force in Phase 1), EXAMPLES.md
- plan: AI/agent support done; Phase 1.5 = Java niche
2026-09-10 11:41:03 +02:00