From 463c24e5ec091faae7d04702d0acd71a3fb7d67f Mon Sep 17 00:00:00 2001 From: "Alexander S." Date: Sat, 21 Sep 2024 17:27:12 +0200 Subject: [PATCH] fix(prettier): handle TSTypeLiteral as an object (#5946) - [x] semi is optional with the right configuration --- crates/oxc_prettier/src/format/mod.rs | 22 +-------- crates/oxc_prettier/src/format/object.rs | 45 +++++++++++++++---- .../snapshots/prettier.ts.snap.md | 16 +------ 3 files changed, 39 insertions(+), 44 deletions(-) diff --git a/crates/oxc_prettier/src/format/mod.rs b/crates/oxc_prettier/src/format/mod.rs index 4480d27ca91d9..4b8d744eed93b 100644 --- a/crates/oxc_prettier/src/format/mod.rs +++ b/crates/oxc_prettier/src/format/mod.rs @@ -1028,27 +1028,7 @@ impl<'a> Format<'a> for TSTupleType<'a> { impl<'a> Format<'a> for TSTypeLiteral<'a> { fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> { - let mut parts = p.vec(); - - parts.push(ss!("{")); - if self.members.len() > 0 { - let mut indent_parts = p.vec(); - - for member in &self.members { - indent_parts.extend(hardline!()); - indent_parts.push(member.format(p)); - - if let Some(semi) = p.semi() { - indent_parts.push(semi); - } - } - - parts.push(Doc::Indent(indent_parts)); - parts.extend(hardline!()); - } - parts.push(ss!("}")); - - Doc::Array(parts) + object::print_object_properties(p, ObjectLike::TSTypeLiteral(self)) } } diff --git a/crates/oxc_prettier/src/format/object.rs b/crates/oxc_prettier/src/format/object.rs index 3553899d6964b..3e321b671d1d5 100644 --- a/crates/oxc_prettier/src/format/object.rs +++ b/crates/oxc_prettier/src/format/object.rs @@ -1,5 +1,5 @@ use oxc_ast::{ - ast::{ObjectAssignmentTarget, ObjectExpression, ObjectPattern, WithClause}, + ast::{ObjectAssignmentTarget, ObjectExpression, ObjectPattern, TSTypeLiteral, WithClause}, AstKind, }; use oxc_span::Span; @@ -16,6 +16,7 @@ pub enum ObjectLike<'a, 'b> { AssignmentTarget(&'b ObjectAssignmentTarget<'a>), Pattern(&'b ObjectPattern<'a>), WithClause(&'b WithClause<'a>), + TSTypeLiteral(&'b TSTypeLiteral<'a>), } impl<'a, 'b> ObjectLike<'a, 'b> { @@ -25,6 +26,7 @@ impl<'a, 'b> ObjectLike<'a, 'b> { Self::AssignmentTarget(target) => target.properties.len(), Self::Pattern(object) => object.properties.len(), Self::WithClause(attributes) => attributes.with_entries.len(), + Self::TSTypeLiteral(literal) => literal.members.len(), } } @@ -33,7 +35,7 @@ impl<'a, 'b> ObjectLike<'a, 'b> { Self::Expression(expr) => false, Self::AssignmentTarget(target) => target.rest.is_some(), Self::Pattern(object) => object.rest.is_some(), - Self::WithClause(_) => false, + Self::WithClause(_) | Self::TSTypeLiteral(_) => false, } } @@ -43,6 +45,7 @@ impl<'a, 'b> ObjectLike<'a, 'b> { Self::AssignmentTarget(object) => object.is_empty(), Self::Pattern(object) => object.is_empty(), Self::WithClause(attributes) => attributes.with_entries.is_empty(), + Self::TSTypeLiteral(literal) => literal.members.is_empty(), } } @@ -56,6 +59,7 @@ impl<'a, 'b> ObjectLike<'a, 'b> { Self::AssignmentTarget(object) => object.span, Self::Pattern(object) => object.span, Self::WithClause(attributes) => attributes.span, + Self::TSTypeLiteral(literal) => literal.span, } } @@ -71,6 +75,22 @@ impl<'a, 'b> ObjectLike<'a, 'b> { Self::WithClause(attributes) => { Box::new(attributes.with_entries.iter().map(|entry| entry.format(p))) } + Self::TSTypeLiteral(literal) => { + Box::new(literal.members.iter().map(|member| member.format(p))) + } + } + } + + fn member_separator(self, p: &'b Prettier<'a>) -> &'a str { + match self { + Self::TSTypeLiteral(_) => { + if p.semi().is_some() { + ";" + } else { + "" + } + } + _ => ",", } } } @@ -83,6 +103,7 @@ pub(super) fn print_object_properties<'a>( let right_brace = ss!("}"); let should_break = false; + let member_separator = object.member_separator(p); let content = if object.is_empty() { group![p, left_brace, softline!(), right_brace] @@ -93,17 +114,21 @@ pub(super) fn print_object_properties<'a>( let len = object.len(); let has_rest = object.has_rest(); let mut indent_parts = p.vec(); + indent_parts.push(if p.options.bracket_spacing { line!() } else { softline!() }); for (i, doc) in object.iter(p).enumerate() { indent_parts.push(doc); if i == len - 1 && !has_rest { break; } - indent_parts.push(ss!(",")); + + indent_parts.push(ss!(member_separator)); indent_parts.push(line!()); } match object { - ObjectLike::Expression(_) | ObjectLike::WithClause(_) => {} + ObjectLike::Expression(_) + | ObjectLike::WithClause(_) + | ObjectLike::TSTypeLiteral(_) => {} ObjectLike::AssignmentTarget(target) => { if let Some(rest) = &target.rest { indent_parts.push(rest.format(p)); @@ -119,17 +144,21 @@ pub(super) fn print_object_properties<'a>( })); if p.should_print_es5_comma() && match object { - ObjectLike::Expression(expr) => true, - ObjectLike::AssignmentTarget(target) => true, ObjectLike::Pattern(pattern) => pattern.rest.is_none(), - ObjectLike::WithClause(_) => true, + _ => true, } { - parts.push(if_break!(p, ",", "", None)); + parts.push(if_break!(p, member_separator, "", None)); } parts.push(if p.options.bracket_spacing { line!() } else { softline!() }); parts.push(ss!("}")); + if matches!(p.current_kind(), AstKind::Program(_)) { + let should_break = + misc::has_new_line_in_range(p.source_text, object.span().start, object.span().end); + return Doc::Group(Group::new(parts).with_break(should_break)); + } + let parent_kind = p.parent_kind(); if (object.is_object_pattern() && should_hug_the_only_parameter(p, parent_kind)) || (!should_break diff --git a/tasks/prettier_conformance/snapshots/prettier.ts.snap.md b/tasks/prettier_conformance/snapshots/prettier.ts.snap.md index 6c59fbe0b7b81..0632152579b3f 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: 177/526 (33.65%) +ts compatibility: 185/526 (35.17%) # Failed @@ -45,7 +45,6 @@ ts compatibility: 177/526 (33.65%) * assignment/issue-10848.tsx * assignment/issue-10850.ts * assignment/issue-2482.ts -* assignment/issue-3122.ts * assignment/parenthesized.ts ### call-signature @@ -165,9 +164,6 @@ ts compatibility: 177/526 (33.65%) ### conformance/expressions/functionCalls * conformance/expressions/functionCalls/callWithSpreadES6.ts -### conformance/interfaces/interfaceDeclarations -* conformance/interfaces/interfaceDeclarations/interfaceWithMultipleBaseTypes2.ts - ### conformance/internalModules/importDeclarations * conformance/internalModules/importDeclarations/circularImportAlias.ts * conformance/internalModules/importDeclarations/exportImportAlias.ts @@ -194,9 +190,6 @@ ts compatibility: 177/526 (33.65%) * conformance/types/functions/functionOverloadErrorsSyntax.ts * conformance/types/functions/parameterInitializersForwardReferencing.ts -### conformance/types/intersectionType -* conformance/types/intersectionType/intersectionType.ts - ### conformance/types/mappedType * conformance/types/mappedType/mappedType.ts @@ -423,9 +416,6 @@ ts compatibility: 177/526 (33.65%) ### method * method/issue-10352-consistency.ts -* method/method-signature.ts -* method/semi.ts -* method/type_literal_optional_method.ts ### method-chain * method-chain/comment.ts @@ -461,10 +451,6 @@ ts compatibility: 177/526 (33.65%) ### optional-type * optional-type/complex.ts -### optional-variance -* optional-variance/basic.ts -* optional-variance/with-jsx.tsx - ### prettier-ignore * prettier-ignore/issue-14238.ts * prettier-ignore/mapped-types.ts