add ProvidedNonNullArguments rule

This commit is contained in:
sunli 2020-03-10 20:35:25 +08:00
parent de96634f1f
commit feb71eef22
5 changed files with 67 additions and 2 deletions

View File

@ -103,7 +103,7 @@ Open `http://localhost:8000` in browser
- [X] NoUnusedVariables
- [ ] OverlappingFieldsCanBeMerged
- [X] PossibleFragmentSpreads
- [ ] ProvidedNonNullArguments
- [X] ProvidedNonNullArguments
- [X] ScalarLeafs
- [X] UniqueArgumentNames
- [X] UniqueFragmentNames

View File

@ -41,6 +41,14 @@ impl<'a> TypeName<'a> {
TypeName::Named(type_name) => type_name,
}
}
pub fn is_non_null(&self) -> bool {
if let TypeName::NonNull(_) = self {
true
} else {
false
}
}
}
pub struct InputValue {

View File

@ -32,7 +32,8 @@ pub fn check_rules(registry: &Registry, doc: &Document) -> Result<()> {
.with(rules::VariablesAreInputTypes)
.with(rules::VariableInAllowedPosition::default())
.with(rules::ScalarLeafs)
.with(rules::PossibleFragmentSpreads::default());
.with(rules::PossibleFragmentSpreads::default())
.with(rules::ProvidedNonNullArguments);
visit(&mut visitor, &mut ctx, doc);
if !ctx.errors.is_empty() {

View File

@ -11,6 +11,7 @@ mod no_undefined_variables;
mod no_unused_fragments;
mod no_unused_variables;
mod possible_fragment_spreads;
mod provided_non_null_arguments;
mod scalar_leafs;
mod unique_argument_names;
mod unique_fragment_names;
@ -32,6 +33,7 @@ pub use no_undefined_variables::NoUndefinedVariables;
pub use no_unused_fragments::NoUnusedFragments;
pub use no_unused_variables::NoUnusedVariables;
pub use possible_fragment_spreads::PossibleFragmentSpreads;
pub use provided_non_null_arguments::ProvidedNonNullArguments;
pub use scalar_leafs::ScalarLeafs;
pub use unique_argument_names::UniqueArgumentNames;
pub use unique_fragment_names::UniqueFragmentNames;

View File

@ -0,0 +1,54 @@
use crate::registry::TypeName;
use crate::validation::context::ValidatorContext;
use crate::validation::visitor::Visitor;
use graphql_parser::query::Field;
use graphql_parser::schema::Directive;
#[derive(Default)]
pub struct ProvidedNonNullArguments;
impl<'a> Visitor<'a> for ProvidedNonNullArguments {
fn enter_directive(&mut self, ctx: &mut ValidatorContext<'a>, directive: &'a Directive) {
if let Some(schema_directive) = ctx.registry.directives.get(&directive.name) {
for arg in schema_directive.args.values() {
if TypeName::create(&arg.ty).is_non_null() {
if directive
.arguments
.iter()
.find(|(name, _)| name == arg.name)
.is_none()
{
ctx.report_error(vec![directive.position],
format!(
"Directive \"@{}\" argument \"{}\" of type \"{}\" is required but not provided",
directive.name, arg.name, arg.ty
));
}
}
}
}
}
fn enter_field(&mut self, ctx: &mut ValidatorContext<'a>, field: &'a Field) {
if let Some(parent_type) = ctx.parent_type() {
if let Some(schema_field) = parent_type.field_by_name(&field.name) {
for arg in schema_field.args.values() {
if TypeName::create(&arg.ty).is_non_null() {
if field
.arguments
.iter()
.find(|(name, _)| name == arg.name)
.is_none()
{
ctx.report_error(vec![field.position],
format!(
r#"Field "{}" argument "{}" of type "{}" is required but not provided"#,
field.name, arg.name, parent_type.name()
));
}
}
}
}
}
}
}