mirror of
https://github.com/oxc-project/oxc.git
synced 2026-11-04 10:29:58 +00:00
refactor(ast): generated Serialize impls flatten struct fields (#8904)
In generated `impl Serialize` for AST types, flatten the fields of `Span` directly in the `serialize` method.
Before:
```rs
self.span.serialize(serde::__private::ser::FlatMapSerializer(&mut map))?;
```
After:
```rs
map.serialize_entry("start", &self.span.start)?;
map.serialize_entry("end", &self.span.end)?;
```
Serde's derive macro can't do this, because it only knows about the type it's deriving the impl for, so it has no idea what the fields of `Span` are. But `oxc_ast_tools` knows the entire AST, so it can use that information.
I doubt this will have a runtime perf impact, but it may help compile times.
Also, shorten generated code for `Serialize` impls on enums.
This commit is contained in:
1 parent
0c55dd684e
commit
cbb4e9c598
6 files changed
+1125
-1032
No files matched your search
File diff suppressed because it is too large.
Load diff
@@ -3,7 +3,9 @@
|
||||
|
||||
#![allow(unused_imports, clippy::match_same_arms)]
|
||||
|
||||
use serde::{ser::SerializeMap, Serialize, Serializer};
|
||||
use serde::{__private::ser::FlatMapSerializer, ser::SerializeMap, Serialize, Serializer};
|
||||
|
||||
use oxc_estree::ser::AppendTo;
|
||||
|
||||
use crate::ast::*;
|
||||
|
||||
@@ -11,7 +13,8 @@ impl Serialize for Pattern<'_> {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
let mut map = serializer.serialize_map(None)?;
|
||||
map.serialize_entry("type", "Pattern")?;
|
||||
self.span.serialize(serde::__private::ser::FlatMapSerializer(&mut map))?;
|
||||
map.serialize_entry("start", &self.span.start)?;
|
||||
map.serialize_entry("end", &self.span.end)?;
|
||||
map.serialize_entry("body", &self.body)?;
|
||||
map.end()
|
||||
}
|
||||
@@ -21,7 +24,8 @@ impl Serialize for Disjunction<'_> {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
let mut map = serializer.serialize_map(None)?;
|
||||
map.serialize_entry("type", "Disjunction")?;
|
||||
self.span.serialize(serde::__private::ser::FlatMapSerializer(&mut map))?;
|
||||
map.serialize_entry("start", &self.span.start)?;
|
||||
map.serialize_entry("end", &self.span.end)?;
|
||||
map.serialize_entry("body", &self.body)?;
|
||||
map.end()
|
||||
}
|
||||
@@ -31,7 +35,8 @@ impl Serialize for Alternative<'_> {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
let mut map = serializer.serialize_map(None)?;
|
||||
map.serialize_entry("type", "Alternative")?;
|
||||
self.span.serialize(serde::__private::ser::FlatMapSerializer(&mut map))?;
|
||||
map.serialize_entry("start", &self.span.start)?;
|
||||
map.serialize_entry("end", &self.span.end)?;
|
||||
map.serialize_entry("body", &self.body)?;
|
||||
map.end()
|
||||
}
|
||||
@@ -40,18 +45,18 @@ impl Serialize for Alternative<'_> {
|
||||
impl Serialize for Term<'_> {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
match self {
|
||||
Term::BoundaryAssertion(it) => Serialize::serialize(it, serializer),
|
||||
Term::LookAroundAssertion(it) => Serialize::serialize(it, serializer),
|
||||
Term::Quantifier(it) => Serialize::serialize(it, serializer),
|
||||
Term::Character(it) => Serialize::serialize(it, serializer),
|
||||
Term::Dot(it) => Serialize::serialize(it, serializer),
|
||||
Term::CharacterClassEscape(it) => Serialize::serialize(it, serializer),
|
||||
Term::UnicodePropertyEscape(it) => Serialize::serialize(it, serializer),
|
||||
Term::CharacterClass(it) => Serialize::serialize(it, serializer),
|
||||
Term::CapturingGroup(it) => Serialize::serialize(it, serializer),
|
||||
Term::IgnoreGroup(it) => Serialize::serialize(it, serializer),
|
||||
Term::IndexedReference(it) => Serialize::serialize(it, serializer),
|
||||
Term::NamedReference(it) => Serialize::serialize(it, serializer),
|
||||
Term::BoundaryAssertion(it) => it.serialize(serializer),
|
||||
Term::LookAroundAssertion(it) => it.serialize(serializer),
|
||||
Term::Quantifier(it) => it.serialize(serializer),
|
||||
Term::Character(it) => it.serialize(serializer),
|
||||
Term::Dot(it) => it.serialize(serializer),
|
||||
Term::CharacterClassEscape(it) => it.serialize(serializer),
|
||||
Term::UnicodePropertyEscape(it) => it.serialize(serializer),
|
||||
Term::CharacterClass(it) => it.serialize(serializer),
|
||||
Term::CapturingGroup(it) => it.serialize(serializer),
|
||||
Term::IgnoreGroup(it) => it.serialize(serializer),
|
||||
Term::IndexedReference(it) => it.serialize(serializer),
|
||||
Term::NamedReference(it) => it.serialize(serializer),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -60,7 +65,8 @@ impl Serialize for BoundaryAssertion {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
let mut map = serializer.serialize_map(None)?;
|
||||
map.serialize_entry("type", "BoundaryAssertion")?;
|
||||
self.span.serialize(serde::__private::ser::FlatMapSerializer(&mut map))?;
|
||||
map.serialize_entry("start", &self.span.start)?;
|
||||
map.serialize_entry("end", &self.span.end)?;
|
||||
map.serialize_entry("kind", &self.kind)?;
|
||||
map.end()
|
||||
}
|
||||
@@ -68,7 +74,7 @@ impl Serialize for BoundaryAssertion {
|
||||
|
||||
impl Serialize for BoundaryAssertionKind {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
match *self {
|
||||
match self {
|
||||
BoundaryAssertionKind::Start => {
|
||||
serializer.serialize_unit_variant("BoundaryAssertionKind", 0, "start")
|
||||
}
|
||||
@@ -89,7 +95,8 @@ impl Serialize for LookAroundAssertion<'_> {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
let mut map = serializer.serialize_map(None)?;
|
||||
map.serialize_entry("type", "LookAroundAssertion")?;
|
||||
self.span.serialize(serde::__private::ser::FlatMapSerializer(&mut map))?;
|
||||
map.serialize_entry("start", &self.span.start)?;
|
||||
map.serialize_entry("end", &self.span.end)?;
|
||||
map.serialize_entry("kind", &self.kind)?;
|
||||
map.serialize_entry("body", &self.body)?;
|
||||
map.end()
|
||||
@@ -98,7 +105,7 @@ impl Serialize for LookAroundAssertion<'_> {
|
||||
|
||||
impl Serialize for LookAroundAssertionKind {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
match *self {
|
||||
match self {
|
||||
LookAroundAssertionKind::Lookahead => {
|
||||
serializer.serialize_unit_variant("LookAroundAssertionKind", 0, "lookahead")
|
||||
}
|
||||
@@ -121,7 +128,8 @@ impl Serialize for Quantifier<'_> {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
let mut map = serializer.serialize_map(None)?;
|
||||
map.serialize_entry("type", "Quantifier")?;
|
||||
self.span.serialize(serde::__private::ser::FlatMapSerializer(&mut map))?;
|
||||
map.serialize_entry("start", &self.span.start)?;
|
||||
map.serialize_entry("end", &self.span.end)?;
|
||||
map.serialize_entry("min", &self.min)?;
|
||||
map.serialize_entry("max", &self.max)?;
|
||||
map.serialize_entry("greedy", &self.greedy)?;
|
||||
@@ -134,7 +142,8 @@ impl Serialize for Character {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
let mut map = serializer.serialize_map(None)?;
|
||||
map.serialize_entry("type", "Character")?;
|
||||
self.span.serialize(serde::__private::ser::FlatMapSerializer(&mut map))?;
|
||||
map.serialize_entry("start", &self.span.start)?;
|
||||
map.serialize_entry("end", &self.span.end)?;
|
||||
map.serialize_entry("kind", &self.kind)?;
|
||||
map.serialize_entry("value", &self.value)?;
|
||||
map.end()
|
||||
@@ -143,7 +152,7 @@ impl Serialize for Character {
|
||||
|
||||
impl Serialize for CharacterKind {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
match *self {
|
||||
match self {
|
||||
CharacterKind::ControlLetter => {
|
||||
serializer.serialize_unit_variant("CharacterKind", 0, "controlLetter")
|
||||
}
|
||||
@@ -180,7 +189,8 @@ impl Serialize for CharacterClassEscape {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
let mut map = serializer.serialize_map(None)?;
|
||||
map.serialize_entry("type", "CharacterClassEscape")?;
|
||||
self.span.serialize(serde::__private::ser::FlatMapSerializer(&mut map))?;
|
||||
map.serialize_entry("start", &self.span.start)?;
|
||||
map.serialize_entry("end", &self.span.end)?;
|
||||
map.serialize_entry("kind", &self.kind)?;
|
||||
map.end()
|
||||
}
|
||||
@@ -188,7 +198,7 @@ impl Serialize for CharacterClassEscape {
|
||||
|
||||
impl Serialize for CharacterClassEscapeKind {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
match *self {
|
||||
match self {
|
||||
CharacterClassEscapeKind::D => {
|
||||
serializer.serialize_unit_variant("CharacterClassEscapeKind", 0, "d")
|
||||
}
|
||||
@@ -215,7 +225,8 @@ impl Serialize for UnicodePropertyEscape<'_> {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
let mut map = serializer.serialize_map(None)?;
|
||||
map.serialize_entry("type", "UnicodePropertyEscape")?;
|
||||
self.span.serialize(serde::__private::ser::FlatMapSerializer(&mut map))?;
|
||||
map.serialize_entry("start", &self.span.start)?;
|
||||
map.serialize_entry("end", &self.span.end)?;
|
||||
map.serialize_entry("negative", &self.negative)?;
|
||||
map.serialize_entry("strings", &self.strings)?;
|
||||
map.serialize_entry("name", &self.name)?;
|
||||
@@ -228,7 +239,8 @@ impl Serialize for Dot {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
let mut map = serializer.serialize_map(None)?;
|
||||
map.serialize_entry("type", "Dot")?;
|
||||
self.span.serialize(serde::__private::ser::FlatMapSerializer(&mut map))?;
|
||||
map.serialize_entry("start", &self.span.start)?;
|
||||
map.serialize_entry("end", &self.span.end)?;
|
||||
map.end()
|
||||
}
|
||||
}
|
||||
@@ -237,7 +249,8 @@ impl Serialize for CharacterClass<'_> {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
let mut map = serializer.serialize_map(None)?;
|
||||
map.serialize_entry("type", "CharacterClass")?;
|
||||
self.span.serialize(serde::__private::ser::FlatMapSerializer(&mut map))?;
|
||||
map.serialize_entry("start", &self.span.start)?;
|
||||
map.serialize_entry("end", &self.span.end)?;
|
||||
map.serialize_entry("negative", &self.negative)?;
|
||||
map.serialize_entry("strings", &self.strings)?;
|
||||
map.serialize_entry("kind", &self.kind)?;
|
||||
@@ -248,7 +261,7 @@ impl Serialize for CharacterClass<'_> {
|
||||
|
||||
impl Serialize for CharacterClassContentsKind {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
match *self {
|
||||
match self {
|
||||
CharacterClassContentsKind::Union => {
|
||||
serializer.serialize_unit_variant("CharacterClassContentsKind", 0, "union")
|
||||
}
|
||||
@@ -265,20 +278,12 @@ impl Serialize for CharacterClassContentsKind {
|
||||
impl Serialize for CharacterClassContents<'_> {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
match self {
|
||||
CharacterClassContents::CharacterClassRange(it) => Serialize::serialize(it, serializer),
|
||||
CharacterClassContents::CharacterClassEscape(it) => {
|
||||
Serialize::serialize(it, serializer)
|
||||
}
|
||||
CharacterClassContents::UnicodePropertyEscape(it) => {
|
||||
Serialize::serialize(it, serializer)
|
||||
}
|
||||
CharacterClassContents::Character(it) => Serialize::serialize(it, serializer),
|
||||
CharacterClassContents::NestedCharacterClass(it) => {
|
||||
Serialize::serialize(it, serializer)
|
||||
}
|
||||
CharacterClassContents::ClassStringDisjunction(it) => {
|
||||
Serialize::serialize(it, serializer)
|
||||
}
|
||||
CharacterClassContents::CharacterClassRange(it) => it.serialize(serializer),
|
||||
CharacterClassContents::CharacterClassEscape(it) => it.serialize(serializer),
|
||||
CharacterClassContents::UnicodePropertyEscape(it) => it.serialize(serializer),
|
||||
CharacterClassContents::Character(it) => it.serialize(serializer),
|
||||
CharacterClassContents::NestedCharacterClass(it) => it.serialize(serializer),
|
||||
CharacterClassContents::ClassStringDisjunction(it) => it.serialize(serializer),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -287,7 +292,8 @@ impl Serialize for CharacterClassRange {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
let mut map = serializer.serialize_map(None)?;
|
||||
map.serialize_entry("type", "CharacterClassRange")?;
|
||||
self.span.serialize(serde::__private::ser::FlatMapSerializer(&mut map))?;
|
||||
map.serialize_entry("start", &self.span.start)?;
|
||||
map.serialize_entry("end", &self.span.end)?;
|
||||
map.serialize_entry("min", &self.min)?;
|
||||
map.serialize_entry("max", &self.max)?;
|
||||
map.end()
|
||||
@@ -298,7 +304,8 @@ impl Serialize for ClassStringDisjunction<'_> {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
let mut map = serializer.serialize_map(None)?;
|
||||
map.serialize_entry("type", "ClassStringDisjunction")?;
|
||||
self.span.serialize(serde::__private::ser::FlatMapSerializer(&mut map))?;
|
||||
map.serialize_entry("start", &self.span.start)?;
|
||||
map.serialize_entry("end", &self.span.end)?;
|
||||
map.serialize_entry("strings", &self.strings)?;
|
||||
map.serialize_entry("body", &self.body)?;
|
||||
map.end()
|
||||
@@ -309,7 +316,8 @@ impl Serialize for ClassString<'_> {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
let mut map = serializer.serialize_map(None)?;
|
||||
map.serialize_entry("type", "ClassString")?;
|
||||
self.span.serialize(serde::__private::ser::FlatMapSerializer(&mut map))?;
|
||||
map.serialize_entry("start", &self.span.start)?;
|
||||
map.serialize_entry("end", &self.span.end)?;
|
||||
map.serialize_entry("strings", &self.strings)?;
|
||||
map.serialize_entry("body", &self.body)?;
|
||||
map.end()
|
||||
@@ -320,7 +328,8 @@ impl Serialize for CapturingGroup<'_> {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
let mut map = serializer.serialize_map(None)?;
|
||||
map.serialize_entry("type", "CapturingGroup")?;
|
||||
self.span.serialize(serde::__private::ser::FlatMapSerializer(&mut map))?;
|
||||
map.serialize_entry("start", &self.span.start)?;
|
||||
map.serialize_entry("end", &self.span.end)?;
|
||||
map.serialize_entry("name", &self.name)?;
|
||||
map.serialize_entry("body", &self.body)?;
|
||||
map.end()
|
||||
@@ -331,7 +340,8 @@ impl Serialize for IgnoreGroup<'_> {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
let mut map = serializer.serialize_map(None)?;
|
||||
map.serialize_entry("type", "IgnoreGroup")?;
|
||||
self.span.serialize(serde::__private::ser::FlatMapSerializer(&mut map))?;
|
||||
map.serialize_entry("start", &self.span.start)?;
|
||||
map.serialize_entry("end", &self.span.end)?;
|
||||
map.serialize_entry("modifiers", &self.modifiers)?;
|
||||
map.serialize_entry("body", &self.body)?;
|
||||
map.end()
|
||||
@@ -342,7 +352,8 @@ impl Serialize for Modifiers {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
let mut map = serializer.serialize_map(None)?;
|
||||
map.serialize_entry("type", "Modifiers")?;
|
||||
self.span.serialize(serde::__private::ser::FlatMapSerializer(&mut map))?;
|
||||
map.serialize_entry("start", &self.span.start)?;
|
||||
map.serialize_entry("end", &self.span.end)?;
|
||||
map.serialize_entry("enabling", &self.enabling)?;
|
||||
map.serialize_entry("disabling", &self.disabling)?;
|
||||
map.end()
|
||||
@@ -364,7 +375,8 @@ impl Serialize for IndexedReference {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
let mut map = serializer.serialize_map(None)?;
|
||||
map.serialize_entry("type", "IndexedReference")?;
|
||||
self.span.serialize(serde::__private::ser::FlatMapSerializer(&mut map))?;
|
||||
map.serialize_entry("start", &self.span.start)?;
|
||||
map.serialize_entry("end", &self.span.end)?;
|
||||
map.serialize_entry("index", &self.index)?;
|
||||
map.end()
|
||||
}
|
||||
@@ -374,7 +386,8 @@ impl Serialize for NamedReference<'_> {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
let mut map = serializer.serialize_map(None)?;
|
||||
map.serialize_entry("type", "NamedReference")?;
|
||||
self.span.serialize(serde::__private::ser::FlatMapSerializer(&mut map))?;
|
||||
map.serialize_entry("start", &self.span.start)?;
|
||||
map.serialize_entry("end", &self.span.end)?;
|
||||
map.serialize_entry("name", &self.name)?;
|
||||
map.end()
|
||||
}
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
|
||||
#![allow(unused_imports, clippy::match_same_arms)]
|
||||
|
||||
use serde::{ser::SerializeMap, Serialize, Serializer};
|
||||
use serde::{__private::ser::FlatMapSerializer, ser::SerializeMap, Serialize, Serializer};
|
||||
|
||||
use oxc_estree::ser::AppendTo;
|
||||
|
||||
use crate::source_type::*;
|
||||
use crate::span::*;
|
||||
@@ -29,7 +31,7 @@ impl Serialize for SourceType {
|
||||
|
||||
impl Serialize for Language {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
match *self {
|
||||
match self {
|
||||
Language::JavaScript => serializer.serialize_unit_variant("Language", 0, "javascript"),
|
||||
Language::TypeScript => serializer.serialize_unit_variant("Language", 1, "typescript"),
|
||||
Language::TypeScriptDefinition => {
|
||||
@@ -41,7 +43,7 @@ impl Serialize for Language {
|
||||
|
||||
impl Serialize for ModuleKind {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
match *self {
|
||||
match self {
|
||||
ModuleKind::Script => serializer.serialize_unit_variant("ModuleKind", 0, "script"),
|
||||
ModuleKind::Module => serializer.serialize_unit_variant("ModuleKind", 1, "module"),
|
||||
ModuleKind::Unambiguous => {
|
||||
@@ -53,7 +55,7 @@ impl Serialize for ModuleKind {
|
||||
|
||||
impl Serialize for LanguageVariant {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
match *self {
|
||||
match self {
|
||||
LanguageVariant::Standard => {
|
||||
serializer.serialize_unit_variant("LanguageVariant", 0, "standard")
|
||||
}
|
||||
|
||||
@@ -3,13 +3,15 @@
|
||||
|
||||
#![allow(unused_imports, clippy::match_same_arms)]
|
||||
|
||||
use serde::{ser::SerializeMap, Serialize, Serializer};
|
||||
use serde::{__private::ser::FlatMapSerializer, ser::SerializeMap, Serialize, Serializer};
|
||||
|
||||
use oxc_estree::ser::AppendTo;
|
||||
|
||||
use crate::operator::*;
|
||||
|
||||
impl Serialize for AssignmentOperator {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
match *self {
|
||||
match self {
|
||||
AssignmentOperator::Assign => {
|
||||
serializer.serialize_unit_variant("AssignmentOperator", 0, "=")
|
||||
}
|
||||
@@ -64,7 +66,7 @@ impl Serialize for AssignmentOperator {
|
||||
|
||||
impl Serialize for BinaryOperator {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
match *self {
|
||||
match self {
|
||||
BinaryOperator::Equality => {
|
||||
serializer.serialize_unit_variant("BinaryOperator", 0, "==")
|
||||
}
|
||||
@@ -131,7 +133,7 @@ impl Serialize for BinaryOperator {
|
||||
|
||||
impl Serialize for LogicalOperator {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
match *self {
|
||||
match self {
|
||||
LogicalOperator::Or => serializer.serialize_unit_variant("LogicalOperator", 0, "||"),
|
||||
LogicalOperator::And => serializer.serialize_unit_variant("LogicalOperator", 1, "&&"),
|
||||
LogicalOperator::Coalesce => {
|
||||
@@ -143,7 +145,7 @@ impl Serialize for LogicalOperator {
|
||||
|
||||
impl Serialize for UnaryOperator {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
match *self {
|
||||
match self {
|
||||
UnaryOperator::UnaryPlus => serializer.serialize_unit_variant("UnaryOperator", 0, "+"),
|
||||
UnaryOperator::UnaryNegation => {
|
||||
serializer.serialize_unit_variant("UnaryOperator", 1, "-")
|
||||
@@ -163,7 +165,7 @@ impl Serialize for UnaryOperator {
|
||||
|
||||
impl Serialize for UpdateOperator {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
match *self {
|
||||
match self {
|
||||
UpdateOperator::Increment => {
|
||||
serializer.serialize_unit_variant("UpdateOperator", 0, "++")
|
||||
}
|
||||
|
||||
@@ -54,7 +54,14 @@ impl Derive for DeriveESTree {
|
||||
#![allow(unused_imports, clippy::match_same_arms)]
|
||||
|
||||
///@@line_break
|
||||
use serde::{Serialize, Serializer, ser::SerializeMap};
|
||||
use serde::{
|
||||
__private::ser::FlatMapSerializer,
|
||||
ser::SerializeMap,
|
||||
Serialize, Serializer
|
||||
};
|
||||
|
||||
///@@line_break
|
||||
use oxc_estree::ser::AppendTo;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,55 +186,107 @@ fn generate_body_for_struct(struct_def: &StructDef, schema: &Schema) -> TokenStr
|
||||
};
|
||||
}
|
||||
|
||||
let mut stmts = quote!();
|
||||
let mut gen = StructSerializerGenerator::new(!struct_def.estree.no_type, schema);
|
||||
gen.generate_stmts_for_struct(struct_def, "e!(self));
|
||||
|
||||
if should_add_type_field_to_struct(struct_def) {
|
||||
let type_field = if gen.add_type_field {
|
||||
let type_name = struct_def.estree.rename.as_deref().unwrap_or_else(|| struct_def.name());
|
||||
stmts.extend(quote!( map.serialize_entry("type", #type_name)?; ));
|
||||
}
|
||||
|
||||
for field in &struct_def.fields {
|
||||
if !should_skip_field(field, schema) {
|
||||
stmts.extend(generate_stmt_for_struct_field(field, struct_def, schema));
|
||||
quote! {
|
||||
map.serialize_entry("type", #type_name)?;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
quote!()
|
||||
};
|
||||
|
||||
let stmts = gen.stmts;
|
||||
quote! {
|
||||
let mut map = serializer.serialize_map(None)?;
|
||||
#type_field
|
||||
#stmts
|
||||
map.end()
|
||||
}
|
||||
}
|
||||
|
||||
/// Generate code to serialize a struct field.
|
||||
fn generate_stmt_for_struct_field(
|
||||
field: &FieldDef,
|
||||
struct_def: &StructDef,
|
||||
schema: &Schema,
|
||||
) -> TokenStream {
|
||||
let field_name_ident = field.ident();
|
||||
/// Generator for stmts to serialize fields of a struct.
|
||||
///
|
||||
/// Recursively enters any flattened fields which contain a struct,
|
||||
/// and generates statements for each of the flattened struct's fields too.
|
||||
///
|
||||
/// If a field called `type` is found, `add_type_field` is set to `false`.
|
||||
struct StructSerializerGenerator<'s> {
|
||||
/// `serialize` statements
|
||||
stmts: TokenStream,
|
||||
/// `true` if a `type` field should be added.
|
||||
/// `false` one already exists (or if `#[estree(no_type)]` attr on struct).
|
||||
add_type_field: bool,
|
||||
/// Schema
|
||||
schema: &'s Schema,
|
||||
}
|
||||
|
||||
if should_flatten_field(field, schema) {
|
||||
return quote! {
|
||||
self.#field_name_ident.serialize(serde::__private::ser::FlatMapSerializer(&mut map))?;
|
||||
};
|
||||
impl<'s> StructSerializerGenerator<'s> {
|
||||
/// Create new [`StructSerializerGenerator`].
|
||||
fn new(add_type_field: bool, schema: &'s Schema) -> Self {
|
||||
Self { stmts: quote!(), add_type_field, schema }
|
||||
}
|
||||
|
||||
let field_camel_name = get_struct_field_name(field);
|
||||
|
||||
let mut value = quote!( &self.#field_name_ident );
|
||||
if let Some(via_str) = field.estree.via.as_deref() {
|
||||
let via_ty = parse_str::<Type>(via_str).unwrap();
|
||||
value = quote!( &#via_ty::from(#value) );
|
||||
} else if let Some(append_field_index) = field.estree.append_field_index {
|
||||
let append_from_ident = struct_def.fields[append_field_index].ident();
|
||||
value = quote! {
|
||||
&oxc_estree::ser::AppendTo { array: #value, after: &self.#append_from_ident }
|
||||
};
|
||||
/// Generate code to serialize all fields in a struct.
|
||||
fn generate_stmts_for_struct(&mut self, struct_def: &StructDef, self_path: &TokenStream) {
|
||||
for field in &struct_def.fields {
|
||||
self.generate_stmts_for_field(field, struct_def, self_path);
|
||||
}
|
||||
}
|
||||
|
||||
quote! {
|
||||
map.serialize_entry(#field_camel_name, #value)?;
|
||||
/// Generate code to serialize a struct field.
|
||||
fn generate_stmts_for_field(
|
||||
&mut self,
|
||||
field: &FieldDef,
|
||||
struct_def: &StructDef,
|
||||
self_path: &TokenStream,
|
||||
) {
|
||||
if should_skip_field(field, self.schema) {
|
||||
return;
|
||||
}
|
||||
|
||||
let field_name_ident = field.ident();
|
||||
|
||||
if should_flatten_field(field, self.schema) {
|
||||
match field.type_def(self.schema) {
|
||||
TypeDef::Struct(inner_struct_def) => {
|
||||
self.generate_stmts_for_struct(
|
||||
inner_struct_def,
|
||||
"e!(#self_path.#field_name_ident),
|
||||
);
|
||||
}
|
||||
TypeDef::Enum(_) => {
|
||||
self.stmts.extend(quote! {
|
||||
#self_path.#field_name_ident.serialize(FlatMapSerializer(&mut map))?;
|
||||
});
|
||||
}
|
||||
_ => panic!("Cannot flatten a field which is not a struct or enum"),
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
let field_camel_name = get_struct_field_name(field);
|
||||
|
||||
if field_camel_name == "type" {
|
||||
self.add_type_field = false;
|
||||
}
|
||||
|
||||
let mut value = quote!( #self_path.#field_name_ident );
|
||||
if let Some(via_str) = field.estree.via.as_deref() {
|
||||
let via_ty = parse_str::<Type>(via_str).unwrap();
|
||||
value = quote!( #via_ty::from(&#value) );
|
||||
} else if let Some(append_field_index) = field.estree.append_field_index {
|
||||
let append_from_ident = struct_def.fields[append_field_index].ident();
|
||||
value = quote! {
|
||||
AppendTo { array: &#value, after: &#self_path.#append_from_ident }
|
||||
};
|
||||
}
|
||||
|
||||
self.stmts.extend(quote! {
|
||||
map.serialize_entry(#field_camel_name, &#value)?;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -235,57 +294,29 @@ fn generate_stmt_for_struct_field(
|
||||
fn generate_body_for_enum(enum_def: &EnumDef, schema: &Schema) -> TokenStream {
|
||||
let enum_ident = enum_def.ident();
|
||||
|
||||
if enum_def.is_fieldless() {
|
||||
let enum_name = enum_def.name();
|
||||
let match_branches = enum_def.all_variants(schema).map(|variant| {
|
||||
let variant_ident = variant.ident();
|
||||
let match_branches = enum_def.all_variants(schema).map(|variant| {
|
||||
let variant_ident = variant.ident();
|
||||
if variant.is_fieldless() {
|
||||
let enum_name = enum_def.name();
|
||||
let discriminant = number_lit(variant.discriminant);
|
||||
let value = get_fieldless_variant_value(enum_def, variant);
|
||||
|
||||
quote! {
|
||||
#enum_ident::#variant_ident => {
|
||||
serializer.serialize_unit_variant(#enum_name, #discriminant, #value)
|
||||
}
|
||||
#enum_ident::#variant_ident => serializer.serialize_unit_variant(#enum_name, #discriminant, #value),
|
||||
}
|
||||
});
|
||||
|
||||
quote! {
|
||||
match *self {
|
||||
#(#match_branches)*
|
||||
} else {
|
||||
quote! {
|
||||
#enum_ident::#variant_ident(it) => it.serialize(serializer),
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let match_branches = enum_def.all_variants(schema).map(|variant| {
|
||||
let variant_ident = variant.ident();
|
||||
quote! {
|
||||
#enum_ident::#variant_ident(it) => {
|
||||
Serialize::serialize(it, serializer)
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
quote! {
|
||||
match self {
|
||||
#(#match_branches)*
|
||||
}
|
||||
quote! {
|
||||
match self {
|
||||
#(#match_branches)*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Get if should generate a `type` field.
|
||||
///
|
||||
/// Type field should be added unless struct has an `#[estree(no_type)]` attr
|
||||
/// or struct has an existing field called `type`.
|
||||
///
|
||||
/// This function also used by Typescript generator.
|
||||
pub fn should_add_type_field_to_struct(struct_def: &StructDef) -> bool {
|
||||
if struct_def.estree.no_type {
|
||||
false
|
||||
} else {
|
||||
!struct_def.fields.iter().any(|field| matches!(field.name(), "type"))
|
||||
}
|
||||
}
|
||||
|
||||
/// Get if a struct field should be skipped when serializing.
|
||||
///
|
||||
/// Returns `true` if either the field has an `#[estree(skip)]` attr on it,
|
||||
|
||||
@@ -6,8 +6,7 @@ use itertools::Itertools;
|
||||
|
||||
use crate::{
|
||||
derives::estree::{
|
||||
get_fieldless_variant_value, get_struct_field_name, should_add_type_field_to_struct,
|
||||
should_flatten_field, should_skip_field,
|
||||
get_fieldless_variant_value, get_struct_field_name, should_flatten_field, should_skip_field,
|
||||
},
|
||||
output::Output,
|
||||
schema::{Def, EnumDef, FieldDef, Schema, StructDef, TypeDef},
|
||||
@@ -234,3 +233,15 @@ fn get_field_type_name<'s>(field: &'s FieldDef, schema: &'s Schema) -> Cow<'s, s
|
||||
ts_type_name(field_type, schema)
|
||||
}
|
||||
}
|
||||
|
||||
/// Get if should generate a `type` field.
|
||||
///
|
||||
/// Type field should be added unless struct has an `#[estree(no_type)]` attr
|
||||
/// or struct has an existing field called `type`.
|
||||
fn should_add_type_field_to_struct(struct_def: &StructDef) -> bool {
|
||||
if struct_def.estree.no_type {
|
||||
false
|
||||
} else {
|
||||
!struct_def.fields.iter().any(|field| matches!(field.name(), "type"))
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user