diff --git a/crates/swc_ecma_codegen/src/class.rs b/crates/swc_ecma_codegen/src/class.rs index 58607f1529d2..3bd6a720349b 100644 --- a/crates/swc_ecma_codegen/src/class.rs +++ b/crates/swc_ecma_codegen/src/class.rs @@ -1,4 +1,4 @@ -use swc_common::{SourceMapper, Spanned}; +use swc_common::{SourceMapper, Span, Spanned}; use swc_ecma_ast::*; use swc_ecma_codegen_macros::node_impl; @@ -26,8 +26,8 @@ where formatting_space!(self) } } - emit!(self, node.super_class); - emit!(self, node.super_type_params); + emit!(true, self, node.super_class); + emit!(true, self, node.super_type_params); } if !node.implements.is_empty() { @@ -61,10 +61,12 @@ impl MacroNode for ClassExpr { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + srcmap!(emitter, self, true); for dec in &self.class.decorators { - emit!(dec); + emit!(emitter, dec); } if self.class.is_abstract { @@ -76,19 +78,29 @@ impl MacroNode for ClassExpr { if let Some(ref i) = self.ident { space!(emitter); - emit!(i); - emit!(self.class.type_params); + emit!(emitter, i); + emit!(emitter, self.class.type_params); } emitter.emit_class_trailing(&self.class)?; - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(ClassExpr { + class: Box::new(Class { + span: Span::new(lo, hi), + ..*self.class.clone() + }), + ..self.clone() + })) } } #[node_impl] impl MacroNode for Class { fn emit(&mut self, emitter: &mut Macro) -> Result { + let lo = only_new!(emitter.wr.get_pos()); + if self.super_class.is_some() { space!(emitter); keyword!(emitter, "extends"); @@ -103,8 +115,8 @@ impl MacroNode for Class { formatting_space!(emitter) } } - emit!(self.super_class); - emit!(self.super_type_params); + emit!(emitter, self.super_class); + emit!(emitter, self.super_type_params); } if !self.implements.is_empty() { @@ -129,26 +141,65 @@ impl MacroNode for Class { srcmap!(emitter, self, false, true); punct!(emitter, "}"); - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(Class { + span: Span::new(lo, hi), + ..self.clone() + })) } } #[node_impl] impl MacroNode for ClassMember { fn emit(&mut self, emitter: &mut Macro) -> Result { - match self { - ClassMember::Constructor(ref n) => emit!(n), - ClassMember::ClassProp(ref n) => emit!(n), - ClassMember::Method(ref n) => emit!(n), - ClassMember::PrivateMethod(ref n) => emit!(n), - ClassMember::PrivateProp(ref n) => emit!(n), - ClassMember::TsIndexSignature(ref n) => emit!(n), - ClassMember::Empty(ref n) => emit!(n), - ClassMember::StaticBlock(ref n) => emit!(n), - ClassMember::AutoAccessor(ref n) => emit!(n), - } + Ok(match self { + ClassMember::Constructor(ref n) => { + let n = emit!(emitter, n); - Ok(()) + only_new!(ClassMember::Constructor(n)) + } + ClassMember::ClassProp(ref n) => { + let n = emit!(emitter, n); + + only_new!(ClassMember::ClassProp(n)) + } + ClassMember::Method(ref n) => { + let n = emit!(emitter, n); + + only_new!(ClassMember::Method(n)) + } + ClassMember::PrivateMethod(ref n) => { + let n = emit!(emitter, n); + + only_new!(ClassMember::PrivateMethod(n)) + } + ClassMember::PrivateProp(ref n) => { + let n = emit!(emitter, n); + + only_new!(ClassMember::PrivateProp(n)) + } + ClassMember::TsIndexSignature(ref n) => { + let n = emit!(emitter, n); + + only_new!(ClassMember::TsIndexSignature(n)) + } + ClassMember::Empty(ref n) => { + let n = emit!(emitter, n); + + only_new!(ClassMember::Empty(n)) + } + ClassMember::StaticBlock(ref n) => { + let n = emit!(emitter, n); + + only_new!(ClassMember::StaticBlock(n)) + } + ClassMember::AutoAccessor(ref n) => { + let n = emit!(emitter, n); + + only_new!(ClassMember::AutoAccessor(n)) + } + }) } } @@ -157,6 +208,8 @@ impl MacroNode for AutoAccessor { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_list(self.span, Some(&self.decorators), ListFormat::Decorators)?; + let lo = only_new!(emitter.wr.get_pos()); + emitter.emit_accessibility(self.accessibility)?; if self.is_static { @@ -177,7 +230,7 @@ impl MacroNode for AutoAccessor { keyword!(emitter, "accessor"); space!(emitter); - emit!(self.key); + emit!(emitter, self.key); if let Some(type_ann) = &self.type_ann { if self.definite { @@ -185,31 +238,42 @@ impl MacroNode for AutoAccessor { } punct!(emitter, ":"); space!(emitter); - emit!(type_ann); + emit!(emitter, type_ann); } if let Some(init) = &self.value { formatting_space!(emitter); punct!(emitter, "="); formatting_space!(emitter); - emit!(init); + emit!(emitter, init); } semi!(emitter); - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(AutoAccessor { + span: Span::new(lo, hi), + ..self.clone() + })) } } #[node_impl] impl MacroNode for Key { fn emit(&mut self, emitter: &mut Macro) -> Result { - match self { - Key::Private(n) => emit!(n), - Key::Public(n) => emit!(n), - } + Ok(match self { + Key::Private(n) => { + let n = emit!(emitter, n); - Ok(()) + only_new!(Key::Private(n)) + } + Key::Public(n) => { + let n = emit!(emitter, n); + + only_new!(Key::Public(n)) + } + }) } } @@ -218,6 +282,8 @@ impl MacroNode for PrivateMethod { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + srcmap!(emitter, self, true); if self.is_static { @@ -234,25 +300,30 @@ impl MacroNode for PrivateMethod { punct!(emitter, "*"); } - emit!(self.key); + emit!(emitter, self.key); } MethodKind::Getter => { keyword!(emitter, "get"); space!(emitter); - emit!(self.key); + emit!(emitter, self.key); } MethodKind::Setter => { keyword!(emitter, "set"); space!(emitter); - emit!(self.key); + emit!(emitter, self.key); } } emitter.emit_fn_trailing(&self.function)?; - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(PrivateMethod { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -263,10 +334,12 @@ impl MacroNode for ClassMethod { emitter.emit_leading_comments_of_span(self.key.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + srcmap!(emitter, self, true); for d in &self.function.decorators { - emit!(d); + emit!(emitter, d); } emitter.emit_accessibility(self.accessibility)?; @@ -315,7 +388,7 @@ impl MacroNode for ClassMethod { punct!(emitter, "*"); } - emit!(self.key); + emit!(emitter, self.key); } MethodKind::Getter => { keyword!(emitter, "get"); @@ -326,7 +399,7 @@ impl MacroNode for ClassMethod { formatting_space!(emitter) } - emit!(self.key); + emit!(emitter, self.key); } MethodKind::Setter => { keyword!(emitter, "set"); @@ -337,7 +410,7 @@ impl MacroNode for ClassMethod { formatting_space!(emitter) } - emit!(self.key); + emit!(emitter, self.key); } } @@ -346,7 +419,7 @@ impl MacroNode for ClassMethod { } if let Some(type_params) = &self.function.type_params { - emit!(type_params); + emit!(emitter, type_params); } punct!(emitter, "("); @@ -361,17 +434,22 @@ impl MacroNode for ClassMethod { if let Some(ty) = &self.function.return_type { punct!(emitter, ":"); formatting_space!(emitter); - emit!(ty); + emit!(emitter, ty); } if let Some(body) = &self.function.body { formatting_space!(emitter); - emit!(body); + emit!(emitter, body); } else { formatting_semi!(emitter) } - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(ClassMethod { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -380,6 +458,8 @@ impl MacroNode for PrivateProp { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + srcmap!(emitter, self, true); emitter.emit_list(self.span, Some(&self.decorators), ListFormat::Decorators)?; @@ -401,7 +481,7 @@ impl MacroNode for PrivateProp { space!(emitter); } - emit!(self.key); + emit!(emitter, self.key); if self.is_optional { punct!(emitter, "?"); @@ -413,7 +493,7 @@ impl MacroNode for PrivateProp { } punct!(emitter, ":"); space!(emitter); - emit!(type_ann); + emit!(emitter, type_ann); } if let Some(value) = &self.value { @@ -423,10 +503,10 @@ impl MacroNode for PrivateProp { if value.is_seq() { punct!(emitter, "("); - emit!(value); + emit!(emitter, value); punct!(emitter, ")"); } else { - emit!(value); + emit!(emitter, value); } } @@ -434,7 +514,12 @@ impl MacroNode for PrivateProp { srcmap!(emitter, self, false); - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(PrivateProp { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -442,11 +527,16 @@ impl MacroNode for PrivateProp { impl MacroNode for ClassProp { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + + let lo = only_new!(emitter.wr.get_pos()); + srcmap!(emitter, self, true); - for dec in &self.decorators { - emit!(dec) - } + let decorators = self + .decorators + .iter() + .map(|d| Ok(emit!(emitter, d))) + .collect::>>()?; if self.declare { keyword!(emitter, "declare"); @@ -475,7 +565,7 @@ impl MacroNode for ClassProp { space!(emitter) } - emit!(self.key); + emit!(emitter, self.key); if self.is_optional { punct!(emitter, "?"); @@ -487,7 +577,7 @@ impl MacroNode for ClassProp { } punct!(emitter, ":"); space!(emitter); - emit!(ty); + emit!(emitter, ty); } if let Some(v) = &self.value { @@ -497,10 +587,10 @@ impl MacroNode for ClassProp { if v.is_seq() { punct!(emitter, "("); - emit!(v); + emit!(emitter, v); punct!(emitter, ")"); } else { - emit!(v); + emit!(emitter, v); } } @@ -508,7 +598,13 @@ impl MacroNode for ClassProp { srcmap!(emitter, self, false); - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(ClassProp { + span: Span::new(lo, hi), + decorators, + ..self.clone() + })) } } @@ -517,6 +613,8 @@ impl MacroNode for Constructor { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + srcmap!(emitter, self, true); emitter.emit_accessibility(self.accessibility)?; @@ -527,12 +625,17 @@ impl MacroNode for Constructor { punct!(emitter, ")"); if let Some(body) = &self.body { - emit!(body); + emit!(emitter, body); } else { formatting_semi!(emitter); } - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(Constructor { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -541,14 +644,21 @@ impl MacroNode for StaticBlock { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + srcmap!(emitter, self, true); keyword!(emitter, "static"); - emit!(self.body); + emit!(emitter, self.body); srcmap!(emitter, self, false); - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(StaticBlock { + span: Span::new(lo, hi), + ..self.clone() + })) } } diff --git a/crates/swc_ecma_codegen/src/decl.rs b/crates/swc_ecma_codegen/src/decl.rs index f88406756206..9b34f0c2869a 100644 --- a/crates/swc_ecma_codegen/src/decl.rs +++ b/crates/swc_ecma_codegen/src/decl.rs @@ -1,4 +1,4 @@ -use swc_common::{SourceMapper, Spanned}; +use swc_common::{SourceMapper, Span, Spanned}; use swc_ecma_ast::*; use swc_ecma_codegen_macros::node_impl; @@ -26,7 +26,7 @@ where if !skip_decorators { for dec in &node.class.decorators { - emit!(self, dec); + emit!(true, self, dec); } } @@ -37,8 +37,8 @@ where keyword!(self, "class"); space!(self); - emit!(self, node.ident); - emit!(self, node.class.type_params); + emit!(true, self, node.ident); + emit!(true, self, node.class.type_params); self.emit_class_trailing(&node.class)?; @@ -86,29 +86,68 @@ where impl MacroNode for Decl { fn emit(&mut self, emitter: &mut Macro) -> Result { match self { - Decl::Class(n) => emit!(n), - Decl::Fn(n) => emit!(n), + Decl::Class(n) => { + let n = emit!(emitter, n); + + Ok(only_new!(Decl::Class(n))) + } + Decl::Fn(n) => { + let n = emit!(emitter, n); + + Ok(only_new!(Decl::Fn(n))) + } Decl::Var(n) => { emitter.emit_var_decl_inner(n)?; formatting_semi!(emitter); srcmap!(emitter, self, false); + + Ok(only_new!(Decl::Var(n.clone()))) } - Decl::Using(n) => emit!(n), - Decl::TsEnum(n) => emit!(n), - Decl::TsInterface(n) => emit!(n), - Decl::TsModule(n) => emit!(n), - Decl::TsTypeAlias(n) => emit!(n), - } + Decl::Using(n) => { + let n = emit!(emitter, n); - Ok(()) + Ok(only_new!(Decl::Using(n))) + } + Decl::TsEnum(n) => { + let n = emit!(emitter, n); + + Ok(only_new!(Decl::TsEnum(n))) + } + Decl::TsInterface(n) => { + let n = emit!(emitter, n); + + Ok(only_new!(Decl::TsInterface(n))) + } + Decl::TsModule(n) => { + let n = emit!(emitter, n); + + Ok(only_new!(Decl::TsModule(n))) + } + Decl::TsTypeAlias(n) => { + let n = emit!(emitter, n); + + Ok(only_new!(Decl::TsTypeAlias(n))) + } + } } } #[node_impl] impl MacroNode for ClassDecl { fn emit(&mut self, emitter: &mut Macro) -> Result { + let lo = only_new!(emitter.wr.get_pos()); + emitter.emit_class_decl_inner(self, false)?; - Ok(()) + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(ClassDecl { + class: Box::new(Class { + span: Span::new(lo, hi), + ..*self.class.clone() + }), + ..self.clone() + })) } } @@ -117,6 +156,8 @@ impl MacroNode for UsingDecl { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + if self.is_await { keyword!(emitter, "await"); space!(emitter); @@ -131,7 +172,12 @@ impl MacroNode for UsingDecl { ListFormat::VariableDeclarationList, )?; - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(UsingDecl { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -142,6 +188,8 @@ impl MacroNode for FnDecl { emitter.wr.commit_pending_semi()?; + let lo = only_new!(emitter.wr.get_pos()); + srcmap!(emitter, self, true); if self.declare { @@ -162,19 +210,35 @@ impl MacroNode for FnDecl { space!(emitter); } - emit!(self.ident); + emit!(emitter, self.ident); emitter.emit_fn_trailing(&self.function)?; - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(FnDecl { + function: Box::new(Function { + span: Span::new(lo, hi), + ..*self.function.clone() + }), + ..self.clone() + })) } } #[node_impl] impl MacroNode for VarDecl { fn emit(&mut self, emitter: &mut Macro) -> Result { + let lo = only_new!(emitter.wr.get_pos()); + emitter.emit_var_decl_inner(self)?; - Ok(()) + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(VarDecl { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -183,18 +247,25 @@ impl MacroNode for VarDeclarator { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + srcmap!(emitter, self, true); - emit!(self.name); + emit!(emitter, self.name); if let Some(ref init) = self.init { formatting_space!(emitter); punct!(emitter, "="); formatting_space!(emitter); - emit!(init); + emit!(emitter, init); } - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(VarDeclarator { + span: Span::new(lo, hi), + ..self.clone() + })) } } diff --git a/crates/swc_ecma_codegen/src/jsx.rs b/crates/swc_ecma_codegen/src/jsx.rs index ebadf19d3cbb..2fe7f5e0bc7e 100644 --- a/crates/swc_ecma_codegen/src/jsx.rs +++ b/crates/swc_ecma_codegen/src/jsx.rs @@ -1,4 +1,4 @@ -use swc_common::{SourceMapper, Spanned}; +use swc_common::{SourceMapper, Span, Spanned}; use swc_ecma_ast::*; use swc_ecma_codegen_macros::node_impl; @@ -15,27 +15,39 @@ where #[node_impl] impl MacroNode for JSXElement { fn emit(&mut self, emitter: &mut Macro) -> Result { - emit!(self.opening); + let lo = only_new!(emitter.wr.get_pos()); + + emit!(emitter, self.opening); emitter.emit_list( self.span(), Some(&self.children), ListFormat::JsxElementOrFragmentChildren, )?; - if let Some(ref closing) = self.closing { - emit!(closing) - } - Ok(()) + let closing = if let Some(ref closing) = self.closing { + Some(emit!(emitter, closing)) + } else { + None + }; + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(JSXElement { + span: Span::new(lo, hi), + closing, + ..self.clone() + })) } } #[node_impl] impl MacroNode for JSXOpeningElement { fn emit(&mut self, emitter: &mut Macro) -> Result { + let lo = only_new!(emitter.wr.get_pos()); + punct!(emitter, "<"); - emit!(self.name); + emit!(emitter, self.name); if let Some(type_args) = &self.type_args { - emit!(type_args); + emit!(emitter, type_args); } if !self.attrs.is_empty() { @@ -52,7 +64,13 @@ impl MacroNode for JSXOpeningElement { punct!(emitter, "/"); } punct!(emitter, ">"); - Ok(()) + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(JSXOpeningElement { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -60,24 +78,42 @@ impl MacroNode for JSXOpeningElement { impl MacroNode for JSXElementName { fn emit(&mut self, emitter: &mut Macro) -> Result { match *self { - JSXElementName::Ident(ref n) => emit!(n), - JSXElementName::JSXMemberExpr(ref n) => emit!(n), - JSXElementName::JSXNamespacedName(ref n) => emit!(n), + JSXElementName::Ident(ref n) => { + let n = emit!(emitter, n); + + Ok(only_new!(JSXElementName::Ident(n))) + } + JSXElementName::JSXMemberExpr(ref n) => { + let n = emit!(emitter, n); + + Ok(only_new!(JSXElementName::JSXMemberExpr(n))) + } + JSXElementName::JSXNamespacedName(ref n) => { + let n = emit!(emitter, n); + + Ok(only_new!(JSXElementName::JSXNamespacedName(n))) + } } - Ok(()) } } #[node_impl] impl MacroNode for JSXAttr { fn emit(&mut self, emitter: &mut Macro) -> Result { - emit!(self.name); + let lo = only_new!(emitter.wr.get_pos()); + + emit!(emitter, self.name); if let Some(ref value) = self.value { punct!(emitter, "="); - emit!(value); + emit!(emitter, value); } - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(JSXAttr { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -85,12 +121,27 @@ impl MacroNode for JSXAttr { impl MacroNode for JSXAttrValue { fn emit(&mut self, emitter: &mut Macro) -> Result { match *self { - JSXAttrValue::Lit(ref n) => emit!(n), - JSXAttrValue::JSXExprContainer(ref n) => emit!(n), - JSXAttrValue::JSXElement(ref n) => emit!(n), - JSXAttrValue::JSXFragment(ref n) => emit!(n), + JSXAttrValue::Lit(ref n) => { + let n = emit!(emitter, n); + + Ok(only_new!(JSXAttrValue::Lit(n))) + } + JSXAttrValue::JSXExprContainer(ref n) => { + let n = emit!(emitter, n); + + Ok(only_new!(JSXAttrValue::JSXExprContainer(n))) + } + JSXAttrValue::JSXElement(ref n) => { + let n = emit!(emitter, n); + + Ok(only_new!(JSXAttrValue::JSXElement(n))) + } + JSXAttrValue::JSXFragment(ref n) => { + let n = emit!(emitter, n); + + Ok(only_new!(JSXAttrValue::JSXFragment(n))) + } } - Ok(()) } } @@ -98,10 +149,17 @@ impl MacroNode for JSXAttrValue { impl MacroNode for JSXAttrName { fn emit(&mut self, emitter: &mut Macro) -> Result { match *self { - JSXAttrName::Ident(ref n) => emit!(n), - JSXAttrName::JSXNamespacedName(ref n) => emit!(n), + JSXAttrName::Ident(ref n) => { + let n = emit!(emitter, n); + + Ok(only_new!(JSXAttrName::Ident(n))) + } + JSXAttrName::JSXNamespacedName(ref n) => { + let n = emit!(emitter, n); + + Ok(only_new!(JSXAttrName::JSXNamespacedName(n))) + } } - Ok(()) } } @@ -109,14 +167,19 @@ impl MacroNode for JSXAttrName { impl MacroNode for JSXAttrOrSpread { fn emit(&mut self, emitter: &mut Macro) -> Result { match *self { - JSXAttrOrSpread::JSXAttr(ref n) => emit!(n), + JSXAttrOrSpread::JSXAttr(ref n) => { + let n = emit!(emitter, n); + + Ok(only_new!(JSXAttrOrSpread::JSXAttr(n))) + } JSXAttrOrSpread::SpreadElement(ref n) => { punct!(emitter, "{"); - emit!(n); + let n = emit!(emitter, n); punct!(emitter, "}"); + + Ok(only_new!(JSXAttrOrSpread::SpreadElement(n))) } } - Ok(()) } } @@ -124,34 +187,69 @@ impl MacroNode for JSXAttrOrSpread { impl MacroNode for JSXElementChild { fn emit(&mut self, emitter: &mut Macro) -> Result { match *self { - JSXElementChild::JSXElement(ref n) => emit!(n), - JSXElementChild::JSXExprContainer(ref n) => emit!(n), - JSXElementChild::JSXFragment(ref n) => emit!(n), - JSXElementChild::JSXSpreadChild(ref n) => emit!(n), - JSXElementChild::JSXText(ref n) => emit!(n), + JSXElementChild::JSXElement(ref n) => { + let n = emit!(emitter, n); + + Ok(only_new!(JSXElementChild::JSXElement(n))) + } + JSXElementChild::JSXExprContainer(ref n) => { + let n = emit!(emitter, n); + + Ok(only_new!(JSXElementChild::JSXExprContainer(n))) + } + JSXElementChild::JSXSpreadChild(ref n) => { + let n = emit!(emitter, n); + + Ok(only_new!(JSXElementChild::JSXSpreadChild(n))) + } + JSXElementChild::JSXFragment(ref n) => { + let n = emit!(emitter, n); + + Ok(only_new!(JSXElementChild::JSXFragment(n))) + } + JSXElementChild::JSXText(ref n) => { + let n = emit!(emitter, n); + + Ok(only_new!(JSXElementChild::JSXText(n))) + } } - Ok(()) } } #[node_impl] impl MacroNode for JSXSpreadChild { fn emit(&mut self, emitter: &mut Macro) -> Result { + let lo = only_new!(emitter.wr.get_pos()); + punct!(emitter, "{"); punct!(emitter, "..."); - emit!(self.expr); + emit!(emitter, self.expr); punct!(emitter, "}"); - Ok(()) + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(JSXSpreadChild { + span: Span::new(lo, hi), + ..self.clone() + })) } } #[node_impl] impl MacroNode for JSXExprContainer { fn emit(&mut self, emitter: &mut Macro) -> Result { + let lo = only_new!(emitter.wr.get_pos()); + punct!(emitter, "{"); - emit!(self.expr); + emit!(emitter, self.expr); punct!(emitter, "}"); - Ok(()) + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(JSXExprContainer { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -159,27 +257,44 @@ impl MacroNode for JSXExprContainer { impl MacroNode for JSXExpr { fn emit(&mut self, emitter: &mut Macro) -> Result { match *self { - JSXExpr::Expr(ref n) => emit!(n), - JSXExpr::JSXEmptyExpr(ref n) => emit!(n), + JSXExpr::Expr(ref n) => { + let n = emit!(emitter, n); + + Ok(only_new!(JSXExpr::Expr(n))) + } + JSXExpr::JSXEmptyExpr(ref n) => { + let n = emit!(emitter, n); + + Ok(only_new!(JSXExpr::JSXEmptyExpr(n))) + } } - Ok(()) } } #[node_impl] impl MacroNode for JSXClosingElement { fn emit(&mut self, emitter: &mut Macro) -> Result { + let lo = only_new!(emitter.wr.get_pos()); + punct!(emitter, ""); - Ok(()) + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(JSXClosingElement { + span: Span::new(lo, hi), + ..self.clone() + })) } } #[node_impl] impl MacroNode for JSXFragment { fn emit(&mut self, emitter: &mut Macro) -> Result { - emit!(self.opening); + let lo = only_new!(emitter.wr.get_pos()); + + emit!(emitter, self.opening); emitter.emit_list( self.span(), @@ -187,59 +302,106 @@ impl MacroNode for JSXFragment { ListFormat::JsxElementOrFragmentChildren, )?; - emit!(self.closing); - Ok(()) + emit!(emitter, self.closing); + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(JSXFragment { + span: Span::new(lo, hi), + ..self.clone() + })) } } #[node_impl] impl MacroNode for JSXOpeningFragment { fn emit(&mut self, emitter: &mut Macro) -> Result { + let lo = only_new!(emitter.wr.get_pos()); + punct!(emitter, "<>"); - Ok(()) + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(JSXOpeningFragment { + span: Span::new(lo, hi), + })) } } #[node_impl] impl MacroNode for JSXClosingFragment { fn emit(&mut self, emitter: &mut Macro) -> Result { + let lo = only_new!(emitter.wr.get_pos()); + punct!(emitter, ""); - Ok(()) + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(JSXClosingFragment { + span: Span::new(lo, hi), + })) } } - #[node_impl] impl MacroNode for JSXNamespacedName { fn emit(&mut self, emitter: &mut Macro) -> Result { - emit!(self.ns); + let lo = only_new!(emitter.wr.get_pos()); + + emit!(emitter, self.ns); punct!(emitter, ":"); - emit!(self.name); - Ok(()) + emit!(emitter, self.name); + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(JSXNamespacedName { + span: Span::new(lo, hi), + ..self.clone() + })) } } #[node_impl] impl MacroNode for JSXEmptyExpr { fn emit(&mut self, emitter: &mut Macro) -> Result { - Ok(()) + let lo = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(JSXEmptyExpr { + span: Span::new(lo, lo), + })) } } #[node_impl] impl MacroNode for JSXText { fn emit(&mut self, emitter: &mut Macro) -> Result { + let lo = only_new!(emitter.wr.get_pos()); + emitter.emit_atom(self.span(), &self.raw)?; - Ok(()) + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(JSXText { + span: Span::new(lo, hi), + ..self.clone() + })) } } #[node_impl] impl MacroNode for JSXMemberExpr { fn emit(&mut self, emitter: &mut Macro) -> Result { - emit!(self.obj); + let lo = only_new!(emitter.wr.get_pos()); + + emit!(emitter, self.obj); punct!(emitter, "."); - emit!(self.prop); - Ok(()) + emit!(emitter, self.prop); + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(JSXMemberExpr { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -247,9 +409,16 @@ impl MacroNode for JSXMemberExpr { impl MacroNode for JSXObject { fn emit(&mut self, emitter: &mut Macro) -> Result { match *self { - JSXObject::Ident(ref n) => emit!(n), - JSXObject::JSXMemberExpr(ref n) => emit!(n), + JSXObject::Ident(ref n) => { + let n = emit!(emitter, n); + + Ok(only_new!(JSXObject::Ident(n))) + } + JSXObject::JSXMemberExpr(ref n) => { + let n = emit!(emitter, n); + + Ok(only_new!(JSXObject::JSXMemberExpr(n))) + } } - Ok(()) } } diff --git a/crates/swc_ecma_codegen/src/lib.rs b/crates/swc_ecma_codegen/src/lib.rs index 8377a3e0ce91..f2d2d58980e5 100644 --- a/crates/swc_ecma_codegen/src/lib.rs +++ b/crates/swc_ecma_codegen/src/lib.rs @@ -5,7 +5,13 @@ #![allow(clippy::nonminimal_bool)] #![allow(non_local_definitions)] -use std::{borrow::Cow, fmt::Write, io, ops::Deref, str}; +use std::{ + borrow::Cow, + fmt::Write, + io, + ops::{Deref, DerefMut}, + str, +}; use compact_str::{format_compact, CompactString}; use memchr::memmem::Finder; @@ -18,6 +24,7 @@ use swc_common::{ }; use swc_ecma_ast::*; use swc_ecma_codegen_macros::node_impl; +use text_writer::SpannedWriteJs; pub use self::config::Config; use self::{text_writer::WriteJs, util::StartsWithAlphaNum}; @@ -42,7 +49,7 @@ pub mod text_writer; mod typescript; pub mod util; -pub type Result = io::Result<()>; +pub type Result = io::Result; /// Generate a code from a syntax node using default options. pub fn to_code_default( @@ -74,37 +81,60 @@ pub fn to_code(node: &impl Node) -> String { to_code_with_comments(None, node) } -pub trait Node: Spanned { - fn emit_with(&self, e: &mut Emitter<'_, W, S>) -> Result +pub trait Node: Spanned + Sized { + fn emit_with(&self, emitter: &mut Emitter<'_, W, S>) -> Result where W: WriteJs, S: SourceMapper + SourceMapperExt; + + fn with_new_span(&self, emitter: &mut NodeEmitter<'_, W, S>) -> Result + where + W: SpannedWriteJs, + S: SourceMapper + SourceMapperExt; } + impl Node for Box { - #[inline] - fn emit_with(&self, e: &mut Emitter<'_, W, S>) -> Result + fn emit_with(&self, emitter: &mut Emitter<'_, W, S>) -> Result where W: WriteJs, S: SourceMapper + SourceMapperExt, { - (**self).emit_with(e) + (**self).emit_with(emitter) + } + + fn with_new_span(&self, emitter: &mut NodeEmitter<'_, W, S>) -> Result + where + W: SpannedWriteJs, + S: SourceMapper + SourceMapperExt, + { + (**self).with_new_span(emitter).map(Box::new) } } -impl Node for &N { - #[inline] - fn emit_with(&self, e: &mut Emitter<'_, W, S>) -> Result + +/// TODO(kdy1): We may need to remove this impl +impl Node for &'_ N { + fn emit_with(&self, emitter: &mut Emitter<'_, W, S>) -> Result where W: WriteJs, S: SourceMapper + SourceMapperExt, { - (**self).emit_with(e) + (**self).emit_with(emitter) + } + + /// Noop + fn with_new_span(&self, _emitter: &mut NodeEmitter<'_, W, S>) -> Result + where + W: SpannedWriteJs, + S: SourceMapper + SourceMapperExt, + { + Ok(self) } } -pub struct Emitter<'a, W, S: SourceMapper> +pub struct Emitter<'a, W, S> where W: WriteJs, - S: SourceMapperExt, + S: SourceMapper + SourceMapperExt, { pub cfg: config::Config, pub cm: Lrc, @@ -112,6 +142,45 @@ where pub wr: W, } +pub struct NodeEmitter<'a, W, S> +where + W: SpannedWriteJs, + S: SourceMapper + SourceMapperExt, +{ + emitter: Emitter<'a, W, S>, +} + +impl<'a, W, S> NodeEmitter<'a, W, S> +where + W: SpannedWriteJs, + S: SourceMapper + SourceMapperExt, +{ + pub fn new(emitter: Emitter<'a, W, S>) -> Self { + Self { emitter } + } +} +impl<'a, W, S> Deref for NodeEmitter<'a, W, S> +where + W: SpannedWriteJs, + S: SourceMapper + SourceMapperExt, +{ + type Target = Emitter<'a, W, S>; + + fn deref(&self) -> &Self::Target { + &self.emitter + } +} + +impl DerefMut for NodeEmitter<'_, W, S> +where + W: SpannedWriteJs, + S: SourceMapper + SourceMapperExt, +{ + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.emitter + } +} + enum CowStr<'a> { Borrowed(&'a str), Owned(CompactString), @@ -163,10 +232,10 @@ where } else { formatting_space!(self); } - emit!(self, node.callee); + emit!(true, self, node.callee); if let Some(type_args) = &node.type_args { - emit!(self, type_args); + emit!(true, self, type_args); } if let Some(ref args) = node.args { @@ -202,7 +271,7 @@ where self.emit_template_element_for_tagged_template(&node.quasis[i / 2])?; } else { punct!(self, "${"); - emit!(self, node.exprs[i / 2]); + emit!(true, self, node.exprs[i / 2]); punct!(self, "}"); } } @@ -284,7 +353,7 @@ where } else { formatting_space!(self); } - emit!(self, node.right); + emit!(true, self, node.right); Ok(()) } @@ -292,7 +361,7 @@ where /// prints `(b){}` from `function a(b){}` fn emit_fn_trailing(&mut self, node: &Function) -> Result { if let Some(type_params) = &node.type_params { - emit!(self, type_params); + emit!(true, self, type_params); } punct!(self, "("); @@ -302,7 +371,7 @@ where if let Some(ty) = &node.return_type { punct!(self, ":"); formatting_space!(self); - emit!(self, ty); + emit!(true, self, ty); } if let Some(body) = &node.body { @@ -971,6 +1040,17 @@ where None => Ok(()), } } + + fn with_new_span(&self, emitter: &mut NodeEmitter<'_, W, S>) -> Result + where + W: SpannedWriteJs, + S: SourceMapper + SourceMapperExt, + { + match self { + Some(n) => Ok(Some(n.with_new_span(emitter)?)), + None => Ok(None), + } + } } fn get_template_element_from_raw( @@ -1402,14 +1482,18 @@ fn span_has_leading_comment(cmt: &dyn Comments, span: Span) -> bool { #[node_impl] impl MacroNode for Program { fn emit(&mut self, emitter: &mut Macro) -> Result { - match self { - Program::Module(m) => emit!(m), - Program::Script(s) => emit!(s), - // TODO: reenable once experimental_metadata breaking change is merged - // _ => unreachable!(), - } + Ok(match self { + Program::Module(m) => { + let n = emit!(emitter, m); - Ok(()) + only_new!(Program::Module(n)) + } + Program::Script(s) => { + let n = emit!(emitter, s); + + only_new!(Program::Script(n)) + } + }) } } @@ -1419,6 +1503,8 @@ impl MacroNode for Module { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + if self.body.is_empty() { srcmap!(emitter, self, true); } @@ -1429,7 +1515,7 @@ impl MacroNode for Module { emitter.wr.write_line()?; } for stmt in &self.body { - emit!(stmt); + emit!(emitter, stmt); } emitter.emit_trailing_comments_of_pos(self.span().hi, true, true)?; @@ -1437,7 +1523,12 @@ impl MacroNode for Module { emitter.wr.commit_pending_semi()?; } - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(Module { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -1447,6 +1538,8 @@ impl MacroNode for Script { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + if self.body.is_empty() { srcmap!(emitter, self, true); } @@ -1457,7 +1550,7 @@ impl MacroNode for Script { emitter.wr.write_line()?; } for stmt in &self.body { - emit!(stmt); + emit!(emitter, stmt); } emitter.emit_trailing_comments_of_pos(self.span().hi, true, true)?; @@ -1465,7 +1558,12 @@ impl MacroNode for Script { emitter.wr.commit_pending_semi()?; } - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(Script { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -1473,47 +1571,71 @@ impl MacroNode for Script { impl MacroNode for ModuleItem { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; - match self { - ModuleItem::Stmt(stmt) => emit!(stmt), - ModuleItem::ModuleDecl(decl) => emit!(decl), - } + let node = match self { + ModuleItem::Stmt(stmt) => { + let stmt = emit!(emitter, stmt); + + only_new!(ModuleItem::Stmt(stmt)) + } + ModuleItem::ModuleDecl(decl) => { + let decl = emit!(emitter, decl); + + only_new!(ModuleItem::ModuleDecl(decl)) + } + }; emitter.emit_trailing_comments_of_pos(self.span().hi, true, true)?; - Ok(()) + Ok(node) } } #[node_impl] impl MacroNode for Callee { fn emit(&mut self, emitter: &mut Macro) -> Result { - match self { + Ok(match self { Callee::Expr(e) => { - if let Expr::New(new) = &**e { + let e = if let Expr::New(new) = &**e { emitter.emit_new(new, false)?; + only_new!(Box::new(Expr::New(new.clone()))) } else { - emit!(e); - } + emit!(emitter, e) + }; + + only_new!(Callee::Expr(e)) } - Callee::Super(n) => emit!(n), - Callee::Import(n) => emit!(n), - } + Callee::Super(n) => { + let n = emit!(emitter, n); - Ok(()) + only_new!(Callee::Super(n)) + } + Callee::Import(n) => { + let n = emit!(emitter, n); + only_new!(Callee::Import(n)) + } + }) } } #[node_impl] impl MacroNode for Super { fn emit(&mut self, emitter: &mut Macro) -> Result { + let lo = only_new!(emitter.wr.get_pos()); + keyword!(emitter, self.span, "super"); - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(Super { + span: Span::new(lo, hi), + })) } } #[node_impl] impl MacroNode for Import { fn emit(&mut self, emitter: &mut Macro) -> Result { + let lo = only_new!(emitter.wr.get_pos()); + keyword!(emitter, self.span, "import"); match self.phase { ImportPhase::Source => { @@ -1527,63 +1649,216 @@ impl MacroNode for Import { _ => {} } - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(Import { + span: Span::new(lo, hi), + ..*self + })) } } #[node_impl] impl MacroNode for Expr { fn emit(&mut self, emitter: &mut Macro) -> Result { - match self { - Expr::Array(n) => emit!(n), - Expr::Arrow(n) => emit!(n), - Expr::Assign(n) => emit!(n), - Expr::Await(n) => emit!(n), - Expr::Bin(n) => emit!(n), - Expr::Call(n) => emit!(n), - Expr::Class(n) => emit!(n), - Expr::Cond(n) => emit!(n), - Expr::Fn(n) => emit!(n), - Expr::Ident(n) => emit!(n), - Expr::Lit(n) => emit!(n), - Expr::Member(n) => emit!(n), - Expr::SuperProp(n) => emit!(n), - Expr::MetaProp(n) => emit!(n), - Expr::New(n) => emit!(n), - Expr::Object(n) => emit!(n), - Expr::Paren(n) => emit!(n), - Expr::Seq(n) => emit!(n), - Expr::TaggedTpl(n) => emit!(n), - Expr::This(n) => emit!(n), - Expr::Tpl(n) => emit!(n), - Expr::Unary(n) => emit!(n), - Expr::Update(n) => emit!(n), - Expr::Yield(n) => emit!(n), - Expr::PrivateName(n) => emit!(n), - - Expr::JSXMember(n) => emit!(n), - Expr::JSXNamespacedName(n) => emit!(n), - Expr::JSXEmpty(n) => emit!(n), - Expr::JSXElement(n) => emit!(n), - Expr::JSXFragment(n) => emit!(n), - - Expr::TsAs(n) => emit!(n), - Expr::TsNonNull(n) => emit!(n), - Expr::TsTypeAssertion(n) => emit!(n), - Expr::TsConstAssertion(n) => emit!(n), - Expr::TsInstantiation(n) => emit!(n), - Expr::OptChain(n) => emit!(n), - Expr::Invalid(n) => emit!(n), + let result = match self { + Expr::Array(n) => { + let n = emit!(emitter, n); + + only_new!(Expr::Array(n)) + } + Expr::Arrow(n) => { + let n = emit!(emitter, n); + + only_new!(Expr::Arrow(n)) + } + Expr::Assign(n) => { + let n = emit!(emitter, n); + + only_new!(Expr::Assign(n)) + } + Expr::Await(n) => { + let n = emit!(emitter, n); + + only_new!(Expr::Await(n)) + } + Expr::Bin(n) => { + let n = emit!(emitter, n); + + only_new!(Expr::Bin(n)) + } + Expr::Call(n) => { + let n = emit!(emitter, n); + + only_new!(Expr::Call(n)) + } + Expr::Class(n) => { + let n = emit!(emitter, n); + + only_new!(Expr::Class(n)) + } + Expr::Cond(n) => { + let n = emit!(emitter, n); + + only_new!(Expr::Cond(n)) + } + Expr::Fn(n) => { + let n = emit!(emitter, n); + + only_new!(Expr::Fn(n)) + } + Expr::Ident(n) => { + let n = emit!(emitter, n); + + only_new!(Expr::Ident(n)) + } + Expr::Lit(n) => { + let n = emit!(emitter, n); + + only_new!(Expr::Lit(n)) + } + Expr::Member(n) => { + let n = emit!(emitter, n); + + only_new!(Expr::Member(n)) + } + Expr::SuperProp(n) => { + let n = emit!(emitter, n); + + only_new!(Expr::SuperProp(n)) + } + Expr::MetaProp(n) => { + let n = emit!(emitter, n); + + only_new!(Expr::MetaProp(n)) + } + Expr::New(n) => { + let n = emit!(emitter, n); + + only_new!(Expr::New(n)) + } + Expr::Object(n) => { + let n = emit!(emitter, n); + + only_new!(Expr::Object(n)) + } + Expr::Paren(n) => { + let n = emit!(emitter, n); + + only_new!(Expr::Paren(n)) + } + Expr::Seq(n) => { + let n = emit!(emitter, n); + + only_new!(Expr::Seq(n)) + } + Expr::TaggedTpl(n) => { + let n = emit!(emitter, n); + + only_new!(Expr::TaggedTpl(n)) + } + Expr::This(n) => { + let n = emit!(emitter, n); + + only_new!(Expr::This(n)) + } + Expr::Tpl(n) => { + let n = emit!(emitter, n); + + only_new!(Expr::Tpl(n)) + } + Expr::Unary(n) => { + let n = emit!(emitter, n); + + only_new!(Expr::Unary(n)) + } + Expr::Update(n) => { + let n = emit!(emitter, n); + + only_new!(Expr::Update(n)) + } + Expr::Yield(n) => { + let n = emit!(emitter, n); + + only_new!(Expr::Yield(n)) + } + Expr::JSXMember(n) => { + let n = emit!(emitter, n); + + only_new!(Expr::JSXMember(n)) + } + Expr::JSXNamespacedName(n) => { + let n = emit!(emitter, n); + + only_new!(Expr::JSXNamespacedName(n)) + } + Expr::JSXEmpty(n) => { + let n = emit!(emitter, n); + + only_new!(Expr::JSXEmpty(n)) + } + Expr::JSXElement(n) => { + let n = emit!(emitter, n); + + only_new!(Expr::JSXElement(n)) + } + Expr::JSXFragment(n) => { + let n = emit!(emitter, n); + + only_new!(Expr::JSXFragment(n)) + } + Expr::TsAs(n) => { + let n = emit!(emitter, n); + + only_new!(Expr::TsAs(n)) + } + Expr::TsNonNull(n) => { + let n = emit!(emitter, n); + + only_new!(Expr::TsNonNull(n)) + } + Expr::TsTypeAssertion(n) => { + let n = emit!(emitter, n); + + only_new!(Expr::TsTypeAssertion(n)) + } + Expr::TsConstAssertion(n) => { + let n = emit!(emitter, n); + + only_new!(Expr::TsConstAssertion(n)) + } + Expr::TsInstantiation(n) => { + let n = emit!(emitter, n); + + only_new!(Expr::TsInstantiation(n)) + } + Expr::OptChain(n) => { + let n = emit!(emitter, n); + + only_new!(Expr::OptChain(n)) + } Expr::TsSatisfies(n) => { - emit!(n) + let n = emit!(emitter, n); + + only_new!(Expr::TsSatisfies(n)) } - } + Expr::Invalid(n) => { + let n = emit!(emitter, n); + + only_new!(Expr::Invalid(n)) + } + Expr::PrivateName(n) => { + let n = emit!(emitter, n); + + only_new!(Expr::PrivateName(n)) + } + }; if emitter.comments.is_some() { emitter.emit_trailing_comments_of_pos(self.span().hi, true, true)?; } - Ok(()) + Ok(result) } } @@ -1592,28 +1867,51 @@ impl MacroNode for OptChainExpr { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; - match &*self.base { + let lo = only_new!(emitter.wr.get_pos()); + + let base = match &*self.base { OptChainBase::Member(e) => { - if let Expr::New(new) = &*e.obj { + let obj = if let Expr::New(new) = &*e.obj { emitter.emit_new(new, false)?; + only_new!(Box::new(Expr::New(new.clone()))) } else { - emit!(e.obj); - } + emit!(emitter, e.obj) + }; + if self.optional { punct!(emitter, "?."); } else if !e.prop.is_computed() { punct!(emitter, "."); } - match &e.prop { - MemberProp::Computed(computed) => emit!(computed), - MemberProp::Ident(i) => emit!(i), - MemberProp::PrivateName(p) => emit!(p), - } + let prop = match &e.prop { + MemberProp::Computed(computed) => { + let n = emit!(emitter, computed); + + only_new!(MemberProp::Computed(n)) + } + MemberProp::Ident(i) => { + let n = emit!(emitter, i); + + only_new!(MemberProp::Ident(n)) + } + MemberProp::PrivateName(p) => { + let n = emit!(emitter, p); + only_new!(MemberProp::PrivateName(n)) + } + }; + + let hi = only_new!(emitter.wr.get_pos()); + + only_new!(Box::new(OptChainBase::Member(MemberExpr { + span: Span::new(lo, hi), + obj, + prop, + }))) } OptChainBase::Call(e) => { debug_assert!(!e.callee.is_new()); - emit!(e.callee); + emit!(emitter, e.callee); if self.optional { punct!(emitter, "?."); @@ -1626,10 +1924,23 @@ impl MacroNode for OptChainExpr { ListFormat::CallExpressionArguments, )?; punct!(emitter, ")"); + + let hi = only_new!(emitter.wr.get_pos()); + + only_new!(Box::new(OptChainBase::Call(OptCall { + span: Span::new(lo, hi), + ..e.clone() + }))) } - } + }; - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(OptChainExpr { + span: Span::new(lo, hi), + base, + ..self.clone() + })) } } @@ -1638,9 +1949,15 @@ impl MacroNode for Invalid { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span, false)?; + let lo = only_new!(emitter.wr.get_pos()); + emitter.wr.write_str_lit(self.span, "")?; - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(Invalid { + span: Span::new(lo, hi), + })) } } @@ -1649,14 +1966,16 @@ impl MacroNode for CallExpr { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.wr.commit_pending_semi()?; + let lo = only_new!(emitter.wr.get_pos()); + emitter.emit_leading_comments_of_span(self.span(), false)?; srcmap!(emitter, self, true); - emit!(self.callee); + emit!(emitter, self.callee); if let Some(type_args) = &self.type_args { - emit!(type_args); + emit!(emitter, type_args); } punct!(emitter, "("); @@ -1669,16 +1988,28 @@ impl MacroNode for CallExpr { // srcmap!(emitter, self, false); - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(CallExpr { + span: Span::new(lo, hi), + ..self.clone() + })) } } #[node_impl] impl MacroNode for NewExpr { fn emit(&mut self, emitter: &mut Macro) -> Result { + let lo = only_new!(emitter.wr.get_pos()); + emitter.emit_new(self, true)?; - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(NewExpr { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -1687,6 +2018,8 @@ impl MacroNode for MemberExpr { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + srcmap!(emitter, self, true); let mut needs_2dots_for_property_access = false; @@ -1699,12 +2032,16 @@ impl MacroNode for MemberExpr { needs_2dots_for_property_access = emitter.emit_num_lit_internal(num, true)?; } _ => { - emit!(self.obj); + emit!(emitter, self.obj); } } - match &self.prop { - MemberProp::Computed(computed) => emit!(computed), + let prop = match &self.prop { + MemberProp::Computed(computed) => { + let n = emit!(emitter, computed); + + only_new!(MemberProp::Computed(n)) + } MemberProp::Ident(ident) => { if needs_2dots_for_property_access { if self.prop.span().lo() >= BytePos(2) { @@ -1716,7 +2053,9 @@ impl MacroNode for MemberExpr { emitter.emit_leading_comments(self.prop.span().lo() - BytePos(1), false)?; } punct!(emitter, "."); - emit!(ident); + let ident = emit!(emitter, ident); + + only_new!(MemberProp::Ident(ident)) } MemberProp::PrivateName(private) => { if needs_2dots_for_property_access { @@ -1729,13 +2068,21 @@ impl MacroNode for MemberExpr { emitter.emit_leading_comments(self.prop.span().lo() - BytePos(1), false)?; } punct!(emitter, "."); - emit!(private); + let private = emit!(emitter, private); + + only_new!(MemberProp::PrivateName(private)) } - } + }; srcmap!(emitter, self, false); - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(MemberExpr { + span: Span::new(lo, hi), + prop, + ..self.clone() + })) } } @@ -1744,22 +2091,36 @@ impl MacroNode for SuperPropExpr { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + srcmap!(emitter, self, true); - emit!(self.obj); + emit!(emitter, self.obj); - match &self.prop { - SuperProp::Computed(computed) => emit!(computed), + let prop = match &self.prop { + SuperProp::Computed(computed) => { + let n = emit!(emitter, computed); + + only_new!(SuperProp::Computed(n)) + } SuperProp::Ident(i) => { if self.prop.span().lo() >= BytePos(1) { emitter.emit_leading_comments(self.prop.span().lo() - BytePos(1), false)?; } punct!(emitter, "."); - emit!(i); + let ident = emit!(emitter, i); + + only_new!(SuperProp::Ident(ident)) } - } + }; - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(SuperPropExpr { + span: Span::new(lo, hi), + prop, + ..self.clone() + })) } } @@ -1768,6 +2129,8 @@ impl MacroNode for ArrowExpr { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + srcmap!(emitter, self, true); let space = !emitter.cfg.minify @@ -1794,7 +2157,7 @@ impl MacroNode for ArrowExpr { _ => true, }; - emit!(self.type_params); + emit!(emitter, self.type_params); if parens { punct!(emitter, "("); @@ -1808,14 +2171,19 @@ impl MacroNode for ArrowExpr { if let Some(ty) = &self.return_type { punct!(emitter, ":"); formatting_space!(emitter); - emit!(ty); + emit!(emitter, ty); formatting_space!(emitter); } punct!(emitter, "=>"); - emit!(self.body); + emit!(emitter, self.body); - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(ArrowExpr { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -1826,6 +2194,8 @@ impl MacroNode for MetaPropExpr { emitter.emit_leading_comments_of_span(self.span(), false)?; } + let lo = only_new!(emitter.wr.get_pos()); + srcmap!(emitter, self, true); match self.kind { @@ -1834,7 +2204,12 @@ impl MacroNode for MetaPropExpr { MetaPropKind::NewTarget => keyword!(emitter, "new.target"), } - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(MetaPropExpr { + span: Span::new(lo, hi), + ..*self + })) } } @@ -1843,6 +2218,8 @@ impl MacroNode for SeqExpr { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + srcmap!(emitter, self, true); let mut first = true; @@ -1855,10 +2232,15 @@ impl MacroNode for SeqExpr { formatting_space!(emitter); } - emit!(e); + emit!(emitter, e); } - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(SeqExpr { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -1867,13 +2249,20 @@ impl MacroNode for AssignExpr { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; - emit!(self.left); + let lo = only_new!(emitter.wr.get_pos()); + + emit!(emitter, self.left); formatting_space!(emitter); operator!(emitter, self.op.as_str()); formatting_space!(emitter); - emit!(self.right); + emit!(emitter, self.right); - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(AssignExpr { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -1882,6 +2271,8 @@ impl MacroNode for BinExpr { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + srcmap!(emitter, self, true); { @@ -1902,7 +2293,7 @@ impl MacroNode for BinExpr { for (i, left) in lefts.into_iter().rev().enumerate() { if i == 0 { - emit!(left.left); + emit!(emitter, left.left); } // Check if it's last if i + 1 != len { @@ -1913,7 +2304,12 @@ impl MacroNode for BinExpr { emitter.emit_bin_expr_trailing(self)?; - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(BinExpr { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -1922,15 +2318,22 @@ impl MacroNode for Decorator { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + srcmap!(emitter, self, true); punct!(emitter, "@"); - emit!(self.expr); + emit!(emitter, self.expr); emitter.wr.write_line()?; srcmap!(emitter, self, false); - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(Decorator { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -1939,19 +2342,26 @@ impl MacroNode for CondExpr { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + srcmap!(emitter, self, true); - emit!(self.test); + emit!(emitter, self.test); formatting_space!(emitter); punct!(emitter, "?"); formatting_space!(emitter); - emit!(self.cons); + emit!(emitter, self.cons); formatting_space!(emitter); punct!(emitter, ":"); formatting_space!(emitter); - emit!(self.alt); + emit!(emitter, self.alt); - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(CondExpr { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -1962,6 +2372,8 @@ impl MacroNode for FnExpr { emitter.wr.commit_pending_semi()?; + let lo = only_new!(emitter.wr.get_pos()); + srcmap!(emitter, self, true); if self.function.is_async { @@ -1977,12 +2389,20 @@ impl MacroNode for FnExpr { } if let Some(ref i) = self.ident { space!(emitter); - emit!(i); + emit!(emitter, i); } emitter.emit_fn_trailing(&self.function)?; - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(FnExpr { + function: Box::new(Function { + span: Span::new(lo, hi), + ..*self.function.clone() + }), + ..self.clone() + })) } } @@ -1992,15 +2412,17 @@ impl MacroNode for BlockStmtOrExpr { match self { BlockStmtOrExpr::BlockStmt(block) => { emitter.emit_block_stmt_inner(block, true)?; + + Ok(only_new!(BlockStmtOrExpr::BlockStmt(block.clone()))) } BlockStmtOrExpr::Expr(expr) => { emitter.wr.increase_indent()?; - emit!(expr); + let expr = emit!(emitter, expr); emitter.wr.decrease_indent()?; + + Ok(only_new!(BlockStmtOrExpr::Expr(expr))) } } - - Ok(()) } } @@ -2009,9 +2431,15 @@ impl MacroNode for ThisExpr { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + keyword!(emitter, self.span, "this"); - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(ThisExpr { + span: Span::new(lo, hi), + })) } } @@ -2022,16 +2450,18 @@ impl MacroNode for Tpl { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + srcmap!(emitter, self, true); punct!(emitter, "`"); for i in 0..(self.quasis.len() + self.exprs.len()) { if i % 2 == 0 { - emit!(self.quasis[i / 2]); + emit!(emitter, self.quasis[i / 2]); } else { punct!(emitter, "${"); - emit!(self.exprs[i / 2]); + emit!(emitter, self.exprs[i / 2]); punct!(emitter, "}"); } } @@ -2040,13 +2470,20 @@ impl MacroNode for Tpl { srcmap!(emitter, self, false); - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(Tpl { + span: Span::new(lo, hi), + ..self.clone() + })) } } #[node_impl] impl MacroNode for TplElement { fn emit(&mut self, emitter: &mut Macro) -> Result { + let lo = only_new!(emitter.wr.get_pos()); + let raw = self.raw.replace("\r\n", "\n").replace('\r', "\n"); if emitter.cfg.minify || (emitter.cfg.ascii_only && !self.raw.is_ascii()) { let v = get_template_element_from_raw( @@ -2085,7 +2522,12 @@ impl MacroNode for TplElement { emitter.wr.write_str_lit(self.span(), &raw)?; } - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(TplElement { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -2094,20 +2536,27 @@ impl MacroNode for TaggedTpl { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + srcmap!(emitter, self, true); if let Expr::New(new) = &*self.tag { emitter.emit_new(new, false)?; } else { - emit!(self.tag); + emit!(emitter, self.tag); } - emit!(self.type_params); + emit!(emitter, self.type_params); emitter.emit_template_for_tagged_template(&self.tpl)?; srcmap!(emitter, self, false); - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(TaggedTpl { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -2116,6 +2565,8 @@ impl MacroNode for UnaryExpr { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + srcmap!(emitter, self, true); let need_formatting_space = match self.op { @@ -2136,9 +2587,14 @@ impl MacroNode for UnaryExpr { formatting_space!(emitter); } - emit!(self.arg); + emit!(emitter, self.arg); - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(UnaryExpr { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -2147,18 +2603,25 @@ impl MacroNode for UpdateExpr { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + srcmap!(emitter, self, true); if self.prefix { operator!(emitter, self.op.as_str()); //TODO: Check if we should use should_emit_whitespace_before_operand - emit!(self.arg); + emit!(emitter, self.arg); } else { - emit!(self.arg); + emit!(emitter, self.arg); operator!(emitter, self.op.as_str()); } - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(UpdateExpr { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -2167,6 +2630,8 @@ impl MacroNode for YieldExpr { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + srcmap!(emitter, self, true); keyword!(emitter, "yield"); @@ -2188,13 +2653,18 @@ impl MacroNode for YieldExpr { formatting_space!(emitter) } - emit!(self.arg); + emit!(emitter, self.arg); if need_paren { punct!(emitter, ")") } } - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(YieldExpr { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -2207,9 +2677,9 @@ impl MacroNode for ExprOrSpread { punct!(emitter, "..."); } - emit!(self.expr); + emit!(emitter, self.expr); - Ok(()) + Ok(only_new!(ExprOrSpread { ..self.clone() })) } } @@ -2218,14 +2688,21 @@ impl MacroNode for AwaitExpr { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + srcmap!(emitter, self, true); keyword!(emitter, "await"); space!(emitter); - emit!(self.arg); + emit!(emitter, self.arg); - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(AwaitExpr { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -2234,6 +2711,8 @@ impl MacroNode for ArrayLit { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + srcmap!(emitter, self, true); punct!(emitter, "["); @@ -2247,7 +2726,12 @@ impl MacroNode for ArrayLit { srcmap!(emitter, self, false); - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(ArrayLit { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -2256,17 +2740,24 @@ impl MacroNode for ParenExpr { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.wr.commit_pending_semi()?; + let lo = only_new!(emitter.wr.get_pos()); + emitter.emit_leading_comments_of_span(self.span(), false)?; srcmap!(emitter, self, true); punct!(emitter, "("); - emit!(self.expr); + emit!(emitter, self.expr); srcmap!(emitter, self, false, true); punct!(emitter, ")"); - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(ParenExpr { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -2275,6 +2766,8 @@ impl MacroNode for PrivateName { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + srcmap!(emitter, self, true); punct!(emitter, "#"); @@ -2282,19 +2775,26 @@ impl MacroNode for PrivateName { srcmap!(emitter, self, false); - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(PrivateName { + span: Span::new(lo, hi), + ..self.clone() + })) } } #[node_impl] impl MacroNode for BindingIdent { fn emit(&mut self, emitter: &mut Macro) -> Result { + let lo = only_new!(emitter.wr.get_pos()); + emitter.emit_ident_like(self.span, &self.sym, self.optional)?; if let Some(ty) = &self.type_ann { punct!(emitter, ":"); formatting_space!(emitter); - emit!(ty); + emit!(emitter, ty); } // Call emitList directly since it could be an array of @@ -2302,24 +2802,46 @@ impl MacroNode for BindingIdent { // emitList(node, node.typeArguments, ListFormat::TypeParameters); - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(BindingIdent { + id: Ident { + span: Span::new(lo, hi), + ..self.id.clone() + }, + ..self.clone() + })) } } #[node_impl] impl MacroNode for Ident { fn emit(&mut self, emitter: &mut Macro) -> Result { + let lo = only_new!(emitter.wr.get_pos()); + emitter.emit_ident_like(self.span, &self.sym, self.optional)?; - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(Ident { + span: Span::new(lo, hi), + ..self.clone() + })) } } #[node_impl] impl MacroNode for IdentName { fn emit(&mut self, emitter: &mut Macro) -> Result { + let lo = only_new!(emitter.wr.get_pos()); + emitter.emit_ident_like(self.span, &self.sym, false)?; - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(IdentName { + span: Span::new(lo, hi), + ..self.clone() + })) } } diff --git a/crates/swc_ecma_codegen/src/lit.rs b/crates/swc_ecma_codegen/src/lit.rs index 1e89f3aae73a..c0102a646429 100644 --- a/crates/swc_ecma_codegen/src/lit.rs +++ b/crates/swc_ecma_codegen/src/lit.rs @@ -2,7 +2,7 @@ use std::{fmt::Write, io, str}; use ascii::AsciiChar; use compact_str::CompactString; -use swc_common::{Spanned, DUMMY_SP}; +use swc_common::{Span, Spanned, DUMMY_SP}; use swc_ecma_ast::*; use swc_ecma_codegen_macros::node_impl; @@ -16,27 +16,59 @@ impl MacroNode for Lit { srcmap!(emitter, self, true); match self { - Lit::Bool(Bool { value, .. }) => { - if *value { - keyword!(emitter, "true") - } else { - keyword!(emitter, "false") - } + Lit::Bool(v) => { + let v = emit!(emitter, v); + + Ok(only_new!(Lit::Bool(v))) + } + Lit::Null(Null { .. }) => { + let lo = only_new!(emitter.wr.get_pos()); + + keyword!(emitter, "null"); + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(Lit::Null(Null { + span: Span::new(lo, hi) + }))) + } + Lit::Str(ref s) => { + let s = emit!(emitter, s); + + Ok(only_new!(Lit::Str(s))) + } + Lit::BigInt(ref s) => { + let bigint = emit!(emitter, s); + + Ok(only_new!(Lit::BigInt(bigint))) + } + Lit::Num(ref n) => { + let number = emit!(emitter, n); + + Ok(only_new!(Lit::Num(number))) } - Lit::Null(Null { .. }) => keyword!(emitter, "null"), - Lit::Str(ref s) => emit!(s), - Lit::BigInt(ref s) => emit!(s), - Lit::Num(ref n) => emit!(n), Lit::Regex(ref n) => { + let lo = only_new!(emitter.wr.get_pos()); + punct!(emitter, "/"); emitter.wr.write_str(&n.exp)?; punct!(emitter, "/"); emitter.wr.write_str(&n.flags)?; + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(Lit::Regex(Regex { + span: Span::new(lo, hi), + exp: n.exp.clone(), + flags: n.flags.clone(), + }))) } - Lit::JSXText(ref n) => emit!(n), - } + Lit::JSXText(ref n) => { + let s = emit!(emitter, n); - Ok(()) + Ok(only_new!(Lit::JSXText(s))) + } + } } } @@ -45,6 +77,8 @@ impl MacroNode for Str { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.wr.commit_pending_semi()?; + let lo = only_new!(emitter.wr.get_pos()); + emitter.emit_leading_comments_of_span(self.span(), false)?; srcmap!(emitter, self, true); @@ -60,7 +94,12 @@ impl MacroNode for Str { srcmap!(emitter, self, false); - return Ok(()); + let hi = only_new!(emitter.wr.get_pos()); + + return Ok(only_new!(Str { + span: Span::new(lo, hi), + ..self.clone() + })); } let target = emitter.cfg.target; @@ -82,7 +121,13 @@ impl MacroNode for Str { || !self.raw.as_ref().unwrap().contains("script")) { emitter.wr.write_str_lit(DUMMY_SP, raw)?; - return Ok(()); + + let hi = only_new!(emitter.wr.get_pos()); + + return Ok(only_new!(Str { + span: Span::new(lo, hi), + ..self.clone() + })); } } } @@ -110,16 +155,28 @@ impl MacroNode for Str { // srcmap!(emitter,self, false); - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(Str { + span: Span::new(lo, hi), + ..self.clone() + })) } } #[node_impl] impl MacroNode for Number { fn emit(&mut self, emitter: &mut Macro) -> Result { + let lo = only_new!(emitter.wr.get_pos()); + emitter.emit_num_lit_internal(self, false)?; - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(Number { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -128,6 +185,8 @@ impl MacroNode for BigInt { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span, false)?; + let lo = only_new!(emitter.wr.get_pos()); + if emitter.cfg.minify { let value = if *self.value >= 10000000000000000_i64.into() { format!("0x{}", self.value.to_str_radix(16)) @@ -155,7 +214,12 @@ impl MacroNode for BigInt { } } - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(BigInt { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -164,13 +228,20 @@ impl MacroNode for Bool { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + if self.value { keyword!(emitter, self.span, "true") } else { keyword!(emitter, self.span, "false") } - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(Bool { + span: Span::new(lo, hi), + ..*self + })) } } diff --git a/crates/swc_ecma_codegen/src/macros.rs b/crates/swc_ecma_codegen/src/macros.rs index 694f85ed1f10..221ac43453ea 100644 --- a/crates/swc_ecma_codegen/src/macros.rs +++ b/crates/swc_ecma_codegen/src/macros.rs @@ -4,7 +4,7 @@ macro_rules! opt_leading_space { ($emitter:expr, $e:expr) => { if let Some(ref e) = $e { formatting_space!($emitter); - emit!($emitter, e); + emit!(true, $emitter, e); } }; } @@ -12,7 +12,7 @@ macro_rules! opt_leading_space { macro_rules! opt { ($emitter:expr, $e:expr) => {{ if let Some(ref expr) = $e { - emit!($emitter, expr); + emit!(true, $emitter, expr); } }}; ($emitter:expr, $e:expr,) => {{ @@ -20,12 +20,6 @@ macro_rules! opt { }}; } -macro_rules! emit { - ($emitter:expr, $e:expr) => {{ - crate::Node::emit_with(&$e, $emitter)?; - }}; -} - macro_rules! keyword { ($emitter:expr, $span:expr, $s:expr) => { $emitter.wr.write_keyword(Some($span), $s)? @@ -129,8 +123,29 @@ macro_rules! srcmap { }; } -macro_rules! emit_node_inner { - ($emitter:expr, true, $n:expr) => { +macro_rules! emit { + (true, $emitter:expr, $n:ident) => { + crate::Node::emit_with($n, $emitter)? + }; + (true, $emitter:expr, $n:expr) => { crate::Node::emit_with(&$n, $emitter)? }; + + (false, $emitter:expr, $n:ident) => { + crate::Node::with_new_span($n, $emitter)? + }; + + (false, $emitter:expr, $n:expr) => { + crate::Node::with_new_span(&$n, $emitter)? + }; +} + +macro_rules! only_new { + (true, $n:expr) => { + () + }; + + (false, $n:expr) => { + $n + }; } diff --git a/crates/swc_ecma_codegen/src/module_decls.rs b/crates/swc_ecma_codegen/src/module_decls.rs index 5fc63e4d71e6..121edaee07e4 100644 --- a/crates/swc_ecma_codegen/src/module_decls.rs +++ b/crates/swc_ecma_codegen/src/module_decls.rs @@ -1,4 +1,4 @@ -use swc_common::Spanned; +use swc_common::{Span, Spanned}; use swc_ecma_ast::*; use swc_ecma_codegen_macros::node_impl; @@ -9,17 +9,53 @@ impl MacroNode for ModuleDecl { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; - match self { - ModuleDecl::Import(ref d) => emit!(d), - ModuleDecl::ExportDecl(ref d) => emit!(d), - ModuleDecl::ExportNamed(ref d) => emit!(d), - ModuleDecl::ExportDefaultDecl(ref d) => emit!(d), - ModuleDecl::ExportDefaultExpr(ref n) => emit!(n), - ModuleDecl::ExportAll(ref d) => emit!(d), - ModuleDecl::TsExportAssignment(ref n) => emit!(n), - ModuleDecl::TsImportEquals(ref n) => emit!(n), - ModuleDecl::TsNamespaceExport(ref n) => emit!(n), - } + let result = match self { + ModuleDecl::Import(ref d) => { + let n = emit!(emitter, d); + + Ok(only_new!(ModuleDecl::Import(n))) + } + ModuleDecl::ExportDecl(ref d) => { + let n = emit!(emitter, d); + + Ok(only_new!(ModuleDecl::ExportDecl(n))) + } + ModuleDecl::ExportNamed(ref d) => { + let n = emit!(emitter, d); + + Ok(only_new!(ModuleDecl::ExportNamed(n))) + } + ModuleDecl::ExportDefaultDecl(ref d) => { + let n = emit!(emitter, d); + + Ok(only_new!(ModuleDecl::ExportDefaultDecl(n))) + } + ModuleDecl::ExportDefaultExpr(ref n) => { + let n = emit!(emitter, n); + + Ok(only_new!(ModuleDecl::ExportDefaultExpr(n))) + } + ModuleDecl::ExportAll(ref d) => { + let n = emit!(emitter, d); + + Ok(only_new!(ModuleDecl::ExportAll(n))) + } + ModuleDecl::TsExportAssignment(ref n) => { + let n = emit!(emitter, n); + + Ok(only_new!(ModuleDecl::TsExportAssignment(n))) + } + ModuleDecl::TsImportEquals(ref n) => { + let n = emit!(emitter, n); + + Ok(only_new!(ModuleDecl::TsImportEquals(n))) + } + ModuleDecl::TsNamespaceExport(ref n) => { + let n = emit!(emitter, n); + + Ok(only_new!(ModuleDecl::TsNamespaceExport(n))) + } + }; emitter.emit_trailing_comments_of_pos(self.span().hi, true, true)?; @@ -27,19 +63,21 @@ impl MacroNode for ModuleDecl { emitter.wr.write_line()?; } - Ok(()) + result } } #[node_impl] impl MacroNode for ExportDecl { fn emit(&mut self, emitter: &mut Macro) -> Result { + let lo = only_new!(emitter.wr.get_pos()); + srcmap!(emitter, self, true); match &self.decl { Decl::Class(decl) => { for dec in &decl.class.decorators { - emit!(dec); + emit!(emitter, dec); } keyword!(emitter, "export"); @@ -51,17 +89,24 @@ impl MacroNode for ExportDecl { keyword!(emitter, "export"); space!(emitter); - emit!(self.decl); + emit!(emitter, self.decl); } } - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(ExportDecl { + span: Span::new(lo, hi), + ..self.clone() + })) } } #[node_impl] impl MacroNode for ExportDefaultExpr { fn emit(&mut self, emitter: &mut Macro) -> Result { + let lo = only_new!(emitter.wr.get_pos()); + srcmap!(emitter, self, true); keyword!(emitter, "export"); @@ -75,13 +120,18 @@ impl MacroNode for ExportDefaultExpr { } else { formatting_space!(emitter); } - emit!(self.expr); + emit!(emitter, self.expr); } semi!(emitter); srcmap!(emitter, self, false); - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(ExportDefaultExpr { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -90,6 +140,8 @@ impl MacroNode for ExportDefaultDecl { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + srcmap!(emitter, self, true); keyword!(emitter, "export"); @@ -97,13 +149,30 @@ impl MacroNode for ExportDefaultDecl { space!(emitter); keyword!(emitter, "default"); space!(emitter); - match self.decl { - DefaultDecl::Class(ref n) => emit!(n), - DefaultDecl::Fn(ref n) => emit!(n), - DefaultDecl::TsInterfaceDecl(ref n) => emit!(n), - } + let decl = match self.decl { + DefaultDecl::Class(ref n) => { + let n = emit!(emitter, n); + + only_new!(DefaultDecl::Class(n)) + } + DefaultDecl::Fn(ref n) => { + let n = emit!(emitter, n); + + only_new!(DefaultDecl::Fn(n)) + } + DefaultDecl::TsInterfaceDecl(ref n) => { + let n = emit!(emitter, n); + + only_new!(DefaultDecl::TsInterfaceDecl(n)) + } + }; - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(ExportDefaultDecl { + span: Span::new(lo, hi), + decl, + })) } } @@ -112,6 +181,8 @@ impl MacroNode for ImportDecl { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + srcmap!(emitter, self, true); keyword!(emitter, "import"); @@ -153,7 +224,7 @@ impl MacroNode for ImportDecl { specifiers.push(s); } ImportSpecifier::Default(ref s) => { - emit!(s.local); + emit!(emitter, s.local); emitted_default = true; } ImportSpecifier::Namespace(ref ns) => { @@ -169,7 +240,7 @@ impl MacroNode for ImportDecl { formatting_space!(emitter); keyword!(emitter, "as"); space!(emitter); - emit!(ns.local); + emit!(emitter, ns.local); } } } @@ -199,7 +270,7 @@ impl MacroNode for ImportDecl { formatting_space!(emitter); } - emit!(self.src); + emit!(emitter, self.src); if let Some(with) = &self.with { formatting_space!(emitter); @@ -209,20 +280,27 @@ impl MacroNode for ImportDecl { keyword!(emitter, "with") }; formatting_space!(emitter); - emit!(with); + emit!(emitter, with); } semi!(emitter); srcmap!(emitter, self, false); - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(ImportDecl { + span: Span::new(lo, hi), + ..self.clone() + })) } } #[node_impl] impl MacroNode for ImportNamedSpecifier { fn emit(&mut self, emitter: &mut Macro) -> Result { + let lo = only_new!(emitter.wr.get_pos()); + srcmap!(emitter, self, true); if self.is_type_only { @@ -231,17 +309,22 @@ impl MacroNode for ImportNamedSpecifier { } if let Some(ref imported) = self.imported { - emit!(imported); + emit!(emitter, imported); space!(emitter); keyword!(emitter, "as"); space!(emitter); } - emit!(self.local); + emit!(emitter, self.local); srcmap!(emitter, self, false); - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(ImportNamedSpecifier { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -252,11 +335,17 @@ impl MacroNode for ExportSpecifier { ExportSpecifier::Default(..) => { unimplemented!("codegen of `export default from 'foo';`") } - ExportSpecifier::Namespace(ref node) => emit!(node), - ExportSpecifier::Named(ref node) => emit!(node), - } + ExportSpecifier::Namespace(ref node) => { + let n = emit!(emitter, node); - Ok(()) + Ok(only_new!(ExportSpecifier::Namespace(n))) + } + ExportSpecifier::Named(ref node) => { + let n = emit!(emitter, node); + + Ok(only_new!(ExportSpecifier::Named(n))) + } + } } } @@ -265,17 +354,24 @@ impl MacroNode for ExportNamespaceSpecifier { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + srcmap!(emitter, self, true); punct!(emitter, "*"); formatting_space!(emitter); keyword!(emitter, "as"); space!(emitter); - emit!(self.name); + emit!(emitter, self.name); srcmap!(emitter, self, false); - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(ExportNamespaceSpecifier { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -284,6 +380,8 @@ impl MacroNode for ExportNamedSpecifier { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + srcmap!(emitter, self, true); if self.is_type_only { @@ -292,17 +390,22 @@ impl MacroNode for ExportNamedSpecifier { } if let Some(exported) = &self.exported { - emit!(self.orig); + emit!(emitter, self.orig); space!(emitter); keyword!(emitter, "as"); space!(emitter); - emit!(exported); + emit!(emitter, exported); } else { - emit!(self.orig); + emit!(emitter, self.orig); } srcmap!(emitter, self, false); - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(ExportNamedSpecifier { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -311,6 +414,8 @@ impl MacroNode for NamedExport { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + srcmap!(emitter, self, true); struct Specifiers<'a> { @@ -357,7 +462,7 @@ impl MacroNode for NamedExport { formatting_space!(emitter); if let Some(spec) = namespace_spec { - emit!(spec); + emit!(emitter, spec); if has_named_specs { punct!(emitter, ","); formatting_space!(emitter); @@ -381,7 +486,7 @@ impl MacroNode for NamedExport { } keyword!(emitter, "from"); formatting_space!(emitter); - emit!(src); + emit!(emitter, src); if let Some(with) = &self.with { formatting_space!(emitter); @@ -391,14 +496,19 @@ impl MacroNode for NamedExport { keyword!(emitter, "with") }; formatting_space!(emitter); - emit!(with); + emit!(emitter, with); } } semi!(emitter); srcmap!(emitter, self, false); - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(NamedExport { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -407,6 +517,8 @@ impl MacroNode for ExportAll { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + srcmap!(emitter, self, true); keyword!(emitter, "export"); @@ -423,7 +535,7 @@ impl MacroNode for ExportAll { formatting_space!(emitter); keyword!(emitter, "from"); formatting_space!(emitter); - emit!(self.src); + emit!(emitter, self.src); if let Some(with) = &self.with { formatting_space!(emitter); @@ -433,13 +545,18 @@ impl MacroNode for ExportAll { keyword!(emitter, "with") }; formatting_space!(emitter); - emit!(with); + emit!(emitter, with); } semi!(emitter); srcmap!(emitter, self, false); - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(ExportAll { + span: Span::new(lo, hi), + ..self.clone() + })) } } diff --git a/crates/swc_ecma_codegen/src/object.rs b/crates/swc_ecma_codegen/src/object.rs index c329826a5cec..0031f7a8560d 100644 --- a/crates/swc_ecma_codegen/src/object.rs +++ b/crates/swc_ecma_codegen/src/object.rs @@ -1,4 +1,4 @@ -use swc_common::{Spanned, DUMMY_SP}; +use swc_common::{Span, Spanned, DUMMY_SP}; use swc_ecma_ast::*; use swc_ecma_codegen_macros::node_impl; @@ -9,6 +9,8 @@ impl MacroNode for ObjectLit { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + srcmap!(emitter, self, true); punct!(emitter, "{"); @@ -36,7 +38,12 @@ impl MacroNode for ObjectLit { srcmap!(emitter, self, false, true); punct!(emitter, "}"); - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(ObjectLit { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -44,15 +51,37 @@ impl MacroNode for ObjectLit { impl MacroNode for Prop { fn emit(&mut self, emitter: &mut Macro) -> Result { match self { - Prop::Shorthand(ref n) => emit!(n), - Prop::KeyValue(ref n) => emit!(n), - Prop::Assign(ref n) => emit!(n), - Prop::Getter(ref n) => emit!(n), - Prop::Setter(ref n) => emit!(n), - Prop::Method(ref n) => emit!(n), - } + Prop::Shorthand(ref n) => { + let n = emit!(emitter, n); + + Ok(only_new!(Prop::Shorthand(n))) + } + Prop::KeyValue(ref n) => { + let n = emit!(emitter, n); - Ok(()) + Ok(only_new!(Prop::KeyValue(n))) + } + Prop::Assign(ref n) => { + let n = emit!(emitter, n); + + Ok(only_new!(Prop::Assign(n))) + } + Prop::Getter(ref n) => { + let n = emit!(emitter, n); + + Ok(only_new!(Prop::Getter(n))) + } + Prop::Setter(ref n) => { + let n = emit!(emitter, n); + + Ok(only_new!(Prop::Setter(n))) + } + Prop::Method(ref n) => { + let n = emit!(emitter, n); + + Ok(only_new!(Prop::Method(n))) + } + } } } @@ -60,12 +89,13 @@ impl MacroNode for Prop { impl MacroNode for KeyValueProp { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let key_span = self.key.span(); let value_span = self.value.span(); if !key_span.is_dummy() { emitter.wr.add_srcmap(key_span.lo)?; } - emit!(self.key); + emit!(emitter, self.key); if !key_span.is_dummy() && value_span.is_dummy() { emitter.wr.add_srcmap(key_span.hi)?; } @@ -74,9 +104,9 @@ impl MacroNode for KeyValueProp { if key_span.is_dummy() && !value_span.is_dummy() { emitter.wr.add_srcmap(value_span.lo)?; } - emit!(self.value); + emit!(emitter, self.value); - Ok(()) + Ok(only_new!(KeyValueProp { ..self.clone() })) } } @@ -85,13 +115,20 @@ impl MacroNode for AssignProp { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + srcmap!(emitter, self, true); - emit!(self.key); + emit!(emitter, self.key); punct!(emitter, "="); - emit!(self.value); + emit!(emitter, self.value); - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(AssignProp { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -100,6 +137,8 @@ impl MacroNode for GetterProp { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + srcmap!(emitter, self, true); keyword!(emitter, "get"); @@ -113,14 +152,19 @@ impl MacroNode for GetterProp { } else { formatting_space!(emitter); } - emit!(self.key); + emit!(emitter, self.key); formatting_space!(emitter); punct!(emitter, "("); punct!(emitter, ")"); formatting_space!(emitter); - emit!(self.body); + emit!(emitter, self.body); - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(GetterProp { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -129,6 +173,8 @@ impl MacroNode for SetterProp { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + srcmap!(emitter, self, true); keyword!(emitter, "set"); @@ -144,24 +190,29 @@ impl MacroNode for SetterProp { formatting_space!(emitter); } - emit!(self.key); + emit!(emitter, self.key); formatting_space!(emitter); punct!(emitter, "("); if let Some(this) = &self.this_param { - emit!(this); + emit!(emitter, this); punct!(emitter, ","); formatting_space!(emitter); } - emit!(self.param); + emit!(emitter, self.param); punct!(emitter, ")"); - emit!(self.body); + emit!(emitter, self.body); + + let hi = only_new!(emitter.wr.get_pos()); - Ok(()) + Ok(only_new!(SetterProp { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -170,6 +221,8 @@ impl MacroNode for MethodProp { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + srcmap!(emitter, self, true); if self.function.is_async { @@ -181,12 +234,20 @@ impl MacroNode for MethodProp { punct!(emitter, "*"); } - emit!(self.key); + emit!(emitter, self.key); formatting_space!(emitter); // TODO emitter.emit_fn_trailing(&self.function)?; - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(MethodProp { + function: Box::new(Function { + span: Span::new(lo, hi), + ..*self.function.clone() + }), + ..self.clone() + })) } } @@ -198,6 +259,9 @@ impl MacroNode for PropName { // TODO: Use write_symbol when ident is a symbol. emitter.emit_leading_comments_of_span(ident.span, false)?; + let target = emitter.cfg.target; + let lo = only_new!(emitter.wr.get_pos()); + // Source map emitter.wr.commit_pending_semi()?; @@ -207,7 +271,7 @@ impl MacroNode for PropName { if emitter.wr.can_ignore_invalid_unicodes() { emitter.wr.write_symbol( DUMMY_SP, - &crate::get_ascii_only_ident(&ident.sym, true, emitter.cfg.target), + &crate::get_ascii_only_ident(&ident.sym, true, target), )?; } else { emitter.wr.write_symbol( @@ -215,21 +279,42 @@ impl MacroNode for PropName { &crate::get_ascii_only_ident( &crate::handle_invalid_unicodes(&ident.sym), true, - emitter.cfg.target, + target, ), )?; } } else { - emit!(ident); + emit!(emitter, ident); } + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(PropName::Ident(IdentName { + span: Span::new(lo, hi), + ..ident.clone() + }))) } - PropName::Str(ref n) => emit!(n), - PropName::Num(ref n) => emit!(n), - PropName::BigInt(ref n) => emit!(n), - PropName::Computed(ref n) => emit!(n), - } + PropName::Str(ref n) => { + let n = emit!(emitter, n); - Ok(()) + Ok(only_new!(PropName::Str(n))) + } + PropName::Num(ref n) => { + let n = emit!(emitter, n); + + Ok(only_new!(PropName::Num(n))) + } + PropName::BigInt(ref n) => { + let n = emit!(emitter, n); + + Ok(only_new!(PropName::BigInt(n))) + } + PropName::Computed(ref n) => { + let n = emit!(emitter, n); + + Ok(only_new!(PropName::Computed(n))) + } + } } } @@ -238,12 +323,19 @@ impl MacroNode for ComputedPropName { fn emit(&mut self, emitter: &mut Macro) -> Result { srcmap!(emitter, self, true); + let lo = only_new!(emitter.wr.get_pos()); + punct!(emitter, "["); - emit!(self.expr); + emit!(emitter, self.expr); punct!(emitter, "]"); srcmap!(emitter, self, false); - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(ComputedPropName { + span: Span::new(lo, hi), + ..self.clone() + })) } } diff --git a/crates/swc_ecma_codegen/src/pat.rs b/crates/swc_ecma_codegen/src/pat.rs index 5e2165e1c9b1..b7cb9ed07a1c 100644 --- a/crates/swc_ecma_codegen/src/pat.rs +++ b/crates/swc_ecma_codegen/src/pat.rs @@ -1,4 +1,4 @@ -use swc_common::Spanned; +use swc_common::{Span, Spanned}; use swc_ecma_ast::*; use swc_ecma_codegen_macros::node_impl; @@ -7,36 +7,71 @@ impl MacroNode for Param { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + srcmap!(emitter, self, true); emitter.emit_list(self.span, Some(&self.decorators), ListFormat::Decorators)?; - emit!(self.pat); + emit!(emitter, self.pat); srcmap!(emitter, self, false); - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(Param { + span: Span::new(lo, hi), + ..self.clone() + })) } } #[node_impl] impl MacroNode for Pat { fn emit(&mut self, emitter: &mut Macro) -> Result { - match self { - Pat::Array(ref n) => emit!(n), - Pat::Assign(ref n) => emit!(n), - Pat::Expr(ref n) => emit!(n), - Pat::Ident(ref n) => emit!(n), - Pat::Object(ref n) => emit!(n), - Pat::Rest(ref n) => emit!(n), - Pat::Invalid(n) => emit!(n), - } + let result = match self { + Pat::Array(ref n) => { + let n = emit!(emitter, n); + + only_new!(Pat::Array(n)) + } + Pat::Assign(ref n) => { + let n = emit!(emitter, n); + + only_new!(Pat::Assign(n)) + } + Pat::Expr(ref n) => { + let n = emit!(emitter, n); + + only_new!(Pat::Expr(n)) + } + Pat::Ident(ref n) => { + let n = emit!(emitter, n); + + only_new!(Pat::Ident(n)) + } + Pat::Object(ref n) => { + let n = emit!(emitter, n); + + only_new!(Pat::Object(n)) + } + Pat::Rest(ref n) => { + let n = emit!(emitter, n); + + only_new!(Pat::Rest(n)) + } + Pat::Invalid(n) => { + let n = emit!(emitter, n); + + only_new!(Pat::Invalid(n)) + } + }; if emitter.comments.is_some() { emitter.emit_trailing_comments_of_pos(self.span().hi, true, true)?; } - Ok(()) + Ok(result) } } @@ -45,28 +80,41 @@ impl MacroNode for RestPat { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + punct!(emitter, self.dot3_token, "..."); - emit!(self.arg); + emit!(emitter, self.arg); if let Some(type_ann) = &self.type_ann { punct!(emitter, ":"); formatting_space!(emitter); - emit!(type_ann); + emit!(emitter, type_ann); } - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(RestPat { + span: Span::new(lo, hi), + ..self.clone() + })) } } #[node_impl] impl MacroNode for PropOrSpread { fn emit(&mut self, emitter: &mut Macro) -> Result { - match self { - PropOrSpread::Prop(ref n) => emit!(n), - PropOrSpread::Spread(ref n) => emit!(n), - } - - Ok(()) + Ok(match self { + PropOrSpread::Prop(ref n) => { + let n = emit!(emitter, n); + + only_new!(PropOrSpread::Prop(n)) + } + PropOrSpread::Spread(ref n) => { + let n = emit!(emitter, n); + + only_new!(PropOrSpread::Spread(n)) + } + }) } } @@ -80,57 +128,115 @@ impl MacroNode for SpreadElement { srcmap!(emitter, self, true); punct!(emitter, "..."); - emit!(self.expr); + emit!(emitter, self.expr); srcmap!(emitter, self, false); - Ok(()) + Ok(only_new!(SpreadElement { ..self.clone() })) } } #[node_impl] impl MacroNode for AssignTarget { fn emit(&mut self, emitter: &mut Macro) -> Result { - match self { - AssignTarget::Simple(ref n) => emit!(n), - AssignTarget::Pat(ref n) => emit!(n), - } - - Ok(()) + Ok(match self { + AssignTarget::Simple(ref n) => { + let n = emit!(emitter, n); + + only_new!(AssignTarget::Simple(n)) + } + AssignTarget::Pat(ref n) => { + let n = emit!(emitter, n); + + only_new!(AssignTarget::Pat(n)) + } + }) } } #[node_impl] impl MacroNode for SimpleAssignTarget { fn emit(&mut self, emitter: &mut Macro) -> Result { - match self { - SimpleAssignTarget::Ident(n) => emit!(n), - SimpleAssignTarget::Member(n) => emit!(n), - SimpleAssignTarget::Invalid(n) => emit!(n), - SimpleAssignTarget::SuperProp(n) => emit!(n), - SimpleAssignTarget::Paren(n) => emit!(n), - SimpleAssignTarget::OptChain(n) => emit!(n), - SimpleAssignTarget::TsAs(n) => emit!(n), - SimpleAssignTarget::TsNonNull(n) => emit!(n), - SimpleAssignTarget::TsSatisfies(n) => emit!(n), - SimpleAssignTarget::TsTypeAssertion(n) => emit!(n), - SimpleAssignTarget::TsInstantiation(n) => emit!(n), - } - - Ok(()) + Ok(match self { + SimpleAssignTarget::Ident(n) => { + let n = emit!(emitter, n); + + only_new!(SimpleAssignTarget::Ident(n)) + } + SimpleAssignTarget::Member(n) => { + let n = emit!(emitter, n); + + only_new!(SimpleAssignTarget::Member(n)) + } + SimpleAssignTarget::Invalid(n) => { + let n = emit!(emitter, n); + + only_new!(SimpleAssignTarget::Invalid(n)) + } + SimpleAssignTarget::SuperProp(n) => { + let n = emit!(emitter, n); + + only_new!(SimpleAssignTarget::SuperProp(n)) + } + SimpleAssignTarget::Paren(n) => { + let n = emit!(emitter, n); + + only_new!(SimpleAssignTarget::Paren(n)) + } + SimpleAssignTarget::OptChain(n) => { + let n = emit!(emitter, n); + + only_new!(SimpleAssignTarget::OptChain(n)) + } + SimpleAssignTarget::TsAs(n) => { + let n = emit!(emitter, n); + + only_new!(SimpleAssignTarget::TsAs(n)) + } + SimpleAssignTarget::TsTypeAssertion(n) => { + let n = emit!(emitter, n); + + only_new!(SimpleAssignTarget::TsTypeAssertion(n)) + } + SimpleAssignTarget::TsInstantiation(n) => { + let n = emit!(emitter, n); + + only_new!(SimpleAssignTarget::TsInstantiation(n)) + } + SimpleAssignTarget::TsNonNull(n) => { + let n = emit!(emitter, n); + + only_new!(SimpleAssignTarget::TsNonNull(n)) + } + SimpleAssignTarget::TsSatisfies(n) => { + let n = emit!(emitter, n); + + only_new!(SimpleAssignTarget::TsSatisfies(n)) + } + }) } } #[node_impl] impl MacroNode for AssignTargetPat { fn emit(&mut self, emitter: &mut Macro) -> Result { - match self { - AssignTargetPat::Array(n) => emit!(n), - AssignTargetPat::Object(n) => emit!(n), - AssignTargetPat::Invalid(n) => emit!(n), - } - - Ok(()) + Ok(match self { + AssignTargetPat::Array(n) => { + let n = emit!(emitter, n); + + only_new!(AssignTargetPat::Array(n)) + } + AssignTargetPat::Object(n) => { + let n = emit!(emitter, n); + + only_new!(AssignTargetPat::Object(n)) + } + AssignTargetPat::Invalid(n) => { + let n = emit!(emitter, n); + + only_new!(AssignTargetPat::Invalid(n)) + } + }) } } @@ -139,6 +245,8 @@ impl MacroNode for ArrayPat { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + srcmap!(emitter, self, true); punct!(emitter, "["); @@ -158,12 +266,17 @@ impl MacroNode for ArrayPat { if let Some(type_ann) = &self.type_ann { punct!(emitter, ":"); space!(emitter); - emit!(type_ann); + emit!(emitter, type_ann); } srcmap!(emitter, self, false); - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(ArrayPat { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -172,17 +285,24 @@ impl MacroNode for AssignPat { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + srcmap!(emitter, self, true); - emit!(self.left); + emit!(emitter, self.left); formatting_space!(emitter); punct!(emitter, "="); formatting_space!(emitter); - emit!(self.right); + emit!(emitter, self.right); srcmap!(emitter, self, false); - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(AssignPat { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -191,6 +311,8 @@ impl MacroNode for ObjectPat { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + srcmap!(emitter, self, true); punct!(emitter, "{"); @@ -209,25 +331,40 @@ impl MacroNode for ObjectPat { if let Some(type_ann) = &self.type_ann { punct!(emitter, ":"); space!(emitter); - emit!(type_ann); + emit!(emitter, type_ann); } srcmap!(emitter, self, false); - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(ObjectPat { + span: Span::new(lo, hi), + ..self.clone() + })) } } #[node_impl] impl MacroNode for ObjectPatProp { fn emit(&mut self, emitter: &mut Macro) -> Result { - match self { - ObjectPatProp::KeyValue(ref node) => emit!(node), - ObjectPatProp::Assign(ref node) => emit!(node), - ObjectPatProp::Rest(ref node) => emit!(node), - } - - Ok(()) + Ok(match self { + ObjectPatProp::KeyValue(ref node) => { + let n = emit!(emitter, node); + + only_new!(ObjectPatProp::KeyValue(n)) + } + ObjectPatProp::Assign(ref node) => { + let n = emit!(emitter, node); + + only_new!(ObjectPatProp::Assign(n)) + } + ObjectPatProp::Rest(ref node) => { + let n = emit!(emitter, node); + + only_new!(ObjectPatProp::Rest(n)) + } + }) } } @@ -238,14 +375,14 @@ impl MacroNode for KeyValuePatProp { srcmap!(emitter, self, true); - emit!(self.key); + emit!(emitter, self.key); punct!(emitter, ":"); formatting_space!(emitter); - emit!(self.value); + emit!(emitter, self.value); srcmap!(emitter, self, false); - Ok(()) + Ok(only_new!(KeyValuePatProp { ..self.clone() })) } } @@ -254,31 +391,48 @@ impl MacroNode for AssignPatProp { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + srcmap!(emitter, self, true); - emit!(self.key); + emit!(emitter, self.key); if let Some(value) = &self.value { formatting_space!(emitter); punct!(emitter, "="); formatting_space!(emitter); - emit!(value); + emit!(emitter, value); } srcmap!(emitter, self, false); - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(AssignPatProp { + span: Span::new(lo, hi), + ..self.clone() + })) } } #[node_impl] impl MacroNode for ForHead { fn emit(&mut self, emitter: &mut Macro) -> Result { - match self { - ForHead::Pat(n) => emit!(n), - ForHead::VarDecl(n) => emit!(n), - ForHead::UsingDecl(n) => emit!(n), - } - - Ok(()) + Ok(match self { + ForHead::Pat(n) => { + let n = emit!(emitter, n); + + only_new!(ForHead::Pat(n)) + } + ForHead::VarDecl(n) => { + let n = emit!(emitter, n); + + only_new!(ForHead::VarDecl(n)) + } + ForHead::UsingDecl(n) => { + let n = emit!(emitter, n); + + only_new!(ForHead::UsingDecl(n)) + } + }) } } diff --git a/crates/swc_ecma_codegen/src/stmt.rs b/crates/swc_ecma_codegen/src/stmt.rs index 91b8b094ee98..e0643efc1a6b 100644 --- a/crates/swc_ecma_codegen/src/stmt.rs +++ b/crates/swc_ecma_codegen/src/stmt.rs @@ -1,4 +1,4 @@ -use swc_common::Spanned; +use swc_common::{Span, Spanned}; use swc_ecma_ast::*; use swc_ecma_codegen_macros::node_impl; @@ -7,38 +7,94 @@ use crate::util::{EndsWithAlphaNum, StartsWithAlphaNum}; #[node_impl] impl MacroNode for Stmt { fn emit(&mut self, emitter: &mut Macro) -> Result { - match self { - Stmt::Expr(ref e) => emit!(e), + let result = match self { + Stmt::Expr(ref e) => { + let n = emit!(emitter, e); + Ok(only_new!(Stmt::Expr(n))) + } Stmt::Block(ref e) => { - emit!(e); - return Ok(()); - } - Stmt::Empty(ref e) => emit!(e), - Stmt::Debugger(ref e) => emit!(e), - Stmt::With(ref e) => emit!(e), - Stmt::Return(ref e) => emit!(e), - Stmt::Labeled(ref e) => emit!(e), - Stmt::Break(ref e) => emit!(e), - Stmt::Continue(ref e) => emit!(e), - Stmt::If(ref e) => emit!(e), - Stmt::Switch(ref e) => emit!(e), - Stmt::Throw(ref e) => emit!(e), - Stmt::Try(ref e) => emit!(e), - Stmt::While(ref e) => emit!(e), - Stmt::DoWhile(ref e) => emit!(e), - Stmt::For(ref e) => emit!(e), - Stmt::ForIn(ref e) => emit!(e), - Stmt::ForOf(ref e) => emit!(e), + let stmt = emit!(emitter, e); + return Ok(only_new!(Stmt::Block(stmt))); + } + Stmt::Empty(ref e) => { + let stmt = emit!(emitter, e); + Ok(only_new!(Stmt::Empty(stmt))) + } + Stmt::Debugger(ref e) => { + let stmt = emit!(emitter, e); + Ok(only_new!(Stmt::Debugger(stmt))) + } + Stmt::With(ref e) => { + let stmt = emit!(emitter, e); + Ok(only_new!(Stmt::With(stmt))) + } + Stmt::Return(ref e) => { + let stmt = emit!(emitter, e); + Ok(only_new!(Stmt::Return(stmt))) + } + Stmt::Labeled(ref e) => { + let stmt = emit!(emitter, e); + Ok(only_new!(Stmt::Labeled(stmt))) + } + Stmt::Break(ref e) => { + let stmt = emit!(emitter, e); + Ok(only_new!(Stmt::Break(stmt))) + } + Stmt::Continue(ref e) => { + let stmt = emit!(emitter, e); + Ok(only_new!(Stmt::Continue(stmt))) + } + Stmt::If(ref e) => { + let stmt = emit!(emitter, e); + Ok(only_new!(Stmt::If(stmt))) + } + Stmt::Switch(ref e) => { + let stmt = emit!(emitter, e); + Ok(only_new!(Stmt::Switch(stmt))) + } + Stmt::Throw(ref e) => { + let stmt = emit!(emitter, e); + Ok(only_new!(Stmt::Throw(stmt))) + } + Stmt::Try(ref e) => { + let stmt = emit!(emitter, e); + Ok(only_new!(Stmt::Try(stmt))) + } + Stmt::While(ref e) => { + let stmt = emit!(emitter, e); + Ok(only_new!(Stmt::While(stmt))) + } + Stmt::DoWhile(ref e) => { + let stmt = emit!(emitter, e); + Ok(only_new!(Stmt::DoWhile(stmt))) + } + Stmt::For(ref e) => { + let stmt = emit!(emitter, e); + Ok(only_new!(Stmt::For(stmt))) + } + Stmt::ForIn(ref e) => { + let stmt = emit!(emitter, e); + Ok(only_new!(Stmt::ForIn(stmt))) + } + Stmt::ForOf(ref e) => { + let stmt = emit!(emitter, e); + Ok(only_new!(Stmt::ForOf(stmt))) + } Stmt::Decl(Decl::Var(e)) => { - emit!(e); + let stmt = emit!(emitter, e); semi!(emitter); + Ok(only_new!(Stmt::Decl(Decl::Var(stmt)))) } Stmt::Decl(e @ Decl::Using(..)) => { - emit!(e); + let stmt = emit!(emitter, e); semi!(emitter); + Ok(only_new!(Stmt::Decl(stmt))) } - Stmt::Decl(ref e) => emit!(e), - } + Stmt::Decl(ref e) => { + let stmt = emit!(emitter, e); + Ok(only_new!(Stmt::Decl(stmt))) + } + }; if emitter.comments.is_some() { emitter.emit_trailing_comments_of_pos(self.span().hi(), true, true)?; } @@ -47,7 +103,7 @@ impl MacroNode for Stmt { emitter.wr.write_line()?; } - Ok(()) + result } } @@ -56,18 +112,31 @@ impl MacroNode for EmptyStmt { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + emitter.wr.write_punct(None, ";")?; - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(EmptyStmt { + span: Span::new(lo, hi), + })) } } #[node_impl] impl MacroNode for BlockStmt { fn emit(&mut self, emitter: &mut Macro) -> Result { + let lo = only_new!(emitter.wr.get_pos()); + emitter.emit_block_stmt_inner(self, false)?; - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(BlockStmt { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -76,11 +145,18 @@ impl MacroNode for ExprStmt { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span, false)?; - emit!(self.expr); + let lo = only_new!(emitter.wr.get_pos()); + + let expr = emit!(emitter, self.expr); semi!(emitter); - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(ExprStmt { + span: Span::new(lo, hi), + expr, + })) } } @@ -89,12 +165,18 @@ impl MacroNode for DebuggerStmt { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.wr.commit_pending_semi()?; + let lo = only_new!(emitter.wr.get_pos()); + emitter.emit_leading_comments_of_span(self.span(), false)?; keyword!(emitter, self.span, "debugger"); semi!(emitter); - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(DebuggerStmt { + span: Span::new(lo, hi), + })) } } @@ -103,18 +185,25 @@ impl MacroNode for WithStmt { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.wr.commit_pending_semi()?; + let lo = only_new!(emitter.wr.get_pos()); + srcmap!(emitter, self, true); keyword!(emitter, "with"); formatting_space!(emitter); punct!(emitter, "("); - emit!(self.obj); + emit!(emitter, self.obj); punct!(emitter, ")"); - emit!(self.body); + emit!(emitter, self.body); + + let hi = only_new!(emitter.wr.get_pos()); - Ok(()) + Ok(only_new!(WithStmt { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -125,6 +214,8 @@ impl MacroNode for ReturnStmt { emitter.emit_leading_comments_of_span(self.span, false)?; + let lo = only_new!(emitter.wr.get_pos()); + srcmap!(emitter, self, true); keyword!(emitter, "return"); @@ -143,7 +234,7 @@ impl MacroNode for ReturnStmt { formatting_space!(emitter); } - emit!(arg); + emit!(emitter, arg); if need_paren { punct!(emitter, ")"); } @@ -151,7 +242,12 @@ impl MacroNode for ReturnStmt { semi!(emitter); - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(ReturnStmt { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -160,15 +256,22 @@ impl MacroNode for LabeledStmt { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.wr.commit_pending_semi()?; - emit!(self.label); + let lo = only_new!(emitter.wr.get_pos()); + + emit!(emitter, self.label); // TODO: Comment punct!(emitter, ":"); formatting_space!(emitter); - emit!(self.body); + emit!(emitter, self.body); + + let hi = only_new!(emitter.wr.get_pos()); - Ok(()) + Ok(only_new!(LabeledStmt { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -179,12 +282,14 @@ impl MacroNode for SwitchStmt { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + srcmap!(emitter, self, true); keyword!(emitter, "switch"); punct!(emitter, "("); - emit!(self.discriminant); + emit!(emitter, self.discriminant); punct!(emitter, ")"); punct!(emitter, "{"); @@ -193,7 +298,12 @@ impl MacroNode for SwitchStmt { srcmap!(emitter, self, false, true); punct!(emitter, "}"); - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(SwitchStmt { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -202,6 +312,8 @@ impl MacroNode for CatchClause { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + srcmap!(emitter, self, true); keyword!(emitter, "catch"); @@ -210,15 +322,20 @@ impl MacroNode for CatchClause { if let Some(param) = &self.param { punct!(emitter, "("); - emit!(param); + emit!(emitter, param); punct!(emitter, ")"); } formatting_space!(emitter); - emit!(self.body); + emit!(emitter, self.body); - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(CatchClause { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -227,6 +344,8 @@ impl MacroNode for SwitchCase { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + srcmap!(emitter, self, true); if let Some(ref test) = self.test { @@ -240,7 +359,7 @@ impl MacroNode for SwitchCase { formatting_space!(emitter); } - emit!(test); + emit!(emitter, test); } else { keyword!(emitter, "default"); } @@ -264,7 +383,12 @@ impl MacroNode for SwitchCase { } emitter.emit_list(self.span(), Some(&self.cons), format)?; - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(SwitchCase { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -273,6 +397,8 @@ impl MacroNode for ThrowStmt { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + srcmap!(emitter, self, true); keyword!(emitter, "throw"); @@ -287,14 +413,19 @@ impl MacroNode for ThrowStmt { formatting_space!(emitter); } - emit!(self.arg); + emit!(emitter, self.arg); if need_paren { punct!(emitter, ")"); } } semi!(emitter); - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(ThrowStmt { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -305,26 +436,33 @@ impl MacroNode for TryStmt { emitter.wr.commit_pending_semi()?; + let lo = only_new!(emitter.wr.get_pos()); + srcmap!(emitter, self, true); keyword!(emitter, "try"); formatting_space!(emitter); - emit!(self.block); + emit!(emitter, self.block); if let Some(ref catch) = self.handler { formatting_space!(emitter); - emit!(catch); + emit!(emitter, catch); } if let Some(ref finally) = self.finalizer { formatting_space!(emitter); keyword!(emitter, "finally"); // space!(emitter); - emit!(finally); + emit!(emitter, finally); } - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(TryStmt { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -335,17 +473,24 @@ impl MacroNode for WhileStmt { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + srcmap!(emitter, self, true); keyword!(emitter, "while"); punct!(emitter, "("); - emit!(self.test); + emit!(emitter, self.test); punct!(emitter, ")"); - emit!(self.body); + emit!(emitter, self.body); + + let hi = only_new!(emitter.wr.get_pos()); - Ok(()) + Ok(only_new!(WhileStmt { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -356,6 +501,8 @@ impl MacroNode for DoWhileStmt { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + srcmap!(emitter, self, true); keyword!(emitter, "do"); @@ -364,14 +511,14 @@ impl MacroNode for DoWhileStmt { } else { formatting_space!(emitter) } - emit!(self.body); + emit!(emitter, self.body); keyword!(emitter, "while"); formatting_space!(emitter); punct!(emitter, "("); - emit!(self.test); + emit!(emitter, self.test); punct!(emitter, ")"); if emitter.cfg.target <= EsVersion::Es5 { @@ -380,7 +527,12 @@ impl MacroNode for DoWhileStmt { srcmap!(emitter, self, false); - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(DoWhileStmt { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -391,6 +543,8 @@ impl MacroNode for ForStmt { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + srcmap!(emitter, self, true); keyword!(emitter, "for"); @@ -403,9 +557,14 @@ impl MacroNode for ForStmt { opt_leading_space!(emitter, self.update); punct!(emitter, ")"); - emit!(self.body); + emit!(emitter, self.body); + + let hi = only_new!(emitter.wr.get_pos()); - Ok(()) + Ok(only_new!(ForStmt { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -418,10 +577,12 @@ impl MacroNode for ForInStmt { srcmap!(emitter, self, true); + let lo = only_new!(emitter.wr.get_pos()); + keyword!(emitter, "for"); punct!(emitter, "("); - emit!(self.left); + emit!(emitter, self.left); if self.left.ends_with_alpha_num() { space!(emitter); @@ -438,14 +599,19 @@ impl MacroNode for ForInStmt { } else { formatting_space!(emitter) } - emit!(self.right); + emit!(emitter, self.right); } punct!(emitter, ")"); - emit!(self.body); + emit!(emitter, self.body); + + let hi = only_new!(emitter.wr.get_pos()); - Ok(()) + Ok(only_new!(ForInStmt { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -456,6 +622,8 @@ impl MacroNode for ForOfStmt { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + srcmap!(emitter, self, true); keyword!(emitter, "for"); @@ -466,7 +634,7 @@ impl MacroNode for ForOfStmt { } formatting_space!(emitter); punct!(emitter, "("); - emit!(self.left); + emit!(emitter, self.left); if self.left.ends_with_alpha_num() { space!(emitter); } else { @@ -482,12 +650,17 @@ impl MacroNode for ForOfStmt { } else { formatting_space!(emitter) } - emit!(self.right); + emit!(emitter, self.right); } punct!(emitter, ")"); - emit!(self.body); + emit!(emitter, self.body); + + let hi = only_new!(emitter.wr.get_pos()); - Ok(()) + Ok(only_new!(ForOfStmt { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -496,18 +669,25 @@ impl MacroNode for BreakStmt { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.wr.commit_pending_semi()?; + let lo = only_new!(emitter.wr.get_pos()); + srcmap!(emitter, self, true); keyword!(emitter, "break"); if let Some(ref label) = self.label { space!(emitter); - emit!(label); + emit!(emitter, label); } semi!(emitter); - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(BreakStmt { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -516,18 +696,25 @@ impl MacroNode for ContinueStmt { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.wr.commit_pending_semi()?; + let lo = only_new!(emitter.wr.get_pos()); + srcmap!(emitter, self, true); keyword!(emitter, "continue"); if let Some(ref label) = self.label { space!(emitter); - emit!(label); + emit!(emitter, label); } semi!(emitter); - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(ContinueStmt { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -538,13 +725,15 @@ impl MacroNode for IfStmt { emitter.wr.commit_pending_semi()?; + let lo = only_new!(emitter.wr.get_pos()); + srcmap!(emitter, self, true); keyword!(emitter, "if"); formatting_space!(emitter); punct!(emitter, "("); - emit!(self.test); + emit!(emitter, self.test); punct!(emitter, ")"); formatting_space!(emitter); @@ -553,7 +742,7 @@ impl MacroNode for IfStmt { _ => false, }; - emit!(self.cons); + emit!(emitter, self.cons); if let Some(ref alt) = self.alt { if is_cons_block { @@ -565,10 +754,15 @@ impl MacroNode for IfStmt { } else { formatting_space!(emitter); } - emit!(alt); + emit!(emitter, alt); } - Ok(()) + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(IfStmt { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -576,11 +770,16 @@ impl MacroNode for IfStmt { impl MacroNode for ModuleExportName { fn emit(&mut self, emitter: &mut Macro) -> Result { match self { - ModuleExportName::Ident(ident) => emit!(ident), - ModuleExportName::Str(s) => emit!(s), - } + ModuleExportName::Ident(ident) => { + let n = emit!(emitter, ident); - Ok(()) + Ok(only_new!(ModuleExportName::Ident(n))) + } + ModuleExportName::Str(s) => { + let n = emit!(emitter, s); + Ok(only_new!(ModuleExportName::Str(n))) + } + } } } @@ -588,11 +787,17 @@ impl MacroNode for ModuleExportName { impl MacroNode for VarDeclOrExpr { fn emit(&mut self, emitter: &mut Macro) -> Result { match self { - VarDeclOrExpr::Expr(node) => emit!(node), - VarDeclOrExpr::VarDecl(node) => emit!(node), - } + VarDeclOrExpr::Expr(node) => { + let n = emit!(emitter, node); - Ok(()) + Ok(only_new!(VarDeclOrExpr::Expr(n))) + } + VarDeclOrExpr::VarDecl(node) => { + let n = emit!(emitter, node); + + Ok(only_new!(VarDeclOrExpr::VarDecl(n))) + } + } } } diff --git a/crates/swc_ecma_codegen/src/text_writer.rs b/crates/swc_ecma_codegen/src/text_writer.rs index bc119963d9e1..9ab428e296e8 100644 --- a/crates/swc_ecma_codegen/src/text_writer.rs +++ b/crates/swc_ecma_codegen/src/text_writer.rs @@ -50,6 +50,10 @@ pub trait WriteJs { } } +pub trait SpannedWriteJs: WriteJs { + fn get_pos(&self) -> BytePos; +} + impl WriteJs for Box where W: ?Sized + WriteJs, @@ -149,6 +153,15 @@ where } } +impl SpannedWriteJs for Box +where + W: ?Sized + SpannedWriteJs, +{ + fn get_pos(&self) -> BytePos { + (**self).get_pos() + } +} + impl WriteJs for &'_ mut W where W: ?Sized + WriteJs, @@ -248,3 +261,12 @@ where (**self).can_ignore_invalid_unicodes() } } + +impl SpannedWriteJs for &'_ mut W +where + W: ?Sized + SpannedWriteJs, +{ + fn get_pos(&self) -> BytePos { + (**self).get_pos() + } +} diff --git a/crates/swc_ecma_codegen/src/text_writer/basic_impl.rs b/crates/swc_ecma_codegen/src/text_writer/basic_impl.rs index dd8a42eb7043..38b5732f4bbf 100644 --- a/crates/swc_ecma_codegen/src/text_writer/basic_impl.rs +++ b/crates/swc_ecma_codegen/src/text_writer/basic_impl.rs @@ -4,7 +4,7 @@ use rustc_hash::FxBuildHasher; use swc_allocator::api::global::HashSet; use swc_common::{sync::Lrc, BytePos, LineCol, SourceMap, Span}; -use super::{Result, WriteJs}; +use super::{Result, SpannedWriteJs, WriteJs}; /// /// ----- @@ -18,6 +18,7 @@ pub struct JsWriter<'a, W: Write> { line_start: bool, line_count: usize, line_pos: usize, + byte_pos: BytePos, new_line: &'a str, srcmap: Option<&'a mut Vec<(BytePos, LineCol)>>, srcmap_done: HashSet<(BytePos, u32, u32), FxBuildHasher>, @@ -39,6 +40,7 @@ impl<'a, W: Write> JsWriter<'a, W> { line_start: true, line_count: 0, line_pos: Default::default(), + byte_pos: Default::default(), new_line, srcmap, wr, @@ -67,6 +69,7 @@ impl<'a, W: Write> JsWriter<'a, W> { if self.srcmap.is_some() { self.line_pos += self.indent_str.len() * self.indent; } + self.byte_pos.0 += self.indent_str.len() as u32 * self.indent as u32; Ok(()) } @@ -118,6 +121,8 @@ impl<'a, W: Write> JsWriter<'a, W> { self.line_pos += chars; } } + + self.byte_pos.0 += s.as_bytes().len() as u32; } #[inline] @@ -200,6 +205,7 @@ impl WriteJs for JsWriter<'_, W> { self.line_count += 1; self.line_pos = 0; } + self.byte_pos.0 += self.new_line.len() as u32; self.line_start = true; if let Some(pending) = pending { @@ -284,6 +290,12 @@ impl WriteJs for JsWriter<'_, W> { } } +impl SpannedWriteJs for JsWriter<'_, W> { + fn get_pos(&self) -> BytePos { + self.byte_pos + } +} + #[derive(Debug)] struct LineStart { line_count: usize, diff --git a/crates/swc_ecma_codegen/src/typescript.rs b/crates/swc_ecma_codegen/src/typescript.rs index 39757b7f87e4..a2e67f3fd8dc 100644 --- a/crates/swc_ecma_codegen/src/typescript.rs +++ b/crates/swc_ecma_codegen/src/typescript.rs @@ -1,16 +1,22 @@ -use swc_common::Spanned; +use swc_common::{Span, Spanned}; use swc_ecma_ast::*; use swc_ecma_codegen_macros::node_impl; #[node_impl] impl MacroNode for ParamOrTsParamProp { fn emit(&mut self, emitter: &mut Macro) -> Result { - match self { - ParamOrTsParamProp::Param(n) => emit!(n), - ParamOrTsParamProp::TsParamProp(n) => emit!(n), - } + Ok(match self { + ParamOrTsParamProp::Param(n) => { + let n = emit!(emitter, n); + + only_new!(ParamOrTsParamProp::Param(n)) + } + ParamOrTsParamProp::TsParamProp(n) => { + let n = emit!(emitter, n); - Ok(()) + only_new!(ParamOrTsParamProp::TsParamProp(n)) + } + }) } } @@ -19,10 +25,18 @@ impl MacroNode for TsArrayType { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; - emit!(self.elem_type); + let lo = only_new!(emitter.wr.get_pos()); + + emit!(emitter, self.elem_type); punct!(emitter, "["); punct!(emitter, "]"); - Ok(()) + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(TsArrayType { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -31,14 +45,22 @@ impl MacroNode for TsAsExpr { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; - emit!(self.expr); + let lo = only_new!(emitter.wr.get_pos()); + + emit!(emitter, self.expr); space!(emitter); keyword!(emitter, "as"); space!(emitter); - emit!(self.type_ann); - Ok(()) + emit!(emitter, self.type_ann); + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(TsAsExpr { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -47,14 +69,22 @@ impl MacroNode for TsSatisfiesExpr { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; - emit!(self.expr); + let lo = only_new!(emitter.wr.get_pos()); + + emit!(emitter, self.expr); space!(emitter); keyword!(emitter, "satisfies"); space!(emitter); - emit!(self.type_ann); - Ok(()) + emit!(emitter, self.type_ann); + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(TsSatisfiesExpr { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -63,7 +93,9 @@ impl MacroNode for TsCallSignatureDecl { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; - emit!(self.type_params); + let lo = only_new!(emitter.wr.get_pos()); + + emit!(emitter, self.type_params); punct!(emitter, "("); emitter.emit_list(self.span, Some(&self.params), ListFormat::Parameters)?; @@ -74,9 +106,15 @@ impl MacroNode for TsCallSignatureDecl { punct!(emitter, ":"); space!(emitter); - emit!(type_ann); + emit!(emitter, type_ann); } - Ok(()) + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(TsCallSignatureDecl { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -85,25 +123,33 @@ impl MacroNode for TsConditionalType { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; - emit!(self.check_type); + let lo = only_new!(emitter.wr.get_pos()); + + emit!(emitter, self.check_type); space!(emitter); keyword!(emitter, "extends"); space!(emitter); - emit!(self.extends_type); + emit!(emitter, self.extends_type); space!(emitter); punct!(emitter, "?"); space!(emitter); - emit!(self.true_type); + emit!(emitter, self.true_type); space!(emitter); punct!(emitter, ":"); space!(emitter); - emit!(self.false_type); - Ok(()) + emit!(emitter, self.false_type); + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(TsConditionalType { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -112,10 +158,12 @@ impl MacroNode for TsConstructSignatureDecl { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + keyword!(emitter, "new"); if let Some(type_params) = &self.type_params { space!(emitter); - emit!(type_params); + emit!(emitter, type_params); } punct!(emitter, "("); @@ -125,9 +173,15 @@ impl MacroNode for TsConstructSignatureDecl { if let Some(type_ann) = &self.type_ann { punct!(emitter, ":"); space!(emitter); - emit!(type_ann); + emit!(emitter, type_ann); } - Ok(()) + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(TsConstructSignatureDecl { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -136,6 +190,8 @@ impl MacroNode for TsConstructorType { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + if self.is_abstract { keyword!(emitter, "abstract"); space!(emitter); @@ -144,7 +200,7 @@ impl MacroNode for TsConstructorType { keyword!(emitter, "new"); if let Some(type_params) = &self.type_params { space!(emitter); - emit!(type_params); + emit!(emitter, type_params); } punct!(emitter, "("); @@ -155,8 +211,14 @@ impl MacroNode for TsConstructorType { punct!(emitter, "=>"); formatting_space!(emitter); - emit!(self.type_ann); - Ok(()) + emit!(emitter, self.type_ann); + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(TsConstructorType { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -165,13 +227,18 @@ impl MacroNode for TsEntityName { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; - match self { + Ok(match self { TsEntityName::TsQualifiedName(n) => { - emit!(n); + let n = emit!(emitter, n); + + only_new!(TsEntityName::TsQualifiedName(n)) } - TsEntityName::Ident(n) => emit!(n), - } - Ok(()) + TsEntityName::Ident(n) => { + let n = emit!(emitter, n); + + only_new!(TsEntityName::Ident(n)) + } + }) } } @@ -180,6 +247,8 @@ impl MacroNode for TsEnumDecl { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + if self.declare { keyword!(emitter, "declare"); space!(emitter); @@ -193,7 +262,7 @@ impl MacroNode for TsEnumDecl { keyword!(emitter, "enum"); space!(emitter); - emit!(self.id); + emit!(emitter, self.id); formatting_space!(emitter); punct!(emitter, "{"); @@ -201,7 +270,13 @@ impl MacroNode for TsEnumDecl { emitter.emit_list(self.span, Some(&self.members), ListFormat::EnumMembers)?; punct!(emitter, "}"); - Ok(()) + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(TsEnumDecl { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -210,26 +285,41 @@ impl MacroNode for TsEnumMember { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; - emit!(self.id); + let lo = only_new!(emitter.wr.get_pos()); + + emit!(emitter, self.id); if let Some(init) = &self.init { formatting_space!(emitter); punct!(emitter, "="); formatting_space!(emitter); - emit!(init); + emit!(emitter, init); } - Ok(()) + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(TsEnumMember { + span: Span::new(lo, hi), + ..self.clone() + })) } } #[node_impl] impl MacroNode for TsEnumMemberId { fn emit(&mut self, emitter: &mut Macro) -> Result { - match self { - TsEnumMemberId::Ident(n) => emit!(n), - TsEnumMemberId::Str(n) => emit!(n), - } - Ok(()) + Ok(match self { + TsEnumMemberId::Ident(n) => { + let n = emit!(emitter, n); + + only_new!(TsEnumMemberId::Ident(n)) + } + TsEnumMemberId::Str(n) => { + let n = emit!(emitter, n); + + only_new!(TsEnumMemberId::Str(n)) + } + }) } } @@ -238,12 +328,20 @@ impl MacroNode for TsExportAssignment { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + keyword!(emitter, "export"); formatting_space!(emitter); punct!(emitter, "="); formatting_space!(emitter); - emit!(self.expr); - Ok(()) + emit!(emitter, self.expr); + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(TsExportAssignment { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -252,10 +350,18 @@ impl MacroNode for TsExprWithTypeArgs { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; - emit!(self.expr); + let lo = only_new!(emitter.wr.get_pos()); + + emit!(emitter, self.expr); - emit!(self.type_args); - Ok(()) + emit!(emitter, self.type_args); + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(TsExprWithTypeArgs { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -264,11 +370,19 @@ impl MacroNode for TsExternalModuleRef { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + keyword!(emitter, "require"); punct!(emitter, "("); - emit!(self.expr); + emit!(emitter, self.expr); punct!(emitter, ")"); - Ok(()) + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(TsExternalModuleRef { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -277,24 +391,46 @@ impl MacroNode for TsFnOrConstructorType { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; - match self { - TsFnOrConstructorType::TsFnType(n) => emit!(n), - TsFnOrConstructorType::TsConstructorType(n) => emit!(n), - } - Ok(()) + Ok(match self { + TsFnOrConstructorType::TsFnType(n) => { + let n = emit!(emitter, n); + + only_new!(TsFnOrConstructorType::TsFnType(n)) + } + TsFnOrConstructorType::TsConstructorType(n) => { + let n = emit!(emitter, n); + + only_new!(TsFnOrConstructorType::TsConstructorType(n)) + } + }) } } #[node_impl] impl MacroNode for TsFnParam { fn emit(&mut self, emitter: &mut Macro) -> Result { - match self { - TsFnParam::Ident(n) => emit!(n), - TsFnParam::Array(n) => emit!(n), - TsFnParam::Rest(n) => emit!(n), - TsFnParam::Object(n) => emit!(n), - } - Ok(()) + Ok(match self { + TsFnParam::Ident(n) => { + let n = emit!(emitter, n); + + only_new!(TsFnParam::Ident(n)) + } + TsFnParam::Array(n) => { + let n = emit!(emitter, n); + + only_new!(TsFnParam::Array(n)) + } + TsFnParam::Rest(n) => { + let n = emit!(emitter, n); + + only_new!(TsFnParam::Rest(n)) + } + TsFnParam::Object(n) => { + let n = emit!(emitter, n); + + only_new!(TsFnParam::Object(n)) + } + }) } } @@ -303,7 +439,9 @@ impl MacroNode for TsFnType { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; - emit!(self.type_params); + let lo = only_new!(emitter.wr.get_pos()); + + emit!(emitter, self.type_params); punct!(emitter, "("); emitter.emit_list(self.span, Some(&self.params), ListFormat::Parameters)?; @@ -313,8 +451,14 @@ impl MacroNode for TsFnType { punct!(emitter, "=>"); formatting_space!(emitter); - emit!(self.type_ann); - Ok(()) + emit!(emitter, self.type_ann); + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(TsFnType { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -323,6 +467,8 @@ impl MacroNode for TsImportEqualsDecl { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + if self.is_export { keyword!(emitter, "export"); space!(emitter); @@ -336,16 +482,22 @@ impl MacroNode for TsImportEqualsDecl { space!(emitter); } - emit!(self.id); + emit!(emitter, self.id); formatting_space!(emitter); punct!(emitter, "="); formatting_space!(emitter); - emit!(self.module_ref); + emit!(emitter, self.module_ref); formatting_semi!(emitter); - Ok(()) + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(TsImportEqualsDecl { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -354,6 +506,8 @@ impl MacroNode for TsIndexSignature { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + if self.readonly { keyword!(emitter, "readonly"); formatting_space!(emitter); @@ -366,9 +520,15 @@ impl MacroNode for TsIndexSignature { if let Some(type_ann) = &self.type_ann { punct!(emitter, ":"); formatting_space!(emitter); - emit!(type_ann); + emit!(emitter, type_ann); } - Ok(()) + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(TsIndexSignature { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -377,12 +537,20 @@ impl MacroNode for TsIndexedAccessType { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; - emit!(self.obj_type); + let lo = only_new!(emitter.wr.get_pos()); + + emit!(emitter, self.obj_type); punct!(emitter, "["); - emit!(self.index_type); + emit!(emitter, self.index_type); punct!(emitter, "]"); - Ok(()) + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(TsIndexedAccessType { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -391,10 +559,18 @@ impl MacroNode for TsInferType { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + keyword!(emitter, "infer"); space!(emitter); - emit!(self.type_param); - Ok(()) + emit!(emitter, self.type_param); + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(TsInferType { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -403,12 +579,20 @@ impl MacroNode for TsInterfaceBody { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + punct!(emitter, "{"); emitter.emit_list(self.span, Some(&self.body), ListFormat::InterfaceMembers)?; punct!(emitter, "}"); - Ok(()) + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(TsInterfaceBody { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -417,6 +601,8 @@ impl MacroNode for TsInterfaceDecl { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + if self.declare { keyword!(emitter, "declare"); space!(emitter); @@ -425,10 +611,10 @@ impl MacroNode for TsInterfaceDecl { keyword!(emitter, "interface"); space!(emitter); - emit!(self.id); + emit!(emitter, self.id); if let Some(type_params) = &self.type_params { - emit!(type_params); + emit!(emitter, type_params); } if !self.extends.is_empty() { @@ -447,8 +633,14 @@ impl MacroNode for TsInterfaceDecl { formatting_space!(emitter); - emit!(self.body); - Ok(()) + emit!(emitter, self.body); + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(TsInterfaceDecl { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -457,12 +649,20 @@ impl MacroNode for TsIntersectionType { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + emitter.emit_list( self.span, Some(&self.types), ListFormat::IntersectionTypeConstituents, )?; - Ok(()) + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(TsIntersectionType { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -471,6 +671,8 @@ impl MacroNode for TsKeywordType { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + match self.kind { TsKeywordTypeKind::TsAnyKeyword => keyword!(emitter, self.span, "any"), TsKeywordTypeKind::TsUnknownKeyword => keyword!(emitter, self.span, "unknown"), @@ -486,21 +688,45 @@ impl MacroNode for TsKeywordType { TsKeywordTypeKind::TsNeverKeyword => keyword!(emitter, self.span, "never"), TsKeywordTypeKind::TsIntrinsicKeyword => keyword!(emitter, self.span, "intrinsic"), } - Ok(()) + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(TsKeywordType { + span: Span::new(lo, hi), + ..self.clone() + })) } } #[node_impl] impl MacroNode for TsLit { fn emit(&mut self, emitter: &mut Macro) -> Result { - match self { - TsLit::BigInt(n) => emit!(n), - TsLit::Number(n) => emit!(n), - TsLit::Str(n) => emit!(n), - TsLit::Bool(n) => emit!(n), - TsLit::Tpl(n) => emit!(n), - } - Ok(()) + Ok(match self { + TsLit::BigInt(n) => { + let n = emit!(emitter, n); + + only_new!(TsLit::BigInt(n)) + } + TsLit::Number(n) => { + let n = emit!(emitter, n); + + only_new!(TsLit::Number(n)) + } + TsLit::Str(n) => { + let n = emit!(emitter, n); + + only_new!(TsLit::Str(n)) + } + TsLit::Bool(n) => { + let n = emit!(emitter, n); + only_new!(TsLit::Bool(n)) + } + TsLit::Tpl(n) => { + let n = emit!(emitter, n); + + only_new!(TsLit::Tpl(n)) + } + }) } } @@ -509,20 +735,28 @@ impl MacroNode for TsTplLitType { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + punct!(emitter, "`"); for i in 0..(self.quasis.len() + self.types.len()) { if i % 2 == 0 { - emit!(self.quasis[i / 2]); + emit!(emitter, self.quasis[i / 2]); } else { punct!(emitter, "${"); - emit!(self.types[i / 2]); + emit!(emitter, self.types[i / 2]); punct!(emitter, "}"); } } punct!(emitter, "`"); - Ok(()) + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(TsTplLitType { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -531,8 +765,16 @@ impl MacroNode for TsLitType { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; - emit!(self.lit); - Ok(()) + let lo = only_new!(emitter.wr.get_pos()); + + let lit = emit!(emitter, self.lit); + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(TsLitType { + span: Span::new(lo, hi), + lit, + })) } } @@ -541,6 +783,8 @@ impl MacroNode for TsMappedType { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + punct!(emitter, "{"); emitter.wr.write_line()?; emitter.wr.increase_indent()?; @@ -567,27 +811,27 @@ impl MacroNode for TsMappedType { punct!(emitter, "["); - emit!(self.type_param.name); + emit!(emitter, self.type_param.name); if let Some(constraints) = &self.type_param.constraint { space!(emitter); keyword!(emitter, "in"); space!(emitter); - emit!(constraints); + emit!(emitter, constraints); } if let Some(default) = &self.type_param.default { formatting_space!(emitter); punct!(emitter, "="); formatting_space!(emitter); - emit!(default); + emit!(emitter, default); } if let Some(name_type) = &self.name_type { space!(emitter); keyword!(emitter, "as"); space!(emitter); - emit!(name_type); + emit!(emitter, name_type); } punct!(emitter, "]"); @@ -612,7 +856,7 @@ impl MacroNode for TsMappedType { if let Some(type_ann) = &self.type_ann { punct!(emitter, ":"); space!(emitter); - emit!(type_ann); + emit!(emitter, type_ann); } formatting_semi!(emitter); @@ -620,7 +864,13 @@ impl MacroNode for TsMappedType { emitter.wr.write_line()?; emitter.wr.decrease_indent()?; punct!(emitter, "}"); - Ok(()) + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(TsMappedType { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -629,20 +879,24 @@ impl MacroNode for TsMethodSignature { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; - if self.computed { + let lo = only_new!(emitter.wr.get_pos()); + + let key = if self.computed { punct!(emitter, "["); - emit!(self.key); + let n = emit!(emitter, self.key); punct!(emitter, "]"); + + n } else { - emit!(self.key) - } + emit!(emitter, self.key) + }; if self.optional { punct!(emitter, "?"); } if let Some(type_params) = &self.type_params { - emit!(type_params); + emit!(emitter, type_params); } punct!(emitter, "("); @@ -652,22 +906,37 @@ impl MacroNode for TsMethodSignature { if let Some(ref type_ann) = self.type_ann { punct!(emitter, ":"); formatting_space!(emitter); - emit!(type_ann); + emit!(emitter, type_ann); } - Ok(()) + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(TsMethodSignature { + span: Span::new(lo, hi), + key, + ..self.clone() + })) } } #[node_impl] impl MacroNode for TsModuleBlock { fn emit(&mut self, emitter: &mut Macro) -> Result { + let lo = only_new!(emitter.wr.get_pos()); + emitter.emit_list( self.span, Some(&self.body), ListFormat::SourceFileStatements, )?; emitter.emit_leading_comments_of_span(self.span(), false)?; - Ok(()) + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(TsModuleBlock { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -676,6 +945,8 @@ impl MacroNode for TsModuleDecl { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + if self.declare { keyword!(emitter, "declare"); space!(emitter); @@ -691,30 +962,43 @@ impl MacroNode for TsModuleDecl { TsModuleName::Str(_) => keyword!(emitter, "module"), } space!(emitter); - emit!(self.id); + emit!(emitter, self.id); } if let Some(mut body) = self.body.as_ref() { while let TsNamespaceBody::TsNamespaceDecl(decl) = body { punct!(emitter, "."); - emit!(decl.id); + emit!(emitter, decl.id); body = &*decl.body; } formatting_space!(emitter); - emit!(body); + emit!(emitter, body); } - Ok(()) + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(TsModuleDecl { + span: Span::new(lo, hi), + ..self.clone() + })) } } #[node_impl] impl MacroNode for TsModuleName { fn emit(&mut self, emitter: &mut Macro) -> Result { - match self { - TsModuleName::Ident(n) => emit!(n), - TsModuleName::Str(n) => emit!(n), - } - Ok(()) + Ok(match self { + TsModuleName::Ident(n) => { + let n = emit!(emitter, n); + + only_new!(TsModuleName::Ident(n)) + } + TsModuleName::Str(n) => { + let n = emit!(emitter, n); + + only_new!(TsModuleName::Str(n)) + } + }) } } @@ -723,11 +1007,18 @@ impl MacroNode for TsModuleRef { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; - match self { - TsModuleRef::TsEntityName(n) => emit!(n), - TsModuleRef::TsExternalModuleRef(n) => emit!(n), - } - Ok(()) + Ok(match self { + TsModuleRef::TsEntityName(n) => { + let n = emit!(emitter, n); + + only_new!(TsModuleRef::TsEntityName(n)) + } + TsModuleRef::TsExternalModuleRef(n) => { + let n = emit!(emitter, n); + + only_new!(TsModuleRef::TsExternalModuleRef(n)) + } + }) } } @@ -738,13 +1029,22 @@ impl MacroNode for TsNamespaceBody { punct!(emitter, "{"); emitter.wr.increase_indent()?; - match self { - TsNamespaceBody::TsModuleBlock(n) => emit!(n), - TsNamespaceBody::TsNamespaceDecl(n) => emit!(n), - } + let result = match self { + TsNamespaceBody::TsModuleBlock(n) => { + let n = emit!(emitter, n); + + only_new!(TsNamespaceBody::TsModuleBlock(n)) + } + TsNamespaceBody::TsNamespaceDecl(n) => { + let n = emit!(emitter, n); + + only_new!(TsNamespaceBody::TsNamespaceDecl(n)) + } + }; emitter.wr.decrease_indent()?; punct!(emitter, "}"); - Ok(()) + + Ok(result) } } @@ -753,6 +1053,8 @@ impl MacroNode for TsNamespaceDecl { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + if self.declare { keyword!(emitter, "declare"); space!(emitter); @@ -760,11 +1062,17 @@ impl MacroNode for TsNamespaceDecl { keyword!(emitter, "namespace"); space!(emitter); - emit!(self.id); + emit!(emitter, self.id); formatting_space!(emitter); - emit!(self.body); - Ok(()) + emit!(emitter, self.body); + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(TsNamespaceDecl { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -773,12 +1081,20 @@ impl MacroNode for TsNamespaceExportDecl { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + keyword!(emitter, "export"); space!(emitter); punct!(emitter, "="); space!(emitter); - emit!(self.id); - Ok(()) + emit!(emitter, self.id); + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(TsNamespaceExportDecl { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -787,9 +1103,17 @@ impl MacroNode for TsNonNullExpr { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; - emit!(self.expr); + let lo = only_new!(emitter.wr.get_pos()); + + emit!(emitter, self.expr); punct!(emitter, "!"); - Ok(()) + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(TsNonNullExpr { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -798,9 +1122,16 @@ impl MacroNode for TsOptionalType { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; - emit!(self.type_ann); + let lo = only_new!(emitter.wr.get_pos()); + emit!(emitter, self.type_ann); punct!(emitter, "?"); - Ok(()) + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(TsOptionalType { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -809,6 +1140,8 @@ impl MacroNode for TsParamProp { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + emitter.emit_list(self.span, Some(&self.decorators), ListFormat::Decorators)?; if self.accessibility.is_some() { @@ -830,8 +1163,14 @@ impl MacroNode for TsParamProp { space!(emitter); } - emit!(self.param); - Ok(()) + emit!(emitter, self.param); + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(TsParamProp { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -840,11 +1179,18 @@ impl MacroNode for TsParamPropParam { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; - match self { - TsParamPropParam::Ident(n) => emit!(n), - TsParamPropParam::Assign(n) => emit!(n), - } - Ok(()) + Ok(match self { + TsParamPropParam::Ident(n) => { + let n = emit!(emitter, n); + + only_new!(TsParamPropParam::Ident(n)) + } + TsParamPropParam::Assign(n) => { + let n = emit!(emitter, n); + + only_new!(TsParamPropParam::Assign(n)) + } + }) } } @@ -853,10 +1199,18 @@ impl MacroNode for TsParenthesizedType { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + punct!(emitter, "("); - emit!(self.type_ann); + emit!(emitter, self.type_ann); punct!(emitter, ")"); - Ok(()) + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(TsParenthesizedType { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -865,6 +1219,8 @@ impl MacroNode for TsPropertySignature { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + if self.readonly { keyword!(emitter, "readonly"); space!(emitter); @@ -872,10 +1228,10 @@ impl MacroNode for TsPropertySignature { if self.computed { punct!(emitter, "["); - emit!(self.key); + emit!(emitter, self.key); punct!(emitter, "]"); } else { - emit!(self.key); + emit!(emitter, self.key); } if self.optional { @@ -885,9 +1241,15 @@ impl MacroNode for TsPropertySignature { if let Some(type_ann) = &self.type_ann { punct!(emitter, ":"); formatting_space!(emitter); - emit!(type_ann); + emit!(emitter, type_ann); } - Ok(()) + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(TsPropertySignature { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -896,10 +1258,18 @@ impl MacroNode for TsQualifiedName { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; - emit!(self.left); + let lo = only_new!(emitter.wr.get_pos()); + + emit!(emitter, self.left); punct!(emitter, "."); - emit!(self.right); - Ok(()) + emit!(emitter, self.right); + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(TsQualifiedName { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -908,9 +1278,17 @@ impl MacroNode for TsRestType { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + punct!(emitter, "..."); - emit!(self.type_ann); - Ok(()) + emit!(emitter, self.type_ann); + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(TsRestType { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -919,8 +1297,15 @@ impl MacroNode for TsThisType { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + keyword!(emitter, self.span, "this"); - Ok(()) + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(TsThisType { + span: Span::new(lo, hi), + })) } } @@ -929,11 +1314,18 @@ impl MacroNode for TsThisTypeOrIdent { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; - match self { - TsThisTypeOrIdent::TsThisType(n) => emit!(n), - TsThisTypeOrIdent::Ident(n) => emit!(n), - } - Ok(()) + Ok(match self { + TsThisTypeOrIdent::TsThisType(n) => { + let n = emit!(emitter, n); + + only_new!(TsThisTypeOrIdent::TsThisType(n)) + } + TsThisTypeOrIdent::Ident(n) => { + let n = emit!(emitter, n); + + only_new!(TsThisTypeOrIdent::Ident(n)) + } + }) } } @@ -942,6 +1334,8 @@ impl MacroNode for TsTupleType { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + punct!(emitter, "["); emitter.emit_list( self.span, @@ -949,7 +1343,13 @@ impl MacroNode for TsTupleType { ListFormat::TupleTypeElements, )?; punct!(emitter, "]"); - Ok(()) + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(TsTupleType { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -958,43 +1358,130 @@ impl MacroNode for TsTupleElement { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + if let Some(label) = &self.label { - emit!(label); + emit!(emitter, label); punct!(emitter, ":"); formatting_space!(emitter); } - emit!(self.ty); - Ok(()) + emit!(emitter, self.ty); + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(TsTupleElement { + span: Span::new(lo, hi), + ..self.clone() + })) } } #[node_impl] impl MacroNode for TsType { fn emit(&mut self, emitter: &mut Macro) -> Result { - match self { - TsType::TsKeywordType(n) => emit!(n), - TsType::TsThisType(n) => emit!(n), - TsType::TsFnOrConstructorType(n) => emit!(n), - TsType::TsTypeRef(n) => emit!(n), - TsType::TsTypeQuery(n) => emit!(n), - TsType::TsTypeLit(n) => emit!(n), - TsType::TsArrayType(n) => emit!(n), - TsType::TsTupleType(n) => emit!(n), - TsType::TsOptionalType(n) => emit!(n), - TsType::TsRestType(n) => emit!(n), - TsType::TsUnionOrIntersectionType(n) => emit!(n), - TsType::TsConditionalType(n) => emit!(n), - TsType::TsInferType(n) => emit!(n), - TsType::TsParenthesizedType(n) => emit!(n), - TsType::TsTypeOperator(n) => emit!(n), - TsType::TsIndexedAccessType(n) => emit!(n), - TsType::TsMappedType(n) => emit!(n), - TsType::TsLitType(n) => emit!(n), - TsType::TsTypePredicate(n) => emit!(n), - TsType::TsImportType(n) => emit!(n), - } - Ok(()) + Ok(match self { + TsType::TsKeywordType(n) => { + let n = emit!(emitter, n); + + only_new!(TsType::TsKeywordType(n)) + } + TsType::TsThisType(n) => { + let n = emit!(emitter, n); + + only_new!(TsType::TsThisType(n)) + } + TsType::TsFnOrConstructorType(n) => { + let n = emit!(emitter, n); + + only_new!(TsType::TsFnOrConstructorType(n)) + } + TsType::TsTypeRef(n) => { + let n = emit!(emitter, n); + + only_new!(TsType::TsTypeRef(n)) + } + TsType::TsTypeQuery(n) => { + let n = emit!(emitter, n); + + only_new!(TsType::TsTypeQuery(n)) + } + TsType::TsTypeLit(n) => { + let n = emit!(emitter, n); + + only_new!(TsType::TsTypeLit(n)) + } + TsType::TsArrayType(n) => { + let n = emit!(emitter, n); + + only_new!(TsType::TsArrayType(n)) + } + TsType::TsTupleType(n) => { + let n = emit!(emitter, n); + + only_new!(TsType::TsTupleType(n)) + } + TsType::TsOptionalType(n) => { + let n = emit!(emitter, n); + + only_new!(TsType::TsOptionalType(n)) + } + TsType::TsRestType(n) => { + let n = emit!(emitter, n); + + only_new!(TsType::TsRestType(n)) + } + TsType::TsUnionOrIntersectionType(n) => { + let n = emit!(emitter, n); + + only_new!(TsType::TsUnionOrIntersectionType(n)) + } + TsType::TsInferType(n) => { + let n = emit!(emitter, n); + + only_new!(TsType::TsInferType(n)) + } + TsType::TsParenthesizedType(n) => { + let n = emit!(emitter, n); + + only_new!(TsType::TsParenthesizedType(n)) + } + TsType::TsTypeOperator(n) => { + let n = emit!(emitter, n); + + only_new!(TsType::TsTypeOperator(n)) + } + TsType::TsIndexedAccessType(n) => { + let n = emit!(emitter, n); + + only_new!(TsType::TsIndexedAccessType(n)) + } + TsType::TsMappedType(n) => { + let n = emit!(emitter, n); + + only_new!(TsType::TsMappedType(n)) + } + TsType::TsLitType(n) => { + let n = emit!(emitter, n); + + only_new!(TsType::TsLitType(n)) + } + TsType::TsTypePredicate(n) => { + let n = emit!(emitter, n); + + only_new!(TsType::TsTypePredicate(n)) + } + TsType::TsImportType(n) => { + let n = emit!(emitter, n); + + only_new!(TsType::TsImportType(n)) + } + TsType::TsConditionalType(n) => { + let n = emit!(emitter, n); + + only_new!(TsType::TsConditionalType(n)) + } + }) } } @@ -1003,29 +1490,39 @@ impl MacroNode for TsImportType { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + keyword!(emitter, "import"); punct!(emitter, "("); - emit!(self.arg); + emit!(emitter, self.arg); if let Some(attributes) = &self.attributes { punct!(emitter, ","); formatting_space!(emitter); - emit!(attributes); + emit!(emitter, attributes); } punct!(emitter, ")"); if let Some(n) = &self.qualifier { punct!(emitter, "."); - emit!(n); + emit!(emitter, n); } - emit!(self.type_args); - Ok(()) + emit!(emitter, self.type_args); + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(TsImportType { + span: Span::new(lo, hi), + ..self.clone() + })) } } #[node_impl] impl MacroNode for TsImportCallOptions { fn emit(&mut self, emitter: &mut Macro) -> Result { + let lo = only_new!(emitter.wr.get_pos()); + punct!(emitter, "{"); if !emitter.cfg.minify { emitter.wr.write_line()?; @@ -1035,14 +1532,20 @@ impl MacroNode for TsImportCallOptions { keyword!(emitter, "with"); punct!(emitter, ":"); formatting_space!(emitter); - emit!(self.with); + emit!(emitter, self.with); if !emitter.cfg.minify { emitter.wr.decrease_indent()?; emitter.wr.write_line()?; } punct!(emitter, "}"); - Ok(()) + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(TsImportCallOptions { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -1051,6 +1554,8 @@ impl MacroNode for TsTypeAliasDecl { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + if self.declare { keyword!(emitter, "declare"); space!(emitter); @@ -1060,9 +1565,9 @@ impl MacroNode for TsTypeAliasDecl { space!(emitter); - emit!(self.id); + emit!(emitter, self.id); if let Some(type_params) = &self.type_params { - emit!(type_params); + emit!(emitter, type_params); } formatting_space!(emitter); @@ -1070,10 +1575,16 @@ impl MacroNode for TsTypeAliasDecl { formatting_space!(emitter); - emit!(self.type_ann); + emit!(emitter, self.type_ann); formatting_semi!(emitter); - Ok(()) + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(TsTypeAliasDecl { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -1082,8 +1593,16 @@ impl MacroNode for TsTypeAnn { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; - emit!(self.type_ann); - Ok(()) + let lo = only_new!(emitter.wr.get_pos()); + + emit!(emitter, self.type_ann); + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(TsTypeAnn { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -1092,11 +1611,19 @@ impl MacroNode for TsTypeAssertion { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + punct!(emitter, "<"); - emit!(self.type_ann); + emit!(emitter, self.type_ann); punct!(emitter, ">"); - emit!(self.expr); - Ok(()) + emit!(emitter, self.expr); + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(TsTypeAssertion { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -1105,50 +1632,85 @@ impl MacroNode for TsConstAssertion { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; - emit!(self.expr); + let lo = only_new!(emitter.wr.get_pos()); + + emit!(emitter, self.expr); space!(emitter); keyword!(emitter, "as"); space!(emitter); keyword!(emitter, "const"); - Ok(()) + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(TsConstAssertion { + span: Span::new(lo, hi), + ..self.clone() + })) } } #[node_impl] impl MacroNode for TsTypeElement { fn emit(&mut self, emitter: &mut Macro) -> Result { - match self { - TsTypeElement::TsCallSignatureDecl(n) => emit!(n), - TsTypeElement::TsConstructSignatureDecl(n) => emit!(n), - TsTypeElement::TsPropertySignature(n) => emit!(n), - TsTypeElement::TsMethodSignature(n) => emit!(n), - TsTypeElement::TsIndexSignature(n) => emit!(n), + let result = match self { + TsTypeElement::TsCallSignatureDecl(n) => { + let n = emit!(emitter, n); + + only_new!(TsTypeElement::TsCallSignatureDecl(n)) + } + TsTypeElement::TsConstructSignatureDecl(n) => { + let n = emit!(emitter, n); + + only_new!(TsTypeElement::TsConstructSignatureDecl(n)) + } + TsTypeElement::TsPropertySignature(n) => { + let n = emit!(emitter, n); + + only_new!(TsTypeElement::TsPropertySignature(n)) + } + TsTypeElement::TsMethodSignature(n) => { + let n = emit!(emitter, n); + + only_new!(TsTypeElement::TsMethodSignature(n)) + } + TsTypeElement::TsIndexSignature(n) => { + let n = emit!(emitter, n); + + only_new!(TsTypeElement::TsIndexSignature(n)) + } TsTypeElement::TsGetterSignature(n) => { - emit!(n) + let n = emit!(emitter, n); + + only_new!(TsTypeElement::TsGetterSignature(n)) } TsTypeElement::TsSetterSignature(n) => { - emit!(n) + let n = emit!(emitter, n); + + only_new!(TsTypeElement::TsSetterSignature(n)) } - } + }; formatting_semi!(emitter); - Ok(()) + Ok(result) } } #[node_impl] impl MacroNode for TsGetterSignature { fn emit(&mut self, emitter: &mut Macro) -> Result { + let lo = only_new!(emitter.wr.get_pos()); + keyword!(emitter, "get"); space!(emitter); - if self.computed { + let key = if self.computed { punct!(emitter, "["); - emit!(self.key); + let n = emit!(emitter, self.key); punct!(emitter, "]"); + n } else { - emit!(self.key) - } + emit!(emitter, self.key) + }; punct!(emitter, "("); punct!(emitter, ")"); @@ -1157,30 +1719,48 @@ impl MacroNode for TsGetterSignature { punct!(emitter, ":"); formatting_space!(emitter); - emit!(ty.type_ann); + emit!(emitter, ty.type_ann); } - Ok(()) + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(TsGetterSignature { + span: Span::new(lo, hi), + key, + ..self.clone() + })) } } #[node_impl] impl MacroNode for TsSetterSignature { fn emit(&mut self, emitter: &mut Macro) -> Result { + let lo = only_new!(emitter.wr.get_pos()); + keyword!(emitter, "set"); space!(emitter); - if self.computed { + let key = if self.computed { punct!(emitter, "["); - emit!(self.key); + let n = emit!(emitter, self.key); punct!(emitter, "]"); + + n } else { - emit!(self.key) - } + emit!(emitter, self.key) + }; punct!(emitter, "("); - emit!(self.param); + emit!(emitter, self.param); punct!(emitter, ")"); - Ok(()) + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(TsSetterSignature { + span: Span::new(lo, hi), + key, + ..self.clone() + })) } } @@ -1189,6 +1769,8 @@ impl MacroNode for TsTypeLit { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + punct!(emitter, "{"); emitter.emit_list( self.span, @@ -1196,7 +1778,13 @@ impl MacroNode for TsTypeLit { ListFormat::MultiLineTypeLiteralMembers, )?; punct!(emitter, "}"); - Ok(()) + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(TsTypeLit { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -1205,14 +1793,22 @@ impl MacroNode for TsTypeOperator { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + match self.op { TsTypeOperatorOp::KeyOf => keyword!(emitter, "keyof"), TsTypeOperatorOp::Unique => keyword!(emitter, "unique"), TsTypeOperatorOp::ReadOnly => keyword!(emitter, "readonly"), } space!(emitter); - emit!(self.type_ann); - Ok(()) + emit!(emitter, self.type_ann); + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(TsTypeOperator { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -1221,6 +1817,8 @@ impl MacroNode for TsTypeParam { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + if self.is_const { keyword!(emitter, "const"); space!(emitter); @@ -1236,22 +1834,28 @@ impl MacroNode for TsTypeParam { space!(emitter); } - emit!(self.name); + emit!(emitter, self.name); if let Some(constraints) = &self.constraint { space!(emitter); keyword!(emitter, "extends"); space!(emitter); - emit!(constraints); + emit!(emitter, constraints); } if let Some(default) = &self.default { formatting_space!(emitter); punct!(emitter, "="); formatting_space!(emitter); - emit!(default); + emit!(emitter, default); } - Ok(()) + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(TsTypeParam { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -1260,12 +1864,20 @@ impl MacroNode for TsTypeParamDecl { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + punct!(emitter, "<"); emitter.emit_list(self.span, Some(&self.params), ListFormat::TypeParameters)?; punct!(emitter, ">"); - Ok(()) + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(TsTypeParamDecl { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -1274,11 +1886,19 @@ impl MacroNode for TsTypeParamInstantiation { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + punct!(emitter, "<"); emitter.emit_list(self.span, Some(&self.params), ListFormat::TypeParameters)?; punct!(emitter, ">"); - Ok(()) + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(TsTypeParamInstantiation { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -1287,20 +1907,28 @@ impl MacroNode for TsTypePredicate { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + if self.asserts { keyword!(emitter, "asserts"); space!(emitter); } - emit!(self.param_name); + emit!(emitter, self.param_name); if let Some(type_ann) = &self.type_ann { space!(emitter); keyword!(emitter, "is"); space!(emitter); - emit!(type_ann); + emit!(emitter, type_ann); } - Ok(()) + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(TsTypePredicate { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -1309,22 +1937,37 @@ impl MacroNode for TsTypeQuery { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + keyword!(emitter, "typeof"); space!(emitter); - emit!(self.expr_name); - emit!(self.type_args); - Ok(()) + emit!(emitter, self.expr_name); + emit!(emitter, self.type_args); + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(TsTypeQuery { + span: Span::new(lo, hi), + ..self.clone() + })) } } #[node_impl] impl MacroNode for TsTypeQueryExpr { fn emit(&mut self, emitter: &mut Macro) -> Result { - match self { - TsTypeQueryExpr::TsEntityName(n) => emit!(n), - TsTypeQueryExpr::Import(n) => emit!(n), - } - Ok(()) + Ok(match self { + TsTypeQueryExpr::TsEntityName(n) => { + let n = emit!(emitter, n); + + only_new!(TsTypeQueryExpr::TsEntityName(n)) + } + TsTypeQueryExpr::Import(n) => { + let n = emit!(emitter, n); + + only_new!(TsTypeQueryExpr::Import(n)) + } + }) } } @@ -1333,25 +1976,40 @@ impl MacroNode for TsTypeRef { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; - emit!(self.type_name); + let lo = only_new!(emitter.wr.get_pos()); + + emit!(emitter, self.type_name); if let Some(n) = &self.type_params { punct!(emitter, "<"); emitter.emit_list(n.span, Some(&n.params), ListFormat::TypeArguments)?; punct!(emitter, ">"); } - Ok(()) + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(TsTypeRef { + span: Span::new(lo, hi), + ..self.clone() + })) } } #[node_impl] impl MacroNode for TsUnionOrIntersectionType { fn emit(&mut self, emitter: &mut Macro) -> Result { - match self { - TsUnionOrIntersectionType::TsUnionType(n) => emit!(n), - TsUnionOrIntersectionType::TsIntersectionType(n) => emit!(n), - } - Ok(()) + Ok(match self { + TsUnionOrIntersectionType::TsUnionType(n) => { + let n = emit!(emitter, n); + + only_new!(TsUnionOrIntersectionType::TsUnionType(n)) + } + TsUnionOrIntersectionType::TsIntersectionType(n) => { + let n = emit!(emitter, n); + + only_new!(TsUnionOrIntersectionType::TsIntersectionType(n)) + } + }) } } @@ -1360,12 +2018,20 @@ impl MacroNode for TsUnionType { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; + let lo = only_new!(emitter.wr.get_pos()); + emitter.emit_list( self.span, Some(&self.types), ListFormat::UnionTypeConstituents, )?; - Ok(()) + + let hi = only_new!(emitter.wr.get_pos()); + + Ok(only_new!(TsUnionType { + span: Span::new(lo, hi), + ..self.clone() + })) } } @@ -1374,10 +2040,18 @@ impl MacroNode for TsInstantiation { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; - emit!(self.expr); + let lo = only_new!(emitter.wr.get_pos()); + + emit!(emitter, self.expr); + + emit!(emitter, self.type_args); + + let hi = only_new!(emitter.wr.get_pos()); - emit!(self.type_args); - Ok(()) + Ok(only_new!(TsInstantiation { + span: Span::new(lo, hi), + ..self.clone() + })) } } diff --git a/crates/swc_ecma_codegen/tests/fixture.rs b/crates/swc_ecma_codegen/tests/fixture.rs index f3754c268c2c..760fb0e1f2d7 100644 --- a/crates/swc_ecma_codegen/tests/fixture.rs +++ b/crates/swc_ecma_codegen/tests/fixture.rs @@ -1,13 +1,16 @@ use std::{ + fmt::Debug, fs::read_to_string, path::{Path, PathBuf}, }; use serde::Deserialize; -use swc_ecma_ast::EsVersion; +use swc_atoms::Atom; +use swc_common::{FileName, Span}; +use swc_ecma_ast::{EsVersion, *}; use swc_ecma_codegen::{ - text_writer::{JsWriter, WriteJs}, - Emitter, + text_writer::{JsWriter, SpannedWriteJs, WriteJs}, + Emitter, Node, NodeEmitter, }; use swc_ecma_parser::{parse_file_as_module, Syntax, TsSyntax}; use testing::{run_test2, NormalizedOutput}; @@ -93,7 +96,7 @@ fn run(input: &Path, minify: bool) { cfg: swc_ecma_codegen::Config::default() .with_minify(minify) .with_reduce_escaped_newline(config.reduce_escaped_newline), - cm, + cm: cm.clone(), comments: None, wr, }; @@ -101,10 +104,40 @@ fn run(input: &Path, minify: bool) { emitter.emit_module(&m).unwrap(); } - NormalizedOutput::from(String::from_utf8(buf).unwrap()) + NormalizedOutput::from(String::from_utf8(buf.clone()).unwrap()) .compare_to_file(&output) .unwrap(); + let new_module = { + let wr = Box::new(JsWriter::new(cm.clone(), "\n", &mut buf, None)) + as Box; + + let mut emitter = NodeEmitter::new(Emitter { + cfg: swc_ecma_codegen::Config::default() + .with_minify(minify) + .with_reduce_escaped_newline(config.reduce_escaped_newline), + cm: cm.clone(), + comments: None, + wr, + }); + + m.with_new_span(&mut emitter).unwrap() + }; + + let buf = String::from_utf8(buf).unwrap(); + let fm = cm.new_source_file(FileName::Anon.into(), buf.clone()); + + let m = parse_file_as_module( + &fm, + Syntax::default(), + EsVersion::latest(), + None, + &mut Vec::new(), + ) + .expect("failed to parse input as a module"); + + AssertEq::assert_eq(&new_module, &m); + Ok(()) }) .unwrap(); @@ -122,3 +155,77 @@ fn js(input: PathBuf) { run(&input, false); run(&input, true); } + +trait AssertEq: Debug + PartialEq { + fn assert_eq(&self, other: &Self); +} + +impl AssertEq for Vec { + fn assert_eq(&self, other: &Self) { + if self.len() != other.len() { + panic!("lengths are different: {} != {}", self.len(), other.len()); + } + + for (a, b) in self.iter().zip(other.iter()) { + a.assert_eq(b); + } + } +} + +impl AssertEq for Option { + fn assert_eq(&self, other: &Self) { + match (self, other) { + (Some(a), Some(b)) => a.assert_eq(b), + (None, None) => (), + (Some(_), None) | (None, Some(_)) => { + panic!("variants are different: {:?} != {:?}", self, other) + } + } + } +} + +macro_rules! impl_assert_using_eq { + ($type:ty) => { + impl AssertEq for $type { + fn assert_eq(&self, other: &Self) { + if self != other { + panic!("{:?} != {:?}", self, other); + } + } + } + }; +} + +macro_rules! assert_struct { + ($type:ty, $($field:ident),*) => { + impl AssertEq for $type { + fn assert_eq(&self, other: &Self) { + $( + AssertEq::assert_eq(&self.$field, &other.$field); + )* + } + } + }; +} + +macro_rules! assert_enum { + ($type:ty, [$($variant:ident),*]) => { + impl AssertEq for $type { + fn assert_eq(&self, other: &Self) { + match (self, other) { + $((Self::$variant(a), Self::$variant(b)) => a.assert_eq(b),)* + _ => panic!("variants are different: {:?} != {:?}", self, other), + } + } + } + }; +} + +impl_assert_using_eq!(Span); +impl_assert_using_eq!(Atom); +impl_assert_using_eq!(Stmt); +impl_assert_using_eq!(ModuleDecl); + +assert_struct!(Module, span, body, shebang); + +assert_enum!(ModuleItem, [Stmt, ModuleDecl]); diff --git a/crates/swc_ecma_codegen_macros/src/lib.rs b/crates/swc_ecma_codegen_macros/src/lib.rs index f8b4a6234876..51fa0a88f6bd 100644 --- a/crates/swc_ecma_codegen_macros/src/lib.rs +++ b/crates/swc_ecma_codegen_macros/src/lib.rs @@ -60,9 +60,12 @@ pub fn node_impl( /// Returns `(emitter_method, adjuster_method)` fn expand_node_impl_method(node_type: &Type, src: ImplItemFn) -> ItemImpl { let emit_block = ReplaceEmit { emit: true }.fold_block(src.block.clone()); + let adjust_block = ReplaceEmit { emit: false }.fold_block(src.block.clone()); parse_quote!( impl crate::Node for #node_type { + #[allow(unused)] + #[allow(clippy::all)] fn emit_with(&self, emitter: &mut crate::Emitter<'_, W, S>) -> crate::Result where W: crate::text_writer::WriteJs, @@ -71,6 +74,13 @@ fn expand_node_impl_method(node_type: &Type, src: ImplItemFn) -> ItemImpl { #emit_block } + fn with_new_span(&self, emitter: &mut crate::NodeEmitter<'_, W, S>) -> crate::Result + where + W: crate::text_writer::SpannedWriteJs, + S: swc_common::SourceMapper + swc_ecma_ast::SourceMapperExt, + { + #adjust_block + } } ) } @@ -81,9 +91,10 @@ struct ReplaceEmit { impl Fold for ReplaceEmit { fn fold_macro(&mut self, mut i: Macro) -> Macro { + let path = &i.path; let name = i.path.clone().into_token_stream().to_string(); - if "emit" == &*name { + if matches!(&*name, "emit" | "only_new") { let args: Punctuated = parse_args(i.tokens); let args: TokenStream = args .into_pairs() @@ -91,7 +102,7 @@ impl Fold for ReplaceEmit { .collect(); let is_emit = self.emit; - i = parse_quote!(emit_node_inner!(emitter, #is_emit, #args)); + i = parse_quote!(#path!(#is_emit, #args)); } i