Skip to content

Commit db5f0f7

Browse files
committed
refactor(formatter): simplify usages of iter + FormatSeparatedIter
1 parent 3f92fa8 commit db5f0f7

File tree

17 files changed

+166
-156
lines changed

17 files changed

+166
-156
lines changed

crates/oxc_formatter/src/formatter/builders.rs

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,9 @@ use super::{
1919
tag::{DedentMode, GroupMode, LabelId},
2020
*,
2121
},
22+
separated::FormatSeparatedIter,
2223
};
23-
use crate::write;
24+
use crate::{TrailingSeparator, write};
2425

2526
/// A line break that only gets printed if the enclosing `Group` doesn't fit on a single line.
2627
///
@@ -2390,6 +2391,26 @@ where
23902391
self
23912392
}
23922393

2394+
pub fn entries_with_trailing_separator<F, I>(
2395+
&mut self,
2396+
entries: I,
2397+
separator: &'static str,
2398+
trailing_separator: TrailingSeparator,
2399+
) -> &mut Self
2400+
where
2401+
F: Format<'ast> + GetSpan,
2402+
I: IntoIterator<Item = F>,
2403+
{
2404+
let iter = FormatSeparatedIter::new(entries.into_iter(), separator)
2405+
.with_trailing_separator(trailing_separator);
2406+
2407+
for entry in iter {
2408+
self.entry(&entry);
2409+
}
2410+
2411+
self
2412+
}
2413+
23932414
/// Finishes the output and returns any error encountered.
23942415
pub fn finish(&mut self) -> FormatResult<()> {
23952416
self.result
@@ -2443,14 +2464,33 @@ where
24432464
pub fn entries<'a, F, I>(&mut self, entries: I) -> &mut Self
24442465
where
24452466
F: Format<'ast> + GetSpan + 'a,
2446-
I: IntoIterator<Item = &'a F>,
2467+
I: IntoIterator<Item = F>,
24472468
{
24482469
for content in entries {
24492470
self.entry(content.span(), &content);
24502471
}
24512472
self
24522473
}
24532474

2475+
pub fn entries_with_trailing_separator<'a, F, I>(
2476+
&mut self,
2477+
entries: I,
2478+
separator: &'static str,
2479+
trailing_separator: TrailingSeparator,
2480+
) -> &mut Self
2481+
where
2482+
F: Format<'ast> + GetSpan + 'a,
2483+
I: IntoIterator<Item = F>,
2484+
{
2485+
let iter = FormatSeparatedIter::new(entries.into_iter(), separator)
2486+
.with_trailing_separator(trailing_separator);
2487+
2488+
for content in iter {
2489+
self.entry(content.span(), &content);
2490+
}
2491+
self
2492+
}
2493+
24542494
pub fn finish(&mut self) -> FormatResult<()> {
24552495
self.result
24562496
}

crates/oxc_formatter/src/formatter/separated.rs

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use oxc_span::{GetSpan, Span};
2+
13
use crate::{
24
formatter::{
35
Format, FormatResult, Formatter,
@@ -10,16 +12,22 @@ use super::GroupId;
1012

1113
/// Formats a single element inside a separated list.
1214
#[derive(Debug, Clone, Eq, PartialEq)]
13-
pub struct FormatSeparatedElement<E> {
15+
pub struct FormatSeparatedElement<E: GetSpan> {
1416
// Public this field to make it easier to get the element span from `FormatSeparatedElement`.
15-
pub element: E,
17+
element: E,
1618
is_last: bool,
1719
/// The separator to write if the element has no separator yet.
1820
separator: &'static str,
1921
options: FormatSeparatedOptions,
2022
}
2123

22-
impl<'a, E: Format<'a>> Format<'a> for FormatSeparatedElement<E> {
24+
impl<T: GetSpan> GetSpan for FormatSeparatedElement<T> {
25+
fn span(&self) -> Span {
26+
self.element.span()
27+
}
28+
}
29+
30+
impl<'a, E: Format<'a> + GetSpan> Format<'a> for FormatSeparatedElement<E> {
2331
fn fmt(&self, f: &mut Formatter<'_, 'a>) -> FormatResult<()> {
2432
if self.options.nodes_grouped {
2533
group(&self.element).fmt(f)?;
@@ -42,14 +50,14 @@ impl<'a, E: Format<'a>> Format<'a> for FormatSeparatedElement<E> {
4250

4351
/// Iterator for formatting separated elements. Prints the separator between each element and
4452
/// inserts a trailing separator if necessary
45-
pub struct FormatSeparatedIter<I, E> {
53+
pub struct FormatSeparatedIter<I, E: GetSpan> {
4654
next: Option<E>,
4755
inner: I,
4856
separator: &'static str,
4957
options: FormatSeparatedOptions,
5058
}
5159

52-
impl<I, E> FormatSeparatedIter<I, E>
60+
impl<I, E: GetSpan> FormatSeparatedIter<I, E>
5361
where
5462
I: Iterator<Item = E>,
5563
{
@@ -74,7 +82,7 @@ where
7482
}
7583
}
7684

77-
impl<I, E> Iterator for FormatSeparatedIter<I, E>
85+
impl<I, E: GetSpan> Iterator for FormatSeparatedIter<I, E>
7886
where
7987
I: Iterator<Item = E>,
8088
{

crates/oxc_formatter/src/generated/ast_nodes.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3110,6 +3110,11 @@ pub struct AstNode<'a, T> {
31103110
pub(super) allocator: &'a Allocator,
31113111
pub(super) following_node: Option<SiblingNode<'a>>,
31123112
}
3113+
impl<T: GetSpan> GetSpan for &AstNode<'_, T> {
3114+
fn span(&self) -> Span {
3115+
self.inner.span()
3116+
}
3117+
}
31133118

31143119
impl<'a, T: fmt::Debug> fmt::Debug for AstNode<'a, T> {
31153120
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {

crates/oxc_formatter/src/utils/member_chain/mod.rs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -193,12 +193,7 @@ impl<'a> Format<'a> for MemberChain<'a, '_> {
193193
let has_comments = self.has_comments(f);
194194

195195
let format_one_line = format_with(|f| {
196-
let mut joiner = f.join();
197-
198-
joiner.entry(&self.head);
199-
joiner.entries(self.tail.iter());
200-
201-
joiner.finish()
196+
f.join().entries(iter::once(&self.head).chain(self.tail.iter())).finish()
202197
});
203198

204199
if self.tail.len() <= 1 && !has_comments {

crates/oxc_formatter/src/write/array_element_list.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,24 +46,24 @@ impl<'a> Format<'a> for ArrayElementList<'a, '_> {
4646
let mut filler = f.fill();
4747

4848
// Using format_separated is valid in this case as can_print_fill does not allow holes
49-
for (formatted) in FormatSeparatedIter::new(self.elements.iter(), ",")
49+
for element in FormatSeparatedIter::new(self.elements.iter(), ",")
5050
.with_trailing_separator(trailing_separator)
5151
.with_group_id(self.group_id)
5252
{
5353
filler.entry(
5454
&format_once(|f| {
55-
if get_lines_before(formatted.element.span(), f) > 1 {
55+
if get_lines_before(element.span(), f) > 1 {
5656
write!(f, empty_line())
5757
} else if f
5858
.comments()
59-
.has_leading_own_line_comments(formatted.element.span().start)
59+
.has_leading_own_line_comments(element.span().start)
6060
{
6161
write!(f, hard_line_break())
6262
} else {
6363
write!(f, soft_line_break_or_space())
6464
}
6565
}),
66-
&formatted,
66+
&element,
6767
);
6868
}
6969

crates/oxc_formatter/src/write/assignment_pattern_property_list.rs

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ enum AssignmentTargetPropertyListNode<'a, 'b> {
1414
Rest(&'b AstNode<'a, AssignmentTargetRest<'a>>),
1515
}
1616

17-
impl AssignmentTargetPropertyListNode<'_, '_> {
18-
pub fn span(&self) -> Span {
17+
impl GetSpan for AssignmentTargetPropertyListNode<'_, '_> {
18+
fn span(&self) -> Span {
1919
match self {
2020
AssignmentTargetPropertyListNode::Property(property) => property.span(),
2121
AssignmentTargetPropertyListNode::Rest(rest) => rest.span(),
@@ -71,21 +71,15 @@ impl<'a> Format<'a> for AssignmentTargetPropertyList<'a, '_> {
7171
} else {
7272
FormatTrailingCommas::ES5.trailing_separator(f.options())
7373
};
74-
let source_text = f.source_text();
75-
let entries = FormatSeparatedIter::new(
76-
AssignmentTargetPropertyListIter {
77-
properties: self.properties.iter(),
78-
rest: self.rest,
79-
},
80-
",",
81-
)
82-
.with_trailing_separator(trailing_separator);
83-
84-
let mut join = f.join_nodes_with_soft_line();
85-
for entry in entries {
86-
join.entry(entry.element.span(), &entry);
87-
}
88-
89-
join.finish()
74+
f.join_nodes_with_soft_line()
75+
.entries_with_trailing_separator(
76+
AssignmentTargetPropertyListIter {
77+
properties: self.properties.iter(),
78+
rest: self.rest,
79+
},
80+
",",
81+
trailing_separator,
82+
)
83+
.finish()
9084
}
9185
}

crates/oxc_formatter/src/write/binding_property_list.rs

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use oxc_allocator::{Box, Vec};
22
use oxc_ast::ast::*;
3+
use oxc_span::GetSpan;
34

45
use crate::{
56
formatter::{
@@ -22,8 +23,8 @@ enum BindingPropertyListNode<'a, 'b> {
2223
Rest(&'b AstNode<'a, BindingRestElement<'a>>),
2324
}
2425

25-
impl BindingPropertyListNode<'_, '_> {
26-
pub fn span(&self) -> Span {
26+
impl GetSpan for BindingPropertyListNode<'_, '_> {
27+
fn span(&self) -> Span {
2728
match self {
2829
BindingPropertyListNode::Property(property) => property.span,
2930
BindingPropertyListNode::Rest(rest) => rest.span,
@@ -75,17 +76,13 @@ impl<'a> Format<'a> for BindingPropertyList<'a, '_> {
7576
FormatTrailingCommas::ES5.trailing_separator(f.options())
7677
};
7778
let source_text = f.source_text();
78-
let entries = FormatSeparatedIter::new(
79-
BindingPropertyListIter { properties: self.properties.iter(), rest: self.rest },
80-
",",
81-
)
82-
.with_trailing_separator(trailing_separator);
8379

84-
let mut join = f.join_nodes_with_soft_line();
85-
for entry in entries {
86-
join.entry(entry.element.span(), &entry);
87-
}
88-
89-
join.finish()
80+
f.join_nodes_with_soft_line()
81+
.entries_with_trailing_separator(
82+
BindingPropertyListIter { properties: self.properties.iter(), rest: self.rest },
83+
",",
84+
trailing_separator,
85+
)
86+
.finish()
9087
}
9188
}

crates/oxc_formatter/src/write/call_arguments.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,10 @@ impl<'a> Format<'a> for AstNode<'a, ArenaVec<'a, Argument<'a>>> {
8686
l_paren_token,
8787
format_with(|f| {
8888
f.join_with(space())
89-
.entries(
90-
FormatSeparatedIter::new(self.iter(), ",")
91-
.with_trailing_separator(TrailingSeparator::Omit),
89+
.entries_with_trailing_separator(
90+
self.iter(),
91+
",",
92+
TrailingSeparator::Omit,
9293
)
9394
.finish()
9495
}),

crates/oxc_formatter/src/write/class.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -201,9 +201,10 @@ impl<'a> Format<'a> for AstNode<'a, Vec<'a, TSClassImplements<'a>>> {
201201
format_once(|f| {
202202
// the grouping will be applied by the parent
203203
f.join_with(&soft_line_break_or_space())
204-
.entries(
205-
FormatSeparatedIter::new(self.iter(), ",")
206-
.with_trailing_separator(TrailingSeparator::Disallowed),
204+
.entries_with_trailing_separator(
205+
self.iter(),
206+
",",
207+
TrailingSeparator::Disallowed,
207208
)
208209
.finish()
209210
})

crates/oxc_formatter/src/write/export_declarations.rs

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -139,26 +139,27 @@ impl<'a> FormatWrite<'a> for AstNode<'a, ExportNamedDeclaration<'a>> {
139139
impl<'a> Format<'a> for AstNode<'a, Vec<'a, ExportSpecifier<'a>>> {
140140
fn fmt(&self, f: &mut Formatter<'_, 'a>) -> FormatResult<()> {
141141
let trailing_separator = FormatTrailingCommas::ES5.trailing_separator(f.options());
142-
let mut joiner = f.join_with(soft_line_break_or_space());
143-
for specifier in
144-
FormatSeparatedIter::new(self.iter(), ",").with_trailing_separator(trailing_separator)
145-
{
146-
joiner.entry(&format_once(|f| {
147-
// Should add empty line before the specifier if there are comments before it.
148-
let comments =
149-
f.context().comments().comments_before(specifier.element.span().start);
150-
if !comments.is_empty() {
151-
if get_lines_before(comments[0].span, f) > 1 {
152-
write!(f, [empty_line()])?;
153-
}
154-
write!(f, [FormatLeadingComments::Comments(comments)])?;
155-
}
156-
157-
write!(f, specifier)
158-
}));
159-
}
160-
161-
joiner.finish()
142+
f.join_with(soft_line_break_or_space())
143+
.entries(
144+
FormatSeparatedIter::new(self.iter(), ",")
145+
.with_trailing_separator(trailing_separator)
146+
.map(|specifier| {
147+
format_once(move |f| {
148+
// Should add empty line before the specifier if there are comments before it.
149+
let comments =
150+
f.context().comments().comments_before(specifier.span().start);
151+
if !comments.is_empty() {
152+
if get_lines_before(comments[0].span, f) > 1 {
153+
write!(f, [empty_line()])?;
154+
}
155+
write!(f, [FormatLeadingComments::Comments(comments)])?;
156+
}
157+
158+
write!(f, specifier)
159+
})
160+
}),
161+
)
162+
.finish()
162163
}
163164
}
164165

0 commit comments

Comments
 (0)