finish impl

This commit is contained in:
WindSoilder 2024-06-18 17:54:57 +08:00
parent 3c43258bbd
commit 6862bf0e26
3 changed files with 70 additions and 12 deletions

View File

@ -1211,6 +1211,7 @@ pub fn parse_export_in_module(
working_set: &mut StateWorkingSet, working_set: &mut StateWorkingSet,
lite_command: &LiteCommand, lite_command: &LiteCommand,
module_name: &[u8], module_name: &[u8],
module: &mut Module,
) -> (Pipeline, Vec<Exportable>) { ) -> (Pipeline, Vec<Exportable>) {
let spans = &lite_command.parts[..]; let spans = &lite_command.parts[..];
@ -1416,7 +1417,7 @@ pub fn parse_export_in_module(
pipe: lite_command.pipe, pipe: lite_command.pipe,
redirection: lite_command.redirection.clone(), redirection: lite_command.redirection.clone(),
}; };
let (pipeline, exportables) = parse_use(working_set, &lite_command); let (pipeline, exportables) = parse_use(working_set, &lite_command, Some(module));
let export_use_decl_id = if let Some(id) = working_set.find_decl(b"export use") { let export_use_decl_id = if let Some(id) = working_set.find_decl(b"export use") {
id id
@ -1774,7 +1775,7 @@ pub fn parse_module_block(
} }
b"export" => { b"export" => {
let (pipe, exportables) = let (pipe, exportables) =
parse_export_in_module(working_set, command, module_name); parse_export_in_module(working_set, command, module_name, &mut module);
for exportable in exportables { for exportable in exportables {
match exportable { match exportable {
@ -1922,23 +1923,38 @@ fn parse_module_file(
// Check if we've parsed the module before. // Check if we've parsed the module before.
if let Some(module_id) = working_set.find_module_by_span(new_span) { if let Some(module_id) = working_set.find_module_by_span(new_span) {
return Some(module_id); let module = working_set.get_module(module_id);
// check if it contains submodules with a file name.
let has_export_submodules = module
.submodules
.iter()
.any(|(_, m)| working_set.get_module(*m).file.is_some());
// check if it's using other modules with a file name.
let has_use_submodules = module
.imported_modules
.iter()
.any(|m| working_set.get_module(*m).file.is_some());
if !(has_export_submodules || has_use_submodules) {
return Some(module_id);
}
} }
// Add the file to the stack of files being processed. // Add the file to the stack of files being processed.
if let Err(e) = working_set.files.push(path.path_buf(), path_span) { let path_buf = path.path_buf();
if let Err(e) = working_set.files.push(path_buf.clone(), path_span) {
working_set.error(e); working_set.error(e);
return None; return None;
} }
// Parse the module // Parse the module
let (block, module, module_comments) = let (block, mut module, module_comments) =
parse_module_block(working_set, new_span, module_name.as_bytes()); parse_module_block(working_set, new_span, module_name.as_bytes());
// Remove the file from the stack of files being processed. // Remove the file from the stack of files being processed.
working_set.files.pop(); working_set.files.pop();
let _ = working_set.add_block(Arc::new(block)); let _ = working_set.add_block(Arc::new(block));
module.file = Some(path_buf);
let module_id = working_set.add_module(&module_name, module, module_comments); let module_id = working_set.add_module(&module_name, module, module_comments);
Some(module_id) Some(module_id)
@ -2422,7 +2438,7 @@ pub fn parse_use(
import_pattern.constants = constants.iter().map(|(_, id)| *id).collect(); import_pattern.constants = constants.iter().map(|(_, id)| *id).collect();
if let Some(m) = user_module { if let Some(m) = user_module {
m.add_usage_modules( m.track_imported_modules(
definitions definitions
.modules .modules
.iter() .iter()

View File

@ -36,7 +36,7 @@ pub struct Module {
pub env_block: Option<BlockId>, // `export-env { ... }` block pub env_block: Option<BlockId>, // `export-env { ... }` block
pub main: Option<DeclId>, // `export def main` pub main: Option<DeclId>, // `export def main`
pub span: Option<Span>, pub span: Option<Span>,
pub use_modules: Vec<ModuleId>, pub imported_modules: Vec<ModuleId>, // use other_module.nu
pub file: Option<PathBuf>, pub file: Option<PathBuf>,
} }
@ -50,7 +50,7 @@ impl Module {
env_block: None, env_block: None,
main: None, main: None,
span: None, span: None,
use_modules: vec![], imported_modules: vec![],
file: None, file: None,
} }
} }
@ -64,7 +64,7 @@ impl Module {
env_block: None, env_block: None,
main: None, main: None,
span: Some(span), span: Some(span),
use_modules: vec![], imported_modules: vec![],
file: None, file: None,
} }
} }
@ -89,9 +89,9 @@ impl Module {
self.env_block = Some(block_id); self.env_block = Some(block_id);
} }
pub fn add_usage_modules(&mut self, module_id: &[ModuleId]) { pub fn track_imported_modules(&mut self, module_id: &[ModuleId]) {
for m in module_id { for m in module_id {
self.use_modules.push(*m) self.imported_modules.push(*m)
} }
} }

View File

@ -1,4 +1,4 @@
use nu_test_support::fs::Stub::FileWithContentToBeTrimmed; use nu_test_support::fs::Stub::{FileWithContent, FileWithContentToBeTrimmed};
use nu_test_support::playground::Playground; use nu_test_support::playground::Playground;
use nu_test_support::{nu, nu_repl_code}; use nu_test_support::{nu, nu_repl_code};
use pretty_assertions::assert_eq; use pretty_assertions::assert_eq;
@ -760,3 +760,45 @@ fn nested_list_export_works() {
let actual = nu!(&inp.join("; ")); let actual = nu!(&inp.join("; "));
assert_eq!(actual.out, "bacon"); assert_eq!(actual.out, "bacon");
} }
#[test]
fn reload_submodules() {
Playground::setup("reload_submodule_changed_file", |dirs, sandbox| {
sandbox.with_files(&[
FileWithContent("voice.nu", r#"export module animals.nu"#),
FileWithContent("animals.nu", "export def cat [] { 'meow'}"),
]);
let inp = [
"use voice.nu",
r#""export def cat [] {'woem'}" | save -f animals.nu"#,
"use voice.nu",
"(voice animals cat) == 'woem'",
];
let actual = nu!(cwd: dirs.test(), nu_repl_code(&inp));
assert_eq!(actual.out, "true");
});
}
#[test]
fn use_submodules() {
Playground::setup("reload_submodule_changed_file", |dirs, sandbox| {
sandbox.with_files(&[
FileWithContent("voice.nu", r#"export use animals.nu"#),
FileWithContent("animals.nu", "export def cat [] { 'meow'}"),
]);
let inp = [
"use voice.nu",
r#""export def cat [] {'woem'}" | save -f animals.nu"#,
"use voice.nu",
"(voice animals cat) == 'woem'",
];
let actual = nu!(cwd: dirs.test(), nu_repl_code(&inp));
assert_eq!(actual.out, "true");
});
}