diff --git a/crates/nu-parser/src/known_external.rs b/crates/nu-parser/src/known_external.rs index a23c904572db9..4fad4bf7776ee 100644 --- a/crates/nu-parser/src/known_external.rs +++ b/crates/nu-parser/src/known_external.rs @@ -51,7 +51,15 @@ impl Command for KnownExternal { let mut extern_call = Call::new(head_span); - let extern_name = engine_state.get_decl(call.decl_id).name(); + let extern_name = if let Some(name_bytes) = engine_state.find_decl_name(call.decl_id, &[]) { + String::from_utf8_lossy(name_bytes) + } else { + return Err(ShellError::NushellFailedSpanned( + "known external name not found".to_string(), + "could not find name for this command".to_string(), + call.head, + )); + }; let extern_name: Vec<_> = extern_name.split(' ').collect(); diff --git a/crates/nu-protocol/src/engine/engine_state.rs b/crates/nu-protocol/src/engine/engine_state.rs index a93f485af49e3..9ec122eacc2f0 100644 --- a/crates/nu-protocol/src/engine/engine_state.rs +++ b/crates/nu-protocol/src/engine/engine_state.rs @@ -585,6 +585,24 @@ impl EngineState { None } + pub fn find_decl_name(&self, decl_id: DeclId, removed_overlays: &[Vec]) -> Option<&[u8]> { + let mut visibility: Visibility = Visibility::new(); + + for overlay_frame in self.active_overlays(removed_overlays).iter().rev() { + visibility.append(&overlay_frame.visibility); + + if visibility.is_decl_id_visible(&decl_id) { + for ((name, _), id) in overlay_frame.decls.iter() { + if id == &decl_id { + return Some(name); + } + } + } + } + + None + } + pub fn find_alias(&self, name: &[u8], removed_overlays: &[Vec]) -> Option { let mut visibility: Visibility = Visibility::new(); diff --git a/src/tests/test_known_external.rs b/src/tests/test_known_external.rs index 2462afc7f93cd..0ec1765a8c6a2 100644 --- a/src/tests/test_known_external.rs +++ b/src/tests/test_known_external.rs @@ -76,3 +76,34 @@ fn known_external_misc_values() -> TestResult { "abc a b c", ) } + +/// GitHub issue #7822 +#[test] +fn known_external_subcommand_from_module() -> TestResult { + run_test_contains( + r#" + module cargo { + export extern check [] + }; + use cargo; + cargo check -h + "#, + "cargo check", + ) +} + +/// GitHub issue #7822 +#[test] +fn known_external_aliased_subcommand_from_module() -> TestResult { + run_test_contains( + r#" + module cargo { + export extern check [] + }; + use cargo; + alias cc = cargo check; + cc -h + "#, + "cargo check", + ) +}