diff --git a/crates/oxc_prettier/src/doc.rs b/crates/oxc_prettier/src/doc.rs index 69323885b..ac83aea56 100644 --- a/crates/oxc_prettier/src/doc.rs +++ b/crates/oxc_prettier/src/doc.rs @@ -15,6 +15,7 @@ pub enum Doc<'a> { Array(Vec<'a, Doc<'a>>), /// Increase the level of indentation. Indent(Vec<'a, Doc<'a>>), + IndentIfBreak(Vec<'a, Doc<'a>>), /// Mark a group of items which the printer should try to fit on one line. /// This is the basic command to tell the printer when to break. /// Groups are usually nested, and the printer will try to fit everything on one line, @@ -117,6 +118,17 @@ fn print_do_to_debug(doc: &Doc<'_>) -> std::string::String { } string.push_str("])"); } + Doc::IndentIfBreak(contents) => { + string.push_str("indentIfBreak("); + string.push_str("[\n"); + for (idx, doc) in contents.iter().enumerate() { + string.push_str(&print_do_to_debug(doc)); + if idx != contents.len() - 1 { + string.push_str(", "); + } + } + string.push_str("]) \n"); + } Doc::Group(contents) => { string.push_str("group([\n"); for (idx, doc) in contents.iter().enumerate() { diff --git a/crates/oxc_prettier/src/macros.rs b/crates/oxc_prettier/src/macros.rs index ab85f855e..3a1f9aecf 100644 --- a/crates/oxc_prettier/src/macros.rs +++ b/crates/oxc_prettier/src/macros.rs @@ -35,6 +35,19 @@ macro_rules! indent { }; } +#[macro_export] +macro_rules! indent_if_break { + ($p:ident, $( $x:expr ),* $(,)?) => { + { + let mut temp_vec = $p.vec(); + $( + temp_vec.push($x); + )* + Doc::IndentIfBreak(temp_vec) + } + }; +} + #[macro_export] macro_rules! line { () => { diff --git a/crates/oxc_prettier/src/printer/mod.rs b/crates/oxc_prettier/src/printer/mod.rs index 3d60b4bb8..8210e1620 100644 --- a/crates/oxc_prettier/src/printer/mod.rs +++ b/crates/oxc_prettier/src/printer/mod.rs @@ -52,6 +52,7 @@ impl<'a> Printer<'a> { Doc::Array(docs) => self.handle_array(indent, mode, docs), Doc::Indent(docs) => self.handle_indent(indent, mode, docs), Doc::Group(docs) => self.handle_group(indent, mode, docs), + Doc::IndentIfBreak(docs) => self.handle_indent_if_break(indent, mode, docs), Doc::Line => self.handle_line(indent, mode), Doc::Softline => self.handle_softline(indent, mode), Doc::Hardline => self.handle_hardline(indent), @@ -102,6 +103,26 @@ impl<'a> Printer<'a> { } } + fn handle_indent_if_break( + &mut self, + indent: Indent, + mode: Mode, + docs: oxc_allocator::Vec<'a, Doc<'a>>, + ) { + match mode { + Mode::Flat => { + self.cmds.extend( + docs.into_iter().rev().map(|doc| Command::new(indent, Mode::Flat, doc)), + ); + } + Mode::Break => { + self.cmds.extend(docs.into_iter().rev().map(|doc| { + Command::new(Indent { length: indent.length + 1 }, Mode::Flat, doc) + })); + } + } + } + fn handle_line(&mut self, indent: Indent, mode: Mode) { if matches!(mode, Mode::Flat) { self.out.push(b' '); @@ -146,7 +167,10 @@ impl<'a> Printer<'a> { Doc::Str(string) => { remaining_width -= string.len() as isize; } - Doc::Array(docs) | Doc::Indent(docs) | Doc::Group(docs) => { + Doc::IndentIfBreak(docs) + | Doc::Array(docs) + | Doc::Indent(docs) + | Doc::Group(docs) => { // Prepend docs to the queue for d in docs.iter().rev() { queue.push_front(d);