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
use crate::registry::InputValue; use crate::validation::context::ValidatorContext; use crate::validation::visitor::Visitor; use crate::Value; use graphql_parser::query::{Directive, Field}; use graphql_parser::Pos; use std::collections::HashMap; enum ArgsType<'a> { Directive(&'a str), Field { field_name: &'a str, type_name: &'a str, }, } #[derive(Default)] pub struct KnownArgumentNames<'a> { current_args: Option<(&'a HashMap<&'static str, InputValue>, ArgsType<'a>)>, } impl<'a> Visitor<'a> for KnownArgumentNames<'a> { fn enter_directive(&mut self, ctx: &mut ValidatorContext<'a>, directive: &'a Directive) { self.current_args = ctx .registry .directives .get(&directive.name) .map(|d| (&d.args, ArgsType::Directive(&directive.name))); } fn exit_directive(&mut self, _ctx: &mut ValidatorContext<'a>, _directive: &'a Directive) { self.current_args = None; } fn enter_argument( &mut self, ctx: &mut ValidatorContext<'a>, pos: Pos, name: &str, _value: &'a Value, ) { if let Some((args, arg_type)) = &self.current_args { if !args.contains_key(name) { match arg_type { ArgsType::Field { field_name, type_name, } => { ctx.report_error( vec![pos], format!( "Unknown argument \"{}\" on field \"{}\" of type \"{}\"", name, field_name, type_name, ), ); } ArgsType::Directive(directive_name) => { ctx.report_error( vec![pos], format!( "Unknown argument \"{}\" on directive \"{}\"", name, directive_name ), ); } } } } } fn enter_field(&mut self, ctx: &mut ValidatorContext<'a>, field: &'a Field) { self.current_args = ctx .parent_type() .and_then(|p| p.field_by_name(&field.name)) .map(|f| { ( &f.args, ArgsType::Field { field_name: &field.name, type_name: ctx.parent_type().unwrap().name(), }, ) }); } fn exit_field(&mut self, _ctx: &mut ValidatorContext<'a>, _field: &'a Field) { self.current_args = None; } }