Adze.Rename (Adze v0.1.0)

Copy Markdown View Source

rename / rename! — globally rename a module across the project.

Wraps Igniter.Refactors.Rename.rename_module/3 via Adze.ProjectRewrite. Updates defmodule, every alias / use / import / require, all call sites, the corresponding test module (if any), and string literals mentioning the module. The module's file is moved to its canonical location (derived from the new name).

CLI

mix adze rename  --from MyApp.Old --to MyApp.New
mix adze rename! --from MyApp.Old --to MyApp.New

Dry-run by default: prints a diff for every touched file. rename! also writes.

Programmatic

Adze.Rename.rename(from: "MyApp.Old", to: "MyApp.New")
#=> {:ok, %{diffs: %{path => diff}, moves: %{old_path => new_path},
#          warnings: [...], notices: [...]}}

Adze.Rename.rename!(from: "MyApp.Old", to: "MyApp.New")

Both accept mix_root: (defaults to the current directory) and files: for in-memory test fixtures (delegates to Adze.ProjectRewrite.new/1).

Short-ref fix-up

When Igniter's same-namespace rename leaves bare OldShort.fun(...) call sites un-rewritten (an upstream bug — string substitution rewrites the alias declaration before the AST pass runs, so bare refs no longer resolve back to the old aliases list), adze patches them itself in files that had a non-as: alias to the renamed module. Patched locations come back as {:rewritten_short_refs, refs} in notices:. Locations that couldn't be safely patched (no qualifying alias declaration in pre-rewrite content) come back as {:surviving_references, refs} in warnings:, and rename!/1 refuses to write unless force: true.

Limitations (inherited from Igniter)

  • Dynamic refs (apply/3, Module.concat/2 with variables) are not rewritten.
  • alias Foo.Old, as: B keeps the as: binding; only the alias declaration is updated. B.* call sites are correct since they resolve through as:.
  • String-literal substitution is a plain substring replace over raw file content — it also rewrites occurrences inside comments and unrelated strings. Grep after.

Summary

Types

opts()

@type opts() :: [
  from: String.t() | module(),
  to: String.t() | module(),
  mix_root: Path.t(),
  files: %{required(Path.t()) => String.t()},
  app_name: atom(),
  force: boolean()
]

result()

@type result() :: %{
  from: module(),
  to: module(),
  diffs: %{required(Path.t()) => String.t()},
  moves: %{required(Path.t()) => Path.t()},
  warnings: list(),
  notices: list()
}

Functions

rename(opts)

@spec rename(opts()) :: {:ok, result()} | {:error, term()}

rename!(opts)

@spec rename!(opts()) :: {:ok, result()} | {:error, term()}