add more helpful error for calling a decl that exists in a module (#6752)

* add more helpful error for calling a decl that exists in a module

* accord to suggestions

* make error more helpful
This commit is contained in:
pwygab 2022-10-23 00:41:31 +08:00 committed by GitHub
parent 4fdf5c663c
commit 3f555a6836
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 42 additions and 0 deletions

View File

@ -270,6 +270,14 @@ impl ExternalCommand {
"'{}' was not found, did you mean '{s}'?",
self.name.item
)
} else if self.name.item == s {
let sugg = engine_state.which_module_has_decl(s.as_bytes());
if let Some(sugg) = sugg {
let sugg = String::from_utf8_lossy(sugg);
format!("command '{s}' was not found but it exists in module '{sugg}'; try using `{sugg} {s}`")
} else {
format!("did you mean '{s}'?")
}
} else {
format!("did you mean '{s}'?")
}

View File

@ -183,3 +183,17 @@ fn use_export_env_combined() {
assert_eq!(actual.out, "foo");
})
}
#[test]
fn use_module_creates_accurate_did_you_mean() {
let actual = nu!(
cwd: ".", pipeline(
r#"
module spam { export def foo [] { "foo" } }; use spam; foo
"#
)
);
assert!(actual.err.contains(
"command 'foo' was not found but it exists in module 'spam'; try using `spam foo`"
));
}

View File

@ -546,6 +546,26 @@ impl EngineState {
None
}
pub fn which_module_has_decl(&self, name: &[u8]) -> Option<&[u8]> {
for (module_id, m) in self.modules.iter().enumerate() {
if m.has_decl(name) {
for overlay_frame in self.active_overlays(&[]).iter() {
let module_name = overlay_frame.modules.iter().find_map(|(key, &val)| {
if val == module_id {
Some(key)
} else {
None
}
});
if let Some(final_name) = module_name {
return Some(&final_name[..]);
}
}
}
}
None
}
pub fn find_overlay(&self, name: &[u8]) -> Option<OverlayId> {
self.scope.find_overlay(name)
}