mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 06:14:46 +00:00
use Parens type in pattern formatting
This commit is contained in:
parent
6046d8ee8e
commit
e18d3bbfe4
5 changed files with 86 additions and 30 deletions
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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!(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue