graphql_query/validate/rules/
unique_variable_names.rs1use super::super::{ValidationContext, ValidationRule};
2use crate::{ast::*, visit::*};
3
4#[derive(Default)]
10pub struct UniqueVariableNames<'a> {
11 used_variable_names: Vec<&'a str>,
12}
13
14impl<'a> ValidationRule<'a> for UniqueVariableNames<'a> {}
15
16impl<'a> Visitor<'a, ValidationContext<'a>> for UniqueVariableNames<'a> {
17 fn enter_operation(
18 &mut self,
19 _ctx: &mut ValidationContext<'a>,
20 _operation: &'a OperationDefinition<'a>,
21 _info: &VisitInfo,
22 ) -> VisitFlow {
23 self.used_variable_names.clear();
24 VisitFlow::Next
25 }
26
27 fn enter_variable_definition(
28 &mut self,
29 ctx: &mut ValidationContext<'a>,
30 var_def: &'a VariableDefinition<'a>,
31 _info: &VisitInfo,
32 ) -> VisitFlow {
33 if self.used_variable_names.contains(&var_def.variable.name) {
34 ctx.add_error("All defined variables per operation must have unique names");
35 VisitFlow::Break
36 } else {
37 self.used_variable_names.push(var_def.variable.name);
38 VisitFlow::Skip
39 }
40 }
41
42 fn enter_selection_set(
43 &mut self,
44 _ctx: &mut ValidationContext<'a>,
45 _selection_set: &'a SelectionSet,
46 _info: &VisitInfo,
47 ) -> VisitFlow {
48 VisitFlow::Skip
49 }
50
51 fn enter_directive(
52 &mut self,
53 _ctx: &mut ValidationContext<'a>,
54 _fragment: &'a Directive,
55 _info: &VisitInfo,
56 ) -> VisitFlow {
57 VisitFlow::Skip
58 }
59
60 fn enter_fragment(
61 &mut self,
62 _ctx: &mut ValidationContext<'a>,
63 _fragment: &'a FragmentDefinition,
64 _info: &VisitInfo,
65 ) -> VisitFlow {
66 VisitFlow::Skip
67 }
68}
69
70#[cfg(test)]
71mod tests {
72 use super::*;
73
74 #[test]
75 fn valid_variables() {
76 let ctx = ASTContext::new();
77 let document = Document::parse(&ctx, "query ($a: Int, $b: Int) { __typename }").unwrap();
78 UniqueVariableNames::validate(&ctx, document).unwrap();
79 }
80
81 #[test]
82 fn overlapping_variables() {
83 let ctx = ASTContext::new();
84 let document = Document::parse(&ctx, "query ($a: Int, $a: Int) { __typename }").unwrap();
85 UniqueVariableNames::validate(&ctx, document).unwrap_err();
86 }
87}