1use error::*;
2use graphql_parser::query::*;
3use visitor::*;
4
5pub struct Traversal<'a> {
12 pub visitor: &'a mut Visitor,
14}
15
16impl<'a> Traversal<'a> {
17 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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}