1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
use crate::{ ast::VariableDefinition, parser::Spanning, validation::{ValidatorContext, Visitor}, value::ScalarValue, }; pub struct UniqueVariableNames; pub fn factory() -> UniqueVariableNames { UniqueVariableNames } impl<'a, S> Visitor<'a, S> for UniqueVariableNames where S: ScalarValue, { fn enter_variable_definition( &mut self, ctx: &mut ValidatorContext<'a, S>, &(ref var_name, ref var_def): &'a (Spanning<&'a str>, VariableDefinition<S>), ) { if let Some(var_type) = ctx .schema .concrete_type_by_name(var_def.var_type.item.innermost_name()) { if !var_type.is_input() { ctx.report_error( &error_message(var_name.item, &format!("{}", var_def.var_type.item)), &[var_def.var_type.start], ); } } } } fn error_message(var_name: &str, type_name: &str) -> String { format!( "Variable \"{}\" cannot be of non-input type \"{}\"", var_name, type_name ) } #[cfg(test)] mod tests { use super::{error_message, factory}; use crate::{ parser::SourcePosition, validation::{expect_fails_rule, expect_passes_rule, RuleError}, value::DefaultScalarValue, }; #[test] fn input_types_are_valid() { expect_passes_rule::<_, _, DefaultScalarValue>( factory, r#" query Foo($a: String, $b: [Boolean!]!, $c: ComplexInput) { field(a: $a, b: $b, c: $c) } "#, ); } #[test] fn output_types_are_invalid() { expect_fails_rule::<_, _, DefaultScalarValue>( factory, r#" query Foo($a: Dog, $b: [[CatOrDog!]]!, $c: Pet) { field(a: $a, b: $b, c: $c) } "#, &[ RuleError::new( &error_message("a", "Dog"), &[SourcePosition::new(25, 1, 24)], ), RuleError::new( &error_message("b", "[[CatOrDog!]]!"), &[SourcePosition::new(34, 1, 33)], ), RuleError::new( &error_message("c", "Pet"), &[SourcePosition::new(54, 1, 53)], ), ], ); } }