Thin wrapper around Igniter for project-wide write ops.
All cross-file write ops in adze — rename, extract!'s caller
rewriting (Session 6.5), find-callers (Session 7) — funnel through
this module so the Igniter-shaped plumbing (build the rewrite, run
the op, extract per-file diffs, write changes) lives in exactly one
place.
Lifecycle
iex> {:ok, rewrite} = Adze.ProjectRewrite.new(mix_root: ".")
iex> {:ok, rewrite, _report} =
...> Adze.ProjectRewrite.rename_module(rewrite, MyApp.Old, MyApp.New)
iex> {:ok, result} = Adze.ProjectRewrite.result(rewrite)
iex> Adze.ProjectRewrite.write!(rewrite)result/1 is dry-run shaped; it inspects the Igniter without
touching disk. write!/1 flushes the same Igniter to the filesystem.
Working directory
Igniter is built around the assumption that the current working
directory is the project root — Igniter.new/0 reads .igniter.exs
and the dot formatter from cwd; prepare_for_write/1 walks
relative paths. The Adze.ProjectRewrite struct carries the project
root so every operation can cd into it before delegating to
Igniter and restore the previous cwd afterwards. Callers already
in the right cwd (e.g. the mix adze task) pay no cost — the
wrapper short-circuits when root == File.cwd!().
Test mode
Adze.ProjectRewrite.new(files: %{"lib/foo.ex" => "..."})builds an in-memory test Igniter backed by
Igniter.Test.test_project/1. No files are read from disk;
write!/1 is unsupported (raises). Used by the tests under
test/project_rewrite_test.exs and test/rename_test.exs.
Summary
Functions
Add a brand-new file to the project. Wraps
Igniter.create_new_file/4 so the eventual write!/1 writes it
alongside any other rewrites.
Build a ProjectRewrite rooted at mix_root: (defaults to the
current directory). When files: is supplied, returns an in-memory
test rewrite instead — see the moduledoc.
Replace the content of an existing tracked source. Used by
Adze.Extract to inject its in-file rewrite (cut + caller fix-up +
alias insert) into the project before the cross-file pass runs.
Rewrite call sites of {old_module, old_function} to
{new_module, new_function} across the project. Wraps
Igniter.Refactors.Rename.rename_function/4.
Rename a module globally across the project. Wraps
Igniter.Refactors.Rename.rename_module/3 and adds the adze-specific
follow-ups documented below.
Extract a dry-run-shaped result from the rewrite without writing.
Flush the rewrite to disk. Refuses to write when the rewrite is in test mode or carries unresolved issues.
Types
Functions
Add a brand-new file to the project. Wraps
Igniter.create_new_file/4 so the eventual write!/1 writes it
alongside any other rewrites.
Build a ProjectRewrite rooted at mix_root: (defaults to the
current directory). When files: is supplied, returns an in-memory
test rewrite instead — see the moduledoc.
Replace the content of an existing tracked source. Used by
Adze.Extract to inject its in-file rewrite (cut + caller fix-up +
alias insert) into the project before the cross-file pass runs.
Rewrite call sites of {old_module, old_function} to
{new_module, new_function} across the project. Wraps
Igniter.Refactors.Rename.rename_function/4.
Pass arity: n (or a list) to narrow to a specific arity; defaults
to :any. When the function definition has already been removed
from old_module (e.g. by Adze.Extract cutting it before this
runs), Igniter's def-move step is a no-op and only the call-site
rewrites take effect.
@spec rename_module(t(), module(), module()) :: {:ok, t(), rename_report()}
Rename a module globally across the project. Wraps
Igniter.Refactors.Rename.rename_module/3 and adds the adze-specific
follow-ups documented below.
Returns {:ok, rewrite, report} where report describes the
short-ref fix-up:
fixed_refs— bareOldShort.fun(...)AST nodes that Igniter's same-namespace pass left in place and adze patched on the caller's behalf.surviving_refs— bare-short references the fix-up could not safely rewrite (no qualifying non-as:alias declaration in pre-rewrite content). Callers likeAdze.Renamesurface these as a warning and refuse to write withoutforce: true.
Follow-up work performed
- Test-file move. Igniter rewrites the test module's
defmodulebut doesn't move its file. We find the rewritten test source and schedule a move to its canonical-for-new-name path so the module name and file path stay in sync. - Short-ref fix-up. Igniter's same-namespace rename has an
upstream bug — the string-substitution pass rewrites the alias
declaration before the AST pass runs, so bare
OldShort.fun(...)call sites are no longer resolvable to the old aliases list and get left un-rewritten. Adze patches them itself in files that had a non-as:alias to the renamed module in their pre-rewrite content. Files without that evidence get left alone and reported insurviving_refs.
Extract a dry-run-shaped result from the rewrite without writing.
diffs keys are file paths; values are plain-text unified-ish diffs
rendered by Rewrite (no ANSI color). moves keys are pre-move
paths, values are post-move paths. Errors/warnings are surfaced
separately so the caller can decide whether to refuse to write.
@spec write!(t()) :: :ok
Flush the rewrite to disk. Refuses to write when the rewrite is in test mode or carries unresolved issues.