Skip to content

Commit 79fc59f

Browse files
committed
refactor(formatter): simplify arguments formatting
1 parent 81d43f2 commit 79fc59f

File tree

3 files changed

+50
-74
lines changed

3 files changed

+50
-74
lines changed

crates/oxc_formatter/src/utils/mod.rs

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -16,30 +16,6 @@ use crate::{
1616
generated::ast_nodes::{AstNode, AstNodes},
1717
};
1818

19-
/// This function is in charge to format the call arguments.
20-
pub fn write_arguments_multi_line<'a, S: Format<'a>, I>(
21-
separated: I,
22-
f: &mut Formatter<'_, 'a>,
23-
) -> FormatResult<()>
24-
where
25-
I: Iterator<Item = S>,
26-
{
27-
let mut iterator = separated.peekable();
28-
let mut join_with = f.join_with(soft_line_break_or_space());
29-
30-
while let Some(element) = iterator.next() {
31-
let last = iterator.peek().is_none();
32-
33-
if last {
34-
join_with.entry(&format_args!(element, FormatTrailingCommas::All));
35-
} else {
36-
join_with.entry(&element);
37-
}
38-
}
39-
40-
join_with.finish()
41-
}
42-
4319
/// Tests if expression is a long curried call
4420
///
4521
/// ```javascript

crates/oxc_formatter/src/write/call_arguments.rs

Lines changed: 49 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use crate::{
2121
generated::ast_nodes::{AstNode, AstNodes},
2222
utils::{
2323
call_expression::is_test_call_expression, is_long_curried_call,
24-
member_chain::simple_argument::SimpleArgument, write_arguments_multi_line,
24+
member_chain::simple_argument::SimpleArgument,
2525
},
2626
write,
2727
write::{
@@ -44,13 +44,15 @@ impl<'a> Format<'a> for AstNode<'a, ArenaVec<'a, Argument<'a>>> {
4444
fn fmt(&self, f: &mut Formatter<'_, 'a>) -> FormatResult<()> {
4545
let l_paren_token = "(";
4646
let r_paren_token = ")";
47+
let call_like_span = self.parent.span();
48+
4749
if self.is_empty() {
4850
return write!(
4951
f,
5052
[
5153
l_paren_token,
5254
// `call/* comment1 */(/* comment2 */)` Both comments are dangling comments.
53-
format_dangling_comments(self.parent.span()).with_soft_block_indent(),
55+
format_dangling_comments(call_like_span).with_soft_block_indent(),
5456
r_paren_token
5557
]
5658
);
@@ -59,26 +61,24 @@ impl<'a> Format<'a> for AstNode<'a, ArenaVec<'a, Argument<'a>>> {
5961
let call_expression =
6062
if let AstNodes::CallExpression(call) = self.parent { Some(call) } else { None };
6163

62-
let (is_commonjs_or_amd_call, is_test_call) = if let Some(call) = call_expression {
63-
(is_commonjs_or_amd_call(self, call), is_test_call_expression(call))
64-
} else {
65-
(false, false)
66-
};
67-
68-
let is_first_arg_string_literal_or_template = self.len() != 2
69-
|| matches!(
70-
self.as_ref().first(),
71-
Some(
72-
Argument::StringLiteral(_)
73-
| Argument::TemplateLiteral(_)
74-
| Argument::TaggedTemplateExpression(_)
75-
)
76-
);
64+
let (is_commonjs_or_amd_call, is_test_call) = call_expression
65+
.map(|call| (is_commonjs_or_amd_call(self, call), is_test_call_expression(call)))
66+
.unwrap_or_default();
7767

7868
if is_commonjs_or_amd_call
7969
|| is_multiline_template_only_args(self, f.source_text())
8070
|| is_react_hook_with_deps_array(self, f.comments())
81-
|| (is_test_call && is_first_arg_string_literal_or_template)
71+
|| (is_test_call && {
72+
self.len() != 2
73+
|| matches!(
74+
self.as_ref().first(),
75+
Some(
76+
Argument::StringLiteral(_)
77+
| Argument::TemplateLiteral(_)
78+
| Argument::TaggedTemplateExpression(_)
79+
)
80+
)
81+
})
8282
{
8383
return write!(
8484
f,
@@ -98,27 +98,26 @@ impl<'a> Format<'a> for AstNode<'a, ArenaVec<'a, Argument<'a>>> {
9898
);
9999
}
100100

101-
let mut has_empty_line = false;
102-
103101
let has_empty_line = self.iter().any(|arg| get_lines_before(arg.span(), f) > 1);
104-
105102
if has_empty_line || is_function_composition_args(self) {
106103
return format_all_args_broken_out(self, true, f);
107104
}
108105

109-
if let Some(group_layout) = arguments_grouped_layout(self, f) {
106+
if let Some(group_layout) = arguments_grouped_layout(call_like_span, self, f) {
110107
write_grouped_arguments(self, group_layout, f)
111108
} else if call_expression.is_some_and(|call| is_long_curried_call(call)) {
112109
write!(
113110
f,
114111
[
115112
l_paren_token,
116113
soft_block_indent(&format_once(|f| {
117-
write_arguments_multi_line(
118-
FormatSeparatedIter::new(self.iter(), ",")
119-
.with_trailing_separator(TrailingSeparator::Omit),
120-
f,
121-
)
114+
f.join_with(soft_line_break_or_space())
115+
.entries_with_trailing_separator(
116+
self.iter(),
117+
",",
118+
TrailingSeparator::Allowed,
119+
)
120+
.finish()
122121
})),
123122
r_paren_token,
124123
]
@@ -175,11 +174,9 @@ pub fn is_function_composition_args(args: &[Argument<'_>]) -> bool {
175174

176175
fn format_all_elements_broken_out<'a, 'b>(
177176
elements: impl Iterator<Item = (FormatResult<Option<FormatElement<'a>>>, usize)>,
178-
node: &'b AstNode<'a, ArenaVec<'a, Argument<'a>>>,
179177
expand: bool,
180178
mut buffer: impl Buffer<'a>,
181179
) -> FormatResult<()> {
182-
let is_inside_import = matches!(node.parent, AstNodes::ImportExpression(_));
183180
write!(
184181
buffer,
185182
[group(&format_args!(
@@ -198,7 +195,7 @@ fn format_all_elements_broken_out<'a, 'b>(
198195
}
199196
}
200197

201-
write!(f, [(!is_inside_import).then_some(FormatTrailingCommas::All)])
198+
write!(f, FormatTrailingCommas::All)
202199
})),
203200
")",
204201
))
@@ -211,7 +208,6 @@ fn format_all_args_broken_out<'a, 'b>(
211208
expand: bool,
212209
mut buffer: impl Buffer<'a>,
213210
) -> FormatResult<()> {
214-
let is_inside_import = matches!(node.parent, AstNodes::ImportExpression(_));
215211
let last_index = node.len() - 1;
216212
write!(
217213
buffer,
@@ -229,7 +225,7 @@ fn format_all_args_broken_out<'a, 'b>(
229225
write!(f, [argument, (index != last_index).then_some(",")])?;
230226
}
231227

232-
write!(f, [(!is_inside_import).then_some(FormatTrailingCommas::All)])
228+
write!(f, FormatTrailingCommas::All)
233229
})),
234230
")",
235231
))
@@ -238,20 +234,25 @@ fn format_all_args_broken_out<'a, 'b>(
238234
}
239235

240236
pub fn arguments_grouped_layout(
241-
args: &AstNode<ArenaVec<Argument>>,
237+
call_like_span: Span,
238+
args: &[Argument],
242239
f: &Formatter<'_, '_>,
243240
) -> Option<GroupedCallArgumentLayout> {
244-
if should_group_first_argument(args, f) {
241+
if should_group_first_argument(call_like_span, args, f) {
245242
Some(GroupedCallArgumentLayout::GroupedFirstArgument)
246-
} else if should_group_last_argument(args, f) {
243+
} else if should_group_last_argument(call_like_span, args, f) {
247244
Some(GroupedCallArgumentLayout::GroupedLastArgument)
248245
} else {
249246
None
250247
}
251248
}
252249

253250
/// Checks if the first argument requires grouping
254-
fn should_group_first_argument(args: &AstNode<ArenaVec<Argument>>, f: &Formatter<'_, '_>) -> bool {
251+
fn should_group_first_argument(
252+
call_like_span: Span,
253+
args: &[Argument],
254+
f: &Formatter<'_, '_>,
255+
) -> bool {
255256
let mut iter = args.iter();
256257
match (iter.next().and_then(|a| a.as_expression()), iter.next().and_then(|a| a.as_expression()))
257258
{
@@ -279,7 +280,6 @@ fn should_group_first_argument(args: &AstNode<ArenaVec<Argument>>, f: &Formatter
279280
return false;
280281
}
281282

282-
let call_like_span = args.parent.span();
283283
!f.comments().has_comments(call_like_span.start, first.span(), second.span().start)
284284
&& !can_group_expression_argument(second, f)
285285
&& is_relatively_short_argument(second)
@@ -289,8 +289,12 @@ fn should_group_first_argument(args: &AstNode<ArenaVec<Argument>>, f: &Formatter
289289
}
290290

291291
/// Checks if the last argument should be grouped.
292-
fn should_group_last_argument(args: &AstNode<ArenaVec<Argument>>, f: &Formatter<'_, '_>) -> bool {
293-
let mut iter = args.as_ref().iter();
292+
fn should_group_last_argument(
293+
call_like_span: Span,
294+
args: &[Argument],
295+
f: &Formatter<'_, '_>,
296+
) -> bool {
297+
let mut iter = args.iter();
294298
let last = iter.next_back();
295299

296300
match last.and_then(|arg| arg.as_expression()) {
@@ -303,7 +307,6 @@ fn should_group_last_argument(args: &AstNode<ArenaVec<Argument>>, f: &Formatter<
303307
// }
304308
}
305309

306-
let call_like_span = args.parent.span();
307310
let previous_span = penultimate.map_or(call_like_span.start, |a| a.span().end);
308311
if f.comments().has_comments(previous_span, last.span(), call_like_span.end) {
309312
return false;
@@ -595,13 +598,10 @@ fn write_grouped_arguments<'a>(
595598
// which would lead to a wrong line count.
596599
let lines_before = get_lines_before(argument.span(), f);
597600

598-
let interned = f.intern(
599-
&format_once(|f| {
600-
format_argument.fmt(f)?;
601-
write!(f, (last_index != index).then_some(","))
602-
})
603-
.memoized(),
604-
);
601+
let interned = f.intern(&format_once(|f| {
602+
format_argument.fmt(f)?;
603+
write!(f, (last_index != index).then_some(","))
604+
}));
605605

606606
let break_type =
607607
if is_grouped_argument { &mut grouped_breaks } else { &mut non_grouped_breaks };
@@ -618,7 +618,7 @@ fn write_grouped_arguments<'a>(
618618
// If any of the not grouped elements break, then fall back to the variant where
619619
// all arguments are printed in expanded mode.
620620
if non_grouped_breaks {
621-
return format_all_elements_broken_out(elements.into_iter(), node, true, f);
621+
return format_all_elements_broken_out(elements.into_iter(), true, f);
622622
}
623623

624624
// We now cache the delimiter tokens. This is needed because `[crate::best_fitting]` will try to
@@ -631,7 +631,7 @@ fn write_grouped_arguments<'a>(
631631
let mut buffer = VecBuffer::new(f.state_mut());
632632
buffer.write_element(FormatElement::Tag(Tag::StartEntry))?;
633633

634-
format_all_elements_broken_out(elements.iter().cloned(), node, true, &mut buffer);
634+
format_all_elements_broken_out(elements.iter().cloned(), true, &mut buffer);
635635

636636
buffer.write_element(FormatElement::Tag(Tag::EndEntry))?;
637637

crates/oxc_formatter/src/write/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ mod decorators;
1111
mod export_declarations;
1212
mod function;
1313
mod import_declaration;
14+
mod import_expression;
1415
mod jsx;
1516
mod member_expression;
1617
mod object_like;
@@ -62,7 +63,6 @@ use crate::{
6263
member_chain::MemberChain,
6364
object::format_property_key,
6465
string_utils::{FormatLiteralStringToken, StringLiteralParentKind},
65-
write_arguments_multi_line,
6666
},
6767
write,
6868
write::parameter_list::{can_avoid_parentheses, should_hug_function_parameters},

0 commit comments

Comments
 (0)