mirror of
https://github.com/swc-project/swc.git
synced 2024-12-23 21:54:36 +03:00
Make deserialization faster (#324)
swc_ecma_ast: - make deserialization faster
This commit is contained in:
parent
dd5f17463e
commit
248a53ce7c
@ -1,4 +1,4 @@
|
||||
required_version = "1.0.1"
|
||||
required_version = "1.0.3"
|
||||
use_field_init_shorthand = true
|
||||
merge_imports = true
|
||||
wrap_comments = true
|
||||
|
@ -15,7 +15,6 @@ use swc_common::Fold;
|
||||
use swc_common::{ast_node, Span};
|
||||
|
||||
#[ast_node]
|
||||
#[derive(Deserialize)]
|
||||
pub struct Class {
|
||||
#[serde(default)]
|
||||
pub span: Span,
|
||||
|
@ -4,12 +4,10 @@ use crate::{
|
||||
stmt::BlockStmt,
|
||||
typescript::{TsParamProp, TsTypeAnn, TsTypeParamDecl},
|
||||
};
|
||||
use serde::Deserialize;
|
||||
use swc_common::{ast_node, Span};
|
||||
|
||||
/// Common parts of function and method.
|
||||
#[ast_node]
|
||||
#[derive(Deserialize)]
|
||||
pub struct Function {
|
||||
pub params: Vec<Pat>,
|
||||
|
||||
|
@ -117,7 +117,7 @@ fn error_tests(tests: &mut Vec<TestDescAndFn>) -> Result<(), io::Error> {
|
||||
|
||||
const TYPES: &[&str] = &[
|
||||
"fail", /* TODO
|
||||
* "early" */
|
||||
* "early" */
|
||||
];
|
||||
|
||||
for err_type in TYPES {
|
||||
|
@ -273,8 +273,7 @@ test!(
|
||||
{a6, a7} = {}) {}"#,
|
||||
"function fn(a1, param, param1, a5, param2) {
|
||||
var a2 = param === void 0 ? 4 : param, ref = param1 ? param1 : _throw(new TypeError(\"Cannot \
|
||||
destructure 'undefined' or 'null'\")), a3 = ref.a3, a4 = ref.a4, ref1 = param2 === void 0 ? \
|
||||
{
|
||||
destructure 'undefined' or 'null'\")), a3 = ref.a3, a4 = ref.a4, ref1 = param2 === void 0 ? {
|
||||
} : param2, ref2 = ref1 ? ref1 : _throw(new TypeError(\"Cannot destructure 'undefined' or \
|
||||
'null'\")), a6 = ref2.a6, a7 = ref2.a7;
|
||||
}
|
||||
|
@ -17,184 +17,10 @@ impl Parse for Args {
|
||||
}
|
||||
}
|
||||
|
||||
struct VariantAttr {
|
||||
_paren_token: token::Paren,
|
||||
tags: Punctuated<Lit, Token![,]>,
|
||||
}
|
||||
|
||||
impl Parse for VariantAttr {
|
||||
fn parse(input: ParseStream) -> syn::Result<Self> {
|
||||
let content;
|
||||
Ok(VariantAttr {
|
||||
_paren_token: parenthesized!(content in input),
|
||||
tags: content.parse_terminated(Lit::parse)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn expand_enum(
|
||||
DeriveInput {
|
||||
generics,
|
||||
ident,
|
||||
data,
|
||||
..
|
||||
}: DeriveInput,
|
||||
) -> Vec<ItemImpl> {
|
||||
let data = match data {
|
||||
Data::Enum(data) => data,
|
||||
_ => unreachable!("expand_enum is called with none-enum item"),
|
||||
};
|
||||
|
||||
let deserialize = {
|
||||
let mut all_tags: Punctuated<_, token::Comma> = Default::default();
|
||||
let mut match_type = data
|
||||
.variants
|
||||
.iter()
|
||||
.map(|variant| {
|
||||
let field_type = match variant.fields {
|
||||
Fields::Unnamed(ref fields) => {
|
||||
assert!(
|
||||
fields.unnamed.len() == 1,
|
||||
"#[ast_node] enum cannot contain variant with multiple fields"
|
||||
);
|
||||
|
||||
fields.unnamed.last().unwrap().into_value().ty.clone()
|
||||
}
|
||||
_ => {
|
||||
unreachable!("#[ast_node] enum cannot contain named fields or unit variant")
|
||||
}
|
||||
};
|
||||
let tags = variant
|
||||
.attrs
|
||||
.iter()
|
||||
.filter_map(|attr| -> Option<VariantAttr> {
|
||||
if !is_attr_name(attr, "tag") {
|
||||
return None;
|
||||
}
|
||||
let tags =
|
||||
parse2(attr.tts.clone()).expect("failed to parse #[tag] attribute");
|
||||
|
||||
Some(tags)
|
||||
})
|
||||
.flat_map(|v| v.tags)
|
||||
.collect::<Punctuated<_, token::Comma>>();
|
||||
|
||||
assert!(
|
||||
tags.len() >= 1,
|
||||
"All #[ast_node] enum variants have one or more tag"
|
||||
);
|
||||
if tags.len() == 1
|
||||
&& match tags.first().map(Pair::into_value) {
|
||||
Some(Lit::Str(s)) => &*s.value() == "*",
|
||||
_ => false,
|
||||
}
|
||||
{
|
||||
Quote::new_call_site()
|
||||
.quote_with(smart_quote!(
|
||||
Vars {
|
||||
Enum: &ident,
|
||||
Variant: &variant.ident,
|
||||
VariantFieldType: &field_type,
|
||||
},
|
||||
{
|
||||
if let Ok(v) = std::result::Result::map(
|
||||
<VariantFieldType as serde::Deserialize>::deserialize(
|
||||
serde::private::de::ContentRefDeserializer::<D::Error>::new(
|
||||
&content,
|
||||
),
|
||||
),
|
||||
Enum::Variant,
|
||||
) {
|
||||
return Ok(v);
|
||||
}
|
||||
}
|
||||
))
|
||||
.parse()
|
||||
} else {
|
||||
for tag in tags.iter() {
|
||||
all_tags.push(tag.clone());
|
||||
}
|
||||
Quote::new_call_site()
|
||||
.quote_with(smart_quote!(
|
||||
Vars {
|
||||
Enum: &ident,
|
||||
Variant: &variant.ident,
|
||||
VariantFieldType: &field_type,
|
||||
tags,
|
||||
},
|
||||
{
|
||||
{
|
||||
const TAGS: &[&str] = &[tags];
|
||||
if TAGS.contains(&&*ty.ty) {
|
||||
if let Ok(v) = std::result::Result::map(
|
||||
<VariantFieldType as serde::Deserialize>::deserialize(
|
||||
serde::private::de::ContentRefDeserializer::<
|
||||
D::Error,
|
||||
>::new(
|
||||
&content
|
||||
),
|
||||
),
|
||||
Enum::Variant,
|
||||
) {
|
||||
return Ok(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
))
|
||||
.parse()
|
||||
}
|
||||
})
|
||||
.collect::<Vec<Expr>>();
|
||||
|
||||
let mut match_type_expr = Quote::new_call_site();
|
||||
for expr in match_type {
|
||||
match_type_expr = match_type_expr.quote_with(smart_quote!(Vars { expr }, { expr }));
|
||||
}
|
||||
|
||||
match_type_expr = match_type_expr.quote_with(smart_quote!(Vars { all_tags }, {
|
||||
return Err(serde::de::Error::unknown_variant(&ty.ty, &[all_tags]));
|
||||
}));
|
||||
|
||||
Quote::new_call_site()
|
||||
.quote_with(smart_quote!(
|
||||
Vars {
|
||||
match_type_expr,
|
||||
Enum: &ident
|
||||
},
|
||||
{
|
||||
impl<'de> serde::Deserialize<'de> for Enum {
|
||||
fn deserialize<D>(Deserializer: D) -> ::std::result::Result<Self, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
let content =
|
||||
<serde::private::de::Content as serde::Deserialize>::deserialize(
|
||||
Deserializer,
|
||||
)?;
|
||||
|
||||
let ty = swc_common::serializer::Type::deserialize(
|
||||
serde::private::de::ContentRefDeserializer::<D::Error>::new(
|
||||
&content,
|
||||
),
|
||||
)?;
|
||||
|
||||
match_type_expr
|
||||
}
|
||||
}
|
||||
}
|
||||
))
|
||||
.parse::<ItemImpl>()
|
||||
.with_generics(generics.clone())
|
||||
};
|
||||
|
||||
vec![deserialize]
|
||||
}
|
||||
|
||||
pub fn expand_struct(args: Args, i: DeriveInput) -> Vec<ItemImpl> {
|
||||
let mut items = vec![];
|
||||
let generics = i.generics.clone();
|
||||
let item_ident = Ident::new("Item", i.ident.span());
|
||||
// let item_ident = Ident::new("Item", i.ident.span());
|
||||
|
||||
items.push(
|
||||
Quote::new_call_site()
|
||||
@ -213,132 +39,133 @@ pub fn expand_struct(args: Args, i: DeriveInput) -> Vec<ItemImpl> {
|
||||
.with_generics(generics.clone()),
|
||||
);
|
||||
|
||||
let ident = i.ident.clone();
|
||||
let cloned = i.clone();
|
||||
// let ident = i.ident.clone();
|
||||
// let cloned = i.clone();
|
||||
|
||||
items.push({
|
||||
let (fields, item_data) = match i.data {
|
||||
Data::Struct(DataStruct {
|
||||
struct_token,
|
||||
semi_token,
|
||||
fields: Fields::Named(FieldsNamed { brace_token, named }),
|
||||
}) => {
|
||||
let fields: Punctuated<_, token::Comma> = named
|
||||
.clone()
|
||||
.into_iter()
|
||||
.map(|field| FieldValue {
|
||||
member: Member::Named(field.ident.clone().unwrap()),
|
||||
expr: Quote::new_call_site()
|
||||
.quote_with(smart_quote!(
|
||||
Vars {
|
||||
field: &field.ident
|
||||
},
|
||||
{ node.node.field }
|
||||
))
|
||||
.parse(),
|
||||
// items.push({
|
||||
// let (fields, item_data) = match i.data {
|
||||
// Data::Struct(DataStruct {
|
||||
// struct_token,
|
||||
// semi_token,
|
||||
// fields: Fields::Named(FieldsNamed { brace_token, named }),
|
||||
// }) => {
|
||||
// let fields: Punctuated<_, token::Comma> = named
|
||||
// .clone()
|
||||
// .into_iter()
|
||||
// .map(|field| FieldValue {
|
||||
// member: Member::Named(field.ident.clone().unwrap()),
|
||||
// expr: Quote::new_call_site()
|
||||
// .quote_with(smart_quote!(
|
||||
// Vars {
|
||||
// field: &field.ident
|
||||
// },
|
||||
// { node.node.field }
|
||||
// ))
|
||||
// .parse(),
|
||||
|
||||
attrs: field
|
||||
.attrs
|
||||
.into_iter()
|
||||
.filter(|attr| is_attr_name(attr, "cfg"))
|
||||
.collect(),
|
||||
colon_token: Some(call_site()),
|
||||
})
|
||||
.collect();
|
||||
// attrs: field
|
||||
// .attrs
|
||||
// .into_iter()
|
||||
// .filter(|attr| is_attr_name(attr, "cfg"))
|
||||
// .collect(),
|
||||
// colon_token: Some(call_site()),
|
||||
// })
|
||||
// .collect();
|
||||
|
||||
let item_data = Data::Struct(DataStruct {
|
||||
struct_token,
|
||||
semi_token,
|
||||
fields: Fields::Named(FieldsNamed {
|
||||
brace_token,
|
||||
named: named
|
||||
.into_pairs()
|
||||
.map(|pair| {
|
||||
let handle = |v: Field| Field {
|
||||
vis: Visibility::Inherited,
|
||||
attrs: v
|
||||
.attrs
|
||||
.into_iter()
|
||||
.filter(|attr| {
|
||||
is_attr_name(attr, "serde") || is_attr_name(attr, "cfg")
|
||||
})
|
||||
.collect(),
|
||||
..v
|
||||
};
|
||||
// let item_data = Data::Struct(DataStruct {
|
||||
// struct_token,
|
||||
// semi_token,
|
||||
// fields: Fields::Named(FieldsNamed {
|
||||
// brace_token,
|
||||
// named: named
|
||||
// .into_pairs()
|
||||
// .map(|pair| {
|
||||
// let handle = |v: Field| Field {
|
||||
// vis: Visibility::Inherited,
|
||||
// attrs: v
|
||||
// .attrs
|
||||
// .into_iter()
|
||||
// .filter(|attr| {
|
||||
// is_attr_name(attr, "serde") ||
|
||||
// is_attr_name(attr, "cfg") })
|
||||
// .collect(),
|
||||
// ..v
|
||||
// };
|
||||
|
||||
match pair {
|
||||
Pair::End(v) => Pair::End(handle(v)),
|
||||
Pair::Punctuated(v, p) => Pair::Punctuated(handle(v), p),
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
}),
|
||||
});
|
||||
// match pair {
|
||||
// Pair::End(v) => Pair::End(handle(v)),
|
||||
// Pair::Punctuated(v, p) =>
|
||||
// Pair::Punctuated(handle(v), p), }
|
||||
// })
|
||||
// .collect(),
|
||||
// }),
|
||||
// });
|
||||
|
||||
(fields, item_data)
|
||||
}
|
||||
_ => unreachable!("enum / tuple struct / union with #[ast_node(\"Foo\")]"),
|
||||
};
|
||||
// (fields, item_data)
|
||||
// }
|
||||
// _ => unreachable!("enum / tuple struct / union with
|
||||
// #[ast_node(\"Foo\")]"), };
|
||||
|
||||
let convert_item_to_self = Quote::new_call_site().quote_with(smart_quote!(
|
||||
Vars {
|
||||
fields,
|
||||
Type: &ident
|
||||
},
|
||||
{ Type { fields } }
|
||||
));
|
||||
// let convert_item_to_self =
|
||||
// Quote::new_call_site().quote_with(smart_quote!( Vars {
|
||||
// fields,
|
||||
// Type: &ident
|
||||
// },
|
||||
// { Type { fields } }
|
||||
// ));
|
||||
|
||||
let body = Quote::new_call_site().quote_with(smart_quote!(
|
||||
Vars {
|
||||
convert_item_to_self
|
||||
},
|
||||
{
|
||||
let node = ::swc_common::serializer::Node::<Item>::deserialize(deserializer)?;
|
||||
// let body = Quote::new_call_site().quote_with(smart_quote!(
|
||||
// Vars {
|
||||
// convert_item_to_self
|
||||
// },
|
||||
// {
|
||||
// let node =
|
||||
// ::swc_common::serializer::Node::<Item>::deserialize(deserializer)?;
|
||||
|
||||
if node.ty != <Self as ::swc_common::AstNode>::TYPE {
|
||||
return Err(D::Error::unknown_variant(
|
||||
&node.ty,
|
||||
&[<Self as ::swc_common::AstNode>::TYPE],
|
||||
));
|
||||
}
|
||||
// if node.ty != <Self as ::swc_common::AstNode>::TYPE {
|
||||
// return Err(D::Error::unknown_variant(
|
||||
// &node.ty,
|
||||
// &[<Self as ::swc_common::AstNode>::TYPE],
|
||||
// ));
|
||||
// }
|
||||
|
||||
Ok(convert_item_to_self)
|
||||
}
|
||||
));
|
||||
// Ok(convert_item_to_self)
|
||||
// }
|
||||
// ));
|
||||
|
||||
let item = DeriveInput {
|
||||
vis: Visibility::Inherited,
|
||||
ident: item_ident,
|
||||
attrs: vec![],
|
||||
data: item_data,
|
||||
..cloned
|
||||
};
|
||||
Quote::new_call_site()
|
||||
.quote_with(smart_quote!(
|
||||
Vars {
|
||||
// A new item which implements Deserialize
|
||||
item,
|
||||
Type: ident,
|
||||
body
|
||||
},
|
||||
{
|
||||
impl<'de> ::serde::Deserialize<'de> for Type {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: ::serde::Deserializer<'de>,
|
||||
{
|
||||
use ::serde::de::Error;
|
||||
#[derive(::serde::Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
item
|
||||
body
|
||||
}
|
||||
}
|
||||
}
|
||||
))
|
||||
.parse::<ItemImpl>()
|
||||
.with_generics(generics)
|
||||
});
|
||||
// let item = DeriveInput {
|
||||
// vis: Visibility::Inherited,
|
||||
// ident: item_ident,
|
||||
// attrs: vec![],
|
||||
// data: item_data,
|
||||
// ..cloned
|
||||
// };
|
||||
// Quote::new_call_site()
|
||||
// .quote_with(smart_quote!(
|
||||
// Vars {
|
||||
// // A new item which implements Deserialize
|
||||
// item,
|
||||
// Type: ident,
|
||||
// body
|
||||
// },
|
||||
// {
|
||||
// impl<'de> ::serde::Deserialize<'de> for Type {
|
||||
// fn deserialize<D>(deserializer: D) -> Result<Self,
|
||||
// D::Error> where
|
||||
// D: ::serde::Deserializer<'de>,
|
||||
// {
|
||||
// use ::serde::de::Error;
|
||||
// #[derive(::serde::Deserialize)]
|
||||
// #[serde(rename_all = "camelCase")]
|
||||
// ite
|
||||
// body
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// ))
|
||||
// .parse::<ItemImpl>()
|
||||
// .with_generics(generics)
|
||||
// });
|
||||
|
||||
items
|
||||
}
|
||||
|
180
macros/ast_node/src/enum_deserialize.rs
Normal file
180
macros/ast_node/src/enum_deserialize.rs
Normal file
@ -0,0 +1,180 @@
|
||||
use pmutil::Quote;
|
||||
use swc_macros_common::prelude::*;
|
||||
use syn::{
|
||||
self,
|
||||
parse::{Parse, ParseStream},
|
||||
*,
|
||||
};
|
||||
struct VariantAttr {
|
||||
_paren_token: token::Paren,
|
||||
tags: Punctuated<Lit, Token![,]>,
|
||||
}
|
||||
|
||||
impl Parse for VariantAttr {
|
||||
fn parse(input: ParseStream) -> syn::Result<Self> {
|
||||
let content;
|
||||
Ok(VariantAttr {
|
||||
_paren_token: parenthesized!(content in input),
|
||||
tags: content.parse_terminated(Lit::parse)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn expand(
|
||||
DeriveInput {
|
||||
generics,
|
||||
ident,
|
||||
data,
|
||||
..
|
||||
}: DeriveInput,
|
||||
) -> Vec<ItemImpl> {
|
||||
let data = match data {
|
||||
Data::Enum(data) => data,
|
||||
_ => unreachable!("expand_enum is called with none-enum item"),
|
||||
};
|
||||
|
||||
let deserialize = {
|
||||
let mut all_tags: Punctuated<_, token::Comma> = Default::default();
|
||||
let mut match_type = data
|
||||
.variants
|
||||
.iter()
|
||||
.map(|variant| {
|
||||
let field_type = match variant.fields {
|
||||
Fields::Unnamed(ref fields) => {
|
||||
assert!(
|
||||
fields.unnamed.len() == 1,
|
||||
"#[ast_node] enum cannot contain variant with multiple fields"
|
||||
);
|
||||
|
||||
fields.unnamed.last().unwrap().into_value().ty.clone()
|
||||
}
|
||||
_ => {
|
||||
unreachable!("#[ast_node] enum cannot contain named fields or unit variant")
|
||||
}
|
||||
};
|
||||
let tags = variant
|
||||
.attrs
|
||||
.iter()
|
||||
.filter_map(|attr| -> Option<VariantAttr> {
|
||||
if !is_attr_name(attr, "tag") {
|
||||
return None;
|
||||
}
|
||||
let tags =
|
||||
parse2(attr.tts.clone()).expect("failed to parse #[tag] attribute");
|
||||
|
||||
Some(tags)
|
||||
})
|
||||
.flat_map(|v| v.tags)
|
||||
.collect::<Punctuated<_, token::Comma>>();
|
||||
|
||||
assert!(
|
||||
tags.len() >= 1,
|
||||
"All #[ast_node] enum variants have one or more tag"
|
||||
);
|
||||
if tags.len() == 1
|
||||
&& match tags.first().map(Pair::into_value) {
|
||||
Some(Lit::Str(s)) => &*s.value() == "*",
|
||||
_ => false,
|
||||
}
|
||||
{
|
||||
Quote::new_call_site()
|
||||
.quote_with(smart_quote!(
|
||||
Vars {
|
||||
Enum: &ident,
|
||||
Variant: &variant.ident,
|
||||
VariantFieldType: &field_type,
|
||||
},
|
||||
{
|
||||
if let Ok(v) = std::result::Result::map(
|
||||
<VariantFieldType as serde::Deserialize>::deserialize(
|
||||
serde::private::de::ContentRefDeserializer::<D::Error>::new(
|
||||
&content,
|
||||
),
|
||||
),
|
||||
Enum::Variant,
|
||||
) {
|
||||
return Ok(v);
|
||||
}
|
||||
}
|
||||
))
|
||||
.parse()
|
||||
} else {
|
||||
for tag in tags.iter() {
|
||||
all_tags.push(tag.clone());
|
||||
}
|
||||
Quote::new_call_site()
|
||||
.quote_with(smart_quote!(
|
||||
Vars {
|
||||
Enum: &ident,
|
||||
Variant: &variant.ident,
|
||||
VariantFieldType: &field_type,
|
||||
tags,
|
||||
},
|
||||
{
|
||||
{
|
||||
const TAGS: &[&str] = &[tags];
|
||||
if TAGS.contains(&&*ty.ty) {
|
||||
if let Ok(v) = std::result::Result::map(
|
||||
<VariantFieldType as serde::Deserialize>::deserialize(
|
||||
serde::private::de::ContentRefDeserializer::<
|
||||
D::Error,
|
||||
>::new(
|
||||
&content
|
||||
),
|
||||
),
|
||||
Enum::Variant,
|
||||
) {
|
||||
return Ok(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
))
|
||||
.parse()
|
||||
}
|
||||
})
|
||||
.collect::<Vec<Expr>>();
|
||||
|
||||
let mut match_type_expr = Quote::new_call_site();
|
||||
for expr in match_type {
|
||||
match_type_expr = match_type_expr.quote_with(smart_quote!(Vars { expr }, { expr }));
|
||||
}
|
||||
|
||||
match_type_expr = match_type_expr.quote_with(smart_quote!(Vars { all_tags }, {
|
||||
return Err(serde::de::Error::unknown_variant(&ty.ty, &[all_tags]));
|
||||
}));
|
||||
|
||||
Quote::new_call_site()
|
||||
.quote_with(smart_quote!(
|
||||
Vars {
|
||||
match_type_expr,
|
||||
Enum: &ident
|
||||
},
|
||||
{
|
||||
impl<'de> serde::Deserialize<'de> for Enum {
|
||||
fn deserialize<D>(Deserializer: D) -> ::std::result::Result<Self, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
let content =
|
||||
<serde::private::de::Content as serde::Deserialize>::deserialize(
|
||||
Deserializer,
|
||||
)?;
|
||||
|
||||
let ty = swc_common::serializer::Type::deserialize(
|
||||
serde::private::de::ContentRefDeserializer::<D::Error>::new(
|
||||
&content,
|
||||
),
|
||||
)?;
|
||||
|
||||
match_type_expr
|
||||
}
|
||||
}
|
||||
}
|
||||
))
|
||||
.parse::<ItemImpl>()
|
||||
.with_generics(generics.clone())
|
||||
};
|
||||
|
||||
vec![deserialize]
|
||||
}
|
@ -14,6 +14,7 @@ use swc_macros_common::prelude::*;
|
||||
use syn::*;
|
||||
|
||||
mod ast_node_macro;
|
||||
mod enum_deserialize;
|
||||
mod fold;
|
||||
mod from_variant;
|
||||
mod spanned;
|
||||
@ -87,7 +88,7 @@ pub fn derive_deserialize_enum(input: proc_macro::TokenStream) -> proc_macro::To
|
||||
let input = parse::<DeriveInput>(input).expect("failed to parse input as DeriveInput");
|
||||
|
||||
let item =
|
||||
ast_node_macro::expand_enum(input)
|
||||
enum_deserialize::expand(input)
|
||||
.into_iter()
|
||||
.fold(TokenStream::new(), |mut t, item| {
|
||||
item.to_tokens(&mut t);
|
||||
@ -117,8 +118,15 @@ pub fn ast_node(
|
||||
}
|
||||
|
||||
item.quote_with(smart_quote!(Vars { input }, {
|
||||
#[derive(::swc_common::FromVariant, ::swc_common::Spanned, Clone, Debug, PartialEq)]
|
||||
#[derive(::serde::Serialize, ::swc_common::DeserializeEnum)]
|
||||
#[derive(
|
||||
::swc_common::FromVariant,
|
||||
::swc_common::Spanned,
|
||||
Clone,
|
||||
Debug,
|
||||
PartialEq,
|
||||
::serde::Serialize,
|
||||
::swc_common::DeserializeEnum,
|
||||
)]
|
||||
#[serde(untagged)]
|
||||
#[cfg_attr(feature = "fold", derive(::swc_common::Fold))]
|
||||
input
|
||||
@ -161,7 +169,7 @@ pub fn ast_node(
|
||||
let mut quote =
|
||||
item.quote_with(smart_quote!(Vars { input, serde_tag, serde_rename }, {
|
||||
#[derive(::swc_common::Spanned, Clone, Debug, PartialEq)]
|
||||
#[derive(::serde::Serialize)]
|
||||
#[derive(::serde::Serialize, ::serde::Deserialize)]
|
||||
serde_tag
|
||||
#[serde(rename_all = "camelCase")]
|
||||
serde_rename
|
||||
|
@ -4,8 +4,7 @@ extern crate swc_common;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use swc_common::{ast_node, Fold, Span, Spanned};
|
||||
|
||||
#[ast_node]
|
||||
#[derive(Deserialize)]
|
||||
#[ast_node("Class")]
|
||||
// See https://github.com/rust-lang/rust/issues/44925
|
||||
pub struct Class {
|
||||
#[span]
|
||||
@ -14,8 +13,7 @@ pub struct Class {
|
||||
pub s: String,
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
#[derive(Deserialize)]
|
||||
#[ast_node("Tuple")]
|
||||
pub struct Tuple(#[span] HasSpan, #[fold(ignore)] usize, usize);
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Fold, Spanned, Serialize, Deserialize)]
|
||||
|
Loading…
Reference in New Issue
Block a user