1use std::collections::HashMap;
2
3use lazy_static::lazy_static;
4
5use crate::static_graphql::query::{
6 self, Directive, FragmentSpread, OperationDefinition, SelectionSet, Type, Value,
7 VariableDefinition,
8};
9use crate::static_graphql::schema::{
10 self, DirectiveDefinition, EnumValue, Field, InputValue, InterfaceType, ObjectType,
11 TypeDefinition, TypeExtension, UnionType,
12};
13
14lazy_static! {
15 static ref QUERY_TYPE_DEFAULT_NAME: String = "Query".to_string();
16 static ref MUTATION_TYPE_DEFAULT_NAME: String = "Mutation".to_string();
17 static ref SUBSCRIPTION_TYPE_DEFAULT_NAME: String = "Subscription".to_string();
18}
19
20impl TypeDefinition {
21 pub fn field_by_name(&self, name: &str) -> Option<&schema::Field> {
22 match self {
23 TypeDefinition::Object(object) => {
24 object.fields.iter().find(|field| field.name.eq(name))
25 }
26 TypeDefinition::Interface(interface) => {
27 interface.fields.iter().find(|field| field.name.eq(name))
28 }
29 _ => None,
30 }
31 }
32
33 pub fn input_field_by_name(&self, name: &str) -> Option<&InputValue> {
34 match self {
35 TypeDefinition::InputObject(input_object) => {
36 input_object.fields.iter().find(|field| field.name.eq(name))
37 }
38 _ => None,
39 }
40 }
41}
42
43impl OperationDefinition {
44 pub fn variable_definitions(&self) -> &[VariableDefinition] {
45 match self {
46 OperationDefinition::Query(query) => &query.variable_definitions,
47 OperationDefinition::SelectionSet(_) => &[],
48 OperationDefinition::Mutation(mutation) => &mutation.variable_definitions,
49 OperationDefinition::Subscription(subscription) => &subscription.variable_definitions,
50 }
51 }
52
53 pub fn selection_set(&self) -> &SelectionSet {
54 match self {
55 OperationDefinition::Query(query) => &query.selection_set,
56 OperationDefinition::SelectionSet(selection_set) => selection_set,
57 OperationDefinition::Mutation(mutation) => &mutation.selection_set,
58 OperationDefinition::Subscription(subscription) => &subscription.selection_set,
59 }
60 }
61
62 pub fn directives(&self) -> &[Directive] {
63 match self {
64 OperationDefinition::Query(query) => &query.directives,
65 OperationDefinition::SelectionSet(_) => &[],
66 OperationDefinition::Mutation(mutation) => &mutation.directives,
67 OperationDefinition::Subscription(subscription) => &subscription.directives,
68 }
69 }
70}
71
72impl schema::Document {
73 pub fn type_by_name(&self, name: &str) -> Option<&TypeDefinition> {
74 for def in &self.definitions {
75 if let schema::Definition::TypeDefinition(type_def) = def {
76 if type_def.name().eq(name) {
77 return Some(type_def);
78 }
79 }
80 }
81
82 None
83 }
84
85 pub fn directive_by_name(&self, name: &str) -> Option<&DirectiveDefinition> {
86 for def in &self.definitions {
87 if let schema::Definition::DirectiveDefinition(directive_def) = def {
88 if directive_def.name.eq(name) {
89 return Some(directive_def);
90 }
91 }
92 }
93
94 None
95 }
96
97 fn schema_definition(&self) -> &schema::SchemaDefinition {
98 lazy_static! {
99 static ref DEFAULT_SCHEMA_DEF: schema::SchemaDefinition = {
100 schema::SchemaDefinition {
101 query: Some("Query".to_string()),
102 ..Default::default()
103 }
104 };
105 }
106 self.definitions
107 .iter()
108 .find_map(|definition| match definition {
109 schema::Definition::SchemaDefinition(schema_definition) => Some(schema_definition),
110 _ => None,
111 })
112 .unwrap_or(&*DEFAULT_SCHEMA_DEF)
113 }
114
115 pub fn query_type(&self) -> &ObjectType {
116 let schema_definition = self.schema_definition();
117 self.object_type_by_name(
118 schema_definition
119 .query
120 .as_ref()
121 .unwrap_or(&QUERY_TYPE_DEFAULT_NAME),
122 )
123 .unwrap()
124 }
125
126 pub fn mutation_type(&self) -> Option<&ObjectType> {
127 let schema_definition = self.schema_definition();
128 self.object_type_by_name(
129 schema_definition
130 .mutation
131 .as_ref()
132 .unwrap_or(&MUTATION_TYPE_DEFAULT_NAME),
133 )
134 }
135
136 pub fn subscription_type(&self) -> Option<&ObjectType> {
137 let schema_definition = self.schema_definition();
138
139 self.object_type_by_name(
140 schema_definition
141 .subscription
142 .as_ref()
143 .unwrap_or(&SUBSCRIPTION_TYPE_DEFAULT_NAME),
144 )
145 }
146
147 fn object_type_by_name(&self, name: &str) -> Option<&ObjectType> {
148 match self.type_by_name(name) {
149 Some(TypeDefinition::Object(object_def)) => Some(object_def),
150 _ => None,
151 }
152 }
153
154 pub fn type_map(&self) -> HashMap<&str, &TypeDefinition> {
155 let mut type_map = HashMap::new();
156
157 for def in &self.definitions {
158 if let schema::Definition::TypeDefinition(type_def) = def {
159 type_map.insert(type_def.name(), type_def);
160 }
161 }
162
163 type_map
164 }
165
166 pub fn is_named_subtype(&self, sub_type_name: &str, super_type_name: &str) -> bool {
167 if sub_type_name == super_type_name {
168 true
169 } else if let (Some(sub_type), Some(super_type)) = (
170 self.type_by_name(sub_type_name),
171 self.type_by_name(super_type_name),
172 ) {
173 super_type.is_abstract_type() && self.is_possible_type(super_type, sub_type)
174 } else {
175 false
176 }
177 }
178
179 fn is_possible_type(
180 &self,
181 abstract_type: &TypeDefinition,
182 possible_type: &TypeDefinition,
183 ) -> bool {
184 match abstract_type {
185 TypeDefinition::Union(union_typedef) => union_typedef
186 .types
187 .iter()
188 .any(|t| t == possible_type.name()),
189 TypeDefinition::Interface(interface_typedef) => {
190 let implementes_interfaces = possible_type.interfaces();
191
192 implementes_interfaces.contains(&interface_typedef.name)
193 }
194 _ => false,
195 }
196 }
197
198 pub fn is_subtype(&self, sub_type: &Type, super_type: &Type) -> bool {
199 if sub_type == super_type {
201 return true;
202 }
203
204 if super_type.is_non_null() {
206 if sub_type.is_non_null() {
207 return self.is_subtype(sub_type.of_type(), super_type.of_type());
208 }
209 return false;
210 }
211
212 if sub_type.is_non_null() {
213 return self.is_subtype(sub_type.of_type(), super_type);
215 }
216
217 if super_type.is_list_type() {
219 if sub_type.is_list_type() {
220 return self.is_subtype(sub_type.of_type(), super_type.of_type());
221 }
222
223 return false;
224 }
225
226 if sub_type.is_list_type() {
227 return false;
229 }
230
231 if let (Some(sub_type), Some(super_type)) = (
234 self.type_by_name(sub_type.inner_type()),
235 self.type_by_name(super_type.inner_type()),
236 ) {
237 return super_type.is_abstract_type()
238 && (sub_type.is_interface_type() || sub_type.is_object_type())
239 && self.is_possible_type(super_type, sub_type);
240 }
241
242 false
243 }
244
245 pub fn query_type_name(&self) -> &str {
246 "Query"
247 }
248
249 pub fn mutation_type_name(&self) -> Option<&str> {
250 for def in &self.definitions {
251 if let schema::Definition::SchemaDefinition(schema_def) = def {
252 if let Some(name) = schema_def.mutation.as_ref() {
253 return Some(name.as_str());
254 }
255 }
256 }
257
258 self.type_by_name("Mutation").map(|typ| typ.name())
259 }
260
261 pub fn subscription_type_name(&self) -> Option<&str> {
262 for def in &self.definitions {
263 if let schema::Definition::SchemaDefinition(schema_def) = def {
264 if let Some(name) = schema_def.subscription.as_ref() {
265 return Some(name.as_str());
266 }
267 }
268 }
269
270 self.type_by_name("Subscription").map(|typ| typ.name())
271 }
272}
273
274impl Type {
275 pub fn inner_type(&self) -> &str {
276 match self {
277 Type::NamedType(name) => name.as_str(),
278 Type::ListType(child) => child.inner_type(),
279 Type::NonNullType(child) => child.inner_type(),
280 }
281 }
282
283 fn of_type(&self) -> &Type {
284 match self {
285 Type::ListType(child) => child,
286 Type::NonNullType(child) => child,
287 Type::NamedType(_) => self,
288 }
289 }
290
291 pub fn is_non_null(&self) -> bool {
292 matches!(self, Type::NonNullType(_))
293 }
294
295 fn is_list_type(&self) -> bool {
296 matches!(self, Type::ListType(_))
297 }
298
299 pub fn is_named_type(&self) -> bool {
300 matches!(self, Type::NamedType(_))
301 }
302}
303
304impl Value {
305 pub fn compare(&self, other: &Self) -> bool {
306 match (self, other) {
307 (Value::Null, Value::Null) => true,
308 (Value::Boolean(a), Value::Boolean(b)) => a == b,
309 (Value::Int(a), Value::Int(b)) => a == b,
310 (Value::Float(a), Value::Float(b)) => a == b,
311 (Value::String(a), Value::String(b)) => a.eq(b),
312 (Value::Enum(a), Value::Enum(b)) => a.eq(b),
313 (Value::List(a), Value::List(b)) => a.iter().zip(b.iter()).all(|(a, b)| a.compare(b)),
314 (Value::Object(a), Value::Object(b)) => {
315 a.iter().zip(b.iter()).all(|(a, b)| a.1.compare(b.1))
316 }
317 (Value::Variable(a), Value::Variable(b)) => a.eq(b),
318 _ => false,
319 }
320 }
321
322 pub fn variables_in_use(&self) -> Vec<&str> {
323 match self {
324 Value::Variable(v) => vec![v],
325 Value::List(list) => list.iter().flat_map(|v| v.variables_in_use()).collect(),
326 Value::Object(object) => object
327 .iter()
328 .flat_map(|(_, v)| v.variables_in_use())
329 .collect(),
330 _ => vec![],
331 }
332 }
333}
334
335impl InputValue {
336 pub fn is_required(&self) -> bool {
337 if let Type::NonNullType(_inner_type) = &self.value_type {
338 if self.default_value.is_none() {
339 return true;
340 }
341 }
342
343 false
344 }
345}
346
347impl TypeDefinition {
348 fn interfaces(&self) -> Vec<String> {
349 match self {
350 schema::TypeDefinition::Object(o) => o.interfaces(),
351 schema::TypeDefinition::Interface(i) => i.interfaces(),
352 _ => vec![],
353 }
354 }
355
356 pub fn has_sub_type(&self, other_type: &TypeDefinition) -> bool {
357 match self {
358 TypeDefinition::Interface(interface_type) => {
359 interface_type.is_implemented_by(other_type)
360 }
361 TypeDefinition::Union(union_type) => union_type.has_sub_type(other_type.name()),
362 _ => false,
363 }
364 }
365
366 pub fn has_concrete_sub_type(&self, concrete_type: &TypeDefinition) -> bool {
367 match self {
368 TypeDefinition::Interface(interface_type) => {
369 interface_type.is_implemented_by(concrete_type)
370 }
371 TypeDefinition::Union(union_type) => union_type.has_sub_type(concrete_type.name()),
372 _ => false,
373 }
374 }
375}
376
377impl TypeDefinition {
378 pub fn possible_types<'a>(&self, schema: &'a schema::Document) -> Vec<&'a TypeDefinition> {
379 match self {
380 TypeDefinition::Object(_) => vec![],
381 TypeDefinition::InputObject(_) => vec![],
382 TypeDefinition::Enum(_) => vec![],
383 TypeDefinition::Scalar(_) => vec![],
384 TypeDefinition::Interface(i) => schema
385 .type_map()
386 .iter()
387 .filter_map(|(_type_name, type_def)| {
388 if i.is_implemented_by(type_def) {
389 return Some(*type_def);
390 }
391
392 None
393 })
394 .collect(),
395 TypeDefinition::Union(u) => u
396 .types
397 .iter()
398 .filter_map(|type_name| {
399 if let Some(type_def) = schema.type_by_name(type_name) {
400 return Some(type_def);
401 }
402
403 None
404 })
405 .collect(),
406 }
407 }
408}
409
410impl InterfaceType {
411 fn interfaces(&self) -> Vec<String> {
412 self.implements_interfaces.clone()
413 }
414
415 pub fn has_sub_type(&self, other_type: &TypeDefinition) -> bool {
416 self.is_implemented_by(other_type)
417 }
418
419 pub fn has_concrete_sub_type(&self, concrete_type: &TypeDefinition) -> bool {
420 self.is_implemented_by(concrete_type)
421 }
422}
423
424impl ObjectType {
425 fn interfaces(&self) -> Vec<String> {
426 self.implements_interfaces.clone()
427 }
428
429 pub fn has_sub_type(&self, _other_type: &TypeDefinition) -> bool {
430 false
431 }
432
433 pub fn has_concrete_sub_type(&self, _concrete_type: &ObjectType) -> bool {
434 false
435 }
436}
437
438impl UnionType {
439 pub fn has_sub_type(&self, other_type_name: &str) -> bool {
440 self.types.iter().any(|v| other_type_name.eq(v))
441 }
442}
443
444impl InterfaceType {
445 pub fn is_implemented_by(&self, other_type: &TypeDefinition) -> bool {
446 other_type.interfaces().iter().any(|v| self.name.eq(v))
447 }
448}
449
450impl schema::TypeDefinition {
451 pub fn name(&self) -> &str {
452 match self {
453 schema::TypeDefinition::Object(o) => &o.name,
454 schema::TypeDefinition::Interface(i) => &i.name,
455 schema::TypeDefinition::Union(u) => &u.name,
456 schema::TypeDefinition::Scalar(s) => &s.name,
457 schema::TypeDefinition::Enum(e) => &e.name,
458 schema::TypeDefinition::InputObject(i) => &i.name,
459 }
460 }
461
462 pub fn is_abstract_type(&self) -> bool {
463 matches!(
464 self,
465 schema::TypeDefinition::Interface(_) | schema::TypeDefinition::Union(_)
466 )
467 }
468
469 fn is_interface_type(&self) -> bool {
470 matches!(self, schema::TypeDefinition::Interface(_))
471 }
472
473 pub fn is_leaf_type(&self) -> bool {
474 matches!(
475 self,
476 schema::TypeDefinition::Scalar(_) | schema::TypeDefinition::Enum(_)
477 )
478 }
479
480 pub fn is_input_type(&self) -> bool {
481 matches!(
482 self,
483 schema::TypeDefinition::Scalar(_)
484 | schema::TypeDefinition::Enum(_)
485 | schema::TypeDefinition::InputObject(_)
486 )
487 }
488
489 pub fn is_composite_type(&self) -> bool {
490 matches!(
491 self,
492 schema::TypeDefinition::Object(_)
493 | schema::TypeDefinition::Interface(_)
494 | schema::TypeDefinition::Union(_)
495 )
496 }
497
498 pub fn is_object_type(&self) -> bool {
499 matches!(self, schema::TypeDefinition::Object(_o))
500 }
501
502 pub fn is_union_type(&self) -> bool {
503 matches!(self, schema::TypeDefinition::Union(_o))
504 }
505
506 pub fn is_enum_type(&self) -> bool {
507 matches!(self, schema::TypeDefinition::Enum(_o))
508 }
509
510 pub fn is_scalar_type(&self) -> bool {
511 matches!(self, schema::TypeDefinition::Scalar(_o))
512 }
513}
514
515pub trait AstNodeWithName {
516 fn node_name(&self) -> Option<&str>;
517}
518
519impl AstNodeWithName for query::OperationDefinition {
520 fn node_name(&self) -> Option<&str> {
521 match self {
522 query::OperationDefinition::Query(q) => q.name.as_deref(),
523 query::OperationDefinition::SelectionSet(_s) => None,
524 query::OperationDefinition::Mutation(m) => m.name.as_deref(),
525 query::OperationDefinition::Subscription(s) => s.name.as_deref(),
526 }
527 }
528}
529
530impl AstNodeWithName for query::FragmentDefinition {
531 fn node_name(&self) -> Option<&str> {
532 Some(&self.name)
533 }
534}
535
536impl AstNodeWithName for query::FragmentSpread {
537 fn node_name(&self) -> Option<&str> {
538 Some(&self.fragment_name)
539 }
540}
541
542impl query::SelectionSet {
543 pub fn get_recursive_fragment_spreads(&self) -> Vec<&FragmentSpread> {
544 self.items
545 .iter()
546 .flat_map(|v| match v {
547 query::Selection::FragmentSpread(f) => vec![f],
548 query::Selection::Field(f) => f.selection_set.get_fragment_spreads(),
549 query::Selection::InlineFragment(f) => f.selection_set.get_fragment_spreads(),
550 })
551 .collect()
552 }
553
554 fn get_fragment_spreads(&self) -> Vec<&FragmentSpread> {
555 self.items
556 .iter()
557 .flat_map(|v| match v {
558 query::Selection::FragmentSpread(f) => vec![f],
559 _ => vec![],
560 })
561 .collect()
562 }
563}
564
565impl query::Selection {
566 pub fn directives(&self) -> &[Directive] {
567 match self {
568 query::Selection::Field(f) => &f.directives,
569 query::Selection::FragmentSpread(f) => &f.directives,
570 query::Selection::InlineFragment(f) => &f.directives,
571 }
572 }
573 pub fn selection_set(&self) -> Option<&SelectionSet> {
574 match self {
575 query::Selection::Field(f) => Some(&f.selection_set),
576 query::Selection::FragmentSpread(_) => None,
577 query::Selection::InlineFragment(f) => Some(&f.selection_set),
578 }
579 }
580}
581
582impl schema::Definition<'static, String> {
583 pub fn name(&self) -> Option<&str> {
584 match self {
585 schema::Definition::SchemaDefinition(_) => None,
586 schema::Definition::TypeDefinition(type_def) => Some(type_def.name()),
587 schema::Definition::TypeExtension(type_ext) => Some(type_ext.name()),
588 schema::Definition::DirectiveDefinition(directive_def) => Some(&directive_def.name),
589 }
590 }
591 pub fn fields<'a>(&'a self) -> Option<TypeDefinitionFields<'a>> {
592 match self {
593 schema::Definition::SchemaDefinition(_) => None,
594 schema::Definition::TypeDefinition(type_def) => type_def.fields(),
595 schema::Definition::TypeExtension(type_ext) => type_ext.fields(),
596 schema::Definition::DirectiveDefinition(_) => None,
597 }
598 }
599 pub fn directives(&self) -> Option<&[Directive]> {
600 match self {
601 schema::Definition::SchemaDefinition(schema_def) => Some(&schema_def.directives),
602 schema::Definition::TypeDefinition(type_def) => type_def.directives(),
603 schema::Definition::TypeExtension(type_ext) => type_ext.directives(),
604 schema::Definition::DirectiveDefinition(_) => None,
605 }
606 }
607}
608
609pub enum TypeDefinitionFields<'a> {
610 Fields(&'a [Field]),
611 InputValues(&'a [InputValue]),
612 EnumValues(&'a [EnumValue]),
613}
614
615impl TypeDefinition {
616 pub fn fields<'a>(&'a self) -> Option<TypeDefinitionFields<'a>> {
617 match self {
618 TypeDefinition::Scalar(_) => None,
619 TypeDefinition::Object(object) => Some(TypeDefinitionFields::Fields(&object.fields)),
620 TypeDefinition::Interface(interface) => {
621 Some(TypeDefinitionFields::Fields(&interface.fields))
622 }
623 TypeDefinition::Union(_) => None,
624 TypeDefinition::Enum(enum_) => Some(TypeDefinitionFields::EnumValues(&enum_.values)),
625 TypeDefinition::InputObject(input_object) => {
626 Some(TypeDefinitionFields::InputValues(&input_object.fields))
627 }
628 }
629 }
630 pub fn directives(&self) -> Option<&[Directive]> {
631 match self {
632 TypeDefinition::Scalar(_) => None,
633 TypeDefinition::Object(object) => Some(&object.directives),
634 TypeDefinition::Interface(interface) => Some(&interface.directives),
635 TypeDefinition::Union(union) => Some(&union.directives),
636 TypeDefinition::Enum(enum_) => Some(&enum_.directives),
637 TypeDefinition::InputObject(input_object) => Some(&input_object.directives),
638 }
639 }
640}
641
642impl TypeExtension<'static, String> {
643 pub fn name(&self) -> &str {
644 match self {
645 TypeExtension::Object(object) => &object.name,
646 TypeExtension::Interface(interface) => &interface.name,
647 TypeExtension::Union(union) => &union.name,
648 TypeExtension::Scalar(scalar) => &scalar.name,
649 TypeExtension::Enum(enum_) => &enum_.name,
650 TypeExtension::InputObject(input_object) => &input_object.name,
651 }
652 }
653 pub fn fields<'a>(&'a self) -> Option<TypeDefinitionFields<'a>> {
654 match self {
655 TypeExtension::Object(object) => Some(TypeDefinitionFields::Fields(&object.fields)),
656 TypeExtension::Interface(interface) => {
657 Some(TypeDefinitionFields::Fields(&interface.fields))
658 }
659 _ => None,
660 }
661 }
662 pub fn directives(&self) -> Option<&[Directive]> {
663 match self {
664 TypeExtension::Object(object) => Some(&object.directives),
665 TypeExtension::Interface(interface) => Some(&interface.directives),
666 TypeExtension::Union(union) => Some(&union.directives),
667 TypeExtension::Enum(enum_) => Some(&enum_.directives),
668 TypeExtension::InputObject(input_object) => Some(&input_object.directives),
669 TypeExtension::Scalar(scalar) => Some(&scalar.directives),
670 }
671 }
672}