Skip to content

Commit

Permalink
Merge pull request #1144 from alanpoon/update_syn_new
Browse files Browse the repository at this point in the history
Update Syn to 0.4 for conrod_derive
  • Loading branch information
mitchmindtree authored Mar 26, 2018
2 parents b598236 + 782b983 commit 80c8028
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 66 deletions.
4 changes: 2 additions & 2 deletions conrod_derive/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@ homepage = "https://github.com/pistondevelopers/conrod"
proc-macro = true

[dependencies]
quote = "0.3"
syn = "0.11"
quote = "0.4"
syn = {version="0.12.13",features=["extra-traits","full"]}
35 changes: 21 additions & 14 deletions conrod_derive/src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ pub fn impl_widget_common(ast: &syn::DeriveInput) -> quote::Tokens {
let ident = &ast.ident;
let common_field = common_builder_field(ast).unwrap();
let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();
let dummy_const = syn::Ident::new(format!("_IMPL_WIDGET_COMMON_FOR_{}", ident));
let dummy_const = syn::Ident::from(format!("_IMPL_WIDGET_COMMON_FOR_{}", ident));

let impl_item = quote! {
impl #impl_generics _conrod::widget::Common for #ident #ty_generics #where_clause {
Expand Down Expand Up @@ -36,8 +36,8 @@ pub fn impl_widget_common_(ast: &syn::DeriveInput) -> quote::Tokens {
let ident = &ast.ident;
let common_field = common_builder_field(ast).unwrap();
let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();
let dummy_const = syn::Ident::new(format!("_IMPL_WIDGET_COMMON_FOR_{}", ident));

let dummy_const = syn::Ident::from(format!("_IMPL_WIDGET_COMMON_FOR_{}", ident));
let impl_item = quote! {
impl #impl_generics ::widget::Common for #ident #ty_generics #where_clause {
fn common(&self) -> &::widget::CommonBuilder {
Expand All @@ -62,32 +62,39 @@ pub fn impl_widget_common_(ast: &syn::DeriveInput) -> quote::Tokens {
fn common_builder_field(ast: &syn::DeriveInput) -> Result<&syn::Ident, Error> {

// Ensure we are deriving for a struct.
let body = match ast.body {
syn::Body::Struct(ref body) => body,
let body = match ast.data {
syn::Data::Struct(ref body) => body,
_ => return Err(Error::NotStruct),
};

// We can only derive `WidgetCommon` for structs with fields.
let fields = match *body {
syn::VariantData::Struct(ref fields) => fields,
syn::VariantData::Tuple(_) => return Err(Error::TupleStruct),
syn::VariantData::Unit => return Err(Error::UnitStruct),
match body.fields {
syn::Fields::Named(_) => {},
syn::Fields::Unnamed(_) => return Err(Error::TupleStruct),
syn::Fields::Unit => return Err(Error::UnitStruct),
};

// Find the field on the struct with the `WidgetCommon` attribute.
//
// We need this to know what field to use for the `common` and `common_mut` accessor methods.
let mut common_field = None;
for field in fields {
for field in body.fields.iter() {
// First, search for the attribute.
for attr in &field.attrs {
if let syn::MetaItem::List(ref ident, ref values) = attr.value {
let has_common_builder = values.iter().any(|v| match *v {
syn::NestedMetaItem::MetaItem(syn::MetaItem::Word(ref w))
if let Some(_meta) = attr.interpret_meta() {
let mut is_conrod=false;
let mut has_common_builder = false;
if let syn::Meta::List(_metalist) = _meta{
if _metalist.ident == syn::Ident::from("conrod"){
is_conrod = true;
}
has_common_builder = _metalist.nested.iter().any(|v| match *v {
syn::NestedMeta::Meta(syn::Meta::Word(ref w))
if w == "common_builder" => true,
_ => false,
});
if ident == "conrod" && has_common_builder {
}
if is_conrod && has_common_builder {
// There should only be one `CommonBuilder` attribute.
if common_field.is_some() {
return Err(Error::MultipleCommonBuilderFields);
Expand Down
12 changes: 4 additions & 8 deletions conrod_derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,11 @@ fn impl_derive(
generate_derive: fn(&syn::DeriveInput) -> quote::Tokens,
) -> TokenStream
{
// A string representation of the type definition.
let input_string = input.to_string();

// Parse the string representation.
let ast = syn::parse_derive_input(&input_string).unwrap();

// Parse the input TokenStream representation.
let ast = syn::parse(input).unwrap();

// Build the implementation.
let gen = generate_derive(&ast);

// Return the generated impl.
gen.parse().unwrap()
gen.into()
}
64 changes: 26 additions & 38 deletions conrod_derive/src/style.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ use quote;
use std;
use syn;
use utils;

use syn::Expr;
// The implementation for `WidgetStyle`.
//
// This generates an accessor method for every field in the struct
pub fn impl_widget_style(ast: &syn::DeriveInput) -> quote::Tokens {
let crate_tokens = quote::Ident::new("_conrod");
let crate_tokens = Some(syn::Ident::from("_conrod"));
let params = params(ast).unwrap();
let impl_tokens = impl_tokens(&params, crate_tokens);
let dummy_const = &params.dummy_const;
Expand All @@ -24,7 +24,8 @@ pub fn impl_widget_style(ast: &syn::DeriveInput) -> quote::Tokens {
//
// The same as `WidgetStyle` but only for use within the conrod crate itself.
pub fn impl_widget_style_(ast: &syn::DeriveInput) -> quote::Tokens {
let crate_tokens = quote::Ident::new("");
// let crate_tokens = syn::Ident::from(syn::token::CapSelf::default());
let crate_tokens= None;
let params = params(ast).unwrap();
let impl_tokens = impl_tokens(&params, crate_tokens);
let dummy_const = &params.dummy_const;
Expand All @@ -36,7 +37,7 @@ pub fn impl_widget_style_(ast: &syn::DeriveInput) -> quote::Tokens {
}
}

fn impl_tokens(params: &Params, crate_tokens: quote::Ident) -> quote::Tokens {
fn impl_tokens(params: &Params, crate_tokens: Option<syn::Ident>) -> quote::Tokens {
let Params {
ref impl_generics,
ref ty_generics,
Expand All @@ -45,18 +46,6 @@ fn impl_tokens(params: &Params, crate_tokens: quote::Ident) -> quote::Tokens {
ref fields,
..
} = *params;

let mut field_initialisers = quote::Tokens::new();
for field in fields {
let ident = &field.ident;
field_initialisers.append_all(&[
quote::Ident::new(ident.as_str()),
quote::Ident::new(":"),
quote::Ident::new("None"),
quote::Ident::new(","),
]);
}

let getter_methods = fields
.iter()
.map(|&FieldParams { ref default, ref ty, ref ident }| {
Expand Down Expand Up @@ -108,32 +97,32 @@ struct FieldParams {
fn params(ast: &syn::DeriveInput) -> Result<Params, Error> {

// Ensure we are deriving for a struct.
let body = match ast.body {
syn::Body::Struct(ref body) => body,
let body = match ast.data {
syn::Data::Struct(ref body) => body,
_ => return Err(Error::NotStruct),
};

// We can only derive `WidgetStyle` for structs with fields.
let fields = match *body {
syn::VariantData::Struct(ref fields) => fields,
syn::VariantData::Tuple(_) => return Err(Error::TupleStruct),
syn::VariantData::Unit => return Err(Error::UnitStruct),
match body.fields {
syn::Fields::Named(_) => {},
syn::Fields::Unnamed(_) => return Err(Error::TupleStruct),
syn::Fields::Unit => return Err(Error::UnitStruct),
};

// For each field in the struct, create a method
//
// Produce an iterator yielding `Tokens` for each method.
let fields = fields
let fields = body.fields
.iter()
.filter_map(|field| {

let attr_elems = utils::conrod_attrs(&field.attrs);

let mut item = None;
'attrs: for nested_items in attr_elems {
for nested_item in nested_items {
if let syn::NestedMetaItem::MetaItem(ref meta_item) = *nested_item {
item = Some(meta_item);
for nested_item in nested_items{
if let syn::NestedMeta::Meta(ref meta_item) = nested_item {
item = Some(meta_item.clone());
break 'attrs;
}
}
Expand All @@ -144,24 +133,23 @@ fn params(ast: &syn::DeriveInput) -> Result<Params, Error> {
None => return None,
};

let literal = match *item {
syn::MetaItem::NameValue(ref ident, ref literal) if ident == "default" => literal,
let literal = match item {
syn::Meta::NameValue(syn::MetaNameValue{ref ident, ref lit,..}) if ident == "default" => lit,
ref item => return Some(Err(Error::UnexpectedMetaItem(item.clone()))),
};

let default = match *literal {
syn::Lit::Str(ref str, _) => quote::Ident::new(&str[..]),
let default:Expr = match *literal {
syn::Lit::Str(ref litstr) => litstr.clone().parse().unwrap(),
ref literal => return Some(Err(Error::UnexpectedLiteral(literal.clone()))),
};

let ident = match field.ident {
Some(ref ident) => ident,
None => return Some(Err(Error::UnnamedStructField)),
};

let ty = {
let path = match field.ty {
syn::Ty::Path(_, ref path) => path,
syn::Type::Path(syn::TypePath{ref path,..}) => path,
_ => return Some(Err(Error::NonOptionFieldTy)),
};

Expand All @@ -175,13 +163,13 @@ fn params(ast: &syn::DeriveInput) -> Result<Params, Error> {
return Some(Err(Error::NonOptionFieldTy));
}

let angle_bracket_data = match path_segment.parameters {
syn::PathParameters::AngleBracketed(ref data) => data,
let angle_bracket_data = match path_segment.arguments {
syn::PathArguments::AngleBracketed(ref data) => data,
_ => return Some(Err(Error::NonOptionFieldTy)),
};

let ty = match angle_bracket_data.types.len() {
1 => &angle_bracket_data.types[0],
let ty = match angle_bracket_data.args.len() {
1 => angle_bracket_data.args.first().unwrap(),
_ => return Some(Err(Error::NonOptionFieldTy)),
};

Expand All @@ -198,7 +186,7 @@ fn params(ast: &syn::DeriveInput) -> Result<Params, Error> {
})
.collect::<Result<_, _>>()?;

let dummy_const = syn::Ident::new(format!("_IMPL_WIDGET_STYLE_FOR_{}", ast.ident));
let dummy_const = syn::Ident::from(format!("_IMPL_WIDGET_STYLE_FOR_{}", ast.ident));
let ident = &ast.ident;
let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();

Expand All @@ -218,7 +206,7 @@ enum Error {
TupleStruct,
UnitStruct,
UnexpectedLiteral(syn::Lit),
UnexpectedMetaItem(syn::MetaItem),
UnexpectedMetaItem(syn::Meta),
UnnamedStructField,
NonOptionFieldTy,
}
Expand Down
11 changes: 7 additions & 4 deletions conrod_derive/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,15 @@ pub fn conrod_attrs<'a, I>(attrs: I) -> ConrodAttrs<I::IntoIter>
impl<'a, I> Iterator for ConrodAttrs<I>
where I: Iterator<Item=&'a syn::Attribute>,
{
type Item = &'a [syn::NestedMetaItem];
type Item = Vec<syn::NestedMeta>;
fn next(&mut self) -> Option<Self::Item> {
while let Some(attr) = self.attrs.next() {
if let syn::MetaItem::List(ref ident, ref values) = attr.value {
if ident == "conrod" {
return Some(&values[..]);
if let Some(_meta) = attr.interpret_meta() {
if let &syn::Meta::List(ref _metalist) = &_meta{
if _metalist.ident == syn::Ident::from("conrod"){
let j = _metalist.nested.clone().into_pairs().map(|pair|pair.into_value()).collect::<Vec<syn::NestedMeta>>();
return Some(j);
}
}
}
}
Expand Down

0 comments on commit 80c8028

Please sign in to comment.