Skip to content

Commit

Permalink
fix(parser): should regard comments where after = as leading commen…
Browse files Browse the repository at this point in the history
…ts of next token (#6355)

A part of fixing https://github.com/rolldown/rolldown/pull/2375/files#r1789011257

### Compare to `Babel`
This is also among its behavior, see

<img width="1470" alt="image" src="https://github.com/user-attachments/assets/1b1f9c78-3e44-495d-b2f7-38e6c3bc8bf1">

### Compare to `esbuild`

I haven't looked through related code from esbuild, from its playground, the behavior looks the same

https://esbuild.github.io/try/#dAAwLjI0LjAAAGNvbnN0IEEgPSAvLyBzZGRkZGQKKCkgPT4ge30
  • Loading branch information
Dunqing committed Oct 8, 2024
1 parent 62d45bf commit 1380d8b
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 6 deletions.
2 changes: 1 addition & 1 deletion crates/oxc_parser/src/lexer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ impl<'a> Lexer<'a> {
self.token.end = self.offset();
debug_assert!(self.token.start <= self.token.end);
let token = self.token;
self.trivia_builder.handle_token(token.start);
self.trivia_builder.handle_token(token);
self.token = Token::default();
token
}
Expand Down
53 changes: 48 additions & 5 deletions crates/oxc_parser/src/lexer/trivia_builder.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use oxc_ast::{Comment, CommentKind, CommentPosition, Trivias};
use oxc_span::Span;

use super::{Kind, Token};

#[derive(Debug)]
pub struct TriviaBuilder {
// This is a set of unique comments. Duplicated
Expand All @@ -16,11 +18,20 @@ pub struct TriviaBuilder {

/// Saw a newline before this position
saw_newline: bool,

/// Previous token kind, used to indicates comments are trailing from what kind
previous_kind: Kind,
}

impl Default for TriviaBuilder {
fn default() -> Self {
Self { comments: vec![], irregular_whitespaces: vec![], processed: 0, saw_newline: true }
Self {
comments: vec![],
irregular_whitespaces: vec![],
processed: 0,
saw_newline: true,
previous_kind: Kind::Undetermined,
}
}
}

Expand Down Expand Up @@ -57,13 +68,14 @@ impl TriviaBuilder {
self.saw_newline = true;
}

pub fn handle_token(&mut self, token_start: u32) {
pub fn handle_token(&mut self, token: Token) {
let len = self.comments.len();
self.previous_kind = token.kind;
if self.processed < len {
// All unprocessed preceding comments are leading comments attached to this token start.
for comment in &mut self.comments[self.processed..] {
comment.position = CommentPosition::Leading;
comment.attached_to = token_start;
comment.attached_to = token.start;
}
self.processed = len;
}
Expand All @@ -85,8 +97,8 @@ impl TriviaBuilder {
if comment.is_line() {
// A line comment is always followed by a newline. This is never set in `handle_newline`.
comment.followed_by_newline = true;
// A line comment is trailing when it is no preceded by a newline.
if !self.saw_newline {
// A line comment is trailing when it is no preceded by a newline and it is not after `=`
if !self.saw_newline && self.previous_kind != Kind::Eq {
self.processed = self.comments.len() + 1; // +1 to include this comment.
}
self.saw_newline = true;
Expand Down Expand Up @@ -236,4 +248,35 @@ token /* Trailing 1 */
];
assert_eq!(comments, expected);
}

#[test]
fn leading_comments_after_eq() {
let source_text = "
const v1 = // Leading comment 1
foo();
function foo(param =// Leading comment 2
new Foo()
) {}
";
let comments = get_comments(source_text);
let expected = vec![
Comment {
span: Span::new(26, 44),
kind: CommentKind::Line,
position: CommentPosition::Leading,
attached_to: 57,
preceded_by_newline: false,
followed_by_newline: true,
},
Comment {
span: Span::new(98, 116),
kind: CommentKind::Line,
position: CommentPosition::Leading,
attached_to: 129,
preceded_by_newline: false,
followed_by_newline: true,
},
];
assert_eq!(comments, expected);
}
}

0 comments on commit 1380d8b

Please sign in to comment.