mirror of
https://github.com/roc-lang/roc.git
synced 2024-09-20 15:27:45 +03:00
Correct indentation for when expressions
... and simultaneously remove the need for State::indent_column field / multiline tracking in blankspace.rs. Fixes #2889
This commit is contained in:
parent
19436cc58a
commit
ada8af25cc
@ -197,11 +197,7 @@ where
|
||||
Err((MadeProgress, indent_problem(state.pos()), state))
|
||||
} else {
|
||||
let comments_and_newlines = Vec::with_capacity_in(newlines, arena);
|
||||
let mut spaces = eat_spaces(state, false, comments_and_newlines);
|
||||
|
||||
if spaces.multiline {
|
||||
spaces.state.indent_column = spaces.state.column();
|
||||
}
|
||||
let spaces = eat_spaces(state, comments_and_newlines);
|
||||
|
||||
Ok((
|
||||
MadeProgress,
|
||||
@ -324,13 +320,11 @@ fn fast_eat_spaces(state: &State) -> FastSpaceState {
|
||||
|
||||
struct SpaceState<'a> {
|
||||
state: State<'a>,
|
||||
multiline: bool,
|
||||
comments_and_newlines: Vec<'a, CommentOrNewline<'a>>,
|
||||
}
|
||||
|
||||
fn eat_spaces<'a>(
|
||||
mut state: State<'a>,
|
||||
mut multiline: bool,
|
||||
mut comments_and_newlines: Vec<'a, CommentOrNewline<'a>>,
|
||||
) -> SpaceState<'a> {
|
||||
for c in state.bytes() {
|
||||
@ -340,7 +334,6 @@ fn eat_spaces<'a>(
|
||||
}
|
||||
b'\n' => {
|
||||
state = state.advance_newline();
|
||||
multiline = true;
|
||||
comments_and_newlines.push(CommentOrNewline::Newline);
|
||||
}
|
||||
b'\r' => {
|
||||
@ -350,7 +343,7 @@ fn eat_spaces<'a>(
|
||||
|
||||
b'#' => {
|
||||
state = state.advance(1);
|
||||
return eat_line_comment(state, multiline, comments_and_newlines);
|
||||
return eat_line_comment(state, comments_and_newlines);
|
||||
}
|
||||
_ => break,
|
||||
}
|
||||
@ -358,14 +351,12 @@ fn eat_spaces<'a>(
|
||||
|
||||
SpaceState {
|
||||
state,
|
||||
multiline,
|
||||
comments_and_newlines,
|
||||
}
|
||||
}
|
||||
|
||||
fn eat_line_comment<'a>(
|
||||
mut state: State<'a>,
|
||||
mut multiline: bool,
|
||||
mut comments_and_newlines: Vec<'a, CommentOrNewline<'a>>,
|
||||
) -> SpaceState<'a> {
|
||||
let mut index = state.pos().offset as usize;
|
||||
@ -388,7 +379,6 @@ fn eat_line_comment<'a>(
|
||||
index += 2;
|
||||
|
||||
comments_and_newlines.push(CommentOrNewline::DocComment(""));
|
||||
multiline = true;
|
||||
|
||||
for c in state.bytes() {
|
||||
match c {
|
||||
@ -397,7 +387,6 @@ fn eat_line_comment<'a>(
|
||||
}
|
||||
b'\n' => {
|
||||
state = state.advance_newline();
|
||||
multiline = true;
|
||||
comments_and_newlines.push(CommentOrNewline::Newline);
|
||||
}
|
||||
b'\r' => {
|
||||
@ -417,7 +406,6 @@ fn eat_line_comment<'a>(
|
||||
|
||||
return SpaceState {
|
||||
state,
|
||||
multiline,
|
||||
comments_and_newlines,
|
||||
};
|
||||
}
|
||||
@ -427,7 +415,6 @@ fn eat_line_comment<'a>(
|
||||
|
||||
return SpaceState {
|
||||
state,
|
||||
multiline,
|
||||
comments_and_newlines,
|
||||
};
|
||||
}
|
||||
@ -483,7 +470,6 @@ fn eat_line_comment<'a>(
|
||||
comments_and_newlines.push(CommentOrNewline::LineComment(comment));
|
||||
}
|
||||
state = state.advance_newline();
|
||||
multiline = true;
|
||||
|
||||
index += 1;
|
||||
while index < length {
|
||||
@ -493,7 +479,6 @@ fn eat_line_comment<'a>(
|
||||
}
|
||||
b'\n' => {
|
||||
state = state.advance_newline();
|
||||
multiline = true;
|
||||
comments_and_newlines.push(CommentOrNewline::Newline);
|
||||
}
|
||||
b'\r' => {
|
||||
@ -513,7 +498,6 @@ fn eat_line_comment<'a>(
|
||||
|
||||
return SpaceState {
|
||||
state,
|
||||
multiline,
|
||||
comments_and_newlines,
|
||||
};
|
||||
}
|
||||
@ -550,7 +534,6 @@ fn eat_line_comment<'a>(
|
||||
comments_and_newlines.push(CommentOrNewline::LineComment(comment));
|
||||
}
|
||||
state = state.advance_newline();
|
||||
multiline = true;
|
||||
|
||||
index += 1;
|
||||
while index < length {
|
||||
@ -560,7 +543,6 @@ fn eat_line_comment<'a>(
|
||||
}
|
||||
b'\n' => {
|
||||
state = state.advance_newline();
|
||||
multiline = true;
|
||||
comments_and_newlines.push(CommentOrNewline::Newline);
|
||||
}
|
||||
b'\r' => {
|
||||
@ -580,7 +562,6 @@ fn eat_line_comment<'a>(
|
||||
|
||||
return SpaceState {
|
||||
state,
|
||||
multiline,
|
||||
comments_and_newlines,
|
||||
};
|
||||
}
|
||||
@ -606,7 +587,6 @@ fn eat_line_comment<'a>(
|
||||
|
||||
return SpaceState {
|
||||
state,
|
||||
multiline,
|
||||
comments_and_newlines,
|
||||
};
|
||||
}
|
||||
|
@ -1992,9 +1992,10 @@ mod when {
|
||||
/// Parsing when with indentation.
|
||||
fn when_with_indent<'a>() -> impl Parser<'a, u32, EWhen<'a>> {
|
||||
move |arena, state: State<'a>| {
|
||||
let min_indent = state.column();
|
||||
parser::keyword_e(keyword::WHEN, EWhen::When)
|
||||
.parse(arena, state)
|
||||
.map(|(progress, (), state)| (progress, state.indent_column, state))
|
||||
.map(|(progress, (), state)| (progress, min_indent, state))
|
||||
}
|
||||
}
|
||||
|
||||
@ -2003,14 +2004,12 @@ mod when {
|
||||
options: ExprParseOptions,
|
||||
) -> impl Parser<'a, Vec<'a, &'a WhenBranch<'a>>, EWhen<'a>> {
|
||||
move |arena, state: State<'a>| {
|
||||
let when_indent = state.indent_column;
|
||||
|
||||
let mut branches: Vec<'a, &'a WhenBranch<'a>> = Vec::with_capacity_in(2, arena);
|
||||
|
||||
// 1. Parse the first branch and get its indentation level. (It must be >= min_indent.)
|
||||
// 2. Parse the other branches. Their indentation levels must be == the first branch's.
|
||||
|
||||
let (_, ((pattern_indent_level, loc_first_patterns), loc_first_guard), mut state): (
|
||||
let (_, ((pattern_indent_level, loc_first_patterns), loc_first_guard), state): (
|
||||
_,
|
||||
((_, _), _),
|
||||
State<'a>,
|
||||
@ -2018,8 +2017,6 @@ mod when {
|
||||
|
||||
let original_indent = pattern_indent_level;
|
||||
|
||||
state.indent_column = 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)?;
|
||||
@ -2078,9 +2075,6 @@ mod when {
|
||||
}
|
||||
}
|
||||
|
||||
let mut state = state;
|
||||
state.indent_column = when_indent;
|
||||
|
||||
Ok((MadeProgress, branches, state))
|
||||
}
|
||||
}
|
||||
@ -2382,7 +2376,7 @@ where
|
||||
E: 'a,
|
||||
{
|
||||
move |arena, state: State<'a>| {
|
||||
let indent_column = state.indent_column;
|
||||
let indent_column = state.column();
|
||||
|
||||
let (progress, _, state) = parser.parse(arena, state)?;
|
||||
|
||||
|
@ -14,10 +14,6 @@ pub struct State<'a> {
|
||||
|
||||
/// Position of the start of the current line
|
||||
pub(crate) line_start: Position,
|
||||
|
||||
/// Current indentation level, in columns
|
||||
/// (so no indent is col 1 - this saves an arithmetic operation.)
|
||||
pub(crate) indent_column: u32,
|
||||
}
|
||||
|
||||
impl<'a> State<'a> {
|
||||
@ -26,7 +22,6 @@ impl<'a> State<'a> {
|
||||
original_bytes: bytes,
|
||||
offset: 0,
|
||||
line_start: Position::zero(),
|
||||
indent_column: 0,
|
||||
}
|
||||
}
|
||||
|
||||
@ -86,7 +81,6 @@ impl<'a> fmt::Debug for State<'a> {
|
||||
}
|
||||
|
||||
write!(f, "\n\t(offset): {:?},", self.pos())?;
|
||||
write!(f, "\n\tindent_column: {}", self.indent_column)?;
|
||||
write!(f, "\n}}")
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,57 @@
|
||||
Defs(
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@0-25,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 0),
|
||||
],
|
||||
spaces: [],
|
||||
type_defs: [],
|
||||
value_defs: [
|
||||
Body(
|
||||
@0-1 Identifier(
|
||||
"x",
|
||||
),
|
||||
@4-25 When(
|
||||
@9-10 Var {
|
||||
module_name: "",
|
||||
ident: "n",
|
||||
},
|
||||
[
|
||||
WhenBranch {
|
||||
patterns: [
|
||||
@19-20 SpaceBefore(
|
||||
NumLiteral(
|
||||
"0",
|
||||
),
|
||||
[
|
||||
Newline,
|
||||
],
|
||||
),
|
||||
],
|
||||
value: @24-25 Num(
|
||||
"0",
|
||||
),
|
||||
guard: None,
|
||||
},
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
},
|
||||
@26-28 SpaceBefore(
|
||||
Num(
|
||||
"42",
|
||||
),
|
||||
[
|
||||
Newline,
|
||||
],
|
||||
),
|
||||
)
|
@ -0,0 +1,3 @@
|
||||
x = when n is
|
||||
0 -> 0
|
||||
42
|
@ -0,0 +1,64 @@
|
||||
Defs(
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@0-43,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 0),
|
||||
],
|
||||
spaces: [],
|
||||
type_defs: [],
|
||||
value_defs: [
|
||||
Body(
|
||||
@0-4 Identifier(
|
||||
"func",
|
||||
),
|
||||
@7-43 Closure(
|
||||
[
|
||||
@8-9 Identifier(
|
||||
"x",
|
||||
),
|
||||
],
|
||||
@13-43 When(
|
||||
@18-19 Var {
|
||||
module_name: "",
|
||||
ident: "n",
|
||||
},
|
||||
[
|
||||
WhenBranch {
|
||||
patterns: [
|
||||
@37-38 SpaceBefore(
|
||||
NumLiteral(
|
||||
"0",
|
||||
),
|
||||
[
|
||||
Newline,
|
||||
],
|
||||
),
|
||||
],
|
||||
value: @42-43 Num(
|
||||
"0",
|
||||
),
|
||||
guard: None,
|
||||
},
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
},
|
||||
@44-46 SpaceBefore(
|
||||
Num(
|
||||
"42",
|
||||
),
|
||||
[
|
||||
Newline,
|
||||
],
|
||||
),
|
||||
)
|
@ -0,0 +1,3 @@
|
||||
func = \x -> when n is
|
||||
0 -> 0
|
||||
42
|
@ -122,18 +122,16 @@ mod test_parse {
|
||||
snapshot_tests! {
|
||||
fail/type_argument_no_arrow.expr,
|
||||
fail/type_double_comma.expr,
|
||||
pass/plus_if.expr,
|
||||
pass/list_closing_indent_not_enough.expr,
|
||||
pass/ability_single_line.expr,
|
||||
pass/ability_multi_line.expr,
|
||||
pass/ability_demand_signature_is_multiline.expr,
|
||||
pass/ability_multi_line.expr,
|
||||
pass/ability_single_line.expr,
|
||||
pass/ability_two_in_a_row.expr,
|
||||
pass/add_var_with_spaces.expr,
|
||||
pass/add_with_spaces.expr,
|
||||
pass/annotated_record_destructure.expr,
|
||||
pass/annotated_tag_destructure.expr,
|
||||
pass/apply_tag.expr,
|
||||
pass/apply_parenthetical_tag_args.expr,
|
||||
pass/apply_tag.expr,
|
||||
pass/apply_three_args.expr,
|
||||
pass/apply_two_args.expr,
|
||||
pass/apply_unary_negation.expr,
|
||||
@ -151,9 +149,8 @@ mod test_parse {
|
||||
pass/comment_with_non_ascii.expr,
|
||||
pass/destructure_tag_assignment.expr,
|
||||
pass/empty_app_header.header,
|
||||
pass/empty_interface_header.header,
|
||||
pass/empty_hosted_header.header,
|
||||
pass/nonempty_hosted_header.header,
|
||||
pass/empty_interface_header.header,
|
||||
pass/empty_list.expr,
|
||||
pass/empty_platform_header.header,
|
||||
pass/empty_record.expr,
|
||||
@ -161,7 +158,6 @@ mod test_parse {
|
||||
pass/equals_with_spaces.expr,
|
||||
pass/equals.expr,
|
||||
pass/expect.expr,
|
||||
pass/record_type_with_function.expr,
|
||||
pass/float_with_underscores.expr,
|
||||
pass/full_app_header_trailing_commas.header,
|
||||
pass/full_app_header.header,
|
||||
@ -171,9 +167,10 @@ mod test_parse {
|
||||
pass/if_def.expr,
|
||||
pass/int_with_underscore.expr,
|
||||
pass/interface_with_newline.header,
|
||||
pass/lowest_float.expr,
|
||||
pass/list_closing_indent_not_enough.expr,
|
||||
pass/list_closing_same_indent_no_trailing_comma.expr,
|
||||
pass/list_closing_same_indent_with_trailing_comma.expr,
|
||||
pass/lowest_float.expr,
|
||||
pass/lowest_int.expr,
|
||||
pass/malformed_ident_due_to_underscore.expr,
|
||||
pass/malformed_pattern_field_access.expr, // See https://github.com/rtfeldman/roc/issues/399
|
||||
@ -202,6 +199,7 @@ mod test_parse {
|
||||
pass/newline_before_sub.expr,
|
||||
pass/newline_inside_empty_list.expr,
|
||||
pass/newline_singleton_list.expr,
|
||||
pass/nonempty_hosted_header.header,
|
||||
pass/nonempty_platform_header.header,
|
||||
pass/not_docs.expr,
|
||||
pass/number_literal_suffixes.expr,
|
||||
@ -212,16 +210,16 @@ mod test_parse {
|
||||
pass/one_plus_two.expr,
|
||||
pass/one_spaced_def.expr,
|
||||
pass/opaque_has_abilities.expr,
|
||||
pass/opaque_reference_expr_with_arguments.expr,
|
||||
pass/opaque_reference_expr.expr,
|
||||
pass/opaque_reference_pattern_with_arguments.expr,
|
||||
pass/opaque_reference_pattern.expr,
|
||||
pass/opaque_simple.module,
|
||||
pass/opaque_with_type_arguments.module,
|
||||
pass/opaque_reference_expr.expr,
|
||||
pass/opaque_reference_expr_with_arguments.expr,
|
||||
pass/opaque_reference_pattern.expr,
|
||||
pass/opaque_reference_pattern_with_arguments.expr,
|
||||
pass/ops_with_newlines.expr,
|
||||
pass/outdented_app_with_record.expr,
|
||||
pass/outdented_list.expr,
|
||||
pass/outdented_record.expr,
|
||||
pass/outdented_app_with_record.expr,
|
||||
pass/packed_singleton_list.expr,
|
||||
pass/parenthetical_apply.expr,
|
||||
pass/parenthetical_basic_field.expr,
|
||||
@ -230,6 +228,7 @@ mod test_parse {
|
||||
pass/parse_alias.expr,
|
||||
pass/parse_as_ann.expr,
|
||||
pass/pattern_with_space_in_parens.expr, // https://github.com/rtfeldman/roc/issues/929
|
||||
pass/plus_if.expr,
|
||||
pass/pos_inf_float.expr,
|
||||
pass/positive_float.expr,
|
||||
pass/positive_int.expr,
|
||||
@ -239,6 +238,7 @@ mod test_parse {
|
||||
pass/qualified_var.expr,
|
||||
pass/record_destructure_def.expr,
|
||||
pass/record_func_type_decl.expr,
|
||||
pass/record_type_with_function.expr,
|
||||
pass/record_update.expr,
|
||||
pass/record_with_if.expr,
|
||||
pass/requires_type.header,
|
||||
@ -272,6 +272,8 @@ mod test_parse {
|
||||
pass/var_minus_two.expr,
|
||||
pass/var_then.expr,
|
||||
pass/var_when.expr,
|
||||
pass/when_in_assignment.expr,
|
||||
pass/when_in_function.expr,
|
||||
pass/when_if_guard.expr,
|
||||
pass/when_in_parens_indented.expr,
|
||||
pass/when_in_parens.expr,
|
||||
@ -281,9 +283,9 @@ mod test_parse {
|
||||
pass/when_with_numbers.expr,
|
||||
pass/when_with_records.expr,
|
||||
pass/where_clause_function.expr,
|
||||
pass/where_clause_non_function.expr,
|
||||
pass/where_clause_multiple_has.expr,
|
||||
pass/where_clause_multiple_has_across_newlines.expr,
|
||||
pass/where_clause_multiple_has.expr,
|
||||
pass/where_clause_non_function.expr,
|
||||
pass/where_clause_on_newline.expr,
|
||||
pass/zero_float.expr,
|
||||
pass/zero_int.expr,
|
||||
|
Loading…
Reference in New Issue
Block a user