From 78c6fcd1d040209fb2221caa8474a80cf2c78ddd Mon Sep 17 00:00:00 2001 From: Boshen Date: Thu, 23 Nov 2023 21:52:56 +0800 Subject: [PATCH] feat(prettier): improve format of ExportDefaultDeclaration (#1520) --- crates/oxc_ast/src/ast_kind.rs | 48 ++++++++++++ crates/oxc_prettier/src/needs_parens.rs | 85 ++++++++++++--------- tasks/prettier_conformance/prettier.snap.md | 6 +- 3 files changed, 98 insertions(+), 41 deletions(-) diff --git a/crates/oxc_ast/src/ast_kind.rs b/crates/oxc_ast/src/ast_kind.rs index 7ba899c99..7b2c7fef0 100644 --- a/crates/oxc_ast/src/ast_kind.rs +++ b/crates/oxc_ast/src/ast_kind.rs @@ -139,6 +139,7 @@ pub enum AstKind<'a> { TSAsExpression(&'a TSAsExpression<'a>), TSSatisfiesExpression(&'a TSSatisfiesExpression<'a>), TSNonNullExpression(&'a TSNonNullExpression<'a>), + TSInstantiationExpression(&'a TSInstantiationExpression<'a>), TSEnumDeclaration(&'a TSEnumDeclaration<'a>), TSEnumMember(&'a TSEnumMember<'a>), @@ -256,6 +257,51 @@ impl<'a> AstKind<'a> { _ => false, } } + + pub fn from_expression(e: &'a Expression<'a>) -> Self { + match e { + Expression::BooleanLiteral(e) => Self::BooleanLiteral(e), + Expression::NullLiteral(e) => Self::NullLiteral(e), + Expression::NumberLiteral(e) => Self::NumberLiteral(e), + Expression::BigintLiteral(e) => Self::BigintLiteral(e), + Expression::RegExpLiteral(e) => Self::RegExpLiteral(e), + Expression::StringLiteral(e) => Self::StringLiteral(e), + Expression::TemplateLiteral(e) => Self::TemplateLiteral(e), + Expression::Identifier(e) => Self::IdentifierReference(e), + Expression::MetaProperty(e) => Self::MetaProperty(e), + Expression::Super(e) => Self::Super(e), + Expression::ArrayExpression(e) => Self::ArrayExpression(e), + Expression::ArrowExpression(e) => Self::ArrowExpression(e), + Expression::AssignmentExpression(e) => Self::AssignmentExpression(e), + Expression::AwaitExpression(e) => Self::AwaitExpression(e), + Expression::BinaryExpression(e) => Self::BinaryExpression(e), + Expression::CallExpression(e) => Self::CallExpression(e), + Expression::ChainExpression(e) => Self::ChainExpression(e), + Expression::ClassExpression(e) => Self::Class(e), + Expression::ConditionalExpression(e) => Self::ConditionalExpression(e), + Expression::FunctionExpression(e) => Self::Function(e), + Expression::ImportExpression(e) => Self::ImportExpression(e), + Expression::LogicalExpression(e) => Self::LogicalExpression(e), + Expression::MemberExpression(e) => Self::MemberExpression(e), + Expression::NewExpression(e) => Self::NewExpression(e), + Expression::ObjectExpression(e) => Self::ObjectExpression(e), + Expression::ParenthesizedExpression(e) => Self::ParenthesizedExpression(e), + Expression::SequenceExpression(e) => Self::SequenceExpression(e), + Expression::TaggedTemplateExpression(e) => Self::TaggedTemplateExpression(e), + Expression::ThisExpression(e) => Self::ThisExpression(e), + Expression::UnaryExpression(e) => Self::UnaryExpression(e), + Expression::UpdateExpression(e) => Self::UpdateExpression(e), + Expression::YieldExpression(e) => Self::YieldExpression(e), + Expression::PrivateInExpression(e) => Self::PrivateInExpression(e), + Expression::JSXElement(e) => Self::JSXElement(e), + Expression::JSXFragment(e) => Self::JSXFragment(e), + Expression::TSAsExpression(e) => Self::TSAsExpression(e), + Expression::TSSatisfiesExpression(e) => Self::TSSatisfiesExpression(e), + Expression::TSTypeAssertion(e) => Self::TSTypeAssertion(e), + Expression::TSNonNullExpression(e) => Self::TSNonNullExpression(e), + Expression::TSInstantiationExpression(e) => Self::TSInstantiationExpression(e), + } + } } impl<'a> GetSpan for AstKind<'a> { @@ -391,6 +437,7 @@ impl<'a> GetSpan for AstKind<'a> { Self::TSAsExpression(x) => x.span, Self::TSSatisfiesExpression(x) => x.span, Self::TSNonNullExpression(x) => x.span, + Self::TSInstantiationExpression(x) => x.span, Self::TSEnumDeclaration(x) => x.span, Self::TSEnumMember(x) => x.span, @@ -561,6 +608,7 @@ impl<'a> AstKind<'a> { Self::TSAsExpression(_) => "TSAsExpression".into(), Self::TSSatisfiesExpression(_) => "TSSatisfiesExpression".into(), Self::TSNonNullExpression(_) => "TSNonNullExpression".into(), + Self::TSInstantiationExpression(_) => "TSInstantiationExpression".into(), Self::TSEnumDeclaration(decl) => format!("TSEnumDeclaration({})", &decl.id.name).into(), Self::TSEnumBody(_) => "TSEnumBody".into(), diff --git a/crates/oxc_prettier/src/needs_parens.rs b/crates/oxc_prettier/src/needs_parens.rs index b182f364d..2785a867d 100644 --- a/crates/oxc_prettier/src/needs_parens.rs +++ b/crates/oxc_prettier/src/needs_parens.rs @@ -21,7 +21,7 @@ use oxc_syntax::operator::{BinaryOperator, UnaryOperator, UpdateOperator}; use crate::{array, doc::Doc, ss, Prettier}; impl<'a> Prettier<'a> { - pub(crate) fn wrap_parens(&self, doc: Doc<'a>, kind: AstKind<'a>) -> Doc<'a> { + pub(crate) fn wrap_parens(&mut self, doc: Doc<'a>, kind: AstKind<'a>) -> Doc<'a> { if self.need_parens(kind) { array![self, ss!("("), doc, ss!(")")] } else { @@ -29,7 +29,7 @@ impl<'a> Prettier<'a> { } } - fn need_parens(&self, kind: AstKind<'a>) -> bool { + fn need_parens(&mut self, kind: AstKind<'a>) -> bool { if matches!(kind, AstKind::Program(_)) { return false; } @@ -165,7 +165,7 @@ impl<'a> Prettier<'a> { } } - fn check_parent_kind(&self, kind: AstKind<'a>, parent_kind: AstKind<'a>) -> bool { + fn check_parent_kind(&mut self, kind: AstKind<'a>, parent_kind: AstKind<'a>) -> bool { match parent_kind { AstKind::Class(class) => { if let Some(h) = &class.super_class { @@ -198,7 +198,7 @@ impl<'a> Prettier<'a> { AstKind::ModuleDeclaration(ModuleDeclaration::ExportDefaultDeclaration(decl)) => { if let ExportDefaultDeclarationKind::Expression(e) = &decl.declaration { return matches!(e, Expression::SequenceExpression(_)) - || Self::should_wrap_function_for_export_default(e); + || self.should_wrap_function_for_export_default(); } } _ => {} @@ -307,38 +307,51 @@ impl<'a> Prettier<'a> { } } - // This differs from the prettier implementation, which may be wrong. - fn should_wrap_function_for_export_default(e: &Expression<'a>) -> bool { - match e { - Expression::FunctionExpression(_) | Expression::ClassExpression(_) => true, - Expression::CallExpression(e) => { - Self::should_wrap_function_for_export_default(&e.callee) - } - Expression::MemberExpression(e) => { - Self::should_wrap_function_for_export_default(e.object()) - } - Expression::AssignmentExpression(e) => match &e.left { - AssignmentTarget::SimpleAssignmentTarget(t) => match t { - SimpleAssignmentTarget::AssignmentTargetIdentifier(_) => false, - SimpleAssignmentTarget::MemberAssignmentTarget(e) => { - Self::should_wrap_function_for_export_default(e.object()) - } - SimpleAssignmentTarget::TSAsExpression(e) => { - Self::should_wrap_function_for_export_default(&e.expression) - } - SimpleAssignmentTarget::TSSatisfiesExpression(e) => { - Self::should_wrap_function_for_export_default(&e.expression) - } - SimpleAssignmentTarget::TSNonNullExpression(e) => { - Self::should_wrap_function_for_export_default(&e.expression) - } - SimpleAssignmentTarget::TSTypeAssertion(e) => { - Self::should_wrap_function_for_export_default(&e.expression) - } - }, - AssignmentTarget::AssignmentTargetPattern(_) => false, - }, - _ => false, + fn should_wrap_function_for_export_default(&mut self) -> bool { + let kind = self.current_kind(); + let b = matches!( + self.parent_kind(), + AstKind::ModuleDeclaration(ModuleDeclaration::ExportDefaultDeclaration(_)) + ); + if matches!(kind, AstKind::Function(f) if f.is_expression()) + || matches!(kind, AstKind::Class(c) if c.is_expression()) + { + return b || !self.need_parens(self.current_kind()); + } + + if !Self::has_naked_left_side(kind) || (!b && self.need_parens(self.current_kind())) { + return false; + } + + let lhs = Self::get_left_side_path_name(kind); + self.nodes.push(lhs); + self.should_wrap_function_for_export_default() + } + + fn has_naked_left_side(kind: AstKind<'a>) -> bool { + matches!( + kind, + AstKind::AssignmentExpression(_) + | AstKind::BinaryExpression(_) + | AstKind::LogicalExpression(_) + | AstKind::ConditionalExpression(_) + | AstKind::CallExpression(_) + | AstKind::MemberExpression(_) + | AstKind::SequenceExpression(_) + | AstKind::TaggedTemplateExpression(_) + | AstKind::TSNonNullExpression(_) + | AstKind::ChainExpression(_) + ) || matches!(kind, AstKind::UpdateExpression(e) if !e.prefix) + } + + fn get_left_side_path_name(kind: AstKind<'a>) -> AstKind<'a> { + match kind { + AstKind::CallExpression(e) => AstKind::from_expression(&e.callee), + AstKind::ConditionalExpression(e) => AstKind::from_expression(&e.test), + AstKind::TaggedTemplateExpression(e) => AstKind::from_expression(&e.tag), + AstKind::AssignmentExpression(e) => AstKind::AssignmentTarget(&e.left), + AstKind::MemberExpression(e) => AstKind::from_expression(e.object()), + _ => panic!("need to handle {}", kind.debug_name()), } } diff --git a/tasks/prettier_conformance/prettier.snap.md b/tasks/prettier_conformance/prettier.snap.md index be77cb5a9..d798680a3 100644 --- a/tasks/prettier_conformance/prettier.snap.md +++ b/tasks/prettier_conformance/prettier.snap.md @@ -1,4 +1,4 @@ -Compatibility: 150/597 (25.13%) +Compatibility: 152/597 (25.46%) # Failed @@ -311,9 +311,6 @@ Compatibility: 150/597 (25.13%) * export/blank-line-between-specifiers.js * export/same-local-and-exported.js -### export-default -* export-default/iife.js - ### export-default/escaped * export-default/escaped/default-escaped.js @@ -331,7 +328,6 @@ Compatibility: 150/597 (25.13%) * for/continue-and-break-comment-without-blocks.js ### function -* function/function_expression.js * function/issue-10277.js ### function-comments