mirror of
https://github.com/nushell/nushell
synced 2024-12-26 13:03:07 +00:00
Error on use path item1 item2
, if item1 is not a module (#11183)
# Description Fixes: #11143 # User-Facing Changes Take the following as example: ```nushell module foo { export def bar [] {}; export def baz [] {} } ``` `use foo bar baz` will be error: ``` ❯ use foo c d Error: nu::parser::wrong_import_pattern × Wrong import pattern structure. ╭─[entry #2:1:1] 1 │ use foo c d · ┬ · ╰── Trying to import something but the parent `c` is not a module, maybe you want to try `use <module> [<name1>, <name2>]` ╰──── ``` # Tests + Formatting Done
This commit is contained in:
parent
2ffe30ecf0
commit
fb3350ebc3
4 changed files with 47 additions and 13 deletions
|
@ -296,3 +296,18 @@ fn use_main_not_exported() {
|
||||||
|
|
||||||
assert!(actual.err.contains("external_command"));
|
assert!(actual.err.contains("external_command"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn use_sub_subname_error_if_not_from_submodule() {
|
||||||
|
let inp = r#"module spam { export def foo [] {}; export def bar [] {} }; use spam foo bar"#;
|
||||||
|
let actual = nu!(inp);
|
||||||
|
assert!(actual.err.contains("try `use <module> [<name1>, <name2>]`"))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn can_use_sub_subname_from_submodule() {
|
||||||
|
let inp =
|
||||||
|
r#"module spam { export module foo { export def bar [] {"bar"} } }; use spam foo bar; bar"#;
|
||||||
|
let actual = nu!(inp);
|
||||||
|
assert_eq!(actual.out, "bar")
|
||||||
|
}
|
||||||
|
|
|
@ -10,6 +10,22 @@ pub enum ImportPatternMember {
|
||||||
List { names: Vec<(Vec<u8>, Span)> },
|
List { names: Vec<(Vec<u8>, Span)> },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ImportPatternMember {
|
||||||
|
pub fn span(&self) -> Span {
|
||||||
|
let mut spans = vec![];
|
||||||
|
match self {
|
||||||
|
ImportPatternMember::Glob { span } => spans.push(*span),
|
||||||
|
ImportPatternMember::Name { name: _, span } => spans.push(*span),
|
||||||
|
ImportPatternMember::List { names } => {
|
||||||
|
for (_, span) in names {
|
||||||
|
spans.push(*span);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
span(&spans)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub struct ImportPatternHead {
|
pub struct ImportPatternHead {
|
||||||
pub name: Vec<u8>,
|
pub name: Vec<u8>,
|
||||||
|
@ -46,15 +62,7 @@ impl ImportPattern {
|
||||||
let mut spans = vec![self.head.span];
|
let mut spans = vec![self.head.span];
|
||||||
|
|
||||||
for member in &self.members {
|
for member in &self.members {
|
||||||
match member {
|
spans.push(member.span());
|
||||||
ImportPatternMember::Glob { span } => spans.push(*span),
|
|
||||||
ImportPatternMember::Name { name: _, span } => spans.push(*span),
|
|
||||||
ImportPatternMember::List { names } => {
|
|
||||||
for (_, span) in names {
|
|
||||||
spans.push(*span);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
span(&spans)
|
span(&spans)
|
||||||
|
|
|
@ -157,6 +157,17 @@ impl Module {
|
||||||
|
|
||||||
match head {
|
match head {
|
||||||
ImportPatternMember::Name { name, span } => {
|
ImportPatternMember::Name { name, span } => {
|
||||||
|
// raise errors if user wants to do something like this:
|
||||||
|
// `use a b c`: but b is not a sub-module of a.
|
||||||
|
let errors = if !rest.is_empty() && self.submodules.get(name).is_none() {
|
||||||
|
vec![ParseError::WrongImportPattern(
|
||||||
|
format!("Trying to import something but the parent `{}` is not a module, maybe you want to try `use <module> [<name1>, <name2>]`", String::from_utf8_lossy(name)),
|
||||||
|
rest[0].span(),
|
||||||
|
)]
|
||||||
|
} else {
|
||||||
|
vec![]
|
||||||
|
};
|
||||||
|
|
||||||
if name == b"main" {
|
if name == b"main" {
|
||||||
if let Some(main_decl_id) = self.main {
|
if let Some(main_decl_id) = self.main {
|
||||||
(
|
(
|
||||||
|
@ -165,7 +176,7 @@ impl Module {
|
||||||
vec![],
|
vec![],
|
||||||
vec![],
|
vec![],
|
||||||
),
|
),
|
||||||
vec![],
|
errors,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
(
|
(
|
||||||
|
@ -176,7 +187,7 @@ impl Module {
|
||||||
} else if let Some(decl_id) = self.decls.get(name) {
|
} else if let Some(decl_id) = self.decls.get(name) {
|
||||||
(
|
(
|
||||||
ResolvedImportPattern::new(vec![(name.clone(), *decl_id)], vec![], vec![]),
|
ResolvedImportPattern::new(vec![(name.clone(), *decl_id)], vec![], vec![]),
|
||||||
vec![],
|
errors,
|
||||||
)
|
)
|
||||||
} else if let Some(var_id) = self.constants.get(name) {
|
} else if let Some(var_id) = self.constants.get(name) {
|
||||||
match working_set.get_constant(*var_id) {
|
match working_set.get_constant(*var_id) {
|
||||||
|
@ -186,7 +197,7 @@ impl Module {
|
||||||
vec![],
|
vec![],
|
||||||
vec![(name.clone(), const_val.clone())],
|
vec![(name.clone(), const_val.clone())],
|
||||||
),
|
),
|
||||||
vec![],
|
errors,
|
||||||
),
|
),
|
||||||
Err(err) => (
|
Err(err) => (
|
||||||
ResolvedImportPattern::new(vec![], vec![], vec![]),
|
ResolvedImportPattern::new(vec![], vec![], vec![]),
|
||||||
|
|
|
@ -425,7 +425,7 @@ pub enum ParseError {
|
||||||
MissingImportPattern(#[label = "needs an import pattern"] Span),
|
MissingImportPattern(#[label = "needs an import pattern"] Span),
|
||||||
|
|
||||||
#[error("Wrong import pattern structure.")]
|
#[error("Wrong import pattern structure.")]
|
||||||
#[diagnostic(code(nu::parser::missing_import_pattern))]
|
#[diagnostic(code(nu::parser::wrong_import_pattern))]
|
||||||
WrongImportPattern(String, #[label = "{0}"] Span),
|
WrongImportPattern(String, #[label = "{0}"] Span),
|
||||||
|
|
||||||
#[error("Export not found.")]
|
#[error("Export not found.")]
|
||||||
|
|
Loading…
Reference in a new issue