Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(parser): should regard comments where after = as leading comments of next token #6355

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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);
}
}