use Parens type in pattern formatting

This commit is contained in:
Folkert 2020-07-10 16:32:49 +02:00
parent 6046d8ee8e
commit e18d3bbfe4
5 changed files with 86 additions and 30 deletions

View file

@ -7,7 +7,7 @@ use roc_region::all::Located;
pub enum Parens { pub enum Parens {
NotNeeded, NotNeeded,
InFunctionType, InFunctionType,
InTypeParam, InApply,
} }
pub fn fmt_annotation<'a>(buf: &mut String<'a>, annotation: &'a TypeAnnotation<'a>, indent: u16) { pub fn fmt_annotation<'a>(buf: &mut String<'a>, annotation: &'a TypeAnnotation<'a>, indent: u16) {
@ -98,7 +98,7 @@ impl<'a> Formattable<'a> for TypeAnnotation<'a> {
} }
Apply(_, name, arguments) => { Apply(_, name, arguments) => {
// NOTE apply is never multiline // NOTE apply is never multiline
let write_parens = parens == Parens::InTypeParam && !arguments.is_empty(); let write_parens = parens == Parens::InApply && !arguments.is_empty();
if write_parens { if write_parens {
buf.push('(') buf.push('(')
@ -108,7 +108,7 @@ impl<'a> Formattable<'a> for TypeAnnotation<'a> {
for argument in *arguments { for argument in *arguments {
buf.push(' '); buf.push(' ');
(&argument.value).format_with_parens(buf, Parens::InTypeParam, indent); (&argument.value).format_with_parens(buf, Parens::InApply, indent);
} }
if write_parens { if write_parens {
@ -209,12 +209,12 @@ impl<'a> Formattable<'a> for Tag<'a> {
for arg in *args { for arg in *args {
newline(buf, arg_indent); newline(buf, arg_indent);
(&arg.value).format_with_parens(buf, Parens::InTypeParam, arg_indent); (&arg.value).format_with_parens(buf, Parens::InApply, arg_indent);
} }
} else { } else {
for arg in *args { for arg in *args {
buf.push(' '); buf.push(' ');
(&arg.value).format_with_parens(buf, Parens::InTypeParam, indent); (&arg.value).format_with_parens(buf, Parens::InApply, indent);
} }
} }
} }
@ -226,12 +226,12 @@ impl<'a> Formattable<'a> for Tag<'a> {
for arg in *args { for arg in *args {
newline(buf, arg_indent); newline(buf, arg_indent);
(&arg.value).format_with_parens(buf, Parens::InTypeParam, arg_indent); (&arg.value).format_with_parens(buf, Parens::InApply, arg_indent);
} }
} else { } else {
for arg in *args { for arg in *args {
buf.push(' '); buf.push(' ');
(&arg.value).format_with_parens(buf, Parens::InTypeParam, indent); (&arg.value).format_with_parens(buf, Parens::InApply, indent);
} }
} }
} }

View file

@ -1,4 +1,4 @@
use crate::annotation::fmt_annotation; use crate::annotation::{fmt_annotation, Parens};
use crate::expr::{fmt_expr, is_multiline_expr}; use crate::expr::{fmt_expr, is_multiline_expr};
use crate::pattern::fmt_pattern; use crate::pattern::fmt_pattern;
use crate::spaces::{fmt_spaces, newline, INDENT}; use crate::spaces::{fmt_spaces, newline, INDENT};
@ -20,7 +20,7 @@ pub fn fmt_def<'a>(buf: &mut String<'a>, def: &'a Def<'a>, indent: u16) {
} else { } else {
for var in *vars { for var in *vars {
buf.push(' '); buf.push(' ');
fmt_pattern(buf, &var.value, indent, false, false); fmt_pattern(buf, &var.value, indent, Parens::NotNeeded, false);
} }
} }
@ -53,7 +53,7 @@ pub fn fmt_body<'a>(
body: &'a Expr<'a>, body: &'a Expr<'a>,
indent: u16, indent: u16,
) { ) {
fmt_pattern(buf, pattern, indent, true, false); fmt_pattern(buf, pattern, indent, Parens::InApply, false);
buf.push_str(" ="); buf.push_str(" =");
if is_multiline_expr(body) { if is_multiline_expr(body) {
match body { match body {
@ -78,7 +78,7 @@ pub fn fmt_type_annotation<'a>(
annotation: &'a TypeAnnotation<'a>, annotation: &'a TypeAnnotation<'a>,
indent: u16, indent: u16,
) { ) {
fmt_pattern(buf, pattern, indent, true, false); fmt_pattern(buf, pattern, indent, Parens::NotNeeded, false);
buf.push_str(" : "); buf.push_str(" : ");
fmt_annotation(buf, annotation, indent); fmt_annotation(buf, annotation, indent);
} }

View file

@ -1,3 +1,4 @@
use crate::annotation::Parens;
use crate::def::fmt_def; use crate::def::fmt_def;
use crate::pattern::fmt_pattern; use crate::pattern::fmt_pattern;
use crate::spaces::{ use crate::spaces::{
@ -604,7 +605,13 @@ fn fmt_when<'a>(
Some(last_pattern) => first_pattern.region.start_line != last_pattern.region.end_line, Some(last_pattern) => first_pattern.region.start_line != last_pattern.region.end_line,
}; };
fmt_pattern(buf, &first_pattern.value, indent + INDENT, false, true); fmt_pattern(
buf,
&first_pattern.value,
indent + INDENT,
Parens::NotNeeded,
true,
);
for when_pattern in rest { for when_pattern in rest {
if is_multiline { if is_multiline {
buf.push_str("\n"); buf.push_str("\n");
@ -613,7 +620,13 @@ fn fmt_when<'a>(
} else { } else {
buf.push_str(" | "); buf.push_str(" | ");
} }
fmt_pattern(buf, &when_pattern.value, indent + INDENT, false, true); fmt_pattern(
buf,
&when_pattern.value,
indent + INDENT,
Parens::NotNeeded,
true,
);
} }
if let Some(guard_expr) = &branch.guard { if let Some(guard_expr) = &branch.guard {
@ -782,7 +795,7 @@ pub fn fmt_closure<'a>(
any_args_printed = true; any_args_printed = true;
} }
fmt_pattern(buf, &loc_pattern.value, indent, false, false); fmt_pattern(buf, &loc_pattern.value, indent, Parens::NotNeeded, false);
} }
if !arguments_are_multiline { if !arguments_are_multiline {

View file

@ -1,3 +1,4 @@
use crate::annotation::Parens;
use crate::spaces::{fmt_comments_only, fmt_spaces}; use crate::spaces::{fmt_comments_only, fmt_spaces};
use bumpalo::collections::String; use bumpalo::collections::String;
use roc_parse::ast::{Base, Pattern}; use roc_parse::ast::{Base, Pattern};
@ -6,7 +7,7 @@ pub fn fmt_pattern<'a>(
buf: &mut String<'a>, buf: &mut String<'a>,
pattern: &'a Pattern<'a>, pattern: &'a Pattern<'a>,
indent: u16, indent: u16,
apply_needs_parens: bool, parens: Parens,
only_comments: bool, only_comments: bool,
) { ) {
use self::Pattern::*; use self::Pattern::*;
@ -17,34 +18,48 @@ pub fn fmt_pattern<'a>(
buf.push_str(name); buf.push_str(name);
} }
Apply(loc_pattern, loc_arg_patterns) => { Apply(loc_pattern, loc_arg_patterns) => {
if apply_needs_parens { // Sometimes, an Apply pattern needs parens around it.
// In particular when an Apply's argument is itself an Apply (> 0) arguments
let parens = !loc_arg_patterns.is_empty() && parens == Parens::InApply;
if parens {
buf.push('('); buf.push('(');
} }
fmt_pattern(buf, &loc_pattern.value, indent, true, only_comments); fmt_pattern(
buf,
&loc_pattern.value,
indent,
Parens::InApply,
only_comments,
);
for loc_arg in loc_arg_patterns.iter() { for loc_arg in loc_arg_patterns.iter() {
buf.push(' '); buf.push(' ');
fmt_pattern(buf, &loc_arg.value, indent, true, only_comments); fmt_pattern(buf, &loc_arg.value, indent, Parens::InApply, only_comments);
} }
if apply_needs_parens { if parens {
buf.push(')'); buf.push(')');
} }
} }
RecordDestructure(loc_patterns) => { RecordDestructure(loc_patterns) => {
buf.push_str("{ "); buf.push_str("{ ");
let mut is_first = true; let mut it = loc_patterns.iter().peekable();
for loc_pattern in *loc_patterns { while let Some(loc_pattern) = it.next() {
if is_first { fmt_pattern(
is_first = false; buf,
} else { &loc_pattern.value,
indent,
Parens::NotNeeded,
only_comments,
);
if it.peek().is_some() {
buf.push_str(", "); buf.push_str(", ");
} }
fmt_pattern(buf, &loc_pattern.value, indent, true, only_comments);
} }
buf.push_str(" }"); buf.push_str(" }");
@ -53,7 +68,13 @@ pub fn fmt_pattern<'a>(
RecordField(name, loc_pattern) => { RecordField(name, loc_pattern) => {
buf.push_str(name); buf.push_str(name);
buf.push_str(": "); buf.push_str(": ");
fmt_pattern(buf, &loc_pattern.value, indent, true, only_comments); fmt_pattern(
buf,
&loc_pattern.value,
indent,
Parens::NotNeeded,
only_comments,
);
} }
NumLiteral(string) => buf.push_str(string), NumLiteral(string) => buf.push_str(string),
@ -91,10 +112,10 @@ pub fn fmt_pattern<'a>(
} else { } else {
fmt_spaces(buf, spaces.iter(), indent); fmt_spaces(buf, spaces.iter(), indent);
} }
fmt_pattern(buf, sub_pattern, indent, apply_needs_parens, only_comments); fmt_pattern(buf, sub_pattern, indent, parens, only_comments);
} }
SpaceAfter(sub_pattern, spaces) => { SpaceAfter(sub_pattern, spaces) => {
fmt_pattern(buf, sub_pattern, indent, apply_needs_parens, only_comments); fmt_pattern(buf, sub_pattern, indent, parens, only_comments);
if only_comments { if only_comments {
fmt_comments_only(buf, spaces.iter(), indent) fmt_comments_only(buf, spaces.iter(), indent)
} else { } else {
@ -103,7 +124,7 @@ pub fn fmt_pattern<'a>(
} }
Nested(sub_pattern) => { Nested(sub_pattern) => {
fmt_pattern(buf, sub_pattern, indent, apply_needs_parens, only_comments); fmt_pattern(buf, sub_pattern, indent, parens, only_comments);
} }
// Malformed // Malformed

View file

@ -2138,6 +2138,28 @@ mod test_fmt {
)); ));
} }
#[test]
fn record_pattern_with_apply_guard() {
expr_formats_same(indoc!(
r#"
when { x: 1 } is
{ x: Just 4 } ->
4
"#
));
}
#[test]
fn record_pattern_with_record_guard() {
expr_formats_same(indoc!(
r#"
when { x: 1 } is
{ x: { x: True } } ->
4
"#
));
}
#[test] #[test]
fn applied_tags() { fn applied_tags() {
expr_formats_same(indoc!( expr_formats_same(indoc!(