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

@ -13,14 +13,14 @@ use crate::pattern::{pattern_lift_spaces, pattern_lift_spaces_before};
use crate::spaces::{
fmt_comments_only, fmt_default_newline, fmt_default_spaces, fmt_spaces, NewlineAt, INDENT,
};
use crate::Buf;
use crate::{Buf, MigrationFlags};
use bumpalo::Bump;
use roc_error_macros::internal_error;
use roc_parse::ast::{
AbilityMember, Defs, Expr, ExtractSpaces, ImportAlias, ImportAsKeyword, ImportExposingKeyword,
ImportedModuleName, IngestedFileAnnotation, IngestedFileImport, ModuleImport,
ModuleImportParams, Pattern, Spaceable, Spaces, SpacesAfter, SpacesBefore, StrLiteral,
TypeAnnotation, TypeDef, TypeHeader, ValueDef,
ModuleImportParams, Pattern, PatternApplyStyle, Spaceable, Spaces, SpacesAfter, SpacesBefore,
StrLiteral, TypeAnnotation, TypeDef, TypeHeader, ValueDef,
};
use roc_parse::expr::merge_spaces;
use roc_parse::header::Keyword;
@ -564,6 +564,11 @@ impl<'a> Formattable for TypeHeader<'a> {
_newlines: Newlines,
indent: u16,
) {
let old_flags = buf.flags;
buf.flags = MigrationFlags {
parens_and_commas: false,
..old_flags
};
pattern_fmt_apply(
buf,
Pattern::Tag(self.name.value),
@ -571,7 +576,9 @@ impl<'a> Formattable for TypeHeader<'a> {
Parens::NotNeeded,
indent,
self.vars.iter().any(|v| v.is_multiline()),
PatternApplyStyle::Whitespace,
);
buf.flags = old_flags;
}
}
@ -582,6 +589,7 @@ fn type_head_lift_spaces<'a, 'b: 'a>(
let pat = Pattern::Apply(
arena.alloc(Loc::at(head.name.region, Pattern::Tag(head.name.value))),
head.vars,
PatternApplyStyle::Whitespace,
);
pattern_lift_spaces(arena, &pat)
@ -903,7 +911,9 @@ impl<'a> Formattable for ValueDef<'a> {
fn ann_pattern_needs_parens(value: &Pattern<'_>) -> bool {
match value.extract_spaces().item {
Pattern::Tag(_) => true,
Pattern::Apply(func, _args) if matches!(func.extract_spaces().item, Pattern::Tag(..)) => {
Pattern::Apply(func, _args, _style)
if matches!(func.extract_spaces().item, Pattern::Tag(..)) =>
{
true
}
_ => false,

View file

@ -11,7 +11,7 @@ use crate::spaces::{
use crate::Buf;
use bumpalo::collections::Vec;
use bumpalo::Bump;
use roc_module::called_via::{self, BinOp, UnaryOp};
use roc_module::called_via::{self, BinOp, CalledVia, UnaryOp};
use roc_parse::ast::{
AssignedField, Base, Collection, CommentOrNewline, Expr, ExtractSpaces, Pattern, Spaceable,
Spaces, SpacesAfter, SpacesBefore, TryTarget, WhenBranch,
@ -96,8 +96,9 @@ fn format_expr_only(
}
Expr::Apply(loc_expr, loc_args, _) => {
let apply_needs_parens = parens == Parens::InApply || parens == Parens::InApplyLastArg;
if apply_needs_parens && !loc_args.is_empty() {
if buf.flags().parens_and_commas {
fmt_apply(loc_expr, loc_args, indent, buf, false);
} else if apply_needs_parens && !loc_args.is_empty() {
fmt_parens(item, buf, indent);
} else {
fmt_apply(loc_expr, loc_args, indent, buf, false);
@ -716,7 +717,9 @@ fn fmt_apply(
let is_first_arg = i == 0;
let arg = expr_lift_spaces(
if is_last_arg {
if use_commas_and_parens {
Parens::NotNeeded
} else if is_last_arg {
Parens::InApplyLastArg
} else {
Parens::InApply
@ -1038,7 +1041,7 @@ pub fn expr_lift_spaces<'a, 'b: 'a>(
) -> Spaces<'a, Expr<'a>> {
match expr {
Expr::Apply(func, args, called_via) => {
if args.is_empty() {
if args.is_empty() && !matches!(called_via, CalledVia::ParensAndCommas) {
return expr_lift_spaces(Parens::NotNeeded, arena, &func.value);
}
@ -1082,7 +1085,9 @@ pub fn expr_lift_spaces<'a, 'b: 'a>(
}
};
if parens == Parens::InApply || parens == Parens::InApplyLastArg {
if (parens == Parens::InApply || parens == Parens::InApplyLastArg)
&& !matches!(called_via, CalledVia::ParensAndCommas)
{
res = Spaces {
before: &[],
item: Expr::ParensAround(arena.alloc(lower(arena, res))),

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)
}