# `ExAST.Selector`
[🔗](https://github.com/elixir-vibe/ex_ast/blob/v0.11.0/lib/ex_ast/selector.ex#L50)

CSS-like AST selector builder.

Selectors are built from a starting pattern and relationship steps:

    import ExAST.Selector

    pattern("defmodule _ do ... end")
    |> descendant("def _ do ... end")
    |> child("IO.inspect(_)")

The final step is the selected node. Use `where/2` with predicates such as
`has_child/1`, `has_descendant/1`, `parent/1`, and `ancestor/1` to filter the
selected node without changing it.

    pattern("def _ do ... end")
    |> where(has_descendant("Repo.transaction(_)"))
    |> where(not(has_descendant("IO.inspect(_)")))

`where/2` also accepts quoted boolean predicate expressions, so you can use
`Kernel.not/1` without excluding it from imports:

    pattern("def _ do ... end")
    |> where(not has_descendant("IO.inspect(_)"))

`where/2` supports capture guards using `^` to pin captured values,
allowing runtime checks on matched nodes:

    pattern("Enum.take(_, count)")
    |> where(match?({:-, _, [_]}, ^count))

# `relation`

```elixir
@type relation() :: :self | :child | :descendant
```

# `step`

```elixir
@type step() :: {relation(), ExAST.Pattern.pattern() | [ExAST.Pattern.pattern()]}
```

# `t`

```elixir
@type t() :: %ExAST.Selector{filters: [ExAST.Selector.Predicate.t()], steps: [step()]}
```

# `all`

```elixir
@spec all([ExAST.Selector.Predicate.t()]) :: ExAST.Selector.Predicate.t()
```

Matches when all nested predicates match.

# `ancestor`

```elixir
@spec ancestor(ExAST.Pattern.pattern()) :: ExAST.Selector.Predicate.t()
```

Builds or applies a semantic ancestor predicate.

# `ancestor`

```elixir
@spec ancestor(t(), ExAST.Pattern.pattern()) :: t()
```

# `any`

```elixir
@spec any([ExAST.Selector.Predicate.t()]) :: ExAST.Selector.Predicate.t()
```

Matches when any nested predicate matches.

# `child`

```elixir
@spec child(t(), ExAST.Pattern.pattern() | [ExAST.Pattern.pattern()]) :: t()
```

Selects direct semantic children matching `pattern`.

# `comment`

```elixir
@spec comment(String.t() | Regex.t() | ExAST.Selector.CommentMatcher.t()) ::
  ExAST.Selector.Predicate.t()
```

Matches comments associated with the selected node.

# `comment_after`

```elixir
@spec comment_after(String.t() | Regex.t() | ExAST.Selector.CommentMatcher.t()) ::
  ExAST.Selector.Predicate.t()
```

Matches comments immediately after the selected node.

# `comment_before`

```elixir
@spec comment_before(String.t() | Regex.t() | ExAST.Selector.CommentMatcher.t()) ::
  ExAST.Selector.Predicate.t()
```

Matches comments immediately before the selected node.

# `comment_inline`

```elixir
@spec comment_inline(String.t() | Regex.t() | ExAST.Selector.CommentMatcher.t()) ::
  ExAST.Selector.Predicate.t()
```

Matches inline comments on the selected node start line.

# `comment_inside`

```elixir
@spec comment_inside(String.t() | Regex.t() | ExAST.Selector.CommentMatcher.t()) ::
  ExAST.Selector.Predicate.t()
```

Matches comments inside the selected node range.

# `contains`

```elixir
@spec contains(ExAST.Pattern.pattern()) :: ExAST.Selector.Predicate.t()
```

SQL-like alias for `has_descendant/1` and `has_descendant/2`.

# `contains`

```elixir
@spec contains(t(), ExAST.Pattern.pattern()) :: t()
```

# `descendant`

```elixir
@spec descendant(t(), ExAST.Pattern.pattern() | [ExAST.Pattern.pattern()]) :: t()
```

Selects semantic descendants matching `pattern`.

# `exact`

```elixir
@spec exact(
  String.t(),
  keyword()
) :: ExAST.Selector.CommentMatcher.t()
```

Builds an exact comment matcher.

# `find`

```elixir
@spec find(t(), ExAST.Pattern.pattern() | [ExAST.Pattern.pattern()]) :: t()
```

SQL-like alias for `descendant/2`.

# `find_all`

```elixir
@spec find_all(String.t() | Macro.t() | Sourceror.Zipper.t(), t(), keyword()) :: [
  map()
]
```

Finds selector matches in source text, AST, or a Sourceror zipper.

# `find_child`

```elixir
@spec find_child(t(), ExAST.Pattern.pattern() | [ExAST.Pattern.pattern()]) :: t()
```

SQL-like alias for `child/2`.

# `first`

```elixir
@spec first() :: ExAST.Selector.Predicate.t()
```

Matches the first semantic child in its parent.

# `follows`

```elixir
@spec follows(ExAST.Pattern.pattern()) :: ExAST.Selector.Predicate.t()
```

Matches when a previous sibling matches `pattern`.

# `from`

```elixir
@spec from(ExAST.Pattern.pattern() | [ExAST.Pattern.pattern()]) :: t()
```

SQL-like alias for `pattern/1`.

# `has`

```elixir
@spec has(ExAST.Pattern.pattern()) :: ExAST.Selector.Predicate.t()
```

Alias for `has_descendant/1` and `has_descendant/2`.

# `has`

```elixir
@spec has(t(), ExAST.Pattern.pattern()) :: t()
```

# `has_child`

```elixir
@spec has_child(ExAST.Pattern.pattern()) :: ExAST.Selector.Predicate.t()
```

Builds or applies a direct semantic child predicate.

# `has_child`

```elixir
@spec has_child(t(), ExAST.Pattern.pattern()) :: t()
```

# `has_descendant`

```elixir
@spec has_descendant(ExAST.Pattern.pattern()) :: ExAST.Selector.Predicate.t()
```

Builds or applies a semantic descendant predicate.

# `has_descendant`

```elixir
@spec has_descendant(t(), ExAST.Pattern.pattern()) :: t()
```

# `immediately_follows`

```elixir
@spec immediately_follows(ExAST.Pattern.pattern()) :: ExAST.Selector.Predicate.t()
```

Matches when the immediately previous sibling matches `pattern`.

# `immediately_precedes`

```elixir
@spec immediately_precedes(ExAST.Pattern.pattern()) :: ExAST.Selector.Predicate.t()
```

Matches when the immediately following sibling matches `pattern`.

# `inside`

```elixir
@spec inside(ExAST.Pattern.pattern()) :: ExAST.Selector.Predicate.t()
```

SQL-like alias for `ancestor/1` and `ancestor/2`.

# `inside`

```elixir
@spec inside(t(), ExAST.Pattern.pattern()) :: t()
```

# `last`

```elixir
@spec last() :: ExAST.Selector.Predicate.t()
```

Matches the last semantic child in its parent.

# `match?`

```elixir
@spec match?(String.t() | Macro.t() | Sourceror.Zipper.t(), t(), keyword()) ::
  boolean()
```

Returns true when the selector matches at least once.

# `not`

```elixir
@spec not ExAST.Selector.Predicate.t() :: ExAST.Selector.Predicate.t()
```

Negates a predicate for use with `where/2`.

# `nth`

```elixir
@spec nth(pos_integer()) :: ExAST.Selector.Predicate.t()
```

Matches the nth semantic child in its parent, using 1-based indexing.

# `parent`

```elixir
@spec parent(ExAST.Pattern.pattern()) :: ExAST.Selector.Predicate.t()
```

Builds or applies a direct semantic parent predicate.

# `parent`

```elixir
@spec parent(t(), ExAST.Pattern.pattern()) :: t()
```

# `pattern`

```elixir
@spec pattern(ExAST.Pattern.pattern() | [ExAST.Pattern.pattern()]) :: t()
```

Starts a selector at `pattern`.

# `precedes`

```elixir
@spec precedes(ExAST.Pattern.pattern()) :: ExAST.Selector.Predicate.t()
```

Matches when a following sibling matches `pattern`.

# `prefix`

```elixir
@spec prefix(
  String.t(),
  keyword()
) :: ExAST.Selector.CommentMatcher.t()
```

Builds a comment prefix matcher.

# `requires_comments?`

```elixir
@spec requires_comments?(t()) :: boolean()
```

Returns true when matching this selector depends on comments.

# `requires_source?`

```elixir
@spec requires_source?(t()) :: boolean()
```

Returns true when matching this selector requires source text.

# `selector`

```elixir
@spec selector(ExAST.Pattern.pattern() | [ExAST.Pattern.pattern()]) :: t()
```

Alias for `pattern/1`.

# `suffix`

```elixir
@spec suffix(
  String.t(),
  keyword()
) :: ExAST.Selector.CommentMatcher.t()
```

Builds a comment suffix matcher.

# `text`

```elixir
@spec text(
  String.t(),
  keyword()
) :: ExAST.Selector.CommentMatcher.t()
```

Builds a substring comment matcher.

# `where`
*macro* 

Adds a predicate filter without changing the selected node.

---

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