mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-29 14:54:47 +00:00
implement Formattable for Pattern
This commit is contained in:
parent
e18d3bbfe4
commit
d61b8c88a1
4 changed files with 200 additions and 165 deletions
|
@ -1,5 +1,6 @@
|
|||
use crate::annotation::Parens;
|
||||
use crate::spaces::{fmt_comments_only, fmt_spaces};
|
||||
use crate::annotation::{Formattable, Parens};
|
||||
use crate::expr::is_multiline_pattern;
|
||||
use crate::spaces::{fmt_comments_only, fmt_spaces, is_comment};
|
||||
use bumpalo::collections::String;
|
||||
use roc_parse::ast::{Base, Pattern};
|
||||
|
||||
|
@ -8,134 +9,160 @@ pub fn fmt_pattern<'a>(
|
|||
pattern: &'a Pattern<'a>,
|
||||
indent: u16,
|
||||
parens: Parens,
|
||||
only_comments: bool,
|
||||
_only_comments: bool,
|
||||
) {
|
||||
use self::Pattern::*;
|
||||
pattern.format_with_parens(buf, parens, indent);
|
||||
}
|
||||
|
||||
match pattern {
|
||||
Identifier(string) => buf.push_str(string),
|
||||
GlobalTag(name) | PrivateTag(name) => {
|
||||
buf.push_str(name);
|
||||
impl<'a> Formattable<'a> for Pattern<'a> {
|
||||
fn is_multiline(&self) -> bool {
|
||||
// Theory: a pattern should only be multiline when it contains a comment
|
||||
match self {
|
||||
Pattern::SpaceBefore(_, spaces) | Pattern::SpaceAfter(_, spaces) => {
|
||||
debug_assert!(!spaces.is_empty());
|
||||
|
||||
spaces.iter().any(|s| is_comment(s))
|
||||
}
|
||||
|
||||
Pattern::Nested(nested_pat) => is_multiline_pattern(nested_pat),
|
||||
|
||||
Pattern::RecordDestructure(fields) => fields.iter().any(|f| f.value.is_multiline()),
|
||||
Pattern::RecordField(_, subpattern) => subpattern.value.is_multiline(),
|
||||
|
||||
Pattern::Identifier(_)
|
||||
| Pattern::GlobalTag(_)
|
||||
| Pattern::PrivateTag(_)
|
||||
| Pattern::Apply(_, _)
|
||||
| Pattern::NumLiteral(_)
|
||||
| Pattern::NonBase10Literal { .. }
|
||||
| Pattern::FloatLiteral(_)
|
||||
| Pattern::StrLiteral(_)
|
||||
| Pattern::BlockStrLiteral(_)
|
||||
| Pattern::Underscore
|
||||
| Pattern::Malformed(_)
|
||||
| Pattern::QualifiedIdentifier { .. } => false,
|
||||
}
|
||||
Apply(loc_pattern, loc_arg_patterns) => {
|
||||
// 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('(');
|
||||
fn format_with_parens(&self, buf: &mut String<'a>, parens: Parens, indent: u16) {
|
||||
use self::Pattern::*;
|
||||
|
||||
match self {
|
||||
Identifier(string) => buf.push_str(string),
|
||||
GlobalTag(name) | PrivateTag(name) => {
|
||||
buf.push_str(name);
|
||||
}
|
||||
Apply(loc_pattern, loc_arg_patterns) => {
|
||||
// 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('(');
|
||||
}
|
||||
|
||||
loc_pattern
|
||||
.value
|
||||
.format_with_parens(buf, Parens::InApply, indent);
|
||||
|
||||
for loc_arg in loc_arg_patterns.iter() {
|
||||
buf.push(' ');
|
||||
loc_arg
|
||||
.value
|
||||
.format_with_parens(buf, Parens::InApply, indent);
|
||||
}
|
||||
|
||||
if parens {
|
||||
buf.push(')');
|
||||
}
|
||||
}
|
||||
RecordDestructure(loc_patterns) => {
|
||||
buf.push_str("{ ");
|
||||
|
||||
let mut it = loc_patterns.iter().peekable();
|
||||
|
||||
while let Some(loc_pattern) = it.next() {
|
||||
loc_pattern
|
||||
.value
|
||||
.format_with_parens(buf, Parens::NotNeeded, indent);
|
||||
|
||||
if it.peek().is_some() {
|
||||
buf.push_str(", ");
|
||||
}
|
||||
}
|
||||
|
||||
buf.push_str(" }");
|
||||
}
|
||||
|
||||
fmt_pattern(
|
||||
buf,
|
||||
&loc_pattern.value,
|
||||
indent,
|
||||
Parens::InApply,
|
||||
only_comments,
|
||||
);
|
||||
|
||||
for loc_arg in loc_arg_patterns.iter() {
|
||||
buf.push(' ');
|
||||
fmt_pattern(buf, &loc_arg.value, indent, Parens::InApply, only_comments);
|
||||
RecordField(name, loc_pattern) => {
|
||||
buf.push_str(name);
|
||||
buf.push_str(": ");
|
||||
loc_pattern
|
||||
.value
|
||||
.format_with_parens(buf, Parens::NotNeeded, indent);
|
||||
}
|
||||
|
||||
if parens {
|
||||
buf.push(')');
|
||||
NumLiteral(string) => buf.push_str(string),
|
||||
NonBase10Literal {
|
||||
base,
|
||||
string,
|
||||
is_negative,
|
||||
} => {
|
||||
if *is_negative {
|
||||
buf.push('-');
|
||||
}
|
||||
|
||||
match base {
|
||||
Base::Hex => buf.push_str("0x"),
|
||||
Base::Octal => buf.push_str("0o"),
|
||||
Base::Binary => buf.push_str("0b"),
|
||||
Base::Decimal => { /* nothing */ }
|
||||
}
|
||||
|
||||
buf.push_str(string);
|
||||
}
|
||||
}
|
||||
RecordDestructure(loc_patterns) => {
|
||||
buf.push_str("{ ");
|
||||
FloatLiteral(string) => buf.push_str(string),
|
||||
StrLiteral(string) => buf.push_str(string),
|
||||
BlockStrLiteral(lines) => {
|
||||
for line in *lines {
|
||||
buf.push_str(line)
|
||||
}
|
||||
}
|
||||
Underscore => buf.push('_'),
|
||||
|
||||
let mut it = loc_patterns.iter().peekable();
|
||||
|
||||
while let Some(loc_pattern) = it.next() {
|
||||
fmt_pattern(
|
||||
buf,
|
||||
&loc_pattern.value,
|
||||
indent,
|
||||
Parens::NotNeeded,
|
||||
only_comments,
|
||||
);
|
||||
|
||||
if it.peek().is_some() {
|
||||
buf.push_str(", ");
|
||||
// Space
|
||||
SpaceBefore(sub_pattern, spaces) => {
|
||||
if !sub_pattern.is_multiline() {
|
||||
fmt_comments_only(buf, spaces.iter(), indent)
|
||||
} else {
|
||||
fmt_spaces(buf, spaces.iter(), indent);
|
||||
}
|
||||
sub_pattern.format_with_parens(buf, parens, indent);
|
||||
}
|
||||
SpaceAfter(sub_pattern, spaces) => {
|
||||
sub_pattern.format_with_parens(buf, parens, indent);
|
||||
// if only_comments {
|
||||
if !sub_pattern.is_multiline() {
|
||||
fmt_comments_only(buf, spaces.iter(), indent)
|
||||
} else {
|
||||
fmt_spaces(buf, spaces.iter(), indent);
|
||||
}
|
||||
}
|
||||
|
||||
buf.push_str(" }");
|
||||
}
|
||||
|
||||
RecordField(name, loc_pattern) => {
|
||||
buf.push_str(name);
|
||||
buf.push_str(": ");
|
||||
fmt_pattern(
|
||||
buf,
|
||||
&loc_pattern.value,
|
||||
indent,
|
||||
Parens::NotNeeded,
|
||||
only_comments,
|
||||
);
|
||||
}
|
||||
|
||||
NumLiteral(string) => buf.push_str(string),
|
||||
NonBase10Literal {
|
||||
base,
|
||||
string,
|
||||
is_negative,
|
||||
} => {
|
||||
if *is_negative {
|
||||
buf.push('-');
|
||||
Nested(sub_pattern) => {
|
||||
sub_pattern.format_with_parens(buf, parens, indent);
|
||||
}
|
||||
|
||||
match base {
|
||||
Base::Hex => buf.push_str("0x"),
|
||||
Base::Octal => buf.push_str("0o"),
|
||||
Base::Binary => buf.push_str("0b"),
|
||||
Base::Decimal => { /* nothing */ }
|
||||
}
|
||||
// Malformed
|
||||
Malformed(string) => buf.push_str(string),
|
||||
QualifiedIdentifier { module_name, ident } => {
|
||||
if !module_name.is_empty() {
|
||||
buf.push_str(module_name);
|
||||
buf.push('.');
|
||||
}
|
||||
|
||||
buf.push_str(string);
|
||||
}
|
||||
FloatLiteral(string) => buf.push_str(string),
|
||||
StrLiteral(string) => buf.push_str(string),
|
||||
BlockStrLiteral(lines) => {
|
||||
for line in *lines {
|
||||
buf.push_str(line)
|
||||
buf.push_str(ident);
|
||||
}
|
||||
}
|
||||
Underscore => buf.push('_'),
|
||||
|
||||
// Space
|
||||
SpaceBefore(sub_pattern, spaces) => {
|
||||
if only_comments {
|
||||
fmt_comments_only(buf, spaces.iter(), indent)
|
||||
} else {
|
||||
fmt_spaces(buf, spaces.iter(), indent);
|
||||
}
|
||||
fmt_pattern(buf, sub_pattern, indent, parens, only_comments);
|
||||
}
|
||||
SpaceAfter(sub_pattern, spaces) => {
|
||||
fmt_pattern(buf, sub_pattern, indent, parens, only_comments);
|
||||
if only_comments {
|
||||
fmt_comments_only(buf, spaces.iter(), indent)
|
||||
} else {
|
||||
fmt_spaces(buf, spaces.iter(), indent);
|
||||
}
|
||||
}
|
||||
|
||||
Nested(sub_pattern) => {
|
||||
fmt_pattern(buf, sub_pattern, indent, parens, only_comments);
|
||||
}
|
||||
|
||||
// Malformed
|
||||
Malformed(string) => buf.push_str(string),
|
||||
QualifiedIdentifier { module_name, ident } => {
|
||||
if !module_name.is_empty() {
|
||||
buf.push_str(module_name);
|
||||
buf.push('.');
|
||||
}
|
||||
|
||||
buf.push_str(ident);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue