(juniper_codegen) Upgrade syn + quote
This commit is contained in:
parent
3df18f41f8
commit
05c1011d83
6 changed files with 116 additions and 86 deletions
|
@ -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" }
|
||||
|
|
|
@ -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::<Vec<_>>(),
|
||||
_ => {
|
||||
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::<Tokens>::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!
|
||||
|
|
|
@ -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::<Vec<_>>(),
|
||||
_ => {
|
||||
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::<syn::Expr>(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!
|
||||
|
|
|
@ -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::<Vec<_>>(),
|
||||
_ => {
|
||||
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");
|
||||
}
|
||||
};
|
||||
|
|
|
@ -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::<syn::DeriveInput>(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::<syn::DeriveInput>(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::<syn::DeriveInput>(input).unwrap();
|
||||
let gen = derive_object::impl_object(&ast);
|
||||
gen.parse().unwrap()
|
||||
gen.into()
|
||||
}
|
||||
|
|
|
@ -1,10 +1,16 @@
|
|||
use syn::*;
|
||||
use syn::{
|
||||
Attribute,
|
||||
Meta,
|
||||
NestedMeta,
|
||||
Lit,
|
||||
};
|
||||
|
||||
pub fn get_graphl_attr(attrs: &Vec<Attribute>) -> Option<&Vec<NestedMetaItem>> {
|
||||
// Get the nested items of a a #[graphql(...)] attribute.
|
||||
pub fn get_graphl_attr(attrs: &Vec<Attribute>) -> Option<Vec<NestedMeta>> {
|
||||
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<Attribute>) -> Option<&Vec<NestedMetaItem>> {
|
|||
None
|
||||
}
|
||||
|
||||
pub fn keyed_item_value(item: &NestedMetaItem, name: &str, must_be_string: bool) -> Option<String> {
|
||||
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<String> {
|
||||
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,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue