mirror of
https://github.com/oxc-project/oxc.git
synced 2026-11-04 10:29:58 +00:00
feat(ast_tools): support #[estree(via)] on fieldless enum variants (#10746)
Generators for `ESTree` impls and TS type defs supports `#[estree(via = ...)]` on enum variants where the variant has a field. Extend this support to fieldless variants too.
```rs
#[ast]
#[generate_derive(ESTree)]
enum Foo<'a> {
// This was already supported
#[estree(via = FooBar)]
Bar(Expression<'a>),
// Add support for this
#[estree(via = FooQux)]
Qux,
}
```
This commit is contained in:
1 parent
ee79f03503
commit
d0ba83c719
4 files changed
+39
-26
No files matched your search
@@ -35,7 +35,9 @@ impl ESTree for ImportImportName<'_> {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) {
|
||||
match self {
|
||||
Self::Name(it) => crate::serialize::ImportOrExportNameName(it).serialize(serializer),
|
||||
Self::NamespaceObject => JsonSafeString("namespaceObject").serialize(serializer),
|
||||
Self::NamespaceObject => {
|
||||
crate::serialize::ImportImportNameNamespaceObject(()).serialize(serializer)
|
||||
}
|
||||
Self::Default(it) => {
|
||||
crate::serialize::ImportOrExportNameDefault(it).serialize(serializer)
|
||||
}
|
||||
@@ -61,9 +63,11 @@ impl ESTree for ExportImportName<'_> {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) {
|
||||
match self {
|
||||
Self::Name(it) => crate::serialize::ImportOrExportNameName(it).serialize(serializer),
|
||||
Self::All => JsonSafeString("all").serialize(serializer),
|
||||
Self::AllButDefault => JsonSafeString("allButDefault").serialize(serializer),
|
||||
Self::Null => JsonSafeString("null").serialize(serializer),
|
||||
Self::All => crate::serialize::ExportImportNameAll(()).serialize(serializer),
|
||||
Self::AllButDefault => {
|
||||
crate::serialize::ExportImportNameAllButDefault(()).serialize(serializer)
|
||||
}
|
||||
Self::Null => crate::serialize::ExportNameNull(()).serialize(serializer),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -75,7 +79,7 @@ impl ESTree for ExportExportName<'_> {
|
||||
Self::Default(it) => {
|
||||
crate::serialize::ImportOrExportNameDefault(it).serialize(serializer)
|
||||
}
|
||||
Self::Null => JsonSafeString("null").serialize(serializer),
|
||||
Self::Null => crate::serialize::ExportNameNull(()).serialize(serializer),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -85,7 +89,7 @@ impl ESTree for ExportLocalName<'_> {
|
||||
match self {
|
||||
Self::Name(it) => crate::serialize::ImportOrExportNameName(it).serialize(serializer),
|
||||
Self::Default(it) => crate::serialize::ExportLocalNameDefault(it).serialize(serializer),
|
||||
Self::Null => JsonSafeString("null").serialize(serializer),
|
||||
Self::Null => crate::serialize::ExportNameNull(()).serialize(serializer),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ dummy_estree_impl!(ExportLocalNameDefault<'_, '_>);
|
||||
/// Serializer for `Null` variant of `ExportLocalName`, `ExportExportName`, and `ExportImportName`.
|
||||
#[ast_meta]
|
||||
#[estree(ts_type = "Dummy", raw_deser = "{kind: 'None', name: null, start: null, end: null}")]
|
||||
pub struct ExportNameNull;
|
||||
pub struct ExportNameNull(pub ());
|
||||
|
||||
dummy_estree_impl!(ExportNameNull);
|
||||
|
||||
@@ -68,7 +68,7 @@ dummy_estree_impl!(ImportOrExportNameDefault<'_>);
|
||||
/// Serializer for `All` variant of `ExportImportName`.
|
||||
#[ast_meta]
|
||||
#[estree(ts_type = "Dummy", raw_deser = "{kind: 'All', name: null, start: null, end: null}")]
|
||||
pub struct ExportImportNameAll;
|
||||
pub struct ExportImportNameAll(pub ());
|
||||
|
||||
dummy_estree_impl!(ExportImportNameAll);
|
||||
|
||||
@@ -78,7 +78,7 @@ dummy_estree_impl!(ExportImportNameAll);
|
||||
ts_type = "Dummy",
|
||||
raw_deser = "{kind: 'AllButDefault', name: null, start: null, end: null}"
|
||||
)]
|
||||
pub struct ExportImportNameAllButDefault;
|
||||
pub struct ExportImportNameAllButDefault(pub ());
|
||||
|
||||
dummy_estree_impl!(ExportImportNameAllButDefault);
|
||||
|
||||
@@ -88,6 +88,6 @@ dummy_estree_impl!(ExportImportNameAllButDefault);
|
||||
ts_type = "Dummy",
|
||||
raw_deser = "{kind: 'NamespaceObject', name: null, start: null, end: null}"
|
||||
)]
|
||||
pub struct ImportImportNameNamespaceObject;
|
||||
pub struct ImportImportNameNamespaceObject(pub ());
|
||||
|
||||
dummy_estree_impl!(ImportImportNameNamespaceObject);
|
||||
@@ -440,8 +440,7 @@ impl<'s> StructSerializerGenerator<'s> {
|
||||
}
|
||||
|
||||
let value = if let Some(converter_name) = &field.estree.via {
|
||||
let converter = self.schema.meta_by_name(converter_name);
|
||||
let converter_path = converter.import_path_from_crate(self.krate, self.schema);
|
||||
let converter_path = get_converter_path(converter_name, self.krate, self.schema);
|
||||
quote!( #converter_path(#self_path) )
|
||||
} else if let Some(append_field_index) = field.estree.append_field_index {
|
||||
let append_field = &struct_def.fields[append_field_index];
|
||||
@@ -511,17 +510,23 @@ fn generate_body_for_enum(enum_def: &EnumDef, schema: &Schema) -> TokenStream {
|
||||
};
|
||||
}
|
||||
|
||||
let converter_path = variant.estree.via.as_deref().map(|converter_name| {
|
||||
get_converter_path(converter_name, enum_def.file(schema).krate(), schema)
|
||||
});
|
||||
|
||||
if variant.is_fieldless() {
|
||||
let value = get_fieldless_variant_value(enum_def, variant);
|
||||
let value = string_to_tokens(value.as_ref(), false);
|
||||
let value = if let Some(converter_path) = converter_path {
|
||||
quote!( #converter_path(()) )
|
||||
} else {
|
||||
let value = get_fieldless_variant_value(enum_def, variant);
|
||||
string_to_tokens(value.as_ref(), false)
|
||||
};
|
||||
|
||||
quote! {
|
||||
Self::#variant_ident => #value.serialize(serializer),
|
||||
}
|
||||
} else {
|
||||
let value = if let Some(converter_name) = &variant.estree.via {
|
||||
let converter = schema.meta_by_name(converter_name);
|
||||
let krate = enum_def.file(schema).krate();
|
||||
let converter_path = converter.import_path_from_crate(krate, schema);
|
||||
let value = if let Some(converter_path) = converter_path {
|
||||
quote!( #converter_path(it) )
|
||||
} else {
|
||||
quote!(it)
|
||||
@@ -546,11 +551,17 @@ fn generate_body_for_via_override(
|
||||
file: &File,
|
||||
schema: &Schema,
|
||||
) -> TokenStream {
|
||||
let converter = schema.meta_by_name(converter_name);
|
||||
let converter_path = converter.import_path_from_crate(file.krate(), schema);
|
||||
let converter_path = get_converter_path(converter_name, file.krate(), schema);
|
||||
quote!( #converter_path(self).serialize(serializer) )
|
||||
}
|
||||
|
||||
/// Get path to converter from crate `from_krate`.
|
||||
/// e.g. `oxc_ast::serialize::Null` or `crate::serialize::Null`.
|
||||
fn get_converter_path(converter_name: &str, from_krate: &str, schema: &Schema) -> TokenStream {
|
||||
let converter = schema.meta_by_name(converter_name);
|
||||
converter.import_path_from_crate(from_krate, schema)
|
||||
}
|
||||
|
||||
/// Get if a struct field should be skipped when serializing.
|
||||
///
|
||||
/// Returns `true` if either the field has an `#[estree(skip)]` attr on it,
|
||||
|
||||
@@ -322,12 +322,10 @@ fn generate_ts_type_def_for_enum(enum_def: &EnumDef, schema: &Schema) -> Option<
|
||||
.iter()
|
||||
.filter(|variant| !should_skip_enum_variant(variant))
|
||||
.map(|variant| {
|
||||
if let Some(variant_type) = variant.field_type(schema) {
|
||||
if let Some(converter_name) = &variant.estree.via {
|
||||
Cow::Borrowed(get_ts_type_for_converter(converter_name, schema).unwrap())
|
||||
} else {
|
||||
ts_type_name(variant_type, schema)
|
||||
}
|
||||
if let Some(converter_name) = &variant.estree.via {
|
||||
Cow::Borrowed(get_ts_type_for_converter(converter_name, schema).unwrap())
|
||||
} else if let Some(variant_type) = variant.field_type(schema) {
|
||||
ts_type_name(variant_type, schema)
|
||||
} else {
|
||||
format_cow!("'{}'", get_fieldless_variant_value(enum_def, variant))
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user