mirror of
https://github.com/danbulant/oxc
synced 2026-05-24 12:21:58 +00:00
feat(prettier) use groupId in fluid assignments (#1560)
This commit is contained in:
parent
7d9d04c569
commit
cda0b97ade
4 changed files with 77 additions and 50 deletions
|
|
@ -15,7 +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>>),
|
||||
IndentIfBreak(IndentIfBreak<'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,
|
||||
|
|
@ -77,18 +77,33 @@ impl Line {
|
|||
pub struct Group<'a> {
|
||||
pub contents: Vec<'a, Doc<'a>>,
|
||||
pub should_break: bool,
|
||||
pub id: Option<u32>,
|
||||
pub id: Option<GroupId>,
|
||||
}
|
||||
|
||||
impl<'a> Group<'a> {
|
||||
pub fn new(contents: Vec<'a, Doc<'a>>, should_break: bool) -> Self {
|
||||
Self { contents, should_break, id: None }
|
||||
}
|
||||
pub fn with_id(mut self, id: u32) -> Self {
|
||||
pub fn with_id(mut self, id: GroupId) -> Self {
|
||||
self.id = Some(id);
|
||||
self
|
||||
}
|
||||
}
|
||||
#[derive(Debug)]
|
||||
pub struct IndentIfBreak<'a> {
|
||||
pub contents: Vec<'a, Doc<'a>>,
|
||||
pub group_id: Option<GroupId>,
|
||||
}
|
||||
|
||||
impl<'a> IndentIfBreak<'a> {
|
||||
pub fn new(contents: Vec<'a, Doc<'a>>) -> Self {
|
||||
Self { contents, group_id: None }
|
||||
}
|
||||
pub fn with_id(mut self, id: GroupId) -> Self {
|
||||
self.group_id = Some(id);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Fill<'a> {
|
||||
|
|
@ -212,16 +227,21 @@ fn print_doc_to_debug(doc: &Doc<'_>) -> std::string::String {
|
|||
}
|
||||
string.push_str("])");
|
||||
}
|
||||
Doc::IndentIfBreak(contents) => {
|
||||
Doc::IndentIfBreak(indent_if_break) => {
|
||||
string.push_str("indentIfBreak(");
|
||||
string.push_str("[\n");
|
||||
for (idx, doc) in contents.iter().enumerate() {
|
||||
for (idx, doc) in indent_if_break.contents.iter().enumerate() {
|
||||
string.push_str(&print_doc_to_debug(doc));
|
||||
if idx != contents.len() - 1 {
|
||||
if idx != indent_if_break.contents.len() - 1 {
|
||||
string.push_str(", ");
|
||||
}
|
||||
}
|
||||
string.push_str("]) \n");
|
||||
|
||||
if let Some(id) = indent_if_break.group_id {
|
||||
string.push_str(&format!(", {{id: {id}}}"));
|
||||
}
|
||||
|
||||
string.push_str("])");
|
||||
}
|
||||
Doc::Group(group) => {
|
||||
string.push_str("group([\n");
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ use oxc_ast::{
|
|||
|
||||
use crate::{
|
||||
array,
|
||||
doc::{Doc, DocBuilder},
|
||||
doc::{Doc, DocBuilder, Group, IndentIfBreak},
|
||||
group, indent, line, ss, Format, Prettier,
|
||||
};
|
||||
|
||||
|
|
@ -67,14 +67,21 @@ fn print_assignment<'a>(
|
|||
}
|
||||
// First break right-hand side, then after operator
|
||||
Layout::Fluid => {
|
||||
group!(
|
||||
p,
|
||||
group!(p, left_doc),
|
||||
op,
|
||||
group!(p, indent!(p, line!())),
|
||||
// TODO: wrap `right_doc` in indent_if_break!() when we have support for group IDs.
|
||||
right_doc
|
||||
)
|
||||
let group_id = p.next_id();
|
||||
|
||||
let after_op = {
|
||||
let mut parts = p.vec();
|
||||
parts.push(indent!(p, line!()));
|
||||
Doc::Group(Group::new(parts, false).with_id(group_id))
|
||||
};
|
||||
|
||||
let right_doc = {
|
||||
let mut parts = p.vec();
|
||||
parts.push(group!(p, right_doc));
|
||||
Doc::IndentIfBreak(IndentIfBreak::new(parts).with_id(group_id))
|
||||
};
|
||||
|
||||
group!(p, group!(p, left_doc), op, after_op, right_doc)
|
||||
}
|
||||
Layout::BreakLhs => {
|
||||
group!(p, left_doc, op, ss!(" "), group!(p, right_doc))
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ use oxc_allocator::Allocator;
|
|||
use std::collections::{HashMap, VecDeque};
|
||||
|
||||
use crate::{
|
||||
doc::{Doc, DocBuilder, Fill, IfBreak, Line},
|
||||
doc::{Doc, DocBuilder, Fill, IfBreak, IndentIfBreak, Line},
|
||||
GroupId, PrettierOptions,
|
||||
};
|
||||
|
||||
|
|
@ -122,28 +122,24 @@ impl<'a> Printer<'a> {
|
|||
fn handle_group(&mut self, indent: Indent, mode: Mode, doc: Doc<'a>) {
|
||||
match mode {
|
||||
Mode::Flat => {
|
||||
let Doc::Group(group) = doc else {
|
||||
return;
|
||||
};
|
||||
let Doc::Group(group) = doc else { unreachable!() };
|
||||
self.cmds.extend(group.contents.into_iter().rev().map(|doc| {
|
||||
Command::new(indent, if group.should_break { Mode::Break } else { mode }, doc)
|
||||
}));
|
||||
|
||||
self.set_group_mode_from_last_cmd(group.id);
|
||||
}
|
||||
Mode::Break => {
|
||||
#[allow(clippy::cast_possible_wrap)]
|
||||
let remaining_width = self.remaining_width();
|
||||
let Doc::Group(group) = &doc else {
|
||||
return;
|
||||
};
|
||||
let Doc::Group(group) = &doc else { unreachable!() };
|
||||
let should_break = group.should_break;
|
||||
let id = group.id;
|
||||
let group_id = group.id;
|
||||
let cmd = Command::new(indent, Mode::Flat, doc);
|
||||
if !should_break && self.fits(&cmd, remaining_width) {
|
||||
self.cmds.push(Command::new(indent, Mode::Flat, cmd.doc));
|
||||
} else {
|
||||
let Doc::Group(group) = cmd.doc else {
|
||||
return;
|
||||
};
|
||||
let Doc::Group(group) = cmd.doc else { unreachable!() };
|
||||
self.cmds.extend(
|
||||
group
|
||||
.contents
|
||||
|
|
@ -152,34 +148,29 @@ impl<'a> Printer<'a> {
|
|||
.map(|doc| Command::new(indent, Mode::Break, doc)),
|
||||
);
|
||||
}
|
||||
|
||||
if let Some(id) = id {
|
||||
let Some(mode) = self.cmds.last().map(|cmd| cmd.mode) else { return };
|
||||
self.group_mode_map.insert(id, mode);
|
||||
}
|
||||
self.set_group_mode_from_last_cmd(group_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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)),
|
||||
);
|
||||
fn handle_indent_if_break(&mut self, indent: Indent, mode: Mode, doc: IndentIfBreak<'a>) {
|
||||
let IndentIfBreak { contents, group_id } = doc;
|
||||
let group_mode = group_id.map_or(Some(mode), |id| self.group_mode_map.get(&id).copied());
|
||||
|
||||
match group_mode {
|
||||
Some(Mode::Flat) => {
|
||||
self.cmds
|
||||
.extend(contents.into_iter().rev().map(|doc| Command::new(indent, mode, doc)));
|
||||
}
|
||||
Mode::Break => {
|
||||
Some(Mode::Break) => {
|
||||
self.cmds.extend(
|
||||
docs.into_iter()
|
||||
contents
|
||||
.into_iter()
|
||||
.rev()
|
||||
.map(|doc| Command::new(Indent::new(indent.length + 1), Mode::Break, doc)),
|
||||
.map(|doc| Command::new(Indent::new(indent.length + 1), mode, doc)),
|
||||
);
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -341,6 +332,12 @@ impl<'a> Printer<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn set_group_mode_from_last_cmd(&mut self, id: Option<GroupId>) {
|
||||
let Some(id) = id else { return };
|
||||
let Some(mode) = self.cmds.last().map(|cmd| cmd.mode) else { return };
|
||||
self.group_mode_map.insert(id, mode);
|
||||
}
|
||||
|
||||
#[allow(clippy::cast_possible_wrap)]
|
||||
fn fits(&self, next: &Command<'a>, width: isize) -> bool {
|
||||
let mut remaining_width = width;
|
||||
|
|
@ -353,7 +350,9 @@ impl<'a> Printer<'a> {
|
|||
Doc::Str(string) => {
|
||||
remaining_width -= string.len() as isize;
|
||||
}
|
||||
Doc::IndentIfBreak(docs) | Doc::Indent(docs) | Doc::Array(docs) => {
|
||||
Doc::IndentIfBreak(IndentIfBreak { contents: docs, .. })
|
||||
| Doc::Indent(docs)
|
||||
| Doc::Array(docs) => {
|
||||
// Prepend docs to the queue
|
||||
for d in docs.iter().rev() {
|
||||
queue.push_front((mode, d));
|
||||
|
|
@ -425,7 +424,9 @@ impl<'a> Printer<'a> {
|
|||
group.should_break
|
||||
}
|
||||
Doc::IfBreak(d) => Self::propagate_breaks(&mut d.break_contents),
|
||||
Doc::Array(arr) | Doc::Indent(arr) | Doc::IndentIfBreak(arr) => {
|
||||
Doc::Array(arr)
|
||||
| Doc::Indent(arr)
|
||||
| Doc::IndentIfBreak(IndentIfBreak { contents: arr, .. }) => {
|
||||
arr.iter_mut().any(|doc| Self::propagate_breaks(doc))
|
||||
}
|
||||
_ => false,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
Compatibility: 177/591 (29.95%)
|
||||
Compatibility: 178/591 (30.12%)
|
||||
|
||||
# Failed
|
||||
|
||||
|
|
@ -56,7 +56,6 @@ Compatibility: 177/591 (29.95%)
|
|||
* assignment/chain.js
|
||||
* assignment/discussion-15196.js
|
||||
* assignment/issue-10218.js
|
||||
* assignment/issue-1419.js
|
||||
* assignment/issue-15534.js
|
||||
* assignment/issue-2482-2.js
|
||||
* assignment/issue-2540.js
|
||||
|
|
|
|||
Loading…
Reference in a new issue