mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-03 00:24:34 +00:00
start of imports
This commit is contained in:
parent
8b9804adc2
commit
71ab77b804
4 changed files with 418 additions and 48 deletions
|
@ -9,8 +9,8 @@ use crate::ident::{lowercase_ident, unqualified_ident, uppercase_ident};
|
||||||
use crate::parser::Progress::{self, *};
|
use crate::parser::Progress::{self, *};
|
||||||
use crate::parser::{
|
use crate::parser::{
|
||||||
self, ascii_char, ascii_string, backtrackable, end_of_file, loc, optional, peek_utf8_char,
|
self, ascii_char, ascii_string, backtrackable, end_of_file, loc, optional, peek_utf8_char,
|
||||||
peek_utf8_char_at, specialize, unexpected, unexpected_eof, word1, EHeader, EProvides,
|
peek_utf8_char_at, specialize, unexpected, unexpected_eof, word1, Col, EExposes, EHeader,
|
||||||
ParseResult, Parser, State, SyntaxError,
|
EImports, EProvides, ParseResult, Parser, Row, State, SyntaxError,
|
||||||
};
|
};
|
||||||
use crate::string_literal;
|
use crate::string_literal;
|
||||||
use crate::type_annotation;
|
use crate::type_annotation;
|
||||||
|
@ -342,22 +342,23 @@ fn provides_to_help<'a>() -> impl Parser<'a, ProvidesTo<'a>, EProvides> {
|
||||||
and!(
|
and!(
|
||||||
provides_without_to_help(),
|
provides_without_to_help(),
|
||||||
and!(
|
and!(
|
||||||
space0_e(min_indent, EProvides::Space, EProvides::IndentTo),
|
spaces_around_keyword(
|
||||||
skip_first!(
|
min_indent,
|
||||||
crate::parser::keyword_e("to", EProvides::To),
|
"to",
|
||||||
and!(
|
EProvides::To,
|
||||||
space0_e(min_indent, EProvides::Space, EProvides::IndentPackage),
|
EProvides::Space,
|
||||||
|
EProvides::IndentTo,
|
||||||
|
EProvides::IndentListStart
|
||||||
|
),
|
||||||
loc!(specialize(
|
loc!(specialize(
|
||||||
|_, r, c| EProvides::Package(r, c),
|
|_, r, c| EProvides::Package(r, c),
|
||||||
provides_to_package()
|
provides_to_package()
|
||||||
))
|
))
|
||||||
)
|
)
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
),
|
||||||
|(
|
|(
|
||||||
((before_provides_keyword, after_provides_keyword), entries),
|
((before_provides_keyword, after_provides_keyword), entries),
|
||||||
(before_to_keyword, (after_to_keyword, to)),
|
((before_to_keyword, after_to_keyword), to),
|
||||||
)| {
|
)| {
|
||||||
ProvidesTo {
|
ProvidesTo {
|
||||||
entries,
|
entries,
|
||||||
|
@ -397,12 +398,13 @@ fn provides_without_to_help<'a>() -> impl Parser<
|
||||||
> {
|
> {
|
||||||
let min_indent = 1;
|
let min_indent = 1;
|
||||||
and!(
|
and!(
|
||||||
and!(
|
spaces_around_keyword(
|
||||||
skip_second!(
|
min_indent,
|
||||||
space0_e(min_indent, EProvides::Space, EProvides::IndentProvides),
|
"provides",
|
||||||
crate::parser::keyword_e("provides", EProvides::Provides)
|
EProvides::Provides,
|
||||||
),
|
EProvides::Space,
|
||||||
space0_e(min_indent, EProvides::Space, EProvides::IndentListStart)
|
EProvides::IndentProvides,
|
||||||
|
EProvides::IndentListStart
|
||||||
),
|
),
|
||||||
collection_e!(
|
collection_e!(
|
||||||
word1(b'[', EProvides::ListStart),
|
word1(b'[', EProvides::ListStart),
|
||||||
|
@ -460,14 +462,40 @@ fn exposes_values<'a>() -> impl Parser<
|
||||||
),
|
),
|
||||||
SyntaxError<'a>,
|
SyntaxError<'a>,
|
||||||
> {
|
> {
|
||||||
|
specialize(
|
||||||
|
|e, r, c| SyntaxError::Header(EHeader::Exposes(e, r, c)),
|
||||||
|
exposes_values_help(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn exposes_values_help<'a>() -> impl Parser<
|
||||||
|
'a,
|
||||||
|
(
|
||||||
|
(&'a [CommentOrNewline<'a>], &'a [CommentOrNewline<'a>]),
|
||||||
|
Vec<'a, Located<ExposesEntry<'a, &'a str>>>,
|
||||||
|
),
|
||||||
|
EExposes,
|
||||||
|
> {
|
||||||
|
let min_indent = 1;
|
||||||
|
|
||||||
and!(
|
and!(
|
||||||
and!(skip_second!(space1(1), ascii_string("exposes")), space1(1)),
|
spaces_around_keyword(
|
||||||
collection!(
|
min_indent,
|
||||||
ascii_char(b'['),
|
"exposes",
|
||||||
loc!(map!(unqualified_ident(), ExposesEntry::Exposed)),
|
EExposes::Exposes,
|
||||||
ascii_char(b','),
|
EExposes::Space,
|
||||||
ascii_char(b']'),
|
EExposes::IndentExposes,
|
||||||
1
|
EExposes::IndentListStart
|
||||||
|
),
|
||||||
|
collection_e!(
|
||||||
|
word1(b'[', EExposes::ListStart),
|
||||||
|
exposes_entry(EExposes::Identifier),
|
||||||
|
word1(b',', EExposes::ListEnd),
|
||||||
|
word1(b']', EExposes::ListEnd),
|
||||||
|
min_indent,
|
||||||
|
EExposes::Space,
|
||||||
|
EExposes::IndentListEnd
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -481,18 +509,78 @@ fn exposes_modules<'a>() -> impl Parser<
|
||||||
),
|
),
|
||||||
SyntaxError<'a>,
|
SyntaxError<'a>,
|
||||||
> {
|
> {
|
||||||
|
specialize(
|
||||||
|
|e, r, c| SyntaxError::Header(EHeader::Exposes(e, r, c)),
|
||||||
|
exposes_modules_help(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn spaces_around_keyword<'a, E>(
|
||||||
|
min_indent: u16,
|
||||||
|
keyword: &'static str,
|
||||||
|
expectation: fn(Row, Col) -> E,
|
||||||
|
space_problem: fn(crate::parser::BadInputError, Row, Col) -> E,
|
||||||
|
indent_problem1: fn(Row, Col) -> E,
|
||||||
|
indent_problem2: fn(Row, Col) -> E,
|
||||||
|
) -> impl Parser<'a, (&'a [CommentOrNewline<'a>], &'a [CommentOrNewline<'a>]), E>
|
||||||
|
where
|
||||||
|
E: 'a,
|
||||||
|
{
|
||||||
and!(
|
and!(
|
||||||
and!(skip_second!(space1(1), ascii_string("exposes")), space1(1)),
|
skip_second!(
|
||||||
collection!(
|
space0_e(min_indent, space_problem, indent_problem1),
|
||||||
ascii_char(b'['),
|
crate::parser::keyword_e(keyword, expectation)
|
||||||
loc!(map!(module_name(), ExposesEntry::Exposed)),
|
),
|
||||||
ascii_char(b','),
|
space0_e(min_indent, space_problem, indent_problem2)
|
||||||
ascii_char(b']'),
|
)
|
||||||
1
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn exposes_modules_help<'a>() -> impl Parser<
|
||||||
|
'a,
|
||||||
|
(
|
||||||
|
(&'a [CommentOrNewline<'a>], &'a [CommentOrNewline<'a>]),
|
||||||
|
Vec<'a, Located<ExposesEntry<'a, ModuleName<'a>>>>,
|
||||||
|
),
|
||||||
|
EExposes,
|
||||||
|
> {
|
||||||
|
let min_indent = 1;
|
||||||
|
|
||||||
|
and!(
|
||||||
|
spaces_around_keyword(
|
||||||
|
min_indent,
|
||||||
|
"exposes",
|
||||||
|
EExposes::Exposes,
|
||||||
|
EExposes::Space,
|
||||||
|
EExposes::IndentExposes,
|
||||||
|
EExposes::IndentListStart
|
||||||
|
),
|
||||||
|
collection_e!(
|
||||||
|
word1(b'[', EExposes::ListStart),
|
||||||
|
exposes_module(EExposes::Identifier),
|
||||||
|
word1(b',', EExposes::ListEnd),
|
||||||
|
word1(b']', EExposes::ListEnd),
|
||||||
|
min_indent,
|
||||||
|
EExposes::Space,
|
||||||
|
EExposes::IndentListEnd
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn exposes_module<'a, F, E>(
|
||||||
|
to_expectation: F,
|
||||||
|
) -> impl Parser<'a, Located<ExposesEntry<'a, ModuleName<'a>>>, E>
|
||||||
|
where
|
||||||
|
F: Fn(crate::parser::Row, crate::parser::Col) -> E,
|
||||||
|
F: Copy,
|
||||||
|
E: 'a,
|
||||||
|
{
|
||||||
|
loc!(map!(
|
||||||
|
specialize(|_, r, c| to_expectation(r, c), module_name()),
|
||||||
|
ExposesEntry::Exposed
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct Packages<'a> {
|
struct Packages<'a> {
|
||||||
entries: Vec<'a, Located<PackageEntry<'a>>>,
|
entries: Vec<'a, Located<PackageEntry<'a>>>,
|
||||||
|
@ -551,6 +639,30 @@ fn imports<'a>() -> impl Parser<
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn imports_help<'a>() -> impl Parser<
|
||||||
|
'a,
|
||||||
|
(
|
||||||
|
(&'a [CommentOrNewline<'a>], &'a [CommentOrNewline<'a>]),
|
||||||
|
Vec<'a, Located<ImportsEntry<'a>>>,
|
||||||
|
),
|
||||||
|
SyntaxError<'a>,
|
||||||
|
> {
|
||||||
|
and!(
|
||||||
|
and!(
|
||||||
|
skip_second!(backtrackable(space1(1)), ascii_string("imports")),
|
||||||
|
space1(1)
|
||||||
|
),
|
||||||
|
collection!(
|
||||||
|
ascii_char(b'['),
|
||||||
|
loc!(imports_entry()),
|
||||||
|
ascii_char(b','),
|
||||||
|
ascii_char(b']'),
|
||||||
|
1
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn effects<'a>() -> impl Parser<'a, Effects<'a>, SyntaxError<'a>> {
|
fn effects<'a>() -> impl Parser<'a, Effects<'a>, SyntaxError<'a>> {
|
||||||
move |arena, state| {
|
move |arena, state| {
|
||||||
|
@ -621,23 +733,50 @@ fn typed_ident<'a>() -> impl Parser<'a, TypedIdent<'a>, SyntaxError<'a>> {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[allow(clippy::type_complexity)]
|
#[allow(clippy::type_complexity)]
|
||||||
fn imports_entry<'a>() -> impl Parser<'a, ImportsEntry<'a>, SyntaxError<'a>> {
|
fn imports_entry<'a>() -> impl Parser<'a, ImportsEntry<'a>, SyntaxError<'a>> {
|
||||||
|
specialize(
|
||||||
|
|e, r, c| SyntaxError::Header(EHeader::Imports(e, r, c)),
|
||||||
|
imports_entry_help(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn shortname<'a>() -> impl Parser<'a, &'a str, EImports> {
|
||||||
|
specialize(|_, r, c| EImports::Shortname(r, c), lowercase_ident())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn module_name_help<'a, F, E>(to_expectation: F) -> impl Parser<'a, ModuleName<'a>, E>
|
||||||
|
where
|
||||||
|
F: Fn(crate::parser::Row, crate::parser::Col) -> E,
|
||||||
|
E: 'a,
|
||||||
|
F: 'a,
|
||||||
|
{
|
||||||
|
specialize(move |_, r, c| to_expectation(r, c), module_name())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn imports_entry_help<'a>() -> impl Parser<'a, ImportsEntry<'a>, EImports> {
|
||||||
|
let min_indent = 1;
|
||||||
|
|
||||||
map_with_arena!(
|
map_with_arena!(
|
||||||
and!(
|
and!(
|
||||||
and!(
|
and!(
|
||||||
// e.g. `base.`
|
// e.g. `base.`
|
||||||
optional(skip_second!(lowercase_ident(), ascii_char(b'.'))),
|
maybe!(skip_second!(
|
||||||
|
shortname(),
|
||||||
|
word1(b'.', EImports::ShorthandDot)
|
||||||
|
)),
|
||||||
// e.g. `Task`
|
// e.g. `Task`
|
||||||
module_name()
|
module_name_help(EImports::ModuleName)
|
||||||
),
|
),
|
||||||
// e.g. `.{ Task, after}`
|
// e.g. `.{ Task, after}`
|
||||||
optional(skip_first!(
|
maybe!(skip_first!(
|
||||||
ascii_char(b'.'),
|
word1(b'.', EImports::ExposingDot),
|
||||||
collection!(
|
collection_e!(
|
||||||
ascii_char(b'{'),
|
word1(b'{', EImports::SetStart),
|
||||||
loc!(map!(unqualified_ident(), ExposesEntry::Exposed)),
|
exposes_entry(EImports::Identifier),
|
||||||
ascii_char(b','),
|
word1(b',', EImports::SetEnd),
|
||||||
ascii_char(b'}'),
|
word1(b'}', EImports::SetEnd),
|
||||||
1
|
min_indent,
|
||||||
|
EImports::Space,
|
||||||
|
EImports::IndentSetEnd
|
||||||
)
|
)
|
||||||
))
|
))
|
||||||
),
|
),
|
||||||
|
|
|
@ -341,6 +341,8 @@ pub enum SyntaxError<'a> {
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub enum EHeader {
|
pub enum EHeader {
|
||||||
Provides(EProvides, Row, Col),
|
Provides(EProvides, Row, Col),
|
||||||
|
Exposes(EExposes, Row, Col),
|
||||||
|
Imports(EImports, Row, Col),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
@ -359,6 +361,38 @@ pub enum EProvides {
|
||||||
Space(BadInputError, Row, Col),
|
Space(BadInputError, Row, Col),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub enum EExposes {
|
||||||
|
Exposes(Row, Col),
|
||||||
|
IndentExposes(Row, Col),
|
||||||
|
IndentListStart(Row, Col),
|
||||||
|
IndentListEnd(Row, Col),
|
||||||
|
ListStart(Row, Col),
|
||||||
|
ListEnd(Row, Col),
|
||||||
|
Identifier(Row, Col),
|
||||||
|
Space(BadInputError, Row, Col),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub enum EImports {
|
||||||
|
Imports(Row, Col),
|
||||||
|
IndentImports(Row, Col),
|
||||||
|
IndentListStart(Row, Col),
|
||||||
|
IndentListEnd(Row, Col),
|
||||||
|
ListStart(Row, Col),
|
||||||
|
ListEnd(Row, Col),
|
||||||
|
Identifier(Row, Col),
|
||||||
|
ExposingDot(Row, Col),
|
||||||
|
ShorthandDot(Row, Col),
|
||||||
|
Shortname(Row, Col),
|
||||||
|
ModuleName(Row, Col),
|
||||||
|
Space(BadInputError, Row, Col),
|
||||||
|
IndentSetStart(Row, Col),
|
||||||
|
IndentSetEnd(Row, Col),
|
||||||
|
SetStart(Row, Col),
|
||||||
|
SetEnd(Row, Col),
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub enum BadInputError {
|
pub enum BadInputError {
|
||||||
HasTab,
|
HasTab,
|
||||||
|
@ -1777,6 +1811,19 @@ macro_rules! one_of {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! maybe {
|
||||||
|
($p1:expr) => {
|
||||||
|
move |arena: &'a bumpalo::Bump, state: $crate::parser::State<'a>| match $p1
|
||||||
|
.parse(arena, state)
|
||||||
|
{
|
||||||
|
Ok((progress, value, state)) => Ok((progress, Some(value), state)),
|
||||||
|
Err((MadeProgress, fail, state)) => Err((MadeProgress, fail, state)),
|
||||||
|
Err((NoProgress, _, state)) => Ok((NoProgress, None, state)),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! one_of_with_error {
|
macro_rules! one_of_with_error {
|
||||||
($toerror:expr; $p1:expr) => {
|
($toerror:expr; $p1:expr) => {
|
||||||
|
|
|
@ -2482,7 +2482,15 @@ fn to_header_report<'a>(
|
||||||
match *parse_problem {
|
match *parse_problem {
|
||||||
EHeader::Provides(provides, row, col) => {
|
EHeader::Provides(provides, row, col) => {
|
||||||
to_provides_report(alloc, filename, &provides, row, col)
|
to_provides_report(alloc, filename, &provides, row, col)
|
||||||
} // _ => todo!("unhandled parse error {:?}", parse_problem),
|
}
|
||||||
|
|
||||||
|
EHeader::Exposes(exposes, row, col) => {
|
||||||
|
to_exposes_report(alloc, filename, &exposes, row, col)
|
||||||
|
}
|
||||||
|
|
||||||
|
EHeader::Imports(imports, row, col) => {
|
||||||
|
to_imports_report(alloc, filename, &imports, row, col)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2520,12 +2528,162 @@ fn to_provides_report<'a>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EProvides::Provides(row, col) => {
|
||||||
|
let surroundings = Region::from_rows_cols(start_row, start_col, row, col);
|
||||||
|
let region = Region::from_row_col(row, col);
|
||||||
|
|
||||||
|
let doc = alloc.stack(vec![
|
||||||
|
alloc.reflow(r"I am in the middle of a header, but I got stuck here:"),
|
||||||
|
alloc.region_with_subregion(surroundings, region),
|
||||||
|
alloc.concat(vec![
|
||||||
|
alloc.reflow("I am expecting the "),
|
||||||
|
alloc.keyword("provides"),
|
||||||
|
alloc.reflow(" keyword next, like "),
|
||||||
|
]),
|
||||||
|
alloc
|
||||||
|
.parser_suggestion("provides [ Animal, default, tame ]")
|
||||||
|
.indent(4),
|
||||||
|
]);
|
||||||
|
|
||||||
|
Report {
|
||||||
|
filename,
|
||||||
|
doc,
|
||||||
|
title: "WEIRD PROVIDES".to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
EProvides::Space(error, row, col) => to_space_report(alloc, filename, &error, row, col),
|
EProvides::Space(error, row, col) => to_space_report(alloc, filename, &error, row, col),
|
||||||
|
|
||||||
_ => todo!("unhandled parse error {:?}", parse_problem),
|
_ => todo!("unhandled parse error {:?}", parse_problem),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn to_exposes_report<'a>(
|
||||||
|
alloc: &'a RocDocAllocator<'a>,
|
||||||
|
filename: PathBuf,
|
||||||
|
parse_problem: &roc_parse::parser::EExposes,
|
||||||
|
start_row: Row,
|
||||||
|
start_col: Col,
|
||||||
|
) -> Report<'a> {
|
||||||
|
use roc_parse::parser::EExposes;
|
||||||
|
|
||||||
|
match *parse_problem {
|
||||||
|
EExposes::Identifier(row, col) => {
|
||||||
|
let surroundings = Region::from_rows_cols(start_row, start_col, row, col);
|
||||||
|
let region = Region::from_row_col(row, col);
|
||||||
|
|
||||||
|
let doc = alloc.stack(vec![
|
||||||
|
alloc
|
||||||
|
.reflow(r"I am in the middle of parsing a exposes list, but I got stuck here:"),
|
||||||
|
alloc.region_with_subregion(surroundings, region),
|
||||||
|
alloc.concat(vec![alloc.reflow(
|
||||||
|
"I was expecting a type name, value name or function name next, like ",
|
||||||
|
)]),
|
||||||
|
alloc
|
||||||
|
.parser_suggestion("exposes [ Animal, default, tame ]")
|
||||||
|
.indent(4),
|
||||||
|
]);
|
||||||
|
|
||||||
|
Report {
|
||||||
|
filename,
|
||||||
|
doc,
|
||||||
|
title: "WEIRD EXPOSES".to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EExposes::Exposes(row, col) => {
|
||||||
|
let surroundings = Region::from_rows_cols(start_row, start_col, row, col);
|
||||||
|
let region = Region::from_row_col(row, col);
|
||||||
|
|
||||||
|
let doc = alloc.stack(vec![
|
||||||
|
alloc.reflow(r"I am in the middle of a header, but I got stuck here:"),
|
||||||
|
alloc.region_with_subregion(surroundings, region),
|
||||||
|
alloc.concat(vec![
|
||||||
|
alloc.reflow("I am expecting the "),
|
||||||
|
alloc.keyword("exposes"),
|
||||||
|
alloc.reflow(" keyword next, like "),
|
||||||
|
]),
|
||||||
|
alloc
|
||||||
|
.parser_suggestion("exposes [ Animal, default, tame ]")
|
||||||
|
.indent(4),
|
||||||
|
]);
|
||||||
|
|
||||||
|
Report {
|
||||||
|
filename,
|
||||||
|
doc,
|
||||||
|
title: "WEIRD EXPOSES".to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EExposes::Space(error, row, col) => to_space_report(alloc, filename, &error, row, col),
|
||||||
|
|
||||||
|
_ => todo!("unhandled parse error {:?}", parse_problem),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_imports_report<'a>(
|
||||||
|
alloc: &'a RocDocAllocator<'a>,
|
||||||
|
filename: PathBuf,
|
||||||
|
parse_problem: &roc_parse::parser::EImports,
|
||||||
|
start_row: Row,
|
||||||
|
start_col: Col,
|
||||||
|
) -> Report<'a> {
|
||||||
|
use roc_parse::parser::EImports;
|
||||||
|
|
||||||
|
match *parse_problem {
|
||||||
|
EImports::Identifier(row, col) => {
|
||||||
|
let surroundings = Region::from_rows_cols(start_row, start_col, row, col);
|
||||||
|
let region = Region::from_row_col(row, col);
|
||||||
|
|
||||||
|
let doc = alloc.stack(vec![
|
||||||
|
alloc
|
||||||
|
.reflow(r"I am in the middle of parsing a imports list, but I got stuck here:"),
|
||||||
|
alloc.region_with_subregion(surroundings, region),
|
||||||
|
alloc.concat(vec![alloc.reflow(
|
||||||
|
"I was expecting a type name, value name or function name next, like ",
|
||||||
|
)]),
|
||||||
|
alloc
|
||||||
|
.parser_suggestion("imports [ Animal, default, tame ]")
|
||||||
|
.indent(4),
|
||||||
|
]);
|
||||||
|
|
||||||
|
Report {
|
||||||
|
filename,
|
||||||
|
doc,
|
||||||
|
title: "WEIRD EXPOSES".to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EImports::Imports(row, col) => {
|
||||||
|
let surroundings = Region::from_rows_cols(start_row, start_col, row, col);
|
||||||
|
let region = Region::from_row_col(row, col);
|
||||||
|
|
||||||
|
let doc = alloc.stack(vec![
|
||||||
|
alloc.reflow(r"I am in the middle of a header, but I got stuck here:"),
|
||||||
|
alloc.region_with_subregion(surroundings, region),
|
||||||
|
alloc.concat(vec![
|
||||||
|
alloc.reflow("I am expecting the "),
|
||||||
|
alloc.keyword("imports"),
|
||||||
|
alloc.reflow(" keyword next, like "),
|
||||||
|
]),
|
||||||
|
alloc
|
||||||
|
.parser_suggestion("imports [ Animal, default, tame ]")
|
||||||
|
.indent(4),
|
||||||
|
]);
|
||||||
|
|
||||||
|
Report {
|
||||||
|
filename,
|
||||||
|
doc,
|
||||||
|
title: "WEIRD IMPORTS".to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EImports::Space(error, row, col) => to_space_report(alloc, filename, &error, row, col),
|
||||||
|
|
||||||
|
_ => todo!("unhandled parse error {:?}", parse_problem),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn to_space_report<'a>(
|
fn to_space_report<'a>(
|
||||||
alloc: &'a RocDocAllocator<'a>,
|
alloc: &'a RocDocAllocator<'a>,
|
||||||
filename: PathBuf,
|
filename: PathBuf,
|
||||||
|
|
|
@ -5758,9 +5758,7 @@ mod test_reporting {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn provides_to() {
|
fn provides_to_identifier() {
|
||||||
// this is still bad, but changing the order and progress of other parsers should improve it
|
|
||||||
// down the line
|
|
||||||
report_header_problem_as(
|
report_header_problem_as(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
|
@ -5787,4 +5785,32 @@ mod test_reporting {
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn exposes_identifier() {
|
||||||
|
report_header_problem_as(
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
interface Foobar
|
||||||
|
exposes [ main, @Foo ]
|
||||||
|
imports [base.Task, Base64 ]
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
── WEIRD EXPOSES ───────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
I am in the middle of parsing a exposes list, but I got stuck here:
|
||||||
|
|
||||||
|
1│ interface Foobar
|
||||||
|
2│ exposes [ main, @Foo ]
|
||||||
|
^
|
||||||
|
|
||||||
|
I was expecting a type name, value name or function name next, like
|
||||||
|
|
||||||
|
exposes [ Animal, default, tame ]
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue