Hot Chocolate creates an abstract syntax tree for every incoming request. The execution engine evaluates this syntax tree in many different ways. Validation is a good example. Every incoming request has to be validated. The execution engine has to be sure that the semantic of the requested document is correct. A set of rules is applied to the syntax tree, to find potential semantic flaws.
Usually, you do not have to access the AST directly. The AST only becomes significant, when you want to change execution behavior based on the structure of the query. For example features like Filtering, Sorting, or Selection, analyze the incoming query and generate expressions based on it.
Hot Chocolate provides you with different APIs that support you to traverse these trees. The SyntaxWalker
is a visitor that has built-in all the logic to walk down a syntax tree.
The SyntaxWalker
is completely stateless. All the state is on a context object that is passed along. The generic argument TContext
of SyntaxWalker<TContext>
denotes the type of the context.
To start the visitation of a GraphQL syntax tree, you have to pass the node and the context the visitation should start from to the visitors Visit
method.
Visitation
To start the visitation of a GraphQL syntax tree, you have to pass the node and the context the visitation should start from to the visitors Visit
method. On its way down the syntax tree, the visitor enters a node. The visitor then gets the children of the current node and enters its children. Once the visitor reached a leaf node, it starts walking back up the tree and leaves all the nodes. The visitor provides a virtual Enter
and a virtual Leave
method for all GraphQL AST nodes. These methods are called from the visitor as it enters or leaves a node.
The syntax walker provides a few methods in addition to the Enter
and Leave
methods. For these two methods, there are also convenience methods that are called right before and after the method call. Namely, OnBeforeEnter
, OnAfterEnter
, OnBeforeLeave
, OnAfterLeave
.
These methods can modify the current TContext
. These before and after methods are good places to initialize state that is used in the main enter or leave method. e.g. before entering a FieldNode
, you may want to peek the latest type from the context and get the instance of the ObjectField
corresponding to FieldNode
of this type. You may also want to push this type onto the context to then use it in the Enter
method.
⚠️ NOTE: In the following sequence diagram the participants do NOT represent any object instances. Furthermore, many steps are hidden in this example. The visualization below should just give you provide you visual insight on the order of the methods being called.
query GetFoos { foo { bar }}
- We start walking down the tree and enter.
Call thecsharp±OnBeforeEnter(OperationDefinitionNode node, TContext context)
- Call the
csharp±Enter(OperationDefinitionNode node, TContext context)
- Call the
csharp±OnAfterEnter(OperationDefinitionNode node, TContext context)
- Call the
csharp±VisitChildren(OperationDefinitionNode node, TContext context)
- Call the
csharp±OnBeforeEnter(ObjectFieldNode node, TContext context)
- Call the
csharp±Enter(ObjectFieldNode node, TContext context)
- Call the
csharp±OnAfterEnter(ObjectFieldNode node, TContext context)
- Call the
csharp±VisitChildren(ObjectFieldNode node, TContext context)
- We walk back up the tree and leave
- Call the
csharp±OnBeforeLeave(ObjectFieldNode node, TContext context)
- Call the
csharp±Leave(ObjectFieldNode node, TContext context)
- Call the
csharp±OnAfterLeave(ObjectFieldNode node, TContext context)
- We walk back up the tree and leave.
- Call the
csharp±OnBeforeLeave(OperationDefinitionNode node, TContext context)
- Call the
csharp±Leave(OperationDefinitionNode node, TContext context)
- Call the
csharp±OnAfterLeave(OperationDefinitionNode node, TContext context)
Visitor Actions
The Enter and Leave methods return visitor actions. These methods control the visitors' next step in the visitation. Visitor actions can be used to skip further visitation and step back up, or to continue and walk the current branch of the tree further down.
Continue
If Continue
is returned from the Enter
or Leave
method visitation on the current branch continues.
In the following example Continue
is returned from the onEnter method. The visitor calls VisitChildren
and continues by entering the selection set.
query { foo { bar baz @onEnter(return: CONTINUE) { quux } qux }}
Skip
If Skip
is returned from the Enter
or Leave
method, further visitation on this node stops.
In the following example Skip
is returned from the onEnter method. The visitor skips the field baz. It continues visitation by entering the field qux.
query { foo { bar baz @onEnter(return: SKIP) { quux } qux }}
SkipAndLeave
If SkipAndLeave
is returned from the Enter
method, further visitation on this node stops. Instead of directly calling the next Enter
method. The visitor calls the Leave
method of the current node first.
In the following example SkipAndLeave
is returned from the onEnter method. The visitor skips the field baz. Before it continues visitation with the field qux it leaves the field baz by calling Leave
query { foo { bar baz @onEnter(return: SKIPANDLEAVE) { quux } qux }}
Break
If Break
is returned from the Enter
or Leave
method, further visitation on this branch stops.
In the following example Break
is returned from the onEnter method. The visitor immediately starts walking back up. The visitor calls the Leave
on foo
instead of visiting the selections set of baz it skips baz and qux.
query { foo { bar baz @onEnter(return: BREAK) { quux } qux }}