Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion crates/oxc_formatter/src/write/mapped_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::{
FormatResult,
ast_nodes::AstNode,
formatter::{Formatter, SourceText, prelude::*, trivia::FormatLeadingComments},
utils::suppressed::FormatSuppressedNode,
write,
write::semicolon::OptionalSemicolon,
};
Expand All @@ -12,6 +13,10 @@ use super::FormatWrite;

impl<'a> FormatWrite<'a> for AstNode<'a, TSMappedType<'a>> {
fn write(&self, f: &mut Formatter<'_, 'a>) -> FormatResult<()> {
if f.comments().is_suppressed(self.type_parameter.span.start) {
return write!(f, FormatSuppressedNode(self.span));
}

let type_parameter = self.type_parameter();
let name_type = self.name_type();
let should_expand = has_line_break_before_property_name(self, f.source_text());
Expand All @@ -22,7 +27,11 @@ impl<'a> FormatWrite<'a> for AstNode<'a, TSMappedType<'a>> {
let format_inner = format_with(|f| {
if should_expand {
let comments =
f.context().comments().comments_before_character(self.span.start, b'[');
if f.comments().has_leading_own_line_comment(self.type_parameter.span.start) {
f.context().comments().comments_before(self.type_parameter.span.start)
} else {
f.context().comments().comments_before_character(self.span.start, b'[')
};
write!(f, FormatLeadingComments::Comments(comments))?;
}

Expand Down
4 changes: 4 additions & 0 deletions crates/oxc_formatter/src/write/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1522,6 +1522,10 @@ impl GetSpan for FormatTSSignature<'_, '_> {

impl<'a> Format<'a> for FormatTSSignature<'a, '_> {
fn fmt(&self, f: &mut Formatter<'_, 'a>) -> FormatResult<()> {
if f.comments().is_suppressed(self.signature.span().start) {
return write!(f, [self.signature]);
}

write!(f, [group(&self.signature)])?;

match f.options().semicolons {
Expand Down
89 changes: 49 additions & 40 deletions crates/oxc_formatter/src/write/union_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ use crate::{
FormatResult, Formatter,
prelude::*,
trivia::{FormatLeadingComments, FormatTrailingComments},
write,
},
parentheses::NeedsParentheses,
utils::typescript::should_hug_type,
utils::{suppressed::FormatSuppressedNode, typescript::should_hug_type},
write,
write::FormatWrite,
};
Expand All @@ -28,7 +29,7 @@ impl<'a> FormatWrite<'a> for AstNode<'a, TSUnionType<'a>> {
// should be inlined and not be printed in the multi-line variant
let should_hug = should_hug_type(self, f);
if should_hug {
return format_union_types(self.types(), true, f);
return format_union_types(self.types(), Span::default(), true, f);
}

// Find the head of the nest union type chain
Expand Down Expand Up @@ -66,6 +67,12 @@ impl<'a> FormatWrite<'a> for AstNode<'a, TSUnionType<'a>> {
};

let types = format_with(|f| {
let suppressed_node_span = if f.comments().is_suppressed(self.span.start) {
self.types.first().unwrap().span()
} else {
Span::default()
};

if has_leading_comments {
write!(f, FormatLeadingComments::Comments(leading_comments))?;
}
Expand All @@ -81,7 +88,7 @@ impl<'a> FormatWrite<'a> for AstNode<'a, TSUnionType<'a>> {

write!(f, [if_group_breaks(&separator)])?;

format_union_types(types, false, f)
format_union_types(types, suppressed_node_span, false, f)
});

let content = format_with(|f| {
Expand Down Expand Up @@ -121,27 +128,40 @@ impl<'a> FormatWrite<'a> for AstNode<'a, TSUnionType<'a>> {
}
}

pub struct FormatTSType<'a, 'b> {
next_node_span: Option<Span>,
element: &'b AstNode<'a, TSType<'a>>,
fn format_union_types<'a>(
node: &AstNode<'a, Vec<'a, TSType<'a>>>,
mut suppressed_node_span: Span,
should_hug: bool,
}

impl<'a> Format<'a> for FormatTSType<'a, '_> {
fn fmt(&self, f: &mut Formatter<'_, 'a>) -> FormatResult<()> {
let format_element = format_once(|f| {
self.element.fmt(f)?;
Ok(())
});
if self.should_hug {
write!(f, [format_element])?;
f: &mut Formatter<'_, 'a>,
) -> FormatResult<()> {
let mut node_iter = node.iter().peekable();
while let Some(element) = node_iter.next() {
let element_span = element.span();

if suppressed_node_span == element_span {
let comments = f.context().comments().comments_before(suppressed_node_span.start);
FormatLeadingComments::Comments(comments).fmt(f)?;
let needs_parentheses = element.needs_parentheses(f);
if needs_parentheses {
write!(f, "(")?;
}
write!(f, [FormatSuppressedNode(element_span)])?;
if needs_parentheses {
write!(f, ")")?;
}
} else if should_hug {
write!(f, [element])?;
} else {
write!(f, [align(2, &format_element)])?;
write!(f, [align(2, &element)])?;
}

if let Some(next_node_span) = self.next_node_span {
if let Some(next_node_span) = node_iter.peek().map(GetSpan::span) {
if f.comments().is_suppressed(next_node_span.start) {
suppressed_node_span = next_node_span;
}

let comments_before_separator =
f.context().comments().comments_before_character(self.element.span().end, b'|');
f.context().comments().comments_before_character(element_span.end, b'|');
FormatTrailingComments::Comments(comments_before_separator).fmt(f)?;

// ```ts
Expand All @@ -163,13 +183,13 @@ impl<'a> Format<'a> for FormatTSType<'a, '_> {
FormatTrailingComments::Comments(comments).fmt(f)?;
}

if self.should_hug {
if should_hug {
write!(f, [space()])?;
} else {
write!(f, [soft_line_break_or_space()])?;
}
write!(f, ["|"])
} else if let AstNodes::TSUnionType(parent) = self.element.parent
write!(f, ["|"])?;
} else if let AstNodes::TSUnionType(parent) = element.parent
&& parent.needs_parentheses(f)
{
// ```ts
Expand All @@ -180,25 +200,14 @@ impl<'a> Format<'a> for FormatTSType<'a, '_> {
// )[]; // comment 3
//```
// TODO: We may need to tweak `AstNode<'a, Vec<'a, T>>` iterator as some of Vec's last elements should have the following span.
let comments =
f.context().comments().end_of_line_comments_after(self.element.span().end);
FormatTrailingComments::Comments(comments).fmt(f)
} else {
Ok(())
let comments = f.context().comments().end_of_line_comments_after(element_span.end);
write!(f, FormatTrailingComments::Comments(comments))?;
}

if node_iter.peek().is_some() {
write!(f, space())?;
}
}
}

fn format_union_types<'a>(
node: &AstNode<'a, Vec<'a, TSType<'a>>>,
should_hug: bool,
f: &mut Formatter<'_, 'a>,
) -> FormatResult<()> {
f.join_with(space())
.entries(node.iter().enumerate().map(|(index, item)| FormatTSType {
next_node_span: node.get(index + 1).map(GetSpan::span),
element: item,
should_hug,
}))
.finish()
Ok(())
}
7 changes: 2 additions & 5 deletions tasks/prettier_conformance/snapshots/prettier.ts.snap.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
ts compatibility: 533/573 (93.02%)
ts compatibility: 536/573 (93.54%)

# Failed

Expand Down Expand Up @@ -30,17 +30,14 @@ ts compatibility: 533/573 (93.02%)
| typescript/decorators-ts/angular.ts | 💥 | 87.50% |
| typescript/definite/without-annotation.ts | 💥 | 91.67% |
| typescript/enum/computed-members.ts | 💥 | 0.00% |
| typescript/interface/ignore.ts | 💥✨ | 40.09% |
| typescript/intersection/intersection-parens.ts | 💥💥 | 86.17% |
| typescript/intersection/consistent-with-flow/intersection-parens.ts | 💥 | 69.77% |
| typescript/last-argument-expansion/decorated-function.tsx | 💥 | 29.06% |
| typescript/multiparser-css/issue-6259.ts | 💥 | 57.14% |
| typescript/non-null/optional-chain.ts | 💥 | 72.22% |
| typescript/object-multiline/multiline.ts | 💥✨ | 23.21% |
| typescript/prettier-ignore/mapped-types.ts | 💥 | 63.16% |
| typescript/prettier-ignore/prettier-ignore-nested-unions.ts | 💥 | 68.00% |
| typescript/prettier-ignore/mapped-types.ts | 💥 | 94.92% |
| typescript/type-arguments-bit-shift-left-like/3.ts | 💥 | 0.00% |
| typescript/type-arguments-bit-shift-left-like/5.tsx | 💥 | 0.00% |
| typescript/union/union-parens.ts | 💥 | 92.59% |
| typescript/union/consistent-with-flow/prettier-ignore.ts | 💥 | 88.00% |
| typescript/union/single-type/single-type.ts | 💥 | 0.00% |
Loading