diff --git a/crates/oxc_formatter/examples/formatter.rs b/crates/oxc_formatter/examples/formatter.rs index 99eac76159716..e183cecf87363 100644 --- a/crates/oxc_formatter/examples/formatter.rs +++ b/crates/oxc_formatter/examples/formatter.rs @@ -8,12 +8,13 @@ //! Create a `test.js` file and run: //! ```bash //! cargo run -p oxc_formatter --example formatter [filename] +//! cargo run -p oxc_formatter --example formatter -- --no-semi [filename] //! ``` use std::{fs, path::Path}; use oxc_allocator::Allocator; -use oxc_formatter::{BracketSameLine, FormatOptions, Formatter}; +use oxc_formatter::{BracketSameLine, FormatOptions, Formatter, Semicolons}; use oxc_parser::{ParseOptions, Parser}; use oxc_span::SourceType; use pico_args::Arguments; @@ -21,6 +22,7 @@ use pico_args::Arguments; /// Format a JavaScript or TypeScript file fn main() -> Result<(), String> { let mut args = Arguments::from_env(); + let no_semi = args.contains("--no-semi"); let name = args.free_from_str().unwrap_or_else(|_| "test.js".to_string()); // Read source file @@ -46,8 +48,12 @@ fn main() -> Result<(), String> { } // Format the parsed code - let options = - FormatOptions { bracket_same_line: BracketSameLine::from(true), ..Default::default() }; + let semicolons = if no_semi { Semicolons::AsNeeded } else { Semicolons::Always }; + let options = FormatOptions { + bracket_same_line: BracketSameLine::from(true), + semicolons, + ..Default::default() + }; let code = Formatter::new(&allocator, options).build(&ret.program); println!("{code}"); diff --git a/crates/oxc_formatter/src/parentheses/expression.rs b/crates/oxc_formatter/src/parentheses/expression.rs index 46b2fce1ce895..4c189e6e04ee5 100644 --- a/crates/oxc_formatter/src/parentheses/expression.rs +++ b/crates/oxc_formatter/src/parentheses/expression.rs @@ -173,7 +173,7 @@ impl<'a> NeedsParentheses<'a> for AstNode<'a, CallExpression<'a>> { AstNodes::NewExpression(_) => true, AstNodes::Decorator(_) => !is_identifier_or_static_member_only(&self.callee), AstNodes::ExportDefaultDeclaration(_) => { - let callee = &self.callee; + let callee = &self.callee(); let callee_span = callee.span(); let leftmost = ExpressionLeftSide::leftmost(callee); // require parens for iife and @@ -181,9 +181,8 @@ impl<'a> NeedsParentheses<'a> for AstNode<'a, CallExpression<'a>> { callee_span != leftmost.span() && matches!( leftmost, - ExpressionLeftSide::Expression( - Expression::ClassExpression(_) | Expression::FunctionExpression(_) - ) + ExpressionLeftSide::Expression(e) + if matches!(e.as_ref(), Expression::ClassExpression(_) | Expression::FunctionExpression(_)) ) } _ => false, diff --git a/crates/oxc_formatter/src/write/arrow_function_expression.rs b/crates/oxc_formatter/src/write/arrow_function_expression.rs index 1c81f5cfa698b..ba4d540ea64ea 100644 --- a/crates/oxc_formatter/src/write/arrow_function_expression.rs +++ b/crates/oxc_formatter/src/write/arrow_function_expression.rs @@ -687,31 +687,31 @@ impl<'a> Format<'a> for ArrowChain<'a, '_> { #[derive(Debug)] pub enum ExpressionLeftSide<'a, 'b> { - Expression(&'b Expression<'a>), - AssignmentTarget(&'b AssignmentTarget<'a>), - SimpleAssignmentTarget(&'b SimpleAssignmentTarget<'a>), + Expression(&'b AstNode<'a, Expression<'a>>), + AssignmentTarget(&'b AstNode<'a, AssignmentTarget<'a>>), + SimpleAssignmentTarget(&'b AstNode<'a, SimpleAssignmentTarget<'a>>), } -impl<'a, 'b> From<&'b Expression<'a>> for ExpressionLeftSide<'a, 'b> { - fn from(value: &'b Expression<'a>) -> Self { +impl<'a, 'b> From<&'b AstNode<'a, Expression<'a>>> for ExpressionLeftSide<'a, 'b> { + fn from(value: &'b AstNode<'a, Expression<'a>>) -> Self { Self::Expression(value) } } -impl<'a, 'b> From<&'b AssignmentTarget<'a>> for ExpressionLeftSide<'a, 'b> { - fn from(value: &'b AssignmentTarget<'a>) -> Self { +impl<'a, 'b> From<&'b AstNode<'a, AssignmentTarget<'a>>> for ExpressionLeftSide<'a, 'b> { + fn from(value: &'b AstNode<'a, AssignmentTarget<'a>>) -> Self { Self::AssignmentTarget(value) } } -impl<'a, 'b> From<&'b SimpleAssignmentTarget<'a>> for ExpressionLeftSide<'a, 'b> { - fn from(value: &'b SimpleAssignmentTarget<'a>) -> Self { +impl<'a, 'b> From<&'b AstNode<'a, SimpleAssignmentTarget<'a>>> for ExpressionLeftSide<'a, 'b> { + fn from(value: &'b AstNode<'a, SimpleAssignmentTarget<'a>>) -> Self { Self::SimpleAssignmentTarget(value) } } impl<'a, 'b> ExpressionLeftSide<'a, 'b> { - pub fn leftmost(expression: &'b Expression<'a>) -> Self { + pub fn leftmost(expression: &'b AstNode<'a, Expression<'a>>) -> Self { let mut current: Self = expression.into(); loop { match current.left_expression() { @@ -729,60 +729,46 @@ impl<'a, 'b> ExpressionLeftSide<'a, 'b> { /// if the expression has no left side. pub fn left_expression(&self) -> Option { match self { - Self::Expression(expression) => match expression { - Expression::SequenceExpression(expr) => expr.expressions.first().map(Into::into), - Expression::StaticMemberExpression(expr) => Some((&expr.object).into()), - Expression::ComputedMemberExpression(expr) => Some((&expr.object).into()), - Expression::PrivateFieldExpression(expr) => Some((&expr.object).into()), - Expression::TaggedTemplateExpression(expr) => Some((&expr.tag).into()), - Expression::NewExpression(expr) => Some((&expr.callee).into()), - Expression::CallExpression(expr) => Some((&expr.callee).into()), - Expression::ConditionalExpression(expr) => Some((&expr.test).into()), - Expression::TSAsExpression(expr) => Some((&expr.expression).into()), - Expression::TSSatisfiesExpression(expr) => Some((&expr.expression).into()), - Expression::TSNonNullExpression(expr) => Some((&expr.expression).into()), - Expression::AssignmentExpression(expr) => Some(Self::AssignmentTarget(&expr.left)), - Expression::UpdateExpression(expr) => { + Self::Expression(expression) => match expression.as_ast_nodes() { + AstNodes::SequenceExpression(expr) => expr.expressions().first().map(Into::into), + AstNodes::StaticMemberExpression(expr) => Some(expr.object().into()), + AstNodes::ComputedMemberExpression(expr) => Some(expr.object().into()), + AstNodes::PrivateFieldExpression(expr) => Some(expr.object().into()), + AstNodes::TaggedTemplateExpression(expr) => Some(expr.tag().into()), + AstNodes::NewExpression(expr) => Some(expr.callee().into()), + AstNodes::CallExpression(expr) => Some(expr.callee().into()), + AstNodes::ConditionalExpression(expr) => Some(expr.test().into()), + AstNodes::TSAsExpression(expr) => Some(expr.expression().into()), + AstNodes::TSSatisfiesExpression(expr) => Some(expr.expression().into()), + AstNodes::TSNonNullExpression(expr) => Some(expr.expression().into()), + AstNodes::AssignmentExpression(expr) => Some(Self::AssignmentTarget(expr.left())), + AstNodes::UpdateExpression(expr) => { if expr.prefix { None } else { - Some(Self::SimpleAssignmentTarget(&expr.argument)) + Some(Self::SimpleAssignmentTarget(expr.argument())) } } - Expression::BinaryExpression(binary) => Some((&binary.left).into()), - Expression::LogicalExpression(logical) => Some((&logical.left).into()), - Expression::ChainExpression(chain) => match &chain.expression { - ChainElement::CallExpression(expr) => Some((&expr.callee).into()), - ChainElement::TSNonNullExpression(expr) => Some((&expr.expression).into()), - ChainElement::ComputedMemberExpression(expr) => Some((&expr.object).into()), - ChainElement::StaticMemberExpression(expr) => Some((&expr.object).into()), - ChainElement::PrivateFieldExpression(expr) => Some((&expr.object).into()), + AstNodes::BinaryExpression(binary) => Some(binary.left().into()), + AstNodes::LogicalExpression(logical) => Some(logical.left().into()), + AstNodes::ChainExpression(chain) => match &chain.expression().as_ast_nodes() { + AstNodes::CallExpression(expr) => Some(expr.callee().into()), + AstNodes::TSNonNullExpression(expr) => Some(expr.expression().into()), + AstNodes::ComputedMemberExpression(expr) => Some(expr.object().into()), + AstNodes::StaticMemberExpression(expr) => Some(expr.object().into()), + AstNodes::PrivateFieldExpression(expr) => Some(expr.object().into()), + _ => { + unreachable!() + } }, _ => None, }, - Self::AssignmentTarget(target) => match target { - match_simple_assignment_target!(AssignmentTarget) => { - Self::SimpleAssignmentTarget(target.to_simple_assignment_target()) - .left_expression() - } - _ => None, - }, - Self::SimpleAssignmentTarget(target) => match target { - SimpleAssignmentTarget::TSAsExpression(expr) => Some((&expr.expression).into()), - SimpleAssignmentTarget::TSSatisfiesExpression(expr) => { - Some((&expr.expression).into()) - } - SimpleAssignmentTarget::TSNonNullExpression(expr) => { - Some((&expr.expression).into()) - } - SimpleAssignmentTarget::TSTypeAssertion(expr) => Some((&expr.expression).into()), - SimpleAssignmentTarget::ComputedMemberExpression(expr) => { - Some((&expr.object).into()) - } - SimpleAssignmentTarget::StaticMemberExpression(expr) => Some((&expr.object).into()), - SimpleAssignmentTarget::PrivateFieldExpression(expr) => Some((&expr.object).into()), - SimpleAssignmentTarget::AssignmentTargetIdentifier(identifier_reference) => None, - }, + Self::AssignmentTarget(target) => { + Self::get_left_side_of_assignment(target.as_ast_nodes()) + } + Self::SimpleAssignmentTarget(target) => { + Self::get_left_side_of_assignment(target.as_ast_nodes()) + } } } @@ -793,10 +779,24 @@ impl<'a, 'b> ExpressionLeftSide<'a, 'b> { ExpressionLeftSide::SimpleAssignmentTarget(target) => target.span(), } } + + fn get_left_side_of_assignment(node: &'b AstNodes<'a>) -> Option> { + match node { + AstNodes::TSAsExpression(expr) => Some(expr.expression().into()), + AstNodes::TSSatisfiesExpression(expr) => Some(expr.expression().into()), + AstNodes::TSNonNullExpression(expr) => Some(expr.expression().into()), + AstNodes::TSTypeAssertion(expr) => Some(expr.expression().into()), + AstNodes::ComputedMemberExpression(expr) => Some(expr.object().into()), + AstNodes::StaticMemberExpression(expr) => Some(expr.object().into()), + AstNodes::PrivateFieldExpression(expr) => Some(expr.object().into()), + _ => None, + } + } } -fn should_add_parens(body: &FunctionBody) -> bool { - let Statement::ExpressionStatement(stmt) = body.statements.first().unwrap() else { +fn should_add_parens(body: &AstNode<'_, FunctionBody<'_>>) -> bool { + let AstNodes::ExpressionStatement(stmt) = body.statements().first().unwrap().as_ast_nodes() + else { unreachable!() }; @@ -805,11 +805,13 @@ fn should_add_parens(body: &FunctionBody) -> bool { // case and added by the object expression itself if matches!(&stmt.expression, Expression::ConditionalExpression(_)) { !matches!( - ExpressionLeftSide::leftmost(&stmt.expression), + ExpressionLeftSide::leftmost(stmt.expression()), ExpressionLeftSide::Expression( + e + ) if matches!(e.as_ref(), Expression::ObjectExpression(_) - | Expression::FunctionExpression(_) - | Expression::ClassExpression(_) + | Expression::FunctionExpression(_) + | Expression::ClassExpression(_) ) ) } else { diff --git a/crates/oxc_formatter/src/write/mod.rs b/crates/oxc_formatter/src/write/mod.rs index 6e034101faa83..1093d959a7680 100644 --- a/crates/oxc_formatter/src/write/mod.rs +++ b/crates/oxc_formatter/src/write/mod.rs @@ -53,7 +53,7 @@ use crate::{ }, }, generated::ast_nodes::{AstNode, AstNodes}, - options::{FormatTrailingCommas, QuoteProperties, TrailingSeparator}, + options::{FormatTrailingCommas, QuoteProperties, Semicolons, TrailingSeparator}, parentheses::NeedsParentheses, utils::{ assignment_like::AssignmentLike, @@ -382,7 +382,7 @@ impl<'a> FormatWrite<'a> for AstNode<'a, ArrayAssignmentTarget<'a>> { group(&soft_block_indent(&format_once(|f| { if !self.elements.is_empty() { write_array_node( - self.elements.len(), + self.elements.len() + usize::from(self.rest.is_some()), self.elements().iter().map(AstNode::as_ref), f, )?; @@ -589,8 +589,97 @@ impl<'a> FormatWrite<'a> for AstNode<'a, EmptyStatement> { } } +/// Returns `true` if the expression needs a leading semicolon to prevent ASI issues +fn expression_statement_needs_semicolon<'a>( + stmt: &AstNode<'a, ExpressionStatement<'a>>, + f: &mut Formatter<'_, 'a>, +) -> bool { + if matches!( + stmt.parent, + // `if (true) (() => {})` + AstNodes::IfStatement(_) + // `do ({} => {}) while (true)` + | AstNodes::DoWhileStatement(_) + // `while (true) (() => {})` + | AstNodes::WhileStatement(_) + // `for (;;) (() => {})` + | AstNodes::ForStatement(_) + // `for (i in o) (() => {})` + | AstNodes::ForInStatement(_) + // `for (i of o) (() => {})` + | AstNodes::ForOfStatement(_) + // `with(true) (() => {})` + | AstNodes::WithStatement(_) + // `label: (() => {})` + | AstNodes::LabeledStatement(_) + ) { + return false; + } + // Arrow functions need semicolon only if they will have parentheses + // e.g., `(a) => {}` needs `;(a) => {}` but `a => {}` doesn't need semicolon + if let Expression::ArrowFunctionExpression(arrow) = &stmt.expression { + return !can_avoid_parentheses(arrow, f); + } + + // First check if the expression itself needs protection + let expr = stmt.expression(); + + // Get the leftmost expression to check what the line starts with + let mut current = ExpressionLeftSide::Expression(expr); + loop { + let needs_semi = match current { + ExpressionLeftSide::Expression(expr) => { + expr.needs_parentheses(f) + || match expr.as_ref() { + Expression::ArrayExpression(_) + | Expression::RegExpLiteral(_) + | Expression::TSTypeAssertion(_) + | Expression::ArrowFunctionExpression(_) + | Expression::JSXElement(_) => true, + + Expression::TemplateLiteral(template) => true, + Expression::UnaryExpression(unary) => { + matches!( + unary.operator, + UnaryOperator::UnaryPlus | UnaryOperator::UnaryNegation + ) + } + _ => false, + } + } + ExpressionLeftSide::AssignmentTarget(assignment) => { + matches!( + assignment.as_ref(), + AssignmentTarget::ArrayAssignmentTarget(_) + | AssignmentTarget::TSTypeAssertion(_) + ) + } + ExpressionLeftSide::SimpleAssignmentTarget(assignment) => { + matches!( + assignment.as_ref(), + | SimpleAssignmentTarget::TSTypeAssertion(_) + ) + } + _ => false, + }; + + if needs_semi { + return true; + } + + if let Some(next) = current.left_expression() { current = next } else { return false } + } +} + impl<'a> FormatWrite<'a> for AstNode<'a, ExpressionStatement<'a>> { fn write(&self, f: &mut Formatter<'_, 'a>) -> FormatResult<()> { + // Check if we need a leading semicolon to prevent ASI issues + if f.options().semicolons == Semicolons::AsNeeded + && expression_statement_needs_semicolon(self, f) + { + write!(f, ";")?; + } + write!(f, [self.expression(), OptionalSemicolon]) } } @@ -932,7 +1021,7 @@ impl<'a> FormatWrite<'a> for AstNode<'a, ArrayPattern<'a>> { group(&soft_block_indent(&format_once(|f| { if !self.elements.is_empty() { write_array_node( - self.elements.len(), + self.elements.len() + usize::from(self.rest.is_some()), self.elements().iter().map(AstNode::as_ref), f, )?; diff --git a/crates/oxc_formatter/src/write/return_or_throw_statement.rs b/crates/oxc_formatter/src/write/return_or_throw_statement.rs index 4eb9f886eeb18..e4ca16d336856 100644 --- a/crates/oxc_formatter/src/write/return_or_throw_statement.rs +++ b/crates/oxc_formatter/src/write/return_or_throw_statement.rs @@ -122,7 +122,7 @@ impl<'a> Format<'a> for FormatReturnOrThrowArgument<'a, '_> { /// /// Traversing the left nodes is necessary in case the first node is parenthesized because /// parentheses will be removed (and be re-added by the return statement, but only if the argument breaks) -fn has_argument_leading_comments(argument: &Expression, f: &Formatter<'_, '_>) -> bool { +fn has_argument_leading_comments(argument: &AstNode, f: &Formatter<'_, '_>) -> bool { let source_text = f.source_text(); let mut current = Some(ExpressionLeftSide::from(argument)); @@ -147,7 +147,7 @@ fn has_argument_leading_comments(argument: &Expression, f: &Formatter<'_, '_>) - // This check is based on // if let ExpressionLeftSide::Expression(left_side) = left_side { - let has_leading_own_line_comment = match left_side { + let has_leading_own_line_comment = match left_side.as_ref() { Expression::ChainExpression(chain) => { if let ChainElement::StaticMemberExpression(member) = &chain.expression { is_line_comment_or_multi_line_comment( diff --git a/crates/oxc_formatter/src/write/semicolon.rs b/crates/oxc_formatter/src/write/semicolon.rs index eed9a11d459a0..7209f8e308834 100644 --- a/crates/oxc_formatter/src/write/semicolon.rs +++ b/crates/oxc_formatter/src/write/semicolon.rs @@ -42,23 +42,36 @@ impl<'a, 'b> ClassPropertySemicolon<'a, 'b> { fn needs_semicolon(&self) -> bool { let Self { element, next_element, .. } = self; - if let ClassElement::PropertyDefinition(def) = element.as_ref() { - if def.value.is_none() - && def.type_annotation.is_none() - && matches!(&def.key, PropertyKey::StaticIdentifier(ident) if matches!(ident.name.as_str(), "static" | "get" | "set") ) - { - return true; - } + if let ClassElement::PropertyDefinition(def) = element.as_ref() + && def.value.is_none() + && def.type_annotation.is_none() + && matches!(&def.key, PropertyKey::StaticIdentifier(ident) if matches!(ident.name.as_str(), "static" | "get" | "set") ) + { + return true; } let Some(next_element) = next_element else { return false }; - // TODO - // `needs_semicolon` in crates/biome_js_formatter/src/js/classes/property_class_member.rs match next_element.as_ref() { // When the name starts with the generator token or `[` - ClassElement::MethodDefinition(def) => { - !def.value.r#async && (def.computed || def.value.generator) + ClassElement::MethodDefinition(def) if !def.value.r#async => { + (def.computed + && !(def.kind.is_accessor() + || def.r#static + || def.accessibility.is_some() + || def.r#override)) + || def.value.generator + } + ClassElement::PropertyDefinition(def) => { + def.computed + && !(def.accessibility.is_some() + || def.r#static + || def.declare + || def.r#override + || def.readonly) + } + ClassElement::AccessorProperty(def) => { + def.computed && !(def.accessibility.is_some() || def.r#static || def.r#override) } _ => false, } diff --git a/crates/oxc_formatter/src/write/utils/array.rs b/crates/oxc_formatter/src/write/utils/array.rs index 1faf11bbe70f6..4ab591a00b3af 100644 --- a/crates/oxc_formatter/src/write/utils/array.rs +++ b/crates/oxc_formatter/src/write/utils/array.rs @@ -18,8 +18,6 @@ pub fn write_array_node<'a, 'b, N>( where N: Format<'a> + GetSpan + std::fmt::Debug + 'a, { - let trailing_separator = FormatTrailingCommas::ES5.trailing_separator(f.options()); - // Specifically do not use format_separated as arrays need separators // inserted after holes regardless of the formatting since this makes a // semantic difference diff --git a/tasks/prettier_conformance/snapshots/prettier.js.snap.md b/tasks/prettier_conformance/snapshots/prettier.js.snap.md index 7c406cd71474a..1bed134dd3bdb 100644 --- a/tasks/prettier_conformance/snapshots/prettier.js.snap.md +++ b/tasks/prettier_conformance/snapshots/prettier.js.snap.md @@ -1,31 +1,24 @@ -js compatibility: 603/699 (86.27%) +js compatibility: 616/699 (88.13%) # Failed | Spec path | Failed or Passed | Match ratio | | :-------- | :--------------: | :---------: | | js/arrows/curried.js | 💥💥 | 92.55% | -| js/arrows/semi/semi.js | 💥✨ | 0.00% | | js/assignment/sequence.js | 💥 | 71.43% | | js/class-comment/misc.js | 💥 | 72.73% | | js/comments/15661.js | 💥💥 | 55.81% | | js/comments/16398.js | 💥💥 | 80.00% | | js/comments/blank.js | 💥💥 | 95.24% | -| js/comments/dangling_array.js | 💥✨ | 40.00% | | js/comments/dynamic_imports.js | 💥💥 | 71.43% | | js/comments/empty-statements.js | 💥💥 | 90.91% | | js/comments/export.js | 💥💥 | 97.37% | -| js/comments/function-declaration.js | 💥💥 | 89.60% | -| js/comments/issues.js | 💥✨ | 48.53% | +| js/comments/function-declaration.js | 💥💥 | 92.80% | | js/comments/jsdoc-nestled-dangling.js | 💥💥 | 93.02% | | js/comments/jsdoc-nestled.js | 💥💥 | 89.29% | -| js/comments/jsdoc.js | 💥✨ | 48.08% | -| js/comments/jsx.js | 💥✨ | 40.74% | | js/comments/last-arg.js | 💥💥 | 80.65% | | js/comments/return-statement.js | 💥💥 | 98.27% | -| js/comments/template-literal.js | 💥✨ | 46.43% | | js/comments/trailing_space.js | 💥💥 | 60.00% | -| js/comments/variable_declarator.js | 💥✨ | 49.31% | | js/comments/html-like/comment.js | 💥 | 0.00% | | js/comments-closure-typecast/binary-expr.js | 💥 | 0.00% | | js/comments-closure-typecast/closure-compiler-type-cast.js | 💥 | 66.13% | @@ -46,8 +39,6 @@ js compatibility: 603/699 (86.27%) | js/conditional/new-ternary-examples.js | 💥✨ | 20.14% | | js/conditional/new-ternary-spec.js | 💥✨ | 24.35% | | js/conditional/postfix-ternary-regressions.js | 💥✨ | 20.77% | -| js/decorators/class-expression/class-expression.js | 💥✨ | 43.55% | -| js/decorators/class-expression/member-expression.js | 💥✨ | 37.50% | | js/destructuring-ignore/ignore.js | 💥💥💥 | 83.33% | | js/explicit-resource-management/valid-await-using-comments.js | 💥 | 91.89% | | js/explicit-resource-management/valid-for-await-using-binding-escaped-of-of.js | 💥 | 50.00% | @@ -57,7 +48,7 @@ js compatibility: 603/699 (86.27%) | js/for/parentheses.js | 💥 | 96.00% | | js/identifier/for-of/await.js | 💥 | 50.00% | | js/identifier/for-of/let.js | 💥 | 69.23% | -| js/identifier/parentheses/let.js | 💥💥 | 79.55% | +| js/identifier/parentheses/let.js | 💥💥 | 81.36% | | js/import-assertions/keyword-detect.js | 💥 | 71.43% | | js/import-attributes/keyword-detect.js | 💥 | 71.43% | | js/import-attributes/long-sources.js | 💥 | 75.00% | @@ -67,10 +58,6 @@ js compatibility: 603/699 (86.27%) | js/method-chain/comment.js | 💥 | 97.56% | | js/method-chain/conditional.js | 💥 | 85.19% | | js/new-expression/new_expression.js | 💥 | 55.56% | -| js/no-semi/class.js | 💥✨ | 46.55% | -| js/no-semi/comments.js | 💥✨ | 36.36% | -| js/no-semi/issue2006.js | 💥✨ | 37.50% | -| js/no-semi/no-semi.js | 💥💥 | 90.66% | | js/object-multiline/multiline.js | 💥✨ | 22.22% | | js/object-property-ignore/ignore.js | 💥💥💥 | 84.78% | | js/object-property-ignore/issue-5678.js | 💥💥💥 | 52.50% | diff --git a/tasks/prettier_conformance/snapshots/prettier.ts.snap.md b/tasks/prettier_conformance/snapshots/prettier.ts.snap.md index 09b971b1d7881..24804e37962b4 100644 --- a/tasks/prettier_conformance/snapshots/prettier.ts.snap.md +++ b/tasks/prettier_conformance/snapshots/prettier.ts.snap.md @@ -1,4 +1,4 @@ -ts compatibility: 326/573 (56.89%) +ts compatibility: 329/573 (57.42%) # Failed @@ -182,7 +182,6 @@ ts compatibility: 326/573 (56.89%) | typescript/module/namespace_function.ts | 💥 | 66.67% | | typescript/multiparser-css/issue-6259.ts | 💥 | 57.14% | | typescript/new/new-signature.ts | 💥 | 93.85% | -| typescript/no-semi/no-semi.ts | 💥✨ | 45.45% | | typescript/no-semi/non-null.ts | 💥💥 | 66.67% | | typescript/non-null/optional-chain.ts | 💥 | 72.22% | | typescript/non-null/parens.ts | 💥 | 80.00% | @@ -198,21 +197,19 @@ ts compatibility: 326/573 (56.89%) | typescript/prettier-ignore/prettier-ignore-parenthesized-type.ts | 💥 | 0.00% | | typescript/quote-props/types.ts | 💥💥💥 | 55.56% | | typescript/readonly/array.ts | 💥 | 0.00% | -| typescript/rest/rest.ts | 💥 | 0.00% | | typescript/rest-type/complex.ts | 💥 | 0.00% | | typescript/rest-type/infer-type.ts | 💥 | 72.00% | | typescript/satisfies-operators/argument-expansion.ts | 💥✨ | 46.77% | | typescript/satisfies-operators/assignment.ts | 💥💥 | 72.73% | -| typescript/satisfies-operators/basic.ts | 💥💥 | 93.33% | +| typescript/satisfies-operators/basic.ts | 💥✨ | 45.00% | | typescript/satisfies-operators/export-default-as.ts | 💥💥 | 0.00% | | typescript/satisfies-operators/expression-statement.ts | 💥💥 | 78.38% | | typescript/satisfies-operators/gt-lt.ts | 💥💥 | 0.00% | -| typescript/satisfies-operators/lhs.ts | 💥✨ | 30.00% | +| typescript/satisfies-operators/lhs.ts | 💥✨ | 35.00% | | typescript/satisfies-operators/nested-await-and-satisfies.ts | 💥💥 | 42.86% | | typescript/satisfies-operators/non-null.ts | 💥💥 | 66.67% | -| typescript/satisfies-operators/satisfies.ts | 💥💥 | 68.18% | +| typescript/satisfies-operators/satisfies.ts | 💥💥 | 81.82% | | typescript/satisfies-operators/ternary.ts | 💥💥 | 82.00% | -| typescript/satisfies-operators/types-comments.ts | 💥✨ | 33.33% | | typescript/semi/no-semi.ts | 💥 | 88.89% | | typescript/template-literal-types/template-literal-types.ts | 💥 | 73.33% | | typescript/test-declarations/test_declarations.ts | 💥💥 | 66.67% |