mirror of
https://github.com/pezkuwichain/serde.git
synced 2026-06-15 20:11:01 +00:00
Keep track of a span for alias strings
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
use crate::fragment::{Expr, Fragment, Match, Stmts};
|
use crate::fragment::{Expr, Fragment, Match, Stmts};
|
||||||
use crate::internals::ast::{Container, Data, Field, Style, Variant};
|
use crate::internals::ast::{Container, Data, Field, Style, Variant};
|
||||||
|
use crate::internals::name::Name;
|
||||||
use crate::internals::{attr, replace_receiver, ungroup, Ctxt, Derive};
|
use crate::internals::{attr, replace_receiver, ungroup, Ctxt, Derive};
|
||||||
use crate::{bound, dummy, pretend, this};
|
use crate::{bound, dummy, pretend, this};
|
||||||
use proc_macro2::{Literal, Span, TokenStream};
|
use proc_macro2::{Literal, Span, TokenStream};
|
||||||
@@ -2002,7 +2003,7 @@ fn deserialize_untagged_newtype_variant(
|
|||||||
|
|
||||||
struct FieldWithAliases<'a> {
|
struct FieldWithAliases<'a> {
|
||||||
ident: Ident,
|
ident: Ident,
|
||||||
aliases: &'a BTreeSet<String>,
|
aliases: &'a BTreeSet<Name>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deserialize_generated_identifier(
|
fn deserialize_generated_identifier(
|
||||||
@@ -2224,7 +2225,7 @@ fn deserialize_identifier(
|
|||||||
let aliases = field
|
let aliases = field
|
||||||
.aliases
|
.aliases
|
||||||
.iter()
|
.iter()
|
||||||
.map(|alias| Literal::byte_string(alias.as_bytes()));
|
.map(|alias| Literal::byte_string(alias.value.as_bytes()));
|
||||||
quote!(#(#aliases)|* => _serde::__private::Ok(#this_value::#ident))
|
quote!(#(#aliases)|* => _serde::__private::Ok(#this_value::#ident))
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use crate::internals::name::MultiName;
|
use crate::internals::name::{MultiName, Name};
|
||||||
use crate::internals::symbol::*;
|
use crate::internals::symbol::*;
|
||||||
use crate::internals::{ungroup, Ctxt};
|
use crate::internals::{ungroup, Ctxt};
|
||||||
use proc_macro2::{Spacing, Span, TokenStream, TokenTree};
|
use proc_macro2::{Spacing, Span, TokenStream, TokenTree};
|
||||||
@@ -131,8 +131,8 @@ impl<'c, T> VecAttr<'c, T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unraw(ident: &Ident) -> String {
|
fn unraw(ident: &Ident) -> Ident {
|
||||||
ident.to_string().trim_start_matches("r#").to_owned()
|
Ident::new(ident.to_string().trim_start_matches("r#"), ident.span())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
@@ -278,8 +278,8 @@ impl Container {
|
|||||||
// #[serde(rename = "foo")]
|
// #[serde(rename = "foo")]
|
||||||
// #[serde(rename(serialize = "foo", deserialize = "bar"))]
|
// #[serde(rename(serialize = "foo", deserialize = "bar"))]
|
||||||
let (ser, de) = get_renames(cx, RENAME, &meta)?;
|
let (ser, de) = get_renames(cx, RENAME, &meta)?;
|
||||||
ser_name.set_opt(&meta.path, ser.as_ref().map(syn::LitStr::value));
|
ser_name.set_opt(&meta.path, ser.as_ref().map(Name::from));
|
||||||
de_name.set_opt(&meta.path, de.as_ref().map(syn::LitStr::value));
|
de_name.set_opt(&meta.path, de.as_ref().map(Name::from));
|
||||||
} else if meta.path == RENAME_ALL {
|
} else if meta.path == RENAME_ALL {
|
||||||
// #[serde(rename_all = "foo")]
|
// #[serde(rename_all = "foo")]
|
||||||
// #[serde(rename_all(serialize = "foo", deserialize = "bar"))]
|
// #[serde(rename_all(serialize = "foo", deserialize = "bar"))]
|
||||||
@@ -518,7 +518,7 @@ impl Container {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Container {
|
Container {
|
||||||
name: MultiName::from_attrs(unraw(&item.ident), ser_name, de_name, None),
|
name: MultiName::from_attrs(Name::from(&unraw(&item.ident)), ser_name, de_name, None),
|
||||||
transparent: transparent.get(),
|
transparent: transparent.get(),
|
||||||
deny_unknown_fields: deny_unknown_fields.get(),
|
deny_unknown_fields: deny_unknown_fields.get(),
|
||||||
default: default.get().unwrap_or(Default::None),
|
default: default.get().unwrap_or(Default::None),
|
||||||
@@ -783,15 +783,15 @@ impl Variant {
|
|||||||
// #[serde(rename = "foo")]
|
// #[serde(rename = "foo")]
|
||||||
// #[serde(rename(serialize = "foo", deserialize = "bar"))]
|
// #[serde(rename(serialize = "foo", deserialize = "bar"))]
|
||||||
let (ser, de) = get_multiple_renames(cx, &meta)?;
|
let (ser, de) = get_multiple_renames(cx, &meta)?;
|
||||||
ser_name.set_opt(&meta.path, ser.as_ref().map(syn::LitStr::value));
|
ser_name.set_opt(&meta.path, ser.as_ref().map(Name::from));
|
||||||
for de_value in de {
|
for de_value in de {
|
||||||
de_name.set_if_none(de_value.value());
|
de_name.set_if_none(Name::from(&de_value));
|
||||||
de_aliases.insert(&meta.path, de_value.value());
|
de_aliases.insert(&meta.path, Name::from(&de_value));
|
||||||
}
|
}
|
||||||
} else if meta.path == ALIAS {
|
} else if meta.path == ALIAS {
|
||||||
// #[serde(alias = "foo")]
|
// #[serde(alias = "foo")]
|
||||||
if let Some(s) = get_lit_str(cx, ALIAS, &meta)? {
|
if let Some(s) = get_lit_str(cx, ALIAS, &meta)? {
|
||||||
de_aliases.insert(&meta.path, s.value());
|
de_aliases.insert(&meta.path, Name::from(&s));
|
||||||
}
|
}
|
||||||
} else if meta.path == RENAME_ALL {
|
} else if meta.path == RENAME_ALL {
|
||||||
// #[serde(rename_all = "foo")]
|
// #[serde(rename_all = "foo")]
|
||||||
@@ -898,7 +898,12 @@ impl Variant {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Variant {
|
Variant {
|
||||||
name: MultiName::from_attrs(unraw(&variant.ident), ser_name, de_name, Some(de_aliases)),
|
name: MultiName::from_attrs(
|
||||||
|
Name::from(&unraw(&variant.ident)),
|
||||||
|
ser_name,
|
||||||
|
de_name,
|
||||||
|
Some(de_aliases),
|
||||||
|
),
|
||||||
rename_all_rules: RenameAllRules {
|
rename_all_rules: RenameAllRules {
|
||||||
serialize: rename_all_ser_rule.get().unwrap_or(RenameRule::None),
|
serialize: rename_all_ser_rule.get().unwrap_or(RenameRule::None),
|
||||||
deserialize: rename_all_de_rule.get().unwrap_or(RenameRule::None),
|
deserialize: rename_all_de_rule.get().unwrap_or(RenameRule::None),
|
||||||
@@ -919,16 +924,19 @@ impl Variant {
|
|||||||
&self.name
|
&self.name
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn aliases(&self) -> &BTreeSet<String> {
|
pub fn aliases(&self) -> &BTreeSet<Name> {
|
||||||
self.name.deserialize_aliases()
|
self.name.deserialize_aliases()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rename_by_rules(&mut self, rules: RenameAllRules) {
|
pub fn rename_by_rules(&mut self, rules: RenameAllRules) {
|
||||||
if !self.name.serialize_renamed {
|
if !self.name.serialize_renamed {
|
||||||
self.name.serialize = rules.serialize.apply_to_variant(&self.name.serialize);
|
self.name.serialize.value =
|
||||||
|
rules.serialize.apply_to_variant(&self.name.serialize.value);
|
||||||
}
|
}
|
||||||
if !self.name.deserialize_renamed {
|
if !self.name.deserialize_renamed {
|
||||||
self.name.deserialize = rules.deserialize.apply_to_variant(&self.name.deserialize);
|
self.name.deserialize.value = rules
|
||||||
|
.deserialize
|
||||||
|
.apply_to_variant(&self.name.deserialize.value);
|
||||||
}
|
}
|
||||||
self.name
|
self.name
|
||||||
.deserialize_aliases
|
.deserialize_aliases
|
||||||
@@ -1033,8 +1041,11 @@ impl Field {
|
|||||||
let mut flatten = BoolAttr::none(cx, FLATTEN);
|
let mut flatten = BoolAttr::none(cx, FLATTEN);
|
||||||
|
|
||||||
let ident = match &field.ident {
|
let ident = match &field.ident {
|
||||||
Some(ident) => unraw(ident),
|
Some(ident) => Name::from(&unraw(ident)),
|
||||||
None => index.to_string(),
|
None => Name {
|
||||||
|
value: index.to_string(),
|
||||||
|
span: Span::call_site(),
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(borrow_attribute) = attrs.and_then(|variant| variant.borrow.as_ref()) {
|
if let Some(borrow_attribute) = attrs.and_then(|variant| variant.borrow.as_ref()) {
|
||||||
@@ -1070,15 +1081,15 @@ impl Field {
|
|||||||
// #[serde(rename = "foo")]
|
// #[serde(rename = "foo")]
|
||||||
// #[serde(rename(serialize = "foo", deserialize = "bar"))]
|
// #[serde(rename(serialize = "foo", deserialize = "bar"))]
|
||||||
let (ser, de) = get_multiple_renames(cx, &meta)?;
|
let (ser, de) = get_multiple_renames(cx, &meta)?;
|
||||||
ser_name.set_opt(&meta.path, ser.as_ref().map(syn::LitStr::value));
|
ser_name.set_opt(&meta.path, ser.as_ref().map(Name::from));
|
||||||
for de_value in de {
|
for de_value in de {
|
||||||
de_name.set_if_none(de_value.value());
|
de_name.set_if_none(Name::from(&de_value));
|
||||||
de_aliases.insert(&meta.path, de_value.value());
|
de_aliases.insert(&meta.path, Name::from(&de_value));
|
||||||
}
|
}
|
||||||
} else if meta.path == ALIAS {
|
} else if meta.path == ALIAS {
|
||||||
// #[serde(alias = "foo")]
|
// #[serde(alias = "foo")]
|
||||||
if let Some(s) = get_lit_str(cx, ALIAS, &meta)? {
|
if let Some(s) = get_lit_str(cx, ALIAS, &meta)? {
|
||||||
de_aliases.insert(&meta.path, s.value());
|
de_aliases.insert(&meta.path, Name::from(&s));
|
||||||
}
|
}
|
||||||
} else if meta.path == DEFAULT {
|
} else if meta.path == DEFAULT {
|
||||||
if meta.input.peek(Token![=]) {
|
if meta.input.peek(Token![=]) {
|
||||||
@@ -1261,16 +1272,18 @@ impl Field {
|
|||||||
&self.name
|
&self.name
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn aliases(&self) -> &BTreeSet<String> {
|
pub fn aliases(&self) -> &BTreeSet<Name> {
|
||||||
self.name.deserialize_aliases()
|
self.name.deserialize_aliases()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rename_by_rules(&mut self, rules: RenameAllRules) {
|
pub fn rename_by_rules(&mut self, rules: RenameAllRules) {
|
||||||
if !self.name.serialize_renamed {
|
if !self.name.serialize_renamed {
|
||||||
self.name.serialize = rules.serialize.apply_to_field(&self.name.serialize);
|
self.name.serialize.value = rules.serialize.apply_to_field(&self.name.serialize.value);
|
||||||
}
|
}
|
||||||
if !self.name.deserialize_renamed {
|
if !self.name.deserialize_renamed {
|
||||||
self.name.deserialize = rules.deserialize.apply_to_field(&self.name.deserialize);
|
self.name.deserialize.value = rules
|
||||||
|
.deserialize
|
||||||
|
.apply_to_field(&self.name.deserialize.value);
|
||||||
}
|
}
|
||||||
self.name
|
self.name
|
||||||
.deserialize_aliases
|
.deserialize_aliases
|
||||||
@@ -1720,7 +1733,7 @@ fn is_primitive_path(path: &syn::Path, primitive: &str) -> bool {
|
|||||||
// attribute on the field so there must be at least one borrowable lifetime.
|
// attribute on the field so there must be at least one borrowable lifetime.
|
||||||
fn borrowable_lifetimes(
|
fn borrowable_lifetimes(
|
||||||
cx: &Ctxt,
|
cx: &Ctxt,
|
||||||
name: &str,
|
name: &Name,
|
||||||
field: &syn::Field,
|
field: &syn::Field,
|
||||||
) -> Result<BTreeSet<syn::Lifetime>, ()> {
|
) -> Result<BTreeSet<syn::Lifetime>, ()> {
|
||||||
let mut lifetimes = BTreeSet::new();
|
let mut lifetimes = BTreeSet::new();
|
||||||
|
|||||||
@@ -332,13 +332,13 @@ fn check_internal_tag_field_name_conflict(cx: &Ctxt, cont: &Container) {
|
|||||||
let name = field.attrs.name();
|
let name = field.attrs.name();
|
||||||
let ser_name = name.serialize_name();
|
let ser_name = name.serialize_name();
|
||||||
|
|
||||||
if check_ser && ser_name == tag {
|
if check_ser && ser_name.value == tag {
|
||||||
diagnose_conflict();
|
diagnose_conflict();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for de_name in field.attrs.aliases() {
|
for de_name in field.attrs.aliases() {
|
||||||
if check_de && de_name == tag {
|
if check_de && de_name.value == tag {
|
||||||
diagnose_conflict();
|
diagnose_conflict();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
pub mod ast;
|
pub mod ast;
|
||||||
pub mod attr;
|
pub mod attr;
|
||||||
|
pub mod name;
|
||||||
|
|
||||||
mod case;
|
mod case;
|
||||||
mod check;
|
mod check;
|
||||||
mod ctxt;
|
mod ctxt;
|
||||||
mod name;
|
|
||||||
mod receiver;
|
mod receiver;
|
||||||
mod respan;
|
mod respan;
|
||||||
mod symbol;
|
mod symbol;
|
||||||
|
|||||||
@@ -1,20 +1,25 @@
|
|||||||
use crate::internals::attr::{Attr, VecAttr};
|
use crate::internals::attr::{Attr, VecAttr};
|
||||||
|
use proc_macro2::{Ident, Span, TokenStream};
|
||||||
|
use quote::ToTokens;
|
||||||
|
use std::cmp::Ordering;
|
||||||
use std::collections::BTreeSet;
|
use std::collections::BTreeSet;
|
||||||
|
use std::fmt::{self, Display};
|
||||||
|
use syn::LitStr;
|
||||||
|
|
||||||
pub struct MultiName {
|
pub struct MultiName {
|
||||||
pub(crate) serialize: String,
|
pub(crate) serialize: Name,
|
||||||
pub(crate) serialize_renamed: bool,
|
pub(crate) serialize_renamed: bool,
|
||||||
pub(crate) deserialize: String,
|
pub(crate) deserialize: Name,
|
||||||
pub(crate) deserialize_renamed: bool,
|
pub(crate) deserialize_renamed: bool,
|
||||||
pub(crate) deserialize_aliases: BTreeSet<String>,
|
pub(crate) deserialize_aliases: BTreeSet<Name>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MultiName {
|
impl MultiName {
|
||||||
pub(crate) fn from_attrs(
|
pub(crate) fn from_attrs(
|
||||||
source_name: String,
|
source_name: Name,
|
||||||
ser_name: Attr<String>,
|
ser_name: Attr<Name>,
|
||||||
de_name: Attr<String>,
|
de_name: Attr<Name>,
|
||||||
de_aliases: Option<VecAttr<String>>,
|
de_aliases: Option<VecAttr<Name>>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let mut alias_set = BTreeSet::new();
|
let mut alias_set = BTreeSet::new();
|
||||||
if let Some(de_aliases) = de_aliases {
|
if let Some(de_aliases) = de_aliases {
|
||||||
@@ -37,16 +42,72 @@ impl MultiName {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Return the container name for the container when serializing.
|
/// Return the container name for the container when serializing.
|
||||||
pub fn serialize_name(&self) -> &str {
|
pub fn serialize_name(&self) -> &Name {
|
||||||
&self.serialize
|
&self.serialize
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the container name for the container when deserializing.
|
/// Return the container name for the container when deserializing.
|
||||||
pub fn deserialize_name(&self) -> &str {
|
pub fn deserialize_name(&self) -> &Name {
|
||||||
&self.deserialize
|
&self.deserialize
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn deserialize_aliases(&self) -> &BTreeSet<String> {
|
pub(crate) fn deserialize_aliases(&self) -> &BTreeSet<Name> {
|
||||||
&self.deserialize_aliases
|
&self.deserialize_aliases
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct Name {
|
||||||
|
pub value: String,
|
||||||
|
pub span: Span,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToTokens for Name {
|
||||||
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||||
|
LitStr::new(&self.value, self.span).to_tokens(tokens);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Ord for Name {
|
||||||
|
fn cmp(&self, other: &Self) -> Ordering {
|
||||||
|
Ord::cmp(&self.value, &other.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialOrd for Name {
|
||||||
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||||
|
Some(Ord::cmp(self, other))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Eq for Name {}
|
||||||
|
|
||||||
|
impl PartialEq for Name {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
self.value == other.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&Ident> for Name {
|
||||||
|
fn from(ident: &Ident) -> Self {
|
||||||
|
Name {
|
||||||
|
value: ident.to_string(),
|
||||||
|
span: ident.span(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&LitStr> for Name {
|
||||||
|
fn from(lit: &LitStr) -> Self {
|
||||||
|
Name {
|
||||||
|
value: lit.value(),
|
||||||
|
span: lit.span(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for Name {
|
||||||
|
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
Display::fmt(&self.value, formatter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
use crate::fragment::{Fragment, Match, Stmts};
|
use crate::fragment::{Fragment, Match, Stmts};
|
||||||
use crate::internals::ast::{Container, Data, Field, Style, Variant};
|
use crate::internals::ast::{Container, Data, Field, Style, Variant};
|
||||||
|
use crate::internals::name::Name;
|
||||||
use crate::internals::{attr, replace_receiver, Ctxt, Derive};
|
use crate::internals::{attr, replace_receiver, Ctxt, Derive};
|
||||||
use crate::{bound, dummy, pretend, this};
|
use crate::{bound, dummy, pretend, this};
|
||||||
use proc_macro2::{Span, TokenStream};
|
use proc_macro2::{Span, TokenStream};
|
||||||
@@ -798,9 +799,9 @@ fn serialize_untagged_variant(
|
|||||||
|
|
||||||
enum TupleVariant<'a> {
|
enum TupleVariant<'a> {
|
||||||
ExternallyTagged {
|
ExternallyTagged {
|
||||||
type_name: &'a str,
|
type_name: &'a Name,
|
||||||
variant_index: u32,
|
variant_index: u32,
|
||||||
variant_name: &'a str,
|
variant_name: &'a Name,
|
||||||
},
|
},
|
||||||
Untagged,
|
Untagged,
|
||||||
}
|
}
|
||||||
@@ -867,11 +868,11 @@ fn serialize_tuple_variant(
|
|||||||
enum StructVariant<'a> {
|
enum StructVariant<'a> {
|
||||||
ExternallyTagged {
|
ExternallyTagged {
|
||||||
variant_index: u32,
|
variant_index: u32,
|
||||||
variant_name: &'a str,
|
variant_name: &'a Name,
|
||||||
},
|
},
|
||||||
InternallyTagged {
|
InternallyTagged {
|
||||||
tag: &'a str,
|
tag: &'a str,
|
||||||
variant_name: &'a str,
|
variant_name: &'a Name,
|
||||||
},
|
},
|
||||||
Untagged,
|
Untagged,
|
||||||
}
|
}
|
||||||
@@ -880,7 +881,7 @@ fn serialize_struct_variant(
|
|||||||
context: StructVariant,
|
context: StructVariant,
|
||||||
params: &Parameters,
|
params: &Parameters,
|
||||||
fields: &[Field],
|
fields: &[Field],
|
||||||
name: &str,
|
name: &Name,
|
||||||
) -> Fragment {
|
) -> Fragment {
|
||||||
if fields.iter().any(|field| field.attrs.flatten()) {
|
if fields.iter().any(|field| field.attrs.flatten()) {
|
||||||
return serialize_struct_variant_with_flatten(context, params, fields, name);
|
return serialize_struct_variant_with_flatten(context, params, fields, name);
|
||||||
@@ -964,7 +965,7 @@ fn serialize_struct_variant_with_flatten(
|
|||||||
context: StructVariant,
|
context: StructVariant,
|
||||||
params: &Parameters,
|
params: &Parameters,
|
||||||
fields: &[Field],
|
fields: &[Field],
|
||||||
name: &str,
|
name: &Name,
|
||||||
) -> Fragment {
|
) -> Fragment {
|
||||||
let struct_trait = StructTrait::SerializeMap;
|
let struct_trait = StructTrait::SerializeMap;
|
||||||
let serialize_fields = serialize_struct_visitor(fields, params, true, &struct_trait);
|
let serialize_fields = serialize_struct_visitor(fields, params, true, &struct_trait);
|
||||||
|
|||||||
Reference in New Issue
Block a user