Package org.codehaus.groovy.ast.query

# Class AstQuery<T extends ASTNode>

java.lang.Object
org.codehaus.groovy.ast.query.AstQuery<T>

Type Parameters:
  `T` - the node type produced by this query

public final class AstQuery<T extends ASTNode> extends Object
A small, read-only, fluent query API over a Groovy AST subtree.

An `AstQuery` selects descendant nodes of a root, optionally filtered by type and by an arbitrary predicate, and exposes terminal operations that collect or test the matches. It is a declarative alternative to hand-writing a `ClassCodeVisitorSupport` subclass for the common "find / collect / detect" cases.

     import org.codehaus.groovy.ast.query.AstQuery
     import org.codehaus.groovy.ast.expr.MethodCallExpression
     import org.codehaus.groovy.ast.builder.AstBuilder

     def code = new AstBuilder().buildFromString('foo(); bar()')[0]
     assert AstQuery.from(code).descendants(MethodCallExpression).count() == 2

## Traversal and pruning

By default the traversal descends through closures but does not descend into nested classes, mirroring `ClassCodeVisitorSupport`. Use `notInto(Class[])` to stop descending at a boundary type (for example `ClosureExpression`) and `into(Class[])` to opt back in past a default boundary. Nested classes are currently the only default boundary, so `into(ClassNode.class)` is the only case in which `into(Class[])` has an effect.

## Notes

- The query is read-only; it never mutates the AST.
- Matches are produced in document (pre-)order.
- Instances are immutable and re-runnable: each builder method returns a new query and each terminal performs a fresh traversal, short-circuiting where it can (for example `any()` and `findFirst()`).

Since:
  6.0.0

- ## Method Summary

  Modifier and Type
  Method
  Description
  `AstQuery<T>`
  `andSelf()`
  Includes the root node itself as a candidate (it is excluded by default).
  `boolean`
  `any()`
  `long`
  `count()`
  `AstQuery<ASTNode>`
  `descendants()`
  Selects all descendant nodes regardless of type.
  `final AstQuery<ASTNode>`
  `descendants(Class<? extends ASTNode>... types)`
  Selects descendant nodes that are instances of any of the given types.
  `<U extends ASTNode>
  AstQuery<U>`
  `descendants(Class<U> type)`
  Selects descendant nodes that are instances of the given type.
  `Optional<T>`
  `findFirst()`
  `T`
  `first()`
  `void`
  `forEach(BiConsumer<? super T,AstContext> action)`
  Performs the given action, with enclosing context, for each match in document order.
  `void`
  `forEach(Consumer<? super T> action)`
  Performs the given action for each match in document order.
  `static AstQuery<ASTNode>`
  `from(ASTNode root)`
  Starts a query rooted at the given node.
  `final AstQuery<T>`
  `into(Class<? extends ASTNode>... types)`
  Opts the traversal in to descending past a default boundary.
  `List<T>`
  `list()`
  Collects all matches in document order.
  `boolean`
  `none()`
  `final AstQuery<T>`
  `notInto(Class<? extends ASTNode>... boundary)`
  Stops the traversal from descending into the subtrees rooted at nodes of the given types.
  `Stream<T>`
  `stream()`
  `AstQuery<T>`
  `where(BiPredicate<? super T,AstContext> p)`
  Restricts the selection to nodes satisfying a predicate that also inspects the enclosing `AstContext`.
  `AstQuery<T>`
  `where(Predicate<? super T> p)`
  Restricts the selection to nodes satisfying the predicate.

  ### Methods inherited from class java.lang.Object

  `clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- ## Method Details

  - ### from

    public static AstQuery<ASTNode> from(ASTNode root)
    Starts a query rooted at the given node.
    Parameters:
      `root` - the subtree root to query; must not be `null`
    Returns:
      a query selecting (by default) all descendants of `root`

  - ### descendants

    public AstQuery<ASTNode> descendants()
    Selects all descendant nodes regardless of type.
    Returns:
      a query over every descendant

  - ### descendants

    public <U extends ASTNode> AstQuery<U> descendants(Class<U> type)
    Selects descendant nodes that are instances of the given type.
    Type Parameters:
      `U` - the node type
    Parameters:
      `type` - the node type to match
    Returns:
      a query over descendants of that type

  - ### descendants

    @SafeVarargs public final AstQuery<ASTNode> descendants(Class<? extends ASTNode>... types)
    Selects descendant nodes that are instances of any of the given types.
    Parameters:
      `types` - the node types to match (logical OR)
    Returns:
      a query over descendants matching any type

  - ### andSelf

    public AstQuery<T> andSelf()
    Includes the root node itself as a candidate (it is excluded by default).
    Returns:
      a query that also considers the root

  - ### where

    public AstQuery<T> where(Predicate<? super T> p)
    Restricts the selection to nodes satisfying the predicate. Multiple `where` calls are combined with logical AND.
    Parameters:
      `p` - the predicate (a Groovy `Closure` coerces to this functional type)
    Returns:
      the refined query

  - ### where

    public AstQuery<T> where(BiPredicate<? super T,AstContext> p)
    Restricts the selection to nodes satisfying a predicate that also inspects the enclosing `AstContext`. Combined with logical AND with any other refinements.
    Parameters:
      `p` - the contextual predicate (a two-argument Groovy `Closure` coerces to it)
    Returns:
      the refined query

  - ### notInto

    @SafeVarargs public final AstQuery<T> notInto(Class<? extends ASTNode>... boundary)
    Stops the traversal from descending into the subtrees rooted at nodes of the given types. The boundary nodes themselves are still candidates; only their contents are skipped.
    Parameters:
      `boundary` - the boundary types (for example `ClosureExpression.class`)
    Returns:
      the query with the added boundaries

  - ### into

    @SafeVarargs public final AstQuery<T> into(Class<? extends ASTNode>... types)
    Opts the traversal in to descending past a default boundary. Currently the only default boundary is nested classes, so `into(ClassNode.class)` makes the traversal recurse into inner classes.
    Parameters:
      `types` - the boundary types to descend into
    Returns:
      the query with the boundaries opened

  - ### list

    public List<T> list()
    Collects all matches in document order.
    Returns:
      the matching nodes

  - ### any

    public boolean any()
    Returns:
      `true` if at least one node matches; stops at the first match

  - ### none

    public boolean none()
    Returns:
      `true` if no node matches; stops at the first match

  - ### count

    public long count()
    Returns:
      the number of matching nodes

  - ### findFirst

    public Optional<T> findFirst()
    Returns:
      the first match in document order, if any; stops at the first match

  - ### first

    public T first()
    Returns:
      the first match in document order, or `null`; stops at the first match

  - ### forEach

    public void forEach(Consumer<? super T> action)
    Performs the given action for each match in document order.
    Parameters:
      `action` - the action

  - ### forEach

    public void forEach(BiConsumer<? super T,AstContext> action)
    Performs the given action, with enclosing context, for each match in document order.
    Parameters:
      `action` - the action receiving the node and its `AstContext`

  - ### stream

    public Stream<T> stream()
    Returns:
      a sequential `Stream` of the matches in document order