refactor(prettier): Verify current implementation with refactoring (#8412)

Part of #5068 

I think I will be able to grasp the current implementation status after
a few more iterations... 🏃🏻
This commit is contained in:
Yuji Sugiura 2025-01-10 18:31:33 +09:00 committed by GitHub
parent 0efc845c97
commit a93e27aca0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 118 additions and 181 deletions

View file

@ -11,8 +11,8 @@ use crate::{
format::{
print::{
array, arrow_function, assignment, binaryish, block, call_expression, class, function,
function_parameters, literal, misc, module, object, property, template_literal,
ternary,
function_parameters, literal, misc, module, object, property, statement,
template_literal, ternary,
},
Format,
},
@ -129,29 +129,23 @@ impl<'a> Format<'a> for IfStatement<'a> {
wrap!(p, self, IfStatement, {
let mut parts = Vec::new_in(p.allocator);
let test_doc = self.test.format(p);
let consequent = self.consequent.format(p);
let consequent = misc::adjust_clause(p, &self.consequent, consequent, false);
let opening = group!(
let consequent_doc = self.consequent.format(p);
parts.push(group!(
p,
[
text!("if ("),
group!(p, [indent!(p, [softline!(), test_doc]), softline!()]),
group!(p, [indent!(p, [softline!(), self.test.format(p)]), softline!()]),
text!(")"),
consequent
misc::adjust_clause(p, &self.consequent, consequent_doc, false)
]
);
parts.push(opening);
));
if let Some(alternate) = &self.alternate {
let else_on_same_line = matches!(alternate, Statement::BlockStatement(_));
if else_on_same_line {
parts.push(text!(" "));
} else {
parts.push(hardline!(p));
}
parts.push(if else_on_same_line { text!(" ") } else { hardline!(p) });
parts.push(text!("else"));
let alternate_doc = alternate.format(p);
parts.push(group!(
p,
@ -178,46 +172,45 @@ impl<'a> Format<'a> for BlockStatement<'a> {
impl<'a> Format<'a> for ForStatement<'a> {
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
wrap!(p, self, ForStatement, {
let body = self.body.format(p);
let body = misc::adjust_clause(p, &self.body, body, false);
let body_doc = self.body.format(p);
let body_doc = misc::adjust_clause(p, &self.body, body_doc, false);
if self.init.is_none() && self.test.is_none() && self.update.is_none() {
return group!(p, [text!("for (;;)"), body]);
return group!(p, [text!("for (;;)"), body_doc]);
}
let parts_head = {
let mut parts_head = Vec::new_in(p.allocator);
parts_head.push(softline!());
if let Some(init) = &self.init {
parts_head.push(init.format(p));
}
parts_head.push(text!(";"));
parts_head.push(line!());
if let Some(init) = &self.test {
parts_head.push(init.format(p));
}
parts_head.push(text!(";"));
parts_head.push(line!());
if let Some(init) = &self.update {
parts_head.push(init.format(p));
}
indent!(p, parts_head)
};
let mut init_test_update_parts = Vec::new_in(p.allocator);
init_test_update_parts.push(softline!());
if let Some(init) = &self.init {
init_test_update_parts.push(match init {
ForStatementInit::VariableDeclaration(v) => v.format(p),
match_expression!(ForStatementInit) => init.to_expression().format(p),
});
}
init_test_update_parts.push(text!(";"));
init_test_update_parts.push(line!());
if let Some(init) = &self.test {
init_test_update_parts.push(init.format(p));
}
init_test_update_parts.push(text!(";"));
init_test_update_parts.push(line!());
if let Some(init) = &self.update {
init_test_update_parts.push(init.format(p));
}
group!(p, [text!("for ("), group!(p, [parts_head, softline!()]), text!(")"), body])
group!(
p,
[
text!("for ("),
group!(p, [indent!(p, init_test_update_parts), softline!()]),
text!(")"),
body_doc
]
)
})
}
}
impl<'a> Format<'a> for ForStatementInit<'a> {
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
match self {
ForStatementInit::VariableDeclaration(v) => v.format(p),
match_expression!(ForStatementInit) => self.to_expression().format(p),
}
}
}
impl<'a> Format<'a> for ForInStatement<'a> {
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
wrap!(p, self, ForInStatement, {
@ -353,17 +346,15 @@ impl<'a> Format<'a> for SwitchStatement<'a> {
wrap!(p, self, SwitchStatement, {
let mut parts = Vec::new_in(p.allocator);
let mut header_parts = Vec::new_in(p.allocator);
header_parts.push(text!("switch ("));
let discriminant_doc = self.discriminant.format(p);
header_parts.push(indent!(p, [softline!(), discriminant_doc]));
header_parts.push(softline!());
header_parts.push(text!(")"));
parts.push(group!(p, header_parts));
parts.push(group!(
p,
[
text!("switch ("),
indent!(p, [softline!(), self.discriminant.format(p)]),
softline!(),
text!(")"),
]
));
parts.push(text!(" {"));
@ -397,38 +388,16 @@ impl<'a> Format<'a> for SwitchCase<'a> {
parts.push(text!("default:"));
}
let consequent: Vec<_> = Vec::from_iter_in(
self.consequent.iter().filter(|c| !matches!(c, Statement::EmptyStatement(_))),
p.allocator,
);
let len = consequent.len();
let is_only_one_block_statement =
len == 1 && matches!(self.consequent[0], Statement::BlockStatement(_));
let len =
self.consequent.iter().filter(|c| !matches!(c, Statement::EmptyStatement(_))).count();
if len != 0 {
let consequent_parts =
statement::print_statement_sequence(p, self.consequent.as_slice());
let mut consequent_parts = Vec::new_in(p.allocator);
for i in 0..len {
let stmt = &consequent[i];
if i != 0 && matches!(stmt, Statement::BreakStatement(_)) {
let last_stmt = &consequent[i - 1];
if p.is_next_line_empty(last_stmt.span()) {
consequent_parts.push(hardline!(p));
}
}
if is_only_one_block_statement {
consequent_parts.push(text!(" "));
if len == 1 && matches!(self.consequent[0], Statement::BlockStatement(_)) {
parts.push(array!(p, [text!(" "), array!(p, consequent_parts)]));
} else {
consequent_parts.push(hardline!(p));
}
consequent_parts.push(stmt.format(p));
}
if !consequent_parts.is_empty() {
if is_only_one_block_statement {
parts.extend(consequent_parts);
} else {
parts.push(indent!(p, [group!(p, consequent_parts)]));
parts.push(indent!(p, [hardline!(p), array!(p, consequent_parts)]));
}
}
@ -484,17 +453,14 @@ impl<'a> Format<'a> for TryStatement<'a> {
impl<'a> Format<'a> for CatchClause<'a> {
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
wrap!(p, self, CatchClause, {
let mut parts = Vec::new_in(p.allocator);
parts.push(text!("catch "));
if let Some(param) = &self.param {
parts.push(text!("("));
parts.push(param.pattern.format(p));
parts.push(text!(") "));
return array!(
p,
[text!("catch ("), param.pattern.format(p), text!(") "), self.body.format(p)]
);
}
parts.push(self.body.format(p));
array!(p, parts)
array!(p, [text!("catch "), self.body.format(p)])
})
}
}
@ -618,7 +584,16 @@ impl<'a> Format<'a> for VariableDeclaration<'a> {
impl<'a> Format<'a> for VariableDeclarator<'a> {
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
wrap!(p, self, VariableDeclarator, { assignment::print_variable_declarator(p, self) })
wrap!(p, self, VariableDeclarator, {
let left_doc = self.id.format(p);
assignment::print_assignment(
p,
assignment::AssignmentLikeNode::VariableDeclarator(self),
left_doc,
text!(" ="),
self.init.as_ref(),
)
})
}
}
@ -736,18 +711,11 @@ impl<'a> Format<'a> for WithClause<'a> {
impl<'a> Format<'a> for ImportAttribute<'a> {
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
let key_doc = self.key.format(p);
let value_doc = self.value.format(p);
array!(p, [key_doc, text!(": "), value_doc])
}
}
impl<'a> Format<'a> for ImportAttributeKey<'a> {
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
match self {
Self::Identifier(ident) => ident.format(p),
Self::StringLiteral(literal) => literal.format(p),
}
let key_doc = match &self.key {
ImportAttributeKey::Identifier(ident) => ident.format(p),
ImportAttributeKey::StringLiteral(literal) => literal.format(p),
};
group!(p, [group!(p, [key_doc]), text!(": "), self.value.format(p)])
}
}
@ -805,16 +773,13 @@ impl<'a> Format<'a> for ExportAllDeclaration<'a> {
impl<'a> Format<'a> for ExportDefaultDeclaration<'a> {
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
self.declaration.format(p)
}
}
impl<'a> Format<'a> for ExportDefaultDeclarationKind<'a> {
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
match self {
match_expression!(Self) => self.to_expression().format(p),
Self::FunctionDeclaration(decl) => decl.format(p),
Self::ClassDeclaration(decl) => decl.format(p),
Self::TSInterfaceDeclaration(decl) => decl.format(p),
match &self.declaration {
match_expression!(ExportDefaultDeclarationKind) => {
self.declaration.to_expression().format(p)
}
ExportDefaultDeclarationKind::FunctionDeclaration(decl) => decl.format(p),
ExportDefaultDeclarationKind::ClassDeclaration(decl) => decl.format(p),
ExportDefaultDeclarationKind::TSInterfaceDeclaration(decl) => decl.format(p),
}
}
}
@ -1225,11 +1190,10 @@ impl<'a> Format<'a> for YieldExpression<'a> {
impl<'a> Format<'a> for UpdateExpression<'a> {
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
wrap!(p, self, UpdateExpression, {
let argument_doc = self.argument.format(p);
if self.prefix {
let argument_doc = self.argument.format(p);
array!(p, [text!(self.operator.as_str()), argument_doc])
} else {
let argument_doc = self.argument.format(p);
array!(p, [argument_doc, text!(self.operator.as_str())])
}
})
@ -1305,7 +1269,16 @@ impl<'a> Format<'a> for ConditionalExpression<'a> {
impl<'a> Format<'a> for AssignmentExpression<'a> {
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
wrap!(p, self, AssignmentExpression, { assignment::print_assignment_expression(p, self) })
wrap!(p, self, AssignmentExpression, {
let left_doc = self.left.format(p);
assignment::print_assignment(
p,
assignment::AssignmentLikeNode::AssignmentExpression(self),
left_doc,
array!(p, [text!(" "), text!(self.operator.as_str())]),
Some(&self.right),
)
})
}
}
@ -1495,17 +1468,15 @@ impl<'a> Format<'a> for AwaitExpression<'a> {
impl<'a> Format<'a> for ChainExpression<'a> {
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
wrap!(p, self, ChainExpression, { self.expression.format(p) })
}
}
impl<'a> Format<'a> for ChainElement<'a> {
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
match self {
Self::CallExpression(expr) => expr.format(p),
Self::TSNonNullExpression(expr) => expr.format(p),
match_member_expression!(Self) => self.to_member_expression().format(p),
}
wrap!(p, self, ChainExpression, {
match &self.expression {
ChainElement::CallExpression(expr) => expr.format(p),
ChainElement::TSNonNullExpression(expr) => expr.format(p),
match_member_expression!(ChainElement) => {
self.expression.to_member_expression().format(p)
}
}
})
}
}
@ -1522,9 +1493,7 @@ impl<'a> Format<'a> for NewExpression<'a> {
impl<'a> Format<'a> for MetaProperty<'a> {
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
let meta_doc = self.meta.format(p);
let property_doc = self.property.format(p);
array!(p, [meta_doc, text!("."), property_doc])
array!(p, [self.meta.format(p), text!("."), self.property.format(p)])
}
}
@ -1555,8 +1524,7 @@ impl<'a> Format<'a> for ClassElement<'a> {
impl<'a> Format<'a> for StaticBlock<'a> {
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
wrap!(p, self, StaticBlock, {
let block_doc = block::print_block(p, &self.body, None);
array!(p, [text!("static "), block_doc])
array!(p, [text!("static "), block::print_block(p, &self.body, None)])
})
}
}

View file

@ -17,34 +17,6 @@ use crate::{
line, text, Format, Prettier,
};
pub fn print_assignment_expression<'a>(
p: &mut Prettier<'a>,
assignment_expr: &AssignmentExpression<'a>,
) -> Doc<'a> {
let left_doc = assignment_expr.left.format(p);
print_assignment(
p,
AssignmentLikeNode::AssignmentExpression(assignment_expr),
left_doc,
array!(p, [text!(" "), text!(assignment_expr.operator.as_str())]),
Some(&assignment_expr.right),
)
}
pub fn print_variable_declarator<'a>(
p: &mut Prettier<'a>,
variable_declarator: &VariableDeclarator<'a>,
) -> Doc<'a> {
let left_doc = variable_declarator.id.format(p);
print_assignment(
p,
AssignmentLikeNode::VariableDeclarator(variable_declarator),
left_doc,
text!(" ="),
variable_declarator.init.as_ref(),
)
}
#[derive(Debug, Clone, Copy)]
pub enum AssignmentLikeNode<'a, 'b> {
AssignmentExpression(&'b AssignmentExpression<'a>),
@ -77,14 +49,14 @@ pub fn print_assignment<'a>(
let layout = choose_layout(p, &node, &left_doc, right_expr);
// TODO: set the layout in options so that when we print the right-hand side, we can refer to it.
let right_doc = if let Some(expr) = right_expr { expr.format(p) } else { array!(p, []) };
let right_doc = if let Some(expr) = right_expr { expr.format(p) } else { text!("") };
match layout {
Layout::BreakAfterOperator => {
group!(p, [group!(p, [left_doc]), op, group!(p, [indent!(p, [line!(), right_doc])])])
}
Layout::NeverBreakAfterOperator => {
group!(p, [group!(p, [left_doc]), op, text!(" "), group!(p, [right_doc])])
group!(p, [group!(p, [left_doc]), op, text!(" "), right_doc])
}
// First break right-hand side, then after operator
Layout::Fluid => {

View file

@ -21,24 +21,15 @@ pub fn print_call_arguments<'a>(
p: &mut Prettier<'a>,
expression: &CallExpressionLike<'a, '_>,
) -> Doc<'a> {
let mut parts = Vec::new_in(p.allocator);
parts.push(text!("("));
let callee = expression.callee();
let arguments = expression.arguments();
let should_break = if matches!(expression, CallExpressionLike::CallExpression(_)) {
!is_commons_js_or_amd_call(expression.callee(), arguments)
} else {
true
};
if arguments.is_empty() {
parts.extend(p.print_inner_comment(Span::new(callee.span().end, expression.span().end)));
parts.push(text!(")"));
return array!(p, parts);
return array!(p, [text!("("), text!(")")]);
}
let mut parts = Vec::new_in(p.allocator);
parts.push(text!("("));
#[allow(clippy::cast_sign_loss)]
let get_printed_arguments = |p: &mut Prettier<'a>, skip_index: isize| {
let mut printed_arguments = Vec::new_in(p.allocator);
@ -195,6 +186,12 @@ pub fn print_call_arguments<'a>(
let mut printed_arguments = get_printed_arguments(p, 0);
let should_break = if matches!(expression, CallExpressionLike::CallExpression(_)) {
!is_commons_js_or_amd_call(expression.callee(), arguments)
} else {
true
};
if should_break {
printed_arguments.insert(0, softline!());
parts.push(indent!(p, printed_arguments));