parent
d0fc062892
commit
e75cf26995
7 changed files with 127 additions and 55 deletions
|
@ -54,6 +54,7 @@ All user visible changes to `juniper` crate will be documented in this file. Thi
|
||||||
- Upgraded [GraphiQL] to 3.0.9 version (requires new [`graphql-transport-ws` GraphQL over WebSocket Protocol] integration on server, see `juniper_warp/examples/subscription.rs`). ([#1188], [#1193], [#1204])
|
- Upgraded [GraphiQL] to 3.0.9 version (requires new [`graphql-transport-ws` GraphQL over WebSocket Protocol] integration on server, see `juniper_warp/examples/subscription.rs`). ([#1188], [#1193], [#1204])
|
||||||
- Made `LookAheadMethods::children()` method to return slice instead of `Vec`. ([#1200])
|
- Made `LookAheadMethods::children()` method to return slice instead of `Vec`. ([#1200])
|
||||||
- Abstracted `Spanning::start` and `Spanning::end` fields into separate struct `Span`. ([#1207], [#1208])
|
- Abstracted `Spanning::start` and `Spanning::end` fields into separate struct `Span`. ([#1207], [#1208])
|
||||||
|
- Added `Span` to `Arguments` and `LookAheadArguments`. ([#1206], [#1209])
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
|
@ -132,8 +133,10 @@ All user visible changes to `juniper` crate will be documented in this file. Thi
|
||||||
[#1199]: /../../pull/1199
|
[#1199]: /../../pull/1199
|
||||||
[#1200]: /../../pull/1200
|
[#1200]: /../../pull/1200
|
||||||
[#1204]: /../../pull/1204
|
[#1204]: /../../pull/1204
|
||||||
|
[#1206]: /../../pull/1206
|
||||||
[#1207]: /../../pull/1207
|
[#1207]: /../../pull/1207
|
||||||
[#1208]: /../../pull/1208
|
[#1208]: /../../pull/1208
|
||||||
|
[#1209]: /../../pull/1209
|
||||||
[ba1ed85b]: /../../commit/ba1ed85b3c3dd77fbae7baf6bc4e693321a94083
|
[ba1ed85b]: /../../commit/ba1ed85b3c3dd77fbae7baf6bc4e693321a94083
|
||||||
[CVE-2022-31173]: /../../security/advisories/GHSA-4rx6-g5vg-5f3j
|
[CVE-2022-31173]: /../../security/advisories/GHSA-4rx6-g5vg-5f3j
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ use std::collections::HashMap;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ast::{Directive, Fragment, InputValue, Selection},
|
ast::{Directive, Fragment, InputValue, Selection},
|
||||||
parser::Spanning,
|
parser::{Span, Spanning},
|
||||||
value::ScalarValue,
|
value::ScalarValue,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -18,48 +18,71 @@ pub enum Applies<'a> {
|
||||||
OnlyType(&'a str),
|
OnlyType(&'a str),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A JSON-like value that can is used as argument in the query execution
|
/// Shortcut for a [`Spanning`] containing a borrowed [`Span`].
|
||||||
|
type BorrowedSpanning<'a, T> = Spanning<T, &'a Span>;
|
||||||
|
|
||||||
|
/// JSON-like value that can be used as an argument in the query execution.
|
||||||
///
|
///
|
||||||
/// In contrast to `InputValue` these values do only contain constants,
|
/// In contrast to an [`InputValue`], these values do only contain constants,
|
||||||
/// meaning that variables are already resolved.
|
/// meaning that variables are already resolved.
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
pub enum LookAheadValue<'a, S: 'a> {
|
pub enum LookAheadValue<'a, S: 'a> {
|
||||||
Null,
|
Null,
|
||||||
Scalar(&'a S),
|
Scalar(&'a S),
|
||||||
Enum(&'a str),
|
Enum(&'a str),
|
||||||
List(Vec<LookAheadValue<'a, S>>),
|
List(Vec<BorrowedSpanning<'a, LookAheadValue<'a, S>>>),
|
||||||
Object(Vec<(&'a str, LookAheadValue<'a, S>)>),
|
Object(
|
||||||
|
Vec<(
|
||||||
|
BorrowedSpanning<'a, &'a str>,
|
||||||
|
BorrowedSpanning<'a, LookAheadValue<'a, S>>,
|
||||||
|
)>,
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, S> LookAheadValue<'a, S>
|
impl<'a, S> LookAheadValue<'a, S>
|
||||||
where
|
where
|
||||||
S: ScalarValue,
|
S: ScalarValue,
|
||||||
{
|
{
|
||||||
fn from_input_value(input_value: &'a InputValue<S>, vars: &'a Variables<S>) -> Self {
|
fn from_input_value(
|
||||||
match *input_value {
|
input_value: BorrowedSpanning<'a, &'a InputValue<S>>,
|
||||||
InputValue::Null => LookAheadValue::Null,
|
vars: &'a Variables<S>,
|
||||||
InputValue::Scalar(ref s) => LookAheadValue::Scalar(s),
|
) -> BorrowedSpanning<'a, Self> {
|
||||||
InputValue::Enum(ref e) => LookAheadValue::Enum(e),
|
Spanning {
|
||||||
InputValue::Variable(ref name) => vars
|
span: input_value.span,
|
||||||
.get(name)
|
item: match input_value.item {
|
||||||
.map(|v| Self::from_input_value(v, vars))
|
InputValue::Null => Self::Null,
|
||||||
.unwrap_or(LookAheadValue::Null),
|
InputValue::Scalar(s) => Self::Scalar(s),
|
||||||
InputValue::List(ref l) => LookAheadValue::List(
|
InputValue::Enum(e) => Self::Enum(e),
|
||||||
l.iter()
|
InputValue::Variable(name) => vars
|
||||||
.map(|i| LookAheadValue::from_input_value(&i.item, vars))
|
.get(name)
|
||||||
.collect(),
|
.map(|item| {
|
||||||
),
|
let input_value = Spanning {
|
||||||
InputValue::Object(ref o) => LookAheadValue::Object(
|
span: input_value.span,
|
||||||
o.iter()
|
item,
|
||||||
.map(|(n, i)| {
|
};
|
||||||
(
|
Self::from_input_value(input_value, vars).item
|
||||||
&n.item as &str,
|
|
||||||
LookAheadValue::from_input_value(&i.item, vars),
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
.collect(),
|
.unwrap_or(Self::Null),
|
||||||
),
|
InputValue::List(l) => Self::List(
|
||||||
|
l.iter()
|
||||||
|
.map(|i| Self::from_input_value(i.as_ref(), vars))
|
||||||
|
.collect(),
|
||||||
|
),
|
||||||
|
InputValue::Object(o) => Self::Object(
|
||||||
|
o.iter()
|
||||||
|
.map(|(n, i)| {
|
||||||
|
(
|
||||||
|
Spanning {
|
||||||
|
span: &n.span,
|
||||||
|
item: n.item.as_str(),
|
||||||
|
},
|
||||||
|
Self::from_input_value(i.as_ref(), vars),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -68,7 +91,7 @@ where
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct LookAheadArgument<'a, S: 'a> {
|
pub struct LookAheadArgument<'a, S: 'a> {
|
||||||
name: &'a str,
|
name: &'a str,
|
||||||
value: LookAheadValue<'a, S>,
|
value: BorrowedSpanning<'a, LookAheadValue<'a, S>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, S> LookAheadArgument<'a, S>
|
impl<'a, S> LookAheadArgument<'a, S>
|
||||||
|
@ -81,7 +104,7 @@ where
|
||||||
) -> Self {
|
) -> Self {
|
||||||
LookAheadArgument {
|
LookAheadArgument {
|
||||||
name: name.item,
|
name: name.item,
|
||||||
value: LookAheadValue::from_input_value(&value.item, vars),
|
value: LookAheadValue::from_input_value(value.as_ref(), vars),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,7 +115,12 @@ where
|
||||||
|
|
||||||
/// The value of the argument
|
/// The value of the argument
|
||||||
pub fn value(&'a self) -> &LookAheadValue<'a, S> {
|
pub fn value(&'a self) -> &LookAheadValue<'a, S> {
|
||||||
&self.value
|
&self.value.item
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The input source span of the argument
|
||||||
|
pub fn span(&self) -> &Span {
|
||||||
|
self.value.span
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,7 +173,7 @@ where
|
||||||
.find(|item| item.0.item == "if")
|
.find(|item| item.0.item == "if")
|
||||||
.map(|(_, v)| {
|
.map(|(_, v)| {
|
||||||
if let LookAheadValue::Scalar(s) =
|
if let LookAheadValue::Scalar(s) =
|
||||||
LookAheadValue::from_input_value(&v.item, vars)
|
LookAheadValue::from_input_value(v.as_ref(), vars).item
|
||||||
{
|
{
|
||||||
s.as_bool().unwrap_or(false)
|
s.as_bool().unwrap_or(false)
|
||||||
} else {
|
} else {
|
||||||
|
@ -160,7 +188,7 @@ where
|
||||||
.find(|item| item.0.item == "if")
|
.find(|item| item.0.item == "if")
|
||||||
.map(|(_, v)| {
|
.map(|(_, v)| {
|
||||||
if let LookAheadValue::Scalar(b) =
|
if let LookAheadValue::Scalar(b) =
|
||||||
LookAheadValue::from_input_value(&v.item, vars)
|
LookAheadValue::from_input_value(v.as_ref(), vars).item
|
||||||
{
|
{
|
||||||
b.as_bool().map(::std::ops::Not::not).unwrap_or(false)
|
b.as_bool().map(::std::ops::Not::not).unwrap_or(false)
|
||||||
} else {
|
} else {
|
||||||
|
@ -472,12 +500,12 @@ impl<'a, S> LookAheadMethods<'a, S> for LookAheadSelection<'a, S> {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::collections::HashMap;
|
use std::{collections::HashMap, ops::Range};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ast::{Document, OwnedDocument},
|
ast::{Document, OwnedDocument},
|
||||||
graphql_vars,
|
graphql_vars,
|
||||||
parser::UnlocatedParseResult,
|
parser::{SourcePosition, UnlocatedParseResult},
|
||||||
schema::model::SchemaType,
|
schema::model::SchemaType,
|
||||||
validation::test_harness::{MutationRoot, QueryRoot, SubscriptionRoot},
|
validation::test_harness::{MutationRoot, QueryRoot, SubscriptionRoot},
|
||||||
value::{DefaultScalarValue, ScalarValue},
|
value::{DefaultScalarValue, ScalarValue},
|
||||||
|
@ -509,6 +537,13 @@ mod tests {
|
||||||
fragments
|
fragments
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn span(range: Range<(usize, usize, usize)>) -> Span {
|
||||||
|
Span {
|
||||||
|
start: SourcePosition::new(range.start.0, range.start.1, range.start.2),
|
||||||
|
end: SourcePosition::new(range.end.0, range.end.1, range.end.2),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn check_simple_query() {
|
fn check_simple_query() {
|
||||||
let docs = parse_document_source::<DefaultScalarValue>(
|
let docs = parse_document_source::<DefaultScalarValue>(
|
||||||
|
@ -711,12 +746,17 @@ query Hero {
|
||||||
&fragments,
|
&fragments,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
let span0 = span((32, 2, 18)..(38, 2, 24));
|
||||||
|
let span1 = span((77, 4, 24)..(81, 4, 28));
|
||||||
let expected = LookAheadSelection {
|
let expected = LookAheadSelection {
|
||||||
name: "hero",
|
name: "hero",
|
||||||
alias: None,
|
alias: None,
|
||||||
arguments: vec![LookAheadArgument {
|
arguments: vec![LookAheadArgument {
|
||||||
name: "episode",
|
name: "episode",
|
||||||
value: LookAheadValue::Enum("EMPIRE"),
|
value: Spanning {
|
||||||
|
item: LookAheadValue::Enum("EMPIRE"),
|
||||||
|
span: &span0,
|
||||||
|
},
|
||||||
}],
|
}],
|
||||||
applies_for: Applies::All,
|
applies_for: Applies::All,
|
||||||
children: vec![
|
children: vec![
|
||||||
|
@ -732,7 +772,10 @@ query Hero {
|
||||||
alias: None,
|
alias: None,
|
||||||
arguments: vec![LookAheadArgument {
|
arguments: vec![LookAheadArgument {
|
||||||
name: "uppercase",
|
name: "uppercase",
|
||||||
value: LookAheadValue::Scalar(&DefaultScalarValue::Boolean(true)),
|
value: Spanning {
|
||||||
|
item: LookAheadValue::Scalar(&DefaultScalarValue::Boolean(true)),
|
||||||
|
span: &span1,
|
||||||
|
},
|
||||||
}],
|
}],
|
||||||
children: Vec::new(),
|
children: Vec::new(),
|
||||||
applies_for: Applies::All,
|
applies_for: Applies::All,
|
||||||
|
@ -768,12 +811,16 @@ query Hero($episode: Episode) {
|
||||||
&fragments,
|
&fragments,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
let span0 = span((51, 2, 18)..(59, 2, 26));
|
||||||
let expected = LookAheadSelection {
|
let expected = LookAheadSelection {
|
||||||
name: "hero",
|
name: "hero",
|
||||||
alias: None,
|
alias: None,
|
||||||
arguments: vec![LookAheadArgument {
|
arguments: vec![LookAheadArgument {
|
||||||
name: "episode",
|
name: "episode",
|
||||||
value: LookAheadValue::Enum("JEDI"),
|
value: Spanning {
|
||||||
|
item: LookAheadValue::Enum("JEDI"),
|
||||||
|
span: &span0,
|
||||||
|
},
|
||||||
}],
|
}],
|
||||||
applies_for: Applies::All,
|
applies_for: Applies::All,
|
||||||
children: vec![
|
children: vec![
|
||||||
|
@ -821,12 +868,16 @@ query Hero($episode: Episode) {
|
||||||
&fragments,
|
&fragments,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
let span0 = span((51, 2, 18)..(59, 2, 26));
|
||||||
let expected = LookAheadSelection {
|
let expected = LookAheadSelection {
|
||||||
name: "hero",
|
name: "hero",
|
||||||
alias: None,
|
alias: None,
|
||||||
arguments: vec![LookAheadArgument {
|
arguments: vec![LookAheadArgument {
|
||||||
name: "episode",
|
name: "episode",
|
||||||
value: LookAheadValue::Null,
|
value: Spanning {
|
||||||
|
item: LookAheadValue::Null,
|
||||||
|
span: &span0,
|
||||||
|
},
|
||||||
}],
|
}],
|
||||||
applies_for: Applies::All,
|
applies_for: Applies::All,
|
||||||
children: vec![LookAheadSelection {
|
children: vec![LookAheadSelection {
|
||||||
|
@ -1121,12 +1172,16 @@ fragment comparisonFields on Character {
|
||||||
&fragments,
|
&fragments,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
let span0 = span((85, 2, 11)..(88, 2, 14));
|
||||||
let expected = LookAheadSelection {
|
let expected = LookAheadSelection {
|
||||||
name: "hero",
|
name: "hero",
|
||||||
alias: None,
|
alias: None,
|
||||||
arguments: vec![LookAheadArgument {
|
arguments: vec![LookAheadArgument {
|
||||||
name: "id",
|
name: "id",
|
||||||
value: LookAheadValue::Scalar(&DefaultScalarValue::Int(42)),
|
value: Spanning {
|
||||||
|
item: LookAheadValue::Scalar(&DefaultScalarValue::Int(42)),
|
||||||
|
span: &span0,
|
||||||
|
},
|
||||||
}],
|
}],
|
||||||
applies_for: Applies::All,
|
applies_for: Applies::All,
|
||||||
children: vec![
|
children: vec![
|
||||||
|
|
|
@ -52,15 +52,15 @@ impl Span {
|
||||||
|
|
||||||
/// Data structure used to wrap items into a [`Span`].
|
/// Data structure used to wrap items into a [`Span`].
|
||||||
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
|
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
|
||||||
pub struct Spanning<T> {
|
pub struct Spanning<T, Sp = Span> {
|
||||||
/// Wrapped item.
|
/// Wrapped item.
|
||||||
pub item: T,
|
pub item: T,
|
||||||
|
|
||||||
/// [`Span`] of the wrapped item.
|
/// [`Span`] of the wrapped item.
|
||||||
pub span: Span,
|
pub span: Sp,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Spanning<T> {
|
impl<T> Spanning<T, Span> {
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub fn new(span: Span, item: T) -> Self {
|
pub fn new(span: Span, item: T) -> Self {
|
||||||
Self { item, span }
|
Self { item, span }
|
||||||
|
@ -126,6 +126,14 @@ impl<T> Spanning<T> {
|
||||||
pub fn and_then<O, F: Fn(T) -> Option<O>>(self, f: F) -> Option<Spanning<O>> {
|
pub fn and_then<O, F: Fn(T) -> Option<O>>(self, f: F) -> Option<Spanning<O>> {
|
||||||
f(self.item).map(|item| Spanning::new(self.span, item))
|
f(self.item).map(|item| Spanning::new(self.span, item))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Converts into a [`Spanning`] containing a borrowed item and a borrowed [`Span`].
|
||||||
|
pub(crate) fn as_ref(&self) -> Spanning<&'_ T, &'_ Span> {
|
||||||
|
Spanning {
|
||||||
|
item: &self.item,
|
||||||
|
span: &self.span,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: fmt::Display> fmt::Display for Spanning<T> {
|
impl<T: fmt::Display> fmt::Display for Spanning<T> {
|
||||||
|
|
|
@ -244,7 +244,8 @@ where
|
||||||
m.item
|
m.item
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|(k, v)| {
|
.filter_map(|(k, v)| {
|
||||||
v.item.clone().into_const(exec_vars).map(|v| (k.item, v))
|
let val = v.item.clone().into_const(exec_vars)?;
|
||||||
|
Some((k.item, Spanning::new(v.span, val)))
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -68,13 +68,13 @@ pub enum TypeKind {
|
||||||
/// Field argument container
|
/// Field argument container
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Arguments<'a, S = DefaultScalarValue> {
|
pub struct Arguments<'a, S = DefaultScalarValue> {
|
||||||
args: Option<IndexMap<&'a str, InputValue<S>>>,
|
args: Option<IndexMap<&'a str, Spanning<InputValue<S>>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, S> Arguments<'a, S> {
|
impl<'a, S> Arguments<'a, S> {
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub fn new(
|
pub fn new(
|
||||||
mut args: Option<IndexMap<&'a str, InputValue<S>>>,
|
mut args: Option<IndexMap<&'a str, Spanning<InputValue<S>>>>,
|
||||||
meta_args: &'a Option<Vec<Argument<S>>>,
|
meta_args: &'a Option<Vec<Argument<S>>>,
|
||||||
) -> Self
|
) -> Self
|
||||||
where
|
where
|
||||||
|
@ -89,7 +89,7 @@ impl<'a, S> Arguments<'a, S> {
|
||||||
let arg_name = arg.name.as_str();
|
let arg_name = arg.name.as_str();
|
||||||
if args.get(arg_name).is_none() {
|
if args.get(arg_name).is_none() {
|
||||||
if let Some(val) = arg.default_value.as_ref() {
|
if let Some(val) = arg.default_value.as_ref() {
|
||||||
args.insert(arg_name, val.clone());
|
args.insert(arg_name, Spanning::unlocated(val.clone()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -117,10 +117,16 @@ impl<'a, S> Arguments<'a, S> {
|
||||||
self.args
|
self.args
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|args| args.get(name))
|
.and_then(|args| args.get(name))
|
||||||
|
.map(|spanning| &spanning.item)
|
||||||
.map(InputValue::convert)
|
.map(InputValue::convert)
|
||||||
.transpose()
|
.transpose()
|
||||||
.map_err(IntoFieldError::into_field_error)
|
.map_err(IntoFieldError::into_field_error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Gets a direct reference to the [`Spanning`] argument [`InputValue`].
|
||||||
|
pub fn get_input_value(&self, name: &str) -> Option<&Spanning<InputValue<S>>> {
|
||||||
|
self.args.as_ref().and_then(|args| args.get(name))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Primary trait used to resolve GraphQL values.
|
/// Primary trait used to resolve GraphQL values.
|
||||||
|
@ -472,7 +478,8 @@ where
|
||||||
m.item
|
m.item
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|(k, v)| {
|
.filter_map(|(k, v)| {
|
||||||
v.item.clone().into_const(exec_vars).map(|v| (k.item, v))
|
let val = v.item.clone().into_const(exec_vars)?;
|
||||||
|
Some((k.item, Spanning::new(v.span, val)))
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -316,7 +316,8 @@ where
|
||||||
m.item
|
m.item
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|(k, v)| {
|
.filter_map(|(k, v)| {
|
||||||
v.item.clone().into_const(exec_vars).map(|v| (k.item, v))
|
let val = v.item.clone().into_const(exec_vars)?;
|
||||||
|
Some((k.item, Spanning::new(v.span, val)))
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -72,11 +72,8 @@ where
|
||||||
let mut remaining_required_fields = input_fields
|
let mut remaining_required_fields = input_fields
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|f| {
|
.filter_map(|f| {
|
||||||
if f.arg_type.is_non_null() && f.default_value.is_none() {
|
(f.arg_type.is_non_null() && f.default_value.is_none())
|
||||||
Some(&f.name)
|
.then_some(&f.name)
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.collect::<HashSet<_>>();
|
.collect::<HashSet<_>>();
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue