From 05c1011d8309e093703286273832167326efb550 Mon Sep 17 00:00:00 2001 From: Christoph Herzog Date: Thu, 3 May 2018 01:21:08 +0200 Subject: [PATCH] (juniper_codegen) Upgrade syn + quote --- juniper_codegen/Cargo.toml | 4 +- juniper_codegen/src/derive_enum.rs | 46 ++++++++++------- juniper_codegen/src/derive_input_object.rs | 53 ++++++++++++------- juniper_codegen/src/derive_object.rs | 25 +++++---- juniper_codegen/src/lib.rs | 15 +++--- juniper_codegen/src/util.rs | 59 ++++++++++------------ 6 files changed, 116 insertions(+), 86 deletions(-) diff --git a/juniper_codegen/Cargo.toml b/juniper_codegen/Cargo.toml index 176f8bb6..13dbd08d 100644 --- a/juniper_codegen/Cargo.toml +++ b/juniper_codegen/Cargo.toml @@ -14,8 +14,8 @@ repository = "https://github.com/graphql-rust/juniper" proc-macro = true [dependencies] -syn = "0.11" -quote = "0.3" +syn = { version = "0.13.*", features = ["full", "extra-traits"] } +quote = "0.5.*" [badges] travis-ci = { repository = "graphql-rust/juniper" } diff --git a/juniper_codegen/src/derive_enum.rs b/juniper_codegen/src/derive_enum.rs index d22fb999..83b9bf78 100644 --- a/juniper_codegen/src/derive_enum.rs +++ b/juniper_codegen/src/derive_enum.rs @@ -1,5 +1,13 @@ use syn; -use syn::*; +use syn::{ + DeriveInput, + Meta, + NestedMeta, + Data, + Fields, + Ident, + Variant, +}; use quote::Tokens; use util::*; @@ -23,16 +31,16 @@ impl EnumAttrs { // Check attributes for name and description. if let Some(items) = get_graphl_attr(&input.attrs) { for item in items { - if let Some(val) = keyed_item_value(item, "name", true) { + if let Some(val) = keyed_item_value(&item, "name", true) { res.name = Some(val); continue; } - if let Some(val) = keyed_item_value(item, "description", true) { + if let Some(val) = keyed_item_value(&item, "description", true) { res.description = Some(val); continue; } match item { - &NestedMetaItem::MetaItem(MetaItem::Word(ref ident)) => { + NestedMeta::Meta(Meta::Word(ref ident)) => { if ident == "_internal" { res.internal = true; continue; @@ -64,15 +72,15 @@ impl EnumVariantAttrs { // Check attributes for name and description. if let Some(items) = get_graphl_attr(&variant.attrs) { for item in items { - if let Some(val) = keyed_item_value(item, "name", true) { + if let Some(val) = keyed_item_value(&item, "name", true) { res.name = Some(val); continue; } - if let Some(val) = keyed_item_value(item, "description", true) { + if let Some(val) = keyed_item_value(&item, "description", true) { res.description = Some(val); continue; } - if let Some(val) = keyed_item_value(item, "deprecated", true) { + if let Some(val) = keyed_item_value(&item, "deprecated", true) { res.deprecation = Some(val); continue; } @@ -87,9 +95,9 @@ impl EnumVariantAttrs { } pub fn impl_enum(ast: &syn::DeriveInput) -> Tokens { - let variants = match ast.body { - Body::Enum(ref var) => var, - Body::Struct(_) => { + let variants = match ast.data { + Data::Enum(ref enum_data) => enum_data.variants.iter().collect::>(), + _ => { panic!("#[derive(GraphlQLEnum)] may only be applied to enums, not to structs"); } }; @@ -110,12 +118,16 @@ pub fn impl_enum(ast: &syn::DeriveInput) -> Tokens { let mut to_inputs = Vec::::new(); for variant in variants { - if variant.data != VariantData::Unit { - panic!(format!( - "Invalid enum variant {}.\nGraphQL enums may only contain unit variants.", - variant.ident - )); - } + match variant.fields { + Fields::Unit => {}, + _ => { + panic!(format!( + "Invalid enum variant {}.\nGraphQL enums may only contain unit variants.", + variant.ident + )); + } + } ; + let var_attrs = EnumVariantAttrs::from_input(variant); let var_ident = &variant.ident; @@ -209,7 +221,7 @@ pub fn impl_enum(ast: &syn::DeriveInput) -> Tokens { } }; - let dummy_const = Ident::new(format!("_IMPL_GRAPHQLENUM_FOR_{}", ident)); + let dummy_const = Ident::from(format!("_IMPL_GRAPHQLENUM_FOR_{}", ident).as_str()); // This ugly hack makes it possible to use the derive inside juniper itself. // FIXME: Figure out a better way to do this! diff --git a/juniper_codegen/src/derive_input_object.rs b/juniper_codegen/src/derive_input_object.rs index 95dce59e..f645a3ec 100644 --- a/juniper_codegen/src/derive_input_object.rs +++ b/juniper_codegen/src/derive_input_object.rs @@ -1,6 +1,16 @@ -use syn; -use syn::*; -use quote::Tokens; +use std::str::FromStr; + +use syn::{ + self, + DeriveInput, + NestedMeta, + Meta, + Field, + Fields, + Data, + Ident, +}; +use quote::{Tokens, ToTokens}; use util::*; @@ -18,16 +28,16 @@ impl ObjAttrs { // Check attributes for name and description. if let Some(items) = get_graphl_attr(&input.attrs) { for item in items { - if let Some(val) = keyed_item_value(item, "name", true) { + if let Some(val) = keyed_item_value(&item, "name", true) { res.name = Some(val); continue; } - if let Some(val) = keyed_item_value(item, "description", true) { + if let Some(val) = keyed_item_value(&item, "description", true) { res.description = Some(val); continue; } match item { - &NestedMetaItem::MetaItem(MetaItem::Word(ref ident)) => { + NestedMeta::Meta(Meta::Word(ref ident)) => { if ident == "_internal" { res.internal = true; continue; @@ -60,20 +70,20 @@ impl ObjFieldAttrs { // Check attributes for name and description. if let Some(items) = get_graphl_attr(&variant.attrs) { for item in items { - if let Some(val) = keyed_item_value(item, "name", true) { + if let Some(val) = keyed_item_value(&item, "name", true) { res.name = Some(val); continue; } - if let Some(val) = keyed_item_value(item, "description", true) { + if let Some(val) = keyed_item_value(&item, "description", true) { res.description = Some(val); continue; } - if let Some(val) = keyed_item_value(item, "default", true) { + if let Some(val) = keyed_item_value(&item, "default", true) { res.default_expr = Some(val); continue; } match item { - &NestedMetaItem::MetaItem(MetaItem::Word(ref ident)) => { + NestedMeta::Meta(Meta::Word(ref ident)) => { if ident == "default" { res.default = true; continue; @@ -92,16 +102,16 @@ impl ObjFieldAttrs { } pub fn impl_input_object(ast: &syn::DeriveInput) -> Tokens { - let fields = match ast.body { - Body::Struct(ref data) => match data { - &VariantData::Struct(ref fields) => fields, + let fields = match ast.data { + Data::Struct(ref data) => match data.fields { + Fields::Named(ref named) => named.named.iter().collect::>(), _ => { panic!( "#[derive(GraphQLInputObject)] may only be used on regular structs with fields" ); } }, - Body::Enum(_) => { + _ => { panic!("#[derive(GraphlQLInputObject)] may only be applied to structs, not to enums"); } }; @@ -146,8 +156,17 @@ pub fn impl_input_object(ast: &syn::DeriveInput) -> Tokens { Some(quote! { Default::default() }) } else { match field_attrs.default_expr { - Some(ref def) => match syn::parse_token_trees(def) { - Ok(t) => Some(quote! { #(#t)* }), + Some(ref def) => match ::proc_macro::TokenStream::from_str(def) { + Ok(t) => { + match syn::parse::(t) { + Ok(e) => { + Some(e.into_tokens()) + }, + Err(_) => { + panic!("#graphql(default = ?) must be a valid Rust expression inside a string"); + }, + } + }, Err(_) => { panic!("#graphql(default = ?) must be a valid Rust expression inside a string"); } @@ -256,7 +275,7 @@ pub fn impl_input_object(ast: &syn::DeriveInput) -> Tokens { } }; - let dummy_const = Ident::new(format!("_IMPL_GRAPHQLINPUTOBJECT_FOR_{}", ident)); + let dummy_const = Ident::from(format!("_IMPL_GRAPHQLINPUTOBJECT_FOR_{}", ident).as_str()); // This ugly hack makes it possible to use the derive inside juniper itself. // FIXME: Figure out a better way to do this! diff --git a/juniper_codegen/src/derive_object.rs b/juniper_codegen/src/derive_object.rs index e777d071..67133201 100644 --- a/juniper_codegen/src/derive_object.rs +++ b/juniper_codegen/src/derive_object.rs @@ -1,5 +1,10 @@ use syn; -use syn::*; +use syn::{ + DeriveInput, + Data, + Fields, + Field, +}; use quote::Tokens; use util::*; @@ -17,11 +22,11 @@ impl ObjAttrs { // Check attributes for name and description. if let Some(items) = get_graphl_attr(&input.attrs) { for item in items { - if let Some(val) = keyed_item_value(item, "name", true) { + if let Some(val) = keyed_item_value(&item, "name", true) { res.name = Some(val); continue; } - if let Some(val) = keyed_item_value(item, "description", true) { + if let Some(val) = keyed_item_value(&item, "description", true) { res.description = Some(val); continue; } @@ -49,15 +54,15 @@ impl ObjFieldAttrs { // Check attributes for name and description. if let Some(items) = get_graphl_attr(&variant.attrs) { for item in items { - if let Some(val) = keyed_item_value(item, "name", true) { + if let Some(val) = keyed_item_value(&item, "name", true) { res.name = Some(val); continue; } - if let Some(val) = keyed_item_value(item, "description", true) { + if let Some(val) = keyed_item_value(&item, "description", true) { res.description = Some(val); continue; } - if let Some(val) = keyed_item_value(item, "deprecation", true) { + if let Some(val) = keyed_item_value(&item, "deprecation", true) { res.deprecation = Some(val); continue; } @@ -72,14 +77,14 @@ impl ObjFieldAttrs { } pub fn impl_object(ast: &syn::DeriveInput) -> Tokens { - let fields = match ast.body { - Body::Struct(ref data) => match data { - &VariantData::Struct(ref fields) => fields, + let fields = match ast.data { + Data::Struct(ref data) => match data.fields { + Fields::Named(ref fields) => fields.named.iter().collect::>(), _ => { panic!("#[derive(GraphQLObject)] may only be used on regular structs with fields"); } }, - Body::Enum(_) => { + _ => { panic!("#[derive(GraphlQLObject)] may only be applied to structs, not to enums"); } }; diff --git a/juniper_codegen/src/lib.rs b/juniper_codegen/src/lib.rs index 8c124901..55d7045f 100644 --- a/juniper_codegen/src/lib.rs +++ b/juniper_codegen/src/lib.rs @@ -20,24 +20,21 @@ use proc_macro::TokenStream; #[proc_macro_derive(GraphQLEnum, attributes(graphql))] pub fn derive_enum(input: TokenStream) -> TokenStream { - let s = input.to_string(); - let ast = syn::parse_derive_input(&s).unwrap(); + let ast = syn::parse::(input).unwrap(); let gen = derive_enum::impl_enum(&ast); - gen.parse().unwrap() + gen.into() } #[proc_macro_derive(GraphQLInputObject, attributes(graphql))] pub fn derive_input_object(input: TokenStream) -> TokenStream { - let s = input.to_string(); - let ast = syn::parse_derive_input(&s).unwrap(); + let ast = syn::parse::(input).unwrap(); let gen = derive_input_object::impl_input_object(&ast); - gen.parse().unwrap() + gen.into() } #[proc_macro_derive(GraphQLObject, attributes(graphql))] pub fn derive_object(input: TokenStream) -> TokenStream { - let s = input.to_string(); - let ast = syn::parse_derive_input(&s).unwrap(); + let ast = syn::parse::(input).unwrap(); let gen = derive_object::impl_object(&ast); - gen.parse().unwrap() + gen.into() } diff --git a/juniper_codegen/src/util.rs b/juniper_codegen/src/util.rs index d22b741d..ac1afefd 100644 --- a/juniper_codegen/src/util.rs +++ b/juniper_codegen/src/util.rs @@ -1,10 +1,16 @@ -use syn::*; +use syn::{ + Attribute, + Meta, + NestedMeta, + Lit, +}; -pub fn get_graphl_attr(attrs: &Vec) -> Option<&Vec> { +// Get the nested items of a a #[graphql(...)] attribute. +pub fn get_graphl_attr(attrs: &Vec) -> Option> { for attr in attrs { - match attr.value { - MetaItem::List(ref attr_name, ref items) => if attr_name == "graphql" { - return Some(items); + match attr.interpret_meta() { + Some(Meta::List(ref list)) if list.ident == "graphql" => { + return Some(list.nested.iter().map(|x| x.clone()).collect()); }, _ => {} } @@ -12,33 +18,24 @@ pub fn get_graphl_attr(attrs: &Vec) -> Option<&Vec> { None } -pub fn keyed_item_value(item: &NestedMetaItem, name: &str, must_be_string: bool) -> Option { - let item = match item { - &NestedMetaItem::MetaItem(ref item) => item, - _ => { - return None; - } - }; - let lit = match item { - &MetaItem::NameValue(ref ident, ref lit) => if ident == name { - lit - } else { - return None; - }, - _ => { - return None; - } - }; - match lit { - &Lit::Str(ref val, _) => Some(val.clone()), - _ => if must_be_string { - panic!(format!( - "Invalid format for attribute \"{:?}\": expected a string", - item - )); - } else { - None +pub fn keyed_item_value(item: &NestedMeta, name: &str, must_be_string: bool) -> Option { + match item { + &NestedMeta::Meta(Meta::NameValue(ref nameval)) if nameval.ident == name => { + match &nameval.lit { + &Lit::Str(ref strlit) => { + Some(strlit.value()) + }, + _ => if must_be_string { + panic!(format!( + "Invalid format for attribute \"{:?}\": expected a string", + item + )); + } else { + None + }, + } }, + _ => None, } }