From 853c92a0b7d2b17375134fe7b879acc59d89337c Mon Sep 17 00:00:00 2001 From: Magnus Hallin <mhallin@fastmail.com> Date: Wed, 28 Dec 2016 18:54:09 +0100 Subject: [PATCH] Use borrowed string references in all AST nodes --- src/ast.rs | 78 +++++++++---------- src/executor.rs | 6 +- src/parser/document.rs | 44 +++++------ src/parser/tests/document.rs | 8 +- src/types/base.rs | 18 ++--- src/validation/context.rs | 6 +- src/validation/input_value.rs | 4 +- src/validation/multi_visitor.rs | 8 +- .../rules/arguments_of_correct_type.rs | 2 +- .../rules/default_values_of_correct_type.rs | 2 +- src/validation/rules/known_argument_names.rs | 2 +- src/validation/rules/known_type_names.rs | 2 +- src/validation/rules/no_fragment_cycles.rs | 2 +- .../rules/no_undefined_variables.rs | 6 +- src/validation/rules/no_unused_fragments.rs | 2 +- src/validation/rules/no_unused_variables.rs | 12 +-- .../rules/overlapping_fields_can_be_merged.rs | 8 +- .../rules/possible_fragment_spreads.rs | 2 +- src/validation/rules/unique_argument_names.rs | 2 +- src/validation/rules/unique_variable_names.rs | 2 +- .../rules/variables_are_input_types.rs | 2 +- .../rules/variables_in_allowed_position.rs | 8 +- src/validation/test_harness.rs | 10 +-- src/validation/traits.rs | 8 +- src/validation/visitor.rs | 4 +- 25 files changed, 121 insertions(+), 127 deletions(-) diff --git a/src/ast.rs b/src/ast.rs index 908e910b..8d96b9ba 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -55,35 +55,35 @@ pub struct VariableDefinition<'a> { } #[derive(Clone, PartialEq, Debug)] -pub struct Arguments { - pub items: Vec<(Spanning<String>, Spanning<InputValue>)>, +pub struct Arguments<'a> { + pub items: Vec<(Spanning<&'a str>, Spanning<InputValue>)>, } #[derive(Clone, PartialEq, Debug)] pub struct VariableDefinitions<'a> { - pub items: Vec<(Spanning<String>, VariableDefinition<'a>)>, + pub items: Vec<(Spanning<&'a str>, VariableDefinition<'a>)>, } #[derive(Clone, PartialEq, Debug)] -pub struct Field { - pub alias: Option<Spanning<String>>, - pub name: Spanning<String>, - pub arguments: Option<Spanning<Arguments>>, - pub directives: Option<Vec<Spanning<Directive>>>, - pub selection_set: Option<Vec<Selection>>, +pub struct Field<'a> { + pub alias: Option<Spanning<&'a str>>, + pub name: Spanning<&'a str>, + pub arguments: Option<Spanning<Arguments<'a>>>, + pub directives: Option<Vec<Spanning<Directive<'a>>>>, + pub selection_set: Option<Vec<Selection<'a>>>, } #[derive(Clone, PartialEq, Debug)] -pub struct FragmentSpread { - pub name: Spanning<String>, - pub directives: Option<Vec<Spanning<Directive>>>, +pub struct FragmentSpread<'a> { + pub name: Spanning<&'a str>, + pub directives: Option<Vec<Spanning<Directive<'a>>>>, } #[derive(Clone, PartialEq, Debug)] -pub struct InlineFragment { - pub type_condition: Option<Spanning<String>>, - pub directives: Option<Vec<Spanning<Directive>>>, - pub selection_set: Vec<Selection>, +pub struct InlineFragment<'a> { + pub type_condition: Option<Spanning<&'a str>>, + pub directives: Option<Vec<Spanning<Directive<'a>>>>, + pub selection_set: Vec<Selection<'a>>, } /// Entry in a GraphQL selection set @@ -103,16 +103,16 @@ pub struct InlineFragment { /// ``` #[derive(Clone, PartialEq, Debug)] #[allow(missing_docs)] -pub enum Selection { - Field(Spanning<Field>), - FragmentSpread(Spanning<FragmentSpread>), - InlineFragment(Spanning<InlineFragment>), +pub enum Selection<'a> { + Field(Spanning<Field<'a>>), + FragmentSpread(Spanning<FragmentSpread<'a>>), + InlineFragment(Spanning<InlineFragment<'a>>), } #[derive(Clone, PartialEq, Debug)] -pub struct Directive { - pub name: Spanning<String>, - pub arguments: Option<Spanning<Arguments>>, +pub struct Directive<'a> { + pub name: Spanning<&'a str>, + pub arguments: Option<Spanning<Arguments<'a>>>, } #[derive(Clone, PartialEq, Debug)] @@ -124,24 +124,24 @@ pub enum OperationType { #[derive(Clone, PartialEq, Debug)] pub struct Operation<'a> { pub operation_type: OperationType, - pub name: Option<Spanning<String>>, + pub name: Option<Spanning<&'a str>>, pub variable_definitions: Option<Spanning<VariableDefinitions<'a>>>, - pub directives: Option<Vec<Spanning<Directive>>>, - pub selection_set: Vec<Selection>, + pub directives: Option<Vec<Spanning<Directive<'a>>>>, + pub selection_set: Vec<Selection<'a>>, } #[derive(Clone, PartialEq, Debug)] -pub struct Fragment { - pub name: Spanning<String>, - pub type_condition: Spanning<String>, - pub directives: Option<Vec<Spanning<Directive>>>, - pub selection_set: Vec<Selection>, +pub struct Fragment<'a> { + pub name: Spanning<&'a str>, + pub type_condition: Spanning<&'a str>, + pub directives: Option<Vec<Spanning<Directive<'a>>>>, + pub selection_set: Vec<Selection<'a>>, } #[derive(Clone, PartialEq, Debug)] pub enum Definition<'a> { Operation(Spanning<Operation<'a>>), - Fragment(Spanning<Fragment>), + Fragment(Spanning<Fragment<'a>>), } pub type Document<'a> = Vec<Definition<'a>>; @@ -417,23 +417,19 @@ impl ToJson for InputValue { } } -impl Arguments { - pub fn into_iter(self) -> vec::IntoIter<(Spanning<String>, Spanning<InputValue>)> { +impl<'a> Arguments<'a> { + pub fn into_iter(self) -> vec::IntoIter<(Spanning<&'a str>, Spanning<InputValue>)> { self.items.into_iter() } - pub fn iter(&self) -> slice::Iter<(Spanning<String>, Spanning<InputValue>)> { + pub fn iter(&self) -> slice::Iter<(Spanning<&'a str>, Spanning<InputValue>)> { self.items.iter() } - pub fn iter_mut(&mut self) -> slice::IterMut<(Spanning<String>, Spanning<InputValue>)> { + pub fn iter_mut(&mut self) -> slice::IterMut<(Spanning<&'a str>, Spanning<InputValue>)> { self.items.iter_mut() } - pub fn drain<'a>(&'a mut self) -> vec::Drain<'a, (Spanning<String>, Spanning<InputValue>)> { - self.items.drain(..) - } - pub fn len(&self) -> usize { self.items.len() } @@ -448,7 +444,7 @@ impl Arguments { } impl<'a> VariableDefinitions<'a> { - pub fn iter(&self) -> slice::Iter<(Spanning<String>, VariableDefinition)> { + pub fn iter(&self) -> slice::Iter<(Spanning<&'a str>, VariableDefinition)> { self.items.iter() } } diff --git a/src/executor.rs b/src/executor.rs index bb707378..6e4b2734 100644 --- a/src/executor.rs +++ b/src/executor.rs @@ -35,9 +35,9 @@ pub enum FieldPath<'a> { /// The executor helps drive the query execution in a schema. It keeps track /// of the current field stack, context, variables, and errors. pub struct Executor<'a, CtxT> where CtxT: 'a { - fragments: &'a HashMap<&'a str, &'a Fragment>, + fragments: &'a HashMap<&'a str, &'a Fragment<'a>>, variables: &'a HashMap<String, InputValue>, - current_selection_set: Option<&'a [Selection]>, + current_selection_set: Option<&'a [Selection<'a>]>, schema: &'a SchemaType<'a>, context: &'a CtxT, errors: &'a RwLock<Vec<ExecutionError>>, @@ -332,7 +332,7 @@ pub fn execute_validated_query<'a, QueryT, MutationT, CtxT>( { let executor = Executor { - fragments: &fragments.iter().map(|f| (f.item.name.item.as_str(), &f.item)).collect(), + fragments: &fragments.iter().map(|f| (f.item.name.item, &f.item)).collect(), variables: variables, current_selection_set: Some(&op.item.selection_set[..]), schema: &root_node.schema, diff --git a/src/parser/document.rs b/src/parser/document.rs index 8d47c63d..a7f653d2 100644 --- a/src/parser/document.rs +++ b/src/parser/document.rs @@ -54,7 +54,7 @@ fn parse_operation_definition<'a>(parser: &mut Parser<'a>) -> ParseResult<'a, Op let start_pos = parser.peek().start.clone(); let operation_type = try!(parse_operation_type(parser)); let name = match parser.peek().item { - Token::Name(_) => Some(try!(parser.expect_name()).map(|s| s.to_owned())), + Token::Name(_) => Some(try!(parser.expect_name())), _ => None }; let variable_definitions = try!(parse_variable_definitions(parser)); @@ -74,7 +74,7 @@ fn parse_operation_definition<'a>(parser: &mut Parser<'a>) -> ParseResult<'a, Op } } -fn parse_fragment_definition<'a>(parser: &mut Parser<'a>) -> ParseResult<'a, Fragment> { +fn parse_fragment_definition<'a>(parser: &mut Parser<'a>) -> ParseResult<'a, Fragment<'a>> { let Spanning { start: start_pos, .. } = try!(parser.expect(&Token::Name("fragment"))); let name = match parser.expect_name() { Ok(n) => if n.item == "on" { @@ -95,14 +95,14 @@ fn parse_fragment_definition<'a>(parser: &mut Parser<'a>) -> ParseResult<'a, Fra &start_pos, &selection_set.end, Fragment { - name: name.map(|s| s.to_owned()), - type_condition: type_cond.map(|s| s.to_owned()), + name: name, + type_condition: type_cond, directives: directives.map(|s| s.item), selection_set: selection_set.item, })) } -fn parse_optional_selection_set<'a>(parser: &mut Parser<'a>) -> OptionParseResult<'a, Vec<Selection>> { +fn parse_optional_selection_set<'a>(parser: &mut Parser<'a>) -> OptionParseResult<'a, Vec<Selection<'a>>> { if parser.peek().item == Token::CurlyOpen { Ok(Some(try!(parse_selection_set(parser)))) } @@ -111,21 +111,21 @@ fn parse_optional_selection_set<'a>(parser: &mut Parser<'a>) -> OptionParseResul } } -fn parse_selection_set<'a>(parser: &mut Parser<'a>) -> ParseResult<'a, Vec<Selection>> { +fn parse_selection_set<'a>(parser: &mut Parser<'a>) -> ParseResult<'a, Vec<Selection<'a>>> { parser.unlocated_delimited_nonempty_list( &Token::CurlyOpen, parse_selection, &Token::CurlyClose) } -fn parse_selection<'a>(parser: &mut Parser<'a>) -> UnlocatedParseResult<'a, Selection> { +fn parse_selection<'a>(parser: &mut Parser<'a>) -> UnlocatedParseResult<'a, Selection<'a>> { match parser.peek().item { Token::Ellipsis => parse_fragment(parser), _ => parse_field(parser).map(Selection::Field), } } -fn parse_fragment<'a>(parser: &mut Parser<'a>) -> UnlocatedParseResult<'a, Selection> { +fn parse_fragment<'a>(parser: &mut Parser<'a>) -> UnlocatedParseResult<'a, Selection<'a>> { let Spanning { start: ref start_pos, .. } = try!(parser.expect(&Token::Ellipsis)); match parser.peek().item { @@ -140,7 +140,7 @@ fn parse_fragment<'a>(parser: &mut Parser<'a>) -> UnlocatedParseResult<'a, Selec &start_pos.clone(), &selection_set.end, InlineFragment { - type_condition: Some(name.map(|s| s.to_owned())), + type_condition: Some(name), directives: directives.map(|s| s.item), selection_set: selection_set.item, }))) @@ -167,7 +167,7 @@ fn parse_fragment<'a>(parser: &mut Parser<'a>) -> UnlocatedParseResult<'a, Selec &start_pos.clone(), &directives.as_ref().map_or(&frag_name.end, |s| &s.end).clone(), FragmentSpread { - name: frag_name.map(|s| s.to_owned()), + name: frag_name, directives: directives.map(|s| s.item), }))) }, @@ -189,11 +189,11 @@ fn parse_fragment<'a>(parser: &mut Parser<'a>) -> UnlocatedParseResult<'a, Selec } } -fn parse_field<'a>(parser: &mut Parser<'a>) -> ParseResult<'a, Field> { - let mut alias = Some(try!(parser.expect_name()).map(|s| s.to_owned())); +fn parse_field<'a>(parser: &mut Parser<'a>) -> ParseResult<'a, Field<'a>> { + let mut alias = Some(try!(parser.expect_name())); let name = if try!(parser.skip(&Token::Colon)).is_some() { - try!(parser.expect_name()).map(|s| s.to_owned()) + try!(parser.expect_name()) } else { alias.take().unwrap() @@ -212,14 +212,14 @@ fn parse_field<'a>(parser: &mut Parser<'a>) -> ParseResult<'a, Field> { .clone(), Field { alias: alias, - name: name.map(|s| s.to_owned()), + name: name, arguments: arguments, directives: directives.map(|s| s.item), selection_set: selection_set.map(|s| s.item), })) } -fn parse_arguments<'a>(parser: &mut Parser<'a>) -> OptionParseResult<'a, Arguments> { +fn parse_arguments<'a>(parser: &mut Parser<'a>) -> OptionParseResult<'a, Arguments<'a>> { if parser.peek().item != Token::ParenOpen { Ok(None) } else { @@ -231,7 +231,7 @@ fn parse_arguments<'a>(parser: &mut Parser<'a>) -> OptionParseResult<'a, Argumen } } -fn parse_argument<'a>(parser: &mut Parser<'a>) -> ParseResult<'a, (Spanning<String>, Spanning<InputValue>)> { +fn parse_argument<'a>(parser: &mut Parser<'a>) -> ParseResult<'a, (Spanning<&'a str>, Spanning<InputValue>)> { let name = try!(parser.expect_name()); try!(parser.expect(&Token::Colon)); let value = try!(parse_value_literal(parser, false)); @@ -239,7 +239,7 @@ fn parse_argument<'a>(parser: &mut Parser<'a>) -> ParseResult<'a, (Spanning<Stri Ok(Spanning::start_end( &name.start.clone(), &value.end.clone(), - (name.map(|s| s.to_owned()), value))) + (name, value))) } fn parse_operation_type<'a>(parser: &mut Parser<'a>) -> ParseResult<'a, OperationType> { @@ -263,7 +263,7 @@ fn parse_variable_definitions<'a>(parser: &mut Parser<'a>) -> OptionParseResult< } } -fn parse_variable_definition<'a>(parser: &mut Parser<'a>) -> ParseResult<'a, (Spanning<String>, VariableDefinition<'a>)> { +fn parse_variable_definition<'a>(parser: &mut Parser<'a>) -> ParseResult<'a, (Spanning<&'a str>, VariableDefinition<'a>)> { let Spanning { start: start_pos, .. } = try!(parser.expect(&Token::Dollar)); let var_name = try!(parser.expect_name()); try!(parser.expect(&Token::Colon)); @@ -283,7 +283,7 @@ fn parse_variable_definition<'a>(parser: &mut Parser<'a>) -> ParseResult<'a, (Sp Spanning::start_end( &start_pos, &var_name.end, - var_name.item.to_owned(), + var_name.item, ), VariableDefinition { var_type: var_type, @@ -292,7 +292,7 @@ fn parse_variable_definition<'a>(parser: &mut Parser<'a>) -> ParseResult<'a, (Sp ))) } -fn parse_directives<'a>(parser: &mut Parser<'a>) -> OptionParseResult<'a, Vec<Spanning<Directive>>> { +fn parse_directives<'a>(parser: &mut Parser<'a>) -> OptionParseResult<'a, Vec<Spanning<Directive<'a>>>> { if parser.peek().item != Token::At { Ok(None) } @@ -306,7 +306,7 @@ fn parse_directives<'a>(parser: &mut Parser<'a>) -> OptionParseResult<'a, Vec<Sp } } -fn parse_directive<'a>(parser: &mut Parser<'a>) -> ParseResult<'a, Directive> { +fn parse_directive<'a>(parser: &mut Parser<'a>) -> ParseResult<'a, Directive<'a>> { let Spanning { start: start_pos, .. } = try!(parser.expect(&Token::At)); let name = try!(parser.expect_name()); let arguments = try!(parse_arguments(parser)); @@ -315,7 +315,7 @@ fn parse_directive<'a>(parser: &mut Parser<'a>) -> ParseResult<'a, Directive> { &start_pos, &arguments.as_ref().map_or(&name.end, |s| &s.end).clone(), Directive { - name: name.map(|s| s.to_owned()), + name: name, arguments: arguments, })) } diff --git a/src/parser/tests/document.rs b/src/parser/tests/document.rs index 3908a69d..566fa79f 100644 --- a/src/parser/tests/document.rs +++ b/src/parser/tests/document.rs @@ -44,7 +44,7 @@ fn simple_ast() { name: Spanning::start_end( &SourcePosition::new(31, 2, 16), &SourcePosition::new(35, 2, 20), - "node".to_owned()), + "node"), arguments: Some(Spanning::start_end( &SourcePosition::new(35, 2, 20), &SourcePosition::new(42, 2, 27), @@ -54,7 +54,7 @@ fn simple_ast() { Spanning::start_end( &SourcePosition::new(36, 2, 21), &SourcePosition::new(38, 2, 23), - "id".to_owned()), + "id"), Spanning::start_end( &SourcePosition::new(40, 2, 25), &SourcePosition::new(41, 2, 26), @@ -73,7 +73,7 @@ fn simple_ast() { name: Spanning::start_end( &SourcePosition::new(65, 3, 20), &SourcePosition::new(67, 3, 22), - "id".to_owned()), + "id"), arguments: None, directives: None, selection_set: None, @@ -87,7 +87,7 @@ fn simple_ast() { name: Spanning::start_end( &SourcePosition::new(88, 4, 20), &SourcePosition::new(92, 4, 24), - "name".to_owned()), + "name"), arguments: None, directives: None, selection_set: None, diff --git a/src/types/base.rs b/src/types/base.rs index 149669ba..eadab4a3 100644 --- a/src/types/base.rs +++ b/src/types/base.rs @@ -307,16 +307,16 @@ fn resolve_selection_set_into<T, CtxT>( let response_name = &f.alias.as_ref().unwrap_or(&f.name).item; - if &f.name.item == "__typename" { + if f.name.item == "__typename" { result.insert( - response_name.clone(), + (*response_name).to_owned(), Value::string( instance.concrete_type_name(executor.context()))); continue; } let meta_field = meta_type.field_by_name(&f.name.item) - .expect(&format!("Field {} not found on type {:?}", f.name.item, meta_type.name())); + .unwrap_or_else(|| panic!(format!("Field {} not found on type {:?}", f.name.item, meta_type.name()))); let exec_vars = executor.variables(); @@ -330,15 +330,15 @@ fn resolve_selection_set_into<T, CtxT>( &Arguments::new( f.arguments.as_ref().map(|m| m.item.iter().map(|&(ref k, ref v)| - (k.item.as_str(), v.item.clone().into_const(exec_vars))).collect()), + (k.item, v.item.clone().into_const(exec_vars))).collect()), &meta_field.arguments), &mut sub_exec); match field_result { - Ok(v) => merge_key_into(result, response_name.clone(), v), + Ok(v) => merge_key_into(result, response_name, v), Err(e) => { sub_exec.push_error(e, start_pos.clone()); - result.insert(response_name.clone(), Value::null()); + result.insert((*response_name).to_owned(), Value::null()); } } }, @@ -415,10 +415,10 @@ fn is_excluded(directives: &Option<Vec<Spanning<Directive>>>, vars: &HashMap<Str fn merge_key_into( result: &mut HashMap<String, Value>, - response_name: String, + response_name: &str, value: Value, ) { - match result.entry(response_name) { + match result.entry(response_name.to_owned()) { Entry::Occupied(mut e) => { println!("Merging object at '{}'", e.key()); match (e.get_mut().as_mut_object_value(), value) { @@ -442,7 +442,7 @@ fn merge_maps( ) { for (key, value) in src { if dest.contains_key(&key) { - merge_key_into(dest, key, value); + merge_key_into(dest, &key, value); } else { dest.insert(key, value); diff --git a/src/validation/context.rs b/src/validation/context.rs index 9073ac8a..736362d5 100644 --- a/src/validation/context.rs +++ b/src/validation/context.rs @@ -23,7 +23,7 @@ pub struct ValidatorContext<'a> { input_type_stack: Vec<Option<&'a MetaType<'a>>>, input_type_literal_stack: Vec<Option<Type<'a>>>, parent_type_stack: Vec<Option<&'a MetaType<'a>>>, - fragment_names: HashSet<String>, + fragment_names: HashSet<&'a str>, } impl RuleError { @@ -51,7 +51,7 @@ impl RuleError { impl<'a> ValidatorContext<'a> { #[doc(hidden)] - pub fn new(schema: &'a SchemaType, document: &Document) -> ValidatorContext<'a> { + pub fn new(schema: &'a SchemaType, document: &Document<'a>) -> ValidatorContext<'a> { ValidatorContext { errors: Vec::new(), schema: schema, @@ -62,7 +62,7 @@ impl<'a> ValidatorContext<'a> { input_type_literal_stack: Vec::new(), fragment_names: document.iter() .filter_map(|def| match *def { - Definition::Fragment(ref frag) => Some(frag.item.name.item.clone()), + Definition::Fragment(ref frag) => Some(frag.item.name.item), _ => None, }) .collect() diff --git a/src/validation/input_value.rs b/src/validation/input_value.rs index 456523f2..97130620 100644 --- a/src/validation/input_value.rs +++ b/src/validation/input_value.rs @@ -47,7 +47,7 @@ fn validate_var_defs( Some(t) if t.is_input() => { let ct = schema.make_type(&def.var_type.item); - if def.var_type.item.is_non_null() && is_absent_or_null(values.get(&name.item)) { + if def.var_type.item.is_non_null() && is_absent_or_null(values.get(name.item)) { errors.push(RuleError::new( &format!( r#"Variable "${}" of required type "{}" was not provided."#, @@ -55,7 +55,7 @@ fn validate_var_defs( ), &[ name.start.clone() ], )); - } else if let Some(ref v) = values.get(&name.item) { + } else if let Some(ref v) = values.get(name.item) { unify_value(&name.item, &name.start, v, &ct, schema, errors, Path::Root); } }, diff --git a/src/validation/multi_visitor.rs b/src/validation/multi_visitor.rs index 8fb7d3d8..bda0e43c 100644 --- a/src/validation/multi_visitor.rs +++ b/src/validation/multi_visitor.rs @@ -46,10 +46,10 @@ impl<'a> Visitor<'a> for MultiVisitor<'a> { self.visit_all(|v| v.exit_fragment_definition(ctx, f)); } - fn enter_variable_definition(&mut self, ctx: &mut ValidatorContext<'a>, def: &'a (Spanning<String>, VariableDefinition)) { + fn enter_variable_definition(&mut self, ctx: &mut ValidatorContext<'a>, def: &'a (Spanning<&'a str>, VariableDefinition)) { self.visit_all(|v| v.enter_variable_definition(ctx, def)); } - fn exit_variable_definition(&mut self, ctx: &mut ValidatorContext<'a>, def: &'a (Spanning<String>, VariableDefinition)) { + fn exit_variable_definition(&mut self, ctx: &mut ValidatorContext<'a>, def: &'a (Spanning<&'a str>, VariableDefinition)) { self.visit_all(|v| v.exit_variable_definition(ctx, def)); } @@ -60,10 +60,10 @@ impl<'a> Visitor<'a> for MultiVisitor<'a> { self.visit_all(|v| v.exit_directive(ctx, d)); } - fn enter_argument(&mut self, ctx: &mut ValidatorContext<'a>, arg: &'a (Spanning<String>, Spanning<InputValue>)) { + fn enter_argument(&mut self, ctx: &mut ValidatorContext<'a>, arg: &'a (Spanning<&'a str>, Spanning<InputValue>)) { self.visit_all(|v| v.enter_argument(ctx, arg)); } - fn exit_argument(&mut self, ctx: &mut ValidatorContext<'a>, arg: &'a (Spanning<String>, Spanning<InputValue>)) { + fn exit_argument(&mut self, ctx: &mut ValidatorContext<'a>, arg: &'a (Spanning<&'a str>, Spanning<InputValue>)) { self.visit_all(|v| v.exit_argument(ctx, arg)); } diff --git a/src/validation/rules/arguments_of_correct_type.rs b/src/validation/rules/arguments_of_correct_type.rs index 8a972324..1cffe445 100644 --- a/src/validation/rules/arguments_of_correct_type.rs +++ b/src/validation/rules/arguments_of_correct_type.rs @@ -35,7 +35,7 @@ impl<'a> Visitor<'a> for ArgumentsOfCorrectType<'a> { self.current_args = None; } - fn enter_argument(&mut self, ctx: &mut ValidatorContext<'a>, &(ref arg_name, ref arg_value): &'a (Spanning<String>, Spanning<InputValue>)) { + fn enter_argument(&mut self, ctx: &mut ValidatorContext<'a>, &(ref arg_name, ref arg_value): &'a (Spanning<&'a str>, Spanning<InputValue>)) { if let Some(argument_meta) = self.current_args .and_then(|args| args.iter().filter(|a| a.name == arg_name.item).next()) { diff --git a/src/validation/rules/default_values_of_correct_type.rs b/src/validation/rules/default_values_of_correct_type.rs index f2ecdce7..09f2096a 100644 --- a/src/validation/rules/default_values_of_correct_type.rs +++ b/src/validation/rules/default_values_of_correct_type.rs @@ -12,7 +12,7 @@ pub fn factory() -> DefaultValuesOfCorrectType { } impl<'a> Visitor<'a> for DefaultValuesOfCorrectType { - fn enter_variable_definition(&mut self, ctx: &mut ValidatorContext<'a>, &(ref var_name, ref var_def): &'a (Spanning<String>, VariableDefinition)) { + fn enter_variable_definition(&mut self, ctx: &mut ValidatorContext<'a>, &(ref var_name, ref var_def): &'a (Spanning<&'a str>, VariableDefinition)) { if let Some(Spanning { item: ref var_value, ref start, .. }) = var_def.default_value { if var_def.var_type.item.is_non_null() { ctx.report_error( diff --git a/src/validation/rules/known_argument_names.rs b/src/validation/rules/known_argument_names.rs index 1de82cb5..2141e39b 100644 --- a/src/validation/rules/known_argument_names.rs +++ b/src/validation/rules/known_argument_names.rs @@ -46,7 +46,7 @@ impl<'a> Visitor<'a> for KnownArgumentNames<'a> { self.current_args = None; } - fn enter_argument(&mut self, ctx: &mut ValidatorContext<'a>, &(ref arg_name, _): &'a (Spanning<String>, Spanning<InputValue>)) { + fn enter_argument(&mut self, ctx: &mut ValidatorContext<'a>, &(ref arg_name, _): &'a (Spanning<&'a str>, Spanning<InputValue>)) { if let Some((ref pos, args)) = self.current_args { if args.iter().filter(|a| a.name == arg_name.item).next().is_none() { let message = match *pos { diff --git a/src/validation/rules/known_type_names.rs b/src/validation/rules/known_type_names.rs index 835e63f8..4072798c 100644 --- a/src/validation/rules/known_type_names.rs +++ b/src/validation/rules/known_type_names.rs @@ -20,7 +20,7 @@ impl<'a> Visitor<'a> for KnownTypeNames { validate_type(ctx, &type_cond.item, &type_cond.start); } - fn enter_variable_definition(&mut self, ctx: &mut ValidatorContext<'a>, &(_, ref var_def): &'a (Spanning<String>, VariableDefinition)) { + fn enter_variable_definition(&mut self, ctx: &mut ValidatorContext<'a>, &(_, ref var_def): &'a (Spanning<&'a str>, VariableDefinition)) { let type_name = var_def.var_type.item.innermost_name(); validate_type(ctx, &type_name, &var_def.var_type.start); } diff --git a/src/validation/rules/no_fragment_cycles.rs b/src/validation/rules/no_fragment_cycles.rs index ade106dc..a14d91be 100644 --- a/src/validation/rules/no_fragment_cycles.rs +++ b/src/validation/rules/no_fragment_cycles.rs @@ -55,7 +55,7 @@ impl<'a> Visitor<'a> for NoFragmentCycles<'a> { } fn exit_fragment_definition(&mut self, _: &mut ValidatorContext<'a>, fragment: &'a Spanning<Fragment>) { - assert_eq!(Some(fragment.item.name.item.as_str()), self.current_fragment); + assert_eq!(Some(fragment.item.name.item), self.current_fragment); self.current_fragment = None; } diff --git a/src/validation/rules/no_undefined_variables.rs b/src/validation/rules/no_undefined_variables.rs index 3441793a..89c9ca42 100644 --- a/src/validation/rules/no_undefined_variables.rs +++ b/src/validation/rules/no_undefined_variables.rs @@ -69,7 +69,7 @@ impl<'a> Visitor<'a> for NoUndefinedVariables<'a> { } fn enter_operation_definition(&mut self, _: &mut ValidatorContext<'a>, op: &'a Spanning<Operation>) { - let op_name = op.item.name.as_ref().map(|s| s.item.as_str()); + let op_name = op.item.name.as_ref().map(|s| s.item); self.current_scope = Some(Scope::Operation(op_name)); self.defined_variables.insert(op_name, (op.start.clone(), HashSet::new())); } @@ -86,7 +86,7 @@ impl<'a> Visitor<'a> for NoUndefinedVariables<'a> { } } - fn enter_variable_definition(&mut self, _: &mut ValidatorContext<'a>, &(ref var_name, _): &'a (Spanning<String>, VariableDefinition)) { + fn enter_variable_definition(&mut self, _: &mut ValidatorContext<'a>, &(ref var_name, _): &'a (Spanning<&'a str>, VariableDefinition)) { if let Some(Scope::Operation(ref name)) = self.current_scope { if let Some(&mut (_, ref mut vars)) = self.defined_variables.get_mut(name) { vars.insert(&var_name.item); @@ -94,7 +94,7 @@ impl<'a> Visitor<'a> for NoUndefinedVariables<'a> { } } - fn enter_argument(&mut self, _: &mut ValidatorContext<'a>, &(_, ref value): &'a (Spanning<String>, Spanning<InputValue>)) { + fn enter_argument(&mut self, _: &mut ValidatorContext<'a>, &(_, ref value): &'a (Spanning<&'a str>, Spanning<InputValue>)) { if let Some(ref scope) = self.current_scope { self.used_variables .entry(scope.clone()) diff --git a/src/validation/rules/no_unused_fragments.rs b/src/validation/rules/no_unused_fragments.rs index abeff3af..f96a0e4d 100644 --- a/src/validation/rules/no_unused_fragments.rs +++ b/src/validation/rules/no_unused_fragments.rs @@ -49,7 +49,7 @@ impl<'a> Visitor<'a> for NoUnusedFragments<'a> { for def in defs { if let Definition::Operation(Spanning { item: Operation { ref name, .. }, ..}) = *def { - let op_name = name.as_ref().map(|s| s.item.as_str()); + let op_name = name.as_ref().map(|s| s.item); self.find_reachable_fragments(&Scope::Operation(op_name), &mut reachable); } } diff --git a/src/validation/rules/no_unused_variables.rs b/src/validation/rules/no_unused_variables.rs index a25e923e..953f43a5 100644 --- a/src/validation/rules/no_unused_variables.rs +++ b/src/validation/rules/no_unused_variables.rs @@ -10,7 +10,7 @@ pub enum Scope<'a> { } pub struct NoUnusedVariables<'a> { - defined_variables: HashMap<Option<&'a str>, HashSet<&'a Spanning<String>>>, + defined_variables: HashMap<Option<&'a str>, HashSet<&'a Spanning<&'a str>>>, used_variables: HashMap<Scope<'a>, Vec<&'a str>>, current_scope: Option<Scope<'a>>, spreads: HashMap<Scope<'a>, Vec<&'a str>>, @@ -56,13 +56,13 @@ impl<'a> Visitor<'a> for NoUnusedVariables<'a> { let mut visited = HashSet::new(); self.find_used_vars( &Scope::Operation(op_name.clone()), - &def_vars.iter().map(|def| def.item.as_str()).collect(), + &def_vars.iter().map(|def| def.item).collect(), &mut used, &mut visited); ctx.append_errors(def_vars .iter() - .filter(|var| !used.contains(var.item.as_str())) + .filter(|var| !used.contains(var.item)) .map(|var| RuleError::new( &error_message(&var.item, op_name.clone()), &[var.start.clone()])) @@ -71,7 +71,7 @@ impl<'a> Visitor<'a> for NoUnusedVariables<'a> { } fn enter_operation_definition(&mut self, _: &mut ValidatorContext<'a>, op: &'a Spanning<Operation>) { - let op_name = op.item.name.as_ref().map(|s| s.item.as_str()); + let op_name = op.item.name.as_ref().map(|s| s.item); self.current_scope = Some(Scope::Operation(op_name.clone())); self.defined_variables.insert(op_name, HashSet::new()); } @@ -88,7 +88,7 @@ impl<'a> Visitor<'a> for NoUnusedVariables<'a> { } } - fn enter_variable_definition(&mut self, _: &mut ValidatorContext<'a>, &(ref var_name, _): &'a (Spanning<String>, VariableDefinition)) { + fn enter_variable_definition(&mut self, _: &mut ValidatorContext<'a>, &(ref var_name, _): &'a (Spanning<&'a str>, VariableDefinition)) { if let Some(Scope::Operation(ref name)) = self.current_scope { if let Some(vars) = self.defined_variables.get_mut(name) { vars.insert(var_name); @@ -96,7 +96,7 @@ impl<'a> Visitor<'a> for NoUnusedVariables<'a> { } } - fn enter_argument(&mut self, _: &mut ValidatorContext<'a>, &(_, ref value): &'a (Spanning<String>, Spanning<InputValue>)) { + fn enter_argument(&mut self, _: &mut ValidatorContext<'a>, &(_, ref value): &'a (Spanning<&'a str>, Spanning<InputValue>)) { if let Some(ref scope) = self.current_scope { self.used_variables .entry(scope.clone()) diff --git a/src/validation/rules/overlapping_fields_can_be_merged.rs b/src/validation/rules/overlapping_fields_can_be_merged.rs index 361d13c3..2e0a956e 100644 --- a/src/validation/rules/overlapping_fields_can_be_merged.rs +++ b/src/validation/rules/overlapping_fields_can_be_merged.rs @@ -14,7 +14,7 @@ struct Conflict(ConflictReason, Vec<SourcePosition>, Vec<SourcePosition>); struct ConflictReason(String, ConflictReasonMessage); #[derive(Debug)] -struct AstAndDef<'a>(Option<&'a str>, &'a Spanning<Field>, Option<&'a FieldType<'a>>); +struct AstAndDef<'a>(Option<&'a str>, &'a Spanning<Field<'a>>, Option<&'a FieldType<'a>>); type AstAndDefCollection<'a> = OrderedMap<&'a str, Vec<AstAndDef<'a>>>; @@ -116,7 +116,7 @@ impl<'a> PairSet<'a> { } pub struct OverlappingFieldsCanBeMerged<'a> { - named_fragments: HashMap<&'a str, &'a Fragment>, + named_fragments: HashMap<&'a str, &'a Fragment<'a>>, compared_fragments: RefCell<PairSet<'a>>, } @@ -573,11 +573,11 @@ impl<'a> OverlappingFieldsCanBeMerged<'a> { let field_def = parent_type.and_then(|t| t.field_by_name(field_name)); let response_name = f.item.alias.as_ref().map(|s| &s.item).unwrap_or_else(|| &field_name); - if !ast_and_defs.contains_key(response_name.as_str()) { + if !ast_and_defs.contains_key(response_name) { ast_and_defs.insert(response_name, Vec::new()); } - ast_and_defs.get_mut(response_name.as_str()).unwrap() + ast_and_defs.get_mut(response_name).unwrap() .push(AstAndDef(parent_type.and_then(MetaType::name), f, field_def)); }, Selection::FragmentSpread(Spanning { item: FragmentSpread { ref name, ..}, ..}) => { diff --git a/src/validation/rules/possible_fragment_spreads.rs b/src/validation/rules/possible_fragment_spreads.rs index aed2cb7f..1bc219e8 100644 --- a/src/validation/rules/possible_fragment_spreads.rs +++ b/src/validation/rules/possible_fragment_spreads.rs @@ -42,7 +42,7 @@ impl<'a> Visitor<'a> for PossibleFragmentSpreads<'a> { fn enter_fragment_spread(&mut self, ctx: &mut ValidatorContext<'a>, spread: &'a Spanning<FragmentSpread>) { if let (Some(ref parent_type), Some(ref frag_type)) - = (ctx.parent_type(), self.fragment_types.get(spread.item.name.item.as_str())) + = (ctx.parent_type(), self.fragment_types.get(spread.item.name.item)) { if !ctx.schema.type_overlap(parent_type, frag_type) { ctx.report_error( diff --git a/src/validation/rules/unique_argument_names.rs b/src/validation/rules/unique_argument_names.rs index 99abb946..be84a884 100644 --- a/src/validation/rules/unique_argument_names.rs +++ b/src/validation/rules/unique_argument_names.rs @@ -23,7 +23,7 @@ impl<'a> Visitor<'a> for UniqueArgumentNames<'a> { self.known_names = HashMap::new(); } - fn enter_argument(&mut self, ctx: &mut ValidatorContext<'a>, &(ref arg_name, _): &'a (Spanning<String>, Spanning<InputValue>)) { + fn enter_argument(&mut self, ctx: &mut ValidatorContext<'a>, &(ref arg_name, _): &'a (Spanning<&'a str>, Spanning<InputValue>)) { match self.known_names.entry(&arg_name.item) { Entry::Occupied(e) => { ctx.report_error( diff --git a/src/validation/rules/unique_variable_names.rs b/src/validation/rules/unique_variable_names.rs index 25c48a48..c80cb14d 100644 --- a/src/validation/rules/unique_variable_names.rs +++ b/src/validation/rules/unique_variable_names.rs @@ -19,7 +19,7 @@ impl<'a> Visitor<'a> for UniqueVariableNames<'a> { self.names = HashMap::new(); } - fn enter_variable_definition(&mut self, ctx: &mut ValidatorContext<'a>, &(ref var_name, _): &'a (Spanning<String>, VariableDefinition)) { + fn enter_variable_definition(&mut self, ctx: &mut ValidatorContext<'a>, &(ref var_name, _): &'a (Spanning<&'a str>, VariableDefinition)) { match self.names.entry(&var_name.item) { Entry::Occupied(e) => { ctx.report_error( diff --git a/src/validation/rules/variables_are_input_types.rs b/src/validation/rules/variables_are_input_types.rs index 8b6b9eb9..65eec493 100644 --- a/src/validation/rules/variables_are_input_types.rs +++ b/src/validation/rules/variables_are_input_types.rs @@ -9,7 +9,7 @@ pub fn factory() -> UniqueVariableNames { } impl<'a> Visitor<'a> for UniqueVariableNames { - fn enter_variable_definition(&mut self, ctx: &mut ValidatorContext<'a>, &(ref var_name, ref var_def): &'a (Spanning<String>, VariableDefinition)) { + fn enter_variable_definition(&mut self, ctx: &mut ValidatorContext<'a>, &(ref var_name, ref var_def): &'a (Spanning<&'a str>, VariableDefinition)) { if let Some(var_type) = ctx.schema.concrete_type_by_name(var_def.var_type.item.innermost_name()) { if !var_type.is_input() { ctx.report_error( diff --git a/src/validation/rules/variables_in_allowed_position.rs b/src/validation/rules/variables_in_allowed_position.rs index d7f5131d..ceb30408 100644 --- a/src/validation/rules/variables_in_allowed_position.rs +++ b/src/validation/rules/variables_in_allowed_position.rs @@ -13,7 +13,7 @@ pub enum Scope<'a> { pub struct VariableInAllowedPosition<'a> { spreads: HashMap<Scope<'a>, HashSet<&'a str>>, variable_usages: HashMap<Scope<'a>, Vec<(Spanning<&'a String>, Type<'a>)>>, - variable_defs: HashMap<Scope<'a>, Vec<&'a (Spanning<String>, VariableDefinition<'a>)>>, + variable_defs: HashMap<Scope<'a>, Vec<&'a (Spanning<&'a str>, VariableDefinition<'a>)>>, current_scope: Option<Scope<'a>>, } @@ -30,7 +30,7 @@ impl<'a> VariableInAllowedPosition<'a> { fn collect_incorrect_usages( &self, from: &Scope<'a>, - var_defs: &Vec<&'a (Spanning<String>, VariableDefinition)>, + var_defs: &Vec<&'a (Spanning<&'a str>, VariableDefinition)>, ctx: &mut ValidatorContext<'a>, visited: &mut HashSet<Scope<'a>>, ) @@ -83,7 +83,7 @@ impl<'a> Visitor<'a> for VariableInAllowedPosition<'a> { } fn enter_operation_definition(&mut self, _: &mut ValidatorContext<'a>, op: &'a Spanning<Operation>) { - self.current_scope = Some(Scope::Operation(op.item.name.as_ref().map(|s| s.item.as_str()))); + self.current_scope = Some(Scope::Operation(op.item.name.as_ref().map(|s| s.item))); } fn enter_fragment_spread(&mut self, _: &mut ValidatorContext<'a>, spread: &'a Spanning<FragmentSpread>) { @@ -95,7 +95,7 @@ impl<'a> Visitor<'a> for VariableInAllowedPosition<'a> { } } - fn enter_variable_definition(&mut self, _: &mut ValidatorContext<'a>, def: &'a (Spanning<String>, VariableDefinition)) { + fn enter_variable_definition(&mut self, _: &mut ValidatorContext<'a>, def: &'a (Spanning<&'a str>, VariableDefinition)) { if let Some(ref scope) = self.current_scope { self.variable_defs .entry(scope.clone()) diff --git a/src/validation/test_harness.rs b/src/validation/test_harness.rs index 3d0de147..e96a4bcb 100644 --- a/src/validation/test_harness.rs +++ b/src/validation/test_harness.rs @@ -452,7 +452,7 @@ impl GraphQLType for QueryRoot { } } -pub fn validate<'a, R, V, F>(r: R, q: &str, factory: F) +pub fn validate<'a, R, V, F>(r: R, q: &'a str, factory: F) -> Vec<RuleError> where R: GraphQLType, V: Visitor<'a> + 'a, @@ -479,14 +479,14 @@ pub fn validate<'a, R, V, F>(r: R, q: &str, factory: F) ctx.into_errors() } -pub fn expect_passes_rule<'a, V, F>(factory: F, q: &str) +pub fn expect_passes_rule<'a, V, F>(factory: F, q: &'a str) where V: Visitor<'a> + 'a, F: Fn() -> V { expect_passes_rule_with_schema(QueryRoot, factory, q); } -pub fn expect_passes_rule_with_schema<'a, R, V, F>(r: R, factory: F, q: &str) +pub fn expect_passes_rule_with_schema<'a, R, V, F>(r: R, factory: F, q: &'a str) where R: GraphQLType, V: Visitor<'a> + 'a, F: Fn() -> V @@ -499,14 +499,14 @@ pub fn expect_passes_rule_with_schema<'a, R, V, F>(r: R, factory: F, q: &str) } } -pub fn expect_fails_rule<'a, V, F>(factory: F, q: &str, expected_errors: &[RuleError]) +pub fn expect_fails_rule<'a, V, F>(factory: F, q: &'a str, expected_errors: &[RuleError]) where V: Visitor<'a> + 'a, F: Fn() -> V { expect_fails_rule_with_schema(QueryRoot, factory, q, expected_errors); } -pub fn expect_fails_rule_with_schema<'a, R, V, F>(r: R, factory: F, q: &str, expected_errors: &[RuleError]) +pub fn expect_fails_rule_with_schema<'a, R, V, F>(r: R, factory: F, q: &'a str, expected_errors: &[RuleError]) where R: GraphQLType, V: Visitor<'a> + 'a, F: Fn() -> V diff --git a/src/validation/traits.rs b/src/validation/traits.rs index c6913cdb..aaec53c4 100644 --- a/src/validation/traits.rs +++ b/src/validation/traits.rs @@ -15,14 +15,14 @@ pub trait Visitor<'a> { fn enter_fragment_definition(&mut self, _: &mut ValidatorContext<'a>, _: &'a Spanning<Fragment>) {} fn exit_fragment_definition(&mut self, _: &mut ValidatorContext<'a>, _: &'a Spanning<Fragment>) {} - fn enter_variable_definition(&mut self, _: &mut ValidatorContext<'a>, _: &'a (Spanning<String>, VariableDefinition)) {} - fn exit_variable_definition(&mut self, _: &mut ValidatorContext<'a>, _: &'a (Spanning<String>, VariableDefinition)) {} + fn enter_variable_definition(&mut self, _: &mut ValidatorContext<'a>, _: &'a (Spanning<&'a str>, VariableDefinition)) {} + fn exit_variable_definition(&mut self, _: &mut ValidatorContext<'a>, _: &'a (Spanning<&'a str>, VariableDefinition)) {} fn enter_directive(&mut self, _: &mut ValidatorContext<'a>, _: &'a Spanning<Directive>) {} fn exit_directive(&mut self, _: &mut ValidatorContext<'a>, _: &'a Spanning<Directive>) {} - fn enter_argument(&mut self, _: &mut ValidatorContext<'a>, _: &'a (Spanning<String>, Spanning<InputValue>)) {} - fn exit_argument(&mut self, _: &mut ValidatorContext<'a>, _: &'a (Spanning<String>, Spanning<InputValue>)) {} + fn enter_argument(&mut self, _: &mut ValidatorContext<'a>, _: &'a (Spanning<&'a str>, Spanning<InputValue>)) {} + fn exit_argument(&mut self, _: &mut ValidatorContext<'a>, _: &'a (Spanning<&'a str>, Spanning<InputValue>)) {} fn enter_selection_set(&mut self, _: &mut ValidatorContext<'a>, _: &'a Vec<Selection>) {} fn exit_selection_set(&mut self, _: &mut ValidatorContext<'a>, _: &'a Vec<Selection>) {} diff --git a/src/validation/visitor.rs b/src/validation/visitor.rs index 8c5cd255..7076a331 100644 --- a/src/validation/visitor.rs +++ b/src/validation/visitor.rs @@ -161,8 +161,6 @@ fn visit_fragment_spread<'a, V: Visitor<'a>>(v: &mut V, ctx: &mut ValidatorConte } fn visit_inline_fragment<'a, V: Visitor<'a>>(v: &mut V, ctx: &mut ValidatorContext<'a>, fragment: &'a Spanning<InlineFragment>) { - let type_name = fragment.item.type_condition.as_ref().map(|s| s.item.as_str()); - let mut visit_fn = move |ctx: &mut ValidatorContext<'a>| { v.enter_inline_fragment(ctx, fragment); @@ -172,7 +170,7 @@ fn visit_inline_fragment<'a, V: Visitor<'a>>(v: &mut V, ctx: &mut ValidatorConte v.exit_inline_fragment(ctx, fragment); }; - if let Some(type_name) = type_name { + if let &Some(Spanning { item: ref type_name, .. }) = &fragment.item.type_condition { ctx.with_pushed_type(Some(&Type::NonNullNamed(type_name)), visit_fn); } else {