mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-02 19:32:17 +00:00
Warnings are now yellow
This commit is contained in:
parent
0e1a9545c6
commit
a189e3ab20
7 changed files with 580 additions and 426 deletions
|
@ -4771,7 +4771,7 @@ mod test_reporting {
|
|||
// TODO investigate this test. It was disabled in https://github.com/roc-lang/roc/pull/6634
|
||||
// as the way Defs without final expressions are handled. The changes probably shouldn't have
|
||||
// changed this error report. The exact same test_syntax test for this has not changed, so
|
||||
// we know the parser is parsing thesame thing. Therefore the way the AST is desugared must be
|
||||
// we know the parser is parsing the same thing. Therefore the way the AST is desugared must be
|
||||
// the cause of the change in error report.
|
||||
// test_report!(
|
||||
// def_missing_final_expression,
|
||||
|
@ -8162,7 +8162,7 @@ In roc, functions are always written as a lambda, like{}
|
|||
"#
|
||||
),
|
||||
// TODO(opaques): error could be improved by saying that the opaque definition demands
|
||||
// that the argument be a U8, and linking to the definitin!
|
||||
// that the argument be a U8, and linking to the definition!
|
||||
@r#"
|
||||
── TYPE MISMATCH in /code/proj/Main.roc ────────────────────────────────────────
|
||||
|
||||
|
@ -13530,7 +13530,7 @@ In roc, functions are always written as a lambda, like{}
|
|||
4│ crash "" ""
|
||||
^^^^^
|
||||
|
||||
`crash` must be given exacly one message to crash with.
|
||||
`crash` must be given exactly one message to crash with.
|
||||
"#
|
||||
);
|
||||
|
||||
|
|
|
@ -6303,6 +6303,8 @@ fn to_incorrect_module_name_report<'a>(
|
|||
expected,
|
||||
} = problem;
|
||||
|
||||
let severity = Severity::RuntimeError;
|
||||
|
||||
// SAFETY: if the module was not UTF-8, that would be reported as a parsing problem, rather
|
||||
// than an incorrect module name problem (the latter can happen only after parsing).
|
||||
let src = unsafe { from_utf8_unchecked(src) };
|
||||
|
@ -6317,7 +6319,7 @@ fn to_incorrect_module_name_report<'a>(
|
|||
|
||||
let doc = alloc.stack([
|
||||
alloc.reflow("This module has a different name than I expected:"),
|
||||
alloc.region(lines.convert_region(found.region)),
|
||||
alloc.region(lines.convert_region(found.region), severity),
|
||||
alloc.reflow("Based on the nesting and use of this module, I expect it to have name"),
|
||||
alloc.pq_module_name(expected).indent(4),
|
||||
]);
|
||||
|
@ -6326,7 +6328,7 @@ fn to_incorrect_module_name_report<'a>(
|
|||
filename,
|
||||
doc,
|
||||
title: "INCORRECT MODULE NAME".to_string(),
|
||||
severity: Severity::RuntimeError,
|
||||
severity,
|
||||
};
|
||||
|
||||
let mut buf = String::new();
|
||||
|
@ -6346,6 +6348,7 @@ fn to_no_platform_package_report(
|
|||
) -> String {
|
||||
use roc_reporting::report::{Report, RocDocAllocator, DEFAULT_PALETTE};
|
||||
use ven_pretty::DocAllocator;
|
||||
let severity = Severity::RuntimeError;
|
||||
|
||||
// SAFETY: if the module was not UTF-8, that would be reported as a parsing problem, rather
|
||||
// than an incorrect module name problem (the latter can happen only after parsing).
|
||||
|
@ -6361,7 +6364,7 @@ fn to_no_platform_package_report(
|
|||
|
||||
let doc = alloc.stack([
|
||||
alloc.reflow("This app does not specify a platform:"),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region),severity),
|
||||
alloc.reflow("Make sure you have exactly one package specified as `platform`:"),
|
||||
alloc
|
||||
.parser_suggestion(" app [main] {\n pf: platform \"…path or URL to platform…\"\n ^^^^^^^^\n }"),
|
||||
|
@ -6373,7 +6376,7 @@ fn to_no_platform_package_report(
|
|||
filename,
|
||||
doc,
|
||||
title: "UNSPECIFIED PLATFORM".to_string(),
|
||||
severity: Severity::RuntimeError,
|
||||
severity,
|
||||
};
|
||||
|
||||
let mut buf = String::new();
|
||||
|
@ -6393,6 +6396,7 @@ fn to_multiple_platform_packages_report(
|
|||
) -> String {
|
||||
use roc_reporting::report::{Report, RocDocAllocator, DEFAULT_PALETTE};
|
||||
use ven_pretty::DocAllocator;
|
||||
let severity = Severity::RuntimeError;
|
||||
|
||||
// SAFETY: if the module was not UTF-8, that would be reported as a parsing problem, rather
|
||||
// than an incorrect module name problem (the latter can happen only after parsing).
|
||||
|
@ -6408,7 +6412,7 @@ fn to_multiple_platform_packages_report(
|
|||
|
||||
let doc = alloc.stack([
|
||||
alloc.reflow("This app specifies multiple packages as `platform`:"),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
alloc.reflow("Roc apps must specify exactly one platform."),
|
||||
]);
|
||||
|
||||
|
@ -6416,7 +6420,7 @@ fn to_multiple_platform_packages_report(
|
|||
filename,
|
||||
doc,
|
||||
title: "MULTIPLE PLATFORMS".to_string(),
|
||||
severity: Severity::RuntimeError,
|
||||
severity,
|
||||
};
|
||||
|
||||
let mut buf = String::new();
|
||||
|
|
|
@ -84,7 +84,7 @@ pub fn can_problem<'b>(
|
|||
alloc
|
||||
.symbol_unqualified(symbol)
|
||||
.append(alloc.reflow(" is not used anywhere in your code.")),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
alloc
|
||||
.reflow("If you didn't intend on using ")
|
||||
.append(alloc.symbol_unqualified(symbol))
|
||||
|
@ -99,7 +99,7 @@ pub fn can_problem<'b>(
|
|||
alloc.symbol_qualified(symbol),
|
||||
alloc.reflow(" is not used in this module."),
|
||||
]),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
alloc.concat([
|
||||
alloc.reflow("Since "),
|
||||
alloc.symbol_qualified(symbol),
|
||||
|
@ -115,7 +115,7 @@ pub fn can_problem<'b>(
|
|||
alloc.module(module_id),
|
||||
alloc.reflow(" is imported but not used."),
|
||||
]),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
alloc.concat([
|
||||
alloc.reflow("Since "),
|
||||
alloc.module(module_id),
|
||||
|
@ -145,17 +145,17 @@ pub fn can_problem<'b>(
|
|||
alloc.reflow(" was imported here: ")
|
||||
},
|
||||
]),
|
||||
alloc.region(lines.convert_region(new_import_region)),
|
||||
alloc.region(lines.convert_region(new_import_region), severity),
|
||||
|
||||
match existing_import {
|
||||
ScopeModuleSource::Import(exsting_import_region) => {
|
||||
ScopeModuleSource::Import(existing_import_region) => {
|
||||
alloc.stack([
|
||||
alloc.concat([
|
||||
alloc.reflow("but "),
|
||||
alloc.module_name(name.clone()),
|
||||
alloc.reflow(" is already used by a previous import:"),
|
||||
]),
|
||||
alloc.region(lines.convert_region(exsting_import_region)),
|
||||
alloc.region(lines.convert_region(existing_import_region), severity),
|
||||
])
|
||||
}
|
||||
ScopeModuleSource::Builtin => {
|
||||
|
@ -193,7 +193,7 @@ pub fn can_problem<'b>(
|
|||
alloc.module(module_id),
|
||||
alloc.reflow(" was imported here:"),
|
||||
]),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
alloc.reflow("Builtins are imported automatically, so you can remove this import."),
|
||||
alloc.reflow("Tip: Learn more about builtins in the tutorial:\n\n<https://www.roc-lang.org/tutorial#builtin-modules>"),
|
||||
]);
|
||||
|
@ -207,7 +207,7 @@ pub fn can_problem<'b>(
|
|||
alloc.symbol_qualified(symbol),
|
||||
alloc.reflow(" was imported here:"),
|
||||
]),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
alloc.concat([
|
||||
alloc.reflow("All types from builtins are automatically exposed, so you can remove "),
|
||||
alloc.symbol_unqualified(symbol),
|
||||
|
@ -230,13 +230,13 @@ pub fn can_problem<'b>(
|
|||
alloc.symbol_qualified(new_symbol),
|
||||
alloc.reflow(":"),
|
||||
]),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
alloc.concat([
|
||||
alloc.reflow("However, the name "),
|
||||
alloc.symbol_unqualified(new_symbol),
|
||||
alloc.reflow(" was already used here:"),
|
||||
]),
|
||||
alloc.region(lines.convert_region(existing_symbol_region)),
|
||||
alloc.region(lines.convert_region(existing_symbol_region), severity),
|
||||
alloc.concat([
|
||||
alloc.reflow("You can rename it, or use the qualified name: "),
|
||||
alloc.symbol_qualified(new_symbol),
|
||||
|
@ -249,7 +249,7 @@ pub fn can_problem<'b>(
|
|||
Problem::DefsOnlyUsedInRecursion(1, region) => {
|
||||
doc = alloc.stack([
|
||||
alloc.reflow("This definition is only used in recursion with itself:"),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
alloc.reflow(
|
||||
"If you don't intend to use or export this definition, it should be removed!",
|
||||
),
|
||||
|
@ -264,7 +264,7 @@ pub fn can_problem<'b>(
|
|||
alloc.string(n.to_string()),
|
||||
alloc.reflow(" definitions are only used in mutual recursion with themselves:"),
|
||||
]),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
alloc.reflow(
|
||||
"If you don't intend to use or export any of them, they should all be removed!",
|
||||
),
|
||||
|
@ -293,7 +293,7 @@ pub fn can_problem<'b>(
|
|||
.reflow("I don't know how to generate the ")
|
||||
.append(alloc.ident(loc_ident.value))
|
||||
.append(alloc.reflow(" function.")),
|
||||
alloc.region(lines.convert_region(loc_ident.region)),
|
||||
alloc.region(lines.convert_region(loc_ident.region), severity),
|
||||
alloc
|
||||
.reflow("Only specific functions like `after` and `map` can be generated.")
|
||||
.append(alloc.reflow("Learn more about hosted modules at TODO.")),
|
||||
|
@ -315,7 +315,7 @@ pub fn can_problem<'b>(
|
|||
alloc.symbol_unqualified(argument_symbol),
|
||||
alloc.text("."),
|
||||
]),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
alloc.concat([
|
||||
alloc.reflow("If you don't need "),
|
||||
alloc.symbol_unqualified(argument_symbol),
|
||||
|
@ -343,7 +343,7 @@ pub fn can_problem<'b>(
|
|||
alloc.keyword("when"),
|
||||
alloc.reflow(" branch."),
|
||||
]),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
alloc.concat([
|
||||
alloc.reflow("If you don't need to use "),
|
||||
alloc.symbol_unqualified(symbol),
|
||||
|
@ -378,7 +378,7 @@ pub fn can_problem<'b>(
|
|||
)),
|
||||
])
|
||||
},
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
]);
|
||||
|
||||
title = SYNTAX_PROBLEM.to_string();
|
||||
|
@ -407,7 +407,7 @@ pub fn can_problem<'b>(
|
|||
alloc
|
||||
.reflow("This pattern is not allowed in ")
|
||||
.append(alloc.reflow(this_thing)),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
alloc.concat(suggestion),
|
||||
]);
|
||||
|
||||
|
@ -419,14 +419,14 @@ pub fn can_problem<'b>(
|
|||
kind,
|
||||
} => {
|
||||
let (res_title, res_doc) =
|
||||
report_shadowing(alloc, lines, original_region, shadow, kind);
|
||||
report_shadowing(alloc, lines, original_region, shadow, kind, severity);
|
||||
|
||||
doc = res_doc;
|
||||
title = res_title.to_string();
|
||||
}
|
||||
Problem::CyclicAlias(symbol, region, others, alias_kind) => {
|
||||
let answer = crate::error::r#type::cyclic_alias(
|
||||
alloc, lines, symbol, region, others, alias_kind,
|
||||
alloc, lines, symbol, region, others, alias_kind, severity,
|
||||
);
|
||||
|
||||
doc = answer.0;
|
||||
|
@ -448,7 +448,7 @@ pub fn can_problem<'b>(
|
|||
alloc.reflow(alias_kind.as_str()),
|
||||
alloc.reflow(" definition:"),
|
||||
]),
|
||||
alloc.region(lines.convert_region(variable_region)),
|
||||
alloc.region(lines.convert_region(variable_region), severity),
|
||||
alloc.reflow("Roc does not allow unused type parameters!"),
|
||||
// TODO add link to this guide section
|
||||
alloc.tip().append(alloc.reflow(
|
||||
|
@ -485,7 +485,7 @@ pub fn can_problem<'b>(
|
|||
alloc.reflow(") type variables. Here is one of them:"),
|
||||
]));
|
||||
}
|
||||
stack.push(alloc.region(lines.convert_region(one_occurrence)));
|
||||
stack.push(alloc.region(lines.convert_region(one_occurrence), severity));
|
||||
stack.push(alloc.concat([
|
||||
alloc.reflow(match kind {
|
||||
AliasKind::Structural => "Type alias",
|
||||
|
@ -526,7 +526,7 @@ pub fn can_problem<'b>(
|
|||
]));
|
||||
stack.push(alloc.reflow("Here is one of them:"));
|
||||
}
|
||||
stack.push(alloc.region(lines.convert_region(one_occurrence)));
|
||||
stack.push(alloc.region(lines.convert_region(one_occurrence), severity));
|
||||
stack.push(alloc.concat([
|
||||
alloc.reflow(match kind {
|
||||
AliasKind::Structural => "Type alias",
|
||||
|
@ -568,7 +568,7 @@ pub fn can_problem<'b>(
|
|||
]));
|
||||
stack.push(alloc.reflow("Here is one of them:"));
|
||||
}
|
||||
stack.push(alloc.region(lines.convert_region(one_occurrence)));
|
||||
stack.push(alloc.region(lines.convert_region(one_occurrence), severity));
|
||||
stack.push(alloc.concat([
|
||||
alloc.reflow("All type variables in "),
|
||||
alloc.reflow(match kind {
|
||||
|
@ -587,7 +587,7 @@ pub fn can_problem<'b>(
|
|||
title = UNDECLARED_TYPE_VARIABLE.to_string();
|
||||
}
|
||||
Problem::BadRecursion(entries) => {
|
||||
doc = to_circular_def_doc(alloc, lines, &entries);
|
||||
doc = to_circular_def_doc(alloc, lines, &entries, severity);
|
||||
title = CIRCULAR_DEF.to_string();
|
||||
}
|
||||
Problem::DuplicateRecordFieldValue {
|
||||
|
@ -716,6 +716,7 @@ pub fn can_problem<'b>(
|
|||
),
|
||||
alloc.region(
|
||||
lines.convert_region(Region::span_across(annotation_pattern, def_pattern)),
|
||||
severity,
|
||||
),
|
||||
alloc.reflow("Is it a typo? If not, put either a newline or comment between them."),
|
||||
]);
|
||||
|
@ -732,7 +733,7 @@ pub fn can_problem<'b>(
|
|||
alloc.symbol_unqualified(type_name),
|
||||
alloc.reflow(" has an unexpected pattern:"),
|
||||
]),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
alloc.concat([
|
||||
alloc.reflow("Only type variables like "),
|
||||
alloc.type_variable("a".into()),
|
||||
|
@ -747,7 +748,7 @@ pub fn can_problem<'b>(
|
|||
Problem::InvalidHexadecimal(region) => {
|
||||
doc = alloc.stack([
|
||||
alloc.reflow("This unicode code point is invalid:"),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
alloc.concat([
|
||||
alloc.reflow(r"I was expecting a hexadecimal number, like "),
|
||||
alloc.parser_suggestion("\\u(1100)"),
|
||||
|
@ -763,7 +764,7 @@ pub fn can_problem<'b>(
|
|||
Problem::InvalidUnicodeCodePt(region) => {
|
||||
doc = alloc.stack([
|
||||
alloc.reflow("This unicode code point is invalid:"),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
alloc.reflow("Learn more about working with unicode in roc at TODO"),
|
||||
]);
|
||||
|
||||
|
@ -772,7 +773,7 @@ pub fn can_problem<'b>(
|
|||
Problem::InvalidInterpolation(region) => {
|
||||
doc = alloc.stack([
|
||||
alloc.reflow("This string interpolation is invalid:"),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
alloc.reflow(r"String interpolations cannot contain newlines or other interpolations."),
|
||||
alloc.reflow(r"You can learn more about string interpolation at <https://www.roc-lang.org/tutorial#string-interpolation>"),
|
||||
]);
|
||||
|
@ -795,13 +796,13 @@ pub fn can_problem<'b>(
|
|||
alloc.symbol_unqualified(alias),
|
||||
alloc.reflow(" is a nested datatype. Here is one recursive usage of it:"),
|
||||
]),
|
||||
alloc.region(lines.convert_region(differing_recursion_region)),
|
||||
alloc.region(lines.convert_region(differing_recursion_region), severity),
|
||||
alloc.concat([
|
||||
alloc.reflow("But recursive usages of "),
|
||||
alloc.symbol_unqualified(alias),
|
||||
alloc.reflow(" must match its definition:"),
|
||||
]),
|
||||
alloc.region(lines.convert_region(def_region)),
|
||||
alloc.region(lines.convert_region(def_region), severity),
|
||||
alloc.reflow("Nested datatypes are not supported in Roc."),
|
||||
alloc.concat([
|
||||
alloc.hint("Consider rewriting the definition of "),
|
||||
|
@ -827,7 +828,7 @@ pub fn can_problem<'b>(
|
|||
alloc.text(kind_str),
|
||||
alloc.reflow(" extension type is invalid:"),
|
||||
]),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
alloc.concat([
|
||||
alloc.note("A "),
|
||||
alloc.reflow(kind_str),
|
||||
|
@ -850,7 +851,7 @@ pub fn can_problem<'b>(
|
|||
alloc.symbol_unqualified(name),
|
||||
alloc.reflow(" ability includes type variables:"),
|
||||
]),
|
||||
alloc.region(lines.convert_region(variables_region)),
|
||||
alloc.region(lines.convert_region(variables_region), severity),
|
||||
alloc.reflow(
|
||||
"Abilities cannot depend on type variables, but their member values can!",
|
||||
),
|
||||
|
@ -865,7 +866,7 @@ pub fn can_problem<'b>(
|
|||
alloc.reflow(
|
||||
r#"The type referenced in this "implements" clause is not an ability:"#,
|
||||
),
|
||||
alloc.region(lines.convert_region(clause_region)),
|
||||
alloc.region(lines.convert_region(clause_region), severity),
|
||||
]);
|
||||
title = IMPLEMENTS_CLAUSE_IS_NOT_AN_ABILITY.to_string();
|
||||
}
|
||||
|
@ -877,7 +878,7 @@ pub fn can_problem<'b>(
|
|||
alloc.keyword(roc_parse::keyword::IMPLEMENTS),
|
||||
alloc.reflow(" clause is not allowed here:"),
|
||||
]),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
alloc.concat([
|
||||
alloc.keyword(roc_parse::keyword::IMPLEMENTS),
|
||||
alloc.reflow(
|
||||
|
@ -895,7 +896,7 @@ pub fn can_problem<'b>(
|
|||
alloc.symbol_foreign_qualified(ability),
|
||||
alloc.reflow(" ability once before:"),
|
||||
]),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
alloc.concat([
|
||||
alloc.reflow("Abilities only need to bound to a type variable once in an "),
|
||||
alloc.keyword(roc_parse::keyword::IMPLEMENTS),
|
||||
|
@ -920,7 +921,7 @@ pub fn can_problem<'b>(
|
|||
alloc.symbol_unqualified(ability),
|
||||
alloc.reflow(":"),
|
||||
]),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
alloc.concat([
|
||||
alloc.reflow("Ability members must include an "),
|
||||
alloc.keyword(roc_parse::keyword::IMPLEMENTS),
|
||||
|
@ -953,7 +954,7 @@ pub fn can_problem<'b>(
|
|||
alloc.symbol_unqualified(ability),
|
||||
alloc.keyword(" ability:"),
|
||||
]),
|
||||
alloc.region(lines.convert_region(span_has_clauses)),
|
||||
alloc.region(lines.convert_region(span_has_clauses), severity),
|
||||
alloc.reflow("Ability members can only bind one type variable to their parent ability. Otherwise, I wouldn't know what type implements an ability by looking at specializations!"),
|
||||
alloc.concat([
|
||||
alloc.hint("Did you mean to only bind "),
|
||||
|
@ -971,7 +972,7 @@ pub fn can_problem<'b>(
|
|||
alloc
|
||||
.concat([alloc
|
||||
.reflow("This ability definition is not on the top-level of a module:")]),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
alloc.reflow("Abilities can only be defined on the top-level of a Roc module."),
|
||||
]);
|
||||
title = ABILITY_NOT_ON_TOPLEVEL.to_string();
|
||||
|
@ -984,7 +985,7 @@ pub fn can_problem<'b>(
|
|||
alloc.symbol_unqualified(ability),
|
||||
alloc.reflow(" as a type directly:"),
|
||||
]),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
alloc.reflow(
|
||||
"Abilities can only be used in type annotations to constrain type variables.",
|
||||
),
|
||||
|
@ -1010,7 +1011,7 @@ pub fn can_problem<'b>(
|
|||
alloc.symbol_unqualified(member),
|
||||
alloc.reflow(" ability member is in a nested scope:"),
|
||||
]),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
alloc.reflow("Specializations can only be defined on the top-level of a module."),
|
||||
]);
|
||||
title = SPECIALIZATION_NOT_ON_TOPLEVEL.to_string();
|
||||
|
@ -1018,7 +1019,7 @@ pub fn can_problem<'b>(
|
|||
Problem::IllegalDerivedAbility(region) => {
|
||||
doc = alloc.stack([
|
||||
alloc.reflow("This ability cannot be derived:"),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
alloc.reflow("Only builtin abilities can be derived."),
|
||||
alloc
|
||||
.note("The builtin abilities are ")
|
||||
|
@ -1029,7 +1030,7 @@ pub fn can_problem<'b>(
|
|||
Problem::NotAnAbility(region) => {
|
||||
doc = alloc.stack([
|
||||
alloc.reflow("This identifier is not an ability in scope:"),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
alloc.reflow("Only abilities can be implemented."),
|
||||
]);
|
||||
title = NOT_AN_ABILITY.to_string();
|
||||
|
@ -1043,7 +1044,7 @@ pub fn can_problem<'b>(
|
|||
alloc.concat([
|
||||
alloc.reflow("The "), alloc.symbol_unqualified(ability), alloc.reflow(" ability does not have a member "), alloc.string(name),
|
||||
]),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
alloc.reflow("Only implementations for members an ability has can be specified in this location.")
|
||||
]);
|
||||
title = NOT_AN_ABILITY_MEMBER.to_string();
|
||||
|
@ -1054,7 +1055,7 @@ pub fn can_problem<'b>(
|
|||
alloc.concat([
|
||||
alloc.reflow("An implementation of "), alloc.symbol_unqualified(member), alloc.reflow(" could not be found in this scope:"),
|
||||
]),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
alloc.tip().append(alloc.concat([alloc.reflow("consider adding a value of name "), alloc.symbol_unqualified(member), alloc.reflow(" in this scope, or using another variable that implements this ability member, like "), alloc.type_str(&format!("{{ {member_str}: my{member_str} }}"))]))
|
||||
]);
|
||||
title = IMPLEMENTATION_NOT_FOUND.to_string();
|
||||
|
@ -1071,7 +1072,7 @@ pub fn can_problem<'b>(
|
|||
|
||||
doc = alloc.stack([
|
||||
alloc.reflow("Ability implementations cannot be optional:"),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
alloc.reflow("Custom implementations must be supplied fully."),
|
||||
hint,
|
||||
]);
|
||||
|
@ -1080,7 +1081,7 @@ pub fn can_problem<'b>(
|
|||
Problem::QualifiedAbilityImpl { region } => {
|
||||
doc = alloc.stack([
|
||||
alloc.reflow("This ability implementation is qualified:"),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
alloc.reflow(
|
||||
"Custom implementations must be defined in the local scope, and unqualified.",
|
||||
),
|
||||
|
@ -1090,7 +1091,7 @@ pub fn can_problem<'b>(
|
|||
Problem::AbilityImplNotIdent { region } => {
|
||||
doc = alloc.stack([
|
||||
alloc.reflow("This ability implementation is not an identifier:"),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
alloc.reflow(
|
||||
"Custom ability implementations defined in this position can only be unqualified identifiers, not arbitrary expressions.",
|
||||
),
|
||||
|
@ -1104,9 +1105,9 @@ pub fn can_problem<'b>(
|
|||
} => {
|
||||
doc = alloc.stack([
|
||||
alloc.reflow("This ability member implementation is duplicate:"),
|
||||
alloc.region(lines.convert_region(duplicate)),
|
||||
alloc.region(lines.convert_region(duplicate), severity),
|
||||
alloc.reflow("The first implementation was defined here:"),
|
||||
alloc.region(lines.convert_region(original)),
|
||||
alloc.region(lines.convert_region(original), severity),
|
||||
alloc
|
||||
.reflow("Only one custom implementation can be defined for an ability member."),
|
||||
]);
|
||||
|
@ -1123,7 +1124,7 @@ pub fn can_problem<'b>(
|
|||
alloc.symbol_unqualified(ability),
|
||||
alloc.reflow(" ability:"),
|
||||
]),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
alloc.reflow("The following implemented members should not be listed:"),
|
||||
alloc.type_block(
|
||||
alloc.intersperse(
|
||||
|
@ -1147,7 +1148,7 @@ pub fn can_problem<'b>(
|
|||
alloc.symbol_unqualified(ability),
|
||||
alloc.reflow(" ability:"),
|
||||
]),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
alloc.reflow("The following necessary members are missing implementations:"),
|
||||
alloc.type_block(
|
||||
alloc.intersperse(
|
||||
|
@ -1171,7 +1172,7 @@ pub fn can_problem<'b>(
|
|||
alloc.keyword("when"),
|
||||
alloc.reflow(" branch"),
|
||||
]),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
alloc.concat([
|
||||
alloc.reflow("Identifiers introduced in a "),
|
||||
alloc.keyword("when"),
|
||||
|
@ -1183,7 +1184,7 @@ pub fn can_problem<'b>(
|
|||
Problem::NoIdentifiersIntroduced(region) => {
|
||||
doc = alloc.stack([
|
||||
alloc.reflow("This destructure assignment doesn't introduce any new variables:"),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
alloc.reflow("If you don't need to use the value on the right-hand-side of this assignment, consider removing the assignment. Since Roc is purely functional, assignments that don't introduce variables cannot affect a program's behavior!"),
|
||||
]);
|
||||
title = "UNNECESSARY DEFINITION".to_string();
|
||||
|
@ -1195,7 +1196,7 @@ pub fn can_problem<'b>(
|
|||
} => {
|
||||
doc = alloc.stack([
|
||||
alloc.reflow("This ability member specialization is already claimed to specialize another opaque type:"),
|
||||
alloc.region(lines.convert_region(overload)),
|
||||
alloc.region(lines.convert_region(overload), severity),
|
||||
alloc.concat([
|
||||
alloc.reflow("Previously, we found it to specialize "),
|
||||
alloc.symbol_unqualified(ability_member),
|
||||
|
@ -1214,7 +1215,7 @@ pub fn can_problem<'b>(
|
|||
alloc.keyword("*"),
|
||||
alloc.reflow(") that isn't needed."),
|
||||
]),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
alloc.concat([
|
||||
alloc.reflow("Annotations for tag unions which are constants, or which are returned from functions, work the same way with or without a "),
|
||||
alloc.keyword("*"),
|
||||
|
@ -1229,7 +1230,7 @@ pub fn can_problem<'b>(
|
|||
Problem::MultipleListRestPattern { region } => {
|
||||
doc = alloc.stack([
|
||||
alloc.reflow("This list pattern match has multiple rest patterns:"),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
alloc.concat([
|
||||
alloc.reflow("I only support compiling list patterns with one "),
|
||||
alloc.parser_suggestion(".."),
|
||||
|
@ -1267,7 +1268,7 @@ pub fn can_problem<'b>(
|
|||
found_arguments,
|
||||
alloc.reflow(" instead:"),
|
||||
]),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
alloc.reflow("Are there missing parentheses?"),
|
||||
]);
|
||||
|
||||
|
@ -1282,7 +1283,7 @@ pub fn can_problem<'b>(
|
|||
alloc.concat([
|
||||
alloc.reflow("This "), alloc.keyword("crash"), alloc.reflow(" doesn't have a message given to it:")
|
||||
]),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
alloc.concat([
|
||||
alloc.keyword("crash"), alloc.reflow(" must be passed a message to crash with at the exact place it's used. "),
|
||||
alloc.keyword("crash"), alloc.reflow(" can't be used as a value that's passed around, like functions can be - it must be applied immediately!"),
|
||||
|
@ -1297,10 +1298,10 @@ pub fn can_problem<'b>(
|
|||
alloc.keyword("crash"),
|
||||
alloc.reflow(" has too many values given to it:"),
|
||||
]),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
alloc.concat([
|
||||
alloc.keyword("crash"),
|
||||
alloc.reflow(" must be given exacly one message to crash with."),
|
||||
alloc.reflow(" must be given exactly one message to crash with."),
|
||||
]),
|
||||
]);
|
||||
title = "OVERAPPLIED CRASH".to_string();
|
||||
|
@ -1384,6 +1385,7 @@ fn to_bad_ident_expr_report<'b>(
|
|||
lines: &LineInfo,
|
||||
bad_ident: roc_parse::ident::BadIdent,
|
||||
surroundings: Region,
|
||||
severity: Severity,
|
||||
) -> RocDocBuilder<'b> {
|
||||
use roc_parse::ident::BadIdent::*;
|
||||
|
||||
|
@ -1394,7 +1396,7 @@ fn to_bad_ident_expr_report<'b>(
|
|||
|
||||
alloc.stack([
|
||||
alloc.reflow(r"I am trying to parse a record field access here:"),
|
||||
alloc.region_with_subregion(lines.convert_region(surroundings), region),
|
||||
alloc.region_with_subregion(lines.convert_region(surroundings), region, severity),
|
||||
alloc.concat([
|
||||
alloc.reflow("So I expect to see a lowercase letter next, like "),
|
||||
alloc.parser_suggestion(".name"),
|
||||
|
@ -1407,7 +1409,7 @@ fn to_bad_ident_expr_report<'b>(
|
|||
|
||||
WeirdAccessor(_pos) => alloc.stack([
|
||||
alloc.reflow("I am very confused by this field access"),
|
||||
alloc.region(lines.convert_region(surroundings)),
|
||||
alloc.region(lines.convert_region(surroundings), severity),
|
||||
alloc.concat([
|
||||
alloc.reflow("It looks like a field access on an accessor. I parse"),
|
||||
alloc.parser_suggestion(".client.name"),
|
||||
|
@ -1425,7 +1427,7 @@ fn to_bad_ident_expr_report<'b>(
|
|||
|
||||
alloc.stack([
|
||||
alloc.reflow("I am trying to parse a qualified name here:"),
|
||||
alloc.region_with_subregion(lines.convert_region(surroundings), region),
|
||||
alloc.region_with_subregion(lines.convert_region(surroundings), region, severity),
|
||||
alloc.concat([
|
||||
alloc.reflow("I was expecting to see an identifier next, like "),
|
||||
alloc.parser_suggestion("height"),
|
||||
|
@ -1440,7 +1442,7 @@ fn to_bad_ident_expr_report<'b>(
|
|||
|
||||
alloc.stack([
|
||||
alloc.reflow("I am trying to parse a qualified name here:"),
|
||||
alloc.region_with_subregion(lines.convert_region(surroundings), region),
|
||||
alloc.region_with_subregion(lines.convert_region(surroundings), region, severity),
|
||||
alloc.concat([
|
||||
alloc.reflow("This looks like a tuple accessor on a module or tag name,"),
|
||||
alloc.reflow(r"but neither modules nor tags can have tuple elements! "),
|
||||
|
@ -1455,7 +1457,7 @@ fn to_bad_ident_expr_report<'b>(
|
|||
|
||||
alloc.stack([
|
||||
alloc.reflow("I am trying to parse a qualified name here:"),
|
||||
alloc.region_with_subregion(lines.convert_region(surroundings), region),
|
||||
alloc.region_with_subregion(lines.convert_region(surroundings), region, severity),
|
||||
alloc.concat([
|
||||
alloc.reflow(r"This looks like a qualified tag name to me, "),
|
||||
alloc.reflow(r"but tags cannot be qualified! "),
|
||||
|
@ -1469,7 +1471,7 @@ fn to_bad_ident_expr_report<'b>(
|
|||
UnderscoreAlone(_pos) => {
|
||||
alloc.stack([
|
||||
alloc.reflow("An underscore is being used as a variable here:"),
|
||||
alloc.region(lines.convert_region(surroundings)),
|
||||
alloc.region(lines.convert_region(surroundings), severity),
|
||||
alloc.concat([alloc
|
||||
.reflow(r"An underscore can be used to ignore a value when pattern matching, but it cannot be used as a variable.")]),
|
||||
])
|
||||
|
@ -1478,7 +1480,7 @@ fn to_bad_ident_expr_report<'b>(
|
|||
UnderscoreInMiddle(_pos) => {
|
||||
alloc.stack([
|
||||
alloc.reflow("Underscores are not allowed in identifier names:"),
|
||||
alloc.region(lines.convert_region(surroundings)),
|
||||
alloc.region(lines.convert_region(surroundings), severity),
|
||||
alloc.concat([alloc
|
||||
.reflow(r"I recommend using camelCase. It's the standard style in Roc code!")]),
|
||||
])
|
||||
|
@ -1494,11 +1496,11 @@ fn to_bad_ident_expr_report<'b>(
|
|||
None => alloc.reflow(line),
|
||||
Some(declaration_region) => alloc.stack([
|
||||
alloc.reflow(line),
|
||||
alloc.region(lines.convert_region(declaration_region)),
|
||||
alloc.region(lines.convert_region(declaration_region), severity),
|
||||
alloc.reflow("But then it is used here:"),
|
||||
])
|
||||
},
|
||||
alloc.region(lines.convert_region(surroundings)),
|
||||
alloc.region(lines.convert_region(surroundings), severity),
|
||||
alloc.concat([
|
||||
alloc.reflow(r"A variable's name can only start with an underscore if the variable is unused. "),
|
||||
match declaration_region {
|
||||
|
@ -1521,6 +1523,7 @@ fn to_bad_ident_expr_report<'b>(
|
|||
alloc.region_with_subregion(
|
||||
lines.convert_region(surroundings),
|
||||
lines.convert_region(region),
|
||||
severity
|
||||
),
|
||||
alloc.concat([
|
||||
alloc.reflow(r"It looks like a record field access on "),
|
||||
|
@ -1536,6 +1539,7 @@ fn to_bad_ident_expr_report<'b>(
|
|||
alloc.region_with_subregion(
|
||||
lines.convert_region(surroundings),
|
||||
lines.convert_region(region),
|
||||
severity
|
||||
),
|
||||
alloc.concat([
|
||||
alloc.reflow(r"Looks like "),
|
||||
|
@ -1559,6 +1563,7 @@ fn to_bad_ident_expr_report<'b>(
|
|||
alloc.region_with_subregion(
|
||||
lines.convert_region(surroundings),
|
||||
lines.convert_region(region),
|
||||
severity,
|
||||
),
|
||||
alloc.concat([
|
||||
alloc.reflow(r"But after the "),
|
||||
|
@ -1584,6 +1589,7 @@ fn to_bad_ident_pattern_report<'b>(
|
|||
lines: &LineInfo,
|
||||
bad_ident: roc_parse::ident::BadIdent,
|
||||
surroundings: Region,
|
||||
severity: Severity,
|
||||
) -> RocDocBuilder<'b> {
|
||||
use roc_parse::ident::BadIdent::*;
|
||||
|
||||
|
@ -1594,7 +1600,7 @@ fn to_bad_ident_pattern_report<'b>(
|
|||
|
||||
alloc.stack([
|
||||
alloc.reflow(r"I am trying to parse a record field accessor here:"),
|
||||
alloc.region_with_subregion(lines.convert_region(surroundings), region),
|
||||
alloc.region_with_subregion(lines.convert_region(surroundings), region, severity),
|
||||
alloc.concat([
|
||||
alloc.reflow("Something like "),
|
||||
alloc.parser_suggestion(".name"),
|
||||
|
@ -1607,7 +1613,7 @@ fn to_bad_ident_pattern_report<'b>(
|
|||
|
||||
WeirdAccessor(_pos) => alloc.stack([
|
||||
alloc.reflow("I am very confused by this field access"),
|
||||
alloc.region(lines.convert_region(surroundings)),
|
||||
alloc.region(lines.convert_region(surroundings), severity),
|
||||
alloc.concat([
|
||||
alloc.reflow("It looks like a field access on an accessor. I parse"),
|
||||
alloc.parser_suggestion(".client.name"),
|
||||
|
@ -1625,7 +1631,7 @@ fn to_bad_ident_pattern_report<'b>(
|
|||
|
||||
alloc.stack([
|
||||
alloc.reflow("I am trying to parse a qualified name here:"),
|
||||
alloc.region_with_subregion(lines.convert_region(surroundings), region),
|
||||
alloc.region_with_subregion(lines.convert_region(surroundings), region, severity),
|
||||
alloc.concat([
|
||||
alloc.reflow("I was expecting to see an identifier next, like "),
|
||||
alloc.parser_suggestion("height"),
|
||||
|
@ -1640,7 +1646,7 @@ fn to_bad_ident_pattern_report<'b>(
|
|||
|
||||
alloc.stack([
|
||||
alloc.reflow("I am trying to parse a qualified name here:"),
|
||||
alloc.region_with_subregion(lines.convert_region(surroundings), region),
|
||||
alloc.region_with_subregion(lines.convert_region(surroundings), region, severity),
|
||||
alloc.concat([
|
||||
alloc.reflow(r"This looks like a qualified tag name to me, "),
|
||||
alloc.reflow(r"but tags cannot be qualified! "),
|
||||
|
@ -1665,6 +1671,7 @@ fn to_bad_ident_pattern_report<'b>(
|
|||
alloc.region_with_subregion(
|
||||
lines.convert_region(surroundings),
|
||||
lines.convert_region(region),
|
||||
severity,
|
||||
),
|
||||
alloc.concat([alloc.reflow(
|
||||
r"Underscores are not allowed in identifiers. Use camelCase instead!",
|
||||
|
@ -1677,7 +1684,7 @@ fn to_bad_ident_pattern_report<'b>(
|
|||
|
||||
alloc.stack([
|
||||
alloc.reflow("This opaque type reference has an invalid name:"),
|
||||
alloc.region_with_subregion(lines.convert_region(surroundings), region),
|
||||
alloc.region_with_subregion(lines.convert_region(surroundings), region, severity),
|
||||
alloc.concat([
|
||||
alloc.reflow(r"Opaque type names must begin with a capital letter, "),
|
||||
alloc.reflow(r"and must contain only letters and numbers."),
|
||||
|
@ -1756,6 +1763,7 @@ fn report_shadowing<'b>(
|
|||
original_region: Region,
|
||||
shadow: Loc<Ident>,
|
||||
kind: ShadowKind,
|
||||
severity: Severity,
|
||||
) -> (&'static str, RocDocBuilder<'b>) {
|
||||
let (what, what_plural, is_builtin) = match kind {
|
||||
ShadowKind::Variable => ("variable", "variables", false),
|
||||
|
@ -1771,7 +1779,7 @@ fn report_shadowing<'b>(
|
|||
alloc.reflow(what),
|
||||
alloc.reflow(" has the same name as a builtin:"),
|
||||
]),
|
||||
alloc.region(lines.convert_region(shadow.region)),
|
||||
alloc.region(lines.convert_region(shadow.region), severity),
|
||||
alloc.concat([
|
||||
alloc.reflow("All builtin "),
|
||||
alloc.reflow(what_plural),
|
||||
|
@ -1786,9 +1794,9 @@ fn report_shadowing<'b>(
|
|||
.text("The ")
|
||||
.append(alloc.ident(shadow.value))
|
||||
.append(alloc.reflow(" name is first defined here:")),
|
||||
alloc.region(lines.convert_region(original_region)),
|
||||
alloc.region(lines.convert_region(original_region), severity),
|
||||
alloc.reflow("But then it's defined a second time here:"),
|
||||
alloc.region(lines.convert_region(shadow.region)),
|
||||
alloc.region(lines.convert_region(shadow.region), severity),
|
||||
alloc.concat([
|
||||
alloc.reflow("Since these "),
|
||||
alloc.reflow(what_plural),
|
||||
|
@ -1808,6 +1816,8 @@ fn pretty_runtime_error<'b>(
|
|||
let doc;
|
||||
let title;
|
||||
|
||||
let severity = Severity::RuntimeError;
|
||||
|
||||
match runtime_error {
|
||||
RuntimeError::VoidValue => {
|
||||
// is used to communicate to the compiler that
|
||||
|
@ -1825,7 +1835,7 @@ fn pretty_runtime_error<'b>(
|
|||
shadow,
|
||||
kind,
|
||||
} => {
|
||||
(title, doc) = report_shadowing(alloc, lines, original_region, shadow, kind);
|
||||
(title, doc) = report_shadowing(alloc, lines, original_region, shadow, kind, severity);
|
||||
}
|
||||
|
||||
RuntimeError::LookupNotInScope {
|
||||
|
@ -1840,11 +1850,12 @@ fn pretty_runtime_error<'b>(
|
|||
&loc_name.value,
|
||||
options,
|
||||
underscored_suggestion_region,
|
||||
severity,
|
||||
);
|
||||
title = UNRECOGNIZED_NAME;
|
||||
}
|
||||
RuntimeError::CircularDef(entries) => {
|
||||
doc = to_circular_def_doc(alloc, lines, &entries);
|
||||
doc = to_circular_def_doc(alloc, lines, &entries, severity);
|
||||
title = CIRCULAR_DEF;
|
||||
}
|
||||
RuntimeError::MalformedPattern(problem, region) => {
|
||||
|
@ -1860,7 +1871,7 @@ fn pretty_runtime_error<'b>(
|
|||
MalformedBase(Base::Decimal) => " integer ",
|
||||
BadIdent(bad_ident) => {
|
||||
title = NAMING_PROBLEM;
|
||||
doc = to_bad_ident_pattern_report(alloc, lines, bad_ident, region);
|
||||
doc = to_bad_ident_pattern_report(alloc, lines, bad_ident, region, severity);
|
||||
|
||||
return (doc, title);
|
||||
}
|
||||
|
@ -1892,7 +1903,7 @@ fn pretty_runtime_error<'b>(
|
|||
alloc.text(name),
|
||||
alloc.reflow("pattern is malformed:"),
|
||||
]),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
tip,
|
||||
]);
|
||||
|
||||
|
@ -1933,7 +1944,7 @@ fn pretty_runtime_error<'b>(
|
|||
alloc.string(ident.to_string()),
|
||||
alloc.reflow("`:"),
|
||||
]),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
did_you_mean,
|
||||
]);
|
||||
|
||||
|
@ -1953,6 +1964,7 @@ fn pretty_runtime_error<'b>(
|
|||
&module_name,
|
||||
imported_modules,
|
||||
module_exists,
|
||||
severity,
|
||||
);
|
||||
|
||||
title = MODULE_NOT_IMPORTED;
|
||||
|
@ -1972,14 +1984,14 @@ fn pretty_runtime_error<'b>(
|
|||
unreachable!();
|
||||
}
|
||||
RuntimeError::MalformedIdentifier(_box_str, bad_ident, surroundings) => {
|
||||
doc = to_bad_ident_expr_report(alloc, lines, bad_ident, surroundings);
|
||||
doc = to_bad_ident_expr_report(alloc, lines, bad_ident, surroundings, severity);
|
||||
|
||||
title = SYNTAX_PROBLEM;
|
||||
}
|
||||
RuntimeError::MalformedTypeName(_box_str, surroundings) => {
|
||||
doc = alloc.stack([
|
||||
alloc.reflow(r"I am confused by this type name:"),
|
||||
alloc.region(lines.convert_region(surroundings)),
|
||||
alloc.region(lines.convert_region(surroundings), severity),
|
||||
alloc.concat([
|
||||
alloc.reflow("Type names start with an uppercase letter, "),
|
||||
alloc.reflow("and can optionally be qualified by a module name, like "),
|
||||
|
@ -2016,7 +2028,7 @@ fn pretty_runtime_error<'b>(
|
|||
alloc.text(big_or_small),
|
||||
alloc.reflow(":"),
|
||||
]),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
alloc.concat([
|
||||
alloc
|
||||
.reflow("Roc uses signed 64-bit floating points, allowing values between "),
|
||||
|
@ -2038,7 +2050,7 @@ fn pretty_runtime_error<'b>(
|
|||
alloc.concat([
|
||||
alloc.reflow("This float literal contains an invalid digit:"),
|
||||
]),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
alloc.concat([
|
||||
alloc.reflow("Floating point literals can only contain the digits 0-9, or use scientific notation 10e4, or have a float suffix."),
|
||||
]),
|
||||
|
@ -2052,7 +2064,7 @@ fn pretty_runtime_error<'b>(
|
|||
alloc
|
||||
.concat([alloc
|
||||
.reflow("This number literal is a float, but it has an integer suffix:")]),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
]);
|
||||
|
||||
title = CONFLICTING_NUMBER_SUFFIX;
|
||||
|
@ -2106,7 +2118,7 @@ fn pretty_runtime_error<'b>(
|
|||
alloc.text(problem),
|
||||
alloc.text(":"),
|
||||
]),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
alloc.concat([
|
||||
alloc.text(plurals),
|
||||
contains,
|
||||
|
@ -2154,7 +2166,7 @@ fn pretty_runtime_error<'b>(
|
|||
alloc.text(big_or_small),
|
||||
alloc.reflow(":"),
|
||||
]),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
info,
|
||||
tip,
|
||||
]);
|
||||
|
@ -2166,7 +2178,7 @@ fn pretty_runtime_error<'b>(
|
|||
alloc
|
||||
.concat([alloc
|
||||
.reflow("This number literal is an integer, but it has a float suffix:")]),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
]);
|
||||
|
||||
title = CONFLICTING_NUMBER_SUFFIX;
|
||||
|
@ -2183,7 +2195,7 @@ fn pretty_runtime_error<'b>(
|
|||
doc = alloc.stack([
|
||||
alloc.concat([alloc
|
||||
.reflow("This integer literal overflows the type indicated by its suffix:")]),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
alloc.tip().append(alloc.concat([
|
||||
alloc.reflow("The suffix indicates this integer is a "),
|
||||
alloc.type_str(suffix_type),
|
||||
|
@ -2207,7 +2219,7 @@ fn pretty_runtime_error<'b>(
|
|||
doc = alloc.stack([
|
||||
alloc.concat([alloc
|
||||
.reflow("This integer literal underflows the type indicated by its suffix:")]),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
alloc.tip().append(alloc.concat([
|
||||
alloc.reflow("The suffix indicates this integer is a "),
|
||||
alloc.type_str(suffix_type),
|
||||
|
@ -2240,7 +2252,7 @@ fn pretty_runtime_error<'b>(
|
|||
alloc.reflow("This expression cannot be updated"),
|
||||
alloc.reflow(":"),
|
||||
]),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
alloc.reflow("Only variables can be updated with record update syntax."),
|
||||
]);
|
||||
|
||||
|
@ -2286,7 +2298,7 @@ fn pretty_runtime_error<'b>(
|
|||
|
||||
doc = alloc.stack([
|
||||
alloc.concat([alloc.reflow("This character literal is empty.")]),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
tip,
|
||||
]);
|
||||
|
||||
|
@ -2301,7 +2313,7 @@ fn pretty_runtime_error<'b>(
|
|||
alloc.concat([
|
||||
alloc.reflow("This character literal contains more than one code point.")
|
||||
]),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
alloc.concat([alloc.reflow("Character literals can only contain one code point.")]),
|
||||
tip,
|
||||
]);
|
||||
|
@ -2342,13 +2354,13 @@ fn pretty_runtime_error<'b>(
|
|||
alloc.type_str(opaque.as_inline_str().as_str()),
|
||||
alloc.reflow(" referenced here is not defined:"),
|
||||
]),
|
||||
alloc.region(lines.convert_region(used_region)),
|
||||
alloc.region(lines.convert_region(used_region), severity),
|
||||
];
|
||||
|
||||
if let Some(defined_alias_region) = opt_defined_alias {
|
||||
stack.push(alloc.stack([
|
||||
alloc.note("There is an alias of the same name:"),
|
||||
alloc.region(lines.convert_region(defined_alias_region)),
|
||||
alloc.region(lines.convert_region(defined_alias_region), severity),
|
||||
]));
|
||||
}
|
||||
|
||||
|
@ -2369,9 +2381,9 @@ fn pretty_runtime_error<'b>(
|
|||
alloc.type_str(opaque.as_inline_str().as_str()),
|
||||
alloc.reflow(" referenced here:"),
|
||||
]),
|
||||
alloc.region(lines.convert_region(referenced_region)),
|
||||
alloc.region(lines.convert_region(referenced_region), severity),
|
||||
alloc.reflow("is imported from another module:"),
|
||||
alloc.region(lines.convert_region(imported_region)),
|
||||
alloc.region(lines.convert_region(imported_region), severity),
|
||||
alloc.note(
|
||||
"Opaque types can only be wrapped and unwrapped in the module they are defined in!",
|
||||
),
|
||||
|
@ -2382,7 +2394,7 @@ fn pretty_runtime_error<'b>(
|
|||
RuntimeError::OpaqueNotApplied(loc_ident) => {
|
||||
doc = alloc.stack([
|
||||
alloc.reflow("This opaque type is not applied to an argument:"),
|
||||
alloc.region(lines.convert_region(loc_ident.region)),
|
||||
alloc.region(lines.convert_region(loc_ident.region), severity),
|
||||
alloc.note("Opaque types always wrap exactly one argument!"),
|
||||
]);
|
||||
|
||||
|
@ -2391,7 +2403,7 @@ fn pretty_runtime_error<'b>(
|
|||
RuntimeError::OpaqueAppliedToMultipleArgs(region) => {
|
||||
doc = alloc.stack([
|
||||
alloc.reflow("This opaque type is applied to multiple arguments:"),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
alloc.note("Opaque types always wrap exactly one argument!"),
|
||||
]);
|
||||
|
||||
|
@ -2400,7 +2412,7 @@ fn pretty_runtime_error<'b>(
|
|||
RuntimeError::DegenerateBranch(region) => {
|
||||
doc = alloc.stack([
|
||||
alloc.reflow("This branch pattern does not bind all symbols its body needs:"),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
]);
|
||||
|
||||
title = "DEGENERATE BRANCH";
|
||||
|
@ -2412,7 +2424,7 @@ fn pretty_runtime_error<'b>(
|
|||
|
||||
doc = alloc.stack([
|
||||
alloc.reflow("This function is applied to multiple record builders:"),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
alloc.note("Functions can only take at most one record builder!"),
|
||||
tip,
|
||||
]);
|
||||
|
@ -2422,7 +2434,7 @@ fn pretty_runtime_error<'b>(
|
|||
RuntimeError::UnappliedRecordBuilder(region) => {
|
||||
doc = alloc.stack([
|
||||
alloc.reflow("This record builder was not applied to a function:"),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
alloc.reflow("However, we need a function to construct the record."),
|
||||
alloc.note(
|
||||
"Functions must be applied directly. The pipe operator (|>) cannot be used.",
|
||||
|
@ -2440,6 +2452,7 @@ pub fn to_circular_def_doc<'b>(
|
|||
alloc: &'b RocDocAllocator<'b>,
|
||||
lines: &LineInfo,
|
||||
entries: &[roc_problem::can::CycleEntry],
|
||||
severity: Severity,
|
||||
) -> RocDocBuilder<'b> {
|
||||
// TODO "are you trying to mutate a variable?
|
||||
// TODO tip?
|
||||
|
@ -2451,7 +2464,7 @@ pub fn to_circular_def_doc<'b>(
|
|||
alloc.symbol_unqualified(*symbol),
|
||||
alloc.reflow(" is defined directly in terms of itself:"),
|
||||
]),
|
||||
alloc.region(lines.convert_region(Region::span_across(symbol_region, expr_region))),
|
||||
alloc.region(lines.convert_region(Region::span_across(symbol_region, expr_region)), severity),
|
||||
alloc.reflow("Roc evaluates values strictly, so running this program would enter an infinite loop!"),
|
||||
alloc.hint("").append(alloc.concat([
|
||||
alloc.reflow("Did you mean to define "),alloc.symbol_unqualified(*symbol),alloc.reflow(" as a function?"),
|
||||
|
@ -2463,7 +2476,7 @@ pub fn to_circular_def_doc<'b>(
|
|||
.reflow("The ")
|
||||
.append(alloc.symbol_unqualified(first.symbol))
|
||||
.append(alloc.reflow(" definition is causing a very tricky infinite loop:")),
|
||||
alloc.region(lines.convert_region(first.symbol_region)),
|
||||
alloc.region(lines.convert_region(first.symbol_region), severity),
|
||||
alloc
|
||||
.reflow("The ")
|
||||
.append(alloc.symbol_unqualified(first.symbol))
|
||||
|
@ -2492,6 +2505,7 @@ fn not_found<'b>(
|
|||
name: &Ident,
|
||||
options: MutSet<Box<str>>,
|
||||
underscored_suggestion_region: Option<Region>,
|
||||
severity: Severity,
|
||||
) -> RocDocBuilder<'b> {
|
||||
let mut suggestions = suggest::sort(
|
||||
name.as_inline_str().as_str(),
|
||||
|
@ -2510,7 +2524,7 @@ fn not_found<'b>(
|
|||
let default_yes = match underscored_suggestion_region {
|
||||
Some(underscored_region) => alloc.stack([
|
||||
alloc.reflow("There is an ignored identifier of a similar name here:"),
|
||||
alloc.region(lines.convert_region(underscored_region)),
|
||||
alloc.region(lines.convert_region(underscored_region), severity),
|
||||
alloc.reflow("Did you mean to remove the leading underscore?"),
|
||||
alloc.reflow("If not, did you mean one of these?"),
|
||||
]),
|
||||
|
@ -2536,7 +2550,7 @@ fn not_found<'b>(
|
|||
alloc.string(name.to_string()),
|
||||
alloc.reflow("` in this scope."),
|
||||
]),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
to_details(default_no, default_yes),
|
||||
])
|
||||
}
|
||||
|
@ -2551,13 +2565,14 @@ fn module_not_found<'b>(
|
|||
name: &ModuleName,
|
||||
options: MutSet<Box<str>>,
|
||||
module_exists: bool,
|
||||
severity: Severity,
|
||||
) -> RocDocBuilder<'b> {
|
||||
// If the module exists, sugguest that the user import it
|
||||
// If the module exists, suggest that the user import it
|
||||
let details = if module_exists {
|
||||
// TODO: Maybe give an example of how to do that
|
||||
alloc.reflow("Did you mean to import it?")
|
||||
} else {
|
||||
// If the module might not exist, sugguest that it's a typo
|
||||
// If the module might not exist, suggest that it's a typo
|
||||
let mut suggestions =
|
||||
suggest::sort(name.as_str(), options.iter().map(|v| v.as_ref()).collect());
|
||||
suggestions.truncate(4);
|
||||
|
@ -2587,7 +2602,7 @@ fn module_not_found<'b>(
|
|||
alloc.string(name.to_string()),
|
||||
alloc.reflow("` module is not imported:"),
|
||||
]),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
details,
|
||||
])
|
||||
}
|
||||
|
|
|
@ -80,6 +80,7 @@ impl<'a> Renderer<'a> {
|
|||
symbols: &[Symbol],
|
||||
variables: &[Variable],
|
||||
expressions: &[Expr<'_>],
|
||||
severity: Severity,
|
||||
) -> RocDocBuilder<'a> {
|
||||
use ven_pretty::DocAllocator;
|
||||
|
||||
|
@ -96,7 +97,7 @@ impl<'a> Renderer<'a> {
|
|||
if it.len() > 0 {
|
||||
self.alloc.stack([
|
||||
self.alloc.text("This expectation failed:"),
|
||||
self.alloc.region(line_col_region),
|
||||
self.alloc.region(line_col_region, severity),
|
||||
self.alloc
|
||||
.text("When it failed, these variables had these values:"),
|
||||
self.alloc.stack(it),
|
||||
|
@ -105,7 +106,7 @@ impl<'a> Renderer<'a> {
|
|||
} else {
|
||||
self.alloc.stack([
|
||||
self.alloc.text("This expectation failed:"),
|
||||
self.alloc.region(line_col_region),
|
||||
self.alloc.region(line_col_region, severity),
|
||||
self.alloc.text(""), // Blank line at the end
|
||||
])
|
||||
}
|
||||
|
@ -147,15 +148,23 @@ impl<'a> Renderer<'a> {
|
|||
W: std::io::Write,
|
||||
{
|
||||
use crate::report::Report;
|
||||
let severity = Severity::RuntimeError;
|
||||
|
||||
let line_col_region = self.to_line_col_region(expect_region, failure_region);
|
||||
let doc = self.render_lookups(subs, line_col_region, symbols, variables, expressions);
|
||||
let doc = self.render_lookups(
|
||||
subs,
|
||||
line_col_region,
|
||||
symbols,
|
||||
variables,
|
||||
expressions,
|
||||
severity,
|
||||
);
|
||||
|
||||
let report = Report {
|
||||
title: "EXPECT FAILED".into(),
|
||||
doc,
|
||||
filename: self.filename.clone(),
|
||||
severity: Severity::RuntimeError,
|
||||
severity,
|
||||
};
|
||||
|
||||
let mut buf = String::new();
|
||||
|
@ -214,10 +223,11 @@ impl<'a> Renderer<'a> {
|
|||
use ven_pretty::DocAllocator;
|
||||
|
||||
let line_col_region = self.line_info.convert_region(expect_region);
|
||||
let severity = Severity::RuntimeError;
|
||||
|
||||
let doc = self.alloc.stack([
|
||||
self.alloc.text("This expectation crashed while running:"),
|
||||
self.alloc.region(line_col_region),
|
||||
self.alloc.region(line_col_region, severity),
|
||||
self.alloc.text("The crash reported this message:"),
|
||||
self.alloc.text(message),
|
||||
]);
|
||||
|
@ -226,7 +236,7 @@ impl<'a> Renderer<'a> {
|
|||
title: "EXPECT PANICKED".into(),
|
||||
doc,
|
||||
filename: self.filename.clone(),
|
||||
severity: Severity::RuntimeError,
|
||||
severity,
|
||||
};
|
||||
|
||||
let mut buf = String::new();
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -85,7 +85,7 @@ pub fn type_problem<'b>(
|
|||
UnfulfilledAbility(incomplete) => {
|
||||
let title = "INCOMPLETE ABILITY IMPLEMENTATION".to_string();
|
||||
|
||||
let doc = report_unfulfilled_ability(alloc, lines, incomplete);
|
||||
let doc = report_unfulfilled_ability(alloc, lines, incomplete, severity);
|
||||
|
||||
report(title, doc, filename)
|
||||
}
|
||||
|
@ -96,9 +96,9 @@ pub fn type_problem<'b>(
|
|||
|
||||
let incomplete = incomplete
|
||||
.into_iter()
|
||||
.map(|unfulfilled| report_unfulfilled_ability(alloc, lines, unfulfilled));
|
||||
.map(|unfulfilled| report_unfulfilled_ability(alloc, lines, unfulfilled, severity));
|
||||
let note = alloc.stack(incomplete);
|
||||
let snippet = alloc.region(lines.convert_region(region));
|
||||
let snippet = alloc.region(lines.convert_region(region), severity);
|
||||
let stack = [
|
||||
alloc.text(
|
||||
"This expression has a type that does not implement the abilities it's expected to:",
|
||||
|
@ -118,9 +118,9 @@ pub fn type_problem<'b>(
|
|||
BadPatternMissingAbility(region, _category, _found, incomplete) => {
|
||||
let incomplete = incomplete
|
||||
.into_iter()
|
||||
.map(|unfulfilled| report_unfulfilled_ability(alloc, lines, unfulfilled));
|
||||
.map(|unfulfilled| report_unfulfilled_ability(alloc, lines, unfulfilled, severity));
|
||||
let note = alloc.stack(incomplete);
|
||||
let snippet = alloc.region(lines.convert_region(region));
|
||||
let snippet = alloc.region(lines.convert_region(region), severity);
|
||||
let stack = [
|
||||
alloc.text(
|
||||
"This expression has a type does not implement the abilities it's expected to:",
|
||||
|
@ -139,7 +139,7 @@ pub fn type_problem<'b>(
|
|||
}
|
||||
Exhaustive(problem) => Some(exhaustive_problem(alloc, lines, filename, problem)),
|
||||
CircularDef(entries) => {
|
||||
let doc = to_circular_def_doc(alloc, lines, &entries);
|
||||
let doc = to_circular_def_doc(alloc, lines, &entries, severity);
|
||||
let title = CIRCULAR_DEF.to_string();
|
||||
|
||||
Some(Report {
|
||||
|
@ -161,7 +161,7 @@ pub fn type_problem<'b>(
|
|||
alloc.symbol_unqualified(member),
|
||||
alloc.reflow(" is for a non-opaque type:"),
|
||||
]),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
alloc.reflow("It is specialized for"),
|
||||
alloc.type_block(error_type_to_doc(alloc, typ)),
|
||||
alloc.reflow("but structural types can never specialize abilities!"),
|
||||
|
@ -191,7 +191,7 @@ pub fn type_problem<'b>(
|
|||
alloc.symbol_unqualified(ability_member),
|
||||
alloc.reflow(" is not for the expected type:"),
|
||||
]),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
alloc.concat([
|
||||
alloc.reflow("It was previously claimed to be a specialization for "),
|
||||
alloc.symbol_unqualified(expected_opaque),
|
||||
|
@ -254,6 +254,7 @@ fn report_unfulfilled_ability<'a>(
|
|||
alloc: &'a RocDocAllocator<'a>,
|
||||
lines: &LineInfo,
|
||||
unfulfilled: Unfulfilled,
|
||||
severity: Severity,
|
||||
) -> RocDocBuilder<'a> {
|
||||
match unfulfilled {
|
||||
Unfulfilled::OpaqueDoesNotImplement { typ, ability } => {
|
||||
|
@ -302,7 +303,7 @@ fn report_unfulfilled_ability<'a>(
|
|||
alloc.symbol_foreign_qualified(opaque),
|
||||
alloc.reflow(":"),
|
||||
]),
|
||||
alloc.region(lines.convert_region(derive_region)),
|
||||
alloc.region(lines.convert_region(derive_region), severity),
|
||||
]
|
||||
.into_iter()
|
||||
.chain(reason)
|
||||
|
@ -446,6 +447,7 @@ pub fn cyclic_alias<'b>(
|
|||
region: roc_region::all::Region,
|
||||
others: Vec<Symbol>,
|
||||
alias_kind: AliasKind,
|
||||
severity: Severity,
|
||||
) -> (RocDocBuilder<'b>, String) {
|
||||
let when_is_recursion_legal =
|
||||
alloc.reflow("Recursion in ")
|
||||
|
@ -460,7 +462,7 @@ pub fn cyclic_alias<'b>(
|
|||
.append(alloc.reflow(" "))
|
||||
.append(alloc.reflow(alias_kind.as_str()))
|
||||
.append(alloc.reflow(" is self-recursive in an invalid way:")),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
when_is_recursion_legal,
|
||||
])
|
||||
} else {
|
||||
|
@ -471,7 +473,7 @@ pub fn cyclic_alias<'b>(
|
|||
.append(alloc.reflow(" "))
|
||||
.append(alloc.reflow(alias_kind.as_str()))
|
||||
.append(alloc.reflow(" is recursive in an invalid way:")),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
alloc
|
||||
.reflow("The ")
|
||||
.append(alloc.symbol_unqualified(symbol))
|
||||
|
@ -515,9 +517,10 @@ fn report_mismatch<'b>(
|
|||
alloc.region_with_subregion(
|
||||
lines.convert_region(highlight),
|
||||
lines.convert_region(region),
|
||||
severity,
|
||||
)
|
||||
} else {
|
||||
alloc.region(lines.convert_region(region))
|
||||
alloc.region(lines.convert_region(region), severity)
|
||||
};
|
||||
let lines = vec![
|
||||
problem,
|
||||
|
@ -559,9 +562,10 @@ fn report_bad_type<'b>(
|
|||
alloc.region_with_subregion(
|
||||
lines.convert_region(highlight),
|
||||
lines.convert_region(region),
|
||||
severity,
|
||||
)
|
||||
} else {
|
||||
alloc.region(lines.convert_region(region))
|
||||
alloc.region(lines.convert_region(region), severity)
|
||||
};
|
||||
let lines = vec![
|
||||
problem,
|
||||
|
@ -664,7 +668,7 @@ fn to_expr_report<'b>(
|
|||
title: "TYPE MISMATCH".to_string(),
|
||||
doc: alloc.stack([
|
||||
alloc.text("This expression is used in an unexpected way:"),
|
||||
alloc.region(lines.convert_region(expr_region)),
|
||||
alloc.region(lines.convert_region(expr_region), severity),
|
||||
comparison,
|
||||
]),
|
||||
severity,
|
||||
|
@ -786,6 +790,7 @@ fn to_expr_report<'b>(
|
|||
alloc.region_with_subregion(
|
||||
lines.convert_region(joined),
|
||||
lines.convert_region(expr_region),
|
||||
severity,
|
||||
)
|
||||
},
|
||||
comparison,
|
||||
|
@ -1138,7 +1143,7 @@ fn to_expr_report<'b>(
|
|||
" is an opaque type, so it cannot be called with an argument:",
|
||||
),
|
||||
]),
|
||||
alloc.region(lines.convert_region(expr_region)),
|
||||
alloc.region(lines.convert_region(expr_region), severity),
|
||||
match called_via {
|
||||
CalledVia::RecordBuilder => {
|
||||
alloc.hint("Did you mean to apply it to a function first?")
|
||||
|
@ -1160,7 +1165,7 @@ fn to_expr_report<'b>(
|
|||
}
|
||||
)),
|
||||
]),
|
||||
alloc.region(lines.convert_region(expr_region)),
|
||||
alloc.region(lines.convert_region(expr_region), severity),
|
||||
match called_via {
|
||||
CalledVia::RecordBuilder => {
|
||||
alloc.concat([
|
||||
|
@ -1208,7 +1213,7 @@ fn to_expr_report<'b>(
|
|||
arity
|
||||
)),
|
||||
]),
|
||||
alloc.region(lines.convert_region(expr_region)),
|
||||
alloc.region(lines.convert_region(expr_region), severity),
|
||||
alloc.reflow("Are there any missing commas? Or missing parentheses?"),
|
||||
];
|
||||
|
||||
|
@ -1232,7 +1237,7 @@ fn to_expr_report<'b>(
|
|||
arity
|
||||
)),
|
||||
]),
|
||||
alloc.region(lines.convert_region(expr_region)),
|
||||
alloc.region(lines.convert_region(expr_region), severity),
|
||||
alloc.reflow(
|
||||
"Roc does not allow functions to be partially applied. \
|
||||
Use a closure to make partial application explicit.",
|
||||
|
@ -1407,6 +1412,7 @@ fn to_expr_report<'b>(
|
|||
let snippet = alloc.region_with_subregion(
|
||||
lines.convert_region(region),
|
||||
lines.convert_region(expr_region),
|
||||
severity,
|
||||
);
|
||||
|
||||
let this_is = alloc.concat([
|
||||
|
@ -1460,7 +1466,7 @@ fn to_expr_report<'b>(
|
|||
.append(alloc.text(" argument to "))
|
||||
.append(name.clone())
|
||||
.append(alloc.text(" is weird:")),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
pattern_type_comparison(
|
||||
alloc,
|
||||
expected_type,
|
||||
|
@ -1501,7 +1507,7 @@ fn to_expr_report<'b>(
|
|||
.reflow("This value passed to ")
|
||||
.append(alloc.keyword("crash"))
|
||||
.append(alloc.reflow(" is not a string:")),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
type_comparison(
|
||||
alloc,
|
||||
found,
|
||||
|
@ -1915,7 +1921,7 @@ fn to_pattern_report<'b>(
|
|||
PExpected::NoExpectation(expected_type) => {
|
||||
let doc = alloc.stack([
|
||||
alloc.text("This pattern is being used in an unexpected way:"),
|
||||
alloc.region(lines.convert_region(expr_region)),
|
||||
alloc.region(lines.convert_region(expr_region), severity),
|
||||
pattern_type_comparison(
|
||||
alloc,
|
||||
found,
|
||||
|
@ -1948,7 +1954,7 @@ fn to_pattern_report<'b>(
|
|||
.append(alloc.text(" argument to "))
|
||||
.append(name.clone())
|
||||
.append(alloc.text(" is weird:")),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
pattern_type_comparison(
|
||||
alloc,
|
||||
found,
|
||||
|
@ -1986,6 +1992,7 @@ fn to_pattern_report<'b>(
|
|||
alloc.region_with_subregion(
|
||||
lines.convert_region(region),
|
||||
lines.convert_region(expr_region),
|
||||
severity,
|
||||
),
|
||||
pattern_type_comparison(
|
||||
alloc,
|
||||
|
@ -2030,6 +2037,7 @@ fn to_pattern_report<'b>(
|
|||
alloc.region_with_subregion(
|
||||
lines.convert_region(region),
|
||||
lines.convert_region(expr_region),
|
||||
severity,
|
||||
),
|
||||
pattern_type_comparison(
|
||||
alloc,
|
||||
|
@ -2059,7 +2067,7 @@ fn to_pattern_report<'b>(
|
|||
PReason::ListElem => {
|
||||
let doc = alloc.stack([
|
||||
alloc.concat([alloc.reflow("This list element doesn't match the types of other elements in the pattern:")]),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
pattern_type_comparison(
|
||||
alloc,
|
||||
found,
|
||||
|
@ -2170,7 +2178,7 @@ fn to_circular_report<'b>(
|
|||
.reflow("I'm inferring a weird self-referential type for ")
|
||||
.append(alloc.symbol_unqualified(symbol))
|
||||
.append(alloc.text(":")),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
alloc.stack([
|
||||
alloc.reflow(
|
||||
"Here is my best effort at writing down the type. \
|
||||
|
@ -4810,7 +4818,7 @@ fn report_record_field_typo<'b>(
|
|||
|
||||
let doc = alloc.stack([
|
||||
header,
|
||||
alloc.region(lines.convert_region(field_region)),
|
||||
alloc.region(lines.convert_region(field_region), severity),
|
||||
if suggestions.is_empty() {
|
||||
let r_doc = match opt_sym {
|
||||
Some(symbol) => alloc.symbol_unqualified(symbol).append(" is"),
|
||||
|
@ -4875,7 +4883,7 @@ fn exhaustive_problem<'a>(
|
|||
BadArg => {
|
||||
let doc = alloc.stack([
|
||||
alloc.reflow("This pattern does not cover all the possibilities:"),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
alloc.reflow("Other possibilities include:"),
|
||||
unhandled_patterns_to_doc_block(alloc, missing),
|
||||
alloc.concat([
|
||||
|
@ -4898,7 +4906,7 @@ fn exhaustive_problem<'a>(
|
|||
BadDestruct => {
|
||||
let doc = alloc.stack([
|
||||
alloc.reflow("This pattern does not cover all the possibilities:"),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
alloc.reflow("Other possibilities include:"),
|
||||
unhandled_patterns_to_doc_block(alloc, missing),
|
||||
alloc.concat([
|
||||
|
@ -4926,7 +4934,7 @@ fn exhaustive_problem<'a>(
|
|||
alloc.keyword("when"),
|
||||
alloc.reflow(" does not cover all the possibilities:"),
|
||||
]),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.region(lines.convert_region(region), severity),
|
||||
alloc.reflow("Other possibilities include:"),
|
||||
unhandled_patterns_to_doc_block(alloc, missing),
|
||||
alloc.reflow(
|
||||
|
@ -4958,6 +4966,7 @@ fn exhaustive_problem<'a>(
|
|||
alloc.region_with_subregion(
|
||||
lines.convert_region(overall_region),
|
||||
lines.convert_region(branch_region),
|
||||
severity,
|
||||
),
|
||||
alloc.reflow(
|
||||
"Any value of this shape will be handled by \
|
||||
|
@ -4986,6 +4995,7 @@ fn exhaustive_problem<'a>(
|
|||
alloc.region_with_subregion(
|
||||
lines.convert_region(overall_region),
|
||||
lines.convert_region(branch_region),
|
||||
severity,
|
||||
),
|
||||
alloc.reflow(
|
||||
"It's impossible to create a value of this shape, \
|
||||
|
|
|
@ -223,6 +223,7 @@ pub struct Palette {
|
|||
pub bold: &'static str,
|
||||
pub underline: &'static str,
|
||||
pub reset: &'static str,
|
||||
pub warning: &'static str,
|
||||
}
|
||||
|
||||
/// Set the default styles for various semantic elements,
|
||||
|
@ -250,6 +251,7 @@ const fn default_palette_from_style_codes(codes: StyleCodes) -> Palette {
|
|||
bold: codes.bold,
|
||||
underline: codes.underline,
|
||||
reset: codes.reset,
|
||||
warning: codes.yellow,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -675,6 +677,7 @@ impl<'a> RocDocAllocator<'a> {
|
|||
&'a self,
|
||||
region: LineColumnRegion,
|
||||
sub_region: LineColumnRegion,
|
||||
severity: Severity,
|
||||
) -> DocBuilder<'a, Self, Annotation> {
|
||||
// debug_assert!(region.contains(&sub_region));
|
||||
|
||||
|
@ -684,10 +687,15 @@ impl<'a> RocDocAllocator<'a> {
|
|||
// attempting this will recurse forever, so don't do that! Instead, give up and
|
||||
// accept that this report will take up more than 1 full screen.
|
||||
if !sub_region.contains(®ion) {
|
||||
return self.region_with_subregion(sub_region, sub_region);
|
||||
return self.region_with_subregion(sub_region, sub_region, severity);
|
||||
}
|
||||
}
|
||||
|
||||
let annotation = match severity {
|
||||
Severity::RuntimeError | Severity::Fatal => Annotation::Error,
|
||||
Severity::Warning => Annotation::Warning,
|
||||
};
|
||||
|
||||
// if true, the final line of the snippet will be some ^^^ that point to the region where
|
||||
// the problem is. Otherwise, the snippet will have a > on the lines that are in the region
|
||||
// where the problem is.
|
||||
|
@ -727,7 +735,7 @@ impl<'a> RocDocAllocator<'a> {
|
|||
self.text(" ".repeat(max_line_number_length - this_line_number_length))
|
||||
.append(self.text(line_number).annotate(Annotation::LineNumber))
|
||||
.append(self.text(GUTTER_BAR).annotate(Annotation::GutterBar))
|
||||
.append(self.text(">").annotate(Annotation::Error))
|
||||
.append(self.text(">").annotate(annotation))
|
||||
.append(rest_of_line)
|
||||
} else if error_highlight_line {
|
||||
self.text(" ".repeat(max_line_number_length - this_line_number_length))
|
||||
|
@ -769,7 +777,7 @@ impl<'a> RocDocAllocator<'a> {
|
|||
} else {
|
||||
self.text(" ".repeat(sub_region.start().column as usize))
|
||||
.indent(indent)
|
||||
.append(self.text(highlight_text).annotate(Annotation::Error))
|
||||
.append(self.text(highlight_text).annotate(annotation))
|
||||
});
|
||||
|
||||
result = result.append(highlight_line);
|
||||
|
@ -778,8 +786,12 @@ impl<'a> RocDocAllocator<'a> {
|
|||
result
|
||||
}
|
||||
|
||||
pub fn region(&'a self, region: LineColumnRegion) -> DocBuilder<'a, Self, Annotation> {
|
||||
self.region_with_subregion(region, region)
|
||||
pub fn region(
|
||||
&'a self,
|
||||
region: LineColumnRegion,
|
||||
severity: Severity,
|
||||
) -> DocBuilder<'a, Self, Annotation> {
|
||||
self.region_with_subregion(region, region, severity)
|
||||
}
|
||||
|
||||
pub fn region_without_error(
|
||||
|
@ -884,6 +896,7 @@ pub enum Annotation {
|
|||
Tip,
|
||||
Header,
|
||||
ParserSuggestion,
|
||||
Warning,
|
||||
}
|
||||
|
||||
/// Render with minimal formatting
|
||||
|
@ -1094,6 +1107,9 @@ where
|
|||
ParserSuggestion => {
|
||||
self.write_str(self.palette.parser_suggestion)?;
|
||||
}
|
||||
Warning => {
|
||||
self.write_str(self.palette.warning)?;
|
||||
}
|
||||
TypeBlock | InlineTypeBlock | Tag | RecordField | TupleElem => { /* nothing yet */ }
|
||||
}
|
||||
self.style_stack.push(*annotation);
|
||||
|
@ -1108,7 +1124,8 @@ where
|
|||
Some(annotation) => match annotation {
|
||||
Emphasized | Url | TypeVariable | Alias | Symbol | BinOp | UnaryOp | Error
|
||||
| GutterBar | Ellipsis | Typo | TypoSuggestion | ParserSuggestion | Structure
|
||||
| CodeBlock | PlainText | LineNumber | Tip | Module | Header | Keyword => {
|
||||
| CodeBlock | PlainText | LineNumber | Tip | Module | Header | Keyword
|
||||
| Warning => {
|
||||
self.write_str(self.palette.reset)?;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue