Skip to content

Commit 4c95de1

Browse files
committed
feat(ast, parser, codegen): add CommentKind::MultineBlock
1 parent 09ca386 commit 4c95de1

File tree

19 files changed

+84
-39
lines changed

19 files changed

+84
-39
lines changed

apps/oxlint/src-js/generated/deserialize.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5651,6 +5651,8 @@ function deserializeCommentKind(pos) {
56515651
return "Line";
56525652
case 1:
56535653
return "Block";
5654+
case 2:
5655+
return "Block";
56545656
default:
56555657
throw Error(`Unexpected discriminant ${uint8[pos]} for CommentKind`);
56565658
}

crates/oxc_ast/src/ast/comment.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ pub enum CommentKind {
1717
Line = 0,
1818
/// Block comment
1919
Block = 1,
20+
/// Multiline block comment (contains line breaks)
21+
#[estree(rename = "Block")]
22+
MultilineBlock = 2,
2023
}
2124

2225
/// Information about a comment's position relative to a token.
@@ -172,7 +175,9 @@ impl Comment {
172175
pub fn content_span(&self) -> Span {
173176
match self.kind {
174177
CommentKind::Line => Span::new(self.span.start + 2, self.span.end),
175-
CommentKind::Block => Span::new(self.span.start + 2, self.span.end - 2),
178+
CommentKind::Block | CommentKind::MultilineBlock => {
179+
Span::new(self.span.start + 2, self.span.end - 2)
180+
}
176181
}
177182
}
178183

@@ -185,7 +190,13 @@ impl Comment {
185190
/// Returns `true` if this is a block comment.
186191
#[inline]
187192
pub fn is_block(self) -> bool {
188-
self.kind == CommentKind::Block
193+
matches!(self.kind, CommentKind::Block | CommentKind::MultilineBlock)
194+
}
195+
196+
/// Returns `true` if this is a multi-line block comment.
197+
#[inline]
198+
pub fn is_multiline_block(self) -> bool {
199+
self.kind == CommentKind::MultilineBlock
189200
}
190201

191202
/// Returns `true` if this comment is before a token.

crates/oxc_ast/src/generated/derive_estree.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3234,6 +3234,7 @@ impl ESTree for CommentKind {
32343234
match self {
32353235
Self::Line => JsonSafeString("Line").serialize(serializer),
32363236
Self::Block => JsonSafeString("Block").serialize(serializer),
3237+
Self::MultilineBlock => JsonSafeString("Block").serialize(serializer),
32373238
}
32383239
}
32393240
}

crates/oxc_codegen/src/comment.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
use std::borrow::Cow;
22

3+
use oxc_syntax::line_terminator::LineTerminatorSplitter;
34
use rustc_hash::{FxHashMap, FxHashSet};
45

56
use oxc_ast::{Comment, CommentKind, ast::Program};
6-
use oxc_syntax::line_terminator::{LineTerminatorSplitter, is_line_terminator};
77

88
use crate::{Codegen, LegalComment, options::CommentOptions};
99

@@ -128,10 +128,10 @@ impl Codegen<'_> {
128128
};
129129
let comment_source = comment.span.source_text(source_text);
130130
match comment.kind {
131-
CommentKind::Line => {
131+
CommentKind::Line | CommentKind::Block => {
132132
self.print_str_escaping_script_close_tag(comment_source);
133133
}
134-
CommentKind::Block => {
134+
CommentKind::MultilineBlock => {
135135
for line in LineTerminatorSplitter::new(comment_source) {
136136
if !line.starts_with("/*") {
137137
self.print_indent();
@@ -163,7 +163,7 @@ impl Codegen<'_> {
163163
let source_text = program.source_text;
164164
for comment in program.comments.iter().filter(|c| c.is_legal()) {
165165
let mut text = Cow::Borrowed(comment.span.source_text(source_text));
166-
if comment.is_block() && text.contains(is_line_terminator) {
166+
if comment.is_multiline_block() {
167167
let mut buffer = String::with_capacity(text.len());
168168
// Print block comments with our own indentation.
169169
for line in LineTerminatorSplitter::new(&text) {

crates/oxc_formatter/src/formatter/trivia.rs

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -115,28 +115,31 @@ impl<'a> Format<'a> for FormatLeadingComments<'a> {
115115
write!(f, comment);
116116

117117
match comment.kind {
118-
CommentKind::Block => match f.source_text().lines_after(comment.span.end) {
119-
0 => {
120-
let should_nestle =
121-
leading_comments_iter.peek().is_some_and(|next_comment| {
122-
should_nestle_adjacent_doc_comments(
123-
comment,
124-
next_comment,
125-
f.source_text(),
126-
)
127-
});
128-
129-
write!(f, [maybe_space(!should_nestle)]);
130-
}
131-
1 => {
132-
if f.source_text().get_lines_before(comment.span, f.comments()) == 0 {
133-
write!(f, [soft_line_break_or_space()]);
134-
} else {
135-
write!(f, [hard_line_break()]);
118+
CommentKind::Block | CommentKind::MultilineBlock => {
119+
match f.source_text().lines_after(comment.span.end) {
120+
0 => {
121+
let should_nestle =
122+
leading_comments_iter.peek().is_some_and(|next_comment| {
123+
should_nestle_adjacent_doc_comments(
124+
comment,
125+
next_comment,
126+
f.source_text(),
127+
)
128+
});
129+
130+
write!(f, [maybe_space(!should_nestle)]);
131+
}
132+
1 => {
133+
if f.source_text().get_lines_before(comment.span, f.comments()) == 0
134+
{
135+
write!(f, [soft_line_break_or_space()]);
136+
} else {
137+
write!(f, [hard_line_break()]);
138+
}
136139
}
140+
_ => write!(f, [empty_line()]),
137141
}
138-
_ => write!(f, [empty_line()]),
139-
},
142+
}
140143
CommentKind::Line => match f.source_text().lines_after(comment.span.end) {
141144
0 | 1 => write!(f, [hard_line_break()]),
142145
_ => write!(f, [empty_line()]),

crates/oxc_linter/src/rules/typescript/ban_ts_comment.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use cow_utils::CowUtils;
22
use lazy_regex::Regex;
3-
use oxc_ast::CommentKind;
43
use oxc_diagnostics::OxcDiagnostic;
54
use oxc_macros::declare_oxc_lint;
65
use oxc_span::Span;
@@ -193,9 +192,7 @@ impl Rule for BanTsComment {
193192
if let Some(captures) = find_ts_comment_directive(raw, comm.is_line()) {
194193
// safe to unwrap, if capture success, it can always capture one of the four directives
195194
let (directive, description) = (captures.0, captures.1);
196-
if CommentKind::Block == comm.kind
197-
&& (directive == "check" || directive == "nocheck")
198-
{
195+
if comm.is_block() && (directive == "check" || directive == "nocheck") {
199196
continue;
200197
}
201198

crates/oxc_linter/src/rules/typescript/prefer_function_type.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ fn check_member(member: &TSSignature, node: &AstNode<'_>, ctx: &LintContext<'_>)
174174
let single_line_comment: String = format!("//{comment}\n");
175175
comments_vec.push(single_line_comment);
176176
}
177-
CommentKind::Block => {
177+
CommentKind::Block | CommentKind::MultilineBlock => {
178178
let multi_line_comment: String = format!("/*{comment}*/\n");
179179
comments_vec.push(multi_line_comment);
180180
}

crates/oxc_napi/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ pub fn convert_utf8_to_utf16(
3333
Comment {
3434
r#type: match comment.kind {
3535
CommentKind::Line => String::from("Line"),
36-
CommentKind::Block => String::from("Block"),
36+
CommentKind::Block | CommentKind::MultilineBlock => String::from("Block"),
3737
},
3838
value,
3939
start: span.start,

crates/oxc_parser/src/lexer/comment.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use memchr::memmem::Finder;
22

3+
use oxc_ast::CommentKind;
34
use oxc_syntax::line_terminator::is_line_terminator;
45

56
use crate::diagnostics;
@@ -82,9 +83,13 @@ impl<'a> Lexer<'a> {
8283
/// Section 12.4 Multi Line Comment
8384
pub(super) fn skip_multi_line_comment(&mut self) -> Kind {
8485
// If `is_on_new_line` is already set, go directly to faster search which only looks for `*/`
85-
if self.token.is_on_new_line() {
86-
return self.skip_multi_line_comment_after_line_break(self.source.position());
87-
}
86+
// We need to identify if comment contains line breaks or not
87+
// (`CommentKind::Block` or `CommentKind::MultilineBlock`).
88+
// So we have to use the loop below for the first line of the comment even if
89+
// `Token`'s `is_on_new_line` flag is already set.
90+
// If the loop finds a line break before end of the comment, we then switch to
91+
// the faster `skip_multi_line_comment_after_line_break` which searches
92+
// for the end of the comment using `memchr`.
8893

8994
byte_search! {
9095
lexer: self,
@@ -149,6 +154,7 @@ impl<'a> Lexer<'a> {
149154
self.trivia_builder.add_block_comment(
150155
self.token.start(),
151156
self.offset(),
157+
CommentKind::Block,
152158
self.source.whole(),
153159
);
154160
Kind::Skip
@@ -170,6 +176,7 @@ impl<'a> Lexer<'a> {
170176
self.trivia_builder.add_block_comment(
171177
self.token.start(),
172178
self.offset(),
179+
CommentKind::MultilineBlock,
173180
self.source.whole(),
174181
);
175182
Kind::Skip

crates/oxc_parser/src/lexer/trivia_builder.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,14 @@ impl TriviaBuilder {
5959
self.add_comment(Comment::new(start, end, CommentKind::Line), source_text);
6060
}
6161

62-
pub fn add_block_comment(&mut self, start: u32, end: u32, source_text: &str) {
63-
self.add_comment(Comment::new(start, end, CommentKind::Block), source_text);
62+
pub fn add_block_comment(
63+
&mut self,
64+
start: u32,
65+
end: u32,
66+
kind: CommentKind,
67+
source_text: &str,
68+
) {
69+
self.add_comment(Comment::new(start, end, kind), source_text);
6470
}
6571

6672
// For block comments only. This function is not called after line comments because the lexer skips
@@ -425,15 +431,15 @@ token /* Trailing 1 */
425431
let expected = vec![
426432
Comment {
427433
span: Span::new(1, 13),
428-
kind: CommentKind::Block,
434+
kind: CommentKind::MultilineBlock,
429435
position: CommentPosition::Leading,
430436
attached_to: 28,
431437
newlines: CommentNewlines::Leading | CommentNewlines::Trailing,
432438
content: CommentContent::None,
433439
},
434440
Comment {
435441
span: Span::new(14, 26),
436-
kind: CommentKind::Block,
442+
kind: CommentKind::MultilineBlock,
437443
position: CommentPosition::Leading,
438444
attached_to: 28,
439445
newlines: CommentNewlines::Leading | CommentNewlines::Trailing,

0 commit comments

Comments
 (0)