diff --git a/common/dynaql/derive/Cargo.toml b/common/dynaql/derive/Cargo.toml index f78cbe44f..5a6a9f915 100644 --- a/common/dynaql/derive/Cargo.toml +++ b/common/dynaql/derive/Cargo.toml @@ -19,9 +19,9 @@ unstable_oneof = [] [dependencies] proc-macro2 = "1" -syn = { version = "1", features = ["full", "extra-traits", "visit-mut", "visit"] } +syn = { version = "2", features = ["full", "extra-traits", "visit-mut", "visit"] } quote = "1" Inflector = { version = "0.11", default-features = false } proc-macro-crate = "1" -darling = "0.14" +darling = "0.20" thiserror = { workspace = true } diff --git a/common/dynaql/derive/src/args.rs b/common/dynaql/derive/src/args.rs index 488b6150c..2c94d4822 100644 --- a/common/dynaql/derive/src/args.rs +++ b/common/dynaql/derive/src/args.rs @@ -1,12 +1,10 @@ use std::fmt::{self, Display, Formatter}; -use darling::ast::{Data, Fields}; +use darling::ast::{Data, Fields, NestedMeta}; use darling::util::{Ignored, SpannedValue}; use darling::{FromDeriveInput, FromField, FromMeta, FromVariant}; use inflector::Inflector; -use syn::{ - Attribute, Generics, Ident, Lit, LitBool, LitStr, Meta, NestedMeta, Path, Type, Visibility, -}; +use syn::{Attribute, Generics, Ident, Lit, LitBool, LitStr, Meta, Path, Type, Visibility}; use crate::validators::Validators; @@ -433,7 +431,7 @@ pub struct InterfaceFieldArgument { pub name: String, #[darling(default)] pub desc: Option, - #[darling(rename = "type")] + #[darling(rename = "r#type")] pub ty: LitStr, #[darling(default)] pub default: Option, @@ -448,7 +446,7 @@ pub struct InterfaceFieldArgument { #[derive(FromMeta)] pub struct InterfaceField { pub name: String, - #[darling(rename = "type")] + #[darling(rename = "r#type")] pub ty: LitStr, #[darling(default)] pub method: Option, diff --git a/common/dynaql/derive/src/complex_object.rs b/common/dynaql/derive/src/complex_object.rs index c757d5bf3..65e5632ab 100644 --- a/common/dynaql/derive/src/complex_object.rs +++ b/common/dynaql/derive/src/complex_object.rs @@ -32,7 +32,7 @@ pub fn generate( // Computation of the derivated fields let mut derived_impls = vec![]; for item in &mut item_impl.items { - if let ImplItem::Method(method) = item { + if let ImplItem::Fn(method) = item { let method_args: args::ComplexObjectField = parse_graphql_attrs(&method.attrs)?.unwrap_or_default(); @@ -105,7 +105,7 @@ pub fn generate( new_impl.block = syn::parse2::(new_block).expect("invalid block"); - derived_impls.push(ImplItem::Method(new_impl)); + derived_impls.push(ImplItem::Fn(new_impl)); } } } @@ -113,7 +113,7 @@ pub fn generate( item_impl.items.append(&mut derived_impls); for item in &mut item_impl.items { - if let ImplItem::Method(method) = item { + if let ImplItem::Fn(method) = item { let method_args: args::ComplexObjectField = parse_graphql_attrs(&method.attrs)?.unwrap_or_default(); if method_args.skip { @@ -164,7 +164,7 @@ pub fn generate( .rename_fields .rename(method.sig.ident.unraw().to_string(), RenameTarget::Field) }); - let field_desc = get_rustdoc(&method.attrs)? + let field_desc = get_rustdoc(&method.attrs) .map(|s| quote! { ::std::option::Option::Some(#s) }) .unwrap_or_else(|| quote! {::std::option::Option::None}); let field_deprecation = gen_deprecation(&method_args.deprecation, &crate_name); diff --git a/common/dynaql/derive/src/description.rs b/common/dynaql/derive/src/description.rs index 0d049dcd9..98584fce4 100644 --- a/common/dynaql/derive/src/description.rs +++ b/common/dynaql/derive/src/description.rs @@ -2,13 +2,13 @@ use proc_macro::TokenStream; use quote::quote; use crate::args; -use crate::utils::{get_crate_name, get_rustdoc, GeneratorResult}; +use crate::utils::{get_crate_name, get_rustdoc}; -pub fn generate(desc_args: &args::Description) -> GeneratorResult { +pub fn generate(desc_args: &args::Description) -> TokenStream { let crate_name = get_crate_name(desc_args.internal); let ident = &desc_args.ident; let (impl_generics, ty_generics, where_clause) = desc_args.generics.split_for_impl(); - let doc = get_rustdoc(&desc_args.attrs)?.unwrap_or_default(); + let doc = get_rustdoc(&desc_args.attrs).unwrap_or_default(); let expanded = quote! { impl #impl_generics #crate_name::Description for #ident #ty_generics #where_clause { fn description() -> &'static str { @@ -16,5 +16,5 @@ pub fn generate(desc_args: &args::Description) -> GeneratorResult { } } }; - Ok(expanded.into()) + expanded.into() } diff --git a/common/dynaql/derive/src/directive.rs b/common/dynaql/derive/src/directive.rs index dfd8f85de..64dab26be 100644 --- a/common/dynaql/derive/src/directive.rs +++ b/common/dynaql/derive/src/directive.rs @@ -21,7 +21,7 @@ pub fn generate( .name .clone() .unwrap_or_else(|| item_fn.sig.ident.to_string()); - let desc = get_rustdoc(&item_fn.attrs)? + let desc = get_rustdoc(&item_fn.attrs) .map(|s| quote!(::std::option::Option::Some(#s))) .unwrap_or_else(|| quote!(::std::option::Option::None)); let visible = visible_fn(&directive_args.visible); diff --git a/common/dynaql/derive/src/enum.rs b/common/dynaql/derive/src/enum.rs index 2cf5aba70..97b2f2505 100644 --- a/common/dynaql/derive/src/enum.rs +++ b/common/dynaql/derive/src/enum.rs @@ -20,7 +20,7 @@ pub fn generate(enum_args: &args::Enum) -> GeneratorResult { .clone() .unwrap_or_else(|| RenameTarget::Type.rename(ident.to_string())); - let desc = get_rustdoc(&enum_args.attrs)? + let desc = get_rustdoc(&enum_args.attrs) .map(|s| quote! { ::std::option::Option::Some(::std::borrow::ToOwned::to_owned(#s)) }) .unwrap_or_else(|| quote! {::std::option::Option::None}); @@ -47,7 +47,7 @@ pub fn generate(enum_args: &args::Enum) -> GeneratorResult { .rename(variant.ident.unraw().to_string(), RenameTarget::EnumItem) }); let item_deprecation = gen_deprecation(&variant.deprecation, &crate_name); - let item_desc = get_rustdoc(&variant.attrs)? + let item_desc = get_rustdoc(&variant.attrs) .map(|s| quote! { ::std::option::Option::Some(::std::borrow::ToOwned::to_owned(#s)) }) .unwrap_or_else(|| quote! {::std::option::Option::None}); diff --git a/common/dynaql/derive/src/input_object.rs b/common/dynaql/derive/src/input_object.rs index 2a2e4aeed..f5bd83589 100644 --- a/common/dynaql/derive/src/input_object.rs +++ b/common/dynaql/derive/src/input_object.rs @@ -31,7 +31,7 @@ pub fn generate(object_args: &args::InputObject) -> GeneratorResult let attrs = field .attrs .iter() - .filter(|attr| !attr.path.is_ident("field")) + .filter(|attr| !attr.path().is_ident("field")) .collect::>(); struct_fields.push(quote! { #(#attrs)* @@ -45,7 +45,7 @@ pub fn generate(object_args: &args::InputObject) -> GeneratorResult .or_else(|| object_args.input_name.clone()) .unwrap_or_else(|| RenameTarget::Type.rename(ident.to_string())); - let desc = get_rustdoc(&object_args.attrs)? + let desc = get_rustdoc(&object_args.attrs) .map(|s| quote! { ::std::option::Option::Some(::std::borrow::ToOwned::to_owned(#s)) }) .unwrap_or_else(|| quote! {::std::option::Option::None}); @@ -115,7 +115,7 @@ pub fn generate(object_args: &args::InputObject) -> GeneratorResult continue; } - let desc = get_rustdoc(&field.attrs)? + let desc = get_rustdoc(&field.attrs) .map(|s| quote! { ::std::option::Option::Some(#s) }) .unwrap_or_else(|| quote! {::std::option::Option::None}); let default = generate_default(&field.default, &field.default_with)?; diff --git a/common/dynaql/derive/src/interface.rs b/common/dynaql/derive/src/interface.rs index 19daf923a..4a73c7a33 100644 --- a/common/dynaql/derive/src/interface.rs +++ b/common/dynaql/derive/src/interface.rs @@ -35,7 +35,7 @@ pub fn generate(interface_args: &args::Interface) -> GeneratorResult); + +impl syn::parse::Parse for AttributeArgs { + fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result { + let mut metas = Vec::new(); + + loop { + if input.is_empty() { + break; + } + let value = input.parse()?; + metas.push(value); + if input.is_empty() { + break; + } + input.parse::()?; + } + + Ok(Self(metas)) + } +} #[proc_macro_attribute] #[allow(non_snake_case)] pub fn Object(args: TokenStream, input: TokenStream) -> TokenStream { - let object_args = match args::Object::from_list(&parse_macro_input!(args as AttributeArgs)) { + let object_args = match args::Object::from_list(&parse_macro_input!(args as AttributeArgs).0) { Ok(object_args) => object_args, Err(err) => return TokenStream::from(err.write_errors()), }; @@ -64,7 +86,7 @@ pub fn derive_simple_object(input: TokenStream) -> TokenStream { #[allow(non_snake_case)] pub fn ComplexObject(args: TokenStream, input: TokenStream) -> TokenStream { let object_args = - match args::ComplexObject::from_list(&parse_macro_input!(args as AttributeArgs)) { + match args::ComplexObject::from_list(&parse_macro_input!(args as AttributeArgs).0) { Ok(object_args) => object_args, Err(err) => return TokenStream::from(err.write_errors()), }; @@ -130,7 +152,7 @@ pub fn derive_union(input: TokenStream) -> TokenStream { #[allow(non_snake_case)] pub fn Subscription(args: TokenStream, input: TokenStream) -> TokenStream { let object_args = - match args::Subscription::from_list(&parse_macro_input!(args as AttributeArgs)) { + match args::Subscription::from_list(&parse_macro_input!(args as AttributeArgs).0) { Ok(object_args) => object_args, Err(err) => return TokenStream::from(err.write_errors()), }; @@ -144,7 +166,7 @@ pub fn Subscription(args: TokenStream, input: TokenStream) -> TokenStream { #[proc_macro_attribute] #[allow(non_snake_case)] pub fn Scalar(args: TokenStream, input: TokenStream) -> TokenStream { - let scalar_args = match args::Scalar::from_list(&parse_macro_input!(args as AttributeArgs)) { + let scalar_args = match args::Scalar::from_list(&parse_macro_input!(args as AttributeArgs).0) { Ok(scalar_args) => scalar_args, Err(err) => return TokenStream::from(err.write_errors()), }; @@ -189,10 +211,7 @@ pub fn derive_description(input: TokenStream) -> TokenStream { Ok(desc_args) => desc_args, Err(err) => return TokenStream::from(err.write_errors()), }; - match description::generate(&desc_args) { - Ok(expanded) => expanded, - Err(err) => err.write_errors().into(), - } + description::generate(&desc_args) } #[proc_macro_derive(NewType, attributes(graphql))] @@ -212,7 +231,7 @@ pub fn derive_newtype(input: TokenStream) -> TokenStream { #[allow(non_snake_case)] pub fn Directive(args: TokenStream, input: TokenStream) -> TokenStream { let directive_args = - match args::Directive::from_list(&parse_macro_input!(args as AttributeArgs)) { + match args::Directive::from_list(&parse_macro_input!(args as AttributeArgs).0) { Ok(directive_args) => directive_args, Err(err) => return TokenStream::from(err.write_errors()), }; diff --git a/common/dynaql/derive/src/merged_object.rs b/common/dynaql/derive/src/merged_object.rs index 3e043a8af..239a3e08e 100644 --- a/common/dynaql/derive/src/merged_object.rs +++ b/common/dynaql/derive/src/merged_object.rs @@ -17,7 +17,7 @@ pub fn generate(object_args: &args::MergedObject) -> GeneratorResult GeneratorResult GeneratorResult { NewTypeName::Rust => Some(RenameTarget::Type.rename(ident.to_string())), NewTypeName::Original => None, }; - let desc = get_rustdoc(&newtype_args.attrs)? + let desc = get_rustdoc(&newtype_args.attrs) .map(|s| quote! { ::std::option::Option::Some(#s) }) .unwrap_or_else(|| quote! {::std::option::Option::None}); let visible = visible_fn(&newtype_args.visible); diff --git a/common/dynaql/derive/src/object.rs b/common/dynaql/derive/src/object.rs index b654d9685..d2718cefa 100644 --- a/common/dynaql/derive/src/object.rs +++ b/common/dynaql/derive/src/object.rs @@ -33,7 +33,7 @@ pub fn generate( let desc = if object_args.use_type_description { quote! { ::std::option::Option::Some(::std::borrow::ToOwned::to_owned(::description())) } } else { - get_rustdoc(&item_impl.attrs)? + get_rustdoc(&item_impl.attrs) .map(|s| quote!(::std::option::Option::Some(::std::borrow::ToOwned::to_owned(#s)))) .unwrap_or_else(|| quote!(::std::option::Option::None)) }; @@ -47,7 +47,7 @@ pub fn generate( // Computation of the derivated fields let mut derived_impls = vec![]; for item in &mut item_impl.items { - if let ImplItem::Method(method) = item { + if let ImplItem::Fn(method) = item { let method_args: args::ObjectField = parse_graphql_attrs(&method.attrs)?.unwrap_or_default(); @@ -120,7 +120,7 @@ pub fn generate( new_impl.block = syn::parse2::(new_block).expect("invalid block"); - derived_impls.push(ImplItem::Method(new_impl)); + derived_impls.push(ImplItem::Fn(new_impl)); } } } @@ -128,7 +128,7 @@ pub fn generate( item_impl.items.append(&mut derived_impls); for item in &mut item_impl.items { - if let ImplItem::Method(method) = item { + if let ImplItem::Fn(method) = item { let method_args: args::ObjectField = parse_graphql_attrs(&method.attrs)?.unwrap_or_default(); @@ -300,7 +300,7 @@ pub fn generate( .rename_fields .rename(method.sig.ident.unraw().to_string(), RenameTarget::Field) }); - let field_desc = get_rustdoc(&method.attrs)? + let field_desc = get_rustdoc(&method.attrs) .map(|s| quote! { ::std::option::Option::Some(::std::borrow::ToOwned::to_owned(#s)) }) .unwrap_or_else(|| quote! {::std::option::Option::None}); let field_deprecation = gen_deprecation(&method_args.deprecation, &crate_name); diff --git a/common/dynaql/derive/src/scalar.rs b/common/dynaql/derive/src/scalar.rs index 70dcce16e..507548ad9 100644 --- a/common/dynaql/derive/src/scalar.rs +++ b/common/dynaql/derive/src/scalar.rs @@ -21,7 +21,7 @@ pub fn generate( let desc = if scalar_args.use_type_description { quote! { ::std::option::Option::Some(::std::borrow::ToOwned::to_owned(::description())) } } else { - get_rustdoc(&item_impl.attrs)? + get_rustdoc(&item_impl.attrs) .map(|s| quote!(::std::option::Option::Some(::std::borrow::ToOwned::to_owned(#s)))) .unwrap_or_else(|| quote!(::std::option::Option::None)) }; diff --git a/common/dynaql/derive/src/simple_object.rs b/common/dynaql/derive/src/simple_object.rs index fa3bd6216..66783582b 100644 --- a/common/dynaql/derive/src/simple_object.rs +++ b/common/dynaql/derive/src/simple_object.rs @@ -6,7 +6,7 @@ use quote::quote; use std::str::FromStr; use syn::ext::IdentExt; use syn::visit::Visit; -use syn::{Error, Ident, LifetimeDef, Path, Type}; +use syn::{Error, Ident, Lifetime, Path, Type}; use crate::args::{self, RenameRuleExt, RenameTarget, SimpleObjectField}; use crate::utils::{ @@ -36,7 +36,7 @@ pub fn generate(object_args: &args::SimpleObject) -> GeneratorResult GeneratorResult GeneratorResult { - lifetimes: Vec<&'a LifetimeDef>, + lifetimes: Vec<&'a Lifetime>, } impl<'a> Visit<'a> for GetLifetimes<'a> { - fn visit_lifetime_def(&mut self, i: &'a LifetimeDef) { + fn visit_lifetime(&mut self, i: &'a Lifetime) { self.lifetimes.push(i); } } diff --git a/common/dynaql/derive/src/subscription.rs b/common/dynaql/derive/src/subscription.rs index e8afb9e09..494b743e1 100644 --- a/common/dynaql/derive/src/subscription.rs +++ b/common/dynaql/derive/src/subscription.rs @@ -32,7 +32,7 @@ pub fn generate( let desc = if subscription_args.use_type_description { quote! { ::std::option::Option::Some(::std::borrow::ToOwned::to_owned(::description())) } } else { - get_rustdoc(&item_impl.attrs)? + get_rustdoc(&item_impl.attrs) .map(|s| quote!(::std::option::Option::Some(::std::borrow::ToOwned::to_owned(#s)))) .unwrap_or_else(|| quote!(::std::option::Option::None)) }; @@ -41,7 +41,7 @@ pub fn generate( let mut schema_fields = Vec::new(); for item in &mut item_impl.items { - if let ImplItem::Method(method) = item { + if let ImplItem::Fn(method) = item { let field: SubscriptionField = parse_graphql_attrs(&method.attrs)?.unwrap_or_default(); if field.skip { remove_graphql_attrs(&mut method.attrs); @@ -54,7 +54,7 @@ pub fn generate( .rename_fields .rename(method.sig.ident.unraw().to_string(), RenameTarget::Field) }); - let field_desc = get_rustdoc(&method.attrs)? + let field_desc = get_rustdoc(&method.attrs) .map(|s| quote! {::std::option::Option::Some(::std::borrow::ToOwned::to_owned(#s))}) .unwrap_or_else(|| quote! {::std::option::Option::None}); let field_deprecation = gen_deprecation(&field.deprecation, &crate_name); diff --git a/common/dynaql/derive/src/union.rs b/common/dynaql/derive/src/union.rs index 42f2b2683..77bd6f94e 100644 --- a/common/dynaql/derive/src/union.rs +++ b/common/dynaql/derive/src/union.rs @@ -24,7 +24,7 @@ pub fn generate(union_args: &args::Union) -> GeneratorResult { .clone() .unwrap_or_else(|| RenameTarget::Type.rename(ident.to_string())); - let desc = get_rustdoc(&union_args.attrs)? + let desc = get_rustdoc(&union_args.attrs) .map(|s| quote! { ::std::option::Option::Some(::std::borrow::ToOwned::to_owned(#s)) }) .unwrap_or_else(|| quote! {::std::option::Option::None}); diff --git a/common/dynaql/derive/src/utils.rs b/common/dynaql/derive/src/utils.rs index 43db8310f..7a0e20cbf 100644 --- a/common/dynaql/derive/src/utils.rs +++ b/common/dynaql/derive/src/utils.rs @@ -8,8 +8,8 @@ use quote::quote; use syn::visit::Visit; use syn::visit_mut::VisitMut; use syn::{ - visit_mut, Attribute, Error, Expr, ExprPath, FnArg, Ident, ImplItemMethod, Lifetime, Lit, - LitStr, Meta, Pat, PatIdent, Type, TypeGroup, TypeParamBound, TypeReference, + visit_mut, Attribute, Error, Expr, ExprPath, FnArg, Ident, ImplItemFn, Lifetime, Lit, LitStr, + Meta, Pat, PatIdent, Type, TypeGroup, TypeParamBound, TypeReference, }; use thiserror::Error; @@ -63,28 +63,30 @@ pub fn generate_guards( }) } -pub fn get_rustdoc(attrs: &[Attribute]) -> GeneratorResult> { +pub fn get_rustdoc(attrs: &[Attribute]) -> Option { let mut full_docs = String::new(); for attr in attrs { - match attr.parse_meta()? { - Meta::NameValue(nv) if nv.path.is_ident("doc") => { - if let Lit::Str(doc) = nv.lit { - let doc = doc.value(); - let doc_str = doc.trim(); - if !full_docs.is_empty() { - full_docs += "\n"; + match attr.meta { + Meta::NameValue(ref nv) if nv.path.is_ident("doc") => { + if let Expr::Lit(ref lit) = nv.value { + if let Lit::Str(ref doc) = lit.lit { + let doc = doc.value(); + let doc_str = doc.trim(); + if !full_docs.is_empty() { + full_docs += "\n"; + } + full_docs += doc_str; } - full_docs += doc_str; } } _ => {} } } - Ok(if full_docs.is_empty() { + if full_docs.is_empty() { None } else { Some(full_docs) - }) + } } fn generate_default_value(lit: &Lit) -> GeneratorResult { @@ -137,16 +139,15 @@ pub fn generate_default( pub fn get_cfg_attrs(attrs: &[Attribute]) -> Vec { attrs .iter() - .filter(|attr| !attr.path.segments.is_empty() && attr.path.segments[0].ident == "cfg") + .filter(|attr| !attr.path().segments.is_empty() && attr.path().segments[0].ident == "cfg") .cloned() .collect() } pub fn parse_graphql_attrs(attrs: &[Attribute]) -> GeneratorResult> { for attr in attrs { - if attr.path.is_ident("graphql") { - let meta = attr.parse_meta()?; - return Ok(Some(T::from_meta(&meta)?)); + if attr.path().is_ident("graphql") { + return Ok(Some(T::from_meta(&attr.meta)?)); } } Ok(None) @@ -156,7 +157,7 @@ pub fn remove_graphql_attrs(attrs: &mut Vec) { if let Some((idx, _)) = attrs .iter() .enumerate() - .find(|(_, a)| a.path.is_ident("graphql")) + .find(|(_, a)| a.path().is_ident("graphql")) { attrs.remove(idx); } @@ -240,7 +241,7 @@ pub fn gen_deprecation(deprecation: &Deprecation, crate_name: &TokenStream) -> T pub fn extract_input_args( crate_name: &proc_macro2::TokenStream, - method: &mut ImplItemMethod, + method: &mut ImplItemFn, ) -> GeneratorResult> { let mut args = Vec::new(); let mut create_ctx = true; diff --git a/common/dynaql/src/validation/test_harness.rs b/common/dynaql/src/validation/test_harness.rs index 5a0df683b..f2ae8cc8d 100644 --- a/common/dynaql/src/validation/test_harness.rs +++ b/common/dynaql/src/validation/test_harness.rs @@ -167,8 +167,8 @@ enum HumanOrAlien { internal, field( name = "name", - type = "Option", - arg(name = "surname", type = "Option") + r#type = "Option", + arg(name = "surname", r#type = "Option") ) )] enum Being { @@ -183,8 +183,8 @@ enum Being { internal, field( name = "name", - type = "Option", - arg(name = "surname", type = "Option") + r#type = "Option", + arg(name = "surname", r#type = "Option") ) )] enum Pet { @@ -197,8 +197,8 @@ enum Pet { internal, field( name = "name", - type = "Option", - arg(name = "surname", type = "Option") + r#type = "Option", + arg(name = "surname", r#type = "Option") ) )] enum Canine { @@ -206,7 +206,7 @@ enum Canine { } #[derive(Interface)] -#[graphql(internal, field(name = "iq", type = "Option"))] +#[graphql(internal, field(name = "iq", r#type = "Option"))] enum Intelligent { Human(Human), Alien(Alien),