diff --git a/crates/compiler/fmt/src/annotation.rs b/crates/compiler/fmt/src/annotation.rs index 6f0cb7e7e80..e003d15dad9 100644 --- a/crates/compiler/fmt/src/annotation.rs +++ b/crates/compiler/fmt/src/annotation.rs @@ -343,7 +343,7 @@ fn fmt_ty_ann( } TypeAnnotation::TagUnion { tags, ext } => { - fmt_collection(buf, indent, Braces::Square, *tags, newlines); + fmt_tag_collection(buf, indent, *tags, newlines); fmt_ext(ext, buf, indent); } @@ -403,6 +403,78 @@ fn fmt_ty_ann( } } +fn fmt_tag_collection<'a>( + buf: &mut Buf<'_>, + indent: u16, + tags: Collection<'a, Loc>>, + newlines: Newlines, +) { + let arena = buf.text.bump(); + let mut new_items: Vec<'_, NodeSpaces<'_, Node<'_>>> = Vec::with_capacity_in(tags.len(), arena); + + let mut last_after: &[CommentOrNewline<'_>] = &[]; + + for item in tags.items.iter() { + let lifted = tag_lift_to_node(arena, item.value); + let before = merge_spaces_conservative(arena, last_after, lifted.before); + last_after = lifted.after; + new_items.push(NodeSpaces { + before, + item: lifted.item, + after: &[], + }); + } + + let final_comments = merge_spaces_conservative(arena, last_after, tags.final_comments()); + + let new_items = + Collection::with_items_and_comments(arena, new_items.into_bump_slice(), final_comments); + + fmt_collection(buf, indent, Braces::Square, new_items, newlines); +} + +fn tag_lift_to_node<'a, 'b: 'a>(arena: &'a Bump, value: Tag<'b>) -> Spaces<'a, Node<'a>> { + match value { + Tag::Apply { name, args } => { + if args.is_empty() { + Spaces { + before: &[], + item: Node::Literal(name.value), + after: &[], + } + } else { + let first = Node::Literal(name.value); + let mut new_args: Vec<'a, (Sp<'a>, Node<'a>)> = + Vec::with_capacity_in(args.len(), arena); + let mut last_after: &[CommentOrNewline<'_>] = &[]; + + for arg in args.iter() { + let lifted = ann_lift_to_node(Parens::InApply, arena, &arg.value); + let before = merge_spaces_conservative(arena, last_after, lifted.before); + last_after = lifted.after; + new_args.push((before, lifted.item)); + } + + Spaces { + before: &[], + item: Node::Sequence(arena.alloc(first), new_args.into_bump_slice()), + after: last_after, + } + } + } + Tag::SpaceBefore(inner, sp) => { + let mut inner = tag_lift_to_node(arena, *inner); + inner.before = merge_spaces_conservative(arena, sp, inner.before); + inner + } + Tag::SpaceAfter(inner, sp) => { + let mut inner = tag_lift_to_node(arena, *inner); + inner.after = merge_spaces_conservative(arena, inner.after, sp); + inner + } + } +} + fn lower<'a, 'b: 'a>( arena: &'b Bump, lifted: Spaces<'b, TypeAnnotation<'b>>, @@ -427,7 +499,6 @@ fn lower<'a, 'b: 'a>( fn fmt_ty_collection( buf: &mut Buf<'_>, - indent: u16, braces: Braces, items: Collection<'_, Loc>>, @@ -567,7 +638,6 @@ fn is_multiline_assigned_field_help(afield: &AssignedField<'_, T fn format_assigned_field_help( zelf: &AssignedField, buf: &mut Buf, - indent: u16, separator_spaces: usize, is_multiline: bool, @@ -1072,6 +1142,8 @@ type Sp<'a> = &'a [CommentOrNewline<'a>]; #[derive(Copy, Clone, Debug)] enum Node<'a> { + Literal(&'a str), + Sequence(&'a Node<'a>, &'a [(Sp<'a>, Node<'a>)]), DelimitedSequence(Braces, &'a [(Sp<'a>, Node<'a>)], Sp<'a>), TypeAnnotation(TypeAnnotation<'a>), } @@ -1080,17 +1152,19 @@ impl<'a> Formattable for Node<'a> { fn is_multiline(&self) -> bool { match self { Node::DelimitedSequence(_braces, lefts, right) => { - if !right.is_empty() { - return true; - } - for (sp, l) in *lefts { - if l.is_multiline() || !sp.is_empty() { - return true; - } - } - false + right.is_empty() + && lefts + .iter() + .any(|(sp, l)| l.is_multiline() || !sp.is_empty()) + } + Node::Sequence(first, rest) => { + first.is_multiline() + || rest + .iter() + .any(|(sp, l)| l.is_multiline() || !sp.is_empty()) } Node::TypeAnnotation(type_annotation) => type_annotation.is_multiline(), + Node::Literal(_) => false, } } @@ -1115,9 +1189,26 @@ impl<'a> Formattable for Node<'a> { buf.indent(indent); buf.push(braces.end()); } + Node::Sequence(first, rest) => { + first.format_with_options(buf, parens, newlines, indent); + + for (sp, l) in *rest { + if !sp.is_empty() { + fmt_spaces(buf, sp.iter(), indent); + } else { + buf.spaces(1); + } + + l.format_with_options(buf, parens, newlines, indent); + } + } Node::TypeAnnotation(type_annotation) => { type_annotation.format_with_options(buf, parens, newlines, indent); } + Node::Literal(text) => { + buf.indent(indent); + buf.push_str(text); + } } } } @@ -1160,14 +1251,27 @@ fn ann_lift_to_node<'a, 'b: 'a>( &[] }; - Spaces { - before: &[], - item: Node::TypeAnnotation(TypeAnnotation::Apply( - module, - func, - new_args.into_bump_slice(), - )), - after, + let item = Node::TypeAnnotation(TypeAnnotation::Apply( + module, + func, + new_args.into_bump_slice(), + )); + + if parens == Parens::InApply { + parens_around_node( + arena, + Spaces { + before: &[], + item, + after, + }, + ) + } else { + Spaces { + before: &[], + item, + after, + } } } TypeAnnotation::SpaceBefore(expr, spaces) => { @@ -1200,27 +1304,35 @@ fn ann_lift_to_node<'a, 'b: 'a>( item: Node::TypeAnnotation(new_ann), after: new_res.after, }; - if parens == Parens::InCollection { - let node = Node::DelimitedSequence( - Braces::Round, - arena.alloc_slice_copy(&[(inner.before, inner.item)]), - inner.after, - ); - - Spaces { - before: &[], - item: node, - after: &[], - } + if parens == Parens::InCollection || parens == Parens::InApply { + parens_around_node(arena, inner) } else { inner } } - _ => Spaces { - before: &[], - item: Node::TypeAnnotation(*ann), - after: &[], - }, + _ => { + let lifted = ann_lift_spaces(arena, ann); + Spaces { + before: lifted.before, + item: Node::TypeAnnotation(lifted.item), + after: lifted.after, + } + } + } +} + +fn parens_around_node<'a, 'b: 'a>( + arena: &'a Bump, + item: Spaces<'b, Node<'b>>, +) -> Spaces<'a, Node<'a>> { + Spaces { + before: &[], + item: Node::DelimitedSequence( + Braces::Round, + arena.alloc_slice_copy(&[(item.before, item.item)]), + item.after, + ), + after: &[], } } diff --git a/crates/compiler/fmt/src/def.rs b/crates/compiler/fmt/src/def.rs index 3f62ac41790..8e15498f4f8 100644 --- a/crates/compiler/fmt/src/def.rs +++ b/crates/compiler/fmt/src/def.rs @@ -37,7 +37,6 @@ impl<'a> Formattable for Defs<'a> { buf: &mut Buf, _parens: Parens, _newlines: Newlines, - indent: u16, ) { let mut prev_spaces = true; @@ -558,6 +557,7 @@ impl<'a> Formattable for TypeHeader<'a> { let need_parens = matches!(var.item, Pattern::Apply(..)); if need_parens { + buf.indent(vars_indent); buf.push_str("("); } @@ -803,6 +803,7 @@ impl<'a> Formattable for IngestedFileAnnotation<'a> { } = self; fmt_default_spaces(buf, before_colon, indent); + buf.indent(indent); buf.push_str(":"); buf.spaces(1); annotation.format(buf, indent); @@ -1032,6 +1033,7 @@ pub fn fmt_body<'a>( && pattern_extracted.before.iter().all(|s| s.is_newline()) && pattern_extracted.after.iter().all(|s| s.is_newline()) && !matches!(body.extract_spaces().item, Expr::Defs(..)) + && !matches!(body.extract_spaces().item, Expr::Return(..)) } else { false }; diff --git a/crates/compiler/fmt/src/expr.rs b/crates/compiler/fmt/src/expr.rs index ee3d924a88c..3e4bfb23c54 100644 --- a/crates/compiler/fmt/src/expr.rs +++ b/crates/compiler/fmt/src/expr.rs @@ -133,13 +133,19 @@ fn format_expr_only( buf.push_str(string); } Expr::Record(fields) => { - fmt_record_like(buf, None, *fields, indent, assigned_field_to_spaces); + fmt_record_like( + buf, + None, + prepare_expr_field_collection(buf.text.bump(), *fields), + indent, + assigned_field_to_spaces, + ); } Expr::RecordUpdate { update, fields } => { fmt_record_like( buf, Some(RecordPrefix::Update(update)), - *fields, + prepare_expr_field_collection(buf.text.bump(), *fields), indent, assigned_field_to_spaces, ); @@ -148,7 +154,7 @@ fn format_expr_only( fmt_record_like( buf, Some(RecordPrefix::Mapper(mapper)), - *fields, + prepare_expr_field_collection(buf.text.bump(), *fields), indent, assigned_field_to_spaces, ); @@ -338,6 +344,110 @@ fn format_expr_only( } } +fn prepare_expr_field_collection<'a>( + arena: &'a Bump, + items: Collection<'a, Loc>>>, +) -> Collection<'a, Loc>>> { + let mut new_items: Vec<'_, Loc>>> = + Vec::with_capacity_in(items.len(), arena); + + let mut last_after: &[CommentOrNewline<'_>] = &[]; + + for (i, item) in items.items.iter().enumerate() { + let mut lifted = assigned_field_lift_spaces(arena, item.value); + if i == items.items.len() - 1 { + last_after = lifted.after; + lifted.after = &[]; + } + new_items.push(Loc::at(item.region, lower_assigned_field(arena, lifted))); + } + + let final_comments = merge_spaces_conservative(arena, last_after, items.final_comments()); + + Collection::with_items_and_comments(arena, new_items.into_bump_slice(), final_comments) +} + +fn lower_assigned_field<'a>( + arena: &'a Bump, + lifted: Spaces<'a, AssignedField<'a, Expr<'a>>>, +) -> AssignedField<'a, Expr<'a>> { + if lifted.before.is_empty() && lifted.after.is_empty() { + return lifted.item; + } + if lifted.before.is_empty() { + return AssignedField::SpaceAfter(arena.alloc(lifted.item), lifted.after); + } + if lifted.after.is_empty() { + return AssignedField::SpaceBefore(arena.alloc(lifted.item), lifted.before); + } + AssignedField::SpaceBefore( + arena.alloc(AssignedField::SpaceAfter( + arena.alloc(lifted.item), + lifted.after, + )), + lifted.before, + ) +} + +fn assigned_field_lift_spaces<'a, 'b: 'a>( + arena: &'a Bump, + value: AssignedField<'b, Expr<'b>>, +) -> Spaces<'a, AssignedField<'a, Expr<'a>>> { + match value { + AssignedField::RequiredValue(name, sp, value) => { + let new_value = expr_lift_spaces_after(Parens::NotNeeded, arena, &value.value); + Spaces { + before: &[], + item: AssignedField::RequiredValue( + name, + sp, + arena.alloc(Loc::at(value.region, new_value.item)), + ), + after: new_value.after, + } + } + AssignedField::OptionalValue(name, sp, value) => { + let new_value = expr_lift_spaces_after(Parens::NotNeeded, arena, &value.value); + Spaces { + before: &[], + item: AssignedField::OptionalValue( + name, + sp, + arena.alloc(Loc::at(value.region, new_value.item)), + ), + after: new_value.after, + } + } + AssignedField::IgnoredValue(name, sp, value) => { + let new_value = expr_lift_spaces_after(Parens::NotNeeded, arena, &value.value); + Spaces { + before: &[], + item: AssignedField::IgnoredValue( + name, + sp, + arena.alloc(Loc::at(value.region, new_value.item)), + ), + after: new_value.after, + } + } + AssignedField::LabelOnly(name) => Spaces { + before: &[], + item: AssignedField::LabelOnly(name), + after: &[], + }, + AssignedField::SpaceBefore(inner, sp) => { + let mut inner = assigned_field_lift_spaces(arena, *inner); + inner.before = merge_spaces_conservative(arena, sp, inner.before); + inner + } + AssignedField::SpaceAfter(inner, sp) => { + let mut inner = assigned_field_lift_spaces(arena, *inner); + inner.after = merge_spaces_conservative(arena, inner.after, sp); + inner + } + } +} + pub fn expr_is_multiline(me: &Expr<'_>, comments_only: bool) -> bool { match me { // Return whether these spaces contain any Newlines @@ -389,16 +499,7 @@ pub fn expr_is_multiline(me: &Expr<'_>, comments_only: bool) -> bool { .any(|loc_arg| expr_is_multiline(&loc_arg.value, comments_only)) } - Expr::DbgStmt { - first: condition, - extra_args, - .. - } => { - expr_is_multiline(&condition.value, comments_only) - || extra_args - .iter() - .any(|loc_arg| expr_is_multiline(&loc_arg.value, comments_only)) - } + Expr::DbgStmt { .. } => true, Expr::LowLevelDbg(_, _, _) => { unreachable!("LowLevelDbg should only exist after desugaring, not during formatting") } @@ -513,7 +614,9 @@ fn requires_space_after_unary(item: &Expr<'_>) -> bool { is_negative, } => *is_negative, Expr::RecordUpdater(..) => true, - Expr::RecordAccess(inner, _field) => requires_space_after_unary(inner), + Expr::RecordAccess(inner, _field) | Expr::TupleAccess(inner, _field) => { + requires_space_after_unary(inner) + } Expr::Apply(inner, _, _) => requires_space_after_unary(&inner.value), Expr::TrySuffix { target: _, expr } => requires_space_after_unary(expr), Expr::SpaceAfter(inner, _) | Expr::SpaceBefore(inner, _) => { @@ -646,9 +749,10 @@ fn is_outdentable_collection(expr: &Expr<'_>) -> bool { 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 - } + Expr::Closure(..) + | Expr::SpaceBefore(..) + | Expr::SpaceAfter(Expr::Closure(..), ..) + | Expr::DbgStmt { .. } => false, _ => sub_expr.is_multiline(), }; @@ -670,7 +774,7 @@ fn fmt_parens(sub_expr: &Expr<'_>, buf: &mut Buf<'_>, indent: u16) { sub_expr.format_with_options(buf, Parens::NotNeeded, Newlines::Yes, next_indent); if !matches!(sub_expr, Expr::SpaceAfter(..)) && should_add_newlines { - buf.newline(); + buf.ensure_ends_with_newline(); } buf.indent(indent); buf.push(')'); @@ -740,6 +844,7 @@ fn starts_with_newline(expr: &Expr) -> bool { SpaceBefore(_, comment_or_newline) => { matches!(comment_or_newline.first(), Some(CommentOrNewline::Newline)) } + DbgStmt { .. } => true, _ => false, } } @@ -1010,7 +1115,7 @@ pub fn expr_lift_spaces<'a, 'b: 'a>( after: body_lifted.after, } } - Expr::If { .. } | Expr::When(_, _) | Expr::Return(_, _) => { + Expr::If { .. } | Expr::When(_, _) => { if parens == Parens::InApply || parens == Parens::InApplyLastArg { Spaces { before: &[], @@ -1025,6 +1130,34 @@ pub fn expr_lift_spaces<'a, 'b: 'a>( } } } + Expr::Return(val, opt_after) => { + if parens == Parens::InApply || parens == Parens::InApplyLastArg { + Spaces { + before: &[], + item: Expr::ParensAround(arena.alloc(*expr)), + after: &[], + } + } else if let Some(after) = opt_after { + let after_lifted = expr_lift_spaces_after(Parens::NotNeeded, arena, &after.value); + + Spaces { + before: &[], + item: Expr::Return( + val, + Some(arena.alloc(Loc::at(after.region, after_lifted.item))), + ), + after: after_lifted.after, + } + } else { + let val_lifted = expr_lift_spaces_after(Parens::NotNeeded, arena, &val.value); + + Spaces { + before: &[], + item: Expr::Return(arena.alloc(Loc::at(val.region, val_lifted.item)), None), + after: val_lifted.after, + } + } + } Expr::Backpassing(pats, call, continuation) => { let pats = arena.alloc_slice_copy(pats); let before = if let Some(first) = pats.first_mut() { @@ -1381,7 +1514,6 @@ fn fmt_when<'a>( buf: &mut Buf, loc_condition: &'a Loc>, branches: &[&'a WhenBranch<'a>], - indent: u16, ) { buf.ensure_ends_with_newline(); @@ -1471,11 +1603,14 @@ fn fmt_when<'a>( } buf.indent(indent + INDENT); + let line_indent = buf.cur_line_indent(); buf.push_str(" ->"); + let inner_indent = line_indent + INDENT; + match expr.value { Expr::SpaceBefore(nested, spaces) => { - fmt_spaces_no_blank_lines(buf, spaces.iter(), indent + (INDENT * 2)); + fmt_spaces_no_blank_lines(buf, spaces.iter(), inner_indent); if is_multiline_expr { buf.ensure_ends_with_newline(); @@ -1483,12 +1618,7 @@ fn fmt_when<'a>( buf.spaces(1); } - nested.format_with_options( - buf, - Parens::NotNeeded, - Newlines::Yes, - indent + 2 * INDENT, - ); + nested.format_with_options(buf, Parens::NotNeeded, Newlines::Yes, inner_indent); } _ => { if is_multiline_expr { @@ -1497,12 +1627,7 @@ fn fmt_when<'a>( buf.spaces(1); } - expr.format_with_options( - buf, - Parens::NotNeeded, - Newlines::Yes, - indent + 2 * INDENT, - ); + expr.format_with_options(buf, Parens::NotNeeded, Newlines::Yes, inner_indent); } } @@ -1516,9 +1641,9 @@ fn fmt_dbg_stmt<'a>( extra_args: &'a [&'a Loc>], continuation: &'a Loc>, parens: Parens, - indent: u16, ) { + buf.ensure_ends_with_newline(); let mut args = Vec::with_capacity_in(extra_args.len() + 1, buf.text.bump()); args.push(condition); args.extend_from_slice(extra_args); @@ -1558,14 +1683,16 @@ fn fmt_return<'a>( after_return: &Option<&'a Loc>>, parens: Parens, newlines: Newlines, - indent: u16, ) { buf.ensure_ends_with_newline(); buf.indent(indent); buf.push_str(keyword::RETURN); - if matches!(return_value.value.extract_spaces().item, Expr::Defs(..)) { + if matches!( + return_value.value.extract_spaces().item, + Expr::Defs(..) | Expr::Backpassing(..) + ) { buf.ensure_ends_with_newline(); } else { buf.spaces(1); @@ -1895,7 +2022,7 @@ fn fmt_record_like<'a, 'b: 'a, Field, ToSpacesAround>( indent: u16, to_space_around: ToSpacesAround, ) where - Field: Formattable, + Field: Formattable + std::fmt::Debug, ToSpacesAround: Fn(&'a Bump, &'b Field) -> Spaces<'a, Field>, { let loc_fields = fields.items; @@ -1967,6 +2094,7 @@ fn fmt_record_like<'a, 'b: 'a, Field, ToSpacesAround>( Newlines::No, field_indent, ); + buf.indent(field_indent); buf.push_str(","); last_after = field_lifted.after; } diff --git a/crates/compiler/fmt/src/lib.rs b/crates/compiler/fmt/src/lib.rs index 1f15b0742a2..287067a4aea 100644 --- a/crates/compiler/fmt/src/lib.rs +++ b/crates/compiler/fmt/src/lib.rs @@ -69,6 +69,7 @@ impl<'a> Buf<'a> { self.beginning_of_line = false; } + #[track_caller] pub fn cur_line_indent(&self) -> u16 { debug_assert!(!self.beginning_of_line, "cur_line_indent before indent"); self.line_indent diff --git a/crates/compiler/fmt/src/pattern.rs b/crates/compiler/fmt/src/pattern.rs index debc760ad79..1aece61353b 100644 --- a/crates/compiler/fmt/src/pattern.rs +++ b/crates/compiler/fmt/src/pattern.rs @@ -102,7 +102,6 @@ fn fmt_pattern_inner( pat: &Pattern<'_>, buf: &mut Buf, parens: Parens, - indent: u16, outer_is_multiline: bool, force_newline_at_start: bool, @@ -127,7 +126,7 @@ fn fmt_pattern_inner( let is_multiline = me.item.is_multiline(); - fmt_pattern_only(me, buf, indent, parens, is_multiline); + fmt_pattern_only(&me.item, buf, parens, indent, is_multiline); if !me.after.is_empty() { if starts_with_inline_comment(me.after.iter()) { @@ -147,13 +146,13 @@ fn fmt_pattern_inner( } fn fmt_pattern_only( - me: Spaces<'_, Pattern<'_>>, + me: &Pattern<'_>, buf: &mut Buf<'_>, - indent: u16, parens: Parens, + indent: u16, is_multiline: bool, ) { - match me.item { + match me { Pattern::Identifier { ident: string } => { buf.indent(indent); snakify_camel_ident(buf, string); @@ -188,31 +187,51 @@ fn fmt_pattern_only( } } - fmt_pattern_inner(&pat.item, buf, Parens::InApply, indent, is_multiline, false); + fmt_pattern_only(&pat.item, buf, Parens::InApply, indent, is_multiline); - if !pat.after.is_empty() { - if !is_multiline { - fmt_comments_only(buf, pat.after.iter(), NewlineAt::Bottom, indent_more) - } else { - fmt_spaces(buf, pat.after.iter(), indent_more); - } - } + let mut last_after = pat.after; - let mut add_newlines = false; + let mut add_newlines = is_multiline; for loc_arg in loc_arg_patterns.iter() { buf.spaces(1); - let was_multiline = fmt_pattern_inner( - &loc_arg.value, - buf, - Parens::InApply, - indent_more, - is_multiline, - add_newlines, - ); + + let parens = Parens::InApply; + let arg = pattern_lift_spaces(buf.text.bump(), &loc_arg.value); + + let mut was_multiline = arg.item.is_multiline(); + + let before = merge_spaces(buf.text.bump(), last_after, arg.before); + + if !before.is_empty() { + if !is_multiline { + was_multiline |= before.iter().any(|s| s.is_comment()); + fmt_comments_only(buf, before.iter(), NewlineAt::Bottom, indent_more) + } else { + was_multiline |= true; + fmt_spaces(buf, before.iter(), indent_more); + } + } + + if add_newlines { + buf.ensure_ends_with_newline(); + } + + fmt_pattern_only(&arg.item, buf, parens, indent_more, arg.item.is_multiline()); + + last_after = arg.after; + add_newlines |= was_multiline; } + if !last_after.is_empty() { + if !is_multiline { + fmt_comments_only(buf, last_after.iter(), NewlineAt::Bottom, indent_more) + } else { + fmt_spaces(buf, last_after.iter(), indent_more); + } + } + if parens { buf.push(')'); } @@ -305,7 +324,7 @@ fn fmt_pattern_only( is_negative, } => { buf.indent(indent); - if is_negative { + if *is_negative { buf.push('-'); } @@ -322,7 +341,7 @@ fn fmt_pattern_only( buf.indent(indent); buf.push_str(string); } - Pattern::StrLiteral(literal) => fmt_str_literal(buf, literal, indent), + Pattern::StrLiteral(literal) => fmt_str_literal(buf, *literal, indent), Pattern::SingleQuote(string) => { buf.indent(indent); format_sq_literal(buf, string); @@ -336,15 +355,17 @@ fn fmt_pattern_only( buf.indent(indent); buf.push_str("("); + let mut add_newlines = false; + let mut it = loc_patterns.iter().peekable(); while let Some(loc_pattern) = it.next() { - fmt_pattern_inner( + add_newlines |= fmt_pattern_inner( &loc_pattern.value, buf, Parens::NotNeeded, indent, is_multiline, - false, + add_newlines, ); if it.peek().is_some() { @@ -361,15 +382,17 @@ fn fmt_pattern_only( buf.indent(indent); buf.push_str("["); + let mut add_newlines = false; + let mut it = loc_patterns.iter().peekable(); while let Some(loc_pattern) = it.next() { - fmt_pattern_inner( + add_newlines |= fmt_pattern_inner( &loc_pattern.value, buf, Parens::NotNeeded, indent, is_multiline, - false, + add_newlines, ); if it.peek().is_some() { @@ -449,6 +472,7 @@ pub fn pattern_lift_spaces<'a, 'b: 'a>( match pat { Pattern::Apply(func, args) => { let func_lifted = pattern_lift_spaces(arena, &func.value); + let args = arena.alloc_slice_copy(args); let (before, func, after) = if let Some(last) = args.last_mut() { let last_lifted = pattern_lift_spaces(arena, &last.value); @@ -504,6 +528,19 @@ pub fn pattern_lift_spaces<'a, 'b: 'a>( Pattern::SpaceBefore(expr, spaces) => { let mut inner = pattern_lift_spaces(arena, expr); inner.before = merge_spaces(arena, spaces, inner.before); + + if starts_with_block_str(&inner.item) + && matches!(inner.before.last(), Some(CommentOrNewline::Newline)) + { + // Ick! + // The block string will keep "generating" newlines when formatted (it wants to start on its own line), + // so we strip one out here. + // + // Note that this doesn't affect Expr's because those have explicit parens, and we can control + // whether spaces cross that boundary. + inner.before = &inner.before[..inner.before.len() - 1]; + } + inner } Pattern::SpaceAfter(expr, spaces) => { @@ -519,6 +556,17 @@ pub fn pattern_lift_spaces<'a, 'b: 'a>( } } +fn starts_with_block_str(item: &Pattern<'_>) -> bool { + match item { + Pattern::As(inner, _) | Pattern::Apply(inner, _) => starts_with_block_str(&inner.value), + Pattern::SpaceBefore(inner, _) | Pattern::SpaceAfter(inner, _) => { + starts_with_block_str(inner) + } + Pattern::StrLiteral(str_literal) => is_str_multiline(str_literal), + _ => false, + } +} + pub fn pattern_lift_spaces_before<'a, 'b: 'a>( arena: &'a Bump, pat: &Pattern<'b>, diff --git a/crates/compiler/parse/src/expr.rs b/crates/compiler/parse/src/expr.rs index 6b772fad329..c523597ae15 100644 --- a/crates/compiler/parse/src/expr.rs +++ b/crates/compiler/parse/src/expr.rs @@ -2420,8 +2420,8 @@ mod when { let original_indent = pattern_indent_level; // Parse the first "->" and the expression after it. - let (_, loc_first_expr, mut state) = - branch_result(original_indent + 1).parse(arena, state, original_indent + 1)?; + let (_, loc_first_expr, mut state) = branch_result(options, original_indent + 1) + .parse(arena, state, original_indent + 1)?; // Record this as the first branch, then optionally parse additional branches. branches.push(arena.alloc(WhenBranch { @@ -2443,7 +2443,7 @@ mod when { } }, ), - branch_result(original_indent + 1), + branch_result(options, original_indent + 1), ), |((patterns, guard), expr)| { let patterns: Vec<'a, _> = patterns; @@ -2547,61 +2547,60 @@ mod when { ) -> impl Parser<'a, (u32, Vec<'a, Loc>>), EWhen<'a>> { move |arena, state: State<'a>, min_indent: u32| { // put no restrictions on the indent after the spaces; we'll check it manually - match space0_e(EWhen::IndentPattern).parse(arena, state, 0) { - Err((MadeProgress, fail)) => Err((NoProgress, fail)), - Err((NoProgress, fail)) => Err((NoProgress, fail)), - Ok((_progress, spaces, state)) => { - match pattern_indent_level { - Some(wanted) if state.column() > wanted => { - error_on_arrow(EWhen::IndentPattern).parse(arena, state, min_indent) - } - Some(wanted) if state.column() < wanted => { - let indent = wanted - state.column(); - Err((NoProgress, EWhen::PatternAlignment(indent, state.pos()))) - } - _ => { - let pattern_indent = - min_indent.max(pattern_indent_level.unwrap_or(min_indent)); - // the region is not reliable for the indent column in the case of - // parentheses around patterns - let pattern_indent_column = state.column(); + let (spaces, state) = match space0_e(EWhen::IndentPattern).parse(arena, state, 0) { + Err((MadeProgress, fail)) => return Err((NoProgress, fail)), + Err((NoProgress, fail)) => return Err((NoProgress, fail)), + Ok((_progress, spaces, state)) => (spaces, state), + }; - let parser = - sep_by1(byte(b'|', EWhen::Bar), branch_single_alternative()); + match pattern_indent_level { + Some(wanted) if state.column() > wanted => { + return error_on_arrow(EWhen::IndentPattern).parse(arena, state, min_indent); + } + Some(wanted) if state.column() < wanted => { + let indent = wanted - state.column(); + return Err((NoProgress, EWhen::PatternAlignment(indent, state.pos()))); + } + _ => {} + } - match parser.parse(arena, state.clone(), pattern_indent) { - Err((MadeProgress, fail)) => Err((MadeProgress, fail)), - Err((NoProgress, fail)) => { - // roll back space parsing if the pattern made no progress - Err((NoProgress, fail)) - } + let pattern_indent = min_indent.max(pattern_indent_level.unwrap_or(min_indent)); + // the region is not reliable for the indent column in the case of + // parentheses around patterns + let pattern_indent_column = state.column(); - Ok((_, mut loc_patterns, state)) => { - // tag spaces onto the first parsed pattern - if !spaces.is_empty() { - if let Some(first) = loc_patterns.get_mut(0) { - *first = arena - .alloc(first.value) - .with_spaces_before(spaces, first.region); - } - } + let parser = sep_by1(byte(b'|', EWhen::Bar), branch_single_alternative()); - Ok((MadeProgress, (pattern_indent_column, loc_patterns), state)) - } - } + match parser.parse(arena, state.clone(), pattern_indent) { + Err((MadeProgress, fail)) => Err((MadeProgress, fail)), + Err((NoProgress, fail)) => { + // roll back space parsing if the pattern made no progress + Err((NoProgress, fail)) + } + + Ok((_, mut loc_patterns, state)) => { + // tag spaces onto the first parsed pattern + if !spaces.is_empty() { + if let Some(first) = loc_patterns.get_mut(0) { + *first = arena + .alloc(first.value) + .with_spaces_before(spaces, first.region); } } + + Ok((MadeProgress, (pattern_indent_column, loc_patterns), state)) } } } } /// Parsing the righthandside of a branch in a when conditional. - fn branch_result<'a>(indent: u32) -> impl Parser<'a, Loc>, EWhen<'a>> { - let options = ExprParseOptions { - accept_multi_backpassing: true, - check_for_arrow: true, - }; + fn branch_result<'a>( + mut options: ExprParseOptions, + indent: u32, + ) -> impl Parser<'a, Loc>, EWhen<'a>> { + // it's important we preserve the value of `accept_multi_backpassing` in case it's false + options.check_for_arrow = true; move |arena, state, _min_indent| { skip_first( two_bytes(b'-', b'>', EWhen::Arrow), @@ -3108,13 +3107,25 @@ fn stmts_to_defs<'a>( match sp_stmt.item.value { Stmt::Expr(Expr::Return(return_value, _after_return)) => { if i == stmts.len() - 1 { - last_expr = Some(Loc::at_zero(Expr::Return(return_value, None))); + let region = sp_stmt.item.region; + last_expr = Some(Loc::at( + region, + arena + .alloc(Expr::Return(return_value, None)) + .maybe_before(arena, sp_stmt.before), + )); } else { + let region = Region::span_across( + &sp_stmt.item.region, + &stmts[stmts.len() - 1].item.region, + ); let rest = stmts_to_expr(&stmts[i + 1..], arena)?; - last_expr = Some(Loc::at_zero(Expr::Return( - return_value, - Some(arena.alloc(rest)), - ))); + last_expr = Some(Loc::at( + region, + arena + .alloc(Expr::Return(return_value, Some(arena.alloc(rest)))) + .maybe_before(arena, sp_stmt.before), + )); } // don't re-process the rest of the statements, they got consumed by the early return @@ -3202,11 +3213,7 @@ fn stmts_to_defs<'a>( ) = (td, stmts.get(i + 1).map(|s| (s.before, s.item.value))) { if (spaces_middle.len() <= 1 && !ends_with_spaces_conservative(&ann_type.value)) - || header - .vars - .first() - .map(|var| var.value.equivalent(&loc_pattern.value)) - .unwrap_or(false) + || header_to_pat(arena, header).equivalent(&loc_pattern.value) { // This is a case like // UserId x : [UserId Int] @@ -3323,6 +3330,17 @@ fn stmts_to_defs<'a>( Ok((defs, last_expr)) } +fn header_to_pat<'a>(arena: &'a Bump, header: TypeHeader<'a>) -> Pattern<'a> { + if header.vars.is_empty() { + Pattern::Tag(header.name.value) + } else { + Pattern::Apply( + arena.alloc(Loc::at(header.name.region, Pattern::Tag(header.name.value))), + header.vars, + ) + } +} + fn ends_with_spaces_conservative(ty: &TypeAnnotation<'_>) -> bool { match ty { TypeAnnotation::Function(_, _, res) => ends_with_spaces_conservative(&res.value), diff --git a/crates/compiler/test_syntax/tests/snapshots/fail/return_in_pat.expr.result-ast b/crates/compiler/test_syntax/tests/snapshots/fail/return_in_pat.expr.result-ast new file mode 100644 index 00000000000..0ffbe037c98 --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/fail/return_in_pat.expr.result-ast @@ -0,0 +1 @@ +Expr(BadOperator("=", @13), @0) \ No newline at end of file diff --git a/crates/compiler/test_syntax/tests/snapshots/fail/return_in_pat.expr.roc b/crates/compiler/test_syntax/tests/snapshots/fail/return_in_pat.expr.roc new file mode 100644 index 00000000000..198f3513420 --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/fail/return_in_pat.expr.roc @@ -0,0 +1,3 @@ +( +return e +t)=t diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/annotation_tag_parens_comment.expr.formatted.roc b/crates/compiler/test_syntax/tests/snapshots/pass/annotation_tag_parens_comment.expr.formatted.roc new file mode 100644 index 00000000000..e3097ad48fa --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/annotation_tag_parens_comment.expr.formatted.roc @@ -0,0 +1,4 @@ +g : [ + T T, # +] +D \ No newline at end of file diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/annotation_tag_parens_comment.expr.result-ast b/crates/compiler/test_syntax/tests/snapshots/pass/annotation_tag_parens_comment.expr.result-ast new file mode 100644 index 00000000000..7f9b2cece87 --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/annotation_tag_parens_comment.expr.result-ast @@ -0,0 +1,60 @@ +@0-12 SpaceAfter( + Defs( + Defs { + tags: [ + EitherIndex(2147483648), + ], + regions: [ + @0-10, + ], + space_before: [ + Slice { start: 0, length: 0 }, + ], + space_after: [ + Slice { start: 0, length: 0 }, + ], + spaces: [], + type_defs: [], + value_defs: [ + Annotation( + @0-1 Identifier { + ident: "g", + }, + @2-10 TagUnion { + ext: None, + tags: [ + @3-9 Apply { + name: @3-4 "T", + args: [ + @5-6 SpaceAfter( + Apply( + "", + "T", + [], + ), + [ + LineComment( + "", + ), + ], + ), + ], + }, + ], + }, + ), + ], + }, + @11-12 SpaceBefore( + Tag( + "D", + ), + [ + Newline, + ], + ), + ), + [ + Newline, + ], +) diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/annotation_tag_parens_comment.expr.roc b/crates/compiler/test_syntax/tests/snapshots/pass/annotation_tag_parens_comment.expr.roc new file mode 100644 index 00000000000..064f437af0b --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/annotation_tag_parens_comment.expr.roc @@ -0,0 +1,3 @@ +g:[T(T# +)] +D diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/annotation_tuples_ext_galore.expr.formatted.roc b/crates/compiler/test_syntax/tests/snapshots/pass/annotation_tuples_ext_galore.expr.formatted.roc new file mode 100644 index 00000000000..8118b29c577 --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/annotation_tuples_ext_galore.expr.formatted.roc @@ -0,0 +1,4 @@ +1 : ( + ()n, # +)n +l \ No newline at end of file diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/annotation_tuples_ext_galore.expr.result-ast b/crates/compiler/test_syntax/tests/snapshots/pass/annotation_tuples_ext_galore.expr.result-ast new file mode 100644 index 00000000000..87a50458976 --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/annotation_tuples_ext_galore.expr.result-ast @@ -0,0 +1,63 @@ +@0-16 SpaceAfter( + Defs( + Defs { + tags: [ + EitherIndex(2147483648), + ], + regions: [ + @0-14, + ], + space_before: [ + Slice { start: 0, length: 0 }, + ], + space_after: [ + Slice { start: 0, length: 0 }, + ], + spaces: [], + type_defs: [], + value_defs: [ + Annotation( + @0-1 NumLiteral( + "1", + ), + @2-14 Tuple { + elems: [ + @3-10 Tuple { + elems: [], + ext: Some( + @6-7 SpaceAfter( + BoundVariable( + "n", + ), + [ + LineComment( + "", + ), + ], + ), + ), + }, + ], + ext: Some( + @12-13 BoundVariable( + "n", + ), + ), + }, + ), + ], + }, + @15-16 SpaceBefore( + Var { + module_name: "", + ident: "l", + }, + [ + Newline, + ], + ), + ), + [ + Newline, + ], +) diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/annotation_tuples_ext_galore.expr.roc b/crates/compiler/test_syntax/tests/snapshots/pass/annotation_tuples_ext_galore.expr.roc new file mode 100644 index 00000000000..03de1156f38 --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/annotation_tuples_ext_galore.expr.roc @@ -0,0 +1,3 @@ +1:(()(n# +))(n) +l diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/apply_record_parens_newline_field.expr.formatted.roc b/crates/compiler/test_syntax/tests/snapshots/pass/apply_record_parens_newline_field.expr.formatted.roc new file mode 100644 index 00000000000..2631b565af1 --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/apply_record_parens_newline_field.expr.formatted.roc @@ -0,0 +1,6 @@ +0 { + l, + xt, + l: se, + # +} \ No newline at end of file diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/apply_record_parens_newline_field.expr.result-ast b/crates/compiler/test_syntax/tests/snapshots/pass/apply_record_parens_newline_field.expr.result-ast new file mode 100644 index 00000000000..a9a782d3570 --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/apply_record_parens_newline_field.expr.result-ast @@ -0,0 +1,40 @@ +@0-16 SpaceAfter( + Apply( + @0-1 Num( + "0", + ), + [ + @1-16 Record( + [ + @2-3 LabelOnly( + @2-3 "l", + ), + @4-6 LabelOnly( + @4-6 "xt", + ), + @7-15 RequiredValue( + @7-8 "l", + [], + @9-15 ParensAround( + SpaceAfter( + Var { + module_name: "", + ident: "se", + }, + [ + LineComment( + "", + ), + ], + ), + ), + ), + ], + ), + ], + Space, + ), + [ + Newline, + ], +) diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/apply_record_parens_newline_field.expr.roc b/crates/compiler/test_syntax/tests/snapshots/pass/apply_record_parens_newline_field.expr.roc new file mode 100644 index 00000000000..f31461522ac --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/apply_record_parens_newline_field.expr.roc @@ -0,0 +1,2 @@ +0{l,xt,l:(se# +)} diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/bangs_and_tuple_accessors.expr.formatted.roc b/crates/compiler/test_syntax/tests/snapshots/pass/bangs_and_tuple_accessors.expr.formatted.roc new file mode 100644 index 00000000000..9f9ee910d04 --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/bangs_and_tuple_accessors.expr.formatted.roc @@ -0,0 +1,2 @@ +J +! .1!.0 \ No newline at end of file diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/bangs_and_tuple_accessors.expr.result-ast b/crates/compiler/test_syntax/tests/snapshots/pass/bangs_and_tuple_accessors.expr.result-ast new file mode 100644 index 00000000000..e66ce1ad93d --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/bangs_and_tuple_accessors.expr.result-ast @@ -0,0 +1,54 @@ +@0-9 SpaceAfter( + Defs( + Defs { + tags: [ + EitherIndex(2147483648), + ], + regions: [ + @0-1, + ], + space_before: [ + Slice { start: 0, length: 0 }, + ], + space_after: [ + Slice { start: 0, length: 0 }, + ], + spaces: [], + type_defs: [], + value_defs: [ + Stmt( + @0-1 Tag( + "J", + ), + ), + ], + }, + @2-9 SpaceBefore( + UnaryOp( + @4-6 SpaceBefore( + TupleAccess( + TrySuffix { + target: Task, + expr: AccessorFunction( + TupleIndex( + "1", + ), + ), + }, + "0", + ), + [ + Newline, + ], + ), + @2-3 Not, + ), + [ + Newline, + ], + ), + ), + [ + Newline, + ], +) diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/bangs_and_tuple_accessors.expr.roc b/crates/compiler/test_syntax/tests/snapshots/pass/bangs_and_tuple_accessors.expr.roc new file mode 100644 index 00000000000..16581e5ccda --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/bangs_and_tuple_accessors.expr.roc @@ -0,0 +1,3 @@ +J +! +.1!.0 diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/crazy_annotation_left.expr.formatted.roc b/crates/compiler/test_syntax/tests/snapshots/pass/crazy_annotation_left.expr.formatted.roc index 446560b2429..ab25264ec07 100644 --- a/crates/compiler/test_syntax/tests/snapshots/pass/crazy_annotation_left.expr.formatted.roc +++ b/crates/compiler/test_syntax/tests/snapshots/pass/crazy_annotation_left.expr.formatted.roc @@ -1,4 +1,5 @@ -1 (0 # +1 + (0 # 0) f : f t \ No newline at end of file diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/crazy_annotation_left2.expr.formatted.roc b/crates/compiler/test_syntax/tests/snapshots/pass/crazy_annotation_left2.expr.formatted.roc index d7d9effcad5..9713d5305b9 100644 --- a/crates/compiler/test_syntax/tests/snapshots/pass/crazy_annotation_left2.expr.formatted.roc +++ b/crates/compiler/test_syntax/tests/snapshots/pass/crazy_annotation_left2.expr.formatted.roc @@ -1,4 +1,5 @@ -1 (ts 0) +1 + (ts 0) # diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/dbg_stmt_in_parens.expr.formatted.roc b/crates/compiler/test_syntax/tests/snapshots/pass/dbg_stmt_in_parens.expr.formatted.roc index e719d10a603..13213602dba 100644 --- a/crates/compiler/test_syntax/tests/snapshots/pass/dbg_stmt_in_parens.expr.formatted.roc +++ b/crates/compiler/test_syntax/tests/snapshots/pass/dbg_stmt_in_parens.expr.formatted.roc @@ -2,5 +2,4 @@ dbg D q - h -) \ No newline at end of file + h) \ No newline at end of file diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/double_parens_comment_tuple_pat.expr.formatted.roc b/crates/compiler/test_syntax/tests/snapshots/pass/double_parens_comment_tuple_pat.expr.formatted.roc new file mode 100644 index 00000000000..d6181448844 --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/double_parens_comment_tuple_pat.expr.formatted.roc @@ -0,0 +1,5 @@ +(0 # + e, +0 # + p) : f +t # \ No newline at end of file diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/double_parens_comment_tuple_pat.expr.result-ast b/crates/compiler/test_syntax/tests/snapshots/pass/double_parens_comment_tuple_pat.expr.result-ast new file mode 100644 index 00000000000..4601075a321 --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/double_parens_comment_tuple_pat.expr.result-ast @@ -0,0 +1,79 @@ +@0-19 SpaceAfter( + Defs( + Defs { + tags: [ + EitherIndex(2147483648), + ], + regions: [ + @0-17, + ], + space_before: [ + Slice { start: 0, length: 0 }, + ], + space_after: [ + Slice { start: 0, length: 0 }, + ], + spaces: [], + type_defs: [], + value_defs: [ + Annotation( + @0-15 Tuple( + [ + @1-7 Apply( + @2-3 SpaceAfter( + NumLiteral( + "0", + ), + [ + LineComment( + "", + ), + ], + ), + [ + @6-7 Identifier { + ident: "e", + }, + ], + ), + @8-14 Apply( + @9-10 SpaceAfter( + NumLiteral( + "0", + ), + [ + LineComment( + "", + ), + ], + ), + [ + @13-14 Identifier { + ident: "p", + }, + ], + ), + ], + ), + @16-17 BoundVariable( + "f", + ), + ), + ], + }, + @18-19 SpaceBefore( + Var { + module_name: "", + ident: "t", + }, + [ + Newline, + ], + ), + ), + [ + LineComment( + "", + ), + ], +) diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/double_parens_comment_tuple_pat.expr.roc b/crates/compiler/test_syntax/tests/snapshots/pass/double_parens_comment_tuple_pat.expr.roc new file mode 100644 index 00000000000..745232d4d22 --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/double_parens_comment_tuple_pat.expr.roc @@ -0,0 +1,4 @@ +((0# +)e,(0# +)p):f +t# diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/empty_record_assign_return.expr.formatted.roc b/crates/compiler/test_syntax/tests/snapshots/pass/empty_record_assign_return.expr.formatted.roc new file mode 100644 index 00000000000..204dc524bfc --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/empty_record_assign_return.expr.formatted.roc @@ -0,0 +1,3 @@ +{} = + return f +d \ No newline at end of file diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/empty_record_assign_return.expr.result-ast b/crates/compiler/test_syntax/tests/snapshots/pass/empty_record_assign_return.expr.result-ast new file mode 100644 index 00000000000..8abea2641ed --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/empty_record_assign_return.expr.result-ast @@ -0,0 +1,51 @@ +@0-14 SpaceAfter( + Defs( + Defs { + tags: [ + EitherIndex(2147483648), + ], + regions: [ + @0-12, + ], + space_before: [ + Slice { start: 0, length: 0 }, + ], + space_after: [ + Slice { start: 0, length: 0 }, + ], + spaces: [], + type_defs: [], + value_defs: [ + Body( + @0-2 RecordDestructure( + [], + ), + @4-12 SpaceBefore( + Return( + @4-12 Var { + module_name: "", + ident: "f", + }, + None, + ), + [ + Newline, + ], + ), + ), + ], + }, + @13-14 SpaceBefore( + Var { + module_name: "", + ident: "d", + }, + [ + Newline, + ], + ), + ), + [ + Newline, + ], +) diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/empty_record_assign_return.expr.roc b/crates/compiler/test_syntax/tests/snapshots/pass/empty_record_assign_return.expr.roc new file mode 100644 index 00000000000..2cd99847297 --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/empty_record_assign_return.expr.roc @@ -0,0 +1,3 @@ +{}= +return f +d diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/mega_parens_pat.expr.formatted.roc b/crates/compiler/test_syntax/tests/snapshots/pass/mega_parens_pat.expr.formatted.roc index f5f94c8d198..6afb9689c76 100644 --- a/crates/compiler/test_syntax/tests/snapshots/pass/mega_parens_pat.expr.formatted.roc +++ b/crates/compiler/test_syntax/tests/snapshots/pass/mega_parens_pat.expr.formatted.roc @@ -1,4 +1,5 @@ -1 (0 # +1 + (0 # f) (0 # f) : f diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/multiline_str_apply_in_parens_pat.expr.formatted.roc b/crates/compiler/test_syntax/tests/snapshots/pass/multiline_str_apply_in_parens_pat.expr.formatted.roc new file mode 100644 index 00000000000..853897f4414 --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/multiline_str_apply_in_parens_pat.expr.formatted.roc @@ -0,0 +1,6 @@ +u + ( + """ + """ + 0) : f +s \ No newline at end of file diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/multiline_str_apply_in_parens_pat.expr.result-ast b/crates/compiler/test_syntax/tests/snapshots/pass/multiline_str_apply_in_parens_pat.expr.result-ast new file mode 100644 index 00000000000..6164112a830 --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/multiline_str_apply_in_parens_pat.expr.result-ast @@ -0,0 +1,58 @@ +@0-16 SpaceAfter( + Defs( + Defs { + tags: [ + EitherIndex(2147483648), + ], + regions: [ + @0-14, + ], + space_before: [ + Slice { start: 0, length: 0 }, + ], + space_after: [ + Slice { start: 0, length: 0 }, + ], + spaces: [], + type_defs: [], + value_defs: [ + Annotation( + @0-1 Apply( + @0-1 Identifier { + ident: "u", + }, + [ + @2-11 Apply( + @2-8 StrLiteral( + Block( + [], + ), + ), + [ + @9-10 NumLiteral( + "0", + ), + ], + ), + ], + ), + @13-14 BoundVariable( + "f", + ), + ), + ], + }, + @15-16 SpaceBefore( + Var { + module_name: "", + ident: "s", + }, + [ + Newline, + ], + ), + ), + [ + Newline, + ], +) diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/multiline_str_apply_in_parens_pat.expr.roc b/crates/compiler/test_syntax/tests/snapshots/pass/multiline_str_apply_in_parens_pat.expr.roc new file mode 100644 index 00000000000..16c658528fd --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/multiline_str_apply_in_parens_pat.expr.roc @@ -0,0 +1,2 @@ +u(""""""(0)):f +s diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/multiline_str_opt_field.expr.formatted.roc b/crates/compiler/test_syntax/tests/snapshots/pass/multiline_str_opt_field.expr.formatted.roc new file mode 100644 index 00000000000..0e7ecd88b96 --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/multiline_str_opt_field.expr.formatted.roc @@ -0,0 +1,6 @@ +{ + l? + """ + """, +} + "" \ No newline at end of file diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/multiline_str_opt_field.expr.result-ast b/crates/compiler/test_syntax/tests/snapshots/pass/multiline_str_opt_field.expr.result-ast new file mode 100644 index 00000000000..77a8fab8433 --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/multiline_str_opt_field.expr.result-ast @@ -0,0 +1,28 @@ +@0-12 SpaceAfter( + Apply( + @0-10 Record( + [ + @1-9 OptionalValue( + @1-2 "l", + [], + @3-9 Str( + Block( + [], + ), + ), + ), + ], + ), + [ + @10-12 Str( + PlainLine( + "", + ), + ), + ], + Space, + ), + [ + Newline, + ], +) diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/multiline_str_opt_field.expr.roc b/crates/compiler/test_syntax/tests/snapshots/pass/multiline_str_opt_field.expr.roc new file mode 100644 index 00000000000..66109631434 --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/multiline_str_opt_field.expr.roc @@ -0,0 +1 @@ +{l?""""""}"" diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/nested_list_comment_in_closure_arg.expr.formatted.roc b/crates/compiler/test_syntax/tests/snapshots/pass/nested_list_comment_in_closure_arg.expr.formatted.roc index 3443b960a28..5255bc94fbd 100644 --- a/crates/compiler/test_syntax/tests/snapshots/pass/nested_list_comment_in_closure_arg.expr.formatted.roc +++ b/crates/compiler/test_syntax/tests/snapshots/pass/nested_list_comment_in_closure_arg.expr.formatted.roc @@ -1,4 +1,6 @@ -\I [[ +\I + [[ O # - , i]] + , + i]] -> i \ No newline at end of file diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/nested_when_comment_in_pat.expr.formatted.roc b/crates/compiler/test_syntax/tests/snapshots/pass/nested_when_comment_in_pat.expr.formatted.roc new file mode 100644 index 00000000000..c7276d20cf6 --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/nested_when_comment_in_pat.expr.formatted.roc @@ -0,0 +1,5 @@ +when 6 is + O # + B -> + when 6 is + 1 -> O \ No newline at end of file diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/nested_when_comment_in_pat.expr.result-ast b/crates/compiler/test_syntax/tests/snapshots/pass/nested_when_comment_in_pat.expr.result-ast new file mode 100644 index 00000000000..c0f317fa44c --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/nested_when_comment_in_pat.expr.result-ast @@ -0,0 +1,62 @@ +@0-31 SpaceAfter( + When( + @5-6 Num( + "6", + ), + [ + WhenBranch { + patterns: [ + @10-15 SpaceBefore( + Apply( + @10-11 Tag( + "O", + ), + [ + @14-15 SpaceBefore( + Tag( + "B", + ), + [ + LineComment( + "", + ), + ], + ), + ], + ), + [ + Newline, + ], + ), + ], + value: @17-31 When( + @22-23 Num( + "6", + ), + [ + WhenBranch { + patterns: [ + @27-28 SpaceBefore( + NumLiteral( + "1", + ), + [ + Newline, + ], + ), + ], + value: @30-31 Tag( + "O", + ), + guard: None, + }, + ], + ), + guard: None, + }, + ], + ), + [ + Newline, + ], +) diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/nested_when_comment_in_pat.expr.roc b/crates/compiler/test_syntax/tests/snapshots/pass/nested_when_comment_in_pat.expr.roc new file mode 100644 index 00000000000..529d4f33916 --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/nested_when_comment_in_pat.expr.roc @@ -0,0 +1,4 @@ +when 6 is +O# + B->when 6 is +1->O diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/opaque_in_ann_apply_arg.expr.formatted.roc b/crates/compiler/test_syntax/tests/snapshots/pass/opaque_in_ann_apply_arg.expr.formatted.roc new file mode 100644 index 00000000000..d375b8671ba --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/opaque_in_ann_apply_arg.expr.formatted.roc @@ -0,0 +1,4 @@ +B @A : w +# +@A = e +i \ No newline at end of file diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/opaque_in_ann_apply_arg.expr.result-ast b/crates/compiler/test_syntax/tests/snapshots/pass/opaque_in_ann_apply_arg.expr.result-ast new file mode 100644 index 00000000000..ec5531266b3 --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/opaque_in_ann_apply_arg.expr.result-ast @@ -0,0 +1,66 @@ +@0-14 SpaceAfter( + Defs( + Defs { + tags: [ + EitherIndex(0), + EitherIndex(2147483648), + ], + regions: [ + @0-5, + @8-12, + ], + space_before: [ + Slice { start: 0, length: 0 }, + Slice { start: 0, length: 2 }, + ], + space_after: [ + Slice { start: 0, length: 0 }, + Slice { start: 2, length: 0 }, + ], + spaces: [ + Newline, + LineComment( + "", + ), + ], + type_defs: [ + Alias { + header: TypeHeader { + name: @0-1 "B", + vars: [ + @1-3 OpaqueRef( + "@A", + ), + ], + }, + ann: @4-5 BoundVariable( + "w", + ), + }, + ], + value_defs: [ + Body( + @8-10 OpaqueRef( + "@A", + ), + @11-12 Var { + module_name: "", + ident: "e", + }, + ), + ], + }, + @13-14 SpaceBefore( + Var { + module_name: "", + ident: "i", + }, + [ + Newline, + ], + ), + ), + [ + Newline, + ], +) diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/opaque_in_ann_apply_arg.expr.roc b/crates/compiler/test_syntax/tests/snapshots/pass/opaque_in_ann_apply_arg.expr.roc new file mode 100644 index 00000000000..e11b1644d88 --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/opaque_in_ann_apply_arg.expr.roc @@ -0,0 +1,4 @@ +B@A:w +# +@A=e +i diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/p_return_f_minus_f.expr.result-ast b/crates/compiler/test_syntax/tests/snapshots/pass/p_return_f_minus_f.expr.result-ast index 623833b2182..43e8e794edf 100644 --- a/crates/compiler/test_syntax/tests/snapshots/pass/p_return_f_minus_f.expr.result-ast +++ b/crates/compiler/test_syntax/tests/snapshots/pass/p_return_f_minus_f.expr.result-ast @@ -23,52 +23,57 @@ ), ], }, - Return( - @2-16 SpaceBefore( - Defs( - Defs { - tags: [ - EitherIndex(2147483648), - ], - regions: [ - @11-12, - ], - space_before: [ - Slice { start: 0, length: 0 }, - ], - space_after: [ - Slice { start: 0, length: 0 }, - ], - spaces: [], - type_defs: [], - value_defs: [ - Stmt( - @11-12 Var { + @2-16 SpaceBefore( + Return( + @2-16 SpaceBefore( + Defs( + Defs { + tags: [ + EitherIndex(2147483648), + ], + regions: [ + @11-12, + ], + space_before: [ + Slice { start: 0, length: 0 }, + ], + space_after: [ + Slice { start: 0, length: 0 }, + ], + spaces: [], + type_defs: [], + value_defs: [ + Stmt( + @11-12 Var { + module_name: "", + ident: "f", + }, + ), + ], + }, + @14-16 SpaceBefore( + UnaryOp( + @15-16 Var { module_name: "", ident: "f", }, + @14-15 Negate, ), - ], - }, - @14-16 SpaceBefore( - UnaryOp( - @15-16 Var { - module_name: "", - ident: "f", - }, - @14-15 Negate, + [ + Newline, + ], ), - [ - Newline, - ], ), + [ + LineComment( + "", + ), + ], ), - [ - LineComment( - "", - ), - ], + None, ), - None, + [ + Newline, + ], ), ) diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/paren_newline_before_return.expr.formatted.roc b/crates/compiler/test_syntax/tests/snapshots/pass/paren_newline_before_return.expr.formatted.roc new file mode 100644 index 00000000000..54082853b56 --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/paren_newline_before_return.expr.formatted.roc @@ -0,0 +1,3 @@ +i + +return u \ No newline at end of file diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/paren_newline_before_return.expr.result-ast b/crates/compiler/test_syntax/tests/snapshots/pass/paren_newline_before_return.expr.result-ast new file mode 100644 index 00000000000..4dc80462d59 --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/paren_newline_before_return.expr.result-ast @@ -0,0 +1,51 @@ +@0-14 SpaceAfter( + Defs( + Defs { + tags: [ + EitherIndex(2147483648), + ], + regions: [ + @0-5, + ], + space_before: [ + Slice { start: 0, length: 0 }, + ], + space_after: [ + Slice { start: 0, length: 0 }, + ], + spaces: [], + type_defs: [], + value_defs: [ + Stmt( + @0-5 ParensAround( + SpaceAfter( + Var { + module_name: "", + ident: "i", + }, + [ + Newline, + Newline, + ], + ), + ), + ), + ], + }, + @6-14 SpaceBefore( + Return( + @6-14 Var { + module_name: "", + ident: "u", + }, + None, + ), + [ + Newline, + ], + ), + ), + [ + Newline, + ], +) diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/paren_newline_before_return.expr.roc b/crates/compiler/test_syntax/tests/snapshots/pass/paren_newline_before_return.expr.roc new file mode 100644 index 00000000000..ce24cbf185b --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/paren_newline_before_return.expr.roc @@ -0,0 +1,4 @@ +(i + +) +return u diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/pattern_comma_newlines.expr.formatted.roc b/crates/compiler/test_syntax/tests/snapshots/pass/pattern_comma_newlines.expr.formatted.roc index a03fb36ab84..db431fc0a74 100644 --- a/crates/compiler/test_syntax/tests/snapshots/pass/pattern_comma_newlines.expr.formatted.roc +++ b/crates/compiler/test_syntax/tests/snapshots/pass/pattern_comma_newlines.expr.formatted.roc @@ -1,3 +1,4 @@ -1 (i, p # +1 + (i, p # ) : f n \ No newline at end of file diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/pattern_record_apply_comment.expr.formatted.roc b/crates/compiler/test_syntax/tests/snapshots/pass/pattern_record_apply_comment.expr.formatted.roc index e3ef37924fc..3f2f6663f56 100644 --- a/crates/compiler/test_syntax/tests/snapshots/pass/pattern_record_apply_comment.expr.formatted.roc +++ b/crates/compiler/test_syntax/tests/snapshots/pass/pattern_record_apply_comment.expr.formatted.roc @@ -1,3 +1,4 @@ -s { t # +s + { t # } : s p # \ No newline at end of file diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/repr_7342.expr.formatted.roc b/crates/compiler/test_syntax/tests/snapshots/pass/repr_7342.expr.formatted.roc new file mode 100644 index 00000000000..f2251b05c61 --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/repr_7342.expr.formatted.roc @@ -0,0 +1,6 @@ +( + 1 # + Q + a : t + n +) \ No newline at end of file diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/repr_7342.expr.result-ast b/crates/compiler/test_syntax/tests/snapshots/pass/repr_7342.expr.result-ast new file mode 100644 index 00000000000..a838faad686 --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/repr_7342.expr.result-ast @@ -0,0 +1,61 @@ +@0-14 SpaceAfter( + ParensAround( + Defs( + Defs { + tags: [ + EitherIndex(2147483648), + ], + regions: [ + @1-11, + ], + space_before: [ + Slice { start: 0, length: 0 }, + ], + space_after: [ + Slice { start: 0, length: 0 }, + ], + spaces: [], + type_defs: [], + value_defs: [ + Annotation( + @2-3 Apply( + @2-3 SpaceAfter( + NumLiteral( + "1", + ), + [ + LineComment( + "", + ), + ], + ), + [ + @6-7 Tag( + "Q", + ), + @8-9 Identifier { + ident: "a", + }, + ], + ), + @10-11 BoundVariable( + "t", + ), + ), + ], + }, + @12-13 SpaceBefore( + Var { + module_name: "", + ident: "n", + }, + [ + Newline, + ], + ), + ), + ), + [ + Newline, + ], +) diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/repr_7342.expr.roc b/crates/compiler/test_syntax/tests/snapshots/pass/repr_7342.expr.roc new file mode 100644 index 00000000000..66cfb7994c2 --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/repr_7342.expr.roc @@ -0,0 +1,3 @@ +((1# +)Q a:t +n) diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/repr_7343.expr.formatted.roc b/crates/compiler/test_syntax/tests/snapshots/pass/repr_7343.expr.formatted.roc new file mode 100644 index 00000000000..1067caef3cb --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/repr_7343.expr.formatted.roc @@ -0,0 +1,6 @@ +( + i <- ( + dbg 0 + _) + 9 +) \ No newline at end of file diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/repr_7343.expr.result-ast b/crates/compiler/test_syntax/tests/snapshots/pass/repr_7343.expr.result-ast new file mode 100644 index 00000000000..b7e55e8df5b --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/repr_7343.expr.result-ast @@ -0,0 +1,40 @@ +@0-18 SpaceAfter( + ParensAround( + ParensAround( + Backpassing( + [ + @2-3 Identifier { + ident: "i", + }, + ], + @5-14 ParensAround( + DbgStmt { + first: @10-11 Num( + "0", + ), + extra_args: [], + continuation: @12-13 SpaceBefore( + Underscore( + "", + ), + [ + Newline, + ], + ), + }, + ), + @15-16 SpaceBefore( + Num( + "9", + ), + [ + Newline, + ], + ), + ), + ), + ), + [ + Newline, + ], +) diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/repr_7343.expr.roc b/crates/compiler/test_syntax/tests/snapshots/pass/repr_7343.expr.roc new file mode 100644 index 00000000000..7def50ae12c --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/repr_7343.expr.roc @@ -0,0 +1,3 @@ +((i<-(dbg 0 +_) +9)) diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/repr_7346.expr.formatted.roc b/crates/compiler/test_syntax/tests/snapshots/pass/repr_7346.expr.formatted.roc new file mode 100644 index 00000000000..26fa962bed4 --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/repr_7346.expr.formatted.roc @@ -0,0 +1,4 @@ +il3 \k -> # w#z + CCC @C # i + (t! K) : i + C \ No newline at end of file diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/repr_7346.expr.result-ast b/crates/compiler/test_syntax/tests/snapshots/pass/repr_7346.expr.result-ast new file mode 100644 index 00000000000..d8e89a55735 --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/repr_7346.expr.result-ast @@ -0,0 +1,86 @@ +@0-31 SpaceAfter( + Apply( + @0-3 Var { + module_name: "", + ident: "il3", + }, + [ + @3-31 Closure( + [ + @4-5 Identifier { + ident: "k", + }, + ], + @13-31 SpaceBefore( + Defs( + Defs { + tags: [ + EitherIndex(0), + ], + regions: [ + @13-28, + ], + space_before: [ + Slice { start: 0, length: 0 }, + ], + space_after: [ + Slice { start: 0, length: 0 }, + ], + spaces: [], + type_defs: [ + Alias { + header: TypeHeader { + name: @13-16 "CCC", + vars: [ + @16-18 OpaqueRef( + "@C", + ), + @22-25 SpaceBefore( + Apply( + @22-24 Identifier { + ident: "t!", + }, + [ + @24-25 Tag( + "K", + ), + ], + ), + [ + LineComment( + "i", + ), + ], + ), + ], + }, + ann: @27-28 BoundVariable( + "i", + ), + }, + ], + value_defs: [], + }, + @30-31 SpaceBefore( + Tag( + "C", + ), + [ + Newline, + ], + ), + ), + [ + LineComment( + "w#z", + ), + ], + ), + ), + ], + Space, + ), + [ + Newline, + ], +) diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/repr_7346.expr.roc b/crates/compiler/test_syntax/tests/snapshots/pass/repr_7346.expr.roc new file mode 100644 index 00000000000..7f7f5a10b3a --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/repr_7346.expr.roc @@ -0,0 +1,4 @@ +il3\k->#w#z + CCC@C(#i +t!K):i + C diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/return_backpassing.expr.formatted.roc b/crates/compiler/test_syntax/tests/snapshots/pass/return_backpassing.expr.formatted.roc new file mode 100644 index 00000000000..23fd5fc4c85 --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/return_backpassing.expr.formatted.roc @@ -0,0 +1,3 @@ +return + u <- _ + m \ No newline at end of file diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/return_backpassing.expr.result-ast b/crates/compiler/test_syntax/tests/snapshots/pass/return_backpassing.expr.result-ast new file mode 100644 index 00000000000..be0a498e038 --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/return_backpassing.expr.result-ast @@ -0,0 +1,32 @@ +@0-15 SpaceAfter( + Return( + @0-15 SpaceBefore( + Backpassing( + [ + @8-9 Identifier { + ident: "u", + }, + ], + @11-12 Underscore( + "", + ), + @14-15 SpaceBefore( + Var { + module_name: "", + ident: "m", + }, + [ + Newline, + ], + ), + ), + [ + Newline, + ], + ), + None, + ), + [ + Newline, + ], +) diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/return_backpassing.expr.roc b/crates/compiler/test_syntax/tests/snapshots/pass/return_backpassing.expr.roc new file mode 100644 index 00000000000..4a788a3b675 --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/return_backpassing.expr.roc @@ -0,0 +1,3 @@ +return + u<-_ + m diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/return_in_static_def.expr.result-ast b/crates/compiler/test_syntax/tests/snapshots/pass/return_in_static_def.expr.result-ast index 51fd63a3835..d8da9e12a50 100644 --- a/crates/compiler/test_syntax/tests/snapshots/pass/return_in_static_def.expr.result-ast +++ b/crates/compiler/test_syntax/tests/snapshots/pass/return_in_static_def.expr.result-ast @@ -88,12 +88,17 @@ ), ], }, - Return( - @86-97 Var { - module_name: "", - ident: "x", - }, - None, + @86-97 SpaceBefore( + Return( + @86-97 Var { + module_name: "", + ident: "x", + }, + None, + ), + [ + Newline, + ], ), ), [ diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/return_minus_one.expr.result-ast b/crates/compiler/test_syntax/tests/snapshots/pass/return_minus_one.expr.result-ast index 4571082e1f6..47c7d77aeac 100644 --- a/crates/compiler/test_syntax/tests/snapshots/pass/return_minus_one.expr.result-ast +++ b/crates/compiler/test_syntax/tests/snapshots/pass/return_minus_one.expr.result-ast @@ -1,4 +1,4 @@ -Return( +@0-10 Return( @0-8 UnaryOp( @7-8 Var { module_name: "", diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/return_then_nested_parens.expr.formatted.roc b/crates/compiler/test_syntax/tests/snapshots/pass/return_then_nested_parens.expr.formatted.roc new file mode 100644 index 00000000000..899751821ab --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/return_then_nested_parens.expr.formatted.roc @@ -0,0 +1,2 @@ +return n +0 # \ No newline at end of file diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/return_then_nested_parens.expr.result-ast b/crates/compiler/test_syntax/tests/snapshots/pass/return_then_nested_parens.expr.result-ast new file mode 100644 index 00000000000..9fa302f53c1 --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/return_then_nested_parens.expr.result-ast @@ -0,0 +1,37 @@ +@0-17 SpaceAfter( + Return( + @0-8 Var { + module_name: "", + ident: "n", + }, + Some( + @9-17 SpaceBefore( + ParensAround( + SpaceAfter( + ParensAround( + SpaceAfter( + Num( + "0", + ), + [ + Newline, + ], + ), + ), + [ + LineComment( + "", + ), + ], + ), + ), + [ + Newline, + ], + ), + ), + ), + [ + Newline, + ], +) diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/return_then_nested_parens.expr.roc b/crates/compiler/test_syntax/tests/snapshots/pass/return_then_nested_parens.expr.roc new file mode 100644 index 00000000000..6059a041aa3 --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/return_then_nested_parens.expr.roc @@ -0,0 +1,4 @@ +return n +((0 +)# +) diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/return_with_after.expr.result-ast b/crates/compiler/test_syntax/tests/snapshots/pass/return_with_after.expr.result-ast index a9d9b8d9a53..9b1c30ea05a 100644 --- a/crates/compiler/test_syntax/tests/snapshots/pass/return_with_after.expr.result-ast +++ b/crates/compiler/test_syntax/tests/snapshots/pass/return_with_after.expr.result-ast @@ -1,4 +1,4 @@ -Return( +@0-13 Return( @0-8 Num( "-1", ), diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/when_in_list.expr.formatted.roc b/crates/compiler/test_syntax/tests/snapshots/pass/when_in_list.expr.formatted.roc new file mode 100644 index 00000000000..069fbad9b98 --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/when_in_list.expr.formatted.roc @@ -0,0 +1,6 @@ +[ + when 2 is + 8 -> + [ + ], +] \ No newline at end of file diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/when_in_list.expr.result-ast b/crates/compiler/test_syntax/tests/snapshots/pass/when_in_list.expr.result-ast new file mode 100644 index 00000000000..21c18ce745e --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/when_in_list.expr.result-ast @@ -0,0 +1,32 @@ +@0-18 SpaceAfter( + List( + [ + @1-17 When( + @6-7 Num( + "2", + ), + [ + WhenBranch { + patterns: [ + @11-12 NumLiteral( + "8", + ), + ], + value: @14-17 List( + Collection { + items: [], + final_comments: [ + Newline, + ], + }, + ), + guard: None, + }, + ], + ), + ], + ), + [ + Newline, + ], +) diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/when_in_list.expr.roc b/crates/compiler/test_syntax/tests/snapshots/pass/when_in_list.expr.roc new file mode 100644 index 00000000000..19641b99516 --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/when_in_list.expr.roc @@ -0,0 +1,2 @@ +[when 2 is 8->[ +]] diff --git a/crates/compiler/test_syntax/tests/test_snapshots.rs b/crates/compiler/test_syntax/tests/test_snapshots.rs index b1ae9285588..f6d610007f8 100644 --- a/crates/compiler/test_syntax/tests/test_snapshots.rs +++ b/crates/compiler/test_syntax/tests/test_snapshots.rs @@ -240,6 +240,7 @@ mod test_snapshots { fail/record_type_open_indent.expr, fail/record_type_tab.expr, fail/return_as_single_line_expr.expr, + fail/return_in_pat.expr, fail/single_no_end.expr, fail/tab_crash.header, fail/tag_union_end.expr, @@ -297,14 +298,17 @@ mod test_snapshots { pass/annotated_tuple_destructure.expr, pass/annotation_apply_newlines.expr, pass/annotation_comment_before_colon.expr, + pass/annotation_tag_parens_comment.expr, pass/annotation_tuple_comment.expr, pass/annotation_tuple_newline.expr, pass/annotation_tuple_parens_newlines.expr, + pass/annotation_tuples_ext_galore.expr, pass/applies_in_binop.expr, pass/apply_binop_switch.expr, pass/apply_closure_pizza.expr, pass/apply_parenthetical_tag_args.expr, pass/apply_record_ann.expr, + pass/apply_record_parens_newline_field.expr, pass/apply_tag.expr, pass/apply_three_args.expr, pass/apply_tuple_ext_parens_ty.expr, @@ -315,6 +319,7 @@ mod test_snapshots { pass/backpassing_bananza.expr, pass/backpassing_in_parens_in_tuple.expr, pass/bang_newline_double_accessor.expr, + pass/bangs_and_tuple_accessors.expr, pass/basic_apply.expr, pass/basic_docs.expr, pass/basic_field.expr, @@ -376,6 +381,7 @@ mod test_snapshots { pass/defs_suffixed_middle_extra_indents.moduledefs, pass/destructure_tag_assignment.expr, pass/docs.expr, + pass/double_parens_comment_tuple_pat.expr, pass/double_space_before.expr, pass/effectful_closure_statements.expr, pass/empty_app_header.header, @@ -385,6 +391,7 @@ mod test_snapshots { pass/empty_package_header.header, pass/empty_platform_header.header, pass/empty_record.expr, + pass/empty_record_assign_return.expr, pass/empty_record_assign_tag.expr, pass/empty_record_assignment.expr, pass/empty_record_assignment_d_when_bang.expr, @@ -468,8 +475,10 @@ mod test_snapshots { pass/multiline_apply_equals_multiline_apply.expr, pass/multiline_backpassing.expr, pass/multiline_binop_when_with_comments.expr, + pass/multiline_str_apply_in_parens_pat.expr, pass/multiline_str_crazyness.expr, pass/multiline_str_in_pat.expr, + pass/multiline_str_opt_field.expr, pass/multiline_string.expr, pass/multiline_string_in_apply.expr, pass/multiline_tuple_with_comments.expr, @@ -492,6 +501,7 @@ mod test_snapshots { pass/nested_if.expr, pass/nested_list_comment_in_closure_arg.expr, pass/nested_parens_in_pattern.expr, + pass/nested_when_comment_in_pat.expr, pass/newline_after_equals.expr, // Regression test for https://github.com/roc-lang/roc/issues/51 pass/newline_after_mul.expr, pass/newline_after_opt_field.expr, @@ -527,6 +537,7 @@ mod test_snapshots { pass/opaque_comment_after_head.expr, pass/opaque_destructure_first_item_in_body.expr, pass/opaque_has_abilities.expr, + pass/opaque_in_ann_apply_arg.expr, pass/opaque_reference_expr.expr, pass/opaque_reference_expr_with_arguments.expr, pass/opaque_reference_pattern.expr, @@ -542,6 +553,7 @@ mod test_snapshots { pass/outdented_record.expr, pass/p_return_f_minus_f.expr, pass/packed_singleton_list.expr, + pass/paren_newline_before_return.expr, pass/parens_apply_newline.expr, pass/parens_apply_not_parens.expr, pass/parens_comment_in_ty_annotation.expr, @@ -594,8 +606,12 @@ mod test_snapshots { pass/record_updater_var_apply.expr, pass/record_with_if.expr, pass/record_with_lots_of_newlines.expr, + pass/repr_7342.expr, + pass/repr_7343.expr, + pass/repr_7346.expr, pass/requires_type.header, pass/return_apply_newline.expr, + pass/return_backpassing.expr, pass/return_field_access_in_parens.expr, pass/return_in_apply_func.expr, pass/return_in_if.expr, @@ -604,6 +620,7 @@ mod test_snapshots { pass/return_minus_one.expr, pass/return_multiline.expr, pass/return_only_statement.expr, + pass/return_then_nested_parens.expr, pass/return_with_after.expr, pass/separate_defs.moduledefs, pass/single_arg_closure.expr, @@ -677,6 +694,7 @@ mod test_snapshots { pass/when_in_binops.expr, pass/when_in_function.expr, pass/when_in_function_python_style_indent.expr, + pass/when_in_list.expr, pass/when_in_parens.expr, pass/when_in_parens_indented.expr, pass/when_newline_after_condition.expr, @@ -706,7 +724,11 @@ mod test_snapshots { // This is the current list as of writing. // We should be driving these down to zero over time. // Adding this protection in now to avoid accidentally adding more. - "all_the_bangs" => true, + "all_the_bangs" | "bangs_and_tuple_accessors" => { + // both of these result in: + // "a Expr::TrySuffix expression was not completely removed in desugar_value_def_suffixed" + true + } // When adding new snapshot tests, strongly prefer fixing any canonicalization panics // they may run into rather than adding them to this list.