Improve visitability of lookahead types. (#431)
I've added methods which allow Juniper users to visit all nodes of a lookahead tree so that they can be used for query generation.
This commit is contained in:
parent
b61aa900b1
commit
5be66654a9
2 changed files with 105 additions and 5 deletions
|
@ -1,10 +1,11 @@
|
|||
# master
|
||||
|
||||
- Add ability to parse 'subscription'
|
||||
- Improve lookahead visitability.
|
||||
- Add ability to parse 'subscription'.
|
||||
|
||||
# [[0.13.1] 2019-07-29](https://github.com/graphql-rust/juniper/releases/tag/juniper-0.13.1)
|
||||
|
||||
- Fix a regression when using lookaheads with fragments containing nested types [#404](https://github.com/graphql-rust/juniper/pull/404)
|
||||
- Fix a regression when using lookaheads with fragments containing nested types [#404](https://github.com/graphql-rust/juniper/pull/404)
|
||||
|
||||
- Allow `mut` arguments for resolver functions in `#[object]` macros [#402](https://github.com/graphql-rust/juniper/pull/402)
|
||||
|
||||
|
@ -15,7 +16,7 @@
|
|||
See [#345](https://github.com/graphql-rust/juniper/pull/345).
|
||||
|
||||
The newtype pattern can now be used with the `GraphQLScalarValue` custom derive
|
||||
to easily implement custom scalar values that just wrap another scalar,
|
||||
to easily implement custom scalar values that just wrap another scalar,
|
||||
similar to serdes `#[serde(transparent)]` functionality.
|
||||
|
||||
Example:
|
||||
|
@ -34,7 +35,7 @@ struct UserId(i32);
|
|||
|
||||
### object macro
|
||||
|
||||
The `graphql_object!` macro is deprecated and will be removed in the future.
|
||||
The `graphql_object!` macro is deprecated and will be removed in the future.
|
||||
It is replaced by the new [object](https://docs.rs/juniper/latest/juniper/macro.object.html) procedural macro.
|
||||
|
||||
[#333](https://github.com/graphql-rust/juniper/pull/333)
|
||||
|
@ -53,7 +54,7 @@ This should not have any impact on your code, since juniper already was 2018 com
|
|||
- The `GraphQLType` impl for () was removed to improve compile time safefty. [#355](https://github.com/graphql-rust/juniper/pull/355)
|
||||
- The `ScalarValue` custom derive has been renamed to `GraphQLScalarValue`.
|
||||
- Added built-in support for the canonical schema introspection query via
|
||||
`juniper::introspect()`.
|
||||
`juniper::introspect()`.
|
||||
[#307](https://github.com/graphql-rust/juniper/issues/307)
|
||||
- Fix introspection query validity
|
||||
The DirectiveLocation::InlineFragment had an invalid literal value,
|
||||
|
|
|
@ -88,6 +88,11 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
/// The argument's name
|
||||
pub fn name(&'a self) -> &str {
|
||||
&self.name
|
||||
}
|
||||
|
||||
/// The value of the argument
|
||||
pub fn value(&'a self) -> &LookAheadValue<'a, S> {
|
||||
&self.value
|
||||
|
@ -347,6 +352,12 @@ pub trait LookAheadMethods<S> {
|
|||
self.select_child(name).is_some()
|
||||
}
|
||||
|
||||
/// Does the current node have any arguments?
|
||||
fn has_arguments(&self) -> bool;
|
||||
|
||||
/// Does the current node have any children?
|
||||
fn has_children(&self) -> bool;
|
||||
|
||||
/// Get the top level arguments for the current selection
|
||||
fn arguments(&self) -> &[LookAheadArgument<S>];
|
||||
|
||||
|
@ -354,6 +365,9 @@ pub trait LookAheadMethods<S> {
|
|||
fn argument(&self, name: &str) -> Option<&LookAheadArgument<S>> {
|
||||
self.arguments().iter().find(|a| a.name == name)
|
||||
}
|
||||
|
||||
/// Get the top level children for the current selection
|
||||
fn child_names(&self) -> Vec<&str>;
|
||||
}
|
||||
|
||||
impl<'a, S> LookAheadMethods<S> for ConcreteLookAheadSelection<'a, S> {
|
||||
|
@ -368,6 +382,21 @@ impl<'a, S> LookAheadMethods<S> for ConcreteLookAheadSelection<'a, S> {
|
|||
fn arguments(&self) -> &[LookAheadArgument<S>] {
|
||||
&self.arguments
|
||||
}
|
||||
|
||||
fn child_names(&self) -> Vec<&str> {
|
||||
self.children
|
||||
.iter()
|
||||
.map(|c| c.alias.unwrap_or(c.name))
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn has_arguments(&self) -> bool {
|
||||
!self.arguments.is_empty()
|
||||
}
|
||||
|
||||
fn has_children(&self) -> bool {
|
||||
!self.children.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, S> LookAheadMethods<S> for LookAheadSelection<'a, S> {
|
||||
|
@ -385,6 +414,21 @@ impl<'a, S> LookAheadMethods<S> for LookAheadSelection<'a, S> {
|
|||
fn arguments(&self) -> &[LookAheadArgument<S>] {
|
||||
&self.arguments
|
||||
}
|
||||
|
||||
fn child_names(&self) -> Vec<&str> {
|
||||
self.children
|
||||
.iter()
|
||||
.map(|c| c.inner.alias.unwrap_or(c.inner.name))
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn has_arguments(&self) -> bool {
|
||||
!self.arguments.is_empty()
|
||||
}
|
||||
|
||||
fn has_children(&self) -> bool {
|
||||
!self.children.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -1399,4 +1443,59 @@ fragment heroFriendNames on Hero {
|
|||
panic!("No Operation found");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_visitability() {
|
||||
let docs = parse_document_source::<DefaultScalarValue>(
|
||||
"
|
||||
query Hero {
|
||||
hero(episode: EMPIRE) {
|
||||
name
|
||||
friends {
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
",
|
||||
)
|
||||
.unwrap();
|
||||
let fragments = extract_fragments(&docs);
|
||||
|
||||
if let crate::ast::Definition::Operation(ref op) = docs[0] {
|
||||
let vars = Variables::default();
|
||||
let look_ahead = LookAheadSelection::build_from_selection(
|
||||
&op.item.selection_set[0],
|
||||
&vars,
|
||||
&fragments,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(look_ahead.field_name(), "hero");
|
||||
|
||||
assert!(look_ahead.has_arguments());
|
||||
let args = look_ahead.arguments();
|
||||
assert_eq!(args[0].name(), "episode");
|
||||
assert_eq!(args[0].value(), &LookAheadValue::Enum("EMPIRE"));
|
||||
|
||||
assert!(look_ahead.has_children());
|
||||
assert_eq!(look_ahead.child_names(), vec!["name", "friends"]);
|
||||
|
||||
let child0 = look_ahead.select_child("name").unwrap();
|
||||
assert_eq!(child0.field_name(), "name");
|
||||
assert!(!child0.has_arguments());
|
||||
assert!(!child0.has_children());
|
||||
|
||||
let child1 = look_ahead.select_child("friends").unwrap();
|
||||
assert_eq!(child1.field_name(), "friends");
|
||||
assert!(!child1.has_arguments());
|
||||
assert!(child1.has_children());
|
||||
assert_eq!(child1.child_names(), vec!["name"]);
|
||||
|
||||
let child2 = child1.select_child("name").unwrap();
|
||||
assert!(!child2.has_arguments());
|
||||
assert!(!child2.has_children());
|
||||
} else {
|
||||
panic!("No Operation found");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue