mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-30 07:14:46 +00:00
better messages for types in parens and applied types
This commit is contained in:
parent
f6d3b4ed93
commit
c339f96244
4 changed files with 549 additions and 25 deletions
|
@ -121,6 +121,10 @@ fn to_type_report<'a>(
|
|||
Type::TTagUnion(tag_union, row, col) => {
|
||||
to_ttag_union_report(alloc, filename, &tag_union, *row, *col)
|
||||
}
|
||||
Type::TInParens(tinparens, row, col) => {
|
||||
to_tinparens_report(alloc, filename, &tinparens, *row, *col)
|
||||
}
|
||||
Type::TApply(tapply, row, col) => to_tapply_report(alloc, filename, &tapply, *row, *col),
|
||||
_ => todo!("unhandled type parse error: {:?}", &parse_problem),
|
||||
}
|
||||
}
|
||||
|
@ -373,8 +377,6 @@ fn to_ttag_union_report<'a>(
|
|||
) -> Report<'a> {
|
||||
use roc_parse::parser::TTagUnion;
|
||||
|
||||
dbg!(parse_problem);
|
||||
|
||||
match *parse_problem {
|
||||
TTagUnion::Open(row, col) => match what_is_next(alloc.src_lines, row, col) {
|
||||
Next::Keyword(keyword) => {
|
||||
|
@ -565,6 +567,304 @@ fn to_ttag_union_report<'a>(
|
|||
}
|
||||
}
|
||||
|
||||
fn to_tinparens_report<'a>(
|
||||
alloc: &'a RocDocAllocator<'a>,
|
||||
filename: PathBuf,
|
||||
parse_problem: &roc_parse::parser::TInParens<'a>,
|
||||
start_row: Row,
|
||||
start_col: Col,
|
||||
) -> Report<'a> {
|
||||
use roc_parse::parser::TInParens;
|
||||
|
||||
match *parse_problem {
|
||||
TInParens::Open(row, col) => {
|
||||
match what_is_next(alloc.src_lines, row, col) {
|
||||
Next::Keyword(keyword) => {
|
||||
let surroundings = Region::from_rows_cols(start_row, start_col, row, col);
|
||||
let region = to_keyword_region(row, col, keyword);
|
||||
|
||||
let doc = alloc.stack(vec![
|
||||
alloc.reflow(r"I just saw an open parenthesis, so I was expecting to see a type next."),
|
||||
alloc.region_with_subregion(surroundings, region),
|
||||
alloc.concat(vec![
|
||||
alloc.reflow(r"Something like "),
|
||||
alloc.parser_suggestion("(List Person)"),
|
||||
alloc.text(" or "),
|
||||
alloc.parser_suggestion("(Result I64 Str)"),
|
||||
]),
|
||||
]);
|
||||
|
||||
Report {
|
||||
filename,
|
||||
doc,
|
||||
title: "UNFINISHED PARENTHESES".to_string(),
|
||||
}
|
||||
}
|
||||
Next::Other(Some(c)) if c.is_alphabetic() => {
|
||||
debug_assert!(c.is_lowercase());
|
||||
|
||||
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 partway through parsing a type in parentheses, but I got stuck here:",
|
||||
),
|
||||
alloc.region_with_subregion(surroundings, region),
|
||||
alloc.reflow(r"I was expecting to see a tag name."),
|
||||
hint_for_tag_name(alloc),
|
||||
]);
|
||||
|
||||
Report {
|
||||
filename,
|
||||
doc,
|
||||
title: "WEIRD TAG NAME".to_string(),
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
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 just started parsing a type in parentheses, but I got stuck here:",
|
||||
),
|
||||
alloc.region_with_subregion(surroundings, region),
|
||||
alloc.concat(vec![
|
||||
alloc.reflow(r"Tag unions look like "),
|
||||
alloc.parser_suggestion("[ Many I64, None ],"),
|
||||
alloc.reflow(" so I was expecting to see a tag name next."),
|
||||
]),
|
||||
]);
|
||||
|
||||
Report {
|
||||
filename,
|
||||
doc,
|
||||
title: "UNFINISHED PARENTHESES".to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TInParens::End(row, col) => {
|
||||
let surroundings = Region::from_rows_cols(start_row, start_col, row, col);
|
||||
let region = Region::from_row_col(row, col);
|
||||
|
||||
match what_is_next(alloc.src_lines, row, col) {
|
||||
Next::Other(Some(c)) if c.is_alphabetic() => {
|
||||
debug_assert!(c.is_lowercase());
|
||||
|
||||
// TODO hint for tuples?
|
||||
let doc = alloc.stack(vec![
|
||||
alloc.reflow(
|
||||
r"I am partway through parsing a type in parentheses, but I got stuck here:",
|
||||
),
|
||||
alloc.region_with_subregion(surroundings, region),
|
||||
alloc.reflow(r"I was expecting to see a tag name."),
|
||||
hint_for_tag_name(alloc),
|
||||
]);
|
||||
|
||||
Report {
|
||||
filename,
|
||||
doc,
|
||||
title: "WEIRD TAG NAME".to_string(),
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
let doc = alloc.stack(vec![
|
||||
alloc.reflow(r"I am partway through parsing a type in parentheses, but I got stuck here:"),
|
||||
alloc.region_with_subregion(surroundings, region),
|
||||
alloc.concat(vec![
|
||||
alloc.reflow(
|
||||
r"I was expecting to see a closing parenthesis before this, so try adding a ",
|
||||
),
|
||||
alloc.parser_suggestion(")"),
|
||||
alloc.reflow(" and see if that helps?"),
|
||||
]),
|
||||
]);
|
||||
|
||||
Report {
|
||||
filename,
|
||||
doc,
|
||||
title: "UNFINISHED PARENTHESES".to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TInParens::Type(tipe, row, col) => to_type_report(alloc, filename, tipe, row, col),
|
||||
|
||||
TInParens::Syntax(error, row, col) => to_syntax_report(alloc, filename, error, row, col),
|
||||
|
||||
TInParens::IndentOpen(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 just started parsing a type in parentheses, but I got stuck here:"),
|
||||
alloc.region_with_subregion(surroundings, region),
|
||||
alloc.concat(vec![
|
||||
alloc.reflow(r"Tag unions look like "),
|
||||
alloc.parser_suggestion("[ Many I64, None ],"),
|
||||
alloc.reflow(" so I was expecting to see a tag name next."),
|
||||
]),
|
||||
note_for_tag_union_type_indent(alloc),
|
||||
]);
|
||||
|
||||
Report {
|
||||
filename,
|
||||
doc,
|
||||
title: "UNFINISHED PARENTHESES".to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
TInParens::IndentEnd(row, col) => {
|
||||
match next_line_starts_with_close_square_bracket(alloc.src_lines, row - 1) {
|
||||
Some((curly_row, curly_col)) => {
|
||||
let surroundings =
|
||||
Region::from_rows_cols(start_row, start_col, curly_row, curly_col);
|
||||
let region = Region::from_row_col(curly_row, curly_col);
|
||||
|
||||
let doc = alloc.stack(vec![
|
||||
alloc.reflow(
|
||||
"I am partway through parsing a type in parentheses, but I got stuck here:",
|
||||
),
|
||||
alloc.region_with_subregion(surroundings, region),
|
||||
alloc.concat(vec![
|
||||
alloc.reflow("I need this square bracket to be indented more. Try adding more spaces before it!"),
|
||||
]),
|
||||
]);
|
||||
|
||||
Report {
|
||||
filename,
|
||||
doc,
|
||||
title: "NEED MORE INDENTATION".to_string(),
|
||||
}
|
||||
}
|
||||
None => {
|
||||
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 partway through parsing a type in parentheses, but I got stuck here:",
|
||||
),
|
||||
alloc.region_with_subregion(surroundings, region),
|
||||
alloc.concat(vec![
|
||||
alloc.reflow("I was expecting to see a closing square "),
|
||||
alloc.reflow("bracket before this, so try adding a "),
|
||||
alloc.parser_suggestion("]"),
|
||||
alloc.reflow(" and see if that helps?"),
|
||||
]),
|
||||
note_for_tag_union_type_indent(alloc),
|
||||
]);
|
||||
|
||||
Report {
|
||||
filename,
|
||||
doc,
|
||||
title: "UNFINISHED PARENTHESES".to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TInParens::Space(error, row, col) => to_space_report(alloc, filename, &error, row, col),
|
||||
}
|
||||
}
|
||||
|
||||
fn to_tapply_report<'a>(
|
||||
alloc: &'a RocDocAllocator<'a>,
|
||||
filename: PathBuf,
|
||||
parse_problem: &roc_parse::parser::TApply<'a>,
|
||||
start_row: Row,
|
||||
start_col: Col,
|
||||
) -> Report<'a> {
|
||||
use roc_parse::parser::TApply;
|
||||
|
||||
match *parse_problem {
|
||||
TApply::DoubleDot(row, col) => {
|
||||
let region = Region::from_row_col(row, col);
|
||||
|
||||
let doc = alloc.stack(vec![
|
||||
alloc.reflow(r"I encountered two dots in a row:"),
|
||||
alloc.region(region),
|
||||
alloc.concat(vec![alloc.reflow("Try removing one of them.")]),
|
||||
]);
|
||||
|
||||
Report {
|
||||
filename,
|
||||
doc,
|
||||
title: "DOUBLE DOT".to_string(),
|
||||
}
|
||||
}
|
||||
TApply::TrailingDot(row, col) => {
|
||||
let region = Region::from_row_col(row, col);
|
||||
|
||||
let doc = alloc.stack(vec![
|
||||
alloc.reflow(r"I encountered a dot with nothing after it:"),
|
||||
alloc.region(region),
|
||||
alloc.concat(vec![
|
||||
alloc.reflow("Dots are used to refer to a type in a qualified way, like "),
|
||||
alloc.parser_suggestion("Num.I64"),
|
||||
alloc.text(" or "),
|
||||
alloc.parser_suggestion("List.List a"),
|
||||
alloc.reflow(". Try adding a type name next."),
|
||||
]),
|
||||
]);
|
||||
|
||||
Report {
|
||||
filename,
|
||||
doc,
|
||||
title: "TRAILING DOT".to_string(),
|
||||
}
|
||||
}
|
||||
TApply::StartIsNumber(row, col) => {
|
||||
let region = Region::from_row_col(row, col);
|
||||
|
||||
let doc = alloc.stack(vec![
|
||||
alloc.reflow(r"I encountered a number at the start of a qualified name segment:"),
|
||||
alloc.region(region),
|
||||
alloc.concat(vec![
|
||||
alloc.reflow("All parts of a qualified type name must start with an uppercase letter, like "),
|
||||
alloc.parser_suggestion("Num.I64"),
|
||||
alloc.text(" or "),
|
||||
alloc.parser_suggestion("List.List a"),
|
||||
alloc.text("."),
|
||||
]),
|
||||
]);
|
||||
|
||||
Report {
|
||||
filename,
|
||||
doc,
|
||||
title: "WEIRD QUALIFIED NAME".to_string(),
|
||||
}
|
||||
}
|
||||
TApply::StartNotUppercase(row, col) => {
|
||||
let region = Region::from_row_col(row, col);
|
||||
|
||||
let doc = alloc.stack(vec![
|
||||
alloc.reflow(r"I encountered a lowercase letter at the start of a qualified name segment:"),
|
||||
alloc.region(region),
|
||||
alloc.concat(vec![
|
||||
alloc.reflow("All parts of a qualified type name must start with an uppercase letter, like "),
|
||||
alloc.parser_suggestion("Num.I64"),
|
||||
alloc.text(" or "),
|
||||
alloc.parser_suggestion("List.List a"),
|
||||
alloc.text("."),
|
||||
]),
|
||||
]);
|
||||
|
||||
Report {
|
||||
filename,
|
||||
doc,
|
||||
title: "WEIRD QUALIFIED NAME".to_string(),
|
||||
}
|
||||
}
|
||||
_ => todo!("unhandled type parse error: {:?}", &parse_problem),
|
||||
}
|
||||
}
|
||||
|
||||
fn to_space_report<'a>(
|
||||
alloc: &'a RocDocAllocator<'a>,
|
||||
filename: PathBuf,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue