Fix where clauses in tuple types with trailing commas

This commit is contained in:
Joshua Warner 2025-01-01 13:48:35 -05:00
parent 9ff1b630a8
commit 7d91b01c5a
No known key found for this signature in database
GPG key ID: 89AD497003F93FDD
7 changed files with 109 additions and 13 deletions

View file

@ -97,7 +97,7 @@ where
) )
} }
fn spaces_around_help<'a, S>( pub fn spaces_around_help<'a, S>(
arena: &'a Bump, arena: &'a Bump,
tuples: ( tuples: (
&'a [CommentOrNewline<'a>], &'a [CommentOrNewline<'a>],

View file

@ -4,7 +4,7 @@ use crate::ast::{
TypeAnnotation, TypeHeader, TypeAnnotation, TypeHeader,
}; };
use crate::blankspace::{ use crate::blankspace::{
space0_around_ee, space0_before_e, space0_before_optional_after, space0_e, self, space0_around_ee, space0_before_e, space0_before_optional_after, space0_e,
spaces_before_optional_after, spaces_before_optional_after,
}; };
use crate::expr::record_field; use crate::expr::record_field;
@ -311,6 +311,7 @@ fn loc_type_in_parens<'a>(
fields.push(first_field); fields.push(first_field);
loop { loop {
#[derive(Debug)]
enum Sep { enum Sep {
Comma, Comma,
FunctionArrow(FunctionArrow), FunctionArrow(FunctionArrow),
@ -326,25 +327,43 @@ fn loc_type_in_parens<'a>(
crate::parser::keyword(keyword::WHERE, ETypeInParens::End), crate::parser::keyword(keyword::WHERE, ETypeInParens::End),
|_| Sep::Where |_| Sep::Where
), ),
]; ]
.trace("sep");
match sep.parse(arena, state.clone(), 0) { match sep.parse(arena, state.clone(), 0) {
Ok((_, Sep::Comma, next_state)) => { Ok((_, Sep::Comma, next_state)) => {
match spaces_before_optional_after(specialize_err_ref( let parser = map_with_arena(
and(
backtrackable(blankspace::spaces()),
and(
specialize_err_ref(
ETypeInParens::Type, ETypeInParens::Type,
term_or_apply_with_as(false), term_or_apply_with_as(false),
)) ),
.parse(arena, next_state.clone(), 0) one_of![
{ backtrackable(blankspace::spaces()),
succeed(&[] as &[_]),
],
),
),
blankspace::spaces_around_help,
);
match parser.parse(arena, next_state.clone(), 0) {
Ok((element_progress, next_field, next_state)) => { Ok((element_progress, next_field, next_state)) => {
dbg!();
debug_assert_eq!(element_progress, MadeProgress); debug_assert_eq!(element_progress, MadeProgress);
state = next_state; state = next_state;
fields.push(next_field); fields.push(next_field);
} }
Err((_, _fail)) => { Err((NoProgress, _fail)) => {
dbg!();
state = next_state; state = next_state;
break; break;
} }
Err((MadeProgress, fail)) => {
dbg!();
return Err((MadeProgress, fail));
}
} }
} }
Ok((_, Sep::FunctionArrow(arrow), next_state)) => { Ok((_, Sep::FunctionArrow(arrow), next_state)) => {
@ -755,10 +774,10 @@ fn parse_implements_clause_chain_after_where<'a>(
// Parse the first clause (there must be one), then the rest // Parse the first clause (there must be one), then the rest
let (_, first_clause, state) = implements_clause().parse(arena, state, min_indent)?; let (_, first_clause, state) = implements_clause().parse(arena, state, min_indent)?;
let (_, mut clauses, state) = zero_or_more(skip_first( let (_, mut clauses, state) = zero_or_more(backtrackable(skip_first(
byte(b',', EType::TImplementsClause), byte(b',', EType::TImplementsClause),
implements_clause(), implements_clause(),
)) )))
.parse(arena, state, min_indent)?; .parse(arena, state, min_indent)?;
// Usually the number of clauses shouldn't be too large, so this is okay // Usually the number of clauses shouldn't be too large, so this is okay

View file

@ -1 +1 @@
Expr(Type(TInParens(End(@7), @2), @2), @0) Expr(Type(TInParens(Type(TInParens(Type(TInParens(Type(TInParens(Type(TInParens(Type(TInParens(Type(TInParens(Type(TInParens(Type(TInParens(Type(TInParens(Type(TInParens(Type(TInParens(Type(TInParens(Type(TInParens(Type(TInParens(Type(TInParens(Type(TInParens(Type(TInParens(Type(TInParens(Type(TInParens(Type(TInParens(End(@78), @74), @74), @71), @71), @68), @68), @65), @65), @60), @60), @57), @57), @52), @52), @49), @49), @46), @46), @43), @43), @40), @39), @38), @38), @35), @35), @30), @30), @27), @27), @22), @22), @19), @19), @16), @16), @10), @10), @7), @7), @2), @2), @0)

View file

@ -0,0 +1,5 @@
1 : (
* #
where e implements J,
)*
l

View file

@ -0,0 +1,68 @@
@0-30 SpaceAfter(
Defs(
Defs {
tags: [
EitherIndex(2147483648),
],
regions: [
@0-28,
],
space_before: [
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
],
space_after: [
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
],
spaces: [],
type_defs: [],
value_defs: [
Annotation(
@0-1 NumLiteral(
"1",
),
@2-28 Tuple {
elems: [
@3-26 Where(
@3-4 SpaceAfter(
Wildcard,
[
LineComment(
"",
),
],
),
[
@12-26 ImplementsClause {
var: @12-13 "e",
abilities: [
@25-26 Apply(
"",
"J",
[],
),
],
},
],
),
],
ext: Some(
@27-28 Wildcard,
),
},
),
],
},
@29-30 SpaceBefore(
Var {
module_name: "",
ident: "l",
},
[
Newline,
],
),
),
[
Newline,
],
)

View file

@ -0,0 +1,3 @@
1:(*#
where e implements J)*
l

View file

@ -782,6 +782,7 @@ mod test_snapshots {
pass/where_clause_non_function.expr, pass/where_clause_non_function.expr,
pass/where_clause_on_newline.expr, pass/where_clause_on_newline.expr,
pass/where_ident.expr, pass/where_ident.expr,
pass/where_in_tuple_after_comment.expr,
pass/zero_float.expr, pass/zero_float.expr,
pass/zero_int.expr, pass/zero_int.expr,
// END SNAPSHOTS (for automatic test detection via `env ROC_SNAPSHOT_TEST_OVERWRITE=1 cargo test`) // END SNAPSHOTS (for automatic test detection via `env ROC_SNAPSHOT_TEST_OVERWRITE=1 cargo test`)