From d0bc344a4d7b931ec18f712f5ffdc749feb05c53 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Sat, 20 Nov 2021 18:50:36 -0500 Subject: [PATCH] graphql_client_codegen: update to graphql_parser 0.4 Requires 0.4.x so that `Document<'a, String>::into_static()` exists. Future work can try and reduce the amount of `'static` used throughout the API, but this at least gets 0.4 into a working state. --- graphql_client_codegen/Cargo.toml | 2 +- graphql_client_codegen/src/codegen.rs | 20 ++- graphql_client_codegen/src/lib.rs | 10 +- graphql_client_codegen/src/query.rs | 136 +++++++++++------- graphql_client_codegen/src/schema.rs | 19 ++- .../src/schema/graphql_parser_conversion.rs | 125 +++++++++++----- .../src/schema/tests/github.rs | 2 +- graphql_client_codegen/src/tests/mod.rs | 12 +- graphql_client_codegen/src/type_qualifiers.rs | 5 +- 9 files changed, 213 insertions(+), 118 deletions(-) diff --git a/graphql_client_codegen/Cargo.toml b/graphql_client_codegen/Cargo.toml index a214cf6e2..4ca371d06 100644 --- a/graphql_client_codegen/Cargo.toml +++ b/graphql_client_codegen/Cargo.toml @@ -9,7 +9,7 @@ edition = "2018" [dependencies] graphql-introspection-query = { version = "0.2.0", path = "../graphql-introspection-query" } -graphql-parser = "^0.2" +graphql-parser = "0.4" heck = "0.4.0" lazy_static = "1.3" proc-macro2 = { version = "^1.0", features = [] } diff --git a/graphql_client_codegen/src/codegen.rs b/graphql_client_codegen/src/codegen.rs index 12efd2fd3..5057af85b 100644 --- a/graphql_client_codegen/src/codegen.rs +++ b/graphql_client_codegen/src/codegen.rs @@ -236,12 +236,16 @@ fn generate_fragment_definitions<'a>( } /// For default value constructors. -fn graphql_parser_value_to_literal( - value: &graphql_parser::query::Value, +fn graphql_parser_value_to_literal<'doc, T>( + value: &graphql_parser::query::Value<'doc, T>, ty: TypeId, is_optional: bool, query: &BoundQuery<'_>, -) -> TokenStream { +) -> TokenStream +where + T: graphql_parser::query::Text<'doc>, + T::Value: quote::ToTokens, +{ use graphql_parser::query::Value; let inner = match value { @@ -289,11 +293,15 @@ fn graphql_parser_value_to_literal( } /// For default value constructors. -fn render_object_literal( - object_map: &BTreeMap, +fn render_object_literal<'doc, T>( + object_map: &BTreeMap>, input_id: InputId, query: &BoundQuery<'_>, -) -> TokenStream { +) -> TokenStream +where + T: graphql_parser::query::Text<'doc>, + T::Value: quote::ToTokens, +{ let input = query.schema.get_input(input_id); let constructor = Ident::new(&input.name, Span::call_site()); let fields: Vec = input diff --git a/graphql_client_codegen/src/lib.rs b/graphql_client_codegen/src/lib.rs index 7037eaaba..c23a2b91b 100644 --- a/graphql_client_codegen/src/lib.rs +++ b/graphql_client_codegen/src/lib.rs @@ -47,7 +47,7 @@ type CacheMap = std::sync::Mutex>; lazy_static! { static ref SCHEMA_CACHE: CacheMap = CacheMap::default(); - static ref QUERY_CACHE: CacheMap<(String, graphql_parser::query::Document)> = + static ref QUERY_CACHE: CacheMap<(String, graphql_parser::query::Document<'static, String>)> = CacheMap::default(); } @@ -63,6 +63,7 @@ pub fn generate_module_token_stream( .extension() .and_then(std::ffi::OsStr::to_str) .unwrap_or("INVALID"); + let schema_string; // Check the schema cache. let schema: schema::Schema = { @@ -70,10 +71,10 @@ pub fn generate_module_token_stream( match lock.entry(schema_path.to_path_buf()) { hash_map::Entry::Occupied(o) => o.get().clone(), hash_map::Entry::Vacant(v) => { - let schema_string = read_file(v.key())?; + schema_string = read_file(v.key())?; let schema = match schema_extension { "graphql" | "gql" => { - let s = graphql_parser::schema::parse_schema(&schema_string).map_err(|parser_error| GeneralError(format!("Parser error: {}", parser_error)))?; + let s = graphql_parser::schema::parse_schema::<&str>(&schema_string).map_err(|parser_error| GeneralError(format!("Parser error: {}", parser_error)))?; schema::Schema::from(s) } "json" => { @@ -96,7 +97,8 @@ pub fn generate_module_token_stream( hash_map::Entry::Vacant(v) => { let query_string = read_file(v.key())?; let query = graphql_parser::parse_query(&query_string) - .map_err(|err| GeneralError(format!("Query parser error: {}", err)))?; + .map_err(|err| GeneralError(format!("Query parser error: {}", err)))? + .into_static(); v.insert((query_string, query)).clone() } } diff --git a/graphql_client_codegen/src/query.rs b/graphql_client_codegen/src/query.rs index d8ff35bb3..9f177b3fe 100644 --- a/graphql_client_codegen/src/query.rs +++ b/graphql_client_codegen/src/query.rs @@ -59,10 +59,13 @@ pub(crate) struct ResolvedFragmentId(u32); #[derive(Debug, Clone, Copy)] pub(crate) struct VariableId(u32); -pub(crate) fn resolve( +pub(crate) fn resolve<'doc, T>( schema: &Schema, - query: &graphql_parser::query::Document, -) -> Result { + query: &graphql_parser::query::Document<'doc, T>, +) -> Result +where + T: graphql_parser::query::Text<'doc>, +{ let mut resolved_query: Query = Default::default(); create_roots(&mut resolved_query, query, schema)?; @@ -98,22 +101,25 @@ pub(crate) fn resolve( Ok(resolved_query) } -fn create_roots( +fn create_roots<'doc, T>( resolved_query: &mut Query, - query: &graphql_parser::query::Document, + query: &graphql_parser::query::Document<'doc, T>, schema: &Schema, -) -> Result<(), QueryValidationError> { +) -> Result<(), QueryValidationError> +where + T: graphql_parser::query::Text<'doc>, +{ // First, give ids to all fragments and operations. for definition in &query.definitions { match definition { graphql_parser::query::Definition::Fragment(fragment) => { let graphql_parser::query::TypeCondition::On(on) = &fragment.type_condition; resolved_query.fragments.push(ResolvedFragment { - name: fragment.name.clone(), - on: schema.find_type(on).ok_or_else(|| { + name: fragment.name.as_ref().into(), + on: schema.find_type(on.as_ref()).ok_or_else(|| { QueryValidationError::new(format!( "Could not find type {} for fragment {} in schema.", - on, fragment.name + on.as_ref(), fragment.name.as_ref() )) })?, selection_set: Vec::new(), @@ -130,7 +136,7 @@ fn create_roots( })?; let resolved_operation: ResolvedOperation = ResolvedOperation { object_id: on, - name: m.name.as_ref().expect("mutation without name").to_owned(), + name: m.name.as_ref().expect("mutation without name").as_ref().into(), _operation_type: operations::OperationType::Mutation, selection_set: Vec::with_capacity(m.selection_set.items.len()), }; @@ -142,7 +148,7 @@ fn create_roots( ) => { let on = schema.query_type(); let resolved_operation: ResolvedOperation = ResolvedOperation { - name: q.name.as_ref().expect("query without name").to_owned(), + name: q.name.as_ref().expect("query without name").as_ref().into(), _operation_type: operations::OperationType::Query, object_id: on, selection_set: Vec::with_capacity(q.selection_set.items.len()), @@ -170,7 +176,8 @@ fn create_roots( .name .as_ref() .expect("subscription without name") - .to_owned(), + .as_ref() + .into(), _operation_type: operations::OperationType::Subscription, object_id: on, selection_set: Vec::with_capacity(s.selection_set.items.len()), @@ -191,25 +198,28 @@ fn create_roots( Ok(()) } -fn resolve_fragment( +fn resolve_fragment<'doc, T>( query: &mut Query, schema: &Schema, - fragment_definition: &graphql_parser::query::FragmentDefinition, -) -> Result<(), QueryValidationError> { + fragment_definition: &graphql_parser::query::FragmentDefinition<'doc, T>, +) -> Result<(), QueryValidationError> +where + T: graphql_parser::query::Text<'doc>, +{ let graphql_parser::query::TypeCondition::On(on) = &fragment_definition.type_condition; - let on = schema.find_type(on).ok_or_else(|| { + let on = schema.find_type(on.as_ref()).ok_or_else(|| { QueryValidationError::new(format!( "Could not find type `{}` referenced by fragment `{}`", - on, fragment_definition.name + on.as_ref(), fragment_definition.name.as_ref() )) })?; let (id, _) = query - .find_fragment(&fragment_definition.name) + .find_fragment(fragment_definition.name.as_ref()) .ok_or_else(|| { QueryValidationError::new(format!( "Could not find fragment `{}`.", - fragment_definition.name + fragment_definition.name.as_ref() )) })?; @@ -224,17 +234,20 @@ fn resolve_fragment( Ok(()) } -fn resolve_union_selection( +fn resolve_union_selection<'doc, T>( query: &mut Query, _union_id: UnionId, - selection_set: &graphql_parser::query::SelectionSet, + selection_set: &graphql_parser::query::SelectionSet<'doc, T>, parent: SelectionParent, schema: &Schema, -) -> Result<(), QueryValidationError> { +) -> Result<(), QueryValidationError> +where + T: graphql_parser::query::Text<'doc>, +{ for item in selection_set.items.iter() { match item { graphql_parser::query::Selection::Field(field) => { - if field.name == TYPENAME_FIELD { + if field.name.as_ref() == TYPENAME_FIELD { let id = query.push_selection(Selection::Typename, parent); parent.add_to_selection_set(query, id); } else { @@ -250,11 +263,11 @@ fn resolve_union_selection( } graphql_parser::query::Selection::FragmentSpread(fragment_spread) => { let (fragment_id, _fragment) = query - .find_fragment(&fragment_spread.fragment_name) + .find_fragment(fragment_spread.fragment_name.as_ref()) .ok_or_else(|| { QueryValidationError::new(format!( "Could not find fragment `{}` referenced by fragment spread.", - fragment_spread.fragment_name + fragment_spread.fragment_name.as_ref() )) })?; @@ -268,35 +281,38 @@ fn resolve_union_selection( Ok(()) } -fn resolve_object_selection<'a>( +fn resolve_object_selection<'a, 'doc, T>( query: &mut Query, object: &dyn crate::schema::ObjectLike, - selection_set: &graphql_parser::query::SelectionSet, + selection_set: &graphql_parser::query::SelectionSet<'doc, T>, parent: SelectionParent, schema: &'a Schema, -) -> Result<(), QueryValidationError> { +) -> Result<(), QueryValidationError> +where + T: graphql_parser::query::Text<'doc>, +{ for item in selection_set.items.iter() { match item { graphql_parser::query::Selection::Field(field) => { - if field.name == TYPENAME_FIELD { + if field.name.as_ref() == TYPENAME_FIELD { let id = query.push_selection(Selection::Typename, parent); parent.add_to_selection_set(query, id); continue; } let (field_id, schema_field) = object - .get_field_by_name(&field.name, schema) + .get_field_by_name(field.name.as_ref(), schema) .ok_or_else(|| { QueryValidationError::new(format!( "No field named {} on {}", - &field.name, + field.name.as_ref(), object.name() )) })?; let id = query.push_selection( Selection::Field(SelectedField { - alias: field.alias.clone(), + alias: field.alias.as_ref().map(|alias| alias.as_ref().into()), field_id, selection_set: Vec::with_capacity(selection_set.items.len()), }), @@ -320,11 +336,11 @@ fn resolve_object_selection<'a>( } graphql_parser::query::Selection::FragmentSpread(fragment_spread) => { let (fragment_id, _fragment) = query - .find_fragment(&fragment_spread.fragment_name) + .find_fragment(fragment_spread.fragment_name.as_ref()) .ok_or_else(|| { QueryValidationError::new(format!( "Could not find fragment `{}` referenced by fragment spread.", - fragment_spread.fragment_name + fragment_spread.fragment_name.as_ref() )) })?; @@ -338,13 +354,16 @@ fn resolve_object_selection<'a>( Ok(()) } -fn resolve_selection( +fn resolve_selection<'doc, T>( ctx: &mut Query, on: TypeId, - selection_set: &graphql_parser::query::SelectionSet, + selection_set: &graphql_parser::query::SelectionSet<'doc, T>, parent: SelectionParent, schema: &Schema, -) -> Result<(), QueryValidationError> { +) -> Result<(), QueryValidationError> +where + T: graphql_parser::query::Text<'doc>, +{ match on { TypeId::Object(oid) => { let object = schema.get_object(oid); @@ -370,20 +389,23 @@ fn resolve_selection( Ok(()) } -fn resolve_inline_fragment( +fn resolve_inline_fragment<'doc, T>( query: &mut Query, schema: &Schema, - inline_fragment: &graphql_parser::query::InlineFragment, + inline_fragment: &graphql_parser::query::InlineFragment<'doc, T>, parent: SelectionParent, -) -> Result { +) -> Result +where + T: graphql_parser::query::Text<'doc>, +{ let graphql_parser::query::TypeCondition::On(on) = inline_fragment .type_condition .as_ref() .expect("missing type condition on inline fragment"); - let type_id = schema.find_type(on).ok_or_else(|| { + let type_id = schema.find_type(on.as_ref()).ok_or_else(|| { QueryValidationError::new(format!( "Could not find type `{}` referenced by inline fragment.", - on + on.as_ref() )) })?; @@ -406,11 +428,14 @@ fn resolve_inline_fragment( Ok(id) } -fn resolve_operation( +fn resolve_operation<'doc, T>( query: &mut Query, schema: &Schema, - operation: &graphql_parser::query::OperationDefinition, -) -> Result<(), QueryValidationError> { + operation: &graphql_parser::query::OperationDefinition<'doc, T>, +) -> Result<(), QueryValidationError> +where + T: graphql_parser::query::Text<'doc>, +{ match operation { graphql_parser::query::OperationDefinition::Mutation(m) => { let on = schema.mutation_type().ok_or_else(|| { @@ -421,7 +446,7 @@ fn resolve_operation( })?; let on = schema.get_object(on); - let (id, _) = query.find_operation(m.name.as_ref().unwrap()).unwrap(); + let (id, _) = query.find_operation(m.name.as_ref().map(|name| name.as_ref()).unwrap()).unwrap(); resolve_variables(query, &m.variable_definitions, schema, id); resolve_object_selection( @@ -434,7 +459,7 @@ fn resolve_operation( } graphql_parser::query::OperationDefinition::Query(q) => { let on = schema.get_object(schema.query_type()); - let (id, _) = query.find_operation(q.name.as_ref().unwrap()).unwrap(); + let (id, _) = query.find_operation(q.name.as_ref().map(|name| name.as_ref()).unwrap()).unwrap(); resolve_variables(query, &q.variable_definitions, schema, id); resolve_object_selection( @@ -448,7 +473,7 @@ fn resolve_operation( graphql_parser::query::OperationDefinition::Subscription(s) => { let on = schema.subscription_type().ok_or_else(|| QueryValidationError::new("Query contains a subscription operation, but the schema has no subscription type.".into()))?; let on = schema.get_object(on); - let (id, _) = query.find_operation(s.name.as_ref().unwrap()).unwrap(); + let (id, _) = query.find_operation(s.name.as_ref().map(|name| name.as_ref()).unwrap()).unwrap(); resolve_variables(query, &s.variable_definitions, schema, id); resolve_object_selection( @@ -554,7 +579,7 @@ impl Query { pub(crate) struct ResolvedVariable { pub(crate) operation_id: OperationId, pub(crate) name: String, - pub(crate) default: Option, + pub(crate) default: Option>, pub(crate) r#type: StoredFieldType, } @@ -622,17 +647,20 @@ impl UsedTypes { } } -fn resolve_variables( +fn resolve_variables<'doc, T>( query: &mut Query, - variables: &[graphql_parser::query::VariableDefinition], + variables: &[graphql_parser::query::VariableDefinition<'doc, T>], schema: &Schema, operation_id: OperationId, -) { +) +where + T: graphql_parser::query::Text<'doc>, +{ for var in variables { query.variables.push(ResolvedVariable { operation_id, - name: var.name.clone(), - default: var.default_value.clone(), + name: var.name.as_ref().into(), + default: var.default_value.as_ref().map(|dflt| dflt.into_static()), r#type: resolve_field_type(schema, &var.var_type), }); } diff --git a/graphql_client_codegen/src/schema.rs b/graphql_client_codegen/src/schema.rs index 89721c175..6af5c84e1 100644 --- a/graphql_client_codegen/src/schema.rs +++ b/graphql_client_codegen/src/schema.rs @@ -443,8 +443,12 @@ pub(crate) fn input_is_recursive_without_indirection(input_id: InputId, schema: let mut visited_types = HashSet::<&str>::new(); input.contains_type_without_indirection(input_id, schema, &mut visited_types) } -impl std::convert::From for Schema { - fn from(ast: graphql_parser::schema::Document) -> Schema { +impl<'doc, T> std::convert::From> for Schema +where + T: graphql_parser::query::Text<'doc>, + T::Value: AsRef, +{ + fn from(ast: graphql_parser::schema::Document<'doc, T>) -> Schema { graphql_parser_conversion::build_schema(ast) } } @@ -459,10 +463,13 @@ impl std::convert::From( schema: &Schema, - inner: &graphql_parser::schema::Type, -) -> StoredFieldType { + inner: &graphql_parser::schema::Type<'doc, T>, +) -> StoredFieldType +where + T: graphql_parser::query::Text<'doc>, +{ use crate::type_qualifiers::graphql_parser_depth; use graphql_parser::schema::Type::*; @@ -483,7 +490,7 @@ pub(crate) fn resolve_field_type( } NamedType(name) => { return StoredFieldType { - id: schema.find_type_id(name), + id: schema.find_type_id(name.as_ref()), qualifiers, } } diff --git a/graphql_client_codegen/src/schema/graphql_parser_conversion.rs b/graphql_client_codegen/src/schema/graphql_parser_conversion.rs index a351aaeef..1384be10c 100644 --- a/graphql_client_codegen/src/schema/graphql_parser_conversion.rs +++ b/graphql_client_codegen/src/schema/graphql_parser_conversion.rs @@ -2,13 +2,21 @@ use super::{Schema, StoredInputFieldType, TypeId}; use crate::schema::resolve_field_type; use graphql_parser::schema::{self as parser, Definition, Document, TypeDefinition, UnionType}; -pub(super) fn build_schema(mut src: graphql_parser::schema::Document) -> super::Schema { +pub(super) fn build_schema<'doc, T>(mut src: graphql_parser::schema::Document<'doc, T>) -> super::Schema +where + T: graphql_parser::query::Text<'doc>, + T::Value: AsRef, +{ let mut schema = Schema::new(); convert(&mut src, &mut schema); schema } -fn convert(src: &mut graphql_parser::schema::Document, schema: &mut Schema) { +fn convert<'doc, T>(src: &mut graphql_parser::schema::Document<'doc, T>, schema: &mut Schema) +where + T: graphql_parser::query::Text<'doc>, + T::Value: AsRef, +{ populate_names_map(schema, &src.definitions); src.definitions @@ -38,17 +46,17 @@ fn convert(src: &mut graphql_parser::schema::Document, schema: &mut Schema) { schema.query_type = schema_definition .query .as_mut() - .and_then(|n| schema.names.get(n)) + .and_then(|n| schema.names.get(n.as_ref())) .and_then(|id| id.as_object_id()); schema.mutation_type = schema_definition .mutation .as_mut() - .and_then(|n| schema.names.get(n)) + .and_then(|n| schema.names.get(n.as_ref())) .and_then(|id| id.as_object_id()); schema.subscription_type = schema_definition .subscription .as_mut() - .and_then(|n| schema.names.get(n)) + .and_then(|n| schema.names.get(n.as_ref())) .and_then(|id| id.as_object_id()); } else { schema.query_type = schema.names.get("Query").and_then(|id| id.as_object_id()); @@ -65,11 +73,14 @@ fn convert(src: &mut graphql_parser::schema::Document, schema: &mut Schema) { }; } -fn populate_names_map(schema: &mut Schema, definitions: &[Definition]) { +fn populate_names_map<'doc, T>(schema: &mut Schema, definitions: &[Definition<'doc, T>]) +where + T: graphql_parser::query::Text<'doc>, +{ definitions .iter() .filter_map(|def| match def { - Definition::TypeDefinition(TypeDefinition::Enum(enm)) => Some(enm.name.as_str()), + Definition::TypeDefinition(TypeDefinition::Enum(enm)) => Some(enm.name.as_ref()), _ => None, }) .enumerate() @@ -81,7 +92,7 @@ fn populate_names_map(schema: &mut Schema, definitions: &[Definition]) { .iter() .filter_map(|def| match def { Definition::TypeDefinition(TypeDefinition::Object(object)) => { - Some(object.name.as_str()) + Some(object.name.as_ref()) } _ => None, }) @@ -96,7 +107,7 @@ fn populate_names_map(schema: &mut Schema, definitions: &[Definition]) { .iter() .filter_map(|def| match def { Definition::TypeDefinition(TypeDefinition::Interface(interface)) => { - Some(interface.name.as_str()) + Some(interface.name.as_ref()) } _ => None, }) @@ -110,7 +121,7 @@ fn populate_names_map(schema: &mut Schema, definitions: &[Definition]) { definitions .iter() .filter_map(|def| match def { - Definition::TypeDefinition(TypeDefinition::Union(union)) => Some(union.name.as_str()), + Definition::TypeDefinition(TypeDefinition::Union(union)) => Some(union.name.as_ref()), _ => None, }) .enumerate() @@ -122,7 +133,7 @@ fn populate_names_map(schema: &mut Schema, definitions: &[Definition]) { .iter() .filter_map(|def| match def { Definition::TypeDefinition(TypeDefinition::InputObject(input)) => { - Some(input.name.as_str()) + Some(input.name.as_ref()) } _ => None, }) @@ -134,26 +145,32 @@ fn populate_names_map(schema: &mut Schema, definitions: &[Definition]) { }); } -fn ingest_union(schema: &mut Schema, union: &mut UnionType) { +fn ingest_union<'doc, T>(schema: &mut Schema, union: &mut UnionType<'doc, T>) +where + T: graphql_parser::query::Text<'doc>, +{ let stored_union = super::StoredUnion { - name: std::mem::take(&mut union.name), + name: union.name.as_ref().into(), variants: union .types .iter() - .map(|name| schema.find_type_id(name)) + .map(|name| schema.find_type_id(name.as_ref())) .collect(), }; schema.stored_unions.push(stored_union); } -fn ingest_object(schema: &mut Schema, obj: &mut graphql_parser::schema::ObjectType) { - let object_id = schema.find_type_id(&obj.name).as_object_id().unwrap(); +fn ingest_object<'doc, T>(schema: &mut Schema, obj: &mut graphql_parser::schema::ObjectType<'doc, T>) +where + T: graphql_parser::query::Text<'doc>, +{ + let object_id = schema.find_type_id(obj.name.as_ref()).as_object_id().unwrap(); let mut field_ids = Vec::with_capacity(obj.fields.len()); for field in obj.fields.iter_mut() { let field = super::StoredField { - name: std::mem::take(&mut field.name), + name: field.name.as_ref().into(), r#type: resolve_field_type(schema, &field.field_type), parent: super::StoredFieldParent::Object(object_id), deprecation: find_deprecation(&field.directives), @@ -164,20 +181,23 @@ fn ingest_object(schema: &mut Schema, obj: &mut graphql_parser::schema::ObjectTy // Ingest the object itself let object = super::StoredObject { - name: std::mem::take(&mut obj.name), + name: obj.name.as_ref().into(), fields: field_ids, implements_interfaces: obj .implements_interfaces .iter() - .map(|iface_name| schema.find_interface(iface_name)) + .map(|iface_name| schema.find_interface(iface_name.as_ref())) .collect(), }; schema.push_object(object); } -fn ingest_scalar(schema: &mut Schema, scalar: &mut graphql_parser::schema::ScalarType) { - let name = std::mem::take(&mut scalar.name); +fn ingest_scalar<'doc, T>(schema: &mut Schema, scalar: &mut graphql_parser::schema::ScalarType<'doc, T>) +where + T: graphql_parser::query::Text<'doc>, +{ + let name: String = scalar.name.as_ref().into(); let name_for_names = name.clone(); let scalar = super::StoredScalar { name }; @@ -189,22 +209,28 @@ fn ingest_scalar(schema: &mut Schema, scalar: &mut graphql_parser::schema::Scala .insert(name_for_names, TypeId::Scalar(scalar_id)); } -fn ingest_enum(schema: &mut Schema, enm: &mut graphql_parser::schema::EnumType) { +fn ingest_enum<'doc, T>(schema: &mut Schema, enm: &mut graphql_parser::schema::EnumType<'doc, T>) +where + T: graphql_parser::query::Text<'doc>, +{ let enm = super::StoredEnum { - name: std::mem::take(&mut enm.name), + name: enm.name.as_ref().into(), variants: enm .values .iter_mut() - .map(|value| std::mem::take(&mut value.name)) + .map(|value| value.name.as_ref().into()) .collect(), }; schema.push_enum(enm); } -fn ingest_interface(schema: &mut Schema, interface: &mut graphql_parser::schema::InterfaceType) { +fn ingest_interface<'doc, T>(schema: &mut Schema, interface: &mut graphql_parser::schema::InterfaceType<'doc, T>) +where + T: graphql_parser::query::Text<'doc>, +{ let interface_id = schema - .find_type_id(&interface.name) + .find_type_id(interface.name.as_ref()) .as_interface_id() .unwrap(); @@ -212,7 +238,7 @@ fn ingest_interface(schema: &mut Schema, interface: &mut graphql_parser::schema: for field in interface.fields.iter_mut() { let field = super::StoredField { - name: std::mem::take(&mut field.name), + name: field.name.as_ref().into(), r#type: resolve_field_type(schema, &field.field_type), parent: super::StoredFieldParent::Interface(interface_id), deprecation: find_deprecation(&field.directives), @@ -222,22 +248,25 @@ fn ingest_interface(schema: &mut Schema, interface: &mut graphql_parser::schema: } let new_interface = super::StoredInterface { - name: std::mem::take(&mut interface.name), + name: interface.name.as_ref().into(), fields: field_ids, }; schema.push_interface(new_interface); } -fn find_deprecation(directives: &[parser::Directive]) -> Option> { +fn find_deprecation<'doc, T>(directives: &[parser::Directive<'doc, T>]) -> Option> +where + T: graphql_parser::query::Text<'doc>, +{ directives .iter() - .find(|directive| directive.name == "deprecated") + .find(|directive| directive.name.as_ref() == "deprecated") .map(|directive| { directive .arguments .iter() - .find(|(name, _)| name == "reason") + .find(|(name, _)| name.as_ref() == "reason") .and_then(|(_, value)| match value { graphql_parser::query::Value::String(s) => Some(s.clone()), _ => None, @@ -245,16 +274,19 @@ fn find_deprecation(directives: &[parser::Directive]) -> Option> }) } -fn ingest_input(schema: &mut Schema, input: &mut parser::InputObjectType) { +fn ingest_input<'doc, T>(schema: &mut Schema, input: &mut parser::InputObjectType<'doc, T>) +where + T: graphql_parser::query::Text<'doc>, +{ let input = super::StoredInputType { - name: std::mem::take(&mut input.name), + name: input.name.as_ref().into(), fields: input .fields .iter_mut() .map(|val| { let field_type = super::resolve_field_type(schema, &val.value_type); ( - std::mem::take(&mut val.name), + val.name.as_ref().into(), StoredInputFieldType { qualifiers: field_type.qualifiers, id: field_type.id, @@ -267,35 +299,50 @@ fn ingest_input(schema: &mut Schema, input: &mut parser::InputObjectType) { schema.stored_inputs.push(input); } -fn objects_mut(doc: &mut Document) -> impl Iterator { +fn objects_mut<'a, 'doc: 'a, T>(doc: &'a mut Document<'doc, T>) -> impl Iterator> +where + T: graphql_parser::query::Text<'doc>, +{ doc.definitions.iter_mut().filter_map(|def| match def { Definition::TypeDefinition(TypeDefinition::Object(obj)) => Some(obj), _ => None, }) } -fn interfaces_mut(doc: &mut Document) -> impl Iterator { +fn interfaces_mut<'a, 'doc: 'a, T>(doc: &'a mut Document<'doc, T>) -> impl Iterator> +where + T: graphql_parser::query::Text<'doc>, +{ doc.definitions.iter_mut().filter_map(|def| match def { Definition::TypeDefinition(TypeDefinition::Interface(interface)) => Some(interface), _ => None, }) } -fn unions_mut(doc: &mut Document) -> impl Iterator { +fn unions_mut<'a, 'doc: 'a, T>(doc: &'a mut Document<'doc, T>) -> impl Iterator> +where + T: graphql_parser::query::Text<'doc>, +{ doc.definitions.iter_mut().filter_map(|def| match def { Definition::TypeDefinition(TypeDefinition::Union(union)) => Some(union), _ => None, }) } -fn enums_mut(doc: &mut Document) -> impl Iterator { +fn enums_mut<'a, 'doc: 'a, T>(doc: &'a mut Document<'doc, T>) -> impl Iterator> +where + T: graphql_parser::query::Text<'doc>, +{ doc.definitions.iter_mut().filter_map(|def| match def { Definition::TypeDefinition(TypeDefinition::Enum(r#enum)) => Some(r#enum), _ => None, }) } -fn inputs_mut(doc: &mut Document) -> impl Iterator { +fn inputs_mut<'a, 'doc: 'a, T>(doc: &'a mut Document<'doc, T>) -> impl Iterator> +where + T: graphql_parser::query::Text<'doc>, +{ doc.definitions.iter_mut().filter_map(|def| match def { Definition::TypeDefinition(TypeDefinition::InputObject(input)) => Some(input), _ => None, diff --git a/graphql_client_codegen/src/schema/tests/github.rs b/graphql_client_codegen/src/schema/tests/github.rs index 8957b775c..e0094b648 100644 --- a/graphql_client_codegen/src/schema/tests/github.rs +++ b/graphql_client_codegen/src/schema/tests/github.rs @@ -7,7 +7,7 @@ const SCHEMA_GRAPHQL: &str = include_str!("github_schema.graphql"); fn ast_from_graphql_and_json_produce_the_same_schema() { let json: graphql_introspection_query::introspection_response::IntrospectionResponse = serde_json::from_str(SCHEMA_JSON).unwrap(); - let graphql_parser_schema = graphql_parser::parse_schema(SCHEMA_GRAPHQL).unwrap(); + let graphql_parser_schema = graphql_parser::parse_schema(SCHEMA_GRAPHQL).unwrap().into_static(); let mut json = Schema::from(json); let mut gql = Schema::from(graphql_parser_schema); diff --git a/graphql_client_codegen/src/tests/mod.rs b/graphql_client_codegen/src/tests/mod.rs index d72172957..da6a16fd4 100644 --- a/graphql_client_codegen/src/tests/mod.rs +++ b/graphql_client_codegen/src/tests/mod.rs @@ -3,9 +3,9 @@ use crate::{generated_module, schema::Schema, CodegenMode, GraphQLClientCodegenO #[test] fn schema_with_keywords_works() { let query_string = include_str!("keywords_query.graphql"); - let query = graphql_parser::parse_query(query_string).expect("Parse keywords query"); + let query = graphql_parser::parse_query::<&str>(query_string).expect("Parse keywords query"); let schema = graphql_parser::parse_schema(include_str!("keywords_schema.graphql")) - .expect("Parse keywords schema"); + .expect("Parse keywords schema").into_static(); let schema = Schema::from(schema); let options = GraphQLClientCodegenOptions::new(CodegenMode::Cli); @@ -41,9 +41,9 @@ fn schema_with_keywords_works() { #[test] fn fragments_other_variant_should_generate_unknown_other_variant() { let query_string = include_str!("foobars_query.graphql"); - let query = graphql_parser::parse_query(query_string).expect("Parse foobars query"); + let query = graphql_parser::parse_query::<&str>(query_string).expect("Parse foobars query"); let schema = graphql_parser::parse_schema(include_str!("foobars_schema.graphql")) - .expect("Parse foobars schema"); + .expect("Parse foobars schema").into_static(); let schema = Schema::from(schema); let mut options = GraphQLClientCodegenOptions::new(CodegenMode::Cli); @@ -80,9 +80,9 @@ fn fragments_other_variant_should_generate_unknown_other_variant() { #[test] fn fragments_other_variant_false_should_not_generate_unknown_other_variant() { let query_string = include_str!("foobars_query.graphql"); - let query = graphql_parser::parse_query(query_string).expect("Parse foobars query"); + let query = graphql_parser::parse_query::<&str>(query_string).expect("Parse foobars query"); let schema = graphql_parser::parse_schema(include_str!("foobars_schema.graphql")) - .expect("Parse foobars schema"); + .expect("Parse foobars schema").into_static(); let schema = Schema::from(schema); let options = GraphQLClientCodegenOptions::new(CodegenMode::Cli); diff --git a/graphql_client_codegen/src/type_qualifiers.rs b/graphql_client_codegen/src/type_qualifiers.rs index 0803eb82e..972fdb54e 100644 --- a/graphql_client_codegen/src/type_qualifiers.rs +++ b/graphql_client_codegen/src/type_qualifiers.rs @@ -10,7 +10,10 @@ impl GraphqlTypeQualifier { } } -pub fn graphql_parser_depth(schema_type: &graphql_parser::schema::Type) -> usize { +pub fn graphql_parser_depth<'doc, T>(schema_type: &graphql_parser::schema::Type<'doc, T>) -> usize +where + T: graphql_parser::query::Text<'doc>, +{ match schema_type { graphql_parser::schema::Type::ListType(inner) => 1 + graphql_parser_depth(inner), graphql_parser::schema::Type::NonNullType(inner) => 1 + graphql_parser_depth(inner),