diff --git a/crates/oxc_codegen/src/comment.rs b/crates/oxc_codegen/src/comment.rs index 8040a4384bb58..3365b2c11ecb9 100644 --- a/crates/oxc_codegen/src/comment.rs +++ b/crates/oxc_codegen/src/comment.rs @@ -70,14 +70,15 @@ impl<'a> Codegen<'a> { self.print_comments(start, &comments, unused_comments); } - /// A statement comment also includes legal comments - pub(crate) fn print_statement_comments(&mut self, start: u32) { + pub(crate) fn get_statement_comments( + &mut self, + start: u32, + ) -> Option<(Vec, Vec)> { if self.options.minify { - return; + return None; } - let Some(comments) = self.comments.remove(&start) else { - return; - }; + + let comments = self.comments.remove(&start)?; let mut leading_comments = vec![]; let mut unused_comments = vec![]; @@ -107,7 +108,14 @@ impl<'a> Codegen<'a> { unused_comments.push(comment); } - self.print_comments(start, &leading_comments, unused_comments); + Some((leading_comments, unused_comments)) + } + + /// A statement comment also includes legal comments + pub(crate) fn print_statement_comments(&mut self, start: u32) { + if let Some((comments, unused)) = self.get_statement_comments(start) { + self.print_comments(start, &comments, unused); + } } pub(crate) fn print_annotation_comments(&mut self, node_start: u32) { @@ -162,7 +170,12 @@ impl<'a> Codegen<'a> { } } - fn print_comments(&mut self, start: u32, comments: &[Comment], unused_comments: Vec) { + pub(crate) fn print_comments( + &mut self, + start: u32, + comments: &[Comment], + unused_comments: Vec, + ) { for (i, comment) in comments.iter().enumerate() { if i == 0 { if comment.preceded_by_newline { diff --git a/crates/oxc_codegen/src/gen.rs b/crates/oxc_codegen/src/gen.rs index 7662a053639ef..1e38433d7b5d0 100644 --- a/crates/oxc_codegen/src/gen.rs +++ b/crates/oxc_codegen/src/gen.rs @@ -48,6 +48,8 @@ impl<'a> Gen for Program<'a> { stmt.print(p, ctx); p.print_semicolon_if_needed(); } + // Print trailing statement comments. + p.print_statement_comments(self.span.end); } } @@ -662,7 +664,18 @@ impl<'a> Gen for Function<'a> { impl<'a> Gen for FunctionBody<'a> { fn gen(&self, p: &mut Codegen, ctx: Context) { - p.print_curly_braces(self.span, self.is_empty(), |p| { + let span_end = self.span.end; + let comments_at_end = if !p.options.minify && span_end != 0 { + p.get_statement_comments(span_end - 1) + } else { + None + }; + let is_empty = if self.is_empty() { + comments_at_end.is_none() || comments_at_end.as_ref().is_some_and(|c| c.0.is_empty()) + } else { + false + }; + p.print_curly_braces(self.span, is_empty, |p| { for directive in &self.directives { directive.print(p, ctx); } @@ -670,6 +683,10 @@ impl<'a> Gen for FunctionBody<'a> { p.print_semicolon_if_needed(); stmt.print(p, ctx); } + // Print trailing statement comments. + if let Some((comments, unused)) = comments_at_end { + p.print_comments(span_end - 1, &comments, unused); + } }); p.needs_semicolon = false; } diff --git a/crates/oxc_codegen/tests/integration/legal_comments.rs b/crates/oxc_codegen/tests/integration/legal_comments.rs index 7ac57d2b4b5b0..44be0ca06467e 100644 --- a/crates/oxc_codegen/tests/integration/legal_comments.rs +++ b/crates/oxc_codegen/tests/integration/legal_comments.rs @@ -17,6 +17,23 @@ fn cases() -> Vec<&'static str> { bar; }", "function bar() { var foo; /*! #__NO_SIDE_EFFECTS__ */ function () { } }", + "function foo() { + (() => { + /** + * @preserve + */ + })(); + /** + * @preserve + */ +} +/** + * @preserve + */", + "/** +* @preserve +*/ +", ] } diff --git a/crates/oxc_codegen/tests/integration/snapshots/legal_eof_comments.snap b/crates/oxc_codegen/tests/integration/snapshots/legal_eof_comments.snap index ae79acc40787c..11c641b4e303c 100644 --- a/crates/oxc_codegen/tests/integration/snapshots/legal_eof_comments.snap +++ b/crates/oxc_codegen/tests/integration/snapshots/legal_eof_comments.snap @@ -76,3 +76,41 @@ function bar() { function() {} } /*! #__NO_SIDE_EFFECTS__ */ + +########## 7 +function foo() { + (() => { + /** + * @preserve + */ + })(); + /** + * @preserve + */ +} +/** + * @preserve + */ +---------- +function foo() { + (() => { + /** + * @preserve + */ + })(); + /** + * @preserve + */ +} +/** +* @preserve +*/ +########## 8 +/** +* @preserve +*/ + +---------- +/** +* @preserve +*/ diff --git a/crates/oxc_codegen/tests/integration/snapshots/legal_inline_comments.snap b/crates/oxc_codegen/tests/integration/snapshots/legal_inline_comments.snap index c4bfbd417f47d..ab83cd8fb16d8 100644 --- a/crates/oxc_codegen/tests/integration/snapshots/legal_inline_comments.snap +++ b/crates/oxc_codegen/tests/integration/snapshots/legal_inline_comments.snap @@ -75,3 +75,41 @@ function bar() { var foo; /*! #__NO_SIDE_EFFECTS__ */ function() {} } + +########## 7 +function foo() { + (() => { + /** + * @preserve + */ + })(); + /** + * @preserve + */ +} +/** + * @preserve + */ +---------- +function foo() { + (() => { + /** + * @preserve + */ + })(); + /** + * @preserve + */ +} +/** +* @preserve +*/ +########## 8 +/** +* @preserve +*/ + +---------- +/** +* @preserve +*/ diff --git a/crates/oxc_codegen/tests/integration/snapshots/legal_linked_comments.snap b/crates/oxc_codegen/tests/integration/snapshots/legal_linked_comments.snap index 14d64e1f6fc9a..22a1008aba54c 100644 --- a/crates/oxc_codegen/tests/integration/snapshots/legal_linked_comments.snap +++ b/crates/oxc_codegen/tests/integration/snapshots/legal_linked_comments.snap @@ -62,3 +62,41 @@ function bar() { function() {} } /*! For license information please see test.js */ +########## 7 +function foo() { + (() => { + /** + * @preserve + */ + })(); + /** + * @preserve + */ +} +/** + * @preserve + */ +---------- +function foo() { + (() => { + /** + * @preserve + */ + })(); + /** + * @preserve + */ +} +/** +* @preserve +*//*! For license information please see test.js */ +########## 8 +/** +* @preserve +*/ + +---------- +/** +* @preserve +*/ +/*! For license information please see test.js */