refactor(ast): change Comment struct (#5783)

This commit is contained in:
Boshen 2024-09-15 09:22:58 +00:00
parent 512be65fa7
commit 6dd6f7ca26
16 changed files with 68 additions and 71 deletions

View file

@ -8,19 +8,34 @@ use std::{
use oxc_span::Span; use oxc_span::Span;
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub enum CommentKind {
Line,
Block,
}
/// Single or multiline comment /// Single or multiline comment
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub struct Comment { pub struct Comment {
pub kind: CommentKind,
/// The span of the comment text (without leading/trailing delimiters). /// The span of the comment text (without leading/trailing delimiters).
pub span: Span, pub span: Span,
pub kind: CommentKind,
} }
impl Comment { impl Comment {
#[inline] #[inline]
pub fn new(start: u32, end: u32, kind: CommentKind) -> Self { pub fn new(start: u32, end: u32, kind: CommentKind) -> Self {
let span = Span::new(start, end); 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 { pub fn real_span(&self) -> Span {
@ -29,36 +44,18 @@ impl Comment {
pub fn real_span_end(&self) -> u32 { pub fn real_span_end(&self) -> u32 {
match self.kind { match self.kind {
CommentKind::SingleLine => self.span.end, CommentKind::Line => self.span.end,
// length of `*/` // length of `*/`
CommentKind::MultiLine => self.span.end + 2, CommentKind::Block => self.span.end + 2,
} }
} }
pub fn real_span_start(&self) -> u32 { pub fn real_span_start(&self) -> u32 {
match self.kind { self.span.start - 2
CommentKind::SingleLine | CommentKind::MultiLine => self.span.start - 2,
}
} }
} }
#[derive(Debug, Clone, Copy, Eq, PartialEq)] impl CommentKind {}
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
}
}
/// Sorted set of unique trivia comments, in ascending order by starting position. /// Sorted set of unique trivia comments, in ascending order by starting position.
pub type SortedComments = Box<[Comment]>; pub type SortedComments = Box<[Comment]>;
@ -192,11 +189,11 @@ mod test {
#[test] #[test]
fn test_comments_range() { fn test_comments_range() {
let comments: SortedComments = vec![ let comments: SortedComments = vec![
Comment { span: Span::new(0, 4), kind: CommentKind::SingleLine }, Comment::new(0, 4, CommentKind::Line),
Comment { span: Span::new(5, 9), kind: CommentKind::SingleLine }, Comment::new(5, 9, CommentKind::Line),
Comment { span: Span::new(10, 13), kind: CommentKind::SingleLine }, Comment::new(10, 13, CommentKind::Line),
Comment { span: Span::new(14, 17), kind: CommentKind::SingleLine }, Comment::new(14, 17, CommentKind::Line),
Comment { span: Span::new(18, 23), kind: CommentKind::SingleLine }, Comment::new(18, 23, CommentKind::Line),
] ]
.into_boxed_slice(); .into_boxed_slice();
let full_len = comments.len(); let full_len = comments.len();

View file

@ -106,7 +106,7 @@ impl<'a> Codegen<'a> {
} }
self.update_last_consumed_comment_end(real_span_end); self.update_last_consumed_comment_end(real_span_end);
match comment.kind() { match comment.kind() {
CommentKind::SingleLine => { CommentKind::Line => {
self.print_str("//"); self.print_str("//");
self.print_range_of_source_code( self.print_range_of_source_code(
comment_span.start as usize..comment_span.end as usize, comment_span.start as usize..comment_span.end as usize,
@ -114,7 +114,7 @@ impl<'a> Codegen<'a> {
self.print_soft_newline(); self.print_soft_newline();
self.print_indent(); self.print_indent();
} }
CommentKind::MultiLine => { CommentKind::Block => {
self.print_str("/*"); self.print_str("/*");
self.print_range_of_source_code( self.print_range_of_source_code(
comment_span.start as usize..comment_span.end as usize, comment_span.start as usize..comment_span.end as usize,

View file

@ -642,14 +642,14 @@ impl GraphicalReportHandler {
max_gutter, max_gutter,
line, line,
labels, labels,
LabelRenderMode::MultiLineFirst, LabelRenderMode::BlockFirst,
)?; )?;
self.render_multi_line_end_single( self.render_multi_line_end_single(
f, f,
first, first,
label.style, label.style,
LabelRenderMode::MultiLineFirst, LabelRenderMode::BlockFirst,
)?; )?;
for label_line in rest { for label_line in rest {
// no line number! // no line number!
@ -660,13 +660,13 @@ impl GraphicalReportHandler {
max_gutter, max_gutter,
line, line,
labels, labels,
LabelRenderMode::MultiLineRest, LabelRenderMode::BlockRest,
)?; )?;
self.render_multi_line_end_single( self.render_multi_line_end_single(
f, f,
label_line, label_line,
label.style, label.style,
LabelRenderMode::MultiLineRest, LabelRenderMode::BlockRest,
)?; )?;
} }
} }
@ -764,7 +764,7 @@ impl GraphicalReportHandler {
let applicable = highlights.iter().filter(|hl| line.span_applies_gutter(hl)); let applicable = highlights.iter().filter(|hl| line.span_applies_gutter(hl));
for (i, hl) in applicable.enumerate() { for (i, hl) in applicable.enumerate() {
if !line.span_line_only(hl) && line.span_ends(hl) { 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 // 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 // of horizontal space for them, but not actually draw the lines
let horizontal_space = max_gutter.saturating_sub(i) + 2; let horizontal_space = max_gutter.saturating_sub(i) + 2;
@ -792,7 +792,7 @@ impl GraphicalReportHandler {
num_repeat num_repeat
// if we are rendering a multiline label, then leave a bit of space for the // if we are rendering a multiline label, then leave a bit of space for the
// rcross character // rcross character
- if render_mode == LabelRenderMode::MultiLineFirst { - if render_mode == LabelRenderMode::BlockFirst {
1 1
} else { } else {
0 0
@ -1039,9 +1039,9 @@ impl GraphicalReportHandler {
hl, hl,
label_line, label_line,
if first { if first {
LabelRenderMode::MultiLineFirst LabelRenderMode::BlockFirst
} else { } else {
LabelRenderMode::MultiLineRest LabelRenderMode::BlockRest
}, },
)?; )?;
first = false; first = false;
@ -1090,10 +1090,10 @@ impl GraphicalReportHandler {
LabelRenderMode::SingleLine => { LabelRenderMode::SingleLine => {
format!("{}{} {}", chars.lbot, chars.hbar.to_string().repeat(2), label,) format!("{}{} {}", chars.lbot, chars.hbar.to_string().repeat(2), label,)
} }
LabelRenderMode::MultiLineFirst => { LabelRenderMode::BlockFirst => {
format!("{}{}{} {}", chars.lbot, chars.hbar, chars.rcross, label,) format!("{}{}{} {}", chars.lbot, chars.hbar, chars.rcross, label,)
} }
LabelRenderMode::MultiLineRest => { LabelRenderMode::BlockRest => {
format!(" {} {}", chars.vbar, label,) format!(" {} {}", chars.vbar, label,)
} }
}; };
@ -1115,10 +1115,10 @@ impl GraphicalReportHandler {
LabelRenderMode::SingleLine => { LabelRenderMode::SingleLine => {
writeln!(f, "{} {}", self.theme.characters.hbar.style(style), label)?; writeln!(f, "{} {}", self.theme.characters.hbar.style(style), label)?;
} }
LabelRenderMode::MultiLineFirst => { LabelRenderMode::BlockFirst => {
writeln!(f, "{} {}", self.theme.characters.rcross.style(style), label)?; writeln!(f, "{} {}", self.theme.characters.rcross.style(style), label)?;
} }
LabelRenderMode::MultiLineRest => { LabelRenderMode::BlockRest => {
writeln!(f, "{} {}", self.theme.characters.vbar.style(style), label)?; 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) /// we're rendering a single line label (or not rendering in any special way)
SingleLine, SingleLine,
/// we're rendering a multiline label /// we're rendering a multiline label
MultiLineFirst, BlockFirst,
/// we're rendering the rest of a multiline label /// we're rendering the rest of a multiline label
MultiLineRest, BlockRest,
} }
#[derive(Debug)] #[derive(Debug)]

View file

@ -83,7 +83,7 @@ impl Rule for MaxLines {
let comment_lines = if self.skip_comments { let comment_lines = if self.skip_comments {
let mut comment_lines: usize = 0; let mut comment_lines: usize = 0;
for comment in ctx.semantic().trivias().comments() { 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] let comment_line = ctx.source_text()[..comment.span.start as usize]
.lines() .lines()
.next_back() .next_back()

View file

@ -155,10 +155,10 @@ impl Rule for BanTsComment {
let comments = ctx.semantic().trivias().comments(); let comments = ctx.semantic().trivias().comments();
for comm in comments { for comm in comments {
let raw = ctx.source_range(comm.span); 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 // safe to unwrap, if capture success, it can always capture one of the four directives
let (directive, description) = (captures.0, captures.1); let (directive, description) = (captures.0, captures.1);
if CommentKind::MultiLine == comm.kind if CommentKind::Block == comm.kind
&& (directive == "check" || directive == "nocheck") && (directive == "check" || directive == "nocheck")
{ {
continue; continue;

View file

@ -44,7 +44,7 @@ impl Rule for BanTslintComment {
source_text_len, source_text_len,
comment.span.start, comment.span.start,
comment.span.end, comment.span.end,
comment.kind.is_multi_line(), comment.is_block(),
); );
ctx.diagnostic_with_fix( ctx.diagnostic_with_fix(

View file

@ -173,12 +173,12 @@ fn check_member(member: &TSSignature, node: &AstNode<'_>, ctx: &LintContext<'_>)
[span.start as usize..span.end as usize]; [span.start as usize..span.end as usize];
match comment_interface.kind { match comment_interface.kind {
CommentKind::SingleLine => { CommentKind::Line => {
let single_line_comment: String = let single_line_comment: String =
format!("//{comment}\n"); format!("//{comment}\n");
comments_vec.push(single_line_comment); comments_vec.push(single_line_comment);
} }
CommentKind::MultiLine => { CommentKind::Block => {
let multi_line_comment: String = let multi_line_comment: String =
format!("/*{comment}*/\n"); format!("/*{comment}*/\n");
comments_vec.push(multi_line_comment); comments_vec.push(multi_line_comment);

View file

@ -1,5 +1,5 @@
use cow_utils::CowUtils; use cow_utils::CowUtils;
use oxc_ast::CommentKind; use oxc_ast::Comment;
use oxc_diagnostics::OxcDiagnostic; use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint; use oxc_macros::declare_oxc_lint;
use oxc_span::Span; use oxc_span::Span;
@ -50,11 +50,11 @@ impl Rule for PreferTsExpectError {
for comment in comments { for comment in comments {
let raw = comment.span.source_text(ctx.semantic().source_text()); 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; continue;
} }
if comment.kind.is_single_line() { if comment.is_line() {
let comment_span = Span::new(comment.span.start - 2, comment.span.end); let comment_span = Span::new(comment.span.start - 2, comment.span.end);
ctx.diagnostic_with_fix(prefer_ts_expect_error_diagnostic(comment_span), |fixer| { ctx.diagnostic_with_fix(prefer_ts_expect_error_diagnostic(comment_span), |fixer| {
fixer.replace( fixer.replace(
@ -79,18 +79,18 @@ impl Rule for PreferTsExpectError {
} }
} }
fn get_last_comment_line(comment: CommentKind, raw: &str) -> String { fn get_last_comment_line(comment: Comment, raw: &str) -> String {
if comment.is_single_line() { if comment.is_line() {
return String::from(raw); return String::from(raw);
} }
return String::from(raw.lines().last().unwrap_or(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); let line = get_last_comment_line(comment, raw);
if comment.is_single_line() { if comment.is_line() {
test_single_line_comment(&line) test_single_line_comment(&line)
} else { } else {
test_multi_line_comment(&line) test_multi_line_comment(&line)

View file

@ -70,7 +70,7 @@ impl Rule for NoEmptyFile {
fn has_triple_slash_directive(ctx: &LintContext<'_>) -> bool { fn has_triple_slash_directive(ctx: &LintContext<'_>) -> bool {
for comment in ctx.semantic().trivias().comments() { for comment in ctx.semantic().trivias().comments() {
if !comment.kind.is_single_line() { if !comment.is_line() {
continue; continue;
} }
let text = comment.span.source_text(ctx.source_text()); let text = comment.span.source_text(ctx.source_text());

View file

@ -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(""); ctx.source_text()[..comment.span.end as usize].lines().next_back().unwrap_or("");
let nothing_before_comment = previous_line let nothing_before_comment = previous_line
.trim() .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()); .is_some_and(|s| s.trim().is_empty());
if !nothing_before_comment { if !nothing_before_comment {
return None; return None;

View file

@ -17,12 +17,12 @@ impl TriviaBuilder {
pub fn add_single_line_comment(&mut self, start: u32, end: u32) { pub fn add_single_line_comment(&mut self, start: u32, end: u32) {
// skip leading `//` // 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) { pub fn add_multi_line_comment(&mut self, start: u32, end: u32) {
// skip leading `/*` and trailing `*/` // 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) { fn add_comment(&mut self, comment: Comment) {

View file

@ -510,11 +510,11 @@ mod test {
let allocator = Allocator::default(); let allocator = Allocator::default();
let source_type = SourceType::default().with_typescript(true); let source_type = SourceType::default().with_typescript(true);
let sources = [ let sources = [
("// line comment", CommentKind::SingleLine), ("// line comment", CommentKind::Line),
("/* line comment */", CommentKind::MultiLine), ("/* line comment */", CommentKind::Block),
( (
"type Foo = ( /* Require properties which are not generated automatically. */ 'bar')", "type Foo = ( /* Require properties which are not generated automatically. */ 'bar')",
CommentKind::MultiLine, CommentKind::Block,
), ),
]; ];
for (source, kind) in sources { for (source, kind) in sources {

View file

@ -18,7 +18,7 @@ impl Comment {
Self { Self {
start: span.start, start: span.start,
end: span.end, end: span.end,
is_block: comment.kind.is_multi_line(), is_block: comment.is_block(),
has_line_suffix: false, has_line_suffix: false,
} }
} }

View file

@ -147,7 +147,7 @@ impl<'a> JSDocBuilder<'a> {
} }
fn parse_if_jsdoc_comment(&self, comment: &Comment) -> Option<JSDoc<'a>> { fn parse_if_jsdoc_comment(&self, comment: &Comment) -> Option<JSDoc<'a>> {
if !comment.kind.is_multi_line() { if !comment.is_block() {
return None; return None;
} }

View file

@ -420,8 +420,8 @@ impl Oxc {
.comments() .comments()
.map(|comment| Comment { .map(|comment| Comment {
r#type: match comment.kind { r#type: match comment.kind {
CommentKind::SingleLine => CommentType::Line, CommentKind::Line => CommentType::Line,
CommentKind::MultiLine => CommentType::Block, CommentKind::Block => CommentType::Block,
}, },
value: comment.span.source_text(source_text).to_string(), value: comment.span.source_text(source_text).to_string(),
start: comment.span.start, start: comment.span.start,

View file

@ -109,8 +109,8 @@ fn parse_with_return<'a>(source_text: &'a str, options: &ParserOptions) -> Parse
.comments() .comments()
.map(|comment| Comment { .map(|comment| Comment {
r#type: match comment.kind { r#type: match comment.kind {
CommentKind::SingleLine => "Line", CommentKind::Line => "Line",
CommentKind::MultiLine => "Block", CommentKind::Block => "Block",
}, },
value: comment.span.source_text(source_text).to_string(), value: comment.span.source_text(source_text).to_string(),
start: comment.span.start, start: comment.span.start,