Meaningful spans when invoking serializer trait methods

This commit is contained in:
David Tolnay 2018-01-10 19:22:07 -08:00
parent 5c41661bce
commit cc2558b0dc
No known key found for this signature in database
GPG Key ID: F9BA143B95FF6D82
2 changed files with 74 additions and 19 deletions

View File

@ -7,6 +7,7 @@
// except according to those terms. // except according to those terms.
use syn::{self, Ident, Index, Member}; use syn::{self, Ident, Index, Member};
use syn::spanned::Spanned;
use quote::Tokens; use quote::Tokens;
use proc_macro2::Span; use proc_macro2::Span;
@ -211,8 +212,10 @@ fn serialize_newtype_struct(
field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr); field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr);
} }
let span = Span::def_site().located_at(field.original.span());
let func = quote_spanned!(span=> _serde::Serializer::serialize_newtype_struct);
quote_expr! { quote_expr! {
_serde::Serializer::serialize_newtype_struct(__serializer, #type_name, #field_expr) #func(__serializer, #type_name, #field_expr)
} }
} }
@ -225,7 +228,7 @@ fn serialize_tuple_struct(
fields, fields,
params, params,
false, false,
&quote!(_serde::ser::SerializeTupleStruct::serialize_field), &TupleTrait::SerializeTupleStruct,
); );
let type_name = cattrs.name().serialize_name(); let type_name = cattrs.name().serialize_name();
@ -246,8 +249,7 @@ fn serialize_struct(params: &Parameters, fields: &[Field], cattrs: &attr::Contai
fields, fields,
params, params,
false, false,
&quote!(_serde::ser::SerializeStruct::serialize_field), &StructTrait::SerializeStruct,
&quote!(_serde::ser::SerializeStruct::skip_field),
); );
let type_name = cattrs.name().serialize_name(); let type_name = cattrs.name().serialize_name();
@ -670,14 +672,12 @@ fn serialize_tuple_variant(
params: &Parameters, params: &Parameters,
fields: &[Field], fields: &[Field],
) -> Fragment { ) -> Fragment {
let method = match context { let tuple_trait = match context {
TupleVariant::ExternallyTagged { .. } => { TupleVariant::ExternallyTagged { .. } => TupleTrait::SerializeTupleVariant,
quote!(_serde::ser::SerializeTupleVariant::serialize_field) TupleVariant::Untagged => TupleTrait::SerializeTuple,
}
TupleVariant::Untagged => quote!(_serde::ser::SerializeTuple::serialize_element),
}; };
let serialize_stmts = serialize_tuple_struct_visitor(fields, params, true, &method); let serialize_stmts = serialize_tuple_struct_visitor(fields, params, true, &tuple_trait);
let len = serialize_stmts.len(); let len = serialize_stmts.len();
let let_mut = mut_if(len > 0); let let_mut = mut_if(len > 0);
@ -729,18 +729,16 @@ fn serialize_struct_variant<'a>(
fields: &[Field], fields: &[Field],
name: &str, name: &str,
) -> Fragment { ) -> Fragment {
let (method, skip_method) = match context { let struct_trait = match context {
StructVariant::ExternallyTagged { .. } => ( StructVariant::ExternallyTagged { .. } => (
quote!(_serde::ser::SerializeStructVariant::serialize_field), StructTrait::SerializeStructVariant
quote!(_serde::ser::SerializeStructVariant::skip_field),
), ),
StructVariant::InternallyTagged { .. } | StructVariant::Untagged => ( StructVariant::InternallyTagged { .. } | StructVariant::Untagged => (
quote!(_serde::ser::SerializeStruct::serialize_field), StructTrait::SerializeStruct
quote!(_serde::ser::SerializeStruct::skip_field),
), ),
}; };
let serialize_fields = serialize_struct_visitor(fields, params, true, &method, &skip_method); let serialize_fields = serialize_struct_visitor(fields, params, true, &struct_trait);
let mut serialized_fields = fields let mut serialized_fields = fields
.iter() .iter()
@ -811,7 +809,7 @@ fn serialize_tuple_struct_visitor(
fields: &[Field], fields: &[Field],
params: &Parameters, params: &Parameters,
is_enum: bool, is_enum: bool,
func: &Tokens, tuple_trait: &TupleTrait,
) -> Vec<Tokens> { ) -> Vec<Tokens> {
fields fields
.iter() .iter()
@ -836,6 +834,8 @@ fn serialize_tuple_struct_visitor(
field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr); field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr);
} }
let span = Span::def_site().located_at(field.original.span());
let func = tuple_trait.serialize_element(span);
let ser = quote! { let ser = quote! {
try!(#func(&mut __serde_state, #field_expr)); try!(#func(&mut __serde_state, #field_expr));
}; };
@ -852,8 +852,7 @@ fn serialize_struct_visitor(
fields: &[Field], fields: &[Field],
params: &Parameters, params: &Parameters,
is_enum: bool, is_enum: bool,
func: &Tokens, struct_trait: &StructTrait,
skip_func: &Tokens,
) -> Vec<Tokens> { ) -> Vec<Tokens> {
fields fields
.iter() .iter()
@ -877,6 +876,8 @@ fn serialize_struct_visitor(
field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr); field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr);
} }
let span = Span::def_site().located_at(field.original.span());
let func = struct_trait.serialize_field(span);
let ser = quote! { let ser = quote! {
try!(#func(&mut __serde_state, #key_expr, #field_expr)); try!(#func(&mut __serde_state, #key_expr, #field_expr));
}; };
@ -884,6 +885,7 @@ fn serialize_struct_visitor(
match skip { match skip {
None => ser, None => ser,
Some(skip) => { Some(skip) => {
let skip_func = struct_trait.skip_field(span);
quote! { quote! {
if !#skip { if !#skip {
#ser #ser
@ -1007,3 +1009,54 @@ fn get_member(params: &Parameters, field: &Field, member: &Member) -> Tokens {
} }
} }
} }
enum StructTrait {
SerializeStruct,
SerializeStructVariant,
}
impl StructTrait {
fn serialize_field(&self, span: Span) -> Tokens {
match *self {
StructTrait::SerializeStruct => {
quote_spanned!(span=> _serde::ser::SerializeStruct::serialize_field)
}
StructTrait::SerializeStructVariant => {
quote_spanned!(span=> _serde::ser::SerializeStructVariant::serialize_field)
}
}
}
fn skip_field(&self, span: Span) -> Tokens {
match *self {
StructTrait::SerializeStruct => {
quote_spanned!(span=> _serde::ser::SerializeStruct::skip_field)
}
StructTrait::SerializeStructVariant => {
quote_spanned!(span=> _serde::ser::SerializeStructVariant::skip_field)
}
}
}
}
enum TupleTrait {
SerializeTuple,
SerializeTupleStruct,
SerializeTupleVariant,
}
impl TupleTrait {
fn serialize_element(&self, span: Span) -> Tokens {
match *self {
TupleTrait::SerializeTuple => {
quote_spanned!(span=> _serde::ser::SerializeTuple::serialize_element)
}
TupleTrait::SerializeTupleStruct => {
quote_spanned!(span=> _serde::ser::SerializeTupleStruct::serialize_field)
}
TupleTrait::SerializeTupleVariant => {
quote_spanned!(span=> _serde::ser::SerializeTupleVariant::serialize_field)
}
}
}
}

View File

@ -35,6 +35,7 @@ pub struct Field<'a> {
pub ident: Option<syn::Ident>, pub ident: Option<syn::Ident>,
pub attrs: attr::Field, pub attrs: attr::Field,
pub ty: &'a syn::Type, pub ty: &'a syn::Type,
pub original: &'a syn::Field,
} }
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
@ -157,6 +158,7 @@ fn fields_from_ast<'a>(
ident: field.ident, ident: field.ident,
attrs: attr::Field::from_ast(cx, i, field, attrs, container_default), attrs: attr::Field::from_ast(cx, i, field, attrs, container_default),
ty: &field.ty, ty: &field.ty,
original: &field,
}) })
.collect() .collect()
} }