Move MigrationFlags from an argument on format* to a field on Buf

That has a few advantages:

* We avoid a bunch of extra parameter-passing "noise", since the vast majority of formatting code doesn't need to care about this setting beyond just passing it to nested format calls.
* It aligns really well with the "global" nature of this setting, and makes it impossible to have bugs where e.g. one callsite forgets to pass the correct value to it's children - which would lead to parts of the tree not being migrated. If this is truly a global setting on Buf, that simply can't happen.
This commit is contained in:
Joshua Warner 2024-12-04 17:43:11 -08:00
parent 0274d9b997
commit 120e9be550
No known key found for this signature in database
GPG key ID: 89AD497003F93FDD
15 changed files with 390 additions and 812 deletions

View file

@ -67,34 +67,13 @@ impl Newlines {
}
}
pub struct MigrationFlags {
pub(crate) snakify: bool,
}
impl MigrationFlags {
pub fn new(snakify: bool) -> Self {
MigrationFlags { snakify }
}
pub fn at_least_one_active(&self) -> bool {
self.snakify
}
}
pub trait Formattable {
fn is_multiline(&self) -> bool;
fn format_with_options(
&self,
buf: &mut Buf,
_parens: Parens,
_newlines: Newlines,
flags: &MigrationFlags,
indent: u16,
);
fn format_with_options(&self, buf: &mut Buf, _parens: Parens, _newlines: Newlines, indent: u16);
fn format(&self, buf: &mut Buf, flags: &MigrationFlags, indent: u16) {
self.format_with_options(buf, Parens::NotNeeded, Newlines::No, flags, indent);
fn format(&self, buf: &mut Buf, indent: u16) {
self.format_with_options(buf, Parens::NotNeeded, Newlines::No, indent);
}
}
@ -107,19 +86,12 @@ where
(*self).is_multiline()
}
fn format_with_options(
&self,
buf: &mut Buf,
parens: Parens,
newlines: Newlines,
flags: &MigrationFlags,
indent: u16,
) {
(*self).format_with_options(buf, parens, newlines, flags, indent)
fn format_with_options(&self, buf: &mut Buf, parens: Parens, newlines: Newlines, indent: u16) {
(*self).format_with_options(buf, parens, newlines, indent)
}
fn format(&self, buf: &mut Buf, flags: &MigrationFlags, indent: u16) {
(*self).format(buf, flags, indent)
fn format(&self, buf: &mut Buf, indent: u16) {
(*self).format(buf, indent)
}
}
@ -141,20 +113,13 @@ where
self.value.is_multiline()
}
fn format_with_options(
&self,
buf: &mut Buf,
parens: Parens,
newlines: Newlines,
flags: &MigrationFlags,
indent: u16,
) {
fn format_with_options(&self, buf: &mut Buf, parens: Parens, newlines: Newlines, indent: u16) {
self.value
.format_with_options(buf, parens, newlines, flags, indent)
.format_with_options(buf, parens, newlines, indent)
}
fn format(&self, buf: &mut Buf, flags: &MigrationFlags, indent: u16) {
self.value.format(buf, flags, indent)
fn format(&self, buf: &mut Buf, indent: u16) {
self.value.format(buf, indent)
}
}
@ -168,7 +133,6 @@ impl<'a> Formattable for UppercaseIdent<'a> {
buf: &mut Buf,
_parens: Parens,
_newlines: Newlines,
_flags: &MigrationFlags,
_indent: u16,
) {
buf.push_str((*self).into())
@ -231,22 +195,15 @@ impl<'a> Formattable for TypeAnnotation<'a> {
}
}
fn format_with_options(
&self,
buf: &mut Buf,
parens: Parens,
newlines: Newlines,
flags: &MigrationFlags,
indent: u16,
) {
fmt_ty_ann(self, buf, flags, indent, parens, newlines, false);
fn format_with_options(&self, buf: &mut Buf, parens: Parens, newlines: Newlines, indent: u16) {
fmt_ty_ann(self, buf, indent, parens, newlines, false);
}
}
fn fmt_ty_ann(
me: &TypeAnnotation<'_>,
buf: &mut Buf<'_>,
flags: &MigrationFlags,
indent: u16,
parens: Parens,
newlines: Newlines,
@ -292,7 +249,6 @@ fn fmt_ty_ann(
fmt_ty_ann(
&argument.value,
buf,
flags,
indent,
Parens::InFunctionType,
Newlines::Yes,
@ -315,7 +271,7 @@ fn fmt_ty_ann(
buf.spaces(1);
ret.value
.format_with_options(buf, Parens::InFunctionType, Newlines::No, flags, indent);
.format_with_options(buf, Parens::InFunctionType, Newlines::No, indent);
if needs_parens {
buf.push(')')
@ -357,17 +313,12 @@ fn fmt_ty_ann(
let arg = arg.extract_spaces();
fmt_spaces(buf, arg.before.iter(), arg_indent);
buf.ensure_ends_with_newline();
arg.item.format_with_options(
buf,
Parens::InApply,
Newlines::Yes,
flags,
arg_indent,
);
arg.item
.format_with_options(buf, Parens::InApply, Newlines::Yes, arg_indent);
fmt_spaces(buf, arg.after.iter(), arg_indent);
} else {
buf.spaces(1);
arg.format_with_options(buf, Parens::InApply, Newlines::No, flags, arg_indent);
arg.format_with_options(buf, Parens::InApply, Newlines::No, arg_indent);
}
}
@ -389,24 +340,24 @@ fn fmt_ty_ann(
}
TypeAnnotation::TagUnion { tags, ext } => {
fmt_collection(buf, flags, indent, Braces::Square, *tags, newlines);
fmt_ext(ext, buf, flags, indent);
fmt_collection(buf, indent, Braces::Square, *tags, newlines);
fmt_ext(ext, buf, indent);
}
TypeAnnotation::Tuple { elems: fields, ext } => {
fmt_ty_collection(buf, flags, indent, Braces::Round, *fields, newlines);
fmt_ext(ext, buf, flags, indent);
fmt_ty_collection(buf, indent, Braces::Round, *fields, newlines);
fmt_ext(ext, buf, indent);
}
TypeAnnotation::Record { fields, ext } => {
fmt_collection(buf, flags, indent, Braces::Curly, *fields, newlines);
fmt_ext(ext, buf, flags, indent);
fmt_collection(buf, indent, Braces::Curly, *fields, newlines);
fmt_ext(ext, buf, indent);
}
TypeAnnotation::As(lhs, _spaces, TypeHeader { name, vars }) => {
// TODO use _spaces?
lhs.value
.format_with_options(buf, Parens::InFunctionType, Newlines::No, flags, indent);
.format_with_options(buf, Parens::InFunctionType, Newlines::No, indent);
buf.spaces(1);
buf.push_str("as");
buf.spaces(1);
@ -414,12 +365,12 @@ fn fmt_ty_ann(
for var in *vars {
buf.spaces(1);
var.value
.format_with_options(buf, Parens::NotNeeded, Newlines::No, flags, indent);
.format_with_options(buf, Parens::NotNeeded, Newlines::No, indent);
}
}
TypeAnnotation::Where(annot, implements_clauses) => {
annot.format_with_options(buf, parens, newlines, flags, indent);
annot.format_with_options(buf, parens, newlines, indent);
if implements_clauses
.iter()
.any(|implements| implements.is_multiline())
@ -436,7 +387,7 @@ fn fmt_ty_ann(
","
});
buf.spaces(1);
has.format_with_options(buf, parens, newlines, flags, indent);
has.format_with_options(buf, parens, newlines, indent);
}
}
TypeAnnotation::Malformed(raw) => {
@ -473,7 +424,7 @@ fn lower<'a, 'b: 'a>(
fn fmt_ty_collection(
buf: &mut Buf<'_>,
flags: &MigrationFlags,
indent: u16,
braces: Braces,
items: Collection<'_, Loc<TypeAnnotation<'_>>>,
@ -510,15 +461,10 @@ fn fmt_ty_collection(
let new_items =
Collection::with_items_and_comments(arena, new_items.into_bump_slice(), final_comments);
fmt_collection(buf, flags, indent, braces, new_items, newlines)
fmt_collection(buf, indent, braces, new_items, newlines)
}
fn fmt_ext(
ext: &Option<&Loc<TypeAnnotation<'_>>>,
buf: &mut Buf<'_>,
flags: &MigrationFlags,
indent: u16,
) {
fn fmt_ext(ext: &Option<&Loc<TypeAnnotation<'_>>>, buf: &mut Buf<'_>, indent: u16) {
if let Some(loc_ext_ann) = *ext {
let me = ann_lift_spaces(buf.text.bump(), &loc_ext_ann.value);
let parens_needed = !me.before.is_empty() || ext_needs_parens(me.item);
@ -526,11 +472,11 @@ fn fmt_ext(
// We need to make sure to not have whitespace before the ext of a type,
// since that would make it parse as something else.
buf.push('(');
loc_ext_ann.value.format(buf, flags, indent + INDENT);
loc_ext_ann.value.format(buf, indent + INDENT);
buf.indent(indent);
buf.push(')');
} else {
loc_ext_ann.value.format(buf, flags, indent + INDENT);
loc_ext_ann.value.format(buf, indent + INDENT);
}
}
}
@ -586,16 +532,9 @@ impl<'a> Formattable for AssignedField<'a, TypeAnnotation<'a>> {
is_multiline_assigned_field_help(self)
}
fn format_with_options(
&self,
buf: &mut Buf,
_parens: Parens,
newlines: Newlines,
flags: &MigrationFlags,
indent: u16,
) {
fn format_with_options(&self, buf: &mut Buf, _parens: Parens, newlines: Newlines, indent: u16) {
// we abuse the `Newlines` type to decide between multiline or single-line layout
format_assigned_field_help(self, buf, flags, indent, 1, newlines == Newlines::Yes);
format_assigned_field_help(self, buf, indent, 1, newlines == Newlines::Yes);
}
}
@ -604,16 +543,9 @@ impl<'a> Formattable for AssignedField<'a, Expr<'a>> {
is_multiline_assigned_field_help(self)
}
fn format_with_options(
&self,
buf: &mut Buf,
_parens: Parens,
newlines: Newlines,
flags: &MigrationFlags,
indent: u16,
) {
fn format_with_options(&self, buf: &mut Buf, _parens: Parens, newlines: Newlines, indent: u16) {
// we abuse the `Newlines` type to decide between multiline or single-line layout
format_assigned_field_help(self, buf, flags, indent, 0, newlines == Newlines::Yes);
format_assigned_field_help(self, buf, indent, 0, newlines == Newlines::Yes);
}
}
@ -632,7 +564,7 @@ fn is_multiline_assigned_field_help<T: Formattable>(afield: &AssignedField<'_, T
fn format_assigned_field_help<T>(
zelf: &AssignedField<T>,
buf: &mut Buf,
flags: &MigrationFlags,
indent: u16,
separator_spaces: usize,
is_multiline: bool,
@ -658,7 +590,7 @@ fn format_assigned_field_help<T>(
buf.indent(indent);
buf.push(':');
buf.spaces(1);
ann.value.format(buf, flags, indent);
ann.value.format(buf, indent);
}
OptionalValue(name, spaces, ann) => {
if is_multiline {
@ -676,7 +608,7 @@ fn format_assigned_field_help<T>(
buf.indent(indent);
buf.push('?');
buf.spaces(1);
ann.value.format(buf, flags, indent);
ann.value.format(buf, indent);
}
IgnoredValue(name, spaces, ann) => {
if is_multiline {
@ -694,7 +626,7 @@ fn format_assigned_field_help<T>(
buf.spaces(separator_spaces);
buf.push(':');
buf.spaces(1);
ann.value.format(buf, flags, indent);
ann.value.format(buf, indent);
}
LabelOnly(name) => {
if is_multiline {
@ -706,24 +638,10 @@ fn format_assigned_field_help<T>(
}
AssignedField::SpaceBefore(sub_field, spaces) => {
fmt_comments_only(buf, spaces.iter(), NewlineAt::Bottom, indent);
format_assigned_field_help(
sub_field,
buf,
flags,
indent,
separator_spaces,
is_multiline,
);
format_assigned_field_help(sub_field, buf, indent, separator_spaces, is_multiline);
}
AssignedField::SpaceAfter(sub_field, spaces) => {
format_assigned_field_help(
sub_field,
buf,
flags,
indent,
separator_spaces,
is_multiline,
);
format_assigned_field_help(sub_field, buf, indent, separator_spaces, is_multiline);
fmt_comments_only(buf, spaces.iter(), NewlineAt::Bottom, indent);
}
}
@ -744,7 +662,7 @@ impl<'a> Formattable for Tag<'a> {
buf: &mut Buf,
_parens: Parens,
_newlines: Newlines,
flags: &MigrationFlags,
indent: u16,
) {
let is_multiline = self.is_multiline();
@ -762,14 +680,13 @@ impl<'a> Formattable for Tag<'a> {
buf,
Parens::InApply,
Newlines::No,
flags,
arg_indent,
);
}
} else {
for arg in *args {
buf.spaces(1);
arg.format_with_options(buf, Parens::InApply, Newlines::No, flags, indent);
arg.format_with_options(buf, Parens::InApply, Newlines::No, indent);
}
}
}
@ -784,14 +701,7 @@ impl<'a> Formattable for ImplementsClause<'a> {
false
}
fn format_with_options(
&self,
buf: &mut Buf,
parens: Parens,
newlines: Newlines,
flags: &MigrationFlags,
indent: u16,
) {
fn format_with_options(&self, buf: &mut Buf, parens: Parens, newlines: Newlines, indent: u16) {
buf.push_str(self.var.value.extract_spaces().item);
buf.spaces(1);
buf.push_str(roc_parse::keyword::IMPLEMENTS);
@ -803,7 +713,7 @@ impl<'a> Formattable for ImplementsClause<'a> {
buf.push('&');
buf.spaces(1);
}
ab.format_with_options(buf, parens, newlines, flags, indent);
ab.format_with_options(buf, parens, newlines, indent);
}
}
}
@ -816,30 +726,23 @@ impl<'a> Formattable for AbilityImpls<'a> {
}
}
fn format_with_options(
&self,
buf: &mut Buf,
parens: Parens,
newlines: Newlines,
flags: &MigrationFlags,
indent: u16,
) {
fn format_with_options(&self, buf: &mut Buf, parens: Parens, newlines: Newlines, indent: u16) {
match self {
AbilityImpls::AbilityImpls(impls) => {
if newlines == Newlines::Yes {
buf.newline();
buf.indent(indent);
}
fmt_collection(buf, flags, indent, Braces::Curly, *impls, Newlines::No);
fmt_collection(buf, indent, Braces::Curly, *impls, Newlines::No);
}
AbilityImpls::SpaceBefore(impls, spaces) => {
buf.newline();
buf.indent(indent);
fmt_comments_only(buf, spaces.iter(), NewlineAt::Bottom, indent);
impls.format_with_options(buf, parens, Newlines::No, flags, indent);
impls.format_with_options(buf, parens, Newlines::No, indent);
}
AbilityImpls::SpaceAfter(impls, spaces) => {
impls.format_with_options(buf, parens, newlines, flags, indent);
impls.format_with_options(buf, parens, newlines, indent);
fmt_comments_only(buf, spaces.iter(), NewlineAt::Bottom, indent);
}
}
@ -856,34 +759,27 @@ impl<'a> Formattable for ImplementsAbility<'a> {
}
}
fn format_with_options(
&self,
buf: &mut Buf,
parens: Parens,
newlines: Newlines,
flags: &MigrationFlags,
indent: u16,
) {
fn format_with_options(&self, buf: &mut Buf, parens: Parens, newlines: Newlines, indent: u16) {
match self {
ImplementsAbility::ImplementsAbility { ability, impls } => {
if newlines == Newlines::Yes {
buf.newline();
buf.indent(indent);
}
ability.format_with_options(buf, parens, newlines, flags, indent);
ability.format_with_options(buf, parens, newlines, indent);
if let Some(impls) = impls {
buf.spaces(1);
impls.format_with_options(buf, parens, newlines, flags, indent);
impls.format_with_options(buf, parens, newlines, indent);
}
}
ImplementsAbility::SpaceBefore(ab, spaces) => {
buf.newline();
buf.indent(indent);
fmt_comments_only(buf, spaces.iter(), NewlineAt::Bottom, indent);
ab.format_with_options(buf, parens, Newlines::No, flags, indent)
ab.format_with_options(buf, parens, Newlines::No, indent)
}
ImplementsAbility::SpaceAfter(ab, spaces) => {
ab.format_with_options(buf, parens, newlines, flags, indent);
ab.format_with_options(buf, parens, newlines, indent);
fmt_comments_only(buf, spaces.iter(), NewlineAt::Bottom, indent);
}
}
@ -900,14 +796,7 @@ impl<'a> Formattable for ImplementsAbilities<'a> {
}
}
fn format_with_options(
&self,
buf: &mut Buf,
parens: Parens,
newlines: Newlines,
flags: &MigrationFlags,
indent: u16,
) {
fn format_with_options(&self, buf: &mut Buf, parens: Parens, newlines: Newlines, indent: u16) {
match self {
ImplementsAbilities::Implements(has_abilities) => {
if newlines == Newlines::Yes {
@ -916,23 +805,16 @@ impl<'a> Formattable for ImplementsAbilities<'a> {
}
buf.push_str(roc_parse::keyword::IMPLEMENTS);
buf.spaces(1);
fmt_collection(
buf,
flags,
indent,
Braces::Square,
*has_abilities,
Newlines::No,
);
fmt_collection(buf, indent, Braces::Square, *has_abilities, Newlines::No);
}
ImplementsAbilities::SpaceBefore(has_abilities, spaces) => {
buf.newline();
buf.indent(indent);
fmt_comments_only(buf, spaces.iter(), NewlineAt::Bottom, indent);
has_abilities.format_with_options(buf, parens, Newlines::No, flags, indent)
has_abilities.format_with_options(buf, parens, Newlines::No, indent)
}
ImplementsAbilities::SpaceAfter(has_abilities, spaces) => {
has_abilities.format_with_options(buf, parens, newlines, flags, indent);
has_abilities.format_with_options(buf, parens, newlines, indent);
fmt_comments_only(buf, spaces.iter(), NewlineAt::Bottom, indent);
}
}
@ -1056,14 +938,7 @@ impl<'a> Formattable for Node<'a> {
}
}
fn format_with_options(
&self,
buf: &mut Buf,
parens: Parens,
newlines: Newlines,
flags: &MigrationFlags,
indent: u16,
) {
fn format_with_options(&self, buf: &mut Buf, parens: Parens, newlines: Newlines, indent: u16) {
match self {
Node::DelimitedSequence(braces, lefts, right) => {
buf.indent(indent);
@ -1074,7 +949,7 @@ impl<'a> Formattable for Node<'a> {
fmt_spaces(buf, sp.iter(), indent);
}
l.format_with_options(buf, parens, newlines, flags, indent);
l.format_with_options(buf, parens, newlines, indent);
}
if !right.is_empty() {
@ -1085,7 +960,7 @@ impl<'a> Formattable for Node<'a> {
buf.push(braces.end());
}
Node::TypeAnnotation(type_annotation) => {
type_annotation.format_with_options(buf, parens, newlines, flags, indent);
type_annotation.format_with_options(buf, parens, newlines, indent);
}
}
}
@ -1222,12 +1097,11 @@ impl<'a, V: Formattable> Formattable for NodeSpaces<'a, V> {
buf: &mut Buf,
parens: crate::annotation::Parens,
newlines: Newlines,
flags: &MigrationFlags,
indent: u16,
) {
fmt_spaces(buf, self.before.iter(), indent);
self.item
.format_with_options(buf, parens, newlines, flags, indent);
self.item.format_with_options(buf, parens, newlines, indent);
fmt_spaces(buf, self.after.iter(), indent);
}
}

View file

@ -35,7 +35,7 @@ impl Braces {
pub fn fmt_collection<'a, 'buf, T: ExtractSpaces<'a> + Formattable + std::fmt::Debug>(
buf: &mut Buf<'buf>,
flags: &crate::annotation::MigrationFlags,
indent: u16,
braces: Braces,
items: Collection<'a, T>,
@ -110,7 +110,7 @@ pub fn fmt_collection<'a, 'buf, T: ExtractSpaces<'a> + Formattable + std::fmt::D
}
buf.indent(item_indent);
item.item.format(buf, flags, item_indent);
item.item.format(buf, item_indent);
buf.indent(item_indent);
buf.push(',');
@ -153,7 +153,7 @@ pub fn fmt_collection<'a, 'buf, T: ExtractSpaces<'a> + Formattable + std::fmt::D
buf.spaces(1);
}
item.format(buf, flags, indent);
item.format(buf, indent);
if iter.peek().is_some() {
buf.push(',');
}

View file

@ -1,6 +1,6 @@
use crate::annotation::{
ann_lift_spaces, ann_lift_spaces_after, is_collection_multiline, ty_is_outdentable,
Formattable, MigrationFlags, Newlines, Parens,
Formattable, Newlines, Parens,
};
use crate::collection::{fmt_collection, Braces};
use crate::expr::{
@ -37,7 +37,7 @@ impl<'a> Formattable for Defs<'a> {
buf: &mut Buf,
_parens: Parens,
_newlines: Newlines,
flags: &crate::annotation::MigrationFlags,
indent: u16,
) {
let mut prev_spaces = true;
@ -59,8 +59,8 @@ impl<'a> Formattable for Defs<'a> {
}
match def.item {
Ok(type_def) => type_def.format(buf, flags, indent),
Err(value_def) => value_def.format(buf, flags, indent),
Ok(type_def) => type_def.format(buf, indent),
Err(value_def) => value_def.format(buf, indent),
}
fmt_spaces(buf, spaces_after.iter(), indent);
@ -414,19 +414,12 @@ impl<'a> Formattable for TypeDef<'a> {
}
}
fn format_with_options(
&self,
buf: &mut Buf,
_parens: Parens,
newlines: Newlines,
flags: &crate::annotation::MigrationFlags,
indent: u16,
) {
fn format_with_options(&self, buf: &mut Buf, _parens: Parens, newlines: Newlines, indent: u16) {
use roc_parse::ast::TypeDef::*;
match self {
Alias { header, ann } => {
header.format(buf, flags, indent);
header.format(buf, indent);
buf.indent(indent);
buf.push_str(" :");
@ -440,7 +433,7 @@ impl<'a> Formattable for TypeDef<'a> {
indent + INDENT
};
fmt_comments_only(buf, ann.before.iter(), NewlineAt::Bottom, inner_indent);
ann.item.format(buf, flags, inner_indent);
ann.item.format(buf, inner_indent);
fmt_spaces(buf, ann.after.iter(), indent);
}
Opaque {
@ -461,7 +454,7 @@ impl<'a> Formattable for TypeDef<'a> {
let make_multiline = ann.is_multiline() || has_abilities_multiline;
fmt_general_def(header, buf, flags, indent, ":=", &ann.value, newlines);
fmt_general_def(header, buf, indent, ":=", &ann.value, newlines);
if let Some(has_abilities) = has_abilities {
buf.spaces(1);
@ -470,7 +463,6 @@ impl<'a> Formattable for TypeDef<'a> {
buf,
Parens::NotNeeded,
Newlines::from_bool(make_multiline),
flags,
indent + INDENT,
);
}
@ -480,7 +472,7 @@ impl<'a> Formattable for TypeDef<'a> {
loc_implements: _,
members,
} => {
header.format_with_options(buf, Parens::NotNeeded, Newlines::No, flags, indent);
header.format_with_options(buf, Parens::NotNeeded, Newlines::No, indent);
buf.spaces(1);
buf.push_str(roc_parse::keyword::IMPLEMENTS);
@ -491,7 +483,6 @@ impl<'a> Formattable for TypeDef<'a> {
buf,
Parens::NotNeeded,
Newlines::No,
flags,
indent + INDENT,
);
} else {
@ -500,7 +491,6 @@ impl<'a> Formattable for TypeDef<'a> {
buf,
Parens::NotNeeded,
Newlines::Yes,
flags,
indent + INDENT,
);
}
@ -520,7 +510,7 @@ impl<'a> Formattable for TypeHeader<'a> {
buf: &mut Buf,
_parens: Parens,
_newlines: Newlines,
flags: &crate::annotation::MigrationFlags,
indent: u16,
) {
buf.indent(indent);
@ -563,7 +553,7 @@ impl<'a> Formattable for TypeHeader<'a> {
buf.push_str("(");
}
fmt_pattern(buf, &var.item, flags, vars_indent, Parens::NotNeeded);
fmt_pattern(buf, &var.item, vars_indent, Parens::NotNeeded);
buf.indent(vars_indent);
@ -611,7 +601,7 @@ impl<'a> Formattable for ModuleImport<'a> {
buf: &mut Buf,
_parens: Parens,
_newlines: Newlines,
flags: &crate::annotation::MigrationFlags,
indent: u16,
) {
let Self {
@ -637,20 +627,13 @@ impl<'a> Formattable for ModuleImport<'a> {
fmt_default_spaces(buf, before_name, indent);
name.format(buf, flags, indent);
params.format(buf, flags, indent);
alias.format(buf, flags, indent);
name.format(buf, indent);
params.format(buf, indent);
alias.format(buf, indent);
if let Some(exposed) = exposed {
exposed.keyword.format(buf, flags, indent);
fmt_collection(
buf,
flags,
indent,
Braces::Square,
exposed.item,
Newlines::No,
);
exposed.keyword.format(buf, indent);
fmt_collection(buf, indent, Braces::Square, exposed.item, Newlines::No);
}
}
}
@ -662,18 +645,11 @@ impl<'a> Formattable for ModuleImportParams<'a> {
!before.is_empty() || is_collection_multiline(&params.value)
}
fn format_with_options(
&self,
buf: &mut Buf,
_parens: Parens,
newlines: Newlines,
flags: &crate::annotation::MigrationFlags,
indent: u16,
) {
fn format_with_options(&self, buf: &mut Buf, _parens: Parens, newlines: Newlines, indent: u16) {
let ModuleImportParams { before, params } = self;
fmt_default_spaces(buf, before, indent);
fmt_collection(buf, flags, indent, Braces::Curly, params.value, newlines);
fmt_collection(buf, indent, Braces::Curly, params.value, newlines);
}
}
@ -693,7 +669,7 @@ impl<'a> Formattable for IngestedFileImport<'a> {
buf: &mut Buf,
_parens: Parens,
_newlines: Newlines,
flags: &crate::annotation::MigrationFlags,
indent: u16,
) {
let Self {
@ -709,12 +685,12 @@ impl<'a> Formattable for IngestedFileImport<'a> {
let indent = indent + INDENT;
fmt_default_spaces(buf, before_path, indent);
fmt_str_literal(buf, path.value, flags, indent);
fmt_str_literal(buf, path.value, indent);
name.keyword.format(buf, flags, indent);
name.keyword.format(buf, indent);
buf.push_str(name.item.value);
annotation.format(buf, flags, indent);
annotation.format(buf, indent);
}
}
@ -729,7 +705,7 @@ impl<'a> Formattable for ImportedModuleName<'a> {
buf: &mut Buf,
_parens: Parens,
_newlines: Newlines,
flags: &crate::annotation::MigrationFlags,
indent: u16,
) {
buf.indent(indent);
@ -739,7 +715,7 @@ impl<'a> Formattable for ImportedModuleName<'a> {
buf.push_str(".");
}
self.name.format(buf, flags, indent);
self.name.format(buf, indent);
}
}
@ -754,7 +730,6 @@ impl<'a> Formattable for ImportAlias<'a> {
buf: &mut Buf,
_parens: Parens,
_newlines: Newlines,
_flags: &crate::annotation::MigrationFlags,
indent: u16,
) {
buf.indent(indent);
@ -772,7 +747,6 @@ impl Formattable for ImportAsKeyword {
buf: &mut Buf<'_>,
_parens: crate::annotation::Parens,
_newlines: Newlines,
_flags: &crate::annotation::MigrationFlags,
indent: u16,
) {
buf.indent(indent);
@ -790,7 +764,6 @@ impl Formattable for ImportExposingKeyword {
buf: &mut Buf<'_>,
_parens: crate::annotation::Parens,
_newlines: Newlines,
_flags: &crate::annotation::MigrationFlags,
indent: u16,
) {
buf.indent(indent);
@ -812,7 +785,7 @@ impl<'a> Formattable for IngestedFileAnnotation<'a> {
buf: &mut Buf,
_parens: Parens,
_newlines: Newlines,
flags: &crate::annotation::MigrationFlags,
indent: u16,
) {
let Self {
@ -823,7 +796,7 @@ impl<'a> Formattable for IngestedFileAnnotation<'a> {
fmt_default_spaces(buf, before_colon, indent);
buf.push_str(":");
buf.spaces(1);
annotation.format(buf, flags, indent);
annotation.format(buf, indent);
}
}
@ -846,21 +819,13 @@ impl<'a> Formattable for ValueDef<'a> {
}
}
fn format_with_options(
&self,
buf: &mut Buf,
parens: Parens,
newlines: Newlines,
flags: &crate::annotation::MigrationFlags,
indent: u16,
) {
fn format_with_options(&self, buf: &mut Buf, parens: Parens, newlines: Newlines, indent: u16) {
use roc_parse::ast::ValueDef::*;
match self {
Annotation(loc_pattern, loc_annotation) => {
fmt_general_def(
loc_pattern,
buf,
flags,
indent,
":",
&loc_annotation.value,
@ -868,21 +833,10 @@ impl<'a> Formattable for ValueDef<'a> {
);
}
Body(loc_pattern, loc_expr) => {
fmt_body(
buf,
true,
&loc_pattern.value,
&loc_expr.value,
flags,
indent,
);
}
Dbg { condition, .. } => {
fmt_dbg_in_def(buf, condition, self.is_multiline(), flags, indent)
}
Expect { condition, .. } => {
fmt_expect(buf, condition, self.is_multiline(), flags, indent)
fmt_body(buf, true, &loc_pattern.value, &loc_expr.value, indent);
}
Dbg { condition, .. } => fmt_dbg_in_def(buf, condition, self.is_multiline(), indent),
Expect { condition, .. } => fmt_expect(buf, condition, self.is_multiline(), indent),
AnnotatedBody {
ann_pattern,
ann_type,
@ -890,33 +844,16 @@ impl<'a> Formattable for ValueDef<'a> {
body_pattern,
body_expr,
} => {
fmt_general_def(
ann_pattern,
buf,
flags,
indent,
":",
&ann_type.value,
newlines,
);
fmt_general_def(ann_pattern, buf, indent, ":", &ann_type.value, newlines);
fmt_annotated_body_comment(buf, indent, lines_between);
buf.newline();
fmt_body(
buf,
false,
&body_pattern.value,
&body_expr.value,
flags,
indent,
);
fmt_body(buf, false, &body_pattern.value, &body_expr.value, indent);
}
ModuleImport(module_import) => module_import.format(buf, flags, indent),
IngestedFileImport(ingested_file_import) => {
ingested_file_import.format(buf, flags, indent)
}
Stmt(loc_expr) => loc_expr.format_with_options(buf, parens, newlines, flags, indent),
ModuleImport(module_import) => module_import.format(buf, indent),
IngestedFileImport(ingested_file_import) => ingested_file_import.format(buf, indent),
Stmt(loc_expr) => loc_expr.format_with_options(buf, parens, newlines, indent),
StmtAfterExpr => internal_error!("shouldn't exist before can"),
}
}
@ -925,13 +862,13 @@ impl<'a> Formattable for ValueDef<'a> {
fn fmt_general_def<L: Formattable>(
lhs: L,
buf: &mut Buf,
flags: &crate::annotation::MigrationFlags,
indent: u16,
sep: &str,
rhs: &TypeAnnotation,
newlines: Newlines,
) {
lhs.format(buf, flags, indent);
lhs.format(buf, indent);
buf.indent(indent);
if rhs.is_multiline() {
@ -942,13 +879,9 @@ fn fmt_general_def<L: Formattable>(
let rhs_lifted = ann_lift_spaces(buf.text.bump(), rhs);
if ty_is_outdentable(&rhs_lifted.item) && rhs_lifted.before.iter().all(|s| s.is_newline()) {
rhs_lifted.item.format_with_options(
buf,
Parens::NotNeeded,
Newlines::No,
flags,
indent,
);
rhs_lifted
.item
.format_with_options(buf, Parens::NotNeeded, Newlines::No, indent);
} else {
buf.ensure_ends_with_newline();
fmt_comments_only(
@ -957,46 +890,30 @@ fn fmt_general_def<L: Formattable>(
NewlineAt::Bottom,
indent + INDENT,
);
rhs_lifted.item.format_with_options(
buf,
Parens::NotNeeded,
newlines,
flags,
indent + INDENT,
);
rhs_lifted
.item
.format_with_options(buf, Parens::NotNeeded, newlines, indent + INDENT);
}
fmt_comments_only(buf, rhs_lifted.after.iter(), NewlineAt::Bottom, indent);
} else {
buf.spaces(1);
buf.push_str(sep);
buf.spaces(1);
rhs.format_with_options(buf, Parens::NotNeeded, Newlines::No, flags, indent);
rhs.format_with_options(buf, Parens::NotNeeded, Newlines::No, indent);
}
}
fn fmt_dbg_in_def<'a>(
buf: &mut Buf,
condition: &'a Loc<Expr<'a>>,
_: bool,
flags: &MigrationFlags,
indent: u16,
) {
fn fmt_dbg_in_def<'a>(buf: &mut Buf, condition: &'a Loc<Expr<'a>>, _: bool, indent: u16) {
buf.ensure_ends_with_newline();
buf.indent(indent);
buf.push_str("dbg");
buf.spaces(1);
condition.format(buf, flags, indent);
condition.format(buf, indent);
}
fn fmt_expect<'a>(
buf: &mut Buf,
condition: &'a Loc<Expr<'a>>,
is_multiline: bool,
flags: &crate::annotation::MigrationFlags,
indent: u16,
) {
fn fmt_expect<'a>(buf: &mut Buf, condition: &'a Loc<Expr<'a>>, is_multiline: bool, indent: u16) {
buf.ensure_ends_with_newline();
buf.indent(indent);
buf.push_str("expect");
@ -1009,34 +926,19 @@ fn fmt_expect<'a>(
indent
};
condition.format(buf, flags, return_indent);
condition.format(buf, return_indent);
}
pub fn fmt_value_def(
buf: &mut Buf,
def: &roc_parse::ast::ValueDef,
flags: &crate::annotation::MigrationFlags,
indent: u16,
) {
def.format(buf, flags, indent);
pub fn fmt_value_def(buf: &mut Buf, def: &roc_parse::ast::ValueDef, indent: u16) {
def.format(buf, indent);
}
pub fn fmt_type_def(
buf: &mut Buf,
def: &roc_parse::ast::TypeDef,
flags: &crate::annotation::MigrationFlags,
indent: u16,
) {
def.format(buf, flags, indent);
pub fn fmt_type_def(buf: &mut Buf, def: &roc_parse::ast::TypeDef, indent: u16) {
def.format(buf, indent);
}
pub fn fmt_defs(
buf: &mut Buf,
defs: &Defs,
flags: &crate::annotation::MigrationFlags,
indent: u16,
) {
defs.format(buf, flags, indent);
pub fn fmt_defs(buf: &mut Buf, defs: &Defs, indent: u16) {
defs.format(buf, indent);
}
pub fn fmt_annotated_body_comment<'a>(
@ -1087,7 +989,7 @@ pub fn fmt_body<'a>(
allow_simplify_empty_record_destructure: bool,
pattern: &'a Pattern<'a>,
body: &'a Expr<'a>,
flags: &MigrationFlags,
indent: u16,
) {
let pattern_extracted = pattern.extract_spaces();
@ -1104,10 +1006,10 @@ pub fn fmt_body<'a>(
// Don't format the `{} =` for defs with this pattern
if is_unit_assignment {
return body.format_with_options(buf, Parens::NotNeeded, Newlines::No, flags, indent);
return body.format_with_options(buf, Parens::NotNeeded, Newlines::No, indent);
}
pattern.format_with_options(buf, Parens::InApply, Newlines::No, flags, indent);
pattern.format_with_options(buf, Parens::InApply, Newlines::No, indent);
buf.indent(indent);
buf.push_str(" =");
@ -1126,28 +1028,15 @@ pub fn fmt_body<'a>(
if is_unit_assignment {
fmt_comments_only(buf, spaces.iter(), NewlineAt::Bottom, indent);
sub_def.format_with_options(
buf,
Parens::NotNeeded,
Newlines::Yes,
flags,
indent,
);
sub_def.format_with_options(buf, Parens::NotNeeded, Newlines::Yes, indent);
} else if should_outdent {
buf.spaces(1);
sub_def.format_with_options(
buf,
Parens::NotNeeded,
Newlines::Yes,
flags,
indent,
);
sub_def.format_with_options(buf, Parens::NotNeeded, Newlines::Yes, indent);
} else {
body.format_with_options(
buf,
Parens::NotNeeded,
Newlines::Yes,
flags,
indent + INDENT,
);
}
@ -1160,13 +1049,7 @@ pub fn fmt_body<'a>(
..,
) => {
buf.spaces(1);
body.format_with_options(
buf,
Parens::NotNeeded,
Newlines::Yes,
flags,
indent + INDENT,
);
body.format_with_options(buf, Parens::NotNeeded, Newlines::Yes, indent + INDENT);
}
Expr::Str(s) => {
if is_str_multiline(&s) {
@ -1174,33 +1057,15 @@ pub fn fmt_body<'a>(
} else {
buf.spaces(1);
}
body.format_with_options(
buf,
Parens::NotNeeded,
Newlines::Yes,
flags,
indent + INDENT,
);
body.format_with_options(buf, Parens::NotNeeded, Newlines::Yes, indent + INDENT);
}
_ if starts_with_block_string_literal(&body) => {
buf.ensure_ends_with_newline();
body.format_with_options(
buf,
Parens::NotNeeded,
Newlines::Yes,
flags,
indent + INDENT,
);
body.format_with_options(buf, Parens::NotNeeded, Newlines::Yes, indent + INDENT);
}
Expr::When(..) => {
buf.ensure_ends_with_newline();
body.format_with_options(
buf,
Parens::NotNeeded,
Newlines::Yes,
flags,
indent + INDENT,
);
body.format_with_options(buf, Parens::NotNeeded, Newlines::Yes, indent + INDENT);
}
Expr::Defs(..) | Expr::BinOps(_, _) | Expr::Backpassing(..) => {
// Binop chains always get a newline. Otherwise you can have things like:
@ -1216,13 +1081,7 @@ pub fn fmt_body<'a>(
//
// This makes it clear what the binop is applying to!
buf.newline();
body.format_with_options(
buf,
Parens::NotNeeded,
Newlines::Yes,
flags,
indent + INDENT,
);
body.format_with_options(buf, Parens::NotNeeded, Newlines::Yes, indent + INDENT);
}
Expr::ParensAround(&Expr::SpaceBefore(sub_def, _)) => {
let needs_indent = !sub_expr_requests_parens(sub_def);
@ -1232,16 +1091,16 @@ pub fn fmt_body<'a>(
indent
};
buf.spaces(1);
body.format_with_options(buf, Parens::NotNeeded, Newlines::Yes, flags, indent);
body.format_with_options(buf, Parens::NotNeeded, Newlines::Yes, indent);
}
_ => {
buf.spaces(1);
body.format_with_options(buf, Parens::NotNeeded, Newlines::Yes, flags, indent);
body.format_with_options(buf, Parens::NotNeeded, Newlines::Yes, indent);
}
}
} else {
buf.spaces(1);
body.format_with_options(buf, Parens::NotNeeded, Newlines::Yes, flags, indent);
body.format_with_options(buf, Parens::NotNeeded, Newlines::Yes, indent);
}
}
@ -1267,7 +1126,7 @@ impl<'a> Formattable for AbilityMember<'a> {
buf: &mut Buf,
_parens: Parens,
_newlines: Newlines,
flags: &crate::annotation::MigrationFlags,
indent: u16,
) {
let Spaces { before, item, .. } = self.name.value.extract_spaces();
@ -1278,6 +1137,6 @@ impl<'a> Formattable for AbilityMember<'a> {
buf.spaces(1);
buf.push(':');
buf.spaces(1);
self.typ.value.format(buf, flags, indent + INDENT);
self.typ.value.format(buf, indent + INDENT);
}
}

View file

@ -1,6 +1,4 @@
use crate::annotation::{
except_last, is_collection_multiline, Formattable, MigrationFlags, Newlines, Parens,
};
use crate::annotation::{except_last, is_collection_multiline, Formattable, Newlines, Parens};
use crate::collection::{fmt_collection, Braces};
use crate::def::{fmt_defs, valdef_lift_spaces_before};
use crate::pattern::{fmt_pattern, pattern_lift_spaces, starts_with_inline_comment};
@ -30,14 +28,7 @@ impl<'a> Formattable for Expr<'a> {
expr_is_multiline(self, false)
}
fn format_with_options(
&self,
buf: &mut Buf,
parens: Parens,
newlines: Newlines,
flags: &MigrationFlags,
indent: u16,
) {
fn format_with_options(&self, buf: &mut Buf, parens: Parens, newlines: Newlines, indent: u16) {
use self::Expr::*;
let me = expr_lift_spaces(parens, buf.text.bump(), self);
@ -50,13 +41,13 @@ impl<'a> Formattable for Expr<'a> {
SpaceBefore(_sub_expr, _spaces) | SpaceAfter(_sub_expr, _spaces) => unreachable!(),
ParensAround(sub_expr) => {
if parens == Parens::NotNeeded && !sub_expr_requests_parens(sub_expr) {
sub_expr.format_with_options(buf, Parens::NotNeeded, newlines, flags, indent);
sub_expr.format_with_options(buf, Parens::NotNeeded, newlines, indent);
} else {
fmt_parens(sub_expr, buf, flags, indent);
fmt_parens(sub_expr, buf, indent);
}
}
Str(literal) => {
fmt_str_literal(buf, *literal, flags, indent);
fmt_str_literal(buf, *literal, indent);
}
Var { module_name, ident } => {
buf.indent(indent);
@ -84,9 +75,9 @@ impl<'a> Formattable for Expr<'a> {
let apply_needs_parens = parens == Parens::InApply;
if apply_needs_parens && !loc_args.is_empty() {
fmt_parens(self, buf, flags, indent);
fmt_parens(self, buf, indent);
} else {
fmt_apply(loc_expr, loc_args, flags, indent, buf);
fmt_apply(loc_expr, loc_args, indent, buf);
}
}
&Num(string) => {
@ -129,7 +120,6 @@ impl<'a> Formattable for Expr<'a> {
buf,
None,
*fields,
flags,
indent,
format_assigned_field_multiline,
assigned_field_to_space_before,
@ -140,7 +130,6 @@ impl<'a> Formattable for Expr<'a> {
buf,
Some(RecordPrefix::Update(update)),
*fields,
flags,
indent,
format_assigned_field_multiline,
assigned_field_to_space_before,
@ -151,29 +140,28 @@ impl<'a> Formattable for Expr<'a> {
buf,
Some(RecordPrefix::Mapper(mapper)),
*fields,
flags,
indent,
format_assigned_field_multiline,
assigned_field_to_space_before,
);
}
Closure(loc_patterns, loc_ret) => {
fmt_closure(buf, loc_patterns, loc_ret, flags, indent);
fmt_closure(buf, loc_patterns, loc_ret, indent);
}
Backpassing(loc_patterns, loc_body, loc_ret) => {
fmt_backpassing(buf, loc_patterns, loc_body, loc_ret, flags, indent);
fmt_backpassing(buf, loc_patterns, loc_body, loc_ret, indent);
}
Defs(defs, ret) => {
let defs_needs_parens = parens == Parens::InOperator || parens == Parens::InApply;
if defs_needs_parens {
fmt_parens(self, buf, flags, indent)
fmt_parens(self, buf, indent)
} else {
// It should theoretically be impossible to *parse* an empty defs list.
// (Canonicalization can remove defs later, but that hasn't happened yet!)
debug_assert!(!defs.is_empty());
fmt_defs(buf, defs, flags, indent);
fmt_defs(buf, defs, indent);
match &ret.value {
SpaceBefore(sub_expr, spaces) => {
@ -186,7 +174,6 @@ impl<'a> Formattable for Expr<'a> {
buf,
Parens::NotNeeded,
Newlines::Yes,
flags,
indent,
);
}
@ -195,13 +182,7 @@ impl<'a> Formattable for Expr<'a> {
buf.indent(indent);
// Even if there were no defs, which theoretically should never happen,
// still print the return value.
ret.format_with_options(
buf,
Parens::NotNeeded,
Newlines::Yes,
flags,
indent,
);
ret.format_with_options(buf, Parens::NotNeeded, Newlines::Yes, indent);
}
}
}
@ -215,21 +196,13 @@ impl<'a> Formattable for Expr<'a> {
extra_args,
continuation,
} => {
fmt_dbg_stmt(buf, first, extra_args, continuation, parens, flags, indent);
fmt_dbg_stmt(buf, first, extra_args, continuation, parens, indent);
}
LowLevelDbg(_, _, _) => unreachable!(
"LowLevelDbg should only exist after desugaring, not during formatting"
),
Return(return_value, after_return) => {
fmt_return(
buf,
return_value,
after_return,
parens,
newlines,
flags,
indent,
);
fmt_return(buf, return_value, after_return, parens, newlines, indent);
}
If {
if_thens: branches,
@ -242,18 +215,13 @@ impl<'a> Formattable for Expr<'a> {
final_else,
self.is_multiline(),
*indented_else,
flags,
indent,
);
}
When(loc_condition, branches) => fmt_when(buf, loc_condition, branches, flags, indent),
Tuple(items) => {
fmt_expr_collection(buf, flags, indent, Braces::Round, *items, Newlines::No)
}
List(items) => {
fmt_expr_collection(buf, flags, indent, Braces::Square, *items, Newlines::No)
}
BinOps(lefts, right) => fmt_binops(buf, lefts, right, flags, indent),
When(loc_condition, branches) => fmt_when(buf, loc_condition, branches, indent),
Tuple(items) => fmt_expr_collection(buf, indent, Braces::Round, *items, Newlines::No),
List(items) => fmt_expr_collection(buf, indent, Braces::Square, *items, Newlines::No),
BinOps(lefts, right) => fmt_binops(buf, lefts, right, indent),
UnaryOp(sub_expr, unary_op) => {
buf.indent(indent);
match &unary_op.value {
@ -287,7 +255,7 @@ impl<'a> Formattable for Expr<'a> {
if needs_parens {
// Unary negation can't be followed by whitespace (which is what a newline is) - so
// we need to wrap the negated value in parens.
fmt_parens(&sub_expr.value, buf, flags, indent);
fmt_parens(&sub_expr.value, buf, indent);
} else {
if matches!(unary_op.value, called_via::UnaryOp::Not)
&& requires_space_after_unary(&lifted.item)
@ -313,13 +281,9 @@ impl<'a> Formattable for Expr<'a> {
if !before_all_newlines {
format_spaces(buf, lifted.before, newlines, inner_indent);
}
lifted.item.format_with_options(
buf,
inner_parens,
newlines,
flags,
inner_indent,
);
lifted
.item
.format_with_options(buf, inner_parens, newlines, inner_indent);
format_spaces(buf, lifted.after, newlines, inner_indent);
}
}
@ -337,17 +301,17 @@ impl<'a> Formattable for Expr<'a> {
buf.push_str(key);
}
RecordAccess(expr, key) => {
expr.format_with_options(buf, Parens::InApply, Newlines::Yes, flags, indent);
expr.format_with_options(buf, Parens::InApply, Newlines::Yes, indent);
buf.push('.');
buf.push_str(key);
}
TupleAccess(expr, key) => {
expr.format_with_options(buf, Parens::InApply, Newlines::Yes, flags, indent);
expr.format_with_options(buf, Parens::InApply, Newlines::Yes, indent);
buf.push('.');
buf.push_str(key);
}
TrySuffix { expr, target } => {
expr.format_with_options(buf, Parens::InApply, Newlines::Yes, flags, indent);
expr.format_with_options(buf, Parens::InApply, Newlines::Yes, indent);
match target {
TryTarget::Task => buf.push('!'),
TryTarget::Result => buf.push('?'),
@ -359,7 +323,7 @@ impl<'a> Formattable for Expr<'a> {
}
MalformedSuffixed(loc_expr) => {
buf.indent(indent);
loc_expr.format_with_options(buf, parens, newlines, flags, indent);
loc_expr.format_with_options(buf, parens, newlines, indent);
}
PrecedenceConflict { .. } => {}
EmptyRecordBuilder { .. } => {}
@ -501,7 +465,7 @@ fn lower<'a, 'b: 'a>(arena: &'b Bump, lifted: Spaces<'b, Expr<'b>>) -> Expr<'b>
fn fmt_expr_collection(
buf: &mut Buf<'_>,
flags: &MigrationFlags,
indent: u16,
braces: Braces,
items: Collection<'_, &Loc<Expr<'_>>>,
@ -525,7 +489,7 @@ fn fmt_expr_collection(
let new_items =
Collection::with_items_and_comments(arena, new_items.into_bump_slice(), final_comments);
fmt_collection(buf, flags, indent, braces, new_items, newlines)
fmt_collection(buf, indent, braces, new_items, newlines)
}
fn requires_space_after_unary(item: &Expr<'_>) -> bool {
@ -550,7 +514,7 @@ fn requires_space_after_unary(item: &Expr<'_>) -> bool {
fn fmt_apply(
loc_expr: &Loc<Expr<'_>>,
loc_args: &[&Loc<Expr<'_>>],
flags: &MigrationFlags,
indent: u16,
buf: &mut Buf<'_>,
) {
@ -606,9 +570,9 @@ fn fmt_apply(
|| expr_needs_parens_in_apply(&loc_expr.value);
if expr_needs_parens {
fmt_parens(&loc_expr.value, buf, flags, indent);
fmt_parens(&loc_expr.value, buf, indent);
} else {
loc_expr.format_with_options(buf, Parens::InApply, Newlines::Yes, flags, indent);
loc_expr.format_with_options(buf, Parens::InApply, Newlines::Yes, indent);
}
for loc_arg in loc_args.iter() {
@ -621,17 +585,17 @@ fn fmt_apply(
let arg = loc_arg.extract_spaces();
arg.item
.format_with_options(buf, Parens::InApply, Newlines::Yes, flags, arg_indent);
.format_with_options(buf, Parens::InApply, Newlines::Yes, arg_indent);
} else if needs_indent {
let arg = loc_arg.extract_spaces();
fmt_spaces(buf, arg.before.iter(), arg_indent);
buf.ensure_ends_with_newline();
arg.item
.format_with_options(buf, Parens::InApply, Newlines::Yes, flags, arg_indent);
.format_with_options(buf, Parens::InApply, Newlines::Yes, arg_indent);
fmt_spaces(buf, arg.after.iter(), arg_indent);
} else {
buf.spaces(1);
loc_arg.format_with_options(buf, Parens::InApply, Newlines::Yes, flags, arg_indent);
loc_arg.format_with_options(buf, Parens::InApply, Newlines::Yes, arg_indent);
}
}
}
@ -663,7 +627,7 @@ fn expr_ends_in_closure(expr: &Expr<'_>) -> bool {
}
}
fn fmt_parens(sub_expr: &Expr<'_>, buf: &mut Buf<'_>, flags: &MigrationFlags, indent: u16) {
fn fmt_parens(sub_expr: &Expr<'_>, buf: &mut Buf<'_>, indent: u16) {
let should_add_newlines = match sub_expr {
Expr::Closure(..) | Expr::SpaceBefore(..) | Expr::SpaceAfter(Expr::Closure(..), ..) => {
false
@ -686,7 +650,7 @@ fn fmt_parens(sub_expr: &Expr<'_>, buf: &mut Buf<'_>, flags: &MigrationFlags, in
indent
};
sub_expr.format_with_options(buf, Parens::NotNeeded, Newlines::Yes, flags, next_indent);
sub_expr.format_with_options(buf, Parens::NotNeeded, Newlines::Yes, next_indent);
if !matches!(sub_expr, Expr::SpaceAfter(..)) && should_add_newlines {
buf.newline();
@ -779,7 +743,7 @@ fn fmt_str_body(body: &str, buf: &mut Buf) {
}
}
fn format_str_segment(seg: &StrSegment, buf: &mut Buf, flags: &MigrationFlags, indent: u16) {
fn format_str_segment(seg: &StrSegment, buf: &mut Buf, indent: u16) {
use StrSegment::*;
match seg {
@ -810,7 +774,6 @@ fn format_str_segment(seg: &StrSegment, buf: &mut Buf, flags: &MigrationFlags, i
buf,
Parens::NotNeeded, // We already printed parens!
Newlines::No, // Interpolations can never have newlines
flags,
indent,
);
buf.push(')');
@ -839,7 +802,7 @@ fn push_op(buf: &mut Buf, op: BinOp) {
}
}
pub fn fmt_str_literal(buf: &mut Buf, literal: StrLiteral, flags: &MigrationFlags, indent: u16) {
pub fn fmt_str_literal(buf: &mut Buf, literal: StrLiteral, indent: u16) {
use roc_parse::ast::StrLiteral::*;
match literal {
@ -868,7 +831,7 @@ pub fn fmt_str_literal(buf: &mut Buf, literal: StrLiteral, flags: &MigrationFlag
buf.indent(indent);
buf.push('"');
for seg in segments.iter() {
format_str_segment(seg, buf, flags, 0)
format_str_segment(seg, buf, 0)
}
buf.push('"');
}
@ -884,7 +847,7 @@ pub fn fmt_str_literal(buf: &mut Buf, literal: StrLiteral, flags: &MigrationFlag
// only add indent if the line isn't empty
if *seg != StrSegment::Plaintext("\n") {
buf.indent(indent);
format_str_segment(seg, buf, flags, indent);
format_str_segment(seg, buf, indent);
} else {
buf.push_newline_literal();
}
@ -1083,7 +1046,7 @@ fn fmt_binops<'a>(
buf: &mut Buf,
lefts: &'a [(Loc<Expr<'a>>, Loc<BinOp>)],
loc_right_side: &'a Loc<Expr<'a>>,
flags: &MigrationFlags,
indent: u16,
) {
let is_multiline = loc_right_side.value.is_multiline()
@ -1100,13 +1063,12 @@ fn fmt_binops<'a>(
|| starts_with_unary_minus(lifted_left_side.item);
if need_parens {
fmt_parens(&lifted_left_side.item, buf, flags, indent);
fmt_parens(&lifted_left_side.item, buf, indent);
} else {
lifted_left_side.item.format_with_options(
buf,
Parens::InOperator,
Newlines::Yes,
flags,
indent,
);
}
@ -1133,15 +1095,11 @@ fn fmt_binops<'a>(
|| starts_with_unary_minus(lifted_right_side.item);
if need_parens {
fmt_parens(&lifted_right_side.item, buf, flags, indent);
fmt_parens(&lifted_right_side.item, buf, indent);
} else {
lifted_right_side.item.format_with_options(
buf,
Parens::InOperator,
Newlines::Yes,
flags,
indent,
);
lifted_right_side
.item
.format_with_options(buf, Parens::InOperator, Newlines::Yes, indent);
}
format_spaces(buf, lifted_right_side.after, Newlines::Yes, indent);
@ -1198,7 +1156,7 @@ fn fmt_when<'a>(
buf: &mut Buf,
loc_condition: &'a Loc<Expr<'a>>,
branches: &[&'a WhenBranch<'a>],
flags: &MigrationFlags,
indent: u16,
) {
let is_multiline_condition = loc_condition.is_multiline();
@ -1230,7 +1188,7 @@ fn fmt_when<'a>(
NewlineAt::None
};
expr_above.format(buf, flags, condition_indent);
expr_above.format(buf, condition_indent);
fmt_comments_only(
buf,
spaces_below_expr.iter(),
@ -1240,20 +1198,20 @@ fn fmt_when<'a>(
buf.newline();
}
_ => {
expr_below.format(buf, flags, condition_indent);
expr_below.format(buf, condition_indent);
}
}
}
_ => {
buf.newline();
loc_condition.format(buf, flags, condition_indent);
loc_condition.format(buf, condition_indent);
buf.newline();
}
}
buf.indent(indent);
} else {
buf.spaces(1);
loc_condition.format(buf, flags, indent);
loc_condition.format(buf, indent);
buf.spaces(1);
}
buf.push_str("is");
@ -1302,7 +1260,7 @@ fn fmt_when<'a>(
}
}
fmt_pattern(buf, sub_pattern, flags, indent + INDENT, Parens::NotNeeded);
fmt_pattern(buf, sub_pattern, indent + INDENT, Parens::NotNeeded);
}
other => {
if branch_index > 0 {
@ -1314,7 +1272,7 @@ fn fmt_when<'a>(
}
}
fmt_pattern(buf, other, flags, indent + INDENT, Parens::NotNeeded);
fmt_pattern(buf, other, indent + INDENT, Parens::NotNeeded);
}
}
} else {
@ -1328,26 +1286,14 @@ fn fmt_when<'a>(
buf.spaces(1);
fmt_pattern(
buf,
&pattern.value,
flags,
indent + INDENT,
Parens::NotNeeded,
);
fmt_pattern(buf, &pattern.value, indent + INDENT, Parens::NotNeeded);
}
}
if let Some(guard_expr) = &branch.guard {
buf.push_str(" if");
buf.spaces(1);
guard_expr.format_with_options(
buf,
Parens::NotNeeded,
Newlines::Yes,
flags,
indent + INDENT,
);
guard_expr.format_with_options(buf, Parens::NotNeeded, Newlines::Yes, indent + INDENT);
}
buf.push_str(" ->");
@ -1366,7 +1312,6 @@ fn fmt_when<'a>(
buf,
Parens::NotNeeded,
Newlines::Yes,
flags,
indent + 2 * INDENT,
);
}
@ -1381,7 +1326,6 @@ fn fmt_when<'a>(
buf,
Parens::NotNeeded,
Newlines::Yes,
flags,
indent + 2 * INDENT,
);
}
@ -1397,7 +1341,7 @@ fn fmt_dbg_stmt<'a>(
extra_args: &'a [&'a Loc<Expr<'a>>],
continuation: &'a Loc<Expr<'a>>,
parens: Parens,
flags: &MigrationFlags,
indent: u16,
) {
let mut args = Vec::with_capacity_in(extra_args.len() + 1, buf.text.bump());
@ -1409,12 +1353,12 @@ fn fmt_dbg_stmt<'a>(
args.into_bump_slice(),
called_via::CalledVia::Space,
)
.format_with_options(buf, parens, Newlines::Yes, flags, indent);
.format_with_options(buf, parens, Newlines::Yes, indent);
// Always put a newline after the `dbg` line(s)
buf.ensure_ends_with_newline();
continuation.format(buf, flags, indent);
continuation.format(buf, indent);
}
fn fmt_return<'a>(
@ -1423,7 +1367,7 @@ fn fmt_return<'a>(
after_return: &Option<&'a Loc<Expr<'a>>>,
parens: Parens,
newlines: Newlines,
flags: &MigrationFlags,
indent: u16,
) {
buf.ensure_ends_with_newline();
@ -1442,7 +1386,7 @@ fn fmt_return<'a>(
indent
};
return_value.format_with_options(buf, parens, Newlines::No, flags, return_indent);
return_value.format_with_options(buf, parens, Newlines::No, return_indent);
if let Some(after_return) = after_return {
let lifted = expr_lift_spaces(Parens::NotNeeded, buf.text.bump(), &after_return.value);
@ -1453,7 +1397,7 @@ fn fmt_return<'a>(
}
lifted
.item
.format_with_options(buf, parens, newlines, flags, indent);
.format_with_options(buf, parens, newlines, indent);
fmt_spaces(buf, lifted.after.iter(), indent);
} else if parens != Parens::NotNeeded {
buf.ensure_ends_with_newline();
@ -1466,7 +1410,7 @@ fn fmt_if<'a>(
final_else: &'a Loc<Expr<'a>>,
is_multiline: bool,
indented_else: bool,
flags: &MigrationFlags,
indent: u16,
) {
// let is_multiline_then = loc_then.is_multiline();
@ -1505,7 +1449,7 @@ fn fmt_if<'a>(
match &expr_below {
Expr::SpaceAfter(expr_above, spaces_after_expr) => {
expr_above.format(buf, flags, return_indent);
expr_above.format(buf, return_indent);
// If any of the spaces is a newline, add a newline at the top.
// Otherwise leave it as just a comment.
@ -1528,28 +1472,28 @@ fn fmt_if<'a>(
}
_ => {
expr_below.format(buf, flags, return_indent);
expr_below.format(buf, return_indent);
}
}
}
Expr::SpaceAfter(expr_above, spaces_below_expr) => {
buf.newline();
expr_above.format(buf, flags, return_indent);
expr_above.format(buf, return_indent);
fmt_comments_only(buf, spaces_below_expr.iter(), NewlineAt::Top, return_indent);
buf.newline();
}
_ => {
buf.newline();
loc_condition.format(buf, flags, return_indent);
loc_condition.format(buf, return_indent);
buf.newline();
}
}
buf.indent(indent);
} else {
buf.spaces(1);
loc_condition.format_with_options(buf, Parens::NotNeeded, Newlines::Yes, flags, indent);
loc_condition.format_with_options(buf, Parens::NotNeeded, Newlines::Yes, indent);
buf.spaces(1);
}
@ -1564,7 +1508,7 @@ fn fmt_if<'a>(
match &expr_below {
Expr::SpaceAfter(expr_above, spaces_above) => {
expr_above.format(buf, flags, return_indent);
expr_above.format(buf, return_indent);
// If any of the spaces is a newline, add a newline at the top.
// Otherwise leave it as just a comment.
@ -1582,20 +1526,20 @@ fn fmt_if<'a>(
}
_ => {
expr_below.format(buf, flags, return_indent);
expr_below.format(buf, return_indent);
}
}
}
_ => {
buf.newline();
loc_then.format(buf, flags, return_indent);
loc_then.format(buf, return_indent);
buf.newline();
}
}
} else {
buf.push_str("");
buf.spaces(1);
loc_then.format(buf, flags, return_indent);
loc_then.format(buf, return_indent);
}
}
@ -1614,14 +1558,14 @@ fn fmt_if<'a>(
buf.spaces(1);
}
let indent = if indented_else { indent } else { return_indent };
final_else.format(buf, flags, indent);
final_else.format(buf, indent);
}
fn fmt_closure<'a>(
buf: &mut Buf,
loc_patterns: &'a [Loc<Pattern<'a>>],
loc_ret: &'a Loc<Expr<'a>>,
flags: &MigrationFlags,
indent: u16,
) {
use self::Expr::*;
@ -1662,7 +1606,7 @@ fn fmt_closure<'a>(
}
arg.item
.format_with_options(buf, Parens::InAsPattern, Newlines::No, flags, indent);
.format_with_options(buf, Parens::InAsPattern, Newlines::No, indent);
if !arg.after.is_empty() {
if starts_with_inline_comment(arg.after.iter()) {
@ -1717,38 +1661,20 @@ fn fmt_closure<'a>(
if should_outdent {
buf.spaces(1);
sub_expr.format_with_options(
buf,
Parens::NotNeeded,
Newlines::Yes,
flags,
indent,
);
sub_expr.format_with_options(buf, Parens::NotNeeded, Newlines::Yes, indent);
} else {
loc_ret.format_with_options(
buf,
Parens::NotNeeded,
Newlines::Yes,
flags,
body_indent,
);
loc_ret.format_with_options(buf, Parens::NotNeeded, Newlines::Yes, body_indent);
}
}
Record { .. } | List { .. } => {
loc_ret.format_with_options(buf, Parens::NotNeeded, Newlines::Yes, flags, indent);
loc_ret.format_with_options(buf, Parens::NotNeeded, Newlines::Yes, indent);
}
_ => {
loc_ret.format_with_options(
buf,
Parens::NotNeeded,
Newlines::Yes,
flags,
body_indent,
);
loc_ret.format_with_options(buf, Parens::NotNeeded, Newlines::Yes, body_indent);
}
}
} else {
loc_ret.format_with_options(buf, Parens::NotNeeded, Newlines::Yes, flags, body_indent);
loc_ret.format_with_options(buf, Parens::NotNeeded, Newlines::Yes, body_indent);
}
}
@ -1757,7 +1683,7 @@ fn fmt_backpassing<'a>(
loc_patterns: &'a [Loc<Pattern<'a>>],
loc_body: &'a Loc<Expr<'a>>,
loc_ret: &'a Loc<Expr<'a>>,
flags: &MigrationFlags,
outer_indent: u16,
) {
use self::Expr::*;
@ -1803,7 +1729,6 @@ fn fmt_backpassing<'a>(
buf,
needs_parens,
Newlines::No,
flags,
if first { outer_indent } else { arg_indent },
);
fmt_comments_only(buf, pat.after.iter(), NewlineAt::Bottom, arg_indent);
@ -1843,8 +1768,8 @@ fn fmt_backpassing<'a>(
}
};
loc_body.format_with_options(buf, Parens::NotNeeded, Newlines::Yes, flags, body_indent);
loc_ret.format_with_options(buf, Parens::NotNeeded, Newlines::Yes, flags, outer_indent);
loc_body.format_with_options(buf, Parens::NotNeeded, Newlines::Yes, body_indent);
loc_ret.format_with_options(buf, Parens::NotNeeded, Newlines::Yes, outer_indent);
}
fn pattern_needs_parens_when_backpassing(pat: &Pattern) -> bool {
@ -1866,13 +1791,12 @@ fn fmt_record_like<'a, Field, Format, ToSpaceBefore>(
buf: &mut Buf,
prefix: Option<RecordPrefix<'a>>,
fields: Collection<'a, Loc<Field>>,
flags: &MigrationFlags,
indent: u16,
format_field_multiline: Format,
to_space_before: ToSpaceBefore,
) where
Field: Formattable,
Format: Fn(&mut Buf, &Field, &MigrationFlags, u16, &str),
Format: Fn(&mut Buf, &Field, u16, &str),
ToSpaceBefore: Fn(&'a Field) -> Option<(&'a Field, &'a [CommentOrNewline<'a>])>,
{
let loc_fields = fields.items;
@ -1891,13 +1815,13 @@ fn fmt_record_like<'a, Field, Format, ToSpaceBefore>(
// doesnt make sense.
Some(RecordPrefix::Update(record_var)) => {
buf.spaces(1);
record_var.format(buf, flags, indent);
record_var.format(buf, indent);
buf.indent(indent);
buf.push_str(" &");
}
Some(RecordPrefix::Mapper(mapper_var)) => {
buf.spaces(1);
mapper_var.format(buf, flags, indent);
mapper_var.format(buf, indent);
buf.indent(indent);
buf.push_str(" <-");
}
@ -1933,7 +1857,7 @@ fn fmt_record_like<'a, Field, Format, ToSpaceBefore>(
}
}
format_field_multiline(buf, &field.value, flags, field_indent, "");
format_field_multiline(buf, &field.value, field_indent, "");
}
if count_leading_newlines(final_comments.iter()) > 1 {
@ -1949,13 +1873,7 @@ fn fmt_record_like<'a, Field, Format, ToSpaceBefore>(
let field_indent = indent;
let mut iter = loc_fields.iter().peekable();
while let Some(field) = iter.next() {
field.format_with_options(
buf,
Parens::NotNeeded,
Newlines::No,
flags,
field_indent,
);
field.format_with_options(buf, Parens::NotNeeded, Newlines::No, field_indent);
if iter.peek().is_some() {
buf.push_str(",");
@ -1977,7 +1895,7 @@ fn fmt_record_like<'a, Field, Format, ToSpaceBefore>(
fn format_assigned_field_multiline<T>(
buf: &mut Buf,
field: &AssignedField<T>,
flags: &MigrationFlags,
indent: u16,
separator_prefix: &str,
) where
@ -1998,7 +1916,7 @@ fn format_assigned_field_multiline<T>(
buf.push_str(separator_prefix);
buf.push_str(":");
buf.spaces(1);
ann.value.format(buf, flags, indent);
ann.value.format(buf, indent);
buf.push(',');
}
OptionalValue(name, spaces, ann) => {
@ -2014,7 +1932,7 @@ fn format_assigned_field_multiline<T>(
buf.push_str(separator_prefix);
buf.push_str("?");
buf.spaces(1);
ann.value.format(buf, flags, indent);
ann.value.format(buf, indent);
buf.push(',');
}
IgnoredValue(name, spaces, ann) => {
@ -2031,7 +1949,7 @@ fn format_assigned_field_multiline<T>(
buf.push_str(separator_prefix);
buf.push_str(":");
buf.spaces(1);
ann.value.format(buf, flags, indent);
ann.value.format(buf, indent);
buf.push(',');
}
LabelOnly(name) => {
@ -2048,7 +1966,7 @@ fn format_assigned_field_multiline<T>(
// ```
// we'd like to preserve this
format_assigned_field_multiline(buf, sub_field, flags, indent, separator_prefix);
format_assigned_field_multiline(buf, sub_field, indent, separator_prefix);
}
AssignedField::SpaceAfter(sub_field, spaces) => {
// We have something like that:
@ -2062,7 +1980,7 @@ fn format_assigned_field_multiline<T>(
// # comment
// otherfield
// ```
format_assigned_field_multiline(buf, sub_field, flags, indent, separator_prefix);
format_assigned_field_multiline(buf, sub_field, indent, separator_prefix);
fmt_comments_only(buf, spaces.iter(), NewlineAt::Top, indent);
}
}

View file

@ -1,6 +1,6 @@
use std::cmp::max;
use crate::annotation::{is_collection_multiline, Formattable, MigrationFlags, Newlines, Parens};
use crate::annotation::{is_collection_multiline, Formattable, Newlines, Parens};
use crate::collection::{fmt_collection, Braces};
use crate::expr::fmt_str_literal;
use crate::spaces::{fmt_comments_only, fmt_default_spaces, fmt_spaces, NewlineAt, INDENT};
@ -15,27 +15,23 @@ use roc_parse::header::{
use roc_parse::ident::UppercaseIdent;
use roc_region::all::Loc;
pub fn fmt_header<'a>(
buf: &mut Buf<'_>,
header: &'a SpacesBefore<'a, Header<'a>>,
flags: &MigrationFlags,
) {
pub fn fmt_header<'a>(buf: &mut Buf<'_>, header: &'a SpacesBefore<'a, Header<'a>>) {
fmt_comments_only(buf, header.before.iter(), NewlineAt::Bottom, 0);
match &header.item {
Header::Module(header) => {
fmt_module_header(buf, header, flags);
fmt_module_header(buf, header);
}
Header::App(header) => {
fmt_app_header(buf, header, flags);
fmt_app_header(buf, header);
}
Header::Package(header) => {
fmt_package_header(buf, header, flags);
fmt_package_header(buf, header);
}
Header::Platform(header) => {
fmt_platform_header(buf, header, flags);
fmt_platform_header(buf, header);
}
Header::Hosted(header) => {
fmt_hosted_header(buf, header, flags);
fmt_hosted_header(buf, header);
}
}
}
@ -53,7 +49,6 @@ macro_rules! keywords {
buf: &mut Buf<'_>,
_parens: crate::annotation::Parens,
_newlines: Newlines,
_flags: &crate::annotation::MigrationFlags,
indent: u16,
) {
buf.indent(indent);
@ -89,11 +84,11 @@ impl<V: Formattable> Formattable for Option<V> {
buf: &mut Buf,
parens: crate::annotation::Parens,
newlines: Newlines,
flags: &MigrationFlags,
indent: u16,
) {
if let Some(v) = self {
v.format_with_options(buf, parens, newlines, flags, indent);
v.format_with_options(buf, parens, newlines, indent);
}
}
}
@ -115,13 +110,13 @@ impl<'a> Formattable for ProvidesTo<'a> {
buf: &mut Buf,
_parens: crate::annotation::Parens,
_newlines: Newlines,
flags: &MigrationFlags,
indent: u16,
) {
self.provides_keyword.format(buf, flags, indent);
fmt_provides(buf, self.entries, self.types, flags, indent);
self.to_keyword.format(buf, flags, indent);
fmt_to(buf, self.to.value, flags, indent);
self.provides_keyword.format(buf, indent);
fmt_provides(buf, self.entries, self.types, indent);
self.to_keyword.format(buf, indent);
fmt_to(buf, self.to.value, indent);
}
}
@ -135,10 +130,10 @@ impl<'a> Formattable for PlatformRequires<'a> {
buf: &mut Buf,
_parens: crate::annotation::Parens,
_newlines: Newlines,
flags: &MigrationFlags,
indent: u16,
) {
fmt_requires(buf, self, flags, indent);
fmt_requires(buf, self, indent);
}
}
@ -152,12 +147,11 @@ impl<'a, V: Formattable> Formattable for Spaces<'a, V> {
buf: &mut Buf,
parens: crate::annotation::Parens,
newlines: Newlines,
flags: &MigrationFlags,
indent: u16,
) {
fmt_default_spaces(buf, self.before, indent);
self.item
.format_with_options(buf, parens, newlines, flags, indent);
self.item.format_with_options(buf, parens, newlines, indent);
fmt_default_spaces(buf, self.after, indent);
}
}
@ -167,22 +161,14 @@ impl<'a, K: Formattable, V: Formattable> Formattable for KeywordItem<'a, K, V> {
self.keyword.is_multiline() || self.item.is_multiline()
}
fn format_with_options(
&self,
buf: &mut Buf,
parens: Parens,
newlines: Newlines,
flags: &MigrationFlags,
indent: u16,
) {
fn format_with_options(&self, buf: &mut Buf, parens: Parens, newlines: Newlines, indent: u16) {
self.keyword
.format_with_options(buf, parens, newlines, flags, indent);
self.item
.format_with_options(buf, parens, newlines, flags, indent);
.format_with_options(buf, parens, newlines, indent);
self.item.format_with_options(buf, parens, newlines, indent);
}
}
pub fn fmt_module_header<'a>(buf: &mut Buf, header: &'a ModuleHeader<'a>, flags: &MigrationFlags) {
pub fn fmt_module_header<'a>(buf: &mut Buf, header: &'a ModuleHeader<'a>) {
buf.indent(0);
buf.push_str("module");
@ -195,7 +181,6 @@ pub fn fmt_module_header<'a>(buf: &mut Buf, header: &'a ModuleHeader<'a>, flags:
fmt_collection(
buf,
flags,
indent,
Braces::Curly,
params.pattern.value,
@ -207,10 +192,10 @@ pub fn fmt_module_header<'a>(buf: &mut Buf, header: &'a ModuleHeader<'a>, flags:
indent = fmt_spaces_with_outdent(buf, params.after_arrow, indent);
}
fmt_exposes(buf, header.exposes, flags, indent);
fmt_exposes(buf, header.exposes, indent);
}
pub fn fmt_hosted_header<'a>(buf: &mut Buf, header: &'a HostedHeader<'a>, flags: &MigrationFlags) {
pub fn fmt_hosted_header<'a>(buf: &mut Buf, header: &'a HostedHeader<'a>) {
buf.indent(0);
buf.push_str("hosted");
let indent = INDENT;
@ -218,21 +203,21 @@ pub fn fmt_hosted_header<'a>(buf: &mut Buf, header: &'a HostedHeader<'a>, flags:
buf.push_str(header.name.value.as_str());
header.exposes.keyword.format(buf, flags, indent);
fmt_exposes(buf, header.exposes.item, flags, indent);
header.imports.keyword.format(buf, flags, indent);
fmt_imports(buf, header.imports.item, flags, indent);
header.exposes.keyword.format(buf, indent);
fmt_exposes(buf, header.exposes.item, indent);
header.imports.keyword.format(buf, indent);
fmt_imports(buf, header.imports.item, indent);
}
pub fn fmt_app_header<'a>(buf: &mut Buf, header: &'a AppHeader<'a>, flags: &MigrationFlags) {
pub fn fmt_app_header<'a>(buf: &mut Buf, header: &'a AppHeader<'a>) {
buf.indent(0);
buf.push_str("app");
let indent = fmt_spaces_with_outdent(buf, header.before_provides, 0);
fmt_exposes(buf, header.provides, flags, indent);
fmt_exposes(buf, header.provides, indent);
let indent = fmt_spaces_with_outdent(buf, header.before_packages, indent);
fmt_packages(buf, header.packages.value, flags, indent);
fmt_packages(buf, header.packages.value, indent);
}
pub fn fmt_spaces_with_outdent(buf: &mut Buf, spaces: &[CommentOrNewline], indent: u16) -> u16 {
@ -246,26 +231,18 @@ pub fn fmt_spaces_with_outdent(buf: &mut Buf, spaces: &[CommentOrNewline], inden
}
}
pub fn fmt_package_header<'a>(
buf: &mut Buf,
header: &'a PackageHeader<'a>,
flags: &MigrationFlags,
) {
pub fn fmt_package_header<'a>(buf: &mut Buf, header: &'a PackageHeader<'a>) {
buf.indent(0);
buf.push_str("package");
let indent = fmt_spaces_with_outdent(buf, header.before_exposes, 0);
fmt_exposes(buf, header.exposes, flags, indent);
fmt_exposes(buf, header.exposes, indent);
let indent = fmt_spaces_with_outdent(buf, header.before_packages, indent);
fmt_packages(buf, header.packages.value, flags, indent);
fmt_packages(buf, header.packages.value, indent);
}
pub fn fmt_platform_header<'a>(
buf: &mut Buf,
header: &'a PlatformHeader<'a>,
flags: &MigrationFlags,
) {
pub fn fmt_platform_header<'a>(buf: &mut Buf, header: &'a PlatformHeader<'a>) {
buf.indent(0);
buf.push_str("platform");
let indent = INDENT;
@ -273,31 +250,23 @@ pub fn fmt_platform_header<'a>(
fmt_package_name(buf, header.name.value, indent);
header.requires.format(buf, flags, indent);
header.exposes.keyword.format(buf, flags, indent);
fmt_exposes(buf, header.exposes.item, flags, indent);
header.packages.keyword.format(buf, flags, indent);
fmt_packages(buf, header.packages.item, flags, indent);
header.imports.keyword.format(buf, flags, indent);
fmt_imports(buf, header.imports.item, flags, indent);
header.provides.keyword.format(buf, flags, indent);
fmt_provides(buf, header.provides.item, None, flags, indent);
header.requires.format(buf, indent);
header.exposes.keyword.format(buf, indent);
fmt_exposes(buf, header.exposes.item, indent);
header.packages.keyword.format(buf, indent);
fmt_packages(buf, header.packages.item, indent);
header.imports.keyword.format(buf, indent);
fmt_imports(buf, header.imports.item, indent);
header.provides.keyword.format(buf, indent);
fmt_provides(buf, header.provides.item, None, indent);
}
fn fmt_requires(buf: &mut Buf, requires: &PlatformRequires, flags: &MigrationFlags, indent: u16) {
fmt_collection(
buf,
flags,
indent,
Braces::Curly,
requires.rigids,
Newlines::No,
);
fn fmt_requires(buf: &mut Buf, requires: &PlatformRequires, indent: u16) {
fmt_collection(buf, indent, Braces::Curly, requires.rigids, Newlines::No);
buf.spaces(1);
fmt_collection(
buf,
flags,
indent,
Braces::Curly,
requires.signatures,
@ -315,7 +284,7 @@ impl<'a> Formattable for TypedIdent<'a> {
buf: &mut Buf,
_parens: Parens,
_newlines: Newlines,
flags: &MigrationFlags,
indent: u16,
) {
buf.indent(indent);
@ -324,7 +293,7 @@ impl<'a> Formattable for TypedIdent<'a> {
buf.push(':');
buf.spaces(1);
self.ann.value.format(buf, flags, indent);
self.ann.value.format(buf, indent);
}
}
@ -352,19 +321,19 @@ impl<'a, T: Formattable> Formattable for Spaced<'a, T> {
buf: &mut Buf,
parens: crate::annotation::Parens,
newlines: Newlines,
flags: &MigrationFlags,
indent: u16,
) {
match self {
Spaced::Item(item) => {
item.format_with_options(buf, parens, newlines, flags, indent);
item.format_with_options(buf, parens, newlines, indent);
}
Spaced::SpaceBefore(item, spaces) => {
fmt_spaces(buf, spaces.iter(), indent);
item.format_with_options(buf, parens, newlines, flags, indent);
item.format_with_options(buf, parens, newlines, indent);
}
Spaced::SpaceAfter(item, spaces) => {
item.format_with_options(buf, parens, newlines, flags, indent);
item.format_with_options(buf, parens, newlines, indent);
fmt_spaces(buf, spaces.iter(), indent);
}
}
@ -374,48 +343,27 @@ impl<'a, T: Formattable> Formattable for Spaced<'a, T> {
fn fmt_imports<'a>(
buf: &mut Buf,
loc_entries: Collection<'a, Loc<Spaced<'a, ImportsEntry<'a>>>>,
flags: &MigrationFlags,
indent: u16,
) {
fmt_collection(
buf,
flags,
indent,
Braces::Square,
loc_entries,
Newlines::No,
)
fmt_collection(buf, indent, Braces::Square, loc_entries, Newlines::No)
}
fn fmt_provides<'a>(
buf: &mut Buf,
loc_exposed_names: Collection<'a, Loc<Spaced<'a, ExposedName<'a>>>>,
loc_provided_types: Option<Collection<'a, Loc<Spaced<'a, UppercaseIdent<'a>>>>>,
flags: &MigrationFlags,
indent: u16,
) {
fmt_collection(
buf,
flags,
indent,
Braces::Square,
loc_exposed_names,
Newlines::No,
);
fmt_collection(buf, indent, Braces::Square, loc_exposed_names, Newlines::No);
if let Some(loc_provided) = loc_provided_types {
fmt_default_spaces(buf, &[], indent);
fmt_collection(
buf,
flags,
indent,
Braces::Curly,
loc_provided,
Newlines::No,
);
fmt_collection(buf, indent, Braces::Curly, loc_provided, Newlines::No);
}
}
fn fmt_to(buf: &mut Buf, to: To, _flags: &MigrationFlags, indent: u16) {
fn fmt_to(buf: &mut Buf, to: To, indent: u16) {
match to {
To::ExistingPackage(name) => {
buf.push_str(name);
@ -427,17 +375,10 @@ fn fmt_to(buf: &mut Buf, to: To, _flags: &MigrationFlags, indent: u16) {
fn fmt_exposes<N: Formattable + Copy + core::fmt::Debug>(
buf: &mut Buf,
loc_entries: Collection<'_, Loc<Spaced<'_, N>>>,
flags: &MigrationFlags,
indent: u16,
) {
fmt_collection(
buf,
flags,
indent,
Braces::Square,
loc_entries,
Newlines::No,
)
fmt_collection(buf, indent, Braces::Square, loc_entries, Newlines::No)
}
pub trait FormatName {
@ -466,7 +407,6 @@ impl<'a> Formattable for ModuleName<'a> {
buf: &mut Buf,
_parens: Parens,
_newlines: Newlines,
_flags: &MigrationFlags,
_indent: u16,
) {
buf.push_str(self.as_str());
@ -483,7 +423,6 @@ impl<'a> Formattable for ExposedName<'a> {
buf: &mut Buf,
_parens: Parens,
_newlines: Newlines,
_flags: &MigrationFlags,
indent: u16,
) {
buf.indent(indent);
@ -500,10 +439,9 @@ impl<'a> FormatName for ExposedName<'a> {
fn fmt_packages<'a>(
buf: &mut Buf,
loc_entries: Collection<'a, Loc<Spaced<'a, PackageEntry<'a>>>>,
flags: &MigrationFlags,
indent: u16,
) {
fmt_collection(buf, flags, indent, Braces::Curly, loc_entries, Newlines::No)
fmt_collection(buf, indent, Braces::Curly, loc_entries, Newlines::No)
}
impl<'a> Formattable for PackageEntry<'a> {
@ -516,10 +454,10 @@ impl<'a> Formattable for PackageEntry<'a> {
buf: &mut Buf,
_parens: Parens,
_newlines: Newlines,
flags: &MigrationFlags,
indent: u16,
) {
fmt_packages_entry(buf, self, flags, indent);
fmt_packages_entry(buf, self, indent);
}
}
@ -533,13 +471,13 @@ impl<'a> Formattable for ImportsEntry<'a> {
buf: &mut Buf,
_parens: Parens,
_newlines: Newlines,
flags: &MigrationFlags,
indent: u16,
) {
fmt_imports_entry(buf, self, flags, indent);
fmt_imports_entry(buf, self, indent);
}
}
fn fmt_packages_entry(buf: &mut Buf, entry: &PackageEntry, _flags: &MigrationFlags, indent: u16) {
fn fmt_packages_entry(buf: &mut Buf, entry: &PackageEntry, indent: u16) {
buf.push_str(entry.shorthand);
buf.push(':');
fmt_default_spaces(buf, entry.spaces_after_shorthand, indent);
@ -555,7 +493,7 @@ fn fmt_packages_entry(buf: &mut Buf, entry: &PackageEntry, _flags: &MigrationFla
fmt_package_name(buf, entry.package_name.value, indent);
}
fn fmt_imports_entry(buf: &mut Buf, entry: &ImportsEntry, flags: &MigrationFlags, indent: u16) {
fn fmt_imports_entry(buf: &mut Buf, entry: &ImportsEntry, indent: u16) {
use roc_parse::header::ImportsEntry::*;
buf.indent(indent);
@ -569,7 +507,6 @@ fn fmt_imports_entry(buf: &mut Buf, entry: &ImportsEntry, flags: &MigrationFlags
fmt_collection(
buf,
flags,
indent,
Braces::Curly,
*loc_exposes_entries,
@ -586,14 +523,14 @@ fn fmt_imports_entry(buf: &mut Buf, entry: &ImportsEntry, flags: &MigrationFlags
if !entries.is_empty() {
buf.push('.');
fmt_collection(buf, flags, indent, Braces::Curly, *entries, Newlines::No)
fmt_collection(buf, indent, Braces::Curly, *entries, Newlines::No)
}
}
IngestedFile(file_name, typed_ident) => {
fmt_str_literal(buf, *file_name, flags, indent);
fmt_str_literal(buf, *file_name, indent);
buf.push_str_allow_spaces(" as ");
typed_ident.format(buf, flags, 0);
typed_ident.format(buf, 0);
}
}
}

View file

@ -19,19 +19,40 @@ pub struct Buf<'a> {
newlines_to_flush: usize,
beginning_of_line: bool,
line_indent: u16,
flags: MigrationFlags,
}
#[derive(Debug, Copy, Clone)]
pub struct MigrationFlags {
pub(crate) snakify: bool,
}
impl MigrationFlags {
pub fn new(snakify: bool) -> Self {
MigrationFlags { snakify }
}
pub fn at_least_one_active(&self) -> bool {
self.snakify
}
}
impl<'a> Buf<'a> {
pub fn new_in(arena: &'a Bump) -> Buf<'a> {
pub fn new_in(arena: &'a Bump, flags: MigrationFlags) -> Buf<'a> {
Buf {
text: String::new_in(arena),
line_indent: 0,
spaces_to_flush: 0,
newlines_to_flush: 0,
beginning_of_line: true,
flags,
}
}
pub fn flags(&self) -> MigrationFlags {
self.flags
}
pub fn as_str(&'a self) -> &'a str {
self.text.as_str()
}

View file

@ -1,4 +1,4 @@
use crate::annotation::{Formattable, MigrationFlags, Newlines, Parens};
use crate::annotation::{Formattable, Newlines, Parens};
use crate::expr::{
expr_is_multiline, expr_lift_spaces_after, fmt_str_literal, format_sq_literal, is_str_multiline,
};
@ -11,14 +11,8 @@ use roc_parse::ast::{
use roc_parse::expr::merge_spaces;
use roc_region::all::Loc;
pub fn fmt_pattern<'a>(
buf: &mut Buf,
pattern: &'a Pattern<'a>,
flags: &MigrationFlags,
indent: u16,
parens: Parens,
) {
pattern.format_with_options(buf, parens, Newlines::No, flags, indent);
pub fn fmt_pattern<'a>(buf: &mut Buf, pattern: &'a Pattern<'a>, indent: u16, parens: Parens) {
pattern.format_with_options(buf, parens, Newlines::No, indent);
}
impl<'a> Formattable for PatternAs<'a> {
@ -31,7 +25,6 @@ impl<'a> Formattable for PatternAs<'a> {
buf: &mut Buf,
_parens: Parens,
_newlines: Newlines,
_flags: &MigrationFlags,
indent: u16,
) {
buf.indent(indent);
@ -100,15 +93,8 @@ impl<'a> Formattable for Pattern<'a> {
}
}
fn format_with_options(
&self,
buf: &mut Buf,
parens: Parens,
_newlines: Newlines,
flags: &MigrationFlags,
indent: u16,
) {
fmt_pattern_inner(self, buf, parens, flags, indent, self.is_multiline());
fn format_with_options(&self, buf: &mut Buf, parens: Parens, _newlines: Newlines, indent: u16) {
fmt_pattern_inner(self, buf, parens, indent, self.is_multiline());
}
}
@ -116,7 +102,7 @@ fn fmt_pattern_inner(
pat: &Pattern<'_>,
buf: &mut Buf,
parens: Parens,
flags: &MigrationFlags,
indent: u16,
outer_is_multiline: bool,
) {
@ -137,7 +123,7 @@ fn fmt_pattern_inner(
match me.item {
Identifier { ident: string } => {
buf.indent(indent);
snakify_camel_ident(buf, string, flags);
snakify_camel_ident(buf, string);
}
Tag(name) | OpaqueRef(name) => {
buf.indent(indent);
@ -169,7 +155,7 @@ fn fmt_pattern_inner(
}
}
fmt_pattern_inner(&pat.item, buf, Parens::InApply, flags, indent, is_multiline);
fmt_pattern_inner(&pat.item, buf, Parens::InApply, indent, is_multiline);
if !pat.after.is_empty() {
if !is_multiline {
@ -185,7 +171,6 @@ fn fmt_pattern_inner(
&loc_arg.value,
buf,
Parens::InApply,
flags,
indent_more,
is_multiline,
);
@ -213,14 +198,7 @@ fn fmt_pattern_inner(
}
}
fmt_pattern_inner(
&item.item,
buf,
Parens::NotNeeded,
flags,
indent,
is_multiline,
);
fmt_pattern_inner(&item.item, buf, Parens::NotNeeded, indent, is_multiline);
let is_multiline = item.item.is_multiline();
@ -250,14 +228,13 @@ fn fmt_pattern_inner(
RequiredField(name, loc_pattern) => {
buf.indent(indent);
snakify_camel_ident(buf, name, flags);
snakify_camel_ident(buf, name);
buf.push_str(":");
buf.spaces(1);
fmt_pattern_inner(
&loc_pattern.value,
buf,
Parens::NotNeeded,
flags,
indent,
is_multiline,
);
@ -265,10 +242,10 @@ fn fmt_pattern_inner(
OptionalField(name, loc_pattern) => {
buf.indent(indent);
snakify_camel_ident(buf, name, flags);
snakify_camel_ident(buf, name);
buf.push_str(" ?");
buf.spaces(1);
loc_pattern.format(buf, flags, indent);
loc_pattern.format(buf, indent);
}
NumLiteral(string) => {
@ -298,7 +275,7 @@ fn fmt_pattern_inner(
buf.indent(indent);
buf.push_str(string);
}
StrLiteral(literal) => fmt_str_literal(buf, literal, flags, indent),
StrLiteral(literal) => fmt_str_literal(buf, literal, indent),
SingleQuote(string) => {
buf.indent(indent);
format_sq_literal(buf, string);
@ -318,7 +295,6 @@ fn fmt_pattern_inner(
&loc_pattern.value,
buf,
Parens::NotNeeded,
flags,
indent,
is_multiline,
);
@ -343,7 +319,6 @@ fn fmt_pattern_inner(
&loc_pattern.value,
buf,
Parens::NotNeeded,
flags,
indent,
is_multiline,
);
@ -366,7 +341,7 @@ fn fmt_pattern_inner(
// these spaces "belong" to the `..`, which can never be multiline
fmt_comments_only(buf, list_rest_spaces.iter(), NewlineAt::Bottom, indent);
pattern_as.format(buf, flags, indent + INDENT);
pattern_as.format(buf, indent + INDENT);
}
}
@ -378,9 +353,9 @@ fn fmt_pattern_inner(
buf.push('(');
}
fmt_pattern(buf, &pattern.value, flags, indent, parens);
fmt_pattern(buf, &pattern.value, indent, parens);
pattern_as.format(buf, flags, indent + INDENT);
pattern_as.format(buf, indent + INDENT);
if needs_parens {
buf.indent(indent);
@ -402,7 +377,7 @@ fn fmt_pattern_inner(
buf.push('.');
}
snakify_camel_ident(buf, ident, flags);
snakify_camel_ident(buf, ident);
}
}
@ -528,9 +503,9 @@ pub fn pattern_lift_spaces_after<'a, 'b: 'a>(
}
/// Convert camelCase identifier to snake case
fn snakify_camel_ident(buf: &mut Buf, string: &str, flags: &MigrationFlags) {
fn snakify_camel_ident(buf: &mut Buf, string: &str) {
let chars: Vec<char> = string.chars().collect();
if !flags.snakify || (string.contains('_') && !string.ends_with('_')) {
if !buf.flags().snakify || (string.contains('_') && !string.ends_with('_')) {
buf.push_str(string);
return;
}
@ -572,13 +547,13 @@ mod snakify_test {
use bumpalo::Bump;
use super::snakify_camel_ident;
use crate::{annotation::MigrationFlags, Buf};
use crate::{Buf, MigrationFlags};
fn check_snakify(arena: &Bump, original: &str) -> String {
let mut buf = Buf::new_in(arena);
buf.indent(0);
let flags = MigrationFlags::new(true);
snakify_camel_ident(&mut buf, original, &flags);
let mut buf = Buf::new_in(arena, flags);
buf.indent(0);
snakify_camel_ident(&mut buf, original);
buf.text.to_string()
}

View file

@ -1,5 +1,5 @@
use bumpalo::Bump;
use roc_fmt::{annotation::Formattable, annotation::MigrationFlags, header::fmt_header};
use roc_fmt::{annotation::Formattable, header::fmt_header, MigrationFlags};
use roc_parse::{
ast::{Defs, Expr, FullAst, Header, Malformed, SpacesBefore},
header::parse_module_defs,
@ -82,26 +82,26 @@ pub enum Output<'a> {
impl<'a> Output<'a> {
pub fn format(&self) -> InputOwned {
let arena = Bump::new();
let mut buf = Buf::new_in(&arena);
let flags = MigrationFlags::new(false);
let mut buf = Buf::new_in(&arena, flags);
match self {
Output::Header(header) => {
fmt_header(&mut buf, header, &flags);
fmt_header(&mut buf, header);
buf.fmt_end_of_file();
InputOwned::Header(buf.as_str().to_string())
}
Output::ModuleDefs(defs) => {
defs.format(&mut buf, &flags, 0);
defs.format(&mut buf, 0);
buf.fmt_end_of_file();
InputOwned::ModuleDefs(buf.as_str().to_string())
}
Output::Expr(expr) => {
expr.format(&mut buf, &flags, 0);
expr.format(&mut buf, 0);
InputOwned::Expr(buf.as_str().to_string())
}
Output::Full(full) => {
fmt_header(&mut buf, &full.header, &flags);
full.defs.format(&mut buf, &flags, 0);
fmt_header(&mut buf, &full.header);
full.defs.format(&mut buf, 0);
buf.fmt_end_of_file();
InputOwned::Full(buf.as_str().to_string())
}

View file

@ -4,10 +4,9 @@ extern crate indoc;
#[cfg(test)]
mod test_fmt {
use bumpalo::Bump;
use roc_fmt::annotation::MigrationFlags;
use roc_fmt::def::fmt_defs;
use roc_fmt::header::fmt_header;
use roc_fmt::Buf;
use roc_fmt::{Buf, MigrationFlags};
use roc_parse::ast::{Defs, Header, SpacesBefore};
use roc_parse::header::{self, parse_module_defs};
use roc_parse::state::State;
@ -37,12 +36,11 @@ mod test_fmt {
state: State<'a>,
buf: &mut Buf<'_>,
) {
let flags = MigrationFlags::new(false);
fmt_header(buf, header, &flags);
fmt_header(buf, header);
match parse_module_defs(arena, state, Defs::default()) {
Ok(loc_defs) => {
fmt_defs(buf, &loc_defs, &flags, 0);
fmt_defs(buf, &loc_defs, 0);
}
Err(error) => {
let src = if src.len() > 1000 {
@ -67,7 +65,8 @@ mod test_fmt {
Ok((actual, state)) => {
use roc_parse::normalize::Normalize;
let mut buf = Buf::new_in(&arena);
let flags = MigrationFlags::new(false);
let mut buf = Buf::new_in(&arena, flags);
fmt_module_and_defs(&arena, src, &actual, state, &mut buf);
@ -96,7 +95,7 @@ mod test_fmt {
}
// Now verify that the resultant formatting is _stable_ - i.e. that it doesn't change again if re-formatted
let mut reformatted_buf = Buf::new_in(&arena);
let mut reformatted_buf = Buf::new_in(&arena, flags);
fmt_module_and_defs(&arena, output, &reparsed_ast, state, &mut reformatted_buf);