better messages for types in parens and applied types

This commit is contained in:
Folkert 2021-02-11 21:48:19 +01:00
parent f6d3b4ed93
commit c339f96244
4 changed files with 549 additions and 25 deletions

View file

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