diff --git a/crates/oxc_ast/src/trivia.rs b/crates/oxc_ast/src/trivia.rs index 721d31d32d2bf..834545b8b1295 100644 --- a/crates/oxc_ast/src/trivia.rs +++ b/crates/oxc_ast/src/trivia.rs @@ -8,19 +8,34 @@ use std::{ use oxc_span::Span; +#[derive(Debug, Clone, Copy, Eq, PartialEq)] +pub enum CommentKind { + Line, + Block, +} + /// Single or multiline comment #[derive(Debug, Clone, Copy)] pub struct Comment { - pub kind: CommentKind, /// The span of the comment text (without leading/trailing delimiters). pub span: Span, + + pub kind: CommentKind, } impl Comment { #[inline] pub fn new(start: u32, end: u32, kind: CommentKind) -> Self { let span = Span::new(start, end); - Self { kind, span } + Self { span, kind } + } + + pub fn is_line(self) -> bool { + self.kind == CommentKind::Line + } + + pub fn is_block(self) -> bool { + self.kind == CommentKind::Block } pub fn real_span(&self) -> Span { @@ -29,36 +44,18 @@ impl Comment { pub fn real_span_end(&self) -> u32 { match self.kind { - CommentKind::SingleLine => self.span.end, + CommentKind::Line => self.span.end, // length of `*/` - CommentKind::MultiLine => self.span.end + 2, + CommentKind::Block => self.span.end + 2, } } pub fn real_span_start(&self) -> u32 { - match self.kind { - CommentKind::SingleLine | CommentKind::MultiLine => self.span.start - 2, - } + self.span.start - 2 } } -#[derive(Debug, Clone, Copy, Eq, PartialEq)] -pub enum CommentKind { - SingleLine, - MultiLine, -} - -impl CommentKind { - #[inline] - pub fn is_single_line(self) -> bool { - self == Self::SingleLine - } - - #[inline] - pub fn is_multi_line(self) -> bool { - self == Self::MultiLine - } -} +impl CommentKind {} /// Sorted set of unique trivia comments, in ascending order by starting position. pub type SortedComments = Box<[Comment]>; @@ -192,11 +189,11 @@ mod test { #[test] fn test_comments_range() { let comments: SortedComments = vec![ - Comment { span: Span::new(0, 4), kind: CommentKind::SingleLine }, - Comment { span: Span::new(5, 9), kind: CommentKind::SingleLine }, - Comment { span: Span::new(10, 13), kind: CommentKind::SingleLine }, - Comment { span: Span::new(14, 17), kind: CommentKind::SingleLine }, - Comment { span: Span::new(18, 23), kind: CommentKind::SingleLine }, + Comment::new(0, 4, CommentKind::Line), + Comment::new(5, 9, CommentKind::Line), + Comment::new(10, 13, CommentKind::Line), + Comment::new(14, 17, CommentKind::Line), + Comment::new(18, 23, CommentKind::Line), ] .into_boxed_slice(); let full_len = comments.len(); diff --git a/crates/oxc_codegen/src/annotation_comment.rs b/crates/oxc_codegen/src/annotation_comment.rs index 257ffebce4dbf..f05bdcc87410f 100644 --- a/crates/oxc_codegen/src/annotation_comment.rs +++ b/crates/oxc_codegen/src/annotation_comment.rs @@ -106,7 +106,7 @@ impl<'a> Codegen<'a> { } self.update_last_consumed_comment_end(real_span_end); match comment.kind() { - CommentKind::SingleLine => { + CommentKind::Line => { self.print_str("//"); self.print_range_of_source_code( comment_span.start as usize..comment_span.end as usize, @@ -114,7 +114,7 @@ impl<'a> Codegen<'a> { self.print_soft_newline(); self.print_indent(); } - CommentKind::MultiLine => { + CommentKind::Block => { self.print_str("/*"); self.print_range_of_source_code( comment_span.start as usize..comment_span.end as usize, diff --git a/crates/oxc_diagnostics/src/graphic_reporter.rs b/crates/oxc_diagnostics/src/graphic_reporter.rs index 13f66c7979fa0..82961bb3b9895 100644 --- a/crates/oxc_diagnostics/src/graphic_reporter.rs +++ b/crates/oxc_diagnostics/src/graphic_reporter.rs @@ -642,14 +642,14 @@ impl GraphicalReportHandler { max_gutter, line, labels, - LabelRenderMode::MultiLineFirst, + LabelRenderMode::BlockFirst, )?; self.render_multi_line_end_single( f, first, label.style, - LabelRenderMode::MultiLineFirst, + LabelRenderMode::BlockFirst, )?; for label_line in rest { // no line number! @@ -660,13 +660,13 @@ impl GraphicalReportHandler { max_gutter, line, labels, - LabelRenderMode::MultiLineRest, + LabelRenderMode::BlockRest, )?; self.render_multi_line_end_single( f, label_line, label.style, - LabelRenderMode::MultiLineRest, + LabelRenderMode::BlockRest, )?; } } @@ -764,7 +764,7 @@ impl GraphicalReportHandler { let applicable = highlights.iter().filter(|hl| line.span_applies_gutter(hl)); for (i, hl) in applicable.enumerate() { if !line.span_line_only(hl) && line.span_ends(hl) { - if render_mode == LabelRenderMode::MultiLineRest { + if render_mode == LabelRenderMode::BlockRest { // this is to make multiline labels work. We want to make the right amount // of horizontal space for them, but not actually draw the lines let horizontal_space = max_gutter.saturating_sub(i) + 2; @@ -792,7 +792,7 @@ impl GraphicalReportHandler { num_repeat // if we are rendering a multiline label, then leave a bit of space for the // rcross character - - if render_mode == LabelRenderMode::MultiLineFirst { + - if render_mode == LabelRenderMode::BlockFirst { 1 } else { 0 @@ -1039,9 +1039,9 @@ impl GraphicalReportHandler { hl, label_line, if first { - LabelRenderMode::MultiLineFirst + LabelRenderMode::BlockFirst } else { - LabelRenderMode::MultiLineRest + LabelRenderMode::BlockRest }, )?; first = false; @@ -1090,10 +1090,10 @@ impl GraphicalReportHandler { LabelRenderMode::SingleLine => { format!("{}{} {}", chars.lbot, chars.hbar.to_string().repeat(2), label,) } - LabelRenderMode::MultiLineFirst => { + LabelRenderMode::BlockFirst => { format!("{}{}{} {}", chars.lbot, chars.hbar, chars.rcross, label,) } - LabelRenderMode::MultiLineRest => { + LabelRenderMode::BlockRest => { format!(" {} {}", chars.vbar, label,) } }; @@ -1115,10 +1115,10 @@ impl GraphicalReportHandler { LabelRenderMode::SingleLine => { writeln!(f, "{} {}", self.theme.characters.hbar.style(style), label)?; } - LabelRenderMode::MultiLineFirst => { + LabelRenderMode::BlockFirst => { writeln!(f, "{} {}", self.theme.characters.rcross.style(style), label)?; } - LabelRenderMode::MultiLineRest => { + LabelRenderMode::BlockRest => { writeln!(f, "{} {}", self.theme.characters.vbar.style(style), label)?; } } @@ -1206,9 +1206,9 @@ enum LabelRenderMode { /// we're rendering a single line label (or not rendering in any special way) SingleLine, /// we're rendering a multiline label - MultiLineFirst, + BlockFirst, /// we're rendering the rest of a multiline label - MultiLineRest, + BlockRest, } #[derive(Debug)] diff --git a/crates/oxc_linter/src/rules/eslint/max_lines.rs b/crates/oxc_linter/src/rules/eslint/max_lines.rs index f62f2fe9fe920..1f6a3955b0d44 100644 --- a/crates/oxc_linter/src/rules/eslint/max_lines.rs +++ b/crates/oxc_linter/src/rules/eslint/max_lines.rs @@ -83,7 +83,7 @@ impl Rule for MaxLines { let comment_lines = if self.skip_comments { let mut comment_lines: usize = 0; for comment in ctx.semantic().trivias().comments() { - if comment.kind.is_single_line() { + if comment.is_line() { let comment_line = ctx.source_text()[..comment.span.start as usize] .lines() .next_back() diff --git a/crates/oxc_linter/src/rules/typescript/ban_ts_comment.rs b/crates/oxc_linter/src/rules/typescript/ban_ts_comment.rs index 2c4ae6c3fb1b4..da5a063264d02 100644 --- a/crates/oxc_linter/src/rules/typescript/ban_ts_comment.rs +++ b/crates/oxc_linter/src/rules/typescript/ban_ts_comment.rs @@ -155,10 +155,10 @@ impl Rule for BanTsComment { let comments = ctx.semantic().trivias().comments(); for comm in comments { let raw = ctx.source_range(comm.span); - if let Some(captures) = find_ts_comment_directive(raw, comm.kind.is_single_line()) { + if let Some(captures) = find_ts_comment_directive(raw, comm.is_line()) { // safe to unwrap, if capture success, it can always capture one of the four directives let (directive, description) = (captures.0, captures.1); - if CommentKind::MultiLine == comm.kind + if CommentKind::Block == comm.kind && (directive == "check" || directive == "nocheck") { continue; diff --git a/crates/oxc_linter/src/rules/typescript/ban_tslint_comment.rs b/crates/oxc_linter/src/rules/typescript/ban_tslint_comment.rs index fd10b5effc0f6..be50f9de759e4 100644 --- a/crates/oxc_linter/src/rules/typescript/ban_tslint_comment.rs +++ b/crates/oxc_linter/src/rules/typescript/ban_tslint_comment.rs @@ -44,7 +44,7 @@ impl Rule for BanTslintComment { source_text_len, comment.span.start, comment.span.end, - comment.kind.is_multi_line(), + comment.is_block(), ); ctx.diagnostic_with_fix( diff --git a/crates/oxc_linter/src/rules/typescript/prefer_function_type.rs b/crates/oxc_linter/src/rules/typescript/prefer_function_type.rs index 3d146c0d5cef1..1f329e68e2b1e 100644 --- a/crates/oxc_linter/src/rules/typescript/prefer_function_type.rs +++ b/crates/oxc_linter/src/rules/typescript/prefer_function_type.rs @@ -173,12 +173,12 @@ fn check_member(member: &TSSignature, node: &AstNode<'_>, ctx: &LintContext<'_>) [span.start as usize..span.end as usize]; match comment_interface.kind { - CommentKind::SingleLine => { + CommentKind::Line => { let single_line_comment: String = format!("//{comment}\n"); comments_vec.push(single_line_comment); } - CommentKind::MultiLine => { + CommentKind::Block => { let multi_line_comment: String = format!("/*{comment}*/\n"); comments_vec.push(multi_line_comment); diff --git a/crates/oxc_linter/src/rules/typescript/prefer_ts_expect_error.rs b/crates/oxc_linter/src/rules/typescript/prefer_ts_expect_error.rs index 251ab57ef46ff..c2fade16e69f0 100644 --- a/crates/oxc_linter/src/rules/typescript/prefer_ts_expect_error.rs +++ b/crates/oxc_linter/src/rules/typescript/prefer_ts_expect_error.rs @@ -1,5 +1,5 @@ use cow_utils::CowUtils; -use oxc_ast::CommentKind; +use oxc_ast::Comment; use oxc_diagnostics::OxcDiagnostic; use oxc_macros::declare_oxc_lint; use oxc_span::Span; @@ -50,11 +50,11 @@ impl Rule for PreferTsExpectError { for comment in comments { let raw = comment.span.source_text(ctx.semantic().source_text()); - if !is_valid_ts_ignore_present(comment.kind, raw) { + if !is_valid_ts_ignore_present(*comment, raw) { continue; } - if comment.kind.is_single_line() { + if comment.is_line() { let comment_span = Span::new(comment.span.start - 2, comment.span.end); ctx.diagnostic_with_fix(prefer_ts_expect_error_diagnostic(comment_span), |fixer| { fixer.replace( @@ -79,18 +79,18 @@ impl Rule for PreferTsExpectError { } } -fn get_last_comment_line(comment: CommentKind, raw: &str) -> String { - if comment.is_single_line() { +fn get_last_comment_line(comment: Comment, raw: &str) -> String { + if comment.is_line() { return String::from(raw); } return String::from(raw.lines().last().unwrap_or(raw)); } -fn is_valid_ts_ignore_present(comment: CommentKind, raw: &str) -> bool { +fn is_valid_ts_ignore_present(comment: Comment, raw: &str) -> bool { let line = get_last_comment_line(comment, raw); - if comment.is_single_line() { + if comment.is_line() { test_single_line_comment(&line) } else { test_multi_line_comment(&line) diff --git a/crates/oxc_linter/src/rules/unicorn/no_empty_file.rs b/crates/oxc_linter/src/rules/unicorn/no_empty_file.rs index f658cdc92399a..202212029e90f 100644 --- a/crates/oxc_linter/src/rules/unicorn/no_empty_file.rs +++ b/crates/oxc_linter/src/rules/unicorn/no_empty_file.rs @@ -70,7 +70,7 @@ impl Rule for NoEmptyFile { fn has_triple_slash_directive(ctx: &LintContext<'_>) -> bool { for comment in ctx.semantic().trivias().comments() { - if !comment.kind.is_single_line() { + if !comment.is_line() { continue; } let text = comment.span.source_text(ctx.source_text()); diff --git a/crates/oxc_linter/src/utils/tree_shaking.rs b/crates/oxc_linter/src/utils/tree_shaking.rs index 86ddbc190e6a1..0f6f83dd5f738 100644 --- a/crates/oxc_linter/src/utils/tree_shaking.rs +++ b/crates/oxc_linter/src/utils/tree_shaking.rs @@ -299,7 +299,7 @@ pub fn get_leading_tree_shaking_comment<'a>(span: Span, ctx: &LintContext<'a>) - ctx.source_text()[..comment.span.end as usize].lines().next_back().unwrap_or(""); let nothing_before_comment = previous_line .trim() - .strip_prefix(if comment.kind == CommentKind::SingleLine { "//" } else { "/*" }) + .strip_prefix(if comment.kind == CommentKind::Line { "//" } else { "/*" }) .is_some_and(|s| s.trim().is_empty()); if !nothing_before_comment { return None; diff --git a/crates/oxc_parser/src/lexer/trivia_builder.rs b/crates/oxc_parser/src/lexer/trivia_builder.rs index 1e6ed86543176..bb724ea0b70a4 100644 --- a/crates/oxc_parser/src/lexer/trivia_builder.rs +++ b/crates/oxc_parser/src/lexer/trivia_builder.rs @@ -17,12 +17,12 @@ impl TriviaBuilder { pub fn add_single_line_comment(&mut self, start: u32, end: u32) { // skip leading `//` - self.add_comment(Comment::new(start + 2, end, CommentKind::SingleLine)); + self.add_comment(Comment::new(start + 2, end, CommentKind::Line)); } pub fn add_multi_line_comment(&mut self, start: u32, end: u32) { // skip leading `/*` and trailing `*/` - self.add_comment(Comment::new(start + 2, end - 2, CommentKind::MultiLine)); + self.add_comment(Comment::new(start + 2, end - 2, CommentKind::Block)); } fn add_comment(&mut self, comment: Comment) { diff --git a/crates/oxc_parser/src/lib.rs b/crates/oxc_parser/src/lib.rs index 61b7865a74cc5..e7a83562b1fd8 100644 --- a/crates/oxc_parser/src/lib.rs +++ b/crates/oxc_parser/src/lib.rs @@ -510,11 +510,11 @@ mod test { let allocator = Allocator::default(); let source_type = SourceType::default().with_typescript(true); let sources = [ - ("// line comment", CommentKind::SingleLine), - ("/* line comment */", CommentKind::MultiLine), + ("// line comment", CommentKind::Line), + ("/* line comment */", CommentKind::Block), ( "type Foo = ( /* Require properties which are not generated automatically. */ 'bar')", - CommentKind::MultiLine, + CommentKind::Block, ), ]; for (source, kind) in sources { diff --git a/crates/oxc_prettier/src/comments/mod.rs b/crates/oxc_prettier/src/comments/mod.rs index a28d744eb8368..6d702961e5338 100644 --- a/crates/oxc_prettier/src/comments/mod.rs +++ b/crates/oxc_prettier/src/comments/mod.rs @@ -18,7 +18,7 @@ impl Comment { Self { start: span.start, end: span.end, - is_block: comment.kind.is_multi_line(), + is_block: comment.is_block(), has_line_suffix: false, } } diff --git a/crates/oxc_semantic/src/jsdoc/builder.rs b/crates/oxc_semantic/src/jsdoc/builder.rs index 2ef409ab853f2..e551381c8e045 100644 --- a/crates/oxc_semantic/src/jsdoc/builder.rs +++ b/crates/oxc_semantic/src/jsdoc/builder.rs @@ -147,7 +147,7 @@ impl<'a> JSDocBuilder<'a> { } fn parse_if_jsdoc_comment(&self, comment: &Comment) -> Option> { - if !comment.kind.is_multi_line() { + if !comment.is_block() { return None; } diff --git a/crates/oxc_wasm/src/lib.rs b/crates/oxc_wasm/src/lib.rs index 110d889eb75ff..e9c42d4d191c5 100644 --- a/crates/oxc_wasm/src/lib.rs +++ b/crates/oxc_wasm/src/lib.rs @@ -420,8 +420,8 @@ impl Oxc { .comments() .map(|comment| Comment { r#type: match comment.kind { - CommentKind::SingleLine => CommentType::Line, - CommentKind::MultiLine => CommentType::Block, + CommentKind::Line => CommentType::Line, + CommentKind::Block => CommentType::Block, }, value: comment.span.source_text(source_text).to_string(), start: comment.span.start, diff --git a/napi/parser/src/lib.rs b/napi/parser/src/lib.rs index 4b439efa69758..87b716ea43f32 100644 --- a/napi/parser/src/lib.rs +++ b/napi/parser/src/lib.rs @@ -109,8 +109,8 @@ fn parse_with_return<'a>(source_text: &'a str, options: &ParserOptions) -> Parse .comments() .map(|comment| Comment { r#type: match comment.kind { - CommentKind::SingleLine => "Line", - CommentKind::MultiLine => "Block", + CommentKind::Line => "Line", + CommentKind::Block => "Block", }, value: comment.span.source_text(source_text).to_string(), start: comment.span.start,