Skip to content

Commit c2ee306

Browse files
committed
refactor(formatter): improve line break detaching logic in SourceText
1 parent 0c8e93c commit c2ee306

File tree

2 files changed

+22
-22
lines changed

2 files changed

+22
-22
lines changed

crates/oxc_formatter/src/formatter/source_text.rs

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -129,13 +129,24 @@ impl<'a> SourceText<'a> {
129129
self.text_for(&span).chars().count()
130130
}
131131

132-
/// Count consecutive line breaks after position
132+
/// Count consecutive line breaks after position, returning `0` if only whitespace follows
133133
pub fn lines_after(&self, end: u32) -> usize {
134-
self.slice_from(end)
135-
.chars()
136-
.filter(|&c| !is_white_space_single_line(c))
137-
.take_while(|&c| is_line_terminator(c))
138-
.count()
134+
let mut count = 0;
135+
for char in self.slice_from(end).chars() {
136+
if is_white_space_single_line(char) {
137+
continue;
138+
}
139+
140+
if is_line_terminator(char) {
141+
count += 1;
142+
continue;
143+
}
144+
145+
return count;
146+
}
147+
148+
// No non-whitespace characters found after position, so return `0` to avoid adding extra new lines
149+
0
139150
}
140151

141152
/// Count line breaks between syntax nodes, considering comments and parentheses
@@ -146,7 +157,7 @@ impl<'a> SourceText<'a> {
146157

147158
// Should skip the leading comments of the node.
148159
if let Some(comment) = comments.first()
149-
&& comment.span.end < start
160+
&& comment.span.end <= start
150161
{
151162
start = comment.span.start;
152163
}
@@ -188,7 +199,7 @@ impl<'a> SourceText<'a> {
188199
count += 1;
189200
}
190201

191-
count
202+
0
192203
}
193204

194205
pub fn is_own_line_comment(&self, comment: &Comment) -> bool {

crates/oxc_formatter/src/write/program.rs

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use oxc_syntax::identifier::{ZWNBSP, is_line_terminator};
77

88
use crate::{
99
Buffer, Format, FormatResult, FormatTrailingCommas, TrailingSeparator, format_args,
10-
formatter::{prelude::*, separated::FormatSeparatedIter, trivia::FormatTrailingComments},
10+
formatter::{prelude::*, trivia::FormatTrailingComments},
1111
generated::ast_nodes::{AstNode, AstNodes},
1212
utils::{
1313
call_expression::is_test_call_expression,
@@ -25,7 +25,7 @@ impl<'a> FormatWrite<'a> for AstNode<'a, Program<'a>> {
2525
fn write(&self, f: &mut Formatter<'_, 'a>) -> FormatResult<()> {
2626
let format_trailing_comments = format_once(|f| {
2727
let comments = f.context().comments().comments_before(self.span.end);
28-
FormatTrailingComments::Comments(comments).fmt(f)
28+
write!(f, FormatTrailingComments::Comments(comments))
2929
});
3030

3131
write!(
@@ -112,19 +112,8 @@ impl<'a> Format<'a> for AstNode<'a, Vec<'a, Directive<'a>>> {
112112
// }
113113
//```
114114
// so we should keep an extra empty line after JsDirectiveList
115-
let source_text = f.context().source_text();
116-
let mut count = 0;
117-
let mut source_text_chars = source_text.slice_from(last_directive.span.end).chars();
118-
for char in source_text_chars.by_ref() {
119-
if is_line_terminator(char) {
120-
count += 1;
121-
} else if !char.is_whitespace() {
122-
break;
123-
}
124-
}
125115

126-
// Need an extra empty line if it has the following line and still has non-characters after whitespace.
127-
let need_extra_empty_line = source_text_chars.next().is_some() && count > 1;
116+
let need_extra_empty_line = f.source_text().lines_after(last_directive.span.end) > 1;
128117
write!(f, if need_extra_empty_line { empty_line() } else { hard_line_break() })
129118
}
130119
}

0 commit comments

Comments
 (0)