mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-29 06:44:46 +00:00
Suggest typo fixes for non-existing module values
This commit is contained in:
parent
c156f61b0f
commit
214b8a30a9
4 changed files with 77 additions and 24 deletions
|
@ -1,6 +1,6 @@
|
|||
use crate::procedure::References;
|
||||
use roc_collections::all::{MutMap, MutSet};
|
||||
use roc_module::ident::{Ident, ModuleName};
|
||||
use roc_module::ident::{Ident, Lowercase, ModuleName};
|
||||
use roc_module::symbol::{IdentIds, ModuleId, ModuleIds, Symbol};
|
||||
use roc_problem::can::{Problem, RuntimeError};
|
||||
use roc_region::all::{Located, Region};
|
||||
|
@ -99,11 +99,8 @@ impl<'a> Env<'a> {
|
|||
)),
|
||||
}
|
||||
} else {
|
||||
match self
|
||||
.dep_idents
|
||||
.get(&module_id)
|
||||
.and_then(|exposed_ids| exposed_ids.get_id(&ident))
|
||||
{
|
||||
match self.dep_idents.get(&module_id) {
|
||||
Some(exposed_ids) => match exposed_ids.get_id(&ident) {
|
||||
Some(ident_id) => {
|
||||
let symbol = Symbol::new(module_id, *ident_id);
|
||||
|
||||
|
@ -111,11 +108,33 @@ impl<'a> Env<'a> {
|
|||
|
||||
Ok(symbol)
|
||||
}
|
||||
None => Err(RuntimeError::ValueNotExposed {
|
||||
None => {
|
||||
let exposed_values = exposed_ids
|
||||
.idents()
|
||||
.filter(|(_, ident)| {
|
||||
ident
|
||||
.as_ref()
|
||||
.chars()
|
||||
.next()
|
||||
.filter(|c| c.is_lowercase())
|
||||
.is_some()
|
||||
})
|
||||
.map(|(_, ident)| Lowercase::from(ident.as_ref()))
|
||||
.collect();
|
||||
Err(RuntimeError::ValueNotExposed {
|
||||
module_name,
|
||||
ident,
|
||||
region,
|
||||
}),
|
||||
exposed_values,
|
||||
})
|
||||
}
|
||||
},
|
||||
None => {
|
||||
panic!(
|
||||
"Module {} exists, but is not recorded in dep_idents",
|
||||
module_name
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -139,6 +139,7 @@ pub enum RuntimeError {
|
|||
module_name: ModuleName,
|
||||
ident: Ident,
|
||||
region: Region,
|
||||
exposed_values: Vec<Lowercase>,
|
||||
},
|
||||
ModuleNotImported {
|
||||
module_name: ModuleName,
|
||||
|
|
|
@ -6,6 +6,7 @@ use roc_problem::can::{BadPattern, FloatErrorKind, IntErrorKind, Problem, Runtim
|
|||
use roc_region::all::{Located, Region};
|
||||
use std::path::PathBuf;
|
||||
|
||||
use crate::error::r#type::suggest;
|
||||
use crate::report::{Annotation, Report, RocDocAllocator, RocDocBuilder, Severity};
|
||||
use ven_pretty::DocAllocator;
|
||||
|
||||
|
@ -874,16 +875,36 @@ fn pretty_runtime_error<'b>(
|
|||
module_name,
|
||||
ident,
|
||||
region,
|
||||
exposed_values,
|
||||
} => {
|
||||
let mut suggestions = suggest::sort(ident.as_ref(), exposed_values);
|
||||
suggestions.truncate(4);
|
||||
|
||||
let did_you_mean = if suggestions.is_empty() {
|
||||
alloc.concat(vec![
|
||||
alloc.reflow("In fact, it look like "),
|
||||
alloc.module_name(module_name.clone()),
|
||||
alloc.reflow(" doesn't expose any values!"),
|
||||
])
|
||||
} else {
|
||||
let qualified_suggestions = suggestions
|
||||
.into_iter()
|
||||
.map(|v| alloc.string(module_name.to_string() + "." + v.as_str()));
|
||||
alloc.stack(vec![
|
||||
alloc.reflow("Did you mean one of these?"),
|
||||
alloc.vcat(qualified_suggestions).indent(4),
|
||||
])
|
||||
};
|
||||
doc = alloc.stack(vec![
|
||||
alloc.concat(vec![
|
||||
alloc.reflow("The "),
|
||||
alloc.module_name(module_name),
|
||||
alloc.reflow(" module does not expose a "),
|
||||
alloc.reflow(" module does not expose `"),
|
||||
alloc.string(ident.to_string()),
|
||||
alloc.reflow(" value:"),
|
||||
alloc.reflow("`:"),
|
||||
]),
|
||||
alloc.region(region),
|
||||
did_you_mean,
|
||||
]);
|
||||
|
||||
title = VALUE_NOT_EXPOSED;
|
||||
|
@ -1176,8 +1197,6 @@ fn not_found<'b>(
|
|||
thing: &'b str,
|
||||
options: MutSet<Box<str>>,
|
||||
) -> RocDocBuilder<'b> {
|
||||
use crate::error::r#type::suggest;
|
||||
|
||||
let mut suggestions = suggest::sort(
|
||||
name.as_inline_str().as_str(),
|
||||
options.iter().map(|v| v.as_ref()).collect(),
|
||||
|
|
|
@ -298,17 +298,24 @@ mod test_reporting {
|
|||
report_problem_as(
|
||||
indoc!(
|
||||
r#"
|
||||
List.foobar 1 2
|
||||
List.isempty 1 2
|
||||
"#
|
||||
),
|
||||
indoc!(
|
||||
r#"
|
||||
── NOT EXPOSED ─────────────────────────────────────────────────────────────────
|
||||
|
||||
The List module does not expose a foobar value:
|
||||
The List module does not expose `isempty`:
|
||||
|
||||
1│ List.foobar 1 2
|
||||
^^^^^^^^^^^
|
||||
1│ List.isempty 1 2
|
||||
^^^^^^^^^^^^
|
||||
|
||||
Did you mean one of these?
|
||||
|
||||
List.isEmpty
|
||||
List.set
|
||||
List.get
|
||||
List.keepIf
|
||||
"#
|
||||
),
|
||||
)
|
||||
|
@ -5624,10 +5631,17 @@ mod test_reporting {
|
|||
r#"
|
||||
── NOT EXPOSED ─────────────────────────────────────────────────────────────────
|
||||
|
||||
The Num module does not expose a if value:
|
||||
The Num module does not expose `if`:
|
||||
|
||||
1│ Num.if
|
||||
^^^^^^
|
||||
|
||||
Did you mean one of these?
|
||||
|
||||
Num.sin
|
||||
Num.div
|
||||
Num.abs
|
||||
Num.neg
|
||||
"#
|
||||
),
|
||||
)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue