2020-03-30 02:45:41 +00:00
|
|
|
use crate::context::QueryPathNode;
|
2020-03-08 12:35:36 +00:00
|
|
|
use crate::registry::InputValue;
|
|
|
|
use crate::validation::utils::is_valid_input_value;
|
2020-03-24 10:54:22 +00:00
|
|
|
use crate::validation::visitor::{Visitor, VisitorContext};
|
2020-03-30 02:45:41 +00:00
|
|
|
use crate::QueryPathSegment;
|
2020-03-08 12:35:36 +00:00
|
|
|
use graphql_parser::query::Field;
|
|
|
|
use graphql_parser::schema::{Directive, Value};
|
|
|
|
use graphql_parser::Pos;
|
|
|
|
use std::collections::HashMap;
|
|
|
|
|
|
|
|
#[derive(Default)]
|
|
|
|
pub struct ArgumentsOfCorrectType<'a> {
|
2020-03-09 12:39:46 +00:00
|
|
|
current_args: Option<&'a HashMap<&'static str, InputValue>>,
|
2020-03-08 12:35:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> Visitor<'a> for ArgumentsOfCorrectType<'a> {
|
2020-03-22 08:45:59 +00:00
|
|
|
fn enter_directive(&mut self, ctx: &mut VisitorContext<'a>, directive: &'a Directive) {
|
2020-03-08 12:35:36 +00:00
|
|
|
self.current_args = ctx
|
|
|
|
.registry
|
|
|
|
.directives
|
|
|
|
.get(&directive.name)
|
2020-03-09 12:39:46 +00:00
|
|
|
.map(|d| &d.args);
|
2020-03-08 12:35:36 +00:00
|
|
|
}
|
|
|
|
|
2020-03-22 08:45:59 +00:00
|
|
|
fn exit_directive(&mut self, _ctx: &mut VisitorContext<'a>, _directive: &'a Directive) {
|
2020-03-08 12:35:36 +00:00
|
|
|
self.current_args = None;
|
|
|
|
}
|
|
|
|
|
2020-03-09 12:39:46 +00:00
|
|
|
fn enter_argument(
|
|
|
|
&mut self,
|
2020-03-22 08:45:59 +00:00
|
|
|
ctx: &mut VisitorContext<'a>,
|
2020-03-09 12:39:46 +00:00
|
|
|
pos: Pos,
|
|
|
|
name: &str,
|
|
|
|
value: &'a Value,
|
|
|
|
) {
|
|
|
|
if let Some(arg) = self
|
2020-03-08 12:35:36 +00:00
|
|
|
.current_args
|
2020-03-09 12:39:46 +00:00
|
|
|
.and_then(|args| args.get(name).map(|input| input))
|
2020-03-08 12:35:36 +00:00
|
|
|
{
|
2020-03-22 01:34:32 +00:00
|
|
|
if let Some(validator) = &arg.validator {
|
2020-03-21 01:32:13 +00:00
|
|
|
if let Some(reason) = validator.is_valid(value) {
|
|
|
|
ctx.report_error(
|
|
|
|
vec![pos],
|
|
|
|
format!("Invalid value for argument \"{}\", {}", arg.name, reason,),
|
|
|
|
);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-30 02:45:41 +00:00
|
|
|
if let Some(reason) = is_valid_input_value(
|
|
|
|
ctx.registry,
|
|
|
|
&arg.ty,
|
|
|
|
value,
|
|
|
|
QueryPathNode {
|
|
|
|
parent: None,
|
|
|
|
segment: QueryPathSegment::Name(arg.name),
|
|
|
|
},
|
|
|
|
) {
|
|
|
|
ctx.report_error(vec![pos], format!("Invalid value for argument {}", reason));
|
2020-03-08 12:35:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-22 08:45:59 +00:00
|
|
|
fn enter_field(&mut self, ctx: &mut VisitorContext<'a>, field: &'a Field) {
|
2020-03-08 12:35:36 +00:00
|
|
|
self.current_args = ctx
|
|
|
|
.parent_type()
|
2020-03-09 04:08:50 +00:00
|
|
|
.and_then(|p| p.field_by_name(&field.name))
|
2020-03-09 12:39:46 +00:00
|
|
|
.map(|f| &f.args);
|
2020-03-08 12:35:36 +00:00
|
|
|
}
|
|
|
|
|
2020-03-22 08:45:59 +00:00
|
|
|
fn exit_field(&mut self, _ctx: &mut VisitorContext<'a>, _field: &'a Field) {
|
2020-03-08 12:35:36 +00:00
|
|
|
self.current_args = None;
|
|
|
|
}
|
|
|
|
}
|