# `mix ex_ast.search`
[🔗](https://github.com/elixir-vibe/ex_ast/blob/v0.11.0/lib/mix/tasks/ex_ast.search.ex#L1)

Searches for AST patterns in Elixir source files.

## Usage

    mix ex_ast.search 'IO.inspect(_)' [path ...]

## Options

  * `--count` — only print the number of matches
  * `--limit n` — stop after returning this many matches
  * `--allow-broad` — allow unbounded broad searches like `_`
  * `--inside 'pattern'` — only match inside ancestors matching this pattern
  * `--not-inside 'pattern'` — reject matches inside ancestors matching this pattern
  * `--parent 'pattern'` / `--not-parent 'pattern'` — filter by direct semantic parent
  * `--ancestor 'pattern'` / `--not-ancestor 'pattern'` — filter by semantic ancestor
  * `--has-child 'pattern'` / `--not-has-child 'pattern'` — filter by direct semantic child
  * `--contains 'pattern'` / `--not-contains 'pattern'` — filter by semantic descendant
  * `--has-descendant 'pattern'` / `--not-has-descendant 'pattern'` — aliases for contains filters
  * `--has 'pattern'` / `--not-has 'pattern'` — aliases for contains filters
  * `--follows 'pattern'` / `--not-follows 'pattern'` — filter by earlier sibling
  * `--precedes 'pattern'` / `--not-precedes 'pattern'` — filter by later sibling
  * `--immediately-follows 'pattern'` / `--not-immediately-follows 'pattern'` — filter by previous sibling
  * `--immediately-precedes 'pattern'` / `--not-immediately-precedes 'pattern'` — filter by next sibling
  * `--first` / `--not-first`, `--last` / `--not-last`, `--nth n` / `--not-nth n` — filter by sibling position
  * `--comment text` / `--not-comment text` — filter by associated comments
  * `--comment-before text`, `--comment-after text`, `--comment-inside text`, `--comment-inline text` — filter by comment location

  Comment values are substrings by default. Use `/.../` or `~r/.../` for regexes, including flags like `/todo/i`.

## Pattern syntax

Patterns are valid Elixir expressions:

  * Variables (`name`, `expr`) — capture any node
  * `_` or `_name` — wildcard (match, don't capture)
  * Structs/maps — partial match (only listed keys must be present)
  * Pipes are normalized — `data |> Enum.map(f)` matches `Enum.map(data, f)`
  * Everything else — literal match

## Examples

    mix ex_ast.search 'IO.inspect(_)'
    mix ex_ast.search '%Step{id: "subject"}' lib/documents/
    mix ex_ast.search '{:error, reason}' lib/ test/
    mix ex_ast.search --count 'dbg(_)'
    mix ex_ast.search --inside 'def handle_call(_, _, _) do _ end' 'Repo.get!(_)'
    mix ex_ast.search --not-inside 'test _ do _ end' 'IO.inspect(_)'
    mix ex_ast.search 'IO.inspect(_)' --parent 'def _ do ... end'
    mix ex_ast.search 'def name do ... end' --contains 'Repo.transaction(_)' --not-contains 'IO.inspect(...)'
    mix ex_ast.search 'Repo.delete(record)' --follows 'record = Repo.get!(_, _)'
    mix ex_ast.search 'def name do ... end' --comment-inside TODO
    mix ex_ast.search 'def name do ... end' --comment-inside '/TODO|FIXME/'
    mix ex_ast.search '_' lib/ --limit 100

---

*Consult [api-reference.md](api-reference.md) for complete listing*
