Merge pull request #737 from rtfeldman/format-final-comments-record-type

Format final comments in record annotation
This commit is contained in:
Sébastien Besnier 2020-11-26 11:08:48 +01:00 committed by GitHub
commit 5b675559a9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 211 additions and 38 deletions

View File

@ -37,10 +37,6 @@ pub enum Newlines {
No,
}
pub fn fmt_annotation<'a>(buf: &mut String<'a>, annotation: &'a TypeAnnotation<'a>, indent: u16) {
annotation.format(buf, indent);
}
pub trait Formattable<'a> {
fn is_multiline(&self) -> bool;
@ -85,13 +81,16 @@ where
}
macro_rules! format_sequence {
($buf: expr, $indent:expr, $start:expr, $end:expr, $items:expr, $t:ident) => {
// is it a multiline type annotation?
if $items.iter().any(|item| item.value.is_multiline()) {
($buf: expr, $indent:expr, $start:expr, $end:expr, $items:expr, $final_comments:expr, $newline:expr, $t:ident) => {
let is_multiline =
$items.iter().any(|item| item.value.is_multiline()) || !$final_comments.is_empty();
if is_multiline {
let braces_indent = $indent + INDENT;
let item_indent = braces_indent + INDENT;
newline($buf, braces_indent);
if ($newline == Newlines::Yes) {
newline($buf, braces_indent);
}
$buf.push($start);
for item in $items.iter() {
@ -139,10 +138,12 @@ macro_rules! format_sequence {
}
}
}
fmt_comments_only($buf, $final_comments.iter(), NewlineAt::Top, item_indent);
newline($buf, braces_indent);
$buf.push($end);
} else {
// is_multiline == false
// there is no comment to add
$buf.push($start);
let mut iter = $items.iter().peekable();
while let Some(item) = iter.next() {
@ -285,9 +286,9 @@ impl<'a> Formattable<'a> for TypeAnnotation<'a> {
TagUnion {
tags,
ext,
final_comments: _,
final_comments,
} => {
format_sequence!(buf, indent, '[', ']', tags, Tag);
format_sequence!(buf, indent, '[', ']', tags, final_comments, newlines, Tag);
if let Some(loc_ext_ann) = *ext {
loc_ext_ann.value.format(buf, indent);
@ -297,9 +298,18 @@ impl<'a> Formattable<'a> for TypeAnnotation<'a> {
Record {
fields,
ext,
final_comments: _,
final_comments,
} => {
format_sequence!(buf, indent, '{', '}', fields, AssignedField);
format_sequence!(
buf,
indent,
'{',
'}',
fields,
final_comments,
newlines,
AssignedField
);
if let Some(loc_ext_ann) = *ext {
loc_ext_ann.value.format(buf, indent);
@ -313,8 +323,18 @@ impl<'a> Formattable<'a> for TypeAnnotation<'a> {
rhs.value.format(buf, indent);
}
SpaceBefore(ann, _spaces) | SpaceAfter(ann, _spaces) => {
ann.format_with_options(buf, parens, newlines, indent)
SpaceBefore(ann, spaces) => {
newline(buf, indent + INDENT);
fmt_comments_only(buf, spaces.iter(), NewlineAt::Bottom, indent + INDENT);
ann.format_with_options(buf, parens, Newlines::No, indent)
}
SpaceAfter(ann, spaces) => {
ann.format_with_options(buf, parens, newlines, indent);
fmt_comments_only(buf, spaces.iter(), NewlineAt::Bottom, indent);
// seems like this SpaceAfter is not constructible
// so this branch hasn't be tested. Please add some test if
// this branch is actually reached and remove this dbg_assert.
debug_assert!(false);
}
Malformed(raw) => buf.push_str(raw),

View File

@ -36,8 +36,23 @@ impl<'a> Formattable<'a> for Def<'a> {
match self {
Annotation(loc_pattern, loc_annotation) => {
loc_pattern.format(buf, indent);
buf.push_str(" : ");
loc_annotation.format(buf, indent);
if loc_annotation.is_multiline() {
buf.push_str(" :");
loc_annotation.format_with_options(
buf,
Parens::NotNeeded,
Newlines::Yes,
indent,
);
} else {
buf.push_str(" : ");
loc_annotation.format_with_options(
buf,
Parens::NotNeeded,
Newlines::No,
indent,
);
}
}
Alias { name, vars, ann } => {
buf.push_str(name.value);

View File

@ -770,7 +770,7 @@ mod test_fmt {
),
indoc!(
r#"
f :
f :
{
y : Int,
x : Int,
@ -781,25 +781,125 @@ mod test_fmt {
);
}
// // TODO This raises a parse error:
// // NotYetImplemented("TODO the : in this declaration seems outdented")
// #[test]
// fn comments_in_record_annotation() {
// expr_formats_to(
// indoc!(
// r#"
// f :
// {}
#[test]
fn trailing_comma_in_record_annotation_same() {
expr_formats_same(indoc!(
r#"
f :
{
y : Int,
x : Int,
}
// f"#
// ),
// indoc!(
// r#"
// f : b {}
// f"#
// ),
// );
// }
f"#
));
}
#[test]
fn multiline_type_definition() {
expr_formats_same(indoc!(
r#"
f :
Int
f"#
));
}
#[test]
fn multiline_empty_record_type_definition() {
expr_formats_same(indoc!(
r#"
f :
{}
f"#
));
}
#[test]
fn type_definition_comment_after_colon() {
expr_formats_to(
indoc!(
r#"
f : # comment
{}
f"#
),
indoc!(
r#"
f :
# comment
{}
f"#
),
);
}
#[test]
fn final_comment_in_empty_record_type_definition() {
expr_formats_to(
indoc!(
r#"
f :
{ # comment
}
f"#
),
indoc!(
r#"
f :
{
# comment
}
f"#
),
);
}
#[test]
fn multiline_inside_empty_record_annotation() {
expr_formats_same(indoc!(
r#"
f :
{
}
f"#
));
}
#[test]
fn final_comment_record_annotation() {
expr_formats_to(
indoc!(
r#"
f :
{
x: Int # comment 1
,
# comment 2
}
f"#
),
indoc!(
r#"
f :
{
x : Int,
# comment 1
# comment 2
}
f"#
),
);
}
#[test]
fn def_closure() {

View File

@ -544,7 +544,7 @@ fn annotation<'a>(
ascii_char(b':'),
// Spaces after the ':' (at a normal indentation level) and then the type.
// The type itself must be indented more than the pattern and ':'
space0_before(type_annotation::located(indented_more), indented_more)
space0_before(type_annotation::located(indented_more), min_indent)
)
)
}
@ -835,7 +835,7 @@ fn parse_def_signature<'a>(
// It should be indented more than the original, and it will
// end when outdented again.
and_then_with_indent_level(
type_annotation::located(indented_more),
space0_before(type_annotation::located(indented_more), min_indent),
// The first annotation may be immediately (spaces_then_comment_or_newline())
// followed by a body at the exact same indent_level
// leading to an AnnotatedBody in this case

View File

@ -1775,6 +1775,44 @@ mod test_parse {
);
}
#[test]
fn multiline_type_signature_with_comment() {
assert_parses_to(
"f :# comment\n {}\n\n42",
Defs(
&[&Located::new(
0,
1,
0,
6,
Def::Annotation(
Located::new(0, 0, 0, 1, Pattern::Identifier("f")),
Located::new(
1,
1,
4,
6,
TypeAnnotation::SpaceBefore(
&TypeAnnotation::Record {
fields: &[],
ext: None,
final_comments: &[],
},
&[LineComment(" comment")],
),
),
),
)],
&Located::new(
3,
3,
0,
2,
Expr::SpaceBefore(&Expr::Num("42"), &[Newline, Newline]),
),
),
);
}
// #[test]
// fn type_signature_function_def() {
// use TypeAnnotation;