Merge pull request #1155 from rtfeldman/outdent-parse-crash

Outdent parse crash
This commit is contained in:
Richard Feldman 2021-04-05 21:38:23 -04:00 committed by GitHub
commit e4da63cc48
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 207 additions and 66 deletions

View file

@ -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>(

View file

@ -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) => {

View file

@ -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)
) )
} }

View file

@ -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),

View file

@ -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!
"#
),
)
}
} }