mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-03 03:42:17 +00:00
Merge pull request #4414 from roc-lang/i4412
Parse and format list patterns
This commit is contained in:
commit
67a8bbd6a2
13 changed files with 621 additions and 11 deletions
|
@ -447,6 +447,9 @@ pub fn to_pattern2<'a>(
|
|||
unreachable!("should have been handled in RecordDestructure");
|
||||
}
|
||||
|
||||
List(..) => todo!(),
|
||||
ListRest => todo!(),
|
||||
|
||||
Malformed(_str) => {
|
||||
let problem = MalformedPatternProblem::Unknown;
|
||||
malformed_pattern(env, problem, region)
|
||||
|
|
|
@ -621,6 +621,9 @@ pub fn canonicalize_pattern<'a>(
|
|||
unreachable!("should have been handled in RecordDestructure");
|
||||
}
|
||||
|
||||
List(..) => todo!(),
|
||||
ListRest => todo!(),
|
||||
|
||||
Malformed(_str) => {
|
||||
let problem = MalformedPatternProblem::Unknown;
|
||||
malformed_pattern(env, problem, region)
|
||||
|
|
|
@ -40,7 +40,10 @@ impl<'a> Formattable for Pattern<'a> {
|
|||
| Pattern::Underscore(_)
|
||||
| Pattern::Malformed(_)
|
||||
| Pattern::MalformedIdent(_, _)
|
||||
| Pattern::QualifiedIdentifier { .. } => false,
|
||||
| Pattern::QualifiedIdentifier { .. }
|
||||
| Pattern::ListRest => false,
|
||||
|
||||
Pattern::List(patterns) => patterns.iter().any(|p| p.is_multiline()),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -158,6 +161,26 @@ impl<'a> Formattable for Pattern<'a> {
|
|||
buf.push('_');
|
||||
buf.push_str(name);
|
||||
}
|
||||
List(loc_patterns) => {
|
||||
buf.indent(indent);
|
||||
buf.push_str("[");
|
||||
|
||||
let mut it = loc_patterns.iter().peekable();
|
||||
while let Some(loc_pattern) = it.next() {
|
||||
loc_pattern.format(buf, indent);
|
||||
|
||||
if it.peek().is_some() {
|
||||
buf.push_str(",");
|
||||
buf.spaces(1);
|
||||
}
|
||||
}
|
||||
|
||||
buf.push_str("]");
|
||||
}
|
||||
ListRest => {
|
||||
buf.indent(indent);
|
||||
buf.push_str("..");
|
||||
}
|
||||
|
||||
// Space
|
||||
SpaceBefore(sub_pattern, spaces) => {
|
||||
|
|
|
@ -748,7 +748,9 @@ impl<'a> RemoveSpaces<'a> for Pattern<'a> {
|
|||
}
|
||||
Pattern::SpaceBefore(a, _) => a.remove_spaces(arena),
|
||||
Pattern::SpaceAfter(a, _) => a.remove_spaces(arena),
|
||||
Pattern::SingleQuote(a) => Pattern::NumLiteral(a),
|
||||
Pattern::SingleQuote(a) => Pattern::SingleQuote(a),
|
||||
Pattern::List(pats) => Pattern::List(pats.remove_spaces(arena)),
|
||||
Pattern::ListRest => Pattern::ListRest,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5738,6 +5738,65 @@ mod test_fmt {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn format_list_patterns() {
|
||||
expr_formats_same(indoc!(
|
||||
r#"
|
||||
when [] is
|
||||
[] -> []
|
||||
"#
|
||||
));
|
||||
|
||||
expr_formats_to(
|
||||
indoc!(
|
||||
r#"
|
||||
when [] is
|
||||
[ ] -> []
|
||||
"#
|
||||
),
|
||||
indoc!(
|
||||
r#"
|
||||
when [] is
|
||||
[] -> []
|
||||
"#
|
||||
),
|
||||
);
|
||||
|
||||
expr_formats_to(
|
||||
indoc!(
|
||||
r#"
|
||||
when [] is
|
||||
[ x, .. , A 5 6, .. ] -> []
|
||||
"#
|
||||
),
|
||||
indoc!(
|
||||
r#"
|
||||
when [] is
|
||||
[x, .., A 5 6, ..] -> []
|
||||
"#
|
||||
),
|
||||
);
|
||||
|
||||
expr_formats_to(
|
||||
indoc!(
|
||||
r#"
|
||||
when [] is
|
||||
[ x, 4, 5 ] -> []
|
||||
[ .., 5 ] -> []
|
||||
[ x, .. ] -> []
|
||||
"#
|
||||
),
|
||||
indoc!(
|
||||
r#"
|
||||
when [] is
|
||||
[x, 4, 5] -> []
|
||||
[.., 5] -> []
|
||||
[x, ..] -> []
|
||||
"#
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// this is a parse error atm
|
||||
// #[test]
|
||||
// fn multiline_apply() {
|
||||
|
|
|
@ -653,6 +653,13 @@ pub enum Pattern<'a> {
|
|||
Underscore(&'a str),
|
||||
SingleQuote(&'a str),
|
||||
|
||||
/// A list pattern like [_, x, ..]
|
||||
List(Collection<'a, Loc<Pattern<'a>>>),
|
||||
|
||||
/// A list-rest pattern ".."
|
||||
/// Can only occur inside of a [Pattern::List]
|
||||
ListRest,
|
||||
|
||||
// Space
|
||||
SpaceBefore(&'a Pattern<'a>, &'a [CommentOrNewline<'a>]),
|
||||
SpaceAfter(&'a Pattern<'a>, &'a [CommentOrNewline<'a>]),
|
||||
|
|
|
@ -107,7 +107,8 @@ impl_space_problem! {
|
|||
EWhen<'a>,
|
||||
EAbility<'a>,
|
||||
PInParens<'a>,
|
||||
PRecord<'a>
|
||||
PRecord<'a>,
|
||||
PList<'a>
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
|
@ -519,6 +520,7 @@ pub enum EExpect<'a> {
|
|||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum EPattern<'a> {
|
||||
Record(PRecord<'a>, Position),
|
||||
List(PList<'a>, Position),
|
||||
Underscore(Position),
|
||||
|
||||
Start(Position),
|
||||
|
@ -553,6 +555,20 @@ pub enum PRecord<'a> {
|
|||
IndentEnd(Position),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum PList<'a> {
|
||||
End(Position),
|
||||
Open(Position),
|
||||
|
||||
Rest(Position),
|
||||
Pattern(&'a EPattern<'a>, Position),
|
||||
|
||||
Space(BadInputError, Position),
|
||||
|
||||
IndentOpen(Position),
|
||||
IndentEnd(Position),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum PInParens<'a> {
|
||||
End(Position),
|
||||
|
|
|
@ -3,8 +3,8 @@ use crate::blankspace::{space0_around_ee, space0_before_e, space0_e};
|
|||
use crate::ident::{lowercase_ident, parse_ident, Ident};
|
||||
use crate::parser::Progress::{self, *};
|
||||
use crate::parser::{
|
||||
backtrackable, optional, specialize, specialize_ref, then, word1, EPattern, PInParens, PRecord,
|
||||
ParseResult, Parser,
|
||||
backtrackable, optional, specialize, specialize_ref, then, word1, word2, word3, EPattern,
|
||||
PInParens, PList, PRecord, ParseResult, Parser,
|
||||
};
|
||||
use crate::state::State;
|
||||
use bumpalo::collections::string::String;
|
||||
|
@ -59,6 +59,7 @@ pub fn loc_pattern_help<'a>(min_indent: u32) -> impl Parser<'a, Loc<Pattern<'a>>
|
|||
EPattern::Record,
|
||||
crate::pattern::record_pattern_help(min_indent)
|
||||
)),
|
||||
loc!(specialize(EPattern::List, list_pattern_help(min_indent))),
|
||||
loc!(number_pattern_help()),
|
||||
loc!(string_pattern_help()),
|
||||
loc!(single_quote_pattern_help()),
|
||||
|
@ -202,6 +203,49 @@ fn single_quote_pattern_help<'a>() -> impl Parser<'a, Pattern<'a>, EPattern<'a>>
|
|||
)
|
||||
}
|
||||
|
||||
fn list_pattern_help<'a>(min_indent: u32) -> impl Parser<'a, Pattern<'a>, PList<'a>> {
|
||||
move |arena, state| {
|
||||
let (_, pats, state) = collection_trailing_sep_e!(
|
||||
word1(b'[', PList::Open),
|
||||
list_element_pattern(min_indent),
|
||||
word1(b',', PList::End),
|
||||
word1(b']', PList::End),
|
||||
min_indent,
|
||||
PList::Open,
|
||||
PList::IndentEnd,
|
||||
Pattern::SpaceBefore
|
||||
)
|
||||
.parse(arena, state)?;
|
||||
|
||||
let result = Pattern::List(pats);
|
||||
|
||||
Ok((MadeProgress, result, state))
|
||||
}
|
||||
}
|
||||
|
||||
fn list_element_pattern<'a>(min_indent: u32) -> impl Parser<'a, Loc<Pattern<'a>>, PList<'a>> {
|
||||
one_of!(
|
||||
three_list_rest_pattern_error(),
|
||||
list_rest_pattern(),
|
||||
specialize_ref(PList::Pattern, loc_pattern_help(min_indent)),
|
||||
)
|
||||
}
|
||||
|
||||
fn three_list_rest_pattern_error<'a>() -> impl Parser<'a, Loc<Pattern<'a>>, PList<'a>> {
|
||||
then(
|
||||
loc!(word3(b'.', b'.', b'.', PList::Rest)),
|
||||
|_arena, state, _progress, word| {
|
||||
Err((MadeProgress, PList::Rest(word.region.start()), state))
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
fn list_rest_pattern<'a>() -> impl Parser<'a, Loc<Pattern<'a>>, PList<'a>> {
|
||||
map!(loc!(word2(b'.', b'.', PList::Open)), |loc_word: Loc<_>| {
|
||||
loc_word.map(|_| Pattern::ListRest)
|
||||
})
|
||||
}
|
||||
|
||||
fn loc_ident_pattern_help<'a>(
|
||||
min_indent: u32,
|
||||
can_have_arguments: bool,
|
||||
|
@ -354,11 +398,9 @@ fn lowercase_ident_pattern<'a>(
|
|||
fn record_pattern_help<'a>(min_indent: u32) -> impl Parser<'a, Pattern<'a>, PRecord<'a>> {
|
||||
move |arena, state| {
|
||||
let (_, fields, state) = collection_trailing_sep_e!(
|
||||
// word1_check_indent!(b'{', PRecord::Open, min_indent, PRecord::IndentOpen),
|
||||
word1(b'{', PRecord::Open),
|
||||
record_pattern_field(min_indent),
|
||||
word1(b',', PRecord::End),
|
||||
// word1_check_indent!(b'}', PRecord::End, min_indent, PRecord::IndentEnd),
|
||||
word1(b'}', PRecord::End),
|
||||
min_indent,
|
||||
PRecord::Open,
|
||||
|
|
|
@ -0,0 +1,216 @@
|
|||
When(
|
||||
@5-7 List(
|
||||
[],
|
||||
),
|
||||
[
|
||||
WhenBranch {
|
||||
patterns: [
|
||||
@13-15 SpaceBefore(
|
||||
List(
|
||||
[],
|
||||
),
|
||||
[
|
||||
Newline,
|
||||
],
|
||||
),
|
||||
],
|
||||
value: @19-21 Record(
|
||||
[],
|
||||
),
|
||||
guard: None,
|
||||
},
|
||||
WhenBranch {
|
||||
patterns: [
|
||||
@24-28 SpaceBefore(
|
||||
List(
|
||||
[
|
||||
@25-27 ListRest,
|
||||
],
|
||||
),
|
||||
[
|
||||
Newline,
|
||||
],
|
||||
),
|
||||
],
|
||||
value: @32-34 Record(
|
||||
[],
|
||||
),
|
||||
guard: None,
|
||||
},
|
||||
WhenBranch {
|
||||
patterns: [
|
||||
@37-51 SpaceBefore(
|
||||
List(
|
||||
[
|
||||
@38-39 Underscore(
|
||||
"",
|
||||
),
|
||||
@41-43 ListRest,
|
||||
@45-46 Underscore(
|
||||
"",
|
||||
),
|
||||
@48-50 ListRest,
|
||||
],
|
||||
),
|
||||
[
|
||||
Newline,
|
||||
],
|
||||
),
|
||||
],
|
||||
value: @55-57 Record(
|
||||
[],
|
||||
),
|
||||
guard: None,
|
||||
},
|
||||
WhenBranch {
|
||||
patterns: [
|
||||
@60-72 SpaceBefore(
|
||||
List(
|
||||
[
|
||||
@61-62 Identifier(
|
||||
"a",
|
||||
),
|
||||
@64-65 Identifier(
|
||||
"b",
|
||||
),
|
||||
@67-68 Identifier(
|
||||
"c",
|
||||
),
|
||||
@70-71 Identifier(
|
||||
"d",
|
||||
),
|
||||
],
|
||||
),
|
||||
[
|
||||
Newline,
|
||||
],
|
||||
),
|
||||
],
|
||||
value: @76-78 Record(
|
||||
[],
|
||||
),
|
||||
guard: None,
|
||||
},
|
||||
WhenBranch {
|
||||
patterns: [
|
||||
@81-91 SpaceBefore(
|
||||
List(
|
||||
[
|
||||
@82-83 Identifier(
|
||||
"a",
|
||||
),
|
||||
@85-86 Identifier(
|
||||
"b",
|
||||
),
|
||||
@88-90 ListRest,
|
||||
],
|
||||
),
|
||||
[
|
||||
Newline,
|
||||
],
|
||||
),
|
||||
],
|
||||
value: @95-97 Record(
|
||||
[],
|
||||
),
|
||||
guard: None,
|
||||
},
|
||||
WhenBranch {
|
||||
patterns: [
|
||||
@100-110 SpaceBefore(
|
||||
List(
|
||||
[
|
||||
@101-103 ListRest,
|
||||
@105-106 Identifier(
|
||||
"c",
|
||||
),
|
||||
@108-109 Identifier(
|
||||
"d",
|
||||
),
|
||||
],
|
||||
),
|
||||
[
|
||||
Newline,
|
||||
],
|
||||
),
|
||||
],
|
||||
value: @114-116 Record(
|
||||
[],
|
||||
),
|
||||
guard: None,
|
||||
},
|
||||
WhenBranch {
|
||||
patterns: [
|
||||
@119-135 SpaceBefore(
|
||||
List(
|
||||
[
|
||||
@120-123 List(
|
||||
[
|
||||
@121-122 Tag(
|
||||
"A",
|
||||
),
|
||||
],
|
||||
),
|
||||
@125-129 List(
|
||||
[
|
||||
@126-128 ListRest,
|
||||
],
|
||||
),
|
||||
@131-134 List(
|
||||
[
|
||||
@132-133 Identifier(
|
||||
"a",
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
[
|
||||
Newline,
|
||||
],
|
||||
),
|
||||
],
|
||||
value: @139-141 Record(
|
||||
[],
|
||||
),
|
||||
guard: None,
|
||||
},
|
||||
WhenBranch {
|
||||
patterns: [
|
||||
@144-163 SpaceBefore(
|
||||
List(
|
||||
[
|
||||
@145-153 List(
|
||||
[
|
||||
@146-148 List(
|
||||
[],
|
||||
),
|
||||
@150-152 List(
|
||||
[],
|
||||
),
|
||||
],
|
||||
),
|
||||
@155-162 List(
|
||||
[
|
||||
@156-158 List(
|
||||
[],
|
||||
),
|
||||
@160-161 Identifier(
|
||||
"x",
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
[
|
||||
Newline,
|
||||
],
|
||||
),
|
||||
],
|
||||
value: @167-169 Record(
|
||||
[],
|
||||
),
|
||||
guard: None,
|
||||
},
|
||||
],
|
||||
)
|
|
@ -0,0 +1,9 @@
|
|||
when [] is
|
||||
[] -> {}
|
||||
[..] -> {}
|
||||
[_, .., _, ..] -> {}
|
||||
[a, b, c, d] -> {}
|
||||
[a, b, ..] -> {}
|
||||
[.., c, d] -> {}
|
||||
[[A], [..], [a]] -> {}
|
||||
[[[], []], [[], x]] -> {}
|
|
@ -175,6 +175,7 @@ mod test_parse {
|
|||
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/list_patterns.expr,
|
||||
pass/lowest_float.expr,
|
||||
pass/lowest_int.expr,
|
||||
pass/malformed_ident_due_to_underscore.expr,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use roc_parse::parser::{ENumber, FileError, SyntaxError};
|
||||
use roc_parse::parser::{ENumber, FileError, PList, SyntaxError};
|
||||
use roc_region::all::{LineColumn, LineColumnRegion, LineInfo, Position, Region};
|
||||
use std::path::PathBuf;
|
||||
|
||||
|
@ -23,6 +23,10 @@ fn note_for_record_pattern_indent<'a>(alloc: &'a RocDocAllocator<'a>) -> RocDocB
|
|||
alloc.note("I may be confused by indentation")
|
||||
}
|
||||
|
||||
fn note_for_list_pattern_indent<'a>(alloc: &'a RocDocAllocator<'a>) -> RocDocBuilder<'a> {
|
||||
alloc.note("I may be confused by indentation")
|
||||
}
|
||||
|
||||
fn note_for_tag_union_type_indent<'a>(alloc: &'a RocDocAllocator<'a>) -> RocDocBuilder<'a> {
|
||||
alloc.note("I may be confused by indentation")
|
||||
}
|
||||
|
@ -46,6 +50,15 @@ fn record_patterns_look_like<'a>(alloc: &'a RocDocAllocator<'a>) -> RocDocBuilde
|
|||
])
|
||||
}
|
||||
|
||||
fn list_patterns_look_like<'a>(alloc: &'a RocDocAllocator<'a>) -> RocDocBuilder<'a> {
|
||||
alloc.concat([
|
||||
alloc.reflow(r"Record pattern look like "),
|
||||
alloc.parser_suggestion("[1, 2, ..]"),
|
||||
alloc.reflow(" or "),
|
||||
alloc.parser_suggestion("[first, .., last]"),
|
||||
])
|
||||
}
|
||||
|
||||
fn to_syntax_report<'a>(
|
||||
alloc: &'a RocDocAllocator<'a>,
|
||||
lines: &LineInfo,
|
||||
|
@ -1595,6 +1608,7 @@ fn to_pattern_report<'a>(
|
|||
}
|
||||
}
|
||||
EPattern::Record(record, pos) => to_precord_report(alloc, lines, filename, record, *pos),
|
||||
EPattern::List(list, pos) => to_plist_report(alloc, lines, filename, list, *pos),
|
||||
EPattern::PInParens(inparens, pos) => {
|
||||
to_pattern_in_parens_report(alloc, lines, filename, inparens, *pos)
|
||||
}
|
||||
|
@ -1855,6 +1869,155 @@ fn to_precord_report<'a>(
|
|||
}
|
||||
}
|
||||
|
||||
fn to_plist_report<'a>(
|
||||
alloc: &'a RocDocAllocator<'a>,
|
||||
lines: &LineInfo,
|
||||
filename: PathBuf,
|
||||
parse_problem: &PList<'a>,
|
||||
start: Position,
|
||||
) -> Report<'a> {
|
||||
match *parse_problem {
|
||||
PList::Open(pos) => {
|
||||
let surroundings = Region::new(start, pos);
|
||||
let region = LineColumnRegion::from_pos(lines.convert_pos(pos));
|
||||
|
||||
let doc = alloc.stack([
|
||||
alloc.reflow(r"I just started parsing a list pattern, but I got stuck here:"),
|
||||
alloc.region_with_subregion(lines.convert_region(surroundings), region),
|
||||
list_patterns_look_like(alloc),
|
||||
]);
|
||||
|
||||
Report {
|
||||
filename,
|
||||
doc,
|
||||
title: "UNFINISHED LIST PATTERN".to_string(),
|
||||
severity: Severity::RuntimeError,
|
||||
}
|
||||
}
|
||||
|
||||
PList::End(pos) => {
|
||||
let surroundings = Region::new(start, pos);
|
||||
let region = LineColumnRegion::from_pos(lines.convert_pos(pos));
|
||||
let doc = alloc.stack([
|
||||
alloc.reflow("I am partway through parsing a list pattern, but I got stuck here:"),
|
||||
alloc.region_with_subregion(lines.convert_region(surroundings), region),
|
||||
alloc.concat([
|
||||
alloc.reflow(
|
||||
r"I was expecting to see a closing square brace before this, so try adding a ",
|
||||
),
|
||||
alloc.parser_suggestion("]"),
|
||||
alloc.reflow(" and see if that helps?"),
|
||||
])]);
|
||||
|
||||
Report {
|
||||
filename,
|
||||
doc,
|
||||
title: "UNFINISHED LIST PATTERN".to_string(),
|
||||
severity: Severity::RuntimeError,
|
||||
}
|
||||
}
|
||||
|
||||
PList::Rest(pos) => {
|
||||
let surroundings = Region::new(start, pos);
|
||||
let region = LineColumnRegion::from_pos(lines.convert_pos(pos));
|
||||
let doc = alloc.stack([
|
||||
alloc.reflow("It looks like you may trying to write a list rest pattern, but it's not the form I expect:"),
|
||||
alloc.region_with_subregion(lines.convert_region(surroundings), region),
|
||||
alloc.concat([
|
||||
alloc.reflow(
|
||||
r"List rest patterns, which match zero or more elements in a list, are denoted with ",
|
||||
),
|
||||
alloc.parser_suggestion(".."),
|
||||
alloc.reflow(" - is that what you meant?"),
|
||||
])]);
|
||||
|
||||
Report {
|
||||
filename,
|
||||
doc,
|
||||
title: "INCORRECT REST PATTERN".to_string(),
|
||||
severity: Severity::RuntimeError,
|
||||
}
|
||||
}
|
||||
|
||||
PList::Pattern(pattern, pos) => to_pattern_report(alloc, lines, filename, pattern, pos),
|
||||
|
||||
PList::IndentOpen(pos) => {
|
||||
let surroundings = Region::new(start, pos);
|
||||
let region = LineColumnRegion::from_pos(lines.convert_pos(pos));
|
||||
|
||||
let doc = alloc.stack([
|
||||
alloc.reflow(r"I just started parsing a list pattern, but I got stuck here:"),
|
||||
alloc.region_with_subregion(lines.convert_region(surroundings), region),
|
||||
record_patterns_look_like(alloc),
|
||||
note_for_list_pattern_indent(alloc),
|
||||
]);
|
||||
|
||||
Report {
|
||||
filename,
|
||||
doc,
|
||||
title: "UNFINISHED LIST PATTERN".to_string(),
|
||||
severity: Severity::RuntimeError,
|
||||
}
|
||||
}
|
||||
|
||||
PList::IndentEnd(pos) => {
|
||||
match next_line_starts_with_close_square_bracket(
|
||||
alloc.src_lines,
|
||||
lines.convert_pos(pos),
|
||||
) {
|
||||
Some(curly_pos) => {
|
||||
let surroundings = LineColumnRegion::new(lines.convert_pos(start), curly_pos);
|
||||
let region = LineColumnRegion::from_pos(curly_pos);
|
||||
|
||||
let doc = alloc.stack([
|
||||
alloc.reflow(
|
||||
"I am partway through parsing a list pattern, but I got stuck here:",
|
||||
),
|
||||
alloc.region_with_subregion(surroundings, region),
|
||||
alloc.concat([
|
||||
alloc.reflow("I need this square brace to be indented more. Try adding more spaces before it!"),
|
||||
]),
|
||||
]);
|
||||
|
||||
Report {
|
||||
filename,
|
||||
doc,
|
||||
title: "NEED MORE INDENTATION".to_string(),
|
||||
severity: Severity::RuntimeError,
|
||||
}
|
||||
}
|
||||
None => {
|
||||
let surroundings = Region::new(start, pos);
|
||||
let region = LineColumnRegion::from_pos(lines.convert_pos(pos));
|
||||
|
||||
let doc = alloc.stack([
|
||||
alloc.reflow(
|
||||
r"I am partway through parsing a list pattern, but I got stuck here:",
|
||||
),
|
||||
alloc.region_with_subregion(lines.convert_region(surroundings), region),
|
||||
alloc.concat([
|
||||
alloc.reflow("I was expecting to see a closing square "),
|
||||
alloc.reflow("brace before this, so try adding a "),
|
||||
alloc.parser_suggestion("]"),
|
||||
alloc.reflow(" and see if that helps?"),
|
||||
]),
|
||||
note_for_list_pattern_indent(alloc),
|
||||
]);
|
||||
|
||||
Report {
|
||||
filename,
|
||||
doc,
|
||||
title: "UNFINISHED LIST PATTERN".to_string(),
|
||||
severity: Severity::RuntimeError,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PList::Space(error, pos) => to_space_report(alloc, lines, filename, &error, pos),
|
||||
}
|
||||
}
|
||||
|
||||
fn to_pattern_in_parens_report<'a>(
|
||||
alloc: &'a RocDocAllocator<'a>,
|
||||
lines: &LineInfo,
|
||||
|
@ -1941,9 +2104,9 @@ fn to_pattern_in_parens_report<'a>(
|
|||
|
||||
PInParens::IndentEnd(pos) => {
|
||||
match next_line_starts_with_close_parenthesis(alloc.src_lines, lines.convert_pos(pos)) {
|
||||
Some(curly_pos) => {
|
||||
let surroundings = LineColumnRegion::new(lines.convert_pos(start), curly_pos);
|
||||
let region = LineColumnRegion::from_pos(curly_pos);
|
||||
Some(close_pos) => {
|
||||
let surroundings = LineColumnRegion::new(lines.convert_pos(start), close_pos);
|
||||
let region = LineColumnRegion::from_pos(close_pos);
|
||||
|
||||
let doc = alloc.stack([
|
||||
alloc.reflow(
|
||||
|
|
|
@ -11665,4 +11665,70 @@ All branches in an `if` must have the same type!
|
|||
clause of `x`.
|
||||
"###
|
||||
);
|
||||
|
||||
test_report!(
|
||||
list_pattern_not_terminated,
|
||||
indoc!(
|
||||
r#"
|
||||
when [] is
|
||||
[1, 2, -> ""
|
||||
"#
|
||||
),
|
||||
@r###"
|
||||
── UNFINISHED LIST PATTERN ────────── tmp/list_pattern_not_terminated/Test.roc ─
|
||||
|
||||
I am partway through parsing a list pattern, but I got stuck here:
|
||||
|
||||
5│ [1, 2, -> ""
|
||||
^
|
||||
|
||||
I was expecting to see a closing square brace before this, so try
|
||||
adding a ] and see if that helps?
|
||||
"###
|
||||
);
|
||||
|
||||
test_report!(
|
||||
list_pattern_weird_indent,
|
||||
indoc!(
|
||||
r#"
|
||||
when [] is
|
||||
[1, 2,
|
||||
3] -> ""
|
||||
"#
|
||||
),
|
||||
@r###"
|
||||
── UNFINISHED LIST PATTERN ──────────── tmp/list_pattern_weird_indent/Test.roc ─
|
||||
|
||||
I am partway through parsing a list pattern, but I got stuck here:
|
||||
|
||||
5│ [1, 2,
|
||||
6│ 3] -> ""
|
||||
^
|
||||
|
||||
I was expecting to see a closing square brace before this, so try
|
||||
adding a ] and see if that helps?
|
||||
"###
|
||||
);
|
||||
|
||||
test_report!(
|
||||
list_pattern_weird_rest_pattern,
|
||||
indoc!(
|
||||
r#"
|
||||
when [] is
|
||||
[...] -> ""
|
||||
"#
|
||||
),
|
||||
@r###"
|
||||
── INCORRECT REST PATTERN ─────── tmp/list_pattern_weird_rest_pattern/Test.roc ─
|
||||
|
||||
It looks like you may trying to write a list rest pattern, but it's
|
||||
not the form I expect:
|
||||
|
||||
5│ [...] -> ""
|
||||
^
|
||||
|
||||
List rest patterns, which match zero or more elements in a list, are
|
||||
denoted with .. - is that what you meant?
|
||||
"###
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue