PNC for Patterns, stabilize formatting

This commit is contained in:
Anthony Bullard 2024-12-31 08:25:11 -06:00
parent bac165fd99
commit 3b0db07fa1
No known key found for this signature in database
78 changed files with 789 additions and 332 deletions

View file

@ -7,7 +7,8 @@ use crate::spaces::{fmt_comments_only, fmt_spaces, NewlineAt, INDENT};
use crate::Buf;
use bumpalo::Bump;
use roc_parse::ast::{
Base, CommentOrNewline, Pattern, PatternAs, Spaceable, Spaces, SpacesAfter, SpacesBefore,
Base, CommentOrNewline, Pattern, PatternApplyStyle, PatternAs, Spaceable, Spaces, SpacesAfter,
SpacesBefore,
};
use roc_parse::expr::merge_spaces;
use roc_region::all::Loc;
@ -72,7 +73,7 @@ impl<'a> Formattable for Pattern<'a> {
}
},
Pattern::StrLiteral(literal) => is_str_multiline(literal),
Pattern::Apply(pat, args) => {
Pattern::Apply(pat, args, _) => {
pat.is_multiline() || args.iter().any(|a| a.is_multiline())
}
@ -162,7 +163,22 @@ fn fmt_pattern_only(
buf.indent(indent);
buf.push_str(name);
}
Pattern::Apply(loc_pattern, loc_arg_patterns) => {
Pattern::Apply(
loc_pattern,
loc_arg_patterns,
style @ PatternApplyStyle::ParensAndCommas,
) => {
pattern_fmt_apply(
buf,
loc_pattern.value,
loc_arg_patterns,
Parens::NotNeeded,
indent,
is_multiline,
*style,
);
}
Pattern::Apply(loc_pattern, loc_arg_patterns, style) => {
pattern_fmt_apply(
buf,
loc_pattern.value,
@ -170,6 +186,7 @@ fn fmt_pattern_only(
parens,
indent,
is_multiline,
*style,
);
}
Pattern::RecordDestructure(loc_patterns) => {
@ -445,11 +462,14 @@ pub fn pattern_fmt_apply(
parens: Parens,
indent: u16,
is_multiline: bool,
style: PatternApplyStyle,
) {
let use_commas_and_parens =
matches!(style, PatternApplyStyle::ParensAndCommas) || buf.flags().parens_and_commas;
buf.indent(indent);
// Sometimes, an Apply pattern needs parens around it.
// In particular when an Apply's argument is itself an Apply (> 0) arguments
let parens = !args.is_empty() && parens == Parens::InApply;
let parens = !args.is_empty() && parens == Parens::InApply && !use_commas_and_parens;
let indent_more = if is_multiline {
indent + INDENT
@ -473,14 +493,27 @@ pub fn pattern_fmt_apply(
fmt_pattern_only(&func.item, buf, Parens::InApply, indent, is_multiline);
if use_commas_and_parens {
buf.push('(');
}
let mut last_after = func.after;
let mut add_newlines = is_multiline;
for loc_arg in args.iter() {
buf.spaces(1);
for (i, loc_arg) in args.iter().enumerate() {
let is_last_arg = i == args.len() - 1;
let is_first_arg = i == 0;
let parens = Parens::InApply;
if !(is_first_arg && use_commas_and_parens) {
buf.spaces(1);
}
let parens = if use_commas_and_parens {
Parens::NotNeeded
} else {
Parens::InApply
};
let arg = pattern_lift_spaces(buf.text.bump(), &loc_arg.value);
let mut was_multiline = arg.item.is_multiline();
@ -527,6 +560,9 @@ pub fn pattern_fmt_apply(
buf.push_str("(implements)");
} else {
fmt_pattern_only(&arg.item, buf, parens, indent_more, arg.item.is_multiline());
if use_commas_and_parens && (!is_last_arg || add_newlines) {
buf.push(',');
}
}
last_after = arg.after;
@ -542,7 +578,7 @@ pub fn pattern_fmt_apply(
}
}
if parens {
if parens || use_commas_and_parens {
buf.push(')');
}
}
@ -597,7 +633,7 @@ fn pattern_prec(pat: Pattern<'_>) -> Prec {
| Pattern::Tuple(..)
| Pattern::List(..)
| Pattern::ListRest(_) => Prec::Term,
Pattern::Apply(_, _) | Pattern::As(_, _) => Prec::Apply,
Pattern::Apply(_, _, _) | Pattern::As(_, _) => Prec::Apply,
Pattern::SpaceBefore(inner, _) | Pattern::SpaceAfter(inner, _) => pattern_prec(*inner),
Pattern::Malformed(_) | Pattern::MalformedIdent(..) => Prec::Term,
}
@ -617,7 +653,7 @@ pub fn pattern_lift_spaces<'a, 'b: 'a>(
pat: &Pattern<'b>,
) -> Spaces<'a, Pattern<'a>> {
match pat {
Pattern::Apply(func, args) => {
Pattern::Apply(func, args, style) => {
let func_lifted = pattern_lift_spaces(arena, &func.value);
let args = arena.alloc_slice_copy(args);
@ -652,7 +688,7 @@ pub fn pattern_lift_spaces<'a, 'b: 'a>(
};
Spaces {
before,
item: Pattern::Apply(arena.alloc(func), args),
item: Pattern::Apply(arena.alloc(func), args, *style),
after,
}
}
@ -712,7 +748,7 @@ fn handle_multiline_str_spaces<'a>(pat: &Pattern<'_>, before: &mut &'a [CommentO
fn starts_with_block_str(item: &Pattern<'_>) -> bool {
match item {
Pattern::As(inner, _) | Pattern::Apply(inner, _) => starts_with_block_str(&inner.value),
Pattern::As(inner, _) | Pattern::Apply(inner, _, _) => starts_with_block_str(&inner.value),
Pattern::SpaceBefore(inner, _) | Pattern::SpaceAfter(inner, _) => {
starts_with_block_str(inner)
}