Skip to content

Commit

Permalink
Update syn to 0.12 and quote to 0.4 (#20)
Browse files Browse the repository at this point in the history
* Update syn to 0.12 and quote to 0.4
* Rename Body to Data to match syn's way of naming that
* Rename VariantData to Fields to match syn's way of naming that
* Add deprecated type aliases both for both Body and VariantData to streamline migration from darling 0.2 to darling 0.3
  • Loading branch information
TedDriggs authored Jan 26, 2018
2 parents 3787d08 + b714e27 commit f9f2184
Show file tree
Hide file tree
Showing 51 changed files with 499 additions and 441 deletions.
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ darling_core = { version = "=0.2.2", path = "core" }
darling_macro = { version = "=0.2.2", path = "macro" }

[dev-dependencies]
syn = "0.11.11"
quote = "0.3.15"
syn = "0.12.10"
quote = "0.4"

[workspace]
members = ["macro", "core"]
5 changes: 2 additions & 3 deletions core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,5 @@ default = ["syn/full"]

[dependencies]
ident_case = "1.0.0"
lazy_static = "1.0.0"
syn = "0.11.11"
quote = "0.3.15"
syn = { version = "0.12.10", features = ["extra-traits"] }
quote = "0.4"
197 changes: 115 additions & 82 deletions core/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,96 +8,100 @@ use {Error, FromField, FromVariant, Result};
///
/// `V` is the type which receives any encountered variants, and `F` receives struct fields.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Body<V, F> {
pub enum Data<V, F> {
Enum(Vec<V>),
Struct(VariantData<F>),
Struct(Fields<F>),
}

impl<V, F> Body<V, F> {
#[deprecated(since="0.3", note="this has been renamed to Data")]
pub type Body<V, F> = Data<V, F>;

impl<V, F> Data<V, F> {
/// Creates an empty body of the same shape as the passed-in body.
pub fn empty_from(src: &syn::Body) -> Self {
pub fn empty_from(src: &syn::Data) -> Self {
match *src {
syn::Body::Enum(_) => Body::Enum(vec![]),
syn::Body::Struct(ref vd) => Body::Struct(VariantData::empty_from(vd)),
syn::Data::Enum(_) => Data::Enum(vec![]),
syn::Data::Struct(ref vd) => Data::Struct(Fields::empty_from(&vd.fields)),
syn::Data::Union(_) => unreachable!(),
}
}

/// Creates a new `Body<&'a V, &'a F>` instance from `Body<V, F>`.
pub fn as_ref<'a>(&'a self) -> Body<&'a V, &'a F> {
/// Creates a new `Data<&'a V, &'a F>` instance from `Data<V, F>`.
pub fn as_ref<'a>(&'a self) -> Data<&'a V, &'a F> {
match *self {
Body::Enum(ref variants) => Body::Enum(variants.into_iter().collect()),
Body::Struct(ref data) => Body::Struct(data.as_ref()),
Data::Enum(ref variants) => Data::Enum(variants.into_iter().collect()),
Data::Struct(ref data) => Data::Struct(data.as_ref()),
}
}

/// Applies a function `V -> U` on enum variants, if this is an enum.
pub fn map_enum_variants<T, U>(self, map: T) -> Body<U, F>
pub fn map_enum_variants<T, U>(self, map: T) -> Data<U, F>
where T: FnMut(V) -> U
{
match self {
Body::Enum(v) => Body::Enum(v.into_iter().map(map).collect()),
Body::Struct(f) => Body::Struct(f),
Data::Enum(v) => Data::Enum(v.into_iter().map(map).collect()),
Data::Struct(f) => Data::Struct(f),
}
}

/// Applies a function `F -> U` on struct fields, if this is a struct.
pub fn map_struct_fields<T, U>(self, map: T) -> Body<V, U>
pub fn map_struct_fields<T, U>(self, map: T) -> Data<V, U>
where T: FnMut(F) -> U
{
match self {
Body::Enum(v) => Body::Enum(v),
Body::Struct(f) => Body::Struct(f.map(map)),
Data::Enum(v) => Data::Enum(v),
Data::Struct(f) => Data::Struct(f.map(map)),
}
}

/// Applies a function to the `VariantData` if this is a struct.
pub fn map_struct<T, U>(self, mut map: T) -> Body<V, U>
where T: FnMut(VariantData<F>) -> VariantData<U>
/// Applies a function to the `Fields` if this is a struct.
pub fn map_struct<T, U>(self, mut map: T) -> Data<V, U>
where T: FnMut(Fields<F>) -> Fields<U>
{
match self {
Body::Enum(v) => Body::Enum(v),
Body::Struct(f) => Body::Struct(map(f)),
Data::Enum(v) => Data::Enum(v),
Data::Struct(f) => Data::Struct(map(f)),
}
}

/// Consumes the `Body`, returning `VariantData<F>` if it was a struct.
pub fn take_struct(self) -> Option<VariantData<F>> {
/// Consumes the `Data`, returning `Fields<F>` if it was a struct.
pub fn take_struct(self) -> Option<Fields<F>> {
match self {
Body::Enum(_) => None,
Body::Struct(f) => Some(f),
Data::Enum(_) => None,
Data::Struct(f) => Some(f),
}
}

/// Consumes the `Body`, returning `Vec<V>` if it was an enum.
/// Consumes the `Data`, returning `Vec<V>` if it was an enum.
pub fn take_enum(self) -> Option<Vec<V>> {
match self {
Body::Enum(v) => Some(v),
Body::Struct(_) => None,
Data::Enum(v) => Some(v),
Data::Struct(_) => None,
}
}

/// Returns `true` if this instance is `Body::Enum`.
/// Returns `true` if this instance is `Data::Enum`.
pub fn is_enum(&self) -> bool {
match *self {
Body::Enum(_) => true,
Body::Struct(_) => false,
Data::Enum(_) => true,
Data::Struct(_) => false,
}
}

/// Returns `true` if this instance is `Body::Struct`.
/// Returns `true` if this instance is `Data::Struct`.
pub fn is_struct(&self) -> bool {
!self.is_enum()
}
}

impl<V: FromVariant, F: FromField> Body<V, F> {
/// Attempt to convert from a `syn::Body` instance.
pub fn try_from(body: &syn::Body) -> Result<Self> {
impl<V: FromVariant, F: FromField> Data<V, F> {
/// Attempt to convert from a `syn::Data` instance.
pub fn try_from(body: &syn::Data) -> Result<Self> {
match *body {
syn::Body::Enum(ref variants) => {
let mut items = Vec::with_capacity(variants.len());
syn::Data::Enum(ref data) => {
let mut items = Vec::with_capacity(data.variants.len());
let mut errors = Vec::new();
for v_result in variants.into_iter().map(FromVariant::from_variant) {
for v_result in data.variants.clone().into_iter().map(|v| FromVariant::from_variant(&v)) {
match v_result {
Ok(val) => items.push(val),
Err(err) => errors.push(err)
Expand All @@ -107,29 +111,33 @@ impl<V: FromVariant, F: FromField> Body<V, F> {
if !errors.is_empty() {
Err(Error::multiple(errors))
} else {
Ok(Body::Enum(items))
Ok(Data::Enum(items))
}
}
syn::Body::Struct(ref data) => Ok(Body::Struct(VariantData::try_from(data)?)),
syn::Data::Struct(ref data) => Ok(Data::Struct(Fields::try_from(&data.fields)?)),
syn::Data::Union(_) => unreachable!(),
}
}
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct VariantData<T> {
pub struct Fields<T> {
pub style: Style,
pub fields: Vec<T>,
}

impl<T> VariantData<T> {
pub fn empty_from(vd: &syn::VariantData) -> Self {
VariantData {
#[deprecated(since="0.3", note="this has been renamed to Fields")]
pub type VariantData<T> = Fields<T>;

impl<T> Fields<T> {
pub fn empty_from(vd: &syn::Fields) -> Self {
Fields {
style: vd.into(),
fields: Vec::new(),
}
}

/// Splits the `VariantData` into its style and fields for further processing.
/// Splits the `Fields` into its style and fields for further processing.
/// Returns an empty `Vec` for `Unit` data.
pub fn split(self) -> (Style, Vec<T>) {
(self.style, self.fields)
Expand All @@ -152,60 +160,85 @@ impl<T> VariantData<T> {
self.style.is_struct()
}

pub fn as_ref<'a>(&'a self) -> VariantData<&'a T> {
VariantData {
pub fn as_ref<'a>(&'a self) -> Fields<&'a T> {
Fields {
style: self.style,
fields: self.fields.iter().collect(),
}
}

pub fn map<F, U>(self, map: F) -> VariantData<U> where F: FnMut(T) -> U {
VariantData {
pub fn map<F, U>(self, map: F) -> Fields<U> where F: FnMut(T) -> U {
Fields {
style: self.style,
fields: self.fields.into_iter().map(map).collect()
}
}
}

impl<F: FromField> VariantData<F> {
pub fn try_from(data: &syn::VariantData) -> Result<Self> {
let fields = data.fields();
let mut items = Vec::with_capacity(fields.len());
let mut errors = Vec::new();

for field in fields {
let f_result = FromField::from_field(field);
match f_result {
Ok(val) => items.push(val),
Err(err) => errors.push(if let Some(ref ident) = field.ident {
err.at(ident.as_ref())
} else {
err
})
impl<F: FromField> Fields<F> {
pub fn try_from(fields: &syn::Fields) -> Result<Self> {
let (items, errors) = match *fields {
syn::Fields::Named(ref fields) => {
let mut items = Vec::with_capacity(fields.named.len());
let mut errors = Vec::new();

for field in &fields.named {
let f_result = FromField::from_field(field);
match f_result {
Ok(val) => items.push(val),
Err(err) => errors.push(if let Some(ref ident) = field.ident {
err.at(ident.as_ref())
} else {
err
})
}
}

(items, errors)
}
}
syn::Fields::Unnamed(ref fields) => {
let mut items = Vec::with_capacity(fields.unnamed.len());
let mut errors = Vec::new();

for field in &fields.unnamed {
let f_result = FromField::from_field(field);
match f_result {
Ok(val) => items.push(val),
Err(err) => errors.push(if let Some(ref ident) = field.ident {
err.at(ident.as_ref())
} else {
err
})
}
}

(items, errors)
}
syn::Fields::Unit => (vec![], vec![]),
};


if !errors.is_empty() {
Err(Error::multiple(errors))
} else {
Ok(VariantData {
style: data.into(),
Ok(Fields {
style: fields.into(),
fields: items,
})
})
}
}
}

impl<T> From<Style> for VariantData<T> {
impl<T> From<Style> for Fields<T> {
fn from(style: Style) -> Self {
VariantData {
Fields {
style,
fields: Vec::new(),
}
}
}

impl<T, U: Into<Vec<T>>> From<(Style, U)> for VariantData<T> {
impl<T, U: Into<Vec<T>>> From<(Style, U)> for Fields<T> {
fn from((style, fields): (Style, U)) -> Self {
style.with_fields(fields)
}
Expand All @@ -231,27 +264,27 @@ impl Style {
*self == Style::Struct
}

/// Creates a new `VariantData` of the specified style with the passed-in fields.
fn with_fields<T, U: Into<Vec<T>>>(self, fields: U) -> VariantData<T> {
VariantData {
/// Creates a new `Fields` of the specified style with the passed-in fields.
fn with_fields<T, U: Into<Vec<T>>>(self, fields: U) -> Fields<T> {
Fields {
style: self,
fields: fields.into(),
}
}
}

impl From<syn::VariantData> for Style {
fn from(vd: syn::VariantData) -> Self {
impl From<syn::Fields> for Style {
fn from(vd: syn::Fields) -> Self {
(&vd).into()
}
}

impl<'a> From<&'a syn::VariantData> for Style {
fn from(vd: &syn::VariantData) -> Self {
impl<'a> From<&'a syn::Fields> for Style {
fn from(vd: &syn::Fields) -> Self {
match *vd {
syn::VariantData::Struct(_) => Style::Struct,
syn::VariantData::Tuple(_) => Style::Tuple,
syn::VariantData::Unit => Style::Unit,
syn::Fields::Named(_) => Style::Struct,
syn::Fields::Unnamed(_) => Style::Tuple,
syn::Fields::Unit => Style::Unit,
}
}
}
}
10 changes: 5 additions & 5 deletions core/src/codegen/default_expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ impl<'a> DefaultExpression<'a> {

impl<'a> ToTokens for DefaultExpression<'a> {
fn to_tokens(&self, tokens: &mut Tokens) {
tokens.append(match *self {
tokens.append_all(match *self {
DefaultExpression::Inherit(ident) => {
let dsn = Ident::new(DEFAULT_STRUCT_NAME);
let dsn = Ident::from(DEFAULT_STRUCT_NAME);
quote!(#dsn.#ident)
},
DefaultExpression::Explicit(path) => quote!(#path()),
Expand All @@ -38,8 +38,8 @@ pub struct DefaultDeclaration<'a>(&'a DefaultExpression<'a>);

impl<'a> ToTokens for DefaultDeclaration<'a> {
fn to_tokens(&self, tokens: &mut Tokens) {
let name = Ident::new(DEFAULT_STRUCT_NAME);
let name = Ident::from(DEFAULT_STRUCT_NAME);
let expr = self.0;
tokens.append(quote!(let #name: Self = #expr;));
tokens.append_all(quote!(let #name: Self = #expr;));
}
}
}
6 changes: 3 additions & 3 deletions core/src/codegen/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ impl ErrorDeclaration {

impl ToTokens for ErrorDeclaration {
fn to_tokens(&self, tokens: &mut Tokens) {
tokens.append(quote! {
tokens.append_all(quote! {
let mut __errors = Vec::new();
})
}
Expand Down Expand Up @@ -51,10 +51,10 @@ impl<'a> ToTokens for ErrorCheck<'a> {
quote!()
};

tokens.append(quote! {
tokens.append_all(quote! {
if !__errors.is_empty() {
return ::darling::export::Err(::darling::Error::multiple(__errors) #at_call);
}
})
}
}
}
Loading

0 comments on commit f9f2184

Please sign in to comment.