diff --git a/crates/oxc_ast/src/ast/js.rs b/crates/oxc_ast/src/ast/js.rs index cfda1f6e5..c9c362bee 100644 --- a/crates/oxc_ast/src/ast/js.rs +++ b/crates/oxc_ast/src/ast/js.rs @@ -1,7 +1,7 @@ use std::{cell::Cell, fmt, hash::Hash}; use oxc_allocator::{Box, Vec}; -use oxc_span::{Atom, SourceType, Span}; +use oxc_span::{Atom, GetSpan, SourceType, Span}; use oxc_syntax::{ operator::{ AssignmentOperator, BinaryOperator, LogicalOperator, UnaryOperator, UpdateOperator, @@ -919,6 +919,15 @@ pub enum AssignmentTargetProperty<'a> { AssignmentTargetPropertyProperty(Box<'a, AssignmentTargetPropertyProperty<'a>>), } +impl<'a> GetSpan for AssignmentTargetProperty<'a> { + fn span(&self) -> Span { + match self { + Self::AssignmentTargetPropertyIdentifier(identifier) => identifier.span, + Self::AssignmentTargetPropertyProperty(literal) => literal.span, + } + } +} + /// Assignment Property - Identifier Reference #[derive(Debug, Hash)] #[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] @@ -1447,6 +1456,12 @@ pub struct BindingProperty<'a> { pub computed: bool, } +impl<'a> GetSpan for BindingProperty<'a> { + fn span(&self) -> Span { + self.span + } +} + #[derive(Debug, Hash)] #[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] pub struct ArrayPattern<'a> { diff --git a/crates/oxc_prettier/src/format/misc.rs b/crates/oxc_prettier/src/format/misc.rs index b10c6e3f8..62a4d41ca 100644 --- a/crates/oxc_prettier/src/format/misc.rs +++ b/crates/oxc_prettier/src/format/misc.rs @@ -18,3 +18,7 @@ pub(super) fn adjust_clause<'a>( indent![p, Doc::Line, clause] } + +pub(super) fn has_new_line_in_range(text: &str, start: u32, end: u32) -> bool { + text[(start as usize)..(end as usize)].contains('\n') +} diff --git a/crates/oxc_prettier/src/format/mod.rs b/crates/oxc_prettier/src/format/mod.rs index 8b0cb526f..d49b7bae1 100644 --- a/crates/oxc_prettier/src/format/mod.rs +++ b/crates/oxc_prettier/src/format/mod.rs @@ -36,6 +36,7 @@ use crate::{ use self::{ array::Array, binaryish::{BinaryishLeft, BinaryishOperator}, + object::ObjectLike, template_literal::TemplateLiteralPrinter, }; @@ -1361,7 +1362,7 @@ impl<'a> Format<'a> for ArrayExpression<'a> { impl<'a> Format<'a> for ObjectExpression<'a> { fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> { - object::print_object_properties(p, &self.properties) + object::print_object_properties(p, &ObjectLike::ObjectExpression(self), &self.properties) } } @@ -1582,7 +1583,11 @@ impl<'a> Format<'a> for AssignmentTargetMaybeDefault<'a> { impl<'a> Format<'a> for ObjectAssignmentTarget<'a> { fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> { - object::print_object_properties(p, &self.properties) + object::print_object_properties( + p, + &ObjectLike::ObjectAssignmentTarget(self), + &self.properties, + ) } } @@ -1938,7 +1943,7 @@ impl<'a> Format<'a> for BindingPattern<'a> { impl<'a> Format<'a> for ObjectPattern<'a> { fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> { - object::print_object_properties(p, &self.properties) + object::print_object_properties(p, &ObjectLike::ObjectPattern(self), &self.properties) } } diff --git a/crates/oxc_prettier/src/format/object.rs b/crates/oxc_prettier/src/format/object.rs index 972961c12..649322f95 100644 --- a/crates/oxc_prettier/src/format/object.rs +++ b/crates/oxc_prettier/src/format/object.rs @@ -1,14 +1,34 @@ use oxc_allocator::Vec; +use oxc_ast::ast::{ObjectAssignmentTarget, ObjectExpression, ObjectPattern}; +use oxc_span::{GetSpan, Span}; use crate::{ doc::{Doc, Group}, group, if_break, line, softline, ss, Prettier, }; -use super::Format; +use super::{misc, Format}; -pub(super) fn print_object_properties<'a, F: Format<'a>>( +#[allow(clippy::enum_variant_names)] +pub enum ObjectLike<'a, 'b> { + ObjectExpression(&'b ObjectExpression<'a>), + ObjectAssignmentTarget(&'b ObjectAssignmentTarget<'a>), + ObjectPattern(&'b ObjectPattern<'a>), +} + +impl ObjectLike<'_, '_> { + pub fn span(&self) -> Span { + match self { + ObjectLike::ObjectExpression(object) => object.span, + ObjectLike::ObjectAssignmentTarget(object) => object.span, + ObjectLike::ObjectPattern(object) => object.span, + } + } +} + +pub(super) fn print_object_properties<'a, F: Format<'a> + GetSpan>( p: &mut Prettier<'a>, + object: &ObjectLike<'a, '_>, properties: &Vec<'a, F>, ) -> Doc<'a> { let left_brace = ss!("{"); @@ -29,7 +49,18 @@ pub(super) fn print_object_properties<'a, F: Format<'a>>( indent_parts.push(Doc::Line); } } - parts.push(group!(p, Doc::Indent(indent_parts))); + + let should_break = misc::has_new_line_in_range( + p.source_text, + object.span().start, + // SAFETY: we checked above that `properties` is not empty + properties[0].span().start, + ); + + let mut group = p.vec(); + group.push(Doc::Indent(indent_parts)); + + parts.push(Doc::Group(Group::new(group, should_break))); parts.push(if_break!(p, ",")); if p.options.bracket_spacing { diff --git a/tasks/prettier_conformance/prettier.snap.md b/tasks/prettier_conformance/prettier.snap.md index d992869cb..e9111f762 100644 --- a/tasks/prettier_conformance/prettier.snap.md +++ b/tasks/prettier_conformance/prettier.snap.md @@ -1,4 +1,4 @@ -Compatibility: 109/601 (18.14%) +Compatibility: 110/601 (18.30%) # Failed @@ -89,7 +89,6 @@ Compatibility: 109/601 (18.14%) ### async * async/async-iteration.js -* async/async-shorthand-method.js * async/await-parse.js * async/conditional-expression.js * async/exponentiation.js