From 064353c97e19fef3fadb23d1f48c80d0b4d51b0f Mon Sep 17 00:00:00 2001 From: Boshen Date: Wed, 22 Nov 2023 00:26:56 +0800 Subject: [PATCH] feat(prettier): turn off preserve_parens and start working on need-parens (#1487) --- crates/oxc_ast/src/ast_kind.rs | 3 + crates/oxc_cli/src/format/mod.rs | 2 +- crates/oxc_prettier/examples/prettier.rs | 2 +- crates/oxc_prettier/src/format/mod.rs | 85 ++--- crates/oxc_prettier/src/need_parens.rs | 341 ++++++++++++++++++-- tasks/prettier_conformance/prettier.snap.md | 29 +- tasks/prettier_conformance/src/lib.rs | 2 +- 7 files changed, 389 insertions(+), 75 deletions(-) diff --git a/crates/oxc_ast/src/ast_kind.rs b/crates/oxc_ast/src/ast_kind.rs index 40f6ac23b..94121cf2e 100644 --- a/crates/oxc_ast/src/ast_kind.rs +++ b/crates/oxc_ast/src/ast_kind.rs @@ -117,6 +117,7 @@ pub enum AstKind<'a> { JSXElementName(&'a JSXElementName<'a>), JSXExpressionContainer(&'a JSXExpressionContainer<'a>), JSXAttributeItem(&'a JSXAttributeItem<'a>), + JSXSpreadAttribute(&'a JSXSpreadAttribute<'a>), JSXText(&'a JSXText), // TypeScript @@ -369,6 +370,7 @@ impl<'a> GetSpan for AstKind<'a> { Self::JSXElement(x) => x.span, Self::JSXFragment(x) => x.span, Self::JSXAttributeItem(x) => x.span(), + Self::JSXSpreadAttribute(x) => x.span, Self::JSXText(x) => x.span, Self::JSXExpressionContainer(x) => x.span, @@ -538,6 +540,7 @@ impl<'a> AstKind<'a> { Self::JSXElement(_) => "JSXElement".into(), Self::JSXFragment(_) => "JSXFragment".into(), Self::JSXAttributeItem(_) => "JSXAttributeItem".into(), + Self::JSXSpreadAttribute(_) => "JSXSpreadAttribute".into(), Self::JSXText(_) => "JSXText".into(), Self::JSXExpressionContainer(_) => "JSXExpressionContainer".into(), diff --git a/crates/oxc_cli/src/format/mod.rs b/crates/oxc_cli/src/format/mod.rs index 64a217ca9..d7e133206 100644 --- a/crates/oxc_cli/src/format/mod.rs +++ b/crates/oxc_cli/src/format/mod.rs @@ -51,7 +51,7 @@ impl FormatRunner { let source_text = std::fs::read_to_string(path).unwrap(); let allocator = Allocator::default(); let source_type = SourceType::from_path(path).unwrap(); - let ret = Parser::new(&allocator, &source_text, source_type).parse(); + let ret = Parser::new(&allocator, &source_text, source_type).preserve_parens(false).parse(); let _ = Prettier::new(&allocator, &source_text, ret.trivias, PrettierOptions::default()) .build(&ret.program); } diff --git a/crates/oxc_prettier/examples/prettier.rs b/crates/oxc_prettier/examples/prettier.rs index 5742e3bac..ab910e1ea 100644 --- a/crates/oxc_prettier/examples/prettier.rs +++ b/crates/oxc_prettier/examples/prettier.rs @@ -17,7 +17,7 @@ fn main() { let source_text = std::fs::read_to_string(path).unwrap_or_else(|_| panic!("{name} not found")); let allocator = Allocator::default(); let source_type = SourceType::from_path(path).unwrap(); - let ret = Parser::new(&allocator, &source_text, source_type).parse(); + let ret = Parser::new(&allocator, &source_text, source_type).preserve_parens(false).parse(); let output = Prettier::new(&allocator, &source_text, ret.trivias, PrettierOptions::default()) .build(&ret.program); println!("{output}"); diff --git a/crates/oxc_prettier/src/format/mod.rs b/crates/oxc_prettier/src/format/mod.rs index e70417308..6c3d70327 100644 --- a/crates/oxc_prettier/src/format/mod.rs +++ b/crates/oxc_prettier/src/format/mod.rs @@ -115,15 +115,17 @@ impl<'a> Format<'a> for Statement<'a> { impl<'a> Format<'a> for ExpressionStatement<'a> { fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> { - let mut parts = p.vec(); - if let Some(doc) = p.print_leading_comments(self.span) { - parts.push(doc); - } - parts.push(self.expression.format(p)); - if p.options.semi { - parts.push(ss!(";")); - } - Doc::Array(parts) + wrap!(p, self, ExpressionStatement, { + let mut parts = p.vec(); + if let Some(doc) = p.print_leading_comments(self.span) { + parts.push(doc); + } + parts.push(self.expression.format(p)); + if p.options.semi { + parts.push(ss!(";")); + } + Doc::Array(parts) + }) } } @@ -1291,7 +1293,9 @@ impl<'a> Format<'a> for RegExpLiteral { impl<'a> Format<'a> for StringLiteral { fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> { - p.str(&string::print_string(self.value.as_str(), p.options.single_quote)) + wrap!(p, self, StringLiteral, { + p.str(&string::print_string(self.value.as_str(), p.options.single_quote)) + }) } } @@ -1303,11 +1307,13 @@ impl<'a> Format<'a> for ThisExpression { impl<'a> Format<'a> for MemberExpression<'a> { fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> { - match self { - Self::ComputedMemberExpression(expr) => expr.format(p), - Self::StaticMemberExpression(expr) => expr.format(p), - Self::PrivateFieldExpression(expr) => expr.format(p), - } + wrap!(p, self, MemberExpression, { + match self { + Self::ComputedMemberExpression(expr) => expr.format(p), + Self::StaticMemberExpression(expr) => expr.format(p), + Self::PrivateFieldExpression(expr) => expr.format(p), + } + }) } } @@ -1380,7 +1386,7 @@ impl<'a> Format<'a> for ArrayExpressionElement<'a> { impl<'a> Format<'a> for SpreadElement<'a> { fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> { - array![p, ss!("..."), format!(p, self.argument)] + wrap!(p, self, SpreadElement, { array![p, ss!("..."), format!(p, self.argument)] }) } } @@ -1488,16 +1494,18 @@ impl<'a> Format<'a> for ArrowExpression<'a> { impl<'a> Format<'a> for YieldExpression<'a> { fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> { - let mut parts = p.vec(); - parts.push(ss!("yield")); - if self.delegate { - parts.push(ss!("*")); - } - if let Some(argument) = &self.argument { - parts.push(ss!(" ")); - parts.push(format!(p, argument)); - } - Doc::Array(parts) + wrap!(p, self, YieldExpression, { + let mut parts = p.vec(); + parts.push(ss!("yield")); + if self.delegate { + parts.push(ss!("*")); + } + if let Some(argument) = &self.argument { + parts.push(ss!(" ")); + parts.push(format!(p, argument)); + } + Doc::Array(parts) + }) } } @@ -1693,8 +1701,7 @@ impl<'a> Format<'a> for SequenceExpression<'a> { impl<'a> Format<'a> for ParenthesizedExpression<'a> { fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> { - // TODO: This wrap need to be removed and all logic should go into `need_parens`. - wrap!(p, self, ParenthesizedExpression, { self.expression.format(p) }) + unreachable!("Parser preserve_parens option need to be set to false."); } } @@ -1738,19 +1745,21 @@ impl<'a> Format<'a> for TemplateElement { impl<'a> Format<'a> for TaggedTemplateExpression<'a> { fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> { - let mut parts = p.vec(); + wrap!(p, self, TaggedTemplateExpression, { + let mut parts = p.vec(); - parts.push(format!(p, self.tag)); + parts.push(format!(p, self.tag)); - if let Some(type_parameters) = &self.type_parameters { - parts.push(string!(p, "<")); - parts.push(format!(p, type_parameters)); - parts.push(string!(p, ">")); - } + if let Some(type_parameters) = &self.type_parameters { + parts.push(string!(p, "<")); + parts.push(format!(p, type_parameters)); + parts.push(string!(p, ">")); + } - parts.push(format!(p, self.quasi)); + parts.push(format!(p, self.quasi)); - Doc::Array(parts) + Doc::Array(parts) + }) } } @@ -1805,7 +1814,7 @@ impl<'a> Format<'a> for MetaProperty { impl<'a> Format<'a> for Class<'a> { fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> { - class::print_class(p, self) + wrap!(p, self, Class, { class::print_class(p, self) }) } } diff --git a/crates/oxc_prettier/src/need_parens.rs b/crates/oxc_prettier/src/need_parens.rs index f6e70c253..45e6b6118 100644 --- a/crates/oxc_prettier/src/need_parens.rs +++ b/crates/oxc_prettier/src/need_parens.rs @@ -1,4 +1,19 @@ -use oxc_ast::AstKind; +//! Direct port of needs-parens for adding or removing parentheses. +//! +//! See + +#![allow( + clippy::unused_self, + clippy::match_same_arms, + clippy::match_like_matches_macro, + clippy::single_match +)] +use oxc_ast::{ + ast::{AssignmentTarget, ChainElement, Expression, ModuleDeclaration, SimpleAssignmentTarget}, + AstKind, +}; +use oxc_span::{GetSpan, Span}; +use oxc_syntax::operator::{BinaryOperator, UnaryOperator, UpdateOperator}; use crate::{array, doc::Doc, ss, Prettier}; @@ -12,35 +27,305 @@ impl<'a> Prettier<'a> { } fn need_parens(&self, kind: AstKind<'a>) -> bool { - match kind { - // Only statements don't need parentheses. - kind if kind.is_statement() => return false, - AstKind::SequenceExpression(_) => { - let parent = self.parent_kind(); - - if matches!(parent, AstKind::Program(_)) { - return false; - } - } - AstKind::ObjectExpression(_) => { - let parent = self.parent_kind(); - - if matches!(parent, AstKind::Program(_)) { - return true; - } - } - AstKind::AssignmentExpression(_) => { - let parent = self.parent_kind(); - - if matches!(parent, AstKind::ArrowExpression(arrow_expr) if arrow_expr.expression) { - return true; - } - } - // NOTE: This is a fallback which should be removed when all code are ported. - AstKind::ParenthesizedExpression(_) => return true, - _ => {} + let parent_kind = self.parent_kind(); + if self.check_parent_kind(kind, parent_kind) { + return true; } + match kind { + AstKind::SequenceExpression(_) => !matches!(parent_kind, AstKind::Program(_)), + AstKind::ObjectExpression(e) => self.check_object_function_class(e.span), + AstKind::Function(f) if f.expression => self.check_object_function_class(f.span), + AstKind::Class(c) if c.is_expression() => self.check_object_function_class(c.span), + AstKind::AssignmentExpression(_) => { + matches!(parent_kind, AstKind::ArrowExpression(arrow_expr) if arrow_expr.expression) + } + AstKind::UpdateExpression(update_expr) => match parent_kind { + AstKind::UnaryExpression(unary_expr) => { + update_expr.prefix + && ((update_expr.operator == UpdateOperator::Increment + && unary_expr.operator == UnaryOperator::UnaryPlus) + || (update_expr.operator == UpdateOperator::Decrement + && unary_expr.operator == UnaryOperator::UnaryNegation)) + } + _ => self.check_update_unary(update_expr.span), + }, + AstKind::UnaryExpression(unary_expr) => match parent_kind { + AstKind::UnaryExpression(parent_expr) => { + let u_op = unary_expr.operator; + u_op == parent_expr.operator + && (matches!(u_op, UnaryOperator::UnaryPlus | UnaryOperator::UnaryNegation)) + } + _ => self.check_update_unary(unary_expr.span), + }, + AstKind::YieldExpression(e) => match parent_kind { + AstKind::AwaitExpression(_) => true, + _ => self.check_yield_await(e.span), + }, + AstKind::AwaitExpression(e) => self.check_yield_await(e.span), + AstKind::TSTypeAssertion(e) => self.check_binarish(e.span), + AstKind::TSAsExpression(e) => self.check_binarish(e.span), + AstKind::TSSatisfiesExpression(e) => self.check_binarish(e.span), + AstKind::LogicalExpression(e) => self.check_binarish(e.span), + AstKind::BinaryExpression(e) => match parent_kind { + AstKind::UpdateExpression(_) => true, + _ => self.check_binarish(e.span), + }, + AstKind::MemberExpression(e) => self.check_member_call(e.span()), + AstKind::CallExpression(e) => self.check_member_call(e.span), + AstKind::TaggedTemplateExpression(e) => { + self.check_member_call_tagged_template_ts_non_null(e.span) + } + AstKind::TSNonNullExpression(e) => { + self.check_member_call_tagged_template_ts_non_null(e.span) + } + AstKind::Function(e) if e.expression => match parent_kind { + AstKind::CallExpression(call_expr) => call_expr.callee.span() == e.span, + AstKind::NewExpression(new_expr) => new_expr.callee.span() == e.span, + AstKind::TaggedTemplateExpression(_) => true, + _ => false, + }, + AstKind::ArrowExpression(e) => match parent_kind { + AstKind::CallExpression(call_expr) => call_expr.callee.span() == e.span, + AstKind::NewExpression(new_expr) => new_expr.callee.span() == e.span, + AstKind::MemberExpression(member_expr) => member_expr.object().span() == e.span, + AstKind::TSAsExpression(_) + | AstKind::TSSatisfiesExpression(_) + | AstKind::TSNonNullExpression(_) + | AstKind::TaggedTemplateExpression(_) + | AstKind::UnaryExpression(_) + | AstKind::LogicalExpression(_) + | AstKind::AwaitExpression(_) + | AstKind::TSTypeAssertion(_) => true, + AstKind::ConditionalExpression(cond_expr) => cond_expr.test.span() == e.span, + _ => false, + }, + AstKind::Class(class) if class.is_expression() => match parent_kind { + AstKind::NewExpression(new_expr) => new_expr.callee.span() == class.span, + _ => false, + }, + _ => false, + } + } + + fn check_parent_kind(&self, kind: AstKind<'a>, parent_kind: AstKind<'a>) -> bool { + match parent_kind { + AstKind::Class(class) => { + if let Some(h) = &class.super_class { + match kind { + AstKind::ArrowExpression(e) if e.span == h.span() => return true, + AstKind::AssignmentExpression(e) if e.span == h.span() => return true, + AstKind::AwaitExpression(e) if e.span == h.span() => return true, + AstKind::BinaryExpression(e) if e.span == h.span() => return true, + AstKind::ConditionalExpression(e) if e.span == h.span() => return true, + AstKind::LogicalExpression(e) if e.span == h.span() => return true, + AstKind::NewExpression(e) if e.span == h.span() => return true, + AstKind::ObjectExpression(e) if e.span == h.span() => return true, + AstKind::SequenceExpression(e) if e.span == h.span() => return true, + AstKind::TaggedTemplateExpression(e) if e.span == h.span() => return true, + AstKind::UnaryExpression(e) if e.span == h.span() => return true, + AstKind::UpdateExpression(e) if e.span == h.span() => return true, + AstKind::YieldExpression(e) if e.span == h.span() => return true, + AstKind::TSNonNullExpression(e) if e.span == h.span() => return true, + AstKind::Class(e) + if e.is_expression() + && !e.decorators.is_empty() + && e.span == h.span() => + { + return true + } + _ => {} + } + } + } + AstKind::ModuleDeclaration(ModuleDeclaration::ExportDefaultDeclaration(_)) => { + return matches!(kind, AstKind::SequenceExpression(_)) + || self.should_wrap_function_for_export_default(kind) + } + _ => {} + } false } + + fn check_object_function_class(&self, span: Span) -> bool { + for ast_kind in self.nodes.iter().rev() { + if let AstKind::ExpressionStatement(e) = ast_kind { + if Self::starts_with_no_lookahead_token(&e.expression, span) { + return true; + } + } + } + false + } + + fn check_update_unary(&self, span: Span) -> bool { + match self.parent_kind() { + AstKind::MemberExpression(member_expr) => member_expr.object().span() == span, + AstKind::TaggedTemplateExpression(_) => true, + AstKind::CallExpression(call_expr) => call_expr.callee.span() == span, + AstKind::NewExpression(new_expr) => new_expr.callee.span() == span, + AstKind::BinaryExpression(bin_expr) => { + bin_expr.left.span() == span && bin_expr.operator == BinaryOperator::Exponential + } + AstKind::TSNonNullExpression(_) => true, + _ => false, + } + } + + fn check_yield_await(&self, span: Span) -> bool { + match self.parent_kind() { + AstKind::TaggedTemplateExpression(_) + | AstKind::UnaryExpression(_) + | AstKind::LogicalExpression(_) + | AstKind::SpreadElement(_) + | AstKind::TSAsExpression(_) + | AstKind::TSSatisfiesExpression(_) + | AstKind::TSNonNullExpression(_) + | AstKind::BinaryExpression(_) => true, + AstKind::MemberExpression(member_expr) => member_expr.object().span() == span, + AstKind::NewExpression(new_expr) => new_expr.callee.span() == span, + AstKind::CallExpression(new_expr) => new_expr.callee.span() == span, + AstKind::ConditionalExpression(con_expr) => con_expr.test.span() == span, + _ => false, + } + } + + fn check_binarish(&self, span: Span) -> bool { + match self.parent_kind() { + AstKind::TSAsExpression(_) => !self.is_binary_cast_expression(span), + AstKind::TSSatisfiesExpression(_) => !self.is_binary_cast_expression(span), + AstKind::ConditionalExpression(_) => self.is_binary_cast_expression(span), + AstKind::NewExpression(new_expr) => new_expr.callee.span() == span, + AstKind::CallExpression(new_expr) => new_expr.callee.span() == span, + AstKind::Class(class) => class.super_class.as_ref().is_some_and(|e| e.span() == span), + AstKind::TSTypeAssertion(_) + | AstKind::TaggedTemplateExpression(_) + | AstKind::UnaryExpression(_) + | AstKind::JSXSpreadAttribute(_) + | AstKind::SpreadElement(_) + | AstKind::AwaitExpression(_) + | AstKind::TSNonNullExpression(_) + | AstKind::UpdateExpression(_) => true, + AstKind::MemberExpression(member_expr) => member_expr.object().span() == span, + AstKind::AssignmentExpression(assign_expr) => { + assign_expr.left.span() == span && self.is_binary_cast_expression(span) + } + AstKind::AssignmentPattern(assign_pat) => { + assign_pat.left.span() == span && self.is_binary_cast_expression(span) + } + _ => false, + } + } + + fn check_member_call(&self, span: Span) -> bool { + // if (shouldAddParenthesesToChainElement(path)) { + // return true; + // } + self.check_member_call_tagged_template_ts_non_null(span) + } + + fn check_member_call_tagged_template_ts_non_null(&self, span: Span) -> bool { + match self.parent_kind() { + AstKind::NewExpression(new_expr) if new_expr.callee.span() == span => true, + _ => false, + } + } + + fn should_wrap_function_for_export_default(&self, kind: AstKind<'a>) -> bool { + matches!(kind, AstKind::Function(f) if f.expression) + || matches!(kind, AstKind::Class(c) if c.is_expression()) + } + + fn is_binary_cast_expression(&self, _span: Span) -> bool { + false + } + + fn starts_with_no_lookahead_token(e: &Expression<'a>, span: Span) -> bool { + match e { + Expression::BinaryExpression(e) => Self::starts_with_no_lookahead_token(&e.left, span), + Expression::LogicalExpression(e) => Self::starts_with_no_lookahead_token(&e.left, span), + Expression::AssignmentExpression(e) => match &e.left { + AssignmentTarget::SimpleAssignmentTarget(t) => match t { + SimpleAssignmentTarget::AssignmentTargetIdentifier(_) => false, + SimpleAssignmentTarget::MemberAssignmentTarget(e) => { + Self::starts_with_no_lookahead_token(e.object(), span) + } + SimpleAssignmentTarget::TSAsExpression(e) => { + Self::starts_with_no_lookahead_token(&e.expression, span) + } + SimpleAssignmentTarget::TSSatisfiesExpression(e) => { + Self::starts_with_no_lookahead_token(&e.expression, span) + } + SimpleAssignmentTarget::TSNonNullExpression(e) => { + Self::starts_with_no_lookahead_token(&e.expression, span) + } + SimpleAssignmentTarget::TSTypeAssertion(e) => { + Self::starts_with_no_lookahead_token(&e.expression, span) + } + }, + AssignmentTarget::AssignmentTargetPattern(_) => false, + }, + Expression::MemberExpression(e) => { + Self::starts_with_no_lookahead_token(e.object(), span) + } + Expression::TaggedTemplateExpression(e) => { + if matches!(e.tag, Expression::FunctionExpression(_)) { + return false; + } + Self::starts_with_no_lookahead_token(&e.tag, span) + } + Expression::CallExpression(e) => { + if matches!(e.callee, Expression::FunctionExpression(_)) { + return false; + } + Self::starts_with_no_lookahead_token(&e.callee, span) + } + Expression::ConditionalExpression(e) => { + Self::starts_with_no_lookahead_token(&e.test, span) + } + Expression::UpdateExpression(e) => { + !e.prefix + && match &e.argument { + SimpleAssignmentTarget::AssignmentTargetIdentifier(_) => false, + SimpleAssignmentTarget::MemberAssignmentTarget(e) => { + Self::starts_with_no_lookahead_token(e.object(), span) + } + SimpleAssignmentTarget::TSAsExpression(e) => { + Self::starts_with_no_lookahead_token(&e.expression, span) + } + SimpleAssignmentTarget::TSSatisfiesExpression(e) => { + Self::starts_with_no_lookahead_token(&e.expression, span) + } + SimpleAssignmentTarget::TSNonNullExpression(e) => { + Self::starts_with_no_lookahead_token(&e.expression, span) + } + SimpleAssignmentTarget::TSTypeAssertion(e) => { + Self::starts_with_no_lookahead_token(&e.expression, span) + } + } + } + Expression::SequenceExpression(e) => e + .expressions + .get(0) + .map_or(false, |e| Self::starts_with_no_lookahead_token(e, span)), + Expression::ChainExpression(e) => match &e.expression { + ChainElement::CallExpression(e) => { + Self::starts_with_no_lookahead_token(&e.callee, span) + } + ChainElement::MemberExpression(e) => { + Self::starts_with_no_lookahead_token(e.object(), span) + } + }, + Expression::TSSatisfiesExpression(e) => { + Self::starts_with_no_lookahead_token(&e.expression, span) + } + Expression::TSAsExpression(e) => { + Self::starts_with_no_lookahead_token(&e.expression, span) + } + Expression::TSNonNullExpression(e) => { + Self::starts_with_no_lookahead_token(&e.expression, span) + } + _ => e.span() == span, + } + } } diff --git a/tasks/prettier_conformance/prettier.snap.md b/tasks/prettier_conformance/prettier.snap.md index 1616584ce..cbbbbed9a 100644 --- a/tasks/prettier_conformance/prettier.snap.md +++ b/tasks/prettier_conformance/prettier.snap.md @@ -1,4 +1,4 @@ -Compatibility: 138/601 (22.96%) +Compatibility: 131/601 (21.80%) # Failed @@ -85,7 +85,6 @@ Compatibility: 138/601 (22.96%) * assignment-comments/string.js ### async -* async/await-parse.js * async/conditional-expression.js * async/inline-await.js * async/nested.js @@ -136,6 +135,9 @@ Compatibility: 138/601 (22.96%) ### call/invalid * call/invalid/null-arguments-item.js +### chain-expression +* chain-expression/test.js + ### class-comment * class-comment/class-property.js * class-comment/misc.js @@ -313,14 +315,21 @@ Compatibility: 138/601 (22.96%) * eol/range-1.js * eol/range-and-cursor-1.js +### es6modules +* es6modules/export_default_function_expression.js +* es6modules/export_default_function_expression_named.js + ### export * export/blank-line-between-specifiers.js * export/same-local-and-exported.js ### export-default * export-default/binary_and_template.js +* export-default/body.js +* export-default/class_instance.js * export-default/function_in_template.js * export-default/function_tostring.js +* export-default/iife.js ### export-default/escaped * export-default/escaped/default-escaped.js @@ -330,12 +339,14 @@ Compatibility: 138/601 (22.96%) ### expression_statement * expression_statement/no_regression.js +* expression_statement/use_strict.js ### for * for/comment.js * for/continue-and-break-comment-1.js * for/continue-and-break-comment-2.js * for/continue-and-break-comment-without-blocks.js +* for/in.js ### function * function/function_expression.js @@ -371,6 +382,7 @@ Compatibility: 138/601 (22.96%) * generator/async.js ### identifier/for-of +* identifier/for-of/await.js * identifier/for-of/let.js ### identifier/parentheses @@ -411,6 +423,12 @@ Compatibility: 138/601 (22.96%) ### line-suffix-boundary * line-suffix-boundary/boundary.js +### literal +* literal/number.js + +### logical-assignment +* logical-assignment/logical-assignment.js + ### logical_expressions * logical_expressions/issue-7024.js * logical_expressions/logical_expression_operators.js @@ -446,6 +464,9 @@ Compatibility: 138/601 (22.96%) * method-chain/this.js * method-chain/tuple-and-record.js +### method-chain/print-width-120 +* method-chain/print-width-120/constructor.js + ### module-blocks * module-blocks/comments.js * module-blocks/module-blocks.js @@ -649,11 +670,9 @@ Compatibility: 138/601 (22.96%) ### unary * unary/object.js -* unary/series.js ### unary-expression * unary-expression/comments.js -* unary-expression/urnary_expression.js ### unicode * unicode/combining-characters.js @@ -666,7 +685,5 @@ Compatibility: 138/601 (22.96%) * while/indent.js ### yield -* yield/arrow.js -* yield/conditional.js * yield/jsx-without-parenthesis.js * yield/jsx.js \ No newline at end of file diff --git a/tasks/prettier_conformance/src/lib.rs b/tasks/prettier_conformance/src/lib.rs index 2d4a30100..e2692cb5e 100644 --- a/tasks/prettier_conformance/src/lib.rs +++ b/tasks/prettier_conformance/src/lib.rs @@ -311,7 +311,7 @@ impl TestRunner { fn prettier(path: &Path, source_text: &str, prettier_options: PrettierOptions) -> String { let allocator = Allocator::default(); let source_type = SourceType::from_path(path).unwrap(); - let ret = Parser::new(&allocator, source_text, source_type).parse(); + let ret = Parser::new(&allocator, source_text, source_type).preserve_parens(false).parse(); Prettier::new(&allocator, source_text, ret.trivias, prettier_options).build(&ret.program) } }