Skip to content

Commit 2c66ac2

Browse files
committed
feat(codegen): preserve code coverage ignore comments (e.g. v8 ignore) (#10338)
fixes #10091 This PR attempts to preserve any comments with a start match of ``` /* v8 ignore */ /* c8 ignore */ /* node:coverage */ /* istanbul ignore */ ``` Added a special handle for coverage comment before `catch`: ``` try { something(); } /* istanbul ignore next */ catch(e) { // should never happen } ```
1 parent 283e4c7 commit 2c66ac2

File tree

8 files changed

+427
-238
lines changed

8 files changed

+427
-238
lines changed

crates/oxc_ast/src/ast/comment.rs

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,11 @@ pub enum CommentAnnotation {
7575
/// e.g. `/* @vite-ignore */`
7676
/// <https://github.com/search?q=repo%3Avitejs%2Fvite%20vite-ignore&type=code>
7777
Vite = 6,
78+
79+
/// Code Coverage Ignore
80+
/// `v8 ignore`, `c8 ignore`, `node:coverage`, `istanbul ignore`
81+
/// <https://github.com/oxc-project/oxc/issues/10091>
82+
CoverageIgnore = 7,
7883
}
7984

8085
/// A comment in source code.
@@ -140,33 +145,39 @@ impl Comment {
140145
}
141146

142147
/// Returns `true` if this is a line comment.
148+
#[inline]
143149
pub fn is_line(self) -> bool {
144150
self.kind == CommentKind::Line
145151
}
146152

147153
/// Returns `true` if this is a block comment.
154+
#[inline]
148155
pub fn is_block(self) -> bool {
149156
self.kind == CommentKind::Block
150157
}
151158

152159
/// Returns `true` if this comment is before a token.
160+
#[inline]
153161
pub fn is_leading(self) -> bool {
154162
self.position == CommentPosition::Leading
155163
}
156164

157165
/// Returns `true` if this comment is after a token.
166+
#[inline]
158167
pub fn is_trailing(self) -> bool {
159168
self.position == CommentPosition::Trailing
160169
}
161170

162171
/// Is comment with special meaning.
172+
#[inline]
163173
pub fn is_annotation(self) -> bool {
164174
self.annotation != CommentAnnotation::None
165175
}
166176

167177
/// Returns `true` if this comment is a JSDoc comment. Implies `is_leading` and `is_block`.
178+
#[inline]
168179
pub fn is_jsdoc(self) -> bool {
169-
self.is_leading() && self.annotation == CommentAnnotation::Jsdoc
180+
self.annotation == CommentAnnotation::Jsdoc && self.is_leading()
170181
}
171182

172183
/// Legal comments
@@ -175,27 +186,38 @@ impl Comment {
175186
/// that contains `@license` or `@preserve` or that starts with `//!` or `/*!`.
176187
///
177188
/// <https://esbuild.github.io/api/#legal-comments>
189+
#[inline]
178190
pub fn is_legal(self) -> bool {
179-
self.is_leading() && self.annotation == CommentAnnotation::Legal
191+
self.annotation == CommentAnnotation::Legal && self.is_leading()
180192
}
181193

182194
/// Is `/* @__PURE__*/`.
195+
#[inline]
183196
pub fn is_pure(self) -> bool {
184197
self.annotation == CommentAnnotation::Pure
185198
}
186199

187200
/// Is `/* @__NO_SIDE_EFFECTS__*/`.
201+
#[inline]
188202
pub fn is_no_side_effects(self) -> bool {
189203
self.annotation == CommentAnnotation::NoSideEffects
190204
}
191205

192206
/// Is webpack magic comment.
207+
#[inline]
193208
pub fn is_webpack(self) -> bool {
194209
self.annotation == CommentAnnotation::Webpack
195210
}
196211

197212
/// Is vite special comment.
213+
#[inline]
198214
pub fn is_vite(self) -> bool {
199215
self.annotation == CommentAnnotation::Vite
200216
}
217+
218+
/// Is coverage ignore comment.
219+
#[inline]
220+
pub fn is_coverage_ignore(self) -> bool {
221+
self.annotation == CommentAnnotation::CoverageIgnore && self.is_leading()
222+
}
201223
}

crates/oxc_codegen/src/gen.rs

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -643,16 +643,7 @@ impl Gen for TryStatement<'_> {
643643
p.print_soft_space();
644644
p.print_block_statement(&self.block, ctx);
645645
if let Some(handler) = &self.handler {
646-
p.print_soft_space();
647-
p.print_str("catch");
648-
if let Some(param) = &handler.param {
649-
p.print_soft_space();
650-
p.print_str("(");
651-
param.pattern.print(p, ctx);
652-
p.print_str(")");
653-
}
654-
p.print_soft_space();
655-
p.print_block_statement(&handler.body, ctx);
646+
handler.r#gen(p, ctx);
656647
}
657648
if let Some(finalizer) = &self.finalizer {
658649
p.print_soft_space();
@@ -664,6 +655,22 @@ impl Gen for TryStatement<'_> {
664655
}
665656
}
666657

658+
impl Gen for CatchClause<'_> {
659+
fn r#gen(&self, p: &mut Codegen, ctx: Context) {
660+
p.print_soft_space();
661+
p.print_statement_comments(self.span.start);
662+
p.print_str("catch");
663+
if let Some(param) = &self.param {
664+
p.print_soft_space();
665+
p.print_str("(");
666+
param.pattern.print(p, ctx);
667+
p.print_str(")");
668+
}
669+
p.print_soft_space();
670+
p.print_block_statement(&self.body, ctx);
671+
}
672+
}
673+
667674
impl Gen for ThrowStatement<'_> {
668675
fn r#gen(&self, p: &mut Codegen, _ctx: Context) {
669676
p.add_source_mapping(self.span);

0 commit comments

Comments
 (0)