Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 23 additions & 9 deletions tasks/ast_tools/src/derives/estree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ impl Derive for DeriveESTree {
StructMaybeDerived | EnumMaybeDerived | StructField | EnumVariant | Meta
),
),
("ts", attr_positions!(StructField | EnumVariant)),
("ts", attr_positions!(StructField | EnumVariant | Meta)),
]
}

Expand Down Expand Up @@ -208,14 +208,15 @@ fn parse_ts_attr(location: AttrLocation, part: &AttrPart) -> Result<()> {
return Err(());
}

// Location can only be `StructField` or `EnumVariant`
// Location can only be `StructField`, `EnumVariant`, or `Meta`
match location {
AttrLocation::StructField(struct_def, field_index) => {
struct_def.fields[field_index].estree.is_ts = true;
}
AttrLocation::EnumVariant(enum_def, variant_index) => {
enum_def.variants[variant_index].estree.is_ts = true;
}
AttrLocation::Meta(meta) => meta.estree.is_ts = true,
_ => unreachable!(),
}

Expand All @@ -237,9 +238,11 @@ fn prepare_field_orders(schema: &mut Schema, estree_derive_id: DeriveId) {
if struct_def.estree.field_indices.is_empty() {
// No field order specified with `#[estree(field_order(...))]`.
// Set default order:
// 1. Fields without `#[ts]` attr, in definition order.
// 2. Fields with `#[ts]` attr, in definition order.
// 3. Added fields `#[estree(add_fields(...)]`, in definition order.
// 1. Fields without `#[ts]` attr.
// 2. Fields with `#[ts]` attr.
// 3. Added fields `#[estree(add_fields(...)]`.
// 4. Added fields `#[estree(add_fields(...)]`, where converter meta type has `#[ts]` attr.
// Within the above groups, ordered in definition order.
let mut field_indices = vec![];
let ts_field_indices = &mut field_indices_temp;
for (field_index, field) in struct_def.fields.iter().enumerate() {
Expand All @@ -252,14 +255,20 @@ fn prepare_field_orders(schema: &mut Schema, estree_derive_id: DeriveId) {
}
}
}
field_indices.append(ts_field_indices);

let fields_len = struct_def.fields.len();
for (index, _) in struct_def.estree.add_fields.iter().enumerate() {
for (index, (_, converter_name)) in struct_def.estree.add_fields.iter().enumerate() {
let field_index = u8::try_from(fields_len + index).unwrap();
field_indices.push(field_index);
let converter = schema.meta_by_name(converter_name);
if converter.estree.is_ts {
ts_field_indices.push(field_index);
} else {
field_indices.push(field_index);
}
}

field_indices.append(ts_field_indices);

let struct_def = schema.struct_def_mut(type_id);
struct_def.estree.field_indices = field_indices;
} else {
Expand Down Expand Up @@ -481,8 +490,13 @@ impl<'s> StructSerializerGenerator<'s> {
) {
let converter = self.schema.meta_by_name(converter_name);
let converter_path = converter.import_path_from_crate(self.krate, self.schema);
let serialize_method_ident = create_safe_ident(if converter.estree.is_ts {
"serialize_ts_field"
} else {
"serialize_field"
});
self.stmts.extend(quote! {
state.serialize_field(#field_name, &#converter_path(#self_path));
state.#serialize_method_ident(#field_name, &#converter_path(#self_path));
});
}
}
Expand Down
20 changes: 13 additions & 7 deletions tasks/ast_tools/src/generators/raw_transfer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ use crate::{
},
output::Output,
schema::{
BoxDef, CellDef, Def, EnumDef, FieldDef, OptionDef, PrimitiveDef, Schema, StructDef,
TypeDef, VecDef,
BoxDef, CellDef, Def, EnumDef, FieldDef, MetaType, OptionDef, PrimitiveDef, Schema,
StructDef, TypeDef, VecDef,
extensions::layout::{GetLayout, GetOffset},
},
utils::{FxIndexMap, format_cow, upper_case_first, write_it},
Expand Down Expand Up @@ -142,7 +142,8 @@ fn generate_struct(
let mut generator = StructDeserializerGenerator::new(is_ts, schema);

let body = if let Some(converter_name) = &struct_def.estree.via {
generator.apply_converter(converter_name, struct_def, 0).map(|value| {
let converter = schema.meta_by_name(converter_name);
generator.apply_converter(converter, struct_def, 0).map(|value| {
if generator.preamble.is_empty() {
format!("return {value};")
} else {
Expand Down Expand Up @@ -329,7 +330,8 @@ impl<'s> StructDeserializerGenerator<'s> {

value.clone_from(&field_name);
} else if let Some(converter_name) = &field.estree.via {
value = self.apply_converter(converter_name, struct_def, struct_offset).unwrap();
let converter = self.schema.meta_by_name(converter_name);
value = self.apply_converter(converter, struct_def, struct_offset).unwrap();
}

self.fields.insert(field_name, value);
Expand All @@ -342,17 +344,21 @@ impl<'s> StructDeserializerGenerator<'s> {
converter_name: &str,
struct_offset: u32,
) {
let value = self.apply_converter(converter_name, struct_def, struct_offset).unwrap();
let converter = self.schema.meta_by_name(converter_name);
if !self.is_ts && converter.estree.is_ts {
return;
}

let value = self.apply_converter(converter, struct_def, struct_offset).unwrap();
self.fields.insert(field_name.to_string(), value);
}

fn apply_converter(
&mut self,
converter_name: &str,
converter: &MetaType,
struct_def: &StructDef,
struct_offset: u32,
) -> Option<String> {
let converter = self.schema.meta_by_name(converter_name);
let raw_deser = converter.estree.raw_deser.as_deref()?;

let value = IF_TS_REGEX.replace_all(raw_deser, IfTsReplacer::new(self.is_ts));
Expand Down
2 changes: 2 additions & 0 deletions tasks/ast_tools/src/schema/extensions/estree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,6 @@ pub struct ESTreeMeta {
pub ts_type: Option<String>,
// JS code for raw transfer deserializer
pub raw_deser: Option<String>,
/// `true` if meta type is for a struct field which is present only in TS AST
pub is_ts: bool,
}
Loading