From 61c07b95fcac6965aa454bccf2e4020cc4875edc Mon Sep 17 00:00:00 2001 From: Georg Semmler <georg_semmler_05@web.de> Date: Thu, 15 Mar 2018 15:43:16 +0100 Subject: [PATCH] Small improvements + rustfmt --- juniper/src/executor/look_ahead.rs | 1186 +++++++++++++--------------- juniper/src/executor/mod.rs | 35 +- 2 files changed, 590 insertions(+), 631 deletions(-) diff --git a/juniper/src/executor/look_ahead.rs b/juniper/src/executor/look_ahead.rs index f5fa87fc..8c8e9159 100644 --- a/juniper/src/executor/look_ahead.rs +++ b/juniper/src/executor/look_ahead.rs @@ -34,21 +34,22 @@ impl<'a> LookAheadValue<'a> { InputValue::Boolean(b) => LookAheadValue::Boolean(b), InputValue::Enum(ref e) => LookAheadValue::Enum(e), InputValue::Variable(ref v) => Self::from_input_value(vars.get(v).unwrap(), vars), - InputValue::List(ref l) => LookAheadValue::List( - l.iter() - .map(|i| LookAheadValue::from_input_value(&i.item, vars)) - .collect(), - ), - InputValue::Object(ref o) => LookAheadValue::Object( - o.iter() - .map(|&(ref n, ref i)| { - ( - &n.item as &str, - LookAheadValue::from_input_value(&i.item, vars), - ) - }) - .collect(), - ), + InputValue::List(ref l) => { + LookAheadValue::List(l.iter() + .map(|i| { + LookAheadValue::from_input_value(&i.item, vars) + }) + .collect()) + } + InputValue::Object(ref o) => { + LookAheadValue::Object(o.iter() + .map(|&(ref n, ref i)| { + (&n.item as &str, + LookAheadValue::from_input_value(&i.item, + vars)) + }) + .collect()) + } } } } @@ -60,15 +61,18 @@ pub struct LookAheadArgument<'a> { } impl<'a> LookAheadArgument<'a> { - fn new( - &(ref name, ref value): &'a (Spanning<&'a str>, Spanning<InputValue>), - vars: &'a Variables, - ) -> Self { + pub(super) fn new(&(ref name, ref value): &'a (Spanning<&'a str>, Spanning<InputValue>), + vars: &'a Variables) + -> Self { LookAheadArgument { name: name.item, value: LookAheadValue::from_input_value(&value.item, vars), } } + + pub fn value(&'a self) -> &LookAheadValue<'a> { + &self.value + } } #[derive(Debug, Clone, PartialEq)] @@ -89,61 +93,58 @@ impl<'a> LookAheadSelection<'a> { fn should_include(directives: Option<&Vec<Spanning<Directive>>>, vars: &Variables) -> bool { directives .map(|d| { - d.iter().all(|d| { - let d = &d.item; - let arguments = &d.arguments; - match (d.name.item, arguments) { - ("include", &Some(ref a)) => a.item - .items - .iter() - .find(|item| item.0.item == "if") - .map(|&(_, ref v)| { - if let LookAheadValue::Boolean(b) = - LookAheadValue::from_input_value(&v.item, vars) - { - b - } else { - false - } - }) - .unwrap_or(false), - ("skip", &Some(ref a)) => a.item - .items - .iter() - .find(|item| item.0.item == "if") - .map(|&(_, ref v)| { - if let LookAheadValue::Boolean(b) = - LookAheadValue::from_input_value(&v.item, vars) - { - !b - } else { - false - } - }) - .unwrap_or(false), - ("skip", &None) => false, - ("include", &None) => true, - (_, _) => unreachable!(), - } - }) + d.iter() + .all(|d| { + let d = &d.item; + let arguments = &d.arguments; + match (d.name.item, arguments) { + ("include", &Some(ref a)) => { + a.item + .items + .iter() + .find(|item| item.0.item == "if") + .map(|&(_, ref v)| if let LookAheadValue::Boolean(b) = + LookAheadValue::from_input_value(&v.item, vars) { + b + } else { + false + }) + .unwrap_or(false) + } + ("skip", &Some(ref a)) => { + a.item + .items + .iter() + .find(|item| item.0.item == "if") + .map(|&(_, ref v)| if let LookAheadValue::Boolean(b) = + LookAheadValue::from_input_value(&v.item, vars) { + !b + } else { + false + }) + .unwrap_or(false) + } + ("skip", &None) => false, + ("include", &None) => true, + (_, _) => unreachable!(), + } + }) }) .unwrap_or(true) } - pub(super) fn build_from_selection( - s: &'a Selection<'a>, - vars: &'a Variables, - fragments: &'a HashMap<&'a str, &'a Fragment<'a>>, - ) -> LookAheadSelection<'a> { + pub(super) fn build_from_selection(s: &'a Selection<'a>, + vars: &'a Variables, + fragments: &'a HashMap<&'a str, &'a Fragment<'a>>) + -> LookAheadSelection<'a> { Self::build_from_selection_with_parent(s, None, vars, fragments).unwrap() } - fn build_from_selection_with_parent( - s: &'a Selection<'a>, - parent: Option<&mut Self>, - vars: &'a Variables, - fragments: &'a HashMap<&'a str, &'a Fragment<'a>>, - ) -> Option<LookAheadSelection<'a>> { + fn build_from_selection_with_parent(s: &'a Selection<'a>, + parent: Option<&mut Self>, + vars: &'a Variables, + fragments: &'a HashMap<&'a str, &'a Fragment<'a>>) + -> Option<LookAheadSelection<'a>> { let empty: &[Selection] = &[]; match *s { Selection::Field(ref field) => { @@ -159,11 +160,11 @@ impl<'a> LookAheadSelection<'a> { .as_ref() .map(|a| &a.item) .map(|a| { - a.items - .iter() - .map(|p| LookAheadArgument::new(p, vars)) - .collect() - }) + a.items + .iter() + .map(|p| LookAheadArgument::new(p, vars)) + .collect() + }) .unwrap_or_else(Vec::new); let mut ret = LookAheadSelection { name, @@ -172,25 +173,23 @@ impl<'a> LookAheadSelection<'a> { childs: Vec::new(), }; for c in field - .selection_set - .as_ref() - .map(|s| s as &[_]) - .unwrap_or_else(|| empty) - .iter() - { - let s = LookAheadSelection::build_from_selection_with_parent( - c, - Some(&mut ret), - vars, - fragments, - ); + .selection_set + .as_ref() + .map(|s| s as &[_]) + .unwrap_or_else(|| empty) + .iter() { + let s = LookAheadSelection::build_from_selection_with_parent(c, + Some(&mut ret), + vars, + fragments); assert!(s.is_none()); } if let Some(p) = parent { - p.childs.push(ChildSelection { - inner: ret, - applies_for: Applies::All, - }); + p.childs + .push(ChildSelection { + inner: ret, + applies_for: Applies::All, + }); None } else { Some(ret) @@ -204,12 +203,10 @@ impl<'a> LookAheadSelection<'a> { let parent = parent.unwrap(); let f = fragments.get(&fragment.item.name.item).unwrap(); for c in f.selection_set.iter() { - let s = LookAheadSelection::build_from_selection_with_parent( - c, - Some(parent), - vars, - fragments, - ); + let s = LookAheadSelection::build_from_selection_with_parent(c, + Some(parent), + vars, + fragments); assert!(s.is_none()); } None @@ -221,12 +218,10 @@ impl<'a> LookAheadSelection<'a> { } let parent = parent.unwrap(); for c in inline.item.selection_set.iter() { - let s = LookAheadSelection::build_from_selection_with_parent( - c, - Some(parent), - vars, - fragments, - ); + let s = LookAheadSelection::build_from_selection_with_parent(c, + Some(parent), + vars, + fragments); assert!(s.is_none()); if let Some(ref c) = inline.item.type_condition.as_ref().map(|t| t.item) { if let Some(p) = parent.childs.last_mut() { @@ -245,18 +240,26 @@ impl<'a> LookAheadSelection<'a> { childs: self.childs .iter() .filter_map(|c| match c.applies_for { - Applies::OnlyType(ref t) if *t == type_name => { - Some(c.inner.for_explicit_type(type_name)) - } - Applies::All => Some(c.inner.for_explicit_type(type_name)), - Applies::OnlyType(_) => None, - }) + Applies::OnlyType(ref t) if *t == type_name => { + Some(c.inner.for_explicit_type(type_name)) + } + Applies::All => Some(c.inner.for_explicit_type(type_name)), + Applies::OnlyType(_) => None, + }) .collect(), name: self.name, alias: self.alias, arguments: self.arguments.clone(), } } + + pub fn arguments(&self) -> &[LookAheadArgument] { + &self.arguments + } + + pub fn argument(&self, name: &str) -> Option<&LookAheadArgument> { + self.arguments.iter().find(|a| a.name == name) + } } #[derive(Debug, PartialEq)] @@ -283,7 +286,7 @@ impl<'a> LookAheadMethods for ConcreteLookAheadSelection<'a> { } fn select_child(&self, name: &str) -> Option<&Self> { - self.childs.iter().find(|c| c.name == name) + self.childs.iter().find(|c| c.name == name) } } @@ -293,7 +296,10 @@ impl<'a> LookAheadMethods for LookAheadSelection<'a> { } fn select_child(&self, name: &str) -> Option<&Self> { - self.childs.iter().find(|c| c.inner.name == name).map(|s| &s.inner) + self.childs + .iter() + .find(|c| c.inner.name == name) + .map(|s| &s.inner) } } @@ -316,49 +322,44 @@ mod tests { #[test] fn check_simple_query() { - let docs = ::parse_document_source( - " + let docs = ::parse_document_source(" query Hero { hero { id name } } -", - ).unwrap(); +") + .unwrap(); let fragments = extract_fragments(&docs); if let ::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, - ); + let look_ahead = LookAheadSelection::build_from_selection(&op.item.selection_set[0], + &vars, + &fragments); let expected = LookAheadSelection { name: "hero", alias: None, arguments: Vec::new(), - childs: vec![ - ChildSelection { - inner: LookAheadSelection { - name: "id", - alias: None, - arguments: Vec::new(), - childs: Vec::new(), - }, - applies_for: Applies::All, - }, - ChildSelection { - inner: LookAheadSelection { - name: "name", - alias: None, - arguments: Vec::new(), - childs: Vec::new(), - }, - applies_for: Applies::All, - }, - ], + childs: vec![ChildSelection { + inner: LookAheadSelection { + name: "id", + alias: None, + arguments: Vec::new(), + childs: Vec::new(), + }, + applies_for: Applies::All, + }, + ChildSelection { + inner: LookAheadSelection { + name: "name", + alias: None, + arguments: Vec::new(), + childs: Vec::new(), + }, + applies_for: Applies::All, + }], }; assert_eq!(look_ahead, expected); } else { @@ -368,49 +369,44 @@ query Hero { #[test] fn check_query_with_alias() { - let docs = ::parse_document_source( - " + let docs = ::parse_document_source(" query Hero { custom_hero: hero { id my_name: name } } -", - ).unwrap(); +") + .unwrap(); let fragments = extract_fragments(&docs); if let ::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, - ); + let look_ahead = LookAheadSelection::build_from_selection(&op.item.selection_set[0], + &vars, + &fragments); let expected = LookAheadSelection { name: "hero", alias: Some("custom_hero"), arguments: Vec::new(), - childs: vec![ - ChildSelection { - inner: LookAheadSelection { - name: "id", - alias: None, - arguments: Vec::new(), - childs: Vec::new(), - }, - applies_for: Applies::All, - }, - ChildSelection { - inner: LookAheadSelection { - name: "name", - alias: Some("my_name"), - arguments: Vec::new(), - childs: Vec::new(), - }, - applies_for: Applies::All, - }, - ], + childs: vec![ChildSelection { + inner: LookAheadSelection { + name: "id", + alias: None, + arguments: Vec::new(), + childs: Vec::new(), + }, + applies_for: Applies::All, + }, + ChildSelection { + inner: LookAheadSelection { + name: "name", + alias: Some("my_name"), + arguments: Vec::new(), + childs: Vec::new(), + }, + applies_for: Applies::All, + }], }; assert_eq!(look_ahead, expected); } else { @@ -420,8 +416,7 @@ query Hero { #[test] fn check_query_with_child() { - let docs = ::parse_document_source( - " + let docs = ::parse_document_source(" query Hero { hero { id @@ -432,69 +427,63 @@ query Hero { } } } -", - ).unwrap(); +") + .unwrap(); let fragments = extract_fragments(&docs); if let ::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, - ); + let look_ahead = LookAheadSelection::build_from_selection(&op.item.selection_set[0], + &vars, + &fragments); let expected = LookAheadSelection { name: "hero", alias: None, arguments: Vec::new(), - childs: vec![ - ChildSelection { - inner: LookAheadSelection { - name: "id", - alias: None, - arguments: Vec::new(), - childs: Vec::new(), - }, - applies_for: Applies::All, - }, - ChildSelection { - inner: LookAheadSelection { - name: "name", - alias: None, - arguments: Vec::new(), - childs: Vec::new(), - }, - applies_for: Applies::All, - }, - ChildSelection { - inner: LookAheadSelection { - name: "friends", - alias: None, - arguments: Vec::new(), - childs: vec![ - ChildSelection { - inner: LookAheadSelection { - name: "name", - alias: None, - arguments: Vec::new(), - childs: Vec::new(), - }, - applies_for: Applies::All, - }, - ChildSelection { - inner: LookAheadSelection { - name: "id", - alias: None, - arguments: Vec::new(), - childs: Vec::new(), - }, - applies_for: Applies::All, - }, - ], - }, - applies_for: Applies::All, - }, - ], + childs: vec![ChildSelection { + inner: LookAheadSelection { + name: "id", + alias: None, + arguments: Vec::new(), + childs: Vec::new(), + }, + applies_for: Applies::All, + }, + ChildSelection { + inner: LookAheadSelection { + name: "name", + alias: None, + arguments: Vec::new(), + childs: Vec::new(), + }, + applies_for: Applies::All, + }, + ChildSelection { + inner: LookAheadSelection { + name: "friends", + alias: None, + arguments: Vec::new(), + childs: vec![ChildSelection { + inner: LookAheadSelection { + name: "name", + alias: None, + arguments: Vec::new(), + childs: Vec::new(), + }, + applies_for: Applies::All, + }, + ChildSelection { + inner: LookAheadSelection { + name: "id", + alias: None, + arguments: Vec::new(), + childs: Vec::new(), + }, + applies_for: Applies::All, + }], + }, + applies_for: Applies::All, + }], }; assert_eq!(look_ahead, expected); } else { @@ -504,59 +493,50 @@ query Hero { #[test] fn check_query_with_argument() { - let docs = ::parse_document_source( - " + let docs = ::parse_document_source(" query Hero { hero(episode: EMPIRE) { id name(uppercase: true) } } -", - ).unwrap(); +") + .unwrap(); let fragments = extract_fragments(&docs); if let ::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, - ); + let look_ahead = LookAheadSelection::build_from_selection(&op.item.selection_set[0], + &vars, + &fragments); let expected = LookAheadSelection { name: "hero", alias: None, - arguments: vec![ - LookAheadArgument { - name: "episode", - value: LookAheadValue::Enum("EMPIRE"), - }, - ], - childs: vec![ - ChildSelection { - inner: LookAheadSelection { - name: "id", - alias: None, - arguments: Vec::new(), - childs: Vec::new(), - }, - applies_for: Applies::All, - }, - ChildSelection { - inner: LookAheadSelection { - name: "name", - alias: None, - arguments: vec![ - LookAheadArgument { - name: "uppercase", - value: LookAheadValue::Boolean(true), - }, - ], - childs: Vec::new(), - }, - applies_for: Applies::All, - }, - ], + arguments: vec![LookAheadArgument { + name: "episode", + value: LookAheadValue::Enum("EMPIRE"), + }], + childs: vec![ChildSelection { + inner: LookAheadSelection { + name: "id", + alias: None, + arguments: Vec::new(), + childs: Vec::new(), + }, + applies_for: Applies::All, + }, + ChildSelection { + inner: LookAheadSelection { + name: "name", + alias: None, + arguments: vec![LookAheadArgument { + name: "uppercase", + value: LookAheadValue::Boolean(true), + }], + childs: Vec::new(), + }, + applies_for: Applies::All, + }], }; assert_eq!(look_ahead, expected); } else { @@ -566,55 +546,48 @@ query Hero { #[test] fn check_query_with_variable() { - let docs = ::parse_document_source( - " + let docs = ::parse_document_source(" query Hero($episode: Episode) { hero(episode: $episode) { id name } } -", - ).unwrap(); +") + .unwrap(); let fragments = extract_fragments(&docs); if let ::ast::Definition::Operation(ref op) = docs[0] { let mut vars = Variables::default(); vars.insert("episode".into(), InputValue::Enum("JEDI".into())); - let look_ahead = LookAheadSelection::build_from_selection( - &op.item.selection_set[0], - &vars, - &fragments, - ); + let look_ahead = LookAheadSelection::build_from_selection(&op.item.selection_set[0], + &vars, + &fragments); let expected = LookAheadSelection { name: "hero", alias: None, - arguments: vec![ - LookAheadArgument { - name: "episode", - value: LookAheadValue::Enum("JEDI"), - }, - ], - childs: vec![ - ChildSelection { - inner: LookAheadSelection { - name: "id", - alias: None, - arguments: Vec::new(), - childs: Vec::new(), - }, - applies_for: Applies::All, - }, - ChildSelection { - inner: LookAheadSelection { - name: "name", - alias: None, - arguments: Vec::new(), - childs: Vec::new(), - }, - applies_for: Applies::All, - }, - ], + arguments: vec![LookAheadArgument { + name: "episode", + value: LookAheadValue::Enum("JEDI"), + }], + childs: vec![ChildSelection { + inner: LookAheadSelection { + name: "id", + alias: None, + arguments: Vec::new(), + childs: Vec::new(), + }, + applies_for: Applies::All, + }, + ChildSelection { + inner: LookAheadSelection { + name: "name", + alias: None, + arguments: Vec::new(), + childs: Vec::new(), + }, + applies_for: Applies::All, + }], }; assert_eq!(look_ahead, expected); } else { @@ -624,8 +597,7 @@ query Hero($episode: Episode) { #[test] fn check_query_with_fragment() { - let docs = ::parse_document_source( - " + let docs = ::parse_document_source(" query Hero { hero { id @@ -637,50 +609,46 @@ fragment commonFields on Character { name appearsIn } -", - ).unwrap(); +") + .unwrap(); let fragments = extract_fragments(&docs); if let ::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, - ); + let look_ahead = LookAheadSelection::build_from_selection(&op.item.selection_set[0], + &vars, + &fragments); let expected = LookAheadSelection { name: "hero", alias: None, arguments: Vec::new(), - childs: vec![ - ChildSelection { - inner: LookAheadSelection { - name: "id", - alias: None, - arguments: Vec::new(), - childs: Vec::new(), - }, - applies_for: Applies::All, - }, - ChildSelection { - inner: LookAheadSelection { - name: "name", - alias: None, - arguments: Vec::new(), - childs: Vec::new(), - }, - applies_for: Applies::All, - }, - ChildSelection { - inner: LookAheadSelection { - name: "appearsIn", - alias: None, - arguments: Vec::new(), - childs: Vec::new(), - }, - applies_for: Applies::All, - }, - ], + childs: vec![ChildSelection { + inner: LookAheadSelection { + name: "id", + alias: None, + arguments: Vec::new(), + childs: Vec::new(), + }, + applies_for: Applies::All, + }, + ChildSelection { + inner: LookAheadSelection { + name: "name", + alias: None, + arguments: Vec::new(), + childs: Vec::new(), + }, + applies_for: Applies::All, + }, + ChildSelection { + inner: LookAheadSelection { + name: "appearsIn", + alias: None, + arguments: Vec::new(), + childs: Vec::new(), + }, + applies_for: Applies::All, + }], }; assert_eq!(look_ahead, expected); } else { @@ -690,8 +658,7 @@ fragment commonFields on Character { #[test] fn check_query_with_directives() { - let docs = ::parse_document_source( - " + let docs = ::parse_document_source(" query Hero { hero { id @include(if: true) @@ -699,41 +666,37 @@ query Hero { appearsIn @skip(if: true) height @skip(if: false) } -}", - ).unwrap(); +}") + .unwrap(); let fragments = extract_fragments(&docs); if let ::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, - ); + let look_ahead = LookAheadSelection::build_from_selection(&op.item.selection_set[0], + &vars, + &fragments); let expected = LookAheadSelection { name: "hero", alias: None, arguments: Vec::new(), - childs: vec![ - ChildSelection { - inner: LookAheadSelection { - name: "id", - alias: None, - arguments: Vec::new(), - childs: Vec::new(), - }, - applies_for: Applies::All, - }, - ChildSelection { - inner: LookAheadSelection { - name: "height", - alias: None, - arguments: Vec::new(), - childs: Vec::new(), - }, - applies_for: Applies::All, - }, - ], + childs: vec![ChildSelection { + inner: LookAheadSelection { + name: "id", + alias: None, + arguments: Vec::new(), + childs: Vec::new(), + }, + applies_for: Applies::All, + }, + ChildSelection { + inner: LookAheadSelection { + name: "height", + alias: None, + arguments: Vec::new(), + childs: Vec::new(), + }, + applies_for: Applies::All, + }], }; assert_eq!(look_ahead, expected); } else { @@ -743,8 +706,7 @@ query Hero { #[test] fn check_query_with_inline_fragments() { - let docs = ::parse_document_source( - " + let docs = ::parse_document_source(" query Hero { hero { name @@ -755,50 +717,46 @@ query Hero { height } } -}", - ).unwrap(); +}") + .unwrap(); let fragments = extract_fragments(&docs); if let ::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, - ); + let look_ahead = LookAheadSelection::build_from_selection(&op.item.selection_set[0], + &vars, + &fragments); let expected = LookAheadSelection { name: "hero", alias: None, arguments: Vec::new(), - childs: vec![ - ChildSelection { - inner: LookAheadSelection { - name: "name", - alias: None, - arguments: Vec::new(), - childs: Vec::new(), - }, - applies_for: Applies::All, - }, - ChildSelection { - inner: LookAheadSelection { - name: "primaryFunction", - alias: None, - arguments: Vec::new(), - childs: Vec::new(), - }, - applies_for: Applies::OnlyType("Droid"), - }, - ChildSelection { - inner: LookAheadSelection { - name: "height", - alias: None, - arguments: Vec::new(), - childs: Vec::new(), - }, - applies_for: Applies::OnlyType("Human"), - }, - ], + childs: vec![ChildSelection { + inner: LookAheadSelection { + name: "name", + alias: None, + arguments: Vec::new(), + childs: Vec::new(), + }, + applies_for: Applies::All, + }, + ChildSelection { + inner: LookAheadSelection { + name: "primaryFunction", + alias: None, + arguments: Vec::new(), + childs: Vec::new(), + }, + applies_for: Applies::OnlyType("Droid"), + }, + ChildSelection { + inner: LookAheadSelection { + name: "height", + alias: None, + arguments: Vec::new(), + childs: Vec::new(), + }, + applies_for: Applies::OnlyType("Human"), + }], }; assert_eq!(look_ahead, expected); } else { @@ -808,8 +766,7 @@ query Hero { #[test] fn check_complex_query() { - let docs = ::parse_document_source( - " + let docs = ::parse_document_source(" query HeroNameAndFriends($id: Integer!, $withFriends: Boolean! = true) { hero(id: $id) { id @@ -827,8 +784,8 @@ fragment comparisonFields on Character { appearsIn ... on Droid { primaryFunction } ... on Human { height } -}", - ).unwrap(); +}") + .unwrap(); let fragments = extract_fragments(&docs); if let ::ast::Definition::Operation(ref op) = docs[0] { @@ -836,131 +793,123 @@ fragment comparisonFields on Character { vars.insert("id".into(), InputValue::Int(42)); // This will normally be there vars.insert("withFriends".into(), InputValue::Boolean(true)); - let look_ahead = LookAheadSelection::build_from_selection( - &op.item.selection_set[0], - &vars, - &fragments, - ); + let look_ahead = LookAheadSelection::build_from_selection(&op.item.selection_set[0], + &vars, + &fragments); let expected = LookAheadSelection { name: "hero", alias: None, - arguments: vec![ - LookAheadArgument { - name: "id", - value: LookAheadValue::Int(42), - }, - ], - childs: vec![ - ChildSelection { - inner: LookAheadSelection { - name: "id", - alias: None, - arguments: Vec::new(), - childs: Vec::new(), - }, - applies_for: Applies::All, - }, - ChildSelection { - inner: LookAheadSelection { - name: "__typename", - alias: None, - arguments: Vec::new(), - childs: Vec::new(), - }, - applies_for: Applies::All, - }, - ChildSelection { - inner: LookAheadSelection { - name: "name", - alias: None, - arguments: Vec::new(), - childs: Vec::new(), - }, - applies_for: Applies::All, - }, - ChildSelection { - inner: LookAheadSelection { - name: "appearsIn", - alias: None, - arguments: Vec::new(), - childs: Vec::new(), - }, - applies_for: Applies::All, - }, - ChildSelection { - inner: LookAheadSelection { - name: "primaryFunction", - alias: None, - arguments: Vec::new(), - childs: Vec::new(), - }, - applies_for: Applies::OnlyType("Droid"), - }, - ChildSelection { - inner: LookAheadSelection { - name: "height", - alias: None, - arguments: Vec::new(), - childs: Vec::new(), - }, - applies_for: Applies::OnlyType("Human"), - }, - ChildSelection { - inner: LookAheadSelection { - name: "friends", - alias: None, - arguments: Vec::new(), - childs: vec![ - ChildSelection { - inner: LookAheadSelection { - name: "__typename", - alias: None, - arguments: Vec::new(), - childs: Vec::new(), - }, - applies_for: Applies::All, - }, - ChildSelection { - inner: LookAheadSelection { - name: "name", - alias: None, - arguments: Vec::new(), - childs: Vec::new(), - }, - applies_for: Applies::All, - }, - ChildSelection { - inner: LookAheadSelection { - name: "appearsIn", - alias: None, - arguments: Vec::new(), - childs: Vec::new(), - }, - applies_for: Applies::All, - }, - ChildSelection { - inner: LookAheadSelection { - name: "primaryFunction", - alias: None, - arguments: Vec::new(), - childs: Vec::new(), - }, - applies_for: Applies::OnlyType("Droid"), - }, - ChildSelection { - inner: LookAheadSelection { - name: "height", - alias: None, - arguments: Vec::new(), - childs: Vec::new(), - }, - applies_for: Applies::OnlyType("Human"), - }, - ], - }, - applies_for: Applies::All, - }, - ], + arguments: vec![LookAheadArgument { + name: "id", + value: LookAheadValue::Int(42), + }], + childs: vec![ChildSelection { + inner: LookAheadSelection { + name: "id", + alias: None, + arguments: Vec::new(), + childs: Vec::new(), + }, + applies_for: Applies::All, + }, + ChildSelection { + inner: LookAheadSelection { + name: "__typename", + alias: None, + arguments: Vec::new(), + childs: Vec::new(), + }, + applies_for: Applies::All, + }, + ChildSelection { + inner: LookAheadSelection { + name: "name", + alias: None, + arguments: Vec::new(), + childs: Vec::new(), + }, + applies_for: Applies::All, + }, + ChildSelection { + inner: LookAheadSelection { + name: "appearsIn", + alias: None, + arguments: Vec::new(), + childs: Vec::new(), + }, + applies_for: Applies::All, + }, + ChildSelection { + inner: LookAheadSelection { + name: "primaryFunction", + alias: None, + arguments: Vec::new(), + childs: Vec::new(), + }, + applies_for: Applies::OnlyType("Droid"), + }, + ChildSelection { + inner: LookAheadSelection { + name: "height", + alias: None, + arguments: Vec::new(), + childs: Vec::new(), + }, + applies_for: Applies::OnlyType("Human"), + }, + ChildSelection { + inner: LookAheadSelection { + name: "friends", + alias: None, + arguments: Vec::new(), + childs: vec![ChildSelection { + inner: LookAheadSelection { + name: "__typename", + alias: None, + arguments: Vec::new(), + childs: Vec::new(), + }, + applies_for: Applies::All, + }, + ChildSelection { + inner: LookAheadSelection { + name: "name", + alias: None, + arguments: Vec::new(), + childs: Vec::new(), + }, + applies_for: Applies::All, + }, + ChildSelection { + inner: LookAheadSelection { + name: "appearsIn", + alias: None, + arguments: Vec::new(), + childs: Vec::new(), + }, + applies_for: Applies::All, + }, + ChildSelection { + inner: LookAheadSelection { + name: "primaryFunction", + alias: None, + arguments: Vec::new(), + childs: Vec::new(), + }, + applies_for: Applies::OnlyType("Droid"), + }, + ChildSelection { + inner: LookAheadSelection { + name: "height", + alias: None, + arguments: Vec::new(), + childs: Vec::new(), + }, + applies_for: Applies::OnlyType("Human"), + }], + }, + applies_for: Applies::All, + }], }; assert_eq!(look_ahead, expected); } else { @@ -970,8 +919,7 @@ fragment comparisonFields on Character { #[test] fn check_resolve_concrete_type() { - let docs = ::parse_document_source( - " + let docs = ::parse_document_source(" query Hero { hero { name @@ -982,35 +930,32 @@ query Hero { height } } -}", - ).unwrap(); +}") + .unwrap(); let fragments = extract_fragments(&docs); if let ::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, - ).for_explicit_type("Human"); + let look_ahead = LookAheadSelection::build_from_selection(&op.item.selection_set[0], + &vars, + &fragments) + .for_explicit_type("Human"); let expected = ConcreteLookAheadSelection { name: "hero", alias: None, arguments: Vec::new(), - childs: vec![ - ConcreteLookAheadSelection { - name: "name", - alias: None, - arguments: Vec::new(), - childs: Vec::new(), - }, - ConcreteLookAheadSelection { - name: "height", - alias: None, - arguments: Vec::new(), - childs: Vec::new(), - }, - ], + childs: vec![ConcreteLookAheadSelection { + name: "name", + alias: None, + arguments: Vec::new(), + childs: Vec::new(), + }, + ConcreteLookAheadSelection { + name: "height", + alias: None, + arguments: Vec::new(), + childs: Vec::new(), + }], }; assert_eq!(look_ahead, expected); } else { @@ -1020,87 +965,88 @@ query Hero { #[test] fn check_select_child() { - let lookahead = LookAheadSelection{ + let lookahead = LookAheadSelection { name: "hero", alias: None, arguments: Vec::new(), - childs: vec![ - ChildSelection{ - inner: LookAheadSelection { - name: "id", - alias: None, - arguments: Vec::new(), - childs: Vec::new(), - }, - applies_for: Applies::All, - }, - ChildSelection { - inner: LookAheadSelection { - name: "friends", - alias: None, - arguments: Vec::new(), - childs: vec![ - ChildSelection { - inner: LookAheadSelection { - name: "id", - alias: None, - arguments: Vec::new(), - childs: Vec::new(), - }, - applies_for: Applies::All - }, - ChildSelection { - inner: LookAheadSelection { - name: "name", - alias: None, - arguments: Vec::new(), - childs: Vec::new(), - }, - applies_for: Applies::All - } - ], - }, - applies_for: Applies::All - } - ] + childs: vec![ChildSelection { + inner: LookAheadSelection { + name: "id", + alias: None, + arguments: Vec::new(), + childs: Vec::new(), + }, + applies_for: Applies::All, + }, + ChildSelection { + inner: LookAheadSelection { + name: "friends", + alias: None, + arguments: Vec::new(), + childs: vec![ChildSelection { + inner: LookAheadSelection { + name: "id", + alias: None, + arguments: Vec::new(), + childs: Vec::new(), + }, + applies_for: Applies::All, + }, + ChildSelection { + inner: LookAheadSelection { + name: "name", + alias: None, + arguments: Vec::new(), + childs: Vec::new(), + }, + applies_for: Applies::All, + }], + }, + applies_for: Applies::All, + }], }; let concret_query = lookahead.for_explicit_type("does not matter"); let id = lookahead.select_child("id"); let concrete_id = concret_query.select_child("id"); - let expected = LookAheadSelection{name: "id", alias: None, arguments: Vec::new(), childs: Vec::new()}; + let expected = LookAheadSelection { + name: "id", + alias: None, + arguments: Vec::new(), + childs: Vec::new(), + }; assert_eq!(id, Some(&expected)); - assert_eq!(concrete_id, Some(&expected.for_explicit_type("does not matter"))); + assert_eq!(concrete_id, + Some(&expected.for_explicit_type("does not matter"))); let friends = lookahead.select_child("friends"); let concrete_friends = concret_query.select_child("friends"); - let expected = LookAheadSelection { - name: "friends", - alias: None, - arguments: Vec::new(), - childs: vec![ - ChildSelection { - inner: LookAheadSelection { - name: "id", - alias: None, - arguments: Vec::new(), - childs: Vec::new(), - }, - applies_for: Applies::All - }, - ChildSelection { - inner: LookAheadSelection { - name: "name", - alias: None, - arguments: Vec::new(), - childs: Vec::new(), - }, - applies_for: Applies::All - } - ], - }; + let expected = LookAheadSelection { + name: "friends", + alias: None, + arguments: Vec::new(), + childs: vec![ChildSelection { + inner: LookAheadSelection { + name: "id", + alias: None, + arguments: Vec::new(), + childs: Vec::new(), + }, + applies_for: Applies::All, + }, + ChildSelection { + inner: LookAheadSelection { + name: "name", + alias: None, + arguments: Vec::new(), + childs: Vec::new(), + }, + applies_for: Applies::All, + }], + }; assert_eq!(friends, Some(&expected)); - assert_eq!(concrete_friends, Some(&expected.for_explicit_type("does not matter"))); + assert_eq!(concrete_friends, + Some(&expected.for_explicit_type("does not matter"))); } } diff --git a/juniper/src/executor/mod.rs b/juniper/src/executor/mod.rs index b935bb50..1da04903 100644 --- a/juniper/src/executor/mod.rs +++ b/juniper/src/executor/mod.rs @@ -11,6 +11,10 @@ use ast::{Definition, Document, Fragment, FromInputValue, InputValue, OperationT use parser::SourcePosition; use value::Value; use GraphQLError; +use ast::{Definition, Document, Fragment, FromInputValue, InputValue, OperationType, + Selection, ToInputValue, Type}; +use value::Value; +use parser::SourcePosition; use schema::meta::{Argument, EnumMeta, EnumValue, Field, InputObjectMeta, InterfaceMeta, ListMeta, MetaType, NullableMeta, ObjectMeta, PlaceholderMeta, ScalarMeta, UnionMeta}; @@ -50,6 +54,7 @@ where fragments: &'a HashMap<&'a str, &'a Fragment<'a>>, variables: &'a Variables, current_selection_set: Option<&'a [Selection<'a>]>, + parent_selection_set: Option<&'a [Selection<'a>]>, current_type: TypeType<'a>, schema: &'a SchemaType<'a>, context: &'a CtxT, @@ -319,6 +324,7 @@ impl<'a, CtxT> Executor<'a, CtxT> { fragments: self.fragments, variables: self.variables, current_selection_set: self.current_selection_set, + parent_selection_set: self.parent_selection_set, current_type: self.current_type.clone(), schema: self.schema, context: ctx, @@ -340,6 +346,7 @@ impl<'a, CtxT> Executor<'a, CtxT> { fragments: self.fragments, variables: self.variables, current_selection_set: selection_set, + parent_selection_set: self.current_selection_set, current_type: self.schema.make_type( &self.current_type .innermost_concrete() @@ -351,7 +358,7 @@ impl<'a, CtxT> Executor<'a, CtxT> { context: self.context, errors: self.errors, field_path: FieldPath::Field(field_alias, location, &self.field_path), - type_name: self.type_name + type_name: self.type_name, } } @@ -365,6 +372,7 @@ impl<'a, CtxT> Executor<'a, CtxT> { fragments: self.fragments, variables: self.variables, current_selection_set: selection_set, + parent_selection_set: self.current_selection_set, current_type: match type_name { Some(type_name) => self.schema.type_by_name(type_name).expect("Type not found"), None => self.current_type.clone(), @@ -430,16 +438,20 @@ impl<'a, CtxT> Executor<'a, CtxT> { }); } - pub fn look_ahead(&self) -> LookAheadSelection { - LookAheadSelection{ - name: self.type_name, - alias: None, - arguments: Vec::new(), - childs: self.current_selection_set.map(|s| s.iter().map(|s| ChildSelection { - inner: LookAheadSelection::build_from_selection(s, self.variables, self.fragments), - applies_for: Applies::All - }).collect()).unwrap_or_else(Vec::new) - } + pub fn look_ahead(&'a self) -> LookAheadSelection<'a> { + self.parent_selection_set.map(|p| { + LookAheadSelection::build_from_selection(&p[0], self.variables, self.fragments) + }).unwrap_or_else(||{ + LookAheadSelection{ + name: self.current_type.innermost_concrete().name().unwrap_or(""), + alias: None, + arguments: Vec::new(), + childs: self.current_selection_set.map(|s| s.iter().map(|s| ChildSelection { + inner: LookAheadSelection::build_from_selection(s, self.variables, self.fragments), + applies_for: Applies::All + }).collect()).unwrap_or_else(Vec::new) + } + }) } } @@ -568,6 +580,7 @@ where .collect(), variables: final_vars, current_selection_set: Some(&op.item.selection_set[..]), + parent_selection_set: None, current_type: root_type, schema: &root_node.schema, context: context,