graphql_id/
traverse.rs

1use error::*;
2use graphql_parser::query::*;
3use visitor::*;
4
5/// Traverse a GraphQL AST in a Depth-first fashion
6///
7/// Each handler in the traversal calls a `*_enter` method and a `*_exit` method.
8/// Use `*_enter` visitor if you want to traverse the AST in a *pre-order* fashion,
9/// and `*_exit` visitor if you want to traverse the AST in a *post-order* fashion.
10///
11pub struct Traversal<'a> {
12    /// The input visitor that implements the visitor trait with `*_enter` and `*_exit` callbacks
13    pub visitor: &'a mut Visitor,
14}
15
16impl<'a> Traversal<'a> {
17    /// Handle GraphQL Document node
18    pub fn handle_document(&mut self, document: &Document) -> Result<(), GraphQLError> {
19        self.visitor.visit_document_enter(document)?;
20
21        for definition in &document.definitions {
22            match definition {
23                Definition::Operation(operation) => self.handle_operation_definition(&operation),
24                Definition::Fragment(fragment) => self.handle_fragment_definition(&fragment),
25            }?;
26        }
27
28        self.visitor.visit_document_exit(document)
29    }
30
31    /// Handle GraphQL OperationDefinition node
32    pub fn handle_operation_definition(
33        &mut self,
34        operation_definition: &OperationDefinition,
35    ) -> Result<(), GraphQLError> {
36        self.visitor
37            .visit_operation_definition_enter(operation_definition)?;
38
39        match operation_definition {
40            OperationDefinition::SelectionSet(selection_set) => {
41                self.handle_selection_set(&selection_set)
42            }
43            OperationDefinition::Query(query) => self.handle_query(&query),
44            _ => Ok(()),
45        }?;
46
47        self.visitor
48            .visit_operation_definition_exit(operation_definition)
49    }
50
51    /// Handle GraphQL Query node
52    pub fn handle_query(&mut self, query: &Query) -> Result<(), GraphQLError> {
53        self.visitor.visit_query_enter(&query)?;
54        if let Some(name) = &query.name {
55            self.handle_name(&name)?;
56        }
57        for variable_definition in &query.variable_definitions {
58            self.handle_variable_definition(&variable_definition)?;
59        }
60        for directive in &query.directives {
61            self.handle_directive(&directive)?;
62        }
63        self.handle_selection_set(&query.selection_set)?;
64        self.visitor.visit_query_exit(&query)
65    }
66
67    /// Handle GraphQL VariableDefinition node
68    pub fn handle_variable_definition(
69        &mut self,
70        variable_definition: &VariableDefinition,
71    ) -> Result<(), GraphQLError> {
72        self.visitor
73            .visit_variable_definition_enter(&variable_definition)?;
74        self.handle_name(&variable_definition.name)?;
75        self.handle_type(&variable_definition.var_type)?;
76        if let Some(default_value) = &variable_definition.default_value {
77            self.handle_value(&default_value)?;
78        }
79        self.visitor
80            .visit_variable_definition_exit(&variable_definition)
81    }
82
83    /// Handle GraphQL SelectionSet node
84    pub fn handle_selection_set(
85        &mut self,
86        selection_set: &SelectionSet,
87    ) -> Result<(), GraphQLError> {
88        self.visitor.visit_selection_set_enter(&selection_set)?;
89        for selection in &selection_set.items {
90            self.handle_selection(&selection)?;
91        }
92        self.visitor.visit_selection_set_exit(&selection_set)
93    }
94
95    /// Handle GraphQL Selection node
96    pub fn handle_selection(&mut self, selection: &Selection) -> Result<(), GraphQLError> {
97        self.visitor.visit_selection_enter(&selection)?;
98        match &selection {
99            Selection::Field(field) => self.handle_field(&field),
100            Selection::FragmentSpread(fragment_spread) => {
101                self.handle_fragment_spread(&fragment_spread)
102            }
103            Selection::InlineFragment(inline_fragment) => {
104                self.handle_inline_fragment(&inline_fragment)
105            }
106        }?;
107        self.visitor.visit_selection_exit(&selection)
108    }
109
110    /// Handle GraphQL Field node
111    pub fn handle_field(&mut self, field: &Field) -> Result<(), GraphQLError> {
112        self.visitor.visit_field_enter(&field)?;
113        if let Some(alias) = &field.alias {
114            self.handle_name(&alias)?;
115        }
116        self.handle_name(&field.name)?;
117        for argument in &field.arguments {
118            self.handle_name(&argument.0)?;
119            self.handle_value(&argument.1)?;
120        }
121        for directive in &field.directives {
122            self.handle_directive(&directive)?;
123        }
124        self.handle_selection_set(&field.selection_set)?;
125        self.visitor.visit_field_exit(&field)
126    }
127
128    /// Handle GraphQL FragmentDefinition node
129    pub fn handle_fragment_definition(
130        &mut self,
131        fragment_definition: &FragmentDefinition,
132    ) -> Result<(), GraphQLError> {
133        self.visitor
134            .visit_fragment_definition_enter(&fragment_definition)?;
135        self.handle_name(&fragment_definition.name)?;
136        self.handle_type_condition(&fragment_definition.type_condition)?;
137        for directive in &fragment_definition.directives {
138            self.handle_directive(&directive)?;
139        }
140
141        self.handle_selection_set(&fragment_definition.selection_set)?;
142        self.visitor
143            .visit_fragment_definition_exit(&fragment_definition)
144    }
145
146    /// Handle GraphQL InlineFragment node
147    pub fn handle_inline_fragment(
148        &mut self,
149        inline_fragment: &InlineFragment,
150    ) -> Result<(), GraphQLError> {
151        self.visitor.visit_inline_fragment_enter(&inline_fragment)?;
152        if let Some(type_condition) = &inline_fragment.type_condition {
153            self.handle_type_condition(&type_condition)?;
154        }
155
156        for directive in &inline_fragment.directives {
157            self.handle_directive(&directive)?;
158        }
159        self.visitor.visit_inline_fragment_exit(&inline_fragment)
160    }
161
162    /// Handle GraphQL FragmentSpread node
163    pub fn handle_fragment_spread(
164        &mut self,
165        fragment_spread: &FragmentSpread,
166    ) -> Result<(), GraphQLError> {
167        self.visitor.visit_fragment_spread_enter(&fragment_spread)?;
168        self.handle_name(&fragment_spread.fragment_name)?;
169        for directive in &fragment_spread.directives {
170            self.handle_directive(&directive)?;
171        }
172        self.visitor.visit_fragment_spread_exit(&fragment_spread)
173    }
174
175    /// Handle GraphQL Directive node
176    pub fn handle_directive(&mut self, directive: &Directive) -> Result<(), GraphQLError> {
177        self.visitor.visit_directive_enter(&directive)?;
178
179        for argument in &directive.arguments {
180            self.handle_name(&argument.0)?;
181            self.handle_value(&argument.1)?;
182        }
183        self.visitor.visit_directive_exit(&directive)
184    }
185
186    /// Handle GraphQL TypeCondition node
187    pub fn handle_type_condition(
188        &mut self,
189        type_condition: &TypeCondition,
190    ) -> Result<(), GraphQLError> {
191        self.visitor.visit_type_condition_enter(&type_condition)?;
192
193        match type_condition {
194            TypeCondition::On(name) => self.handle_name(&name),
195        }?;
196        self.visitor.visit_type_condition_exit(&type_condition)
197    }
198
199    /// Handle GraphQL Type node
200    pub fn handle_type(&mut self, type1: &Type) -> Result<(), GraphQLError> {
201        self.visitor.visit_type_enter(&type1)?;
202
203        match &type1 {
204            Type::NamedType(type2) => self.handle_name(&type2),
205            Type::ListType(type2) => self.handle_type(&*type2),
206            Type::NonNullType(type2) => self.handle_type(&*type2),
207        }?;
208        self.visitor.visit_type_exit(&type1)
209    }
210
211    /// Handle GraphQL Name node
212    pub fn handle_name(&mut self, name: &Name) -> Result<(), GraphQLError> {
213        self.visitor.visit_name_enter(&name)?;
214        self.visitor.visit_name_exit(&name)
215    }
216
217    /// Handle GraphQL Value node
218    pub fn handle_value(&mut self, value: &Value) -> Result<(), GraphQLError> {
219        self.visitor.visit_value_enter(&value)?;
220        self.visitor.visit_value_exit(&value)
221    }
222}