mirror of
https://github.com/danbulant/oxc
synced 2026-05-19 04:08:41 +00:00
refactor(ast): change Comment struct (#5783)
This commit is contained in:
parent
512be65fa7
commit
6dd6f7ca26
16 changed files with 68 additions and 71 deletions
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -147,7 +147,7 @@ impl<'a> JSDocBuilder<'a> {
|
|||
}
|
||||
|
||||
fn parse_if_jsdoc_comment(&self, comment: &Comment) -> Option<JSDoc<'a>> {
|
||||
if !comment.kind.is_multi_line() {
|
||||
if !comment.is_block() {
|
||||
return None;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Reference in a new issue