From d64ed0a953a6c20edb5d659ebfa5c6381758349b Mon Sep 17 00:00:00 2001 From: Dunqing Date: Tue, 21 Nov 2023 10:05:39 +0800 Subject: [PATCH] feat(prettier): support format commonjs and amd call (#1473) --- .../src/format/call_expression.rs | 59 ++++++++++++++++--- crates/oxc_prettier/src/format/mod.rs | 4 +- crates/oxc_prettier/src/format/object.rs | 12 +--- tasks/prettier_conformance/prettier.snap.md | 6 +- 4 files changed, 54 insertions(+), 27 deletions(-) diff --git a/crates/oxc_prettier/src/format/call_expression.rs b/crates/oxc_prettier/src/format/call_expression.rs index c9846d982..28f9217b8 100644 --- a/crates/oxc_prettier/src/format/call_expression.rs +++ b/crates/oxc_prettier/src/format/call_expression.rs @@ -27,33 +27,74 @@ pub(super) fn print_call_expression<'a>( parts.push(ss!("?.")); } - parts.push(print_call_expression_arguments(p, arguments)); + parts.push(print_call_expression_arguments(p, callee, arguments)); Doc::Array(parts) } fn print_call_expression_arguments<'a>( p: &mut Prettier<'a>, + callee: &Expression<'a>, arguments: &Vec<'a, Argument<'a>>, ) -> Doc<'a> { let mut parts = p.vec(); parts.push(ss!("(")); let mut parts_inner = p.vec(); - parts_inner.push(Doc::Softline); + + let should_break = !is_commons_js_or_amd_call(callee, arguments); + for (i, element) in arguments.iter().enumerate() { - parts_inner.push(element.format(p)); + let doc = element.format(p); + parts_inner.push(doc); if i < arguments.len() - 1 { parts_inner.push(ss!(",")); parts_inner.push(Doc::Line); } } - parts.push(Doc::Indent(parts_inner)); - parts.push(if_break!(p, ",")); - parts.push(Doc::Softline); + if should_break { + parts_inner.insert(0, Doc::Softline); + parts.push(Doc::Indent(parts_inner)); + parts.push(if_break!(p, ",")); + parts.push(Doc::Softline); + } else { + parts.extend(parts_inner); + } parts.push(ss!(")")); - let should_break = arguments - .iter() - .any(|arg| misc::has_new_line_in_range(p.source_text, arg.span().start, arg.span().end)); + + let should_break = should_break + && arguments.iter().any(|arg| { + misc::has_new_line_in_range(p.source_text, arg.span().start, arg.span().end) + }); Doc::Group(Group::new(parts, should_break)) } + +/// https://github.com/prettier/prettier/blob/7aecca5d6473d73f562ca3af874831315f8f2581/src/language-js/print/call-expression.js#L93-L116 +fn is_commons_js_or_amd_call<'a>( + callee: &Expression<'a>, + arguments: &Vec<'a, Argument<'a>>, +) -> bool { + if let Expression::Identifier(callee) = callee { + if callee.name == "require" { + return arguments.len() == 1 + && matches!(arguments[0], Argument::Expression(Expression::StringLiteral(_))) + || arguments.len() > 1; + } + if callee.name == "define" { + // TODO: the parent node is ExpressionStatement + return arguments.len() == 1 + || (arguments.len() == 2 + && matches!( + arguments[1], + Argument::Expression(Expression::ArrayExpression(_)) + )) + || (arguments.len() == 3 + && matches!(arguments[0], Argument::Expression(Expression::StringLiteral(_))) + && matches!( + arguments[1], + Argument::Expression(Expression::ArrayExpression(_)) + )); + } + } + false +} diff --git a/crates/oxc_prettier/src/format/mod.rs b/crates/oxc_prettier/src/format/mod.rs index b44907bdb..5fb42b9f7 100644 --- a/crates/oxc_prettier/src/format/mod.rs +++ b/crates/oxc_prettier/src/format/mod.rs @@ -570,7 +570,7 @@ impl<'a> Format<'a> for VariableDeclaration<'a> { let mut parts = p.vec(); parts.push(ss!(kind)); parts.push(ss!(" ")); - parts.push(Doc::Array(decls)); + parts.extend(decls); if !parent_for_loop.is_some_and(|span| span != self.span) { parts.push(ss!(";")); @@ -1271,7 +1271,7 @@ impl<'a> Format<'a> for RegExpLiteral { impl<'a> Format<'a> for StringLiteral { fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> { - array!(p, p.str(&string::print_string(self.value.as_str(), p.options.single_quote))) + p.str(&string::print_string(self.value.as_str(), p.options.single_quote)) } } diff --git a/crates/oxc_prettier/src/format/object.rs b/crates/oxc_prettier/src/format/object.rs index b29635efa..9e450f5b2 100644 --- a/crates/oxc_prettier/src/format/object.rs +++ b/crates/oxc_prettier/src/format/object.rs @@ -50,17 +50,7 @@ pub(super) fn print_object_properties<'a, F: Format<'a> + GetSpan>( } } - let should_break = misc::has_new_line_in_range( - p.source_text, - object.span().start, - // SAFETY: we checked above that `properties` is not empty - properties[0].span().start, - ); - - let mut group = p.vec(); - group.push(Doc::Indent(indent_parts)); - - parts.push(Doc::Group(Group::new(group, should_break))); + parts.push(Doc::Indent(indent_parts)); parts.push(if_break!(p, ",")); if p.options.bracket_spacing { diff --git a/tasks/prettier_conformance/prettier.snap.md b/tasks/prettier_conformance/prettier.snap.md index 26f35822f..ded4cc7cf 100644 --- a/tasks/prettier_conformance/prettier.snap.md +++ b/tasks/prettier_conformance/prettier.snap.md @@ -1,4 +1,4 @@ -Compatibility: 129/601 (21.46%) +Compatibility: 131/601 (21.80%) # Failed @@ -177,7 +177,6 @@ Compatibility: 129/601 (21.46%) * classes/keyword-property/static.js ### classes-private-fields -* classes-private-fields/optional-chaining.js * classes-private-fields/private_fields.js * classes-private-fields/with_comments.js @@ -555,9 +554,6 @@ Compatibility: 129/601 (21.46%) ### regex * regex/test.js -### require -* require/require.js - ### require-amd * require-amd/named-amd-module.js * require-amd/require.js