Module visit

Source
Expand description

§Visiting and Transforming GraphQL ASTs

The graphql_query::visit module contains utilities to traverse and transform GraphQL ASTs. Mainly, this module exposes two traits relevant to this task:

  • The Visitor trait can be used to implement a visitor.
  • The Folder trait can be used to implement a folder to transform an AST.

This works via the VisitNode trait and FoldNode trait that most AST nodes implement and where visiting and folding can start.

Typically, a visitor is used in GraphQL to gain information about the AST and inspect it for certain features. It may also be used to collect information about the AST before it’s transformed in a second folder step, if a single pass over the AST isn’t enough.

In this example we’ll define a visitor that counts all operations in a document:

use graphql_query::{ast::*, visit::*};

#[derive(Default)]
struct CountOperations {
   operations: usize,
}

impl<'a> Visitor<'a> for CountOperations {
    fn enter_fragment(
        &mut self,
        _ctx: &mut (),
        _fragment: &'a FragmentDefinition<'a>,
        _info: &VisitInfo
    ) -> VisitFlow {
        // We can skip over fragment nodes and never traverse its children,
        // since we're only interested in counting operations
        VisitFlow::Skip
    }

    fn enter_operation(
        &mut self,
        _ctx: &mut (),
        operation: &'a OperationDefinition<'a>,
        _info: &VisitInfo
    ) -> VisitFlow {
        self.operations += 1;
        VisitFlow::Next
    }
}

We may then execute this visitor using Document::visit, e.g. document.visit(&ctx, &mut CountOperations::default()).

Of course, it’s often necessary to ensure that while the context is mutated inside the visitor, its results should still later on be made accessible.

More information on the Visitor trait

A folder is very similar but instead receives and returns AST nodes to create a new copy of an AST while transforming it. A simple folder that changes all names to "oomph" may look like such:

use graphql_query::{ast::*, visit::*};

#[derive(Default)]
struct OomphRename {}

impl<'a> SimpleFolder<'a> for OomphRename {
    fn named_type(&mut self, _name: NamedType<'a>) -> NamedType<'a> {
      NamedType { name: "oomph" }
    }
}

Which we may then execute using Document::fold, e.g. document.fold(&ctx, &mut OomphRename::default()).unwrap().

Notably, we’ve used the SimpleFolder trait in this example, since it allows us to write less code than with the Folder trait when a folder is really straightforward.

More information on the Folder trait

Re-exports§

pub use super::Path;
pub use super::PathSegment;
pub use super::VisitInfo;
pub use crate::error::Error;
pub use crate::error::Result;

Structs§

ComposedVisitor
This structure implements the Visitor trait and runs two child Visitors in parallel, executing and calling callbacks on them both.
Path
VisitInfo

Enums§

PathSegment
VisitFlow
A visitor signal that is returned from Visitor callbacks to alter the flow of traversal.

Traits§

FoldDocument
Trait for folding a GraphQL Document AST Node by traversing an operation instead of the entire AST tree. This method alters the traversal of the folder and traverses starting from an operation instead; folding the fragment definitions only as they’re used and refered to using FragmentSpread nodes in the operation.
FoldNode
Trait for folding AST Nodes of a GraphQL language document in depth-first order using a custom folder. This transforms the AST while creating a new copy of it.
Folder
Trait for a folder that carries methods that are called as callback while AST nodes implementing the folder pattern are traversed and edited.
SimpleFolder
This trait is a simplified version of the Folder trait for ease of use.
VisitNode
Trait for visiting AST Nodes of a GraphQL language document in depth-first order using a custom visitor.
Visitor
Trait for a visitor that carries methods that are called as callback while AST nodes implementing the visitor pattern are traversed.