mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-04 20:28:02 +00:00
Move PNC apply to separate Expr/Pattern variant
This commit is contained in:
parent
96fc573b6b
commit
898b3f55e5
70 changed files with 873 additions and 555 deletions
|
@ -19,8 +19,8 @@ use roc_error_macros::internal_error;
|
|||
use roc_parse::ast::{
|
||||
AbilityMember, Defs, Expr, ExtractSpaces, ImportAlias, ImportAsKeyword, ImportExposingKeyword,
|
||||
ImportedModuleName, IngestedFileAnnotation, IngestedFileImport, ModuleImport,
|
||||
ModuleImportParams, Pattern, PatternApplyStyle, Spaces, SpacesBefore, StrLiteral,
|
||||
TypeAnnotation, TypeDef, TypeHeader, ValueDef,
|
||||
ModuleImportParams, Pattern, Spaces, SpacesBefore, StrLiteral, TypeAnnotation, TypeDef,
|
||||
TypeHeader, ValueDef,
|
||||
};
|
||||
use roc_parse::expr::merge_spaces;
|
||||
use roc_parse::header::Keyword;
|
||||
|
@ -556,7 +556,8 @@ impl<'a> Formattable for TypeHeader<'a> {
|
|||
Parens::NotNeeded,
|
||||
indent,
|
||||
self.vars.iter().any(|v| v.is_multiline()),
|
||||
PatternApplyStyle::Whitespace,
|
||||
false,
|
||||
None,
|
||||
);
|
||||
buf.flags = old_flags;
|
||||
}
|
||||
|
@ -569,7 +570,6 @@ 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)
|
||||
|
@ -891,9 +891,7 @@ 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, _style)
|
||||
if matches!(func.extract_spaces().item, Pattern::Tag(..)) =>
|
||||
{
|
||||
Pattern::Apply(func, _args) if matches!(func.extract_spaces().item, Pattern::Tag(..)) => {
|
||||
true
|
||||
}
|
||||
_ => false,
|
||||
|
@ -1085,6 +1083,13 @@ pub fn fmt_body<'a>(
|
|||
..
|
||||
},
|
||||
..,
|
||||
)
|
||||
| Expr::PncApply(
|
||||
Loc {
|
||||
value: Expr::Str(StrLiteral::Block(..)),
|
||||
..
|
||||
},
|
||||
..,
|
||||
) => {
|
||||
buf.spaces(1);
|
||||
body.format_with_options(buf, Parens::NotNeeded, Newlines::Yes, indent + INDENT);
|
||||
|
@ -1148,6 +1153,7 @@ fn starts_with_expect_ident(expr: &Expr<'_>) -> bool {
|
|||
// If we removed the `{}=` in this case, that would change the meaning
|
||||
match expr {
|
||||
Expr::Apply(inner, _, _) => starts_with_expect_ident(&inner.value),
|
||||
Expr::PncApply(inner, _) => starts_with_expect_ident(&inner.value),
|
||||
Expr::Var { module_name, ident } => {
|
||||
module_name.is_empty() && (*ident == "expect" || *ident == "expect!")
|
||||
}
|
||||
|
@ -1162,6 +1168,7 @@ pub fn starts_with_block_string_literal(expr: &Expr<'_>) -> bool {
|
|||
starts_with_block_string_literal(inner)
|
||||
}
|
||||
Expr::Apply(inner, _, _) => starts_with_block_string_literal(&inner.value),
|
||||
Expr::PncApply(inner, _) => starts_with_block_string_literal(&inner.value),
|
||||
Expr::TrySuffix { target: _, expr } => starts_with_block_string_literal(expr),
|
||||
_ => false,
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ use crate::spaces::{
|
|||
use crate::Buf;
|
||||
use bumpalo::collections::Vec;
|
||||
use bumpalo::Bump;
|
||||
use roc_module::called_via::{self, BinOp, CalledVia, UnaryOp};
|
||||
use roc_module::called_via::{self, BinOp, UnaryOp};
|
||||
use roc_parse::ast::{
|
||||
AssignedField, Base, Collection, CommentOrNewline, Expr, ExtractSpaces, Pattern, Spaceable,
|
||||
Spaces, SpacesAfter, SpacesBefore, TryTarget, WhenBranch,
|
||||
|
@ -91,13 +91,24 @@ fn format_expr_only(
|
|||
buf.indent(indent);
|
||||
buf.push_str("try");
|
||||
}
|
||||
Expr::Apply(loc_expr, loc_args, called_via::CalledVia::ParensAndCommas) => {
|
||||
fmt_apply(loc_expr, loc_args, indent, buf, true);
|
||||
Expr::PncApply(
|
||||
loc_expr @ Loc {
|
||||
value: Expr::Dbg, ..
|
||||
},
|
||||
loc_args,
|
||||
) => {
|
||||
fmt_apply(&loc_expr, loc_args.items, indent, buf);
|
||||
}
|
||||
Expr::PncApply(loc_expr, loc_args) => {
|
||||
fmt_pnc_apply(loc_expr, loc_args, indent, buf);
|
||||
}
|
||||
Expr::Apply(loc_expr, loc_args, _) => {
|
||||
let apply_needs_parens = parens == Parens::InApply || parens == Parens::InApplyLastArg;
|
||||
if buf.flags().parens_and_commas || !apply_needs_parens || loc_args.is_empty() {
|
||||
fmt_apply(loc_expr, loc_args, indent, buf, false);
|
||||
if buf.flags().parens_and_commas {
|
||||
fmt_pnc_apply(loc_expr, &Collection::with_items(loc_args), indent, buf);
|
||||
} else if !apply_needs_parens || loc_args.is_empty() {
|
||||
println!("No need parens");
|
||||
fmt_apply(loc_expr, loc_args, indent, buf);
|
||||
} else {
|
||||
fmt_parens(item, buf, indent);
|
||||
}
|
||||
|
@ -519,6 +530,12 @@ pub fn expr_is_multiline(me: &Expr<'_>, comments_only: bool) -> bool {
|
|||
.iter()
|
||||
.any(|loc_arg| expr_is_multiline(&loc_arg.value, comments_only))
|
||||
}
|
||||
Expr::PncApply(loc_expr, args) => {
|
||||
expr_is_multiline(&loc_expr.value, comments_only)
|
||||
|| args
|
||||
.iter()
|
||||
.any(|loc_arg| expr_is_multiline(&loc_arg.value, comments_only))
|
||||
}
|
||||
|
||||
Expr::DbgStmt { .. } => true,
|
||||
Expr::LowLevelDbg(_, _, _) => {
|
||||
|
@ -639,13 +656,28 @@ fn requires_space_after_unary(item: &Expr<'_>) -> bool {
|
|||
}
|
||||
}
|
||||
|
||||
fn fmt_pnc_apply(
|
||||
loc_expr: &Loc<Expr<'_>>,
|
||||
loc_args: &Collection<'_, &Loc<Expr<'_>>>,
|
||||
indent: u16,
|
||||
buf: &mut Buf<'_>,
|
||||
) {
|
||||
let expr = expr_lift_spaces(Parens::InApply, buf.text.bump(), &loc_expr.value);
|
||||
|
||||
if !expr.before.is_empty() {
|
||||
format_spaces(buf, expr.before, Newlines::Yes, indent);
|
||||
}
|
||||
expr.item
|
||||
.format_with_options(buf, Parens::InApply, Newlines::Yes, indent);
|
||||
fmt_expr_collection(buf, indent, Braces::Round, *loc_args, Newlines::No);
|
||||
}
|
||||
|
||||
fn fmt_apply(
|
||||
loc_expr: &Loc<Expr<'_>>,
|
||||
loc_args: &[&Loc<Expr<'_>>],
|
||||
|
||||
indent: u16,
|
||||
buf: &mut Buf<'_>,
|
||||
expr_used_commas_and_parens: bool,
|
||||
) {
|
||||
// should_reflow_outdentable, aka should we transform this:
|
||||
//
|
||||
|
@ -665,7 +697,6 @@ fn fmt_apply(
|
|||
// 2,
|
||||
// ]
|
||||
// ```
|
||||
let use_commas_and_parens = expr_used_commas_and_parens || buf.flags().parens_and_commas;
|
||||
let should_reflow_outdentable = loc_expr.extract_spaces().after.is_empty()
|
||||
&& except_last(loc_args).all(|a| !a.is_multiline())
|
||||
&& loc_args
|
||||
|
@ -701,23 +732,17 @@ fn fmt_apply(
|
|||
if !expr.before.is_empty() {
|
||||
format_spaces(buf, expr.before, Newlines::Yes, indent);
|
||||
}
|
||||
|
||||
expr.item
|
||||
.format_with_options(buf, Parens::InApply, Newlines::Yes, indent);
|
||||
|
||||
if use_commas_and_parens {
|
||||
buf.push('(');
|
||||
}
|
||||
|
||||
let mut last_after = expr.after;
|
||||
|
||||
for (i, loc_arg) in loc_args.iter().enumerate() {
|
||||
let is_last_arg = i == loc_args.len() - 1;
|
||||
let is_first_arg = i == 0;
|
||||
|
||||
let arg = expr_lift_spaces(
|
||||
if use_commas_and_parens {
|
||||
Parens::NotNeeded
|
||||
} else if is_last_arg {
|
||||
if is_last_arg {
|
||||
Parens::InApplyLastArg
|
||||
} else {
|
||||
Parens::InApply
|
||||
|
@ -738,7 +763,7 @@ fn fmt_apply(
|
|||
last_after = arg.after;
|
||||
if needs_indent {
|
||||
buf.ensure_ends_with_newline();
|
||||
} else if !(is_first_arg && use_commas_and_parens) {
|
||||
} else {
|
||||
buf.spaces(1);
|
||||
}
|
||||
|
||||
|
@ -746,34 +771,13 @@ fn fmt_apply(
|
|||
{
|
||||
fmt_parens(&arg.item, buf, arg_indent);
|
||||
} else {
|
||||
format_expr_only(
|
||||
&arg.item,
|
||||
buf,
|
||||
if use_commas_and_parens {
|
||||
Parens::NotNeeded
|
||||
} else {
|
||||
Parens::InApply
|
||||
},
|
||||
Newlines::Yes,
|
||||
arg_indent,
|
||||
);
|
||||
}
|
||||
if use_commas_and_parens && (!is_last_arg || needs_indent) {
|
||||
buf.push(',');
|
||||
format_expr_only(&arg.item, buf, Parens::InApply, Newlines::Yes, arg_indent);
|
||||
}
|
||||
}
|
||||
|
||||
if !last_after.is_empty() {
|
||||
format_spaces(buf, last_after, Newlines::Yes, arg_indent);
|
||||
}
|
||||
|
||||
if use_commas_and_parens {
|
||||
if needs_indent {
|
||||
buf.ensure_ends_with_newline();
|
||||
buf.indent(indent);
|
||||
}
|
||||
buf.push(')');
|
||||
}
|
||||
}
|
||||
|
||||
fn is_outdentable_collection(expr: &Expr<'_>) -> bool {
|
||||
|
@ -1038,16 +1042,12 @@ pub fn expr_lift_spaces<'a, 'b: 'a>(
|
|||
expr: &Expr<'b>,
|
||||
) -> Spaces<'a, Expr<'a>> {
|
||||
match expr {
|
||||
Expr::Apply(func, args, CalledVia::ParensAndCommas) => {
|
||||
let lifted = expr_lift_spaces_before(Parens::NotNeeded, arena, &func.value);
|
||||
Expr::PncApply(func, args) => {
|
||||
let lifted = expr_lift_spaces_before(Parens::InApply, arena, &func.value);
|
||||
|
||||
Spaces {
|
||||
before: lifted.before,
|
||||
item: Expr::Apply(
|
||||
arena.alloc(Loc::at(func.region, lifted.item)),
|
||||
args,
|
||||
CalledVia::ParensAndCommas,
|
||||
),
|
||||
item: Expr::PncApply(arena.alloc(Loc::at(func.region, lifted.item)), *args),
|
||||
after: arena.alloc([]),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,8 +7,7 @@ use crate::spaces::{fmt_comments_only, fmt_spaces, NewlineAt, INDENT};
|
|||
use crate::Buf;
|
||||
use bumpalo::Bump;
|
||||
use roc_parse::ast::{
|
||||
Base, CommentOrNewline, Pattern, PatternApplyStyle, PatternAs, Spaceable, Spaces, SpacesAfter,
|
||||
SpacesBefore,
|
||||
Base, CommentOrNewline, Pattern, PatternAs, Spaceable, Spaces, SpacesAfter, SpacesBefore,
|
||||
};
|
||||
use roc_parse::expr::merge_spaces;
|
||||
use roc_region::all::Loc;
|
||||
|
@ -73,9 +72,14 @@ 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())
|
||||
}
|
||||
Pattern::PncApply(pat, args) => {
|
||||
pat.is_multiline()
|
||||
|| args.iter().any(|a| a.is_multiline())
|
||||
|| !args.final_comments().is_empty()
|
||||
}
|
||||
|
||||
Pattern::Identifier { .. }
|
||||
| Pattern::Tag(_)
|
||||
|
@ -163,22 +167,19 @@ fn fmt_pattern_only(
|
|||
buf.indent(indent);
|
||||
buf.push_str(name);
|
||||
}
|
||||
Pattern::Apply(
|
||||
loc_pattern,
|
||||
loc_arg_patterns,
|
||||
style @ PatternApplyStyle::ParensAndCommas,
|
||||
) => {
|
||||
Pattern::PncApply(loc_pattern, loc_arg_patterns) => {
|
||||
pattern_fmt_apply(
|
||||
buf,
|
||||
loc_pattern.value,
|
||||
loc_arg_patterns,
|
||||
loc_arg_patterns.items,
|
||||
Parens::NotNeeded,
|
||||
indent,
|
||||
is_multiline,
|
||||
*style,
|
||||
true,
|
||||
Some(loc_arg_patterns.final_comments()),
|
||||
);
|
||||
}
|
||||
Pattern::Apply(loc_pattern, loc_arg_patterns, style) => {
|
||||
Pattern::Apply(loc_pattern, loc_arg_patterns) => {
|
||||
pattern_fmt_apply(
|
||||
buf,
|
||||
loc_pattern.value,
|
||||
|
@ -186,7 +187,8 @@ fn fmt_pattern_only(
|
|||
parens,
|
||||
indent,
|
||||
is_multiline,
|
||||
*style,
|
||||
false,
|
||||
None,
|
||||
);
|
||||
}
|
||||
Pattern::RecordDestructure(loc_patterns) => {
|
||||
|
@ -462,10 +464,10 @@ pub fn pattern_fmt_apply(
|
|||
parens: Parens,
|
||||
indent: u16,
|
||||
is_multiline: bool,
|
||||
style: PatternApplyStyle,
|
||||
is_pnc: bool,
|
||||
final_comments: Option<&[CommentOrNewline]>,
|
||||
) {
|
||||
let use_commas_and_parens =
|
||||
matches!(style, PatternApplyStyle::ParensAndCommas) || buf.flags().parens_and_commas;
|
||||
let use_commas_and_parens = is_pnc || 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
|
||||
|
@ -560,7 +562,7 @@ 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) {
|
||||
if use_commas_and_parens && (!is_last_arg || is_multiline) {
|
||||
buf.push(',');
|
||||
}
|
||||
}
|
||||
|
@ -570,6 +572,13 @@ pub fn pattern_fmt_apply(
|
|||
add_newlines |= was_multiline;
|
||||
}
|
||||
|
||||
if let Some(comments) = final_comments {
|
||||
if !is_multiline {
|
||||
fmt_comments_only(buf, comments.iter(), NewlineAt::Bottom, indent_more);
|
||||
} else {
|
||||
fmt_spaces(buf, comments.iter(), indent_more);
|
||||
}
|
||||
}
|
||||
if !last_after.is_empty() {
|
||||
if !is_multiline {
|
||||
fmt_comments_only(buf, last_after.iter(), NewlineAt::Bottom, indent_more)
|
||||
|
@ -578,7 +587,21 @@ pub fn pattern_fmt_apply(
|
|||
}
|
||||
}
|
||||
|
||||
if parens || use_commas_and_parens {
|
||||
if use_commas_and_parens {
|
||||
if is_multiline {
|
||||
buf.ensure_ends_with_newline();
|
||||
buf.indent(indent);
|
||||
}
|
||||
if buf.ends_with_newline() {
|
||||
buf.indent(indent);
|
||||
}
|
||||
if buf.ends_with_newline() {
|
||||
buf.indent(indent);
|
||||
}
|
||||
buf.push(')');
|
||||
}
|
||||
|
||||
if parens {
|
||||
buf.push(')');
|
||||
}
|
||||
}
|
||||
|
@ -632,8 +655,9 @@ fn pattern_prec(pat: Pattern<'_>) -> Prec {
|
|||
| Pattern::SingleQuote(_)
|
||||
| Pattern::Tuple(..)
|
||||
| Pattern::List(..)
|
||||
| Pattern::ListRest(_) => Prec::Term,
|
||||
Pattern::Apply(_, _, _) | Pattern::As(_, _) => Prec::Apply,
|
||||
| Pattern::ListRest(_)
|
||||
| Pattern::PncApply(_, _) => Prec::Term,
|
||||
Pattern::Apply(_, _) | Pattern::As(_, _) => Prec::Apply,
|
||||
Pattern::SpaceBefore(inner, _) | Pattern::SpaceAfter(inner, _) => pattern_prec(*inner),
|
||||
Pattern::Malformed(_) | Pattern::MalformedIdent(..) => Prec::Term,
|
||||
}
|
||||
|
@ -653,7 +677,7 @@ pub fn pattern_lift_spaces<'a, 'b: 'a>(
|
|||
pat: &Pattern<'b>,
|
||||
) -> Spaces<'a, Pattern<'a>> {
|
||||
match pat {
|
||||
Pattern::Apply(func, args, style) => {
|
||||
Pattern::Apply(func, args) => {
|
||||
let func_lifted = pattern_lift_spaces(arena, &func.value);
|
||||
|
||||
let args = arena.alloc_slice_copy(args);
|
||||
|
@ -688,10 +712,19 @@ pub fn pattern_lift_spaces<'a, 'b: 'a>(
|
|||
};
|
||||
Spaces {
|
||||
before,
|
||||
item: Pattern::Apply(arena.alloc(func), args, *style),
|
||||
item: Pattern::Apply(arena.alloc(func), args),
|
||||
after,
|
||||
}
|
||||
}
|
||||
Pattern::PncApply(func, args) => {
|
||||
let func_lifted = pattern_lift_spaces_before(arena, &func.value);
|
||||
|
||||
Spaces {
|
||||
before: func_lifted.before,
|
||||
item: Pattern::PncApply(arena.alloc(func), *args),
|
||||
after: &[],
|
||||
}
|
||||
}
|
||||
Pattern::OptionalField(name, expr) => {
|
||||
let lifted = expr_lift_spaces_after(Parens::NotNeeded, arena, &expr.value);
|
||||
Spaces {
|
||||
|
@ -748,7 +781,9 @@ 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, _) | Pattern::PncApply(inner, _) => {
|
||||
starts_with_block_str(&inner.value)
|
||||
}
|
||||
Pattern::SpaceBefore(inner, _) | Pattern::SpaceAfter(inner, _) => {
|
||||
starts_with_block_str(inner)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue