mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-30 15:21:12 +00:00
Revise record field typo error report
This commit is contained in:
parent
9343c6802a
commit
ab44f23e0f
1 changed files with 104 additions and 109 deletions
|
@ -827,111 +827,111 @@ fn to_expr_report<'b>(
|
||||||
You can achieve that with record literal syntax.",
|
You can achieve that with record literal syntax.",
|
||||||
)),
|
)),
|
||||||
),
|
),
|
||||||
Reason::RecordUpdateKeys(symbol, expected_fields) => match found
|
Reason::RecordUpdateKeys(symbol, expected_fields) => {
|
||||||
.clone()
|
match found.clone().unwrap_structural_alias() {
|
||||||
.unwrap_structural_alias()
|
ErrorType::Record(actual_fields, ext) => {
|
||||||
{
|
let expected_set: MutSet<_> = expected_fields.keys().cloned().collect();
|
||||||
ErrorType::Record(actual_fields, ext) => {
|
let actual_set: MutSet<_> = actual_fields.keys().cloned().collect();
|
||||||
let expected_set: MutSet<_> = expected_fields.keys().cloned().collect();
|
|
||||||
let actual_set: MutSet<_> = actual_fields.keys().cloned().collect();
|
|
||||||
|
|
||||||
let mut diff = expected_set.difference(&actual_set);
|
let mut diff = expected_set.difference(&actual_set);
|
||||||
|
|
||||||
match diff.next().and_then(|k| Some((k, expected_fields.get(k)?))) {
|
match diff.next().and_then(|k| Some((k, expected_fields.get(k)?))) {
|
||||||
None => report_mismatch(
|
None => report_mismatch(
|
||||||
alloc,
|
alloc,
|
||||||
lines,
|
lines,
|
||||||
filename,
|
|
||||||
&category,
|
|
||||||
found,
|
|
||||||
expected_type,
|
|
||||||
region,
|
|
||||||
Some(expr_region),
|
|
||||||
alloc.reflow("Something is off with this record update:"),
|
|
||||||
alloc.concat(vec![
|
|
||||||
alloc.reflow("The"),
|
|
||||||
alloc.symbol_unqualified(symbol),
|
|
||||||
alloc.reflow(" record is"),
|
|
||||||
]),
|
|
||||||
alloc.reflow("But this update needs it to be compatible with:"),
|
|
||||||
None,
|
|
||||||
),
|
|
||||||
Some((field, field_region)) => {
|
|
||||||
let r_doc = alloc.symbol_unqualified(symbol);
|
|
||||||
let f_doc = alloc.record_field(field.clone());
|
|
||||||
|
|
||||||
let header = alloc.concat(vec![
|
|
||||||
alloc.reflow("The "),
|
|
||||||
r_doc.clone(),
|
|
||||||
alloc.reflow(" record does not have a "),
|
|
||||||
f_doc.clone(),
|
|
||||||
alloc.reflow(" field:"),
|
|
||||||
]);
|
|
||||||
|
|
||||||
let mut suggestions = suggest::sort(
|
|
||||||
field.as_str(),
|
|
||||||
actual_fields.into_iter().collect::<Vec<_>>(),
|
|
||||||
);
|
|
||||||
|
|
||||||
let doc = alloc.stack(vec![
|
|
||||||
header,
|
|
||||||
alloc.region(lines.convert_region(*field_region)),
|
|
||||||
if suggestions.is_empty() {
|
|
||||||
alloc.concat(vec![
|
|
||||||
alloc.reflow("In fact, "),
|
|
||||||
r_doc,
|
|
||||||
alloc.reflow(" is a record with NO fields!"),
|
|
||||||
])
|
|
||||||
} else {
|
|
||||||
let f = suggestions.remove(0);
|
|
||||||
let fs = suggestions;
|
|
||||||
|
|
||||||
alloc.stack(vec![
|
|
||||||
alloc.concat(vec![
|
|
||||||
alloc.reflow("This is usually a typo. Here are the "),
|
|
||||||
r_doc,
|
|
||||||
alloc.reflow(" fields that are most similar:"),
|
|
||||||
]),
|
|
||||||
report_text::to_suggestion_record(
|
|
||||||
alloc,
|
|
||||||
f.clone(),
|
|
||||||
fs,
|
|
||||||
ext,
|
|
||||||
),
|
|
||||||
alloc.concat(vec![
|
|
||||||
alloc.reflow("So maybe "),
|
|
||||||
f_doc,
|
|
||||||
alloc.reflow(" should be "),
|
|
||||||
alloc.record_field(f.0),
|
|
||||||
alloc.reflow("?"),
|
|
||||||
]),
|
|
||||||
])
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
Report {
|
|
||||||
filename,
|
filename,
|
||||||
title: "TYPE MISMATCH".to_string(),
|
&category,
|
||||||
doc,
|
found,
|
||||||
severity: Severity::RuntimeError,
|
expected_type,
|
||||||
|
region,
|
||||||
|
Some(expr_region),
|
||||||
|
alloc.reflow("Something is off with this record update:"),
|
||||||
|
alloc.concat(vec![
|
||||||
|
alloc.reflow("The"),
|
||||||
|
alloc.symbol_unqualified(symbol),
|
||||||
|
alloc.reflow(" record is"),
|
||||||
|
]),
|
||||||
|
alloc.reflow("But this update needs it to be compatible with:"),
|
||||||
|
None,
|
||||||
|
),
|
||||||
|
Some((field, field_region)) => {
|
||||||
|
let r_doc = alloc.symbol_unqualified(symbol);
|
||||||
|
let f_doc = alloc.type_variable(field.clone());
|
||||||
|
|
||||||
|
let header = alloc.concat(vec![
|
||||||
|
alloc.reflow("The "),
|
||||||
|
r_doc.clone(),
|
||||||
|
alloc.reflow(" record does not have a "),
|
||||||
|
f_doc.clone(),
|
||||||
|
alloc.reflow(" field:"),
|
||||||
|
]);
|
||||||
|
|
||||||
|
let mut suggestions = suggest::sort(
|
||||||
|
field.as_str(),
|
||||||
|
actual_fields.into_iter().collect::<Vec<_>>(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let doc = alloc.stack(vec![
|
||||||
|
header,
|
||||||
|
alloc.region(lines.convert_region(*field_region)),
|
||||||
|
if suggestions.is_empty() {
|
||||||
|
alloc.concat(vec![
|
||||||
|
alloc.reflow("In fact, "),
|
||||||
|
r_doc,
|
||||||
|
alloc.reflow(" is a record with NO fields!"),
|
||||||
|
])
|
||||||
|
} else {
|
||||||
|
let f = suggestions.remove(0);
|
||||||
|
let fs = suggestions;
|
||||||
|
|
||||||
|
alloc.stack(vec![
|
||||||
|
alloc.concat(vec![
|
||||||
|
alloc.reflow("There may be a typo. Here are the "),
|
||||||
|
r_doc,
|
||||||
|
alloc.reflow(" fields that are most similar:"),
|
||||||
|
]),
|
||||||
|
report_text::to_suggestion_record(
|
||||||
|
alloc,
|
||||||
|
f.clone(),
|
||||||
|
fs,
|
||||||
|
ext,
|
||||||
|
),
|
||||||
|
alloc.concat(vec![
|
||||||
|
alloc.reflow("So maybe "),
|
||||||
|
f_doc,
|
||||||
|
alloc.reflow(" should be "),
|
||||||
|
alloc.type_variable(f.0),
|
||||||
|
//alloc.record_field(f.0),
|
||||||
|
alloc.reflow("?"),
|
||||||
|
]),
|
||||||
|
])
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
Report {
|
||||||
|
filename,
|
||||||
|
title: "TYPE MISMATCH".to_string(),
|
||||||
|
doc,
|
||||||
|
severity: Severity::RuntimeError,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
_ => report_bad_type(
|
||||||
|
alloc,
|
||||||
|
lines,
|
||||||
|
filename,
|
||||||
|
&category,
|
||||||
|
found,
|
||||||
|
expected_type,
|
||||||
|
region,
|
||||||
|
Some(expr_region),
|
||||||
|
alloc.reflow("This is not a record, so it has no fields to update!"),
|
||||||
|
alloc.reflow("It is"),
|
||||||
|
alloc.reflow("But I need a record!"),
|
||||||
|
),
|
||||||
}
|
}
|
||||||
_ => report_bad_type(
|
}
|
||||||
alloc,
|
|
||||||
lines,
|
|
||||||
filename,
|
|
||||||
&category,
|
|
||||||
found,
|
|
||||||
expected_type,
|
|
||||||
region,
|
|
||||||
Some(expr_region),
|
|
||||||
alloc.reflow("This is not a record, so it has no fields to update!"),
|
|
||||||
alloc.reflow("It is"),
|
|
||||||
alloc.reflow("But I need a record!"),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
Reason::FnCall { name, arity } => match count_arguments(&found) {
|
Reason::FnCall { name, arity } => match count_arguments(&found) {
|
||||||
0 => {
|
0 => {
|
||||||
let this_value = match name {
|
let this_value = match name {
|
||||||
|
@ -2956,23 +2956,18 @@ mod report_text {
|
||||||
) -> RocDocBuilder<'b> {
|
) -> RocDocBuilder<'b> {
|
||||||
let entry_to_doc = |(field_name, field_type): (RocDocBuilder<'b>, RocDocBuilder<'b>)| {
|
let entry_to_doc = |(field_name, field_type): (RocDocBuilder<'b>, RocDocBuilder<'b>)| {
|
||||||
field_name
|
field_name
|
||||||
|
.indent(4)
|
||||||
.append(alloc.text(" : "))
|
.append(alloc.text(" : "))
|
||||||
.hang(4)
|
|
||||||
.append(field_type)
|
.append(field_type)
|
||||||
|
.append(alloc.text(","))
|
||||||
};
|
};
|
||||||
|
|
||||||
let field = alloc.reflow("{ ").append(entry_to_doc(entry));
|
let fields = std::iter::once(entry_to_doc(entry))
|
||||||
let fields = std::iter::repeat(alloc.reflow(", "))
|
.chain(entries.into_iter().map(entry_to_doc))
|
||||||
.zip(
|
.chain(std::iter::once(alloc.text("…").indent(4)));
|
||||||
entries
|
|
||||||
.into_iter()
|
|
||||||
.map(entry_to_doc)
|
|
||||||
.chain(std::iter::once(alloc.text("..."))),
|
|
||||||
)
|
|
||||||
.map(|(a, b)| a.append(b));
|
|
||||||
|
|
||||||
alloc.vcat(
|
alloc.vcat(
|
||||||
std::iter::once(field)
|
std::iter::once(alloc.reflow("{"))
|
||||||
.chain(fields)
|
.chain(fields)
|
||||||
.chain(std::iter::once(alloc.text("}"))),
|
.chain(std::iter::once(alloc.text("}"))),
|
||||||
)
|
)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue