mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 22:34:45 +00:00
Merge pull request #1155 from rtfeldman/outdent-parse-crash
Outdent parse crash
This commit is contained in:
commit
e4da63cc48
5 changed files with 207 additions and 66 deletions
|
@ -1,7 +1,7 @@
|
||||||
use crate::ast::CommentOrNewline;
|
use crate::ast::CommentOrNewline;
|
||||||
use crate::ast::Spaceable;
|
use crate::ast::Spaceable;
|
||||||
use crate::parser::{
|
use crate::parser::{
|
||||||
self, and, BadInputError, Col, Parser,
|
self, and, backtrackable, BadInputError, Col, Parser,
|
||||||
Progress::{self, *},
|
Progress::{self, *},
|
||||||
Row, State,
|
Row, State,
|
||||||
};
|
};
|
||||||
|
@ -31,11 +31,50 @@ where
|
||||||
space0_e(min_indent, space_problem, indent_after_problem),
|
space0_e(min_indent, space_problem, indent_after_problem),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
move |arena: &'a Bump,
|
spaces_around_help,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn space0_before_optional_after<'a, P, S, E>(
|
||||||
|
parser: P,
|
||||||
|
min_indent: u16,
|
||||||
|
space_problem: fn(BadInputError, Row, Col) -> E,
|
||||||
|
indent_before_problem: fn(Row, Col) -> E,
|
||||||
|
indent_after_problem: fn(Row, Col) -> E,
|
||||||
|
) -> impl Parser<'a, Located<S>, E>
|
||||||
|
where
|
||||||
|
S: Spaceable<'a>,
|
||||||
|
S: 'a,
|
||||||
|
P: Parser<'a, Located<S>, E>,
|
||||||
|
P: 'a,
|
||||||
|
E: 'a,
|
||||||
|
{
|
||||||
|
parser::map_with_arena(
|
||||||
|
and(
|
||||||
|
space0_e(min_indent, space_problem, indent_before_problem),
|
||||||
|
and(
|
||||||
|
parser,
|
||||||
|
one_of![
|
||||||
|
backtrackable(space0_e(min_indent, space_problem, indent_after_problem)),
|
||||||
|
succeed!(&[] as &[_]),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
spaces_around_help,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn spaces_around_help<'a, S>(
|
||||||
|
arena: &'a Bump,
|
||||||
tuples: (
|
tuples: (
|
||||||
&'a [CommentOrNewline<'a>],
|
&'a [CommentOrNewline<'a>],
|
||||||
(Located<S>, &'a [CommentOrNewline<'a>]),
|
(Located<S>, &'a [CommentOrNewline<'a>]),
|
||||||
)| {
|
),
|
||||||
|
) -> Located<S>
|
||||||
|
where
|
||||||
|
S: Spaceable<'a>,
|
||||||
|
S: 'a,
|
||||||
|
{
|
||||||
let (spaces_before, (loc_val, spaces_after)) = tuples;
|
let (spaces_before, (loc_val, spaces_after)) = tuples;
|
||||||
|
|
||||||
if spaces_before.is_empty() {
|
if spaces_before.is_empty() {
|
||||||
|
@ -59,8 +98,6 @@ where
|
||||||
.alloc(wrapped_expr.value)
|
.alloc(wrapped_expr.value)
|
||||||
.with_spaces_before(spaces_before, wrapped_expr.region)
|
.with_spaces_before(spaces_before, wrapped_expr.region)
|
||||||
}
|
}
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn space0_before_e<'a, P, S, E>(
|
pub fn space0_before_e<'a, P, S, E>(
|
||||||
|
|
|
@ -1273,7 +1273,7 @@ macro_rules! collection_trailing_sep_e {
|
||||||
and!(
|
and!(
|
||||||
$crate::parser::trailing_sep_by0(
|
$crate::parser::trailing_sep_by0(
|
||||||
$delimiter,
|
$delimiter,
|
||||||
$crate::blankspace::space0_around_ee(
|
$crate::blankspace::space0_before_optional_after(
|
||||||
$elem,
|
$elem,
|
||||||
$min_indent,
|
$min_indent,
|
||||||
$space_problem,
|
$space_problem,
|
||||||
|
@ -1299,6 +1299,15 @@ macro_rules! collection_trailing_sep_e {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! succeed {
|
||||||
|
($value:expr) => {
|
||||||
|
move |_arena: &'a bumpalo::Bump, state: $crate::parser::State<'a>| {
|
||||||
|
Ok((NoProgress, $value, state))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! and {
|
macro_rules! and {
|
||||||
($p1:expr, $p2:expr) => {
|
($p1:expr, $p2:expr) => {
|
||||||
|
|
|
@ -147,7 +147,7 @@ fn loc_type_in_parens<'a>(
|
||||||
TInParens::IndentOpen,
|
TInParens::IndentOpen,
|
||||||
TInParens::IndentEnd,
|
TInParens::IndentEnd,
|
||||||
),
|
),
|
||||||
word1(b')', TInParens::End)
|
word1(b')', TInParens::IndentEnd)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1750,7 +1750,7 @@ fn to_precord_report<'a>(
|
||||||
}
|
}
|
||||||
|
|
||||||
PRecord::IndentEnd(row, col) => {
|
PRecord::IndentEnd(row, col) => {
|
||||||
match next_line_starts_with_close_curly(alloc.src_lines, row.saturating_sub(1)) {
|
match next_line_starts_with_close_curly(alloc.src_lines, row) {
|
||||||
Some((curly_row, curly_col)) => {
|
Some((curly_row, curly_col)) => {
|
||||||
let surroundings =
|
let surroundings =
|
||||||
Region::from_rows_cols(start_row, start_col, curly_row, curly_col);
|
Region::from_rows_cols(start_row, start_col, curly_row, curly_col);
|
||||||
|
@ -1895,7 +1895,7 @@ fn to_pattern_in_parens_report<'a>(
|
||||||
}
|
}
|
||||||
|
|
||||||
PInParens::IndentEnd(row, col) => {
|
PInParens::IndentEnd(row, col) => {
|
||||||
match next_line_starts_with_close_parenthesis(alloc.src_lines, row.saturating_sub(1)) {
|
match next_line_starts_with_close_parenthesis(alloc.src_lines, row) {
|
||||||
Some((curly_row, curly_col)) => {
|
Some((curly_row, curly_col)) => {
|
||||||
let surroundings =
|
let surroundings =
|
||||||
Region::from_rows_cols(start_row, start_col, curly_row, curly_col);
|
Region::from_rows_cols(start_row, start_col, curly_row, curly_col);
|
||||||
|
@ -2257,7 +2257,7 @@ fn to_trecord_report<'a>(
|
||||||
}
|
}
|
||||||
|
|
||||||
TRecord::IndentEnd(row, col) => {
|
TRecord::IndentEnd(row, col) => {
|
||||||
match next_line_starts_with_close_curly(alloc.src_lines, row.saturating_sub(1)) {
|
match next_line_starts_with_close_curly(alloc.src_lines, row) {
|
||||||
Some((curly_row, curly_col)) => {
|
Some((curly_row, curly_col)) => {
|
||||||
let surroundings =
|
let surroundings =
|
||||||
Region::from_rows_cols(start_row, start_col, curly_row, curly_col);
|
Region::from_rows_cols(start_row, start_col, curly_row, curly_col);
|
||||||
|
@ -2478,7 +2478,7 @@ fn to_ttag_union_report<'a>(
|
||||||
}
|
}
|
||||||
|
|
||||||
TTagUnion::IndentEnd(row, col) => {
|
TTagUnion::IndentEnd(row, col) => {
|
||||||
match next_line_starts_with_close_square_bracket(alloc.src_lines, row - 1) {
|
match next_line_starts_with_close_square_bracket(alloc.src_lines, row) {
|
||||||
Some((curly_row, curly_col)) => {
|
Some((curly_row, curly_col)) => {
|
||||||
let surroundings =
|
let surroundings =
|
||||||
Region::from_rows_cols(start_row, start_col, curly_row, curly_col);
|
Region::from_rows_cols(start_row, start_col, curly_row, curly_col);
|
||||||
|
@ -2682,7 +2682,7 @@ fn to_tinparens_report<'a>(
|
||||||
}
|
}
|
||||||
|
|
||||||
TInParens::IndentEnd(row, col) => {
|
TInParens::IndentEnd(row, col) => {
|
||||||
match next_line_starts_with_close_square_bracket(alloc.src_lines, row - 1) {
|
match next_line_starts_with_close_parenthesis(alloc.src_lines, row) {
|
||||||
Some((curly_row, curly_col)) => {
|
Some((curly_row, curly_col)) => {
|
||||||
let surroundings =
|
let surroundings =
|
||||||
Region::from_rows_cols(start_row, start_col, curly_row, curly_col);
|
Region::from_rows_cols(start_row, start_col, curly_row, curly_col);
|
||||||
|
@ -2694,7 +2694,7 @@ fn to_tinparens_report<'a>(
|
||||||
),
|
),
|
||||||
alloc.region_with_subregion(surroundings, region),
|
alloc.region_with_subregion(surroundings, region),
|
||||||
alloc.concat(vec![
|
alloc.concat(vec![
|
||||||
alloc.reflow("I need this square bracket to be indented more. Try adding more spaces before it!"),
|
alloc.reflow("I need this parenthesis to be indented more. Try adding more spaces before it!"),
|
||||||
]),
|
]),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
@ -2714,9 +2714,9 @@ fn to_tinparens_report<'a>(
|
||||||
),
|
),
|
||||||
alloc.region_with_subregion(surroundings, region),
|
alloc.region_with_subregion(surroundings, region),
|
||||||
alloc.concat(vec![
|
alloc.concat(vec![
|
||||||
alloc.reflow("I was expecting to see a closing square "),
|
alloc.reflow("I was expecting to see a parenthesis "),
|
||||||
alloc.reflow("bracket before this, so try adding a "),
|
alloc.reflow("before this, so try adding a "),
|
||||||
alloc.parser_suggestion("]"),
|
alloc.parser_suggestion(")"),
|
||||||
alloc.reflow(" and see if that helps?"),
|
alloc.reflow(" and see if that helps?"),
|
||||||
]),
|
]),
|
||||||
note_for_tag_union_type_indent(alloc),
|
note_for_tag_union_type_indent(alloc),
|
||||||
|
|
|
@ -4533,8 +4533,10 @@ mod test_reporting {
|
||||||
1│ f : ( I64
|
1│ f : ( I64
|
||||||
^
|
^
|
||||||
|
|
||||||
I was expecting to see a closing parenthesis before this, so try
|
I was expecting to see a parenthesis before this, so try adding a )
|
||||||
adding a ) and see if that helps?
|
and see if that helps?
|
||||||
|
|
||||||
|
Note: I may be confused by indentation
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
@ -6208,4 +6210,97 @@ mod test_reporting {
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn outdented_alias() {
|
||||||
|
report_problem_as(
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
Box item : [
|
||||||
|
Box item,
|
||||||
|
Items item item
|
||||||
|
]
|
||||||
|
|
||||||
|
4
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
── NEED MORE INDENTATION ───────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
I am partway through parsing a tag union type, but I got stuck here:
|
||||||
|
|
||||||
|
1│ Box item : [
|
||||||
|
2│ Box item,
|
||||||
|
3│ Items item item
|
||||||
|
4│ ]
|
||||||
|
^
|
||||||
|
|
||||||
|
I need this square bracket to be indented more. Try adding more spaces
|
||||||
|
before it!
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn outdented_in_parens() {
|
||||||
|
report_problem_as(
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
Box : (
|
||||||
|
Str
|
||||||
|
)
|
||||||
|
|
||||||
|
4
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
── NEED MORE INDENTATION ───────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
I am partway through parsing a type in parentheses, but I got stuck
|
||||||
|
here:
|
||||||
|
|
||||||
|
1│ Box : (
|
||||||
|
2│ Str
|
||||||
|
3│ )
|
||||||
|
^
|
||||||
|
|
||||||
|
I need this parenthesis to be indented more. Try adding more spaces
|
||||||
|
before it!
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn outdented_record() {
|
||||||
|
report_problem_as(
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
Box : {
|
||||||
|
id: Str
|
||||||
|
}
|
||||||
|
|
||||||
|
4
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
── NEED MORE INDENTATION ───────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
I am partway through parsing a record type, but I got stuck here:
|
||||||
|
|
||||||
|
1│ Box : {
|
||||||
|
2│ id: Str
|
||||||
|
3│ }
|
||||||
|
^
|
||||||
|
|
||||||
|
I need this curly brace to be indented more. Try adding more spaces
|
||||||
|
before it!
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue