Igniter.Code.Pattern (igniter v0.8.0)
View SourcePattern-based AST navigation and rewriting powered by ExAST.
Requires {:ex_ast, "~> 0.5"} (included as a dependency of Igniter).
Pattern syntax
Patterns are valid Elixir expressions:
| Syntax | Meaning |
|---|---|
_ or _name | Wildcard — matches any node, not captured |
name, expr | Capture — matches any node, bound by name |
... | Ellipsis — matches zero or more nodes |
| Everything else | Literal — must match exactly |
Structs and maps match partially, pipes are normalized.
Examples
# Move to a node matching a pattern
{:ok, zipper} = Pattern.move_to(zipper, "Repo.get!(_, _)")
# Ellipsis — match any arity
{:ok, zipper} = Pattern.move_to(zipper, "Logger.info(...)")
# Check if current node matches
Pattern.matches?(zipper, "use GenServer")
# Find all matching nodes
zippers = Pattern.find_all(zipper, "Repo.get!(...)")
# Replace with captures
{:ok, zipper} = Pattern.replace(zipper,
"Enum.map(list, f)", "Enum.flat_map(list, f)")
# Replace all occurrences
{:ok, zipper} = Pattern.replace_all(zipper,
"Logger.debug(msg, ...)", "Logger.warning(msg, ...)")
# Context filters
{:ok, zipper} = Pattern.move_to(zipper,
"Repo.get!(...)", not_inside: "test _ do _ end")
# Inside update_elixir_file
Igniter.update_elixir_file(igniter, path, fn zipper ->
Pattern.replace_all(zipper,
"Enum.map(list, f)", "Enum.flat_map(list, f)")
end)
# Project-level: replace across all matching files
Pattern.replace_in_all_files(igniter,
"Logger.debug(msg, ...)", "Logger.warning(msg, ...)")
# ~p sigil for compile-time pattern parsing
import Igniter.Code.Pattern
Pattern.find_all(zipper, ~p"Repo.get!(...)")
Summary
Functions
Returns a list of zippers, one for each node matching pattern.
Returns true if the current node matches the pattern.
Moves to the first node matching pattern.
Replaces the first node matching pattern with replacement.
Replaces all nodes matching pattern with replacement.
Replaces all nodes matching pattern with replacement across all
Elixir files in the project.
Replaces all nodes matching pattern with replacement in a single file.
Parses a pattern string into AST at compile time.
Types
Functions
@spec find_all(Sourceror.Zipper.t(), pattern(), keyword()) :: [Sourceror.Zipper.t()]
Returns a list of zippers, one for each node matching pattern.
Options
:inside— only match inside ancestors matching this pattern:not_inside— skip matches inside ancestors matching this pattern
@spec matches?(Sourceror.Zipper.t(), pattern()) :: boolean()
Returns true if the current node matches the pattern.
Useful as a predicate inside Igniter.Code.Common.move_to/2,
find_all_matching_modules, or similar callbacks.
Examples
Igniter.Code.Common.move_to(zipper, fn zipper ->
Pattern.matches?(zipper, "use GenServer")
end)
@spec move_to(Sourceror.Zipper.t(), pattern(), keyword()) :: {:ok, Sourceror.Zipper.t()} | :error
Moves to the first node matching pattern.
Returns {:ok, zipper} positioned at the matched node, or :error.
Options
:inside— only match inside ancestors matching this pattern:not_inside— skip matches inside ancestors matching this pattern
@spec replace(Sourceror.Zipper.t(), pattern(), pattern(), keyword()) :: {:ok, Sourceror.Zipper.t()} | :error
Replaces the first node matching pattern with replacement.
Returns {:ok, zipper} with the modified tree, or :error if
no match is found.
Options
:inside— only match inside ancestors matching this pattern:not_inside— skip matches inside ancestors matching this pattern
@spec replace_all(Sourceror.Zipper.t(), pattern(), pattern(), keyword()) :: {:ok, Sourceror.Zipper.t()} | :error
Replaces all nodes matching pattern with replacement.
Returns {:ok, zipper} with the modified tree. If no matches
are found, returns the zipper unchanged.
Options
:inside— only match inside ancestors matching this pattern:not_inside— skip matches inside ancestors matching this pattern
Replaces all nodes matching pattern with replacement across all
Elixir files in the project.
Options
:inside— only match inside ancestors matching this pattern:not_inside— skip matches inside ancestors matching this pattern
Replaces all nodes matching pattern with replacement in a single file.
Wraps Igniter.update_elixir_file/3 with pattern-based replacement.
Options
:inside— only match inside ancestors matching this pattern:not_inside— skip matches inside ancestors matching this pattern
Parses a pattern string into AST at compile time.
Avoids runtime string parsing. The result can be passed to any function in this module.
Examples
import Igniter.Code.Pattern
Pattern.find_all(zipper, ~p"IO.inspect(...)")
Pattern.replace_all(zipper, ~p"dbg(expr)", ~p"expr")