Merge pull request #3472 from rtfeldman/fix-comments

Allow single-line comments in multiline annotations
This commit is contained in:
Folkert de Vries 2022-07-10 16:38:40 +02:00 committed by GitHub
commit 73ce1cda5d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 83 additions and 22 deletions

View file

@ -1,8 +1,8 @@
use roc_parse::ast::{Collection, ExtractSpaces}; use roc_parse::ast::{Collection, CommentOrNewline, ExtractSpaces};
use crate::{ use crate::{
annotation::{Formattable, Newlines}, annotation::{Formattable, Newlines},
spaces::{count_leading_newlines, fmt_comments_only, NewlineAt, INDENT}, spaces::{fmt_comments_only, NewlineAt, INDENT},
Buf, Buf,
}; };
@ -41,24 +41,43 @@ pub fn fmt_collection<'a, 'buf, T: ExtractSpaces<'a> + Formattable>(
buf.push(start); buf.push(start);
for (index, item) in items.iter().enumerate() { for (index, item) in items.iter().enumerate() {
let item = item.extract_spaces();
let is_first_item = index == 0; let is_first_item = index == 0;
let item = item.extract_spaces();
buf.newline();
if !item.before.is_empty() {
let is_only_newlines = item.before.iter().all(|s| s.is_newline()); let is_only_newlines = item.before.iter().all(|s| s.is_newline());
if !is_first_item if item.before.is_empty() || is_only_newlines {
&& !is_only_newlines buf.ensure_ends_in_newline();
&& count_leading_newlines(item.before.iter()) > 1 } else {
if is_first_item {
// The first item in a multiline collection always begins with exactly
// one newline (so the delimiter is at the end of its own line),
// and that newline appears before the first comment (if there is one).
buf.ensure_ends_in_newline();
} else {
if item.before.starts_with(&[CommentOrNewline::Newline]) {
buf.ensure_ends_in_newline();
}
if item
.before
.starts_with(&[CommentOrNewline::Newline, CommentOrNewline::Newline])
{ {
// If there's a comment, and it's not on the first item,
// and it's preceded by at least one blank line, maintain 1 blank line.
// (We already ensured that it ends in a newline, so this will turn that
// into a blank line.)
buf.newline();
}
}
fmt_comments_only(buf, item.before.iter(), NewlineAt::None, item_indent);
if !is_only_newlines {
if item.before.ends_with(&[CommentOrNewline::Newline]) {
buf.newline(); buf.newline();
} }
fmt_comments_only(buf, item.before.iter(), NewlineAt::Bottom, item_indent);
if !is_only_newlines && count_leading_newlines(item.before.iter().rev()) > 0 {
buf.newline(); buf.newline();
} }
} }
@ -68,21 +87,33 @@ pub fn fmt_collection<'a, 'buf, T: ExtractSpaces<'a> + Formattable>(
buf.push(','); buf.push(',');
if !item.after.is_empty() { if !item.after.is_empty() {
fmt_comments_only(buf, item.after.iter(), NewlineAt::Top, item_indent); if item.after.iter().any(|s| s.is_newline()) {
buf.newline();
}
fmt_comments_only(buf, item.after.iter(), NewlineAt::None, item_indent);
} }
} }
if count_leading_newlines(items.final_comments().iter()) > 1 { if items.final_comments().iter().any(|s| s.is_newline()) {
buf.newline();
}
if items
.final_comments()
.starts_with(&[CommentOrNewline::Newline, CommentOrNewline::Newline])
{
buf.newline(); buf.newline();
} }
fmt_comments_only( fmt_comments_only(
buf, buf,
items.final_comments().iter(), items.final_comments().iter(),
NewlineAt::Top, NewlineAt::None,
item_indent, item_indent,
); );
buf.newline();
buf.ensure_ends_in_newline();
buf.indent(braces_indent); buf.indent(braces_indent);
} else { } else {
// is_multiline == false // is_multiline == false

View file

@ -2347,8 +2347,7 @@ mod test_fmt {
indoc!( indoc!(
r#" r#"
f : { f : {
x : Int *, x : Int *, # comment 1
# comment 1
# comment 2 # comment 2
} }
@ -4588,7 +4587,7 @@ mod test_fmt {
} }
#[test] #[test]
fn multiline_tag_union_annotation() { fn multiline_tag_union_annotation_no_comments() {
expr_formats_same(indoc!( expr_formats_same(indoc!(
r#" r#"
b : [ b : [
@ -4694,8 +4693,7 @@ mod test_fmt {
b : [ b : [
True, True,
# comment 1 # comment 1
False, False, # comment 2
# comment 2
# comment 3 # comment 3
] ]
@ -5082,6 +5080,38 @@ mod test_fmt {
); );
} }
#[test]
fn comments_in_multiline_tag_union_annotation() {
expr_formats_to(
indoc!(
r#"
UnionAnn : [
Foo, # comment 1
Bar, # comment 2
Baz, # comment 3
# comment 4 line 1
# comment 4 line 2
]
0
"#
),
indoc!(
r#"
UnionAnn : [
Foo, # comment 1
Bar, # comment 2
Baz, # comment 3
# comment 4 line 1
# comment 4 line 2
]
0
"#
),
);
}
#[test] #[test]
/// Test that everything under examples/ is formatted correctly /// Test that everything under examples/ is formatted correctly
/// If this test fails on your diff, it probably means you need to re-format the examples. /// If this test fails on your diff, it probably means you need to re-format the examples.