diff --git a/crates/compiler/parse/src/module.rs b/crates/compiler/parse/src/module.rs index aea466ae9fb..1a1dd256277 100644 --- a/crates/compiler/parse/src/module.rs +++ b/crates/compiler/parse/src/module.rs @@ -221,7 +221,7 @@ fn provides_to_package<'a>() -> impl Parser<'a, To<'a>, EProvides<'a>> { |_, pos| EProvides::Identifier(pos), map!(lowercase_ident(), To::ExistingPackage) ), - specialize(EProvides::Package, map!(package_name(), To::NewPackage)) + specialize(EProvides::PackageName, map!(package_name(), To::NewPackage)) ] } diff --git a/crates/compiler/parse/src/parser.rs b/crates/compiler/parse/src/parser.rs index 385dea9f406..dc752a43302 100644 --- a/crates/compiler/parse/src/parser.rs +++ b/crates/compiler/parse/src/parser.rs @@ -145,7 +145,7 @@ pub enum EProvides<'a> { ListStart(Position), ListEnd(Position), Identifier(Position), - Package(EPackageName<'a>, Position), + PackageName(EPackageName<'a>, Position), Space(BadInputError, Position), } diff --git a/crates/compiler/test_syntax/tests/snapshots/fail/provides_bare_symbol.header.result-ast b/crates/compiler/test_syntax/tests/snapshots/fail/provides_bare_symbol.header.result-ast new file mode 100644 index 00000000000..282f1833c74 --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/fail/provides_bare_symbol.header.result-ast @@ -0,0 +1 @@ +Header(Imports(ListEnd(@89), @67)) \ No newline at end of file diff --git a/crates/compiler/test_syntax/tests/snapshots/fail/provides_bare_symbol.header.roc b/crates/compiler/test_syntax/tests/snapshots/fail/provides_bare_symbol.header.roc new file mode 100644 index 00000000000..32b260f4d49 --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/fail/provides_bare_symbol.header.roc @@ -0,0 +1,4 @@ +app "provides-bare-symbol" + packages { pf: "platform/main.roc" } + imports [pf.Task Base64] + provides main to pf diff --git a/crates/compiler/test_syntax/tests/test_snapshots.rs b/crates/compiler/test_syntax/tests/test_snapshots.rs index eb12ac3da7d..5c4d4d05584 100644 --- a/crates/compiler/test_syntax/tests/test_snapshots.rs +++ b/crates/compiler/test_syntax/tests/test_snapshots.rs @@ -136,7 +136,7 @@ mod test_snapshots { let kind = parts.next().unwrap(); println!("{:?} {:?} {:?}", pass_or_fail, test_name, kind); assert!(parts.next().is_none()); - assert!(kind == "expr" || kind == "moduledefs" || kind == "full"); + assert!(["expr", "moduledefs", "full", "header"].contains(&kind)); (pass_or_fail, test_name, kind) }; let line = format!(" {}/{}.{},", pass_or_fail, test_name, kind); @@ -217,6 +217,7 @@ mod test_snapshots { fail/pattern_in_parens_end_comma.expr, fail/pattern_in_parens_indent_open.expr, fail/pattern_in_parens_open.expr, + fail/provides_bare_symbol.header, fail/record_type_end.expr, fail/record_type_keyword_field_name.expr, fail/record_type_missing_comma.expr, @@ -341,6 +342,7 @@ mod test_snapshots { pass/multi_backpassing_in_def.moduledefs, pass/multi_backpassing_with_apply.expr, pass/multi_char_string.expr, + pass/multi_param_backpassing.moduledefs, pass/multiline_string.expr, pass/multiline_string_in_apply.expr, pass/multiline_tuple_with_comments.expr, diff --git a/crates/reporting/src/error/parse.rs b/crates/reporting/src/error/parse.rs index abf66192240..dd9da94be38 100644 --- a/crates/reporting/src/error/parse.rs +++ b/crates/reporting/src/error/parse.rs @@ -3444,8 +3444,7 @@ fn to_provides_report<'a>( use roc_parse::parser::EProvides; match *parse_problem { - EProvides::ListEnd(pos) | // TODO: give this its own error message - EProvides::Identifier(pos) => { + EProvides::ListEnd(pos) | EProvides::Open(pos) | EProvides::Identifier(pos) => { let surroundings = Region::new(start, pos); let region = LineColumnRegion::from_pos(lines.convert_pos(pos)); @@ -3496,6 +3495,51 @@ fn to_provides_report<'a>( EProvides::Space(error, pos) => to_space_report(alloc, lines, filename, &error, pos), + EProvides::ListStart(pos) => { + 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 header, but I got stuck here:"), + alloc.region_with_subregion(lines.convert_region(surroundings), region), + alloc.concat([ + alloc.reflow("I am expecting the "), + alloc.keyword("provides"), + alloc.reflow(" keyword next, like"), + ]), + alloc.parser_suggestion("provides [main] to pf").indent(4), + ]); + + Report { + filename, + doc, + title: "BAD PROVIDES".to_string(), + severity: Severity::RuntimeError, + } + } + + EProvides::PackageName(_, pos) => { + 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 package header, but got stuck here:"), + alloc.region_with_subregion(lines.convert_region(surroundings), region), + alloc.concat([ + alloc.reflow("I am expecting a package name next, like "), + alloc.parser_suggestion("\"roc/core\""), + alloc.reflow(". Package names must be quoted."), + ]), + ]); + + Report { + filename, + doc, + title: "INVALID PACKAGE NAME".to_string(), + severity: Severity::RuntimeError, + } + } + _ => todo!("unhandled parse error {:?}", parse_problem), } }