Fix a bunch of parser/formatter bugs found in fuzzing

Notably:
* Unified how parens are formatted between (1) when we have a ParensAround, and (2) when we've decided an Apply needs to have parens
* Made unary minus require the be indented to the same level as any other expression continuation. (it used to accidentally have rules meant for binary operators applied)
* Don't apply extra indent to the backpassing continuation in the case that the call does itself require indentation
* Make `try@foo` correctly parse as `try @foo`, so that formatting doesn't change the tree when it adds that space
* Detect more cases where we need to outdent trailing e.g. {} blocks in applies
* Approximately a bagillion other things, 90% of which I added tests for, and none of which affected the formatting of examples or builtins
This commit is contained in:
Joshua Warner 2024-11-17 19:34:47 -08:00
parent 335a8eb258
commit ed62bcc15a
No known key found for this signature in database
GPG key ID: 89AD497003F93FDD
347 changed files with 8219 additions and 1162 deletions

View file

@ -18,12 +18,14 @@ pub struct Buf<'a> {
spaces_to_flush: usize,
newlines_to_flush: usize,
beginning_of_line: bool,
line_indent: u16,
}
impl<'a> Buf<'a> {
pub fn new_in(arena: &'a Bump) -> Buf<'a> {
Buf {
text: String::new_in(arena),
line_indent: 0,
spaces_to_flush: 0,
newlines_to_flush: 0,
beginning_of_line: true,
@ -40,11 +42,18 @@ impl<'a> Buf<'a> {
pub fn indent(&mut self, indent: u16) {
if self.beginning_of_line {
self.line_indent = indent;
self.spaces_to_flush = indent as usize;
}
self.beginning_of_line = false;
}
pub fn cur_line_indent(&self) -> u16 {
debug_assert!(!self.beginning_of_line, "cur_line_indent before indent");
self.line_indent
}
#[track_caller]
pub fn push(&mut self, ch: char) {
debug_assert!(!self.beginning_of_line);
debug_assert!(
@ -61,6 +70,7 @@ impl<'a> Buf<'a> {
self.text.push(ch);
}
#[track_caller]
pub fn push_str_allow_spaces(&mut self, s: &str) {
debug_assert!(
!self.beginning_of_line,
@ -73,6 +83,7 @@ impl<'a> Buf<'a> {
self.text.push_str(s);
}
#[track_caller]
pub fn push_str(&mut self, s: &str) {
debug_assert!(
!self.beginning_of_line,
@ -129,6 +140,12 @@ impl<'a> Buf<'a> {
}
}
pub fn ensure_ends_with_whitespace(&mut self) {
if !self.text.is_empty() && self.newlines_to_flush == 0 && self.spaces_to_flush == 0 {
self.spaces_to_flush = 1;
}
}
fn flush_spaces(&mut self) {
for _ in 0..self.newlines_to_flush {
self.text.push('\n');