graphql_query/validate/rules/
known_fragment_names.rs1use super::super::{ValidationContext, ValidationRule};
2use crate::{ast::*, visit::*};
3
4#[derive(Default)]
9pub struct KnownFragmentNames<'a> {
10 fragment_names: Vec<&'a str>,
11 fragment_spreads: Vec<&'a str>,
12}
13
14impl<'a> ValidationRule<'a> for KnownFragmentNames<'a> {}
15
16impl<'a> Visitor<'a, ValidationContext<'a>> for KnownFragmentNames<'a> {
17 fn enter_fragment(
18 &mut self,
19 _ctx: &mut ValidationContext<'a>,
20 fragment: &'a FragmentDefinition<'a>,
21 _info: &VisitInfo,
22 ) -> VisitFlow {
23 self.fragment_names.push(fragment.name.name);
24 VisitFlow::Next
25 }
26
27 fn enter_fragment_spread(
28 &mut self,
29 _ctx: &mut ValidationContext<'a>,
30 spread: &'a FragmentSpread<'a>,
31 _info: &VisitInfo,
32 ) -> VisitFlow {
33 self.fragment_spreads.push(spread.name.name);
34 VisitFlow::Skip
35 }
36
37 fn leave_document(
38 &mut self,
39 ctx: &mut ValidationContext<'a>,
40 _document: &'a Document<'a>,
41 _info: &VisitInfo,
42 ) -> VisitFlow {
43 for name in self.fragment_spreads.iter() {
44 if !self.fragment_names.contains(name) {
45 ctx.add_error("Only known fragments may occur in fragment spreads.");
46 }
47 }
48 VisitFlow::Next
49 }
50
51 fn enter_variable_definition(
52 &mut self,
53 _ctx: &mut ValidationContext<'a>,
54 _var_def: &'a VariableDefinition,
55 _info: &VisitInfo,
56 ) -> VisitFlow {
57 VisitFlow::Skip
58 }
59
60 fn enter_argument(
61 &mut self,
62 _ctx: &mut ValidationContext<'a>,
63 _argument: &'a Argument,
64 _info: &VisitInfo,
65 ) -> VisitFlow {
66 VisitFlow::Skip
67 }
68
69 fn enter_directive(
70 &mut self,
71 _ctx: &mut ValidationContext<'a>,
72 _directive: &'a Directive,
73 _info: &VisitInfo,
74 ) -> VisitFlow {
75 VisitFlow::Skip
76 }
77}
78
79#[cfg(test)]
80mod tests {
81 use super::*;
82
83 #[test]
84 fn valid_spread() {
85 let ctx = ASTContext::new();
86 let document = Document::parse(
87 &ctx,
88 "query { ...Root } fragment Root on Query { __typename }",
89 )
90 .unwrap();
91 KnownFragmentNames::validate(&ctx, document).unwrap();
92 }
93
94 #[test]
95 fn invalid_spread() {
96 let ctx = ASTContext::new();
97 let document = Document::parse(&ctx, "query { ...Unknown }").unwrap();
98 KnownFragmentNames::validate(&ctx, document).unwrap_err();
99 }
100}