diff --git a/crates/moon/src/cli/build.rs b/crates/moon/src/cli/build.rs index 3073c659..4e10eb23 100644 --- a/crates/moon/src/cli/build.rs +++ b/crates/moon/src/cli/build.rs @@ -147,12 +147,12 @@ fn run_build_internal( &moonbuild_opt, )?; moonc_opt.build_opt.warn_lists = module - .packages + .get_all_packages() .iter() .map(|(name, pkg)| (name.clone(), pkg.warn_list.clone())) .collect(); moonc_opt.build_opt.alert_lists = module - .packages + .get_all_packages() .iter() .map(|(name, pkg)| (name.clone(), pkg.alert_list.clone())) .collect(); diff --git a/crates/moon/src/cli/bundle.rs b/crates/moon/src/cli/bundle.rs index 03765976..59741fdb 100644 --- a/crates/moon/src/cli/bundle.rs +++ b/crates/moon/src/cli/bundle.rs @@ -150,12 +150,12 @@ fn run_bundle_internal( &moonbuild_opt, )?; moonc_opt.build_opt.warn_lists = module - .packages + .get_all_packages() .iter() .map(|(name, pkg)| (name.clone(), pkg.warn_list.clone())) .collect(); moonc_opt.build_opt.alert_lists = module - .packages + .get_all_packages() .iter() .map(|(name, pkg)| (name.clone(), pkg.alert_list.clone())) .collect(); diff --git a/crates/moon/src/cli/check.rs b/crates/moon/src/cli/check.rs index 4ee3c64a..d9e2416a 100644 --- a/crates/moon/src/cli/check.rs +++ b/crates/moon/src/cli/check.rs @@ -165,12 +165,12 @@ fn run_check_internal( &moonbuild_opt, )?; moonc_opt.build_opt.warn_lists = module - .packages + .get_all_packages() .iter() .map(|(name, pkg)| (name.clone(), pkg.warn_list.clone())) .collect(); moonc_opt.build_opt.alert_lists = module - .packages + .get_all_packages() .iter() .map(|(name, pkg)| (name.clone(), pkg.alert_list.clone())) .collect(); diff --git a/crates/moon/src/cli/generate_test_driver.rs b/crates/moon/src/cli/generate_test_driver.rs index fcf89ae1..32158786 100644 --- a/crates/moon/src/cli/generate_test_driver.rs +++ b/crates/moon/src/cli/generate_test_driver.rs @@ -172,13 +172,8 @@ pub fn generate_test_driver( bail!("dry-run is not implemented for generate-test-driver"); } - for (pkgname, pkg) in module.packages.iter() { - if let Some(ref package) = filter_package { - if !package.contains(Path::new(pkgname)) { - continue; - } - } - + let package_filter = moonbuild_opt.get_package_filter(); + for (pkgname, pkg) in module.get_filtered_packages(package_filter) { if pkg.is_third_party { continue; } diff --git a/crates/moon/src/cli/info.rs b/crates/moon/src/cli/info.rs index 7e2c610e..aa8d86bb 100644 --- a/crates/moon/src/cli/info.rs +++ b/crates/moon/src/cli/info.rs @@ -125,7 +125,7 @@ pub fn run_info(cli: UniversalFlags, cmd: InfoSubcommand) -> anyhow::Result None => source_dir.to_path_buf(), Some(p) => source_dir.join(p), }; - for (name, pkg) in mdb.packages { + for (name, pkg) in mdb.get_all_packages() { // Skip if pkg is not part of the module if pkg.is_third_party { continue; diff --git a/crates/moon/src/cli/run.rs b/crates/moon/src/cli/run.rs index dfdbe73f..b4f7cc7b 100644 --- a/crates/moon/src/cli/run.rs +++ b/crates/moon/src/cli/run.rs @@ -285,12 +285,12 @@ pub fn run_run_internal(cli: &UniversalFlags, cmd: RunSubcommand) -> anyhow::Res &moonbuild_opt, )?; moonc_opt.build_opt.warn_lists = module - .packages + .get_all_packages() .iter() .map(|(name, pkg)| (name.clone(), pkg.warn_list.clone())) .collect(); moonc_opt.build_opt.alert_lists = module - .packages + .get_all_packages() .iter() .map(|(name, pkg)| (name.clone(), pkg.alert_list.clone())) .collect(); diff --git a/crates/moon/src/cli/test.rs b/crates/moon/src/cli/test.rs index c1b09f52..c715668d 100644 --- a/crates/moon/src/cli/test.rs +++ b/crates/moon/src/cli/test.rs @@ -210,13 +210,8 @@ fn run_test_internal( &moonbuild_opt, )?; - for (pkgname, pkg) in module.packages.iter_mut() { - if let Some(ref package) = filter_package { - if !package.contains(Path::new(pkgname)) { - continue; - } - } - + let package_filter = moonbuild_opt.get_package_filter(); + for (_, pkg) in module.get_filtered_packages_mut(package_filter) { if pkg.is_third_party || pkg.is_main { continue; } @@ -244,12 +239,12 @@ fn run_test_internal( } moonc_opt.build_opt.warn_lists = module - .packages + .get_all_packages() .iter() .map(|(name, pkg)| (name.clone(), pkg.warn_list.clone())) .collect(); moonc_opt.build_opt.alert_lists = module - .packages + .get_all_packages() .iter() .map(|(name, pkg)| (name.clone(), pkg.alert_list.clone())) .collect(); diff --git a/crates/moonbuild/src/entry.rs b/crates/moonbuild/src/entry.rs index 87c83cf7..cdc05b85 100644 --- a/crates/moonbuild/src/entry.rs +++ b/crates/moonbuild/src/entry.rs @@ -577,7 +577,7 @@ pub fn run_test( artifacts_path: vec![], }; for (pkgname, pkg) in module - .packages + .get_all_packages() .iter() .filter(|(_, p)| !(p.is_main || p.is_third_party)) { diff --git a/crates/moonbuild/src/fmt.rs b/crates/moonbuild/src/fmt.rs index 6460946d..fceade76 100644 --- a/crates/moonbuild/src/fmt.rs +++ b/crates/moonbuild/src/fmt.rs @@ -101,7 +101,7 @@ pub fn gen_fmt( moonbuild_opt: &MoonbuildOpt, ) -> anyhow::Result { let mut items = vec![]; - for (_, pkg) in m.packages.iter() { + for (_, pkg) in m.get_all_packages().iter() { if pkg.is_third_party { continue; } diff --git a/crates/moonbuild/src/gen/gen_build.rs b/crates/moonbuild/src/gen/gen_build.rs index b20a9cff..52fce3d5 100644 --- a/crates/moonbuild/src/gen/gen_build.rs +++ b/crates/moonbuild/src/gen/gen_build.rs @@ -90,7 +90,7 @@ pub fn gen_build_build_item( for dep in pkg.imports.iter() { let full_import_name = dep.path.make_full_path(); - if !m.packages.contains_key(&full_import_name) { + if !m.contains_package(&full_import_name) { bail!( "{}: the imported package `{}` could not be located.", m.source_dir @@ -100,7 +100,7 @@ pub fn gen_build_build_item( full_import_name, ); } - let cur_pkg = &m.packages[&full_import_name]; + let cur_pkg = m.get_package_by_name(&full_import_name); let d = cur_pkg.artifact.with_extension("mi"); let alias = dep.alias.clone().unwrap_or(cur_pkg.last_name().into()); mi_deps.push(MiAlias { @@ -152,7 +152,7 @@ pub fn gen_build( ) -> anyhow::Result { let mut build_items = vec![]; let mut link_items = vec![]; - for (i, (_, pkg)) in m.packages.iter().enumerate() { + for (i, (_, pkg)) in m.get_all_packages().iter().enumerate() { let is_main = m.entries.contains(&i); if is_main { diff --git a/crates/moonbuild/src/gen/gen_bundle.rs b/crates/moonbuild/src/gen/gen_bundle.rs index 6911615b..0800821e 100644 --- a/crates/moonbuild/src/gen/gen_bundle.rs +++ b/crates/moonbuild/src/gen/gen_bundle.rs @@ -61,15 +61,15 @@ pub fn gen_bundle( _moonbuild_opt: &MoonbuildOpt, ) -> anyhow::Result { let mut dep_items = vec![]; - for (_, pkg) in m.packages.iter() { - let item = pkg_to_bundle_item(&m.source_dir, &m.packages, pkg, moonc_opt)?; + for (_, pkg) in m.get_all_packages().iter() { + let item = pkg_to_bundle_item(&m.source_dir, m.get_all_packages(), pkg, moonc_opt)?; dep_items.push(item); } let nodes = super::util::toposort(m)?; let mut order = vec![]; for node in nodes.iter() { - let p = &m.packages[node]; + let p = &m.get_package_by_name(node); order.push( p.artifact .with_extension("core") diff --git a/crates/moonbuild/src/gen/gen_check.rs b/crates/moonbuild/src/gen/gen_check.rs index 49edee75..8c4f19f5 100644 --- a/crates/moonbuild/src/gen/gen_check.rs +++ b/crates/moonbuild/src/gen/gen_check.rs @@ -257,15 +257,21 @@ pub fn gen_check( let _ = moonc_opt; let _ = moonbuild_opt; let mut dep_items = vec![]; - for (_, pkg) in m.packages.iter() { - let item = pkg_to_check_item(&pkg.root_path, &m.packages, pkg, moonc_opt)?; + for (_, pkg) in m.get_all_packages().iter() { + let item = pkg_to_check_item(&pkg.root_path, m.get_all_packages(), pkg, moonc_opt)?; dep_items.push(item); if !pkg.wbtest_files.is_empty() { - let item = pkg_with_wbtest_to_check_item(&pkg.root_path, &m.packages, pkg, moonc_opt)?; + let item = pkg_with_wbtest_to_check_item( + &pkg.root_path, + m.get_all_packages(), + pkg, + moonc_opt, + )?; dep_items.push(item); } if !pkg.test_files.is_empty() { - let item = pkg_with_test_to_check_item(&pkg.root_path, &m.packages, pkg, moonc_opt)?; + let item = + pkg_with_test_to_check_item(&pkg.root_path, m.get_all_packages(), pkg, moonc_opt)?; dep_items.push(item); } } diff --git a/crates/moonbuild/src/gen/gen_runtest.rs b/crates/moonbuild/src/gen/gen_runtest.rs index 010208ba..70443ac8 100644 --- a/crates/moonbuild/src/gen/gen_runtest.rs +++ b/crates/moonbuild/src/gen/gen_runtest.rs @@ -149,7 +149,7 @@ pub fn gen_package_core( let mut mi_deps = vec![]; for dep in pkg.imports.iter() { let full_import_name = dep.path.make_full_path(); - if !m.packages.contains_key(&full_import_name) { + if !m.contains_package(&full_import_name) { bail!( "{}: the imported package `{}` could not be located.", m.source_dir @@ -159,7 +159,7 @@ pub fn gen_package_core( full_import_name, ); } - let cur_pkg = &m.packages[&full_import_name]; + let cur_pkg = m.get_package_by_name(&full_import_name); let d = cur_pkg.artifact.with_extension("mi"); let alias = dep.alias.clone().unwrap_or(cur_pkg.last_name().into()); mi_deps.push(MiAlias { @@ -216,7 +216,7 @@ pub fn gen_package_internal_test( let mut mi_deps = vec![]; for dep in pkg.imports.iter() { let full_import_name = dep.path.make_full_path(); - if !m.packages.contains_key(&full_import_name) { + if !m.contains_package(&full_import_name) { bail!( "{}: the imported package `{}` could not be located.", m.source_dir @@ -226,7 +226,7 @@ pub fn gen_package_internal_test( full_import_name, ); } - let cur_pkg = &m.packages[&full_import_name]; + let cur_pkg = m.get_package_by_name(&full_import_name); let d = cur_pkg.artifact.with_extension("mi"); let alias = dep.alias.clone().unwrap_or(cur_pkg.last_name().into()); mi_deps.push(MiAlias { @@ -291,7 +291,7 @@ pub fn gen_package_whitebox_test( let mut mi_deps = vec![]; for dep in pkg.imports.iter().chain(pkg.wbtest_imports.iter()) { let full_import_name = dep.path.make_full_path(); - if !m.packages.contains_key(&full_import_name) { + if !m.contains_package(&full_import_name) { bail!( "{}: the imported package `{}` could not be located.", m.source_dir @@ -301,7 +301,7 @@ pub fn gen_package_whitebox_test( full_import_name, ); } - let cur_pkg = &m.packages[&full_import_name]; + let cur_pkg = m.get_package_by_name(&full_import_name); let d = cur_pkg.artifact.with_extension("mi"); let alias = dep.alias.clone().unwrap_or(cur_pkg.last_name().into()); mi_deps.push(MiAlias { @@ -386,7 +386,7 @@ pub fn gen_package_blackbox_test( for dep in pkg.imports.iter().chain(pkg.test_imports.iter()) { let full_import_name = dep.path.make_full_path(); - if !m.packages.contains_key(&full_import_name) { + if !m.contains_package(&full_import_name) { bail!( "{}: the imported package `{}` could not be located.", m.source_dir @@ -396,7 +396,7 @@ pub fn gen_package_blackbox_test( full_import_name, ); } - let cur_pkg = &m.packages[&full_import_name]; + let cur_pkg = m.get_package_by_name(&full_import_name); let d = cur_pkg.artifact.with_extension("mi"); let alias = dep.alias.clone().unwrap_or(cur_pkg.last_name().into()); mi_deps.push(MiAlias { @@ -443,7 +443,7 @@ fn get_pkg_topo_order<'a>( return; } visited.insert(cur_pkg_full_name.clone()); - let cur_pkg = &m.packages[cur_pkg_full_name]; + let cur_pkg = m.get_package_by_name(cur_pkg_full_name); let imports = cur_pkg .imports .iter() @@ -665,7 +665,7 @@ pub fn gen_runtest( .as_ref() .and_then(|f| f.filter_package.as_ref()); - for (pkgname, pkg) in m.packages.iter() { + for (pkgname, pkg) in m.get_all_packages().iter() { if pkg.is_main { continue; } diff --git a/crates/moonbuild/src/gen/util.rs b/crates/moonbuild/src/gen/util.rs index 5c256d61..92ca027b 100644 --- a/crates/moonbuild/src/gen/util.rs +++ b/crates/moonbuild/src/gen/util.rs @@ -36,7 +36,7 @@ pub fn toposort(m: &ModuleDB) -> anyhow::Result> { let cycle = get_example_cycle(&m.graph, cycle.node_id()); let cycle = cycle .into_iter() - .map(|n| m.packages[n.index()].full_name()) + .map(|n| m.get_package_by_index(n.index()).full_name()) .collect::>(); bail!("cyclic dependency detected: {:?}", cycle); } @@ -51,20 +51,20 @@ pub fn topo_from_node(m: &ModuleDB, pkg: &Package) -> anyhow::Result fn dfs( m: &ModuleDB, - pkg_full_name: &String, + pkg_full_name: &str, stk: &mut Vec, visited: &mut HashSet, ) -> anyhow::Result<()> { - visited.insert(pkg_full_name.clone()); + visited.insert(pkg_full_name.to_string()); - for neighbor in m.packages[pkg_full_name].imports.iter() { + for neighbor in m.get_package_by_name(pkg_full_name).imports.iter() { let neighbor_full_name = neighbor.path.make_full_path(); if !visited.contains(&neighbor_full_name) { dfs(m, &neighbor_full_name, stk, visited)?; } } - stk.push(pkg_full_name.clone()); + stk.push(pkg_full_name.to_string()); Ok(()) } @@ -75,14 +75,14 @@ pub fn topo_from_node(m: &ModuleDB, pkg: &Package) -> anyhow::Result pub fn nodes_to_names(m: &ModuleDB, nodes: &[usize]) -> Vec { nodes .iter() - .map(|index| m.packages[*index].full_name()) + .map(|index| m.get_package_by_index(*index).full_name()) .collect::>() } pub fn nodes_to_cores(m: &ModuleDB, nodes: &[String]) -> Vec { nodes .iter() - .map(|index| m.packages[index].artifact.with_extension("core")) + .map(|name| m.get_package_by_name(name).artifact.with_extension("core")) .map(|p| p.display().to_string()) .collect::>() } @@ -90,12 +90,12 @@ pub fn nodes_to_cores(m: &ModuleDB, nodes: &[String]) -> Vec { pub fn nodes_to_pkg_sources(m: &ModuleDB, nodes: &[String]) -> Vec<(String, String)> { nodes .iter() - .map(|index| { + .map(|name| { let root_source_dir = match &m.source { None => m.source_dir.clone(), Some(x) => m.source_dir.join(x), }; - let pkg = &m.packages[index]; + let pkg = &m.get_package_by_name(name); let package_source_dir: String = if pkg.rel.components.is_empty() { root_source_dir.display().to_string() } else { diff --git a/crates/moonbuild/src/generate.rs b/crates/moonbuild/src/generate.rs index 9cf9cde7..0603fca1 100644 --- a/crates/moonbuild/src/generate.rs +++ b/crates/moonbuild/src/generate.rs @@ -33,7 +33,7 @@ pub fn load_moon_generate( let mut graph = n2graph::Graph::default(); let mut defaults: Vec = vec![]; - for (_, pkg) in module.packages.iter() { + for (_, pkg) in module.get_all_packages().iter() { if pkg.is_third_party { continue; } diff --git a/crates/moonutil/src/common.rs b/crates/moonutil/src/common.rs index d6a2762e..e5ecefe3 100644 --- a/crates/moonutil/src/common.rs +++ b/crates/moonutil/src/common.rs @@ -19,7 +19,7 @@ use crate::cond_expr::{CompileCondition, OptLevel}; pub use crate::dirs::check_moon_mod_exists; use crate::module::{MoonMod, MoonModJSON}; -use crate::package::{convert_pkg_json_to_package, MoonPkg, MoonPkgJSON}; +use crate::package::{convert_pkg_json_to_package, MoonPkg, MoonPkgJSON, Package}; use anyhow::{bail, Context}; use clap::ValueEnum; use fs4::FileExt; @@ -367,6 +367,12 @@ pub struct MoonbuildOpt { pub build_graph: bool, } +impl MoonbuildOpt { + pub fn get_package_filter(&self) -> Option bool + '_> { + self.test_opt.as_ref().map(|opt| opt.get_package_filter()) + } +} + #[derive(Debug, Clone, Default)] pub struct TestOpt { pub filter_package: Option>, @@ -396,6 +402,15 @@ impl TestOpt { } command_str } + pub fn get_package_filter(&self) -> impl Fn(&Package) -> bool + '_ { + move |pkg| { + if let Some(ref filter_package) = self.filter_package { + filter_package.contains(&PathBuf::from(pkg.full_name())) + } else { + true + } + } + } } #[derive(serde::Serialize, Clone)] diff --git a/crates/moonutil/src/module.rs b/crates/moonutil/src/module.rs index ee58556d..36eda67a 100644 --- a/crates/moonutil/src/module.rs +++ b/crates/moonutil/src/module.rs @@ -35,7 +35,7 @@ use std::path::{Path, PathBuf}; pub struct ModuleDB { pub source_dir: PathBuf, pub name: String, - pub packages: IndexMap, + packages: IndexMap, pub entries: Vec, // index of entry packages pub deps: Vec, pub graph: DiGraph, @@ -44,6 +44,79 @@ pub struct ModuleDB { pub source: Option, } +impl ModuleDB { + #[allow(clippy::too_many_arguments)] + pub fn new( + source_dir: PathBuf, + name: String, + package: IndexMap, + entries: Vec, + deps: Vec, + graph: DiGraph, + backend: String, + opt_level: String, + source: Option, + ) -> Self { + ModuleDB { + source_dir, + name, + packages: package, + entries, + deps, + graph, + backend, + opt_level, + source, + } + } + + pub fn get_all_packages(&self) -> &IndexMap { + &self.packages + } + + pub fn get_all_packages_mut(&mut self) -> &mut IndexMap { + &mut self.packages + } + + pub fn get_package_by_name(&self, name: &str) -> &Package { + self.packages.get(name).unwrap() + } + + pub fn get_package_by_index(&self, index: usize) -> &Package { + &self.packages[self.packages.keys().nth(index).unwrap()] + } + + pub fn contains_package(&self, name: &str) -> bool { + self.packages.contains_key(name) + } + + pub fn get_filtered_packages( + &self, + maybe_filter: Option bool>, + ) -> impl Iterator { + self.packages.iter().filter(move |(_, pkg)| { + if let Some(filter) = &maybe_filter { + filter(pkg) + } else { + true + } + }) + } + + pub fn get_filtered_packages_mut( + &mut self, + maybe_filter: Option bool>, + ) -> impl Iterator { + self.packages.iter_mut().filter(move |(_, pkg)| { + if let Some(filter) = &maybe_filter { + filter(pkg) + } else { + true + } + }) + } +} + impl ModuleDB { pub fn make_pkg_import_path(&self, pkg_idx: usize) -> String { let pkg = &self.packages[pkg_idx]; diff --git a/crates/moonutil/src/scan.rs b/crates/moonutil/src/scan.rs index d90cacdc..57151119 100644 --- a/crates/moonutil/src/scan.rs +++ b/crates/moonutil/src/scan.rs @@ -25,7 +25,7 @@ use crate::path::{ImportComponent, ImportPath, PathComponent}; use anyhow::{bail, Context}; use indexmap::map::IndexMap; use petgraph::graph::{DiGraph, NodeIndex}; -use std::collections::{HashMap, HashSet}; +use std::collections::HashMap; use std::path::{Path, PathBuf}; use std::str::FromStr; use walkdir::WalkDir; @@ -418,25 +418,6 @@ pub fn scan( moonc_opt, )?; - if moonbuild_opt.run_mode == crate::common::RunMode::Test { - if let Some(crate::common::TestOpt { - filter_package: Some(ref filter_package), - .. - }) = moonbuild_opt.test_opt - { - let pkgs = packages - .iter() - .filter(|(k, _)| filter_package.contains(Path::new(k))) - .map(|(_, v)| v); - let mut pkg_and_its_deps = HashSet::new(); - for pkg in pkgs { - pkg_and_its_deps.extend(get_pkg_and_its_deps(pkg, &packages)); - } - // filter out other packages - packages.retain(|k, _| pkg_and_its_deps.contains(k)); - } - } - // scan third party packages in DEP_PATH according to deps field for (module_id, _) in resolved_modules.all_packages_and_id() { if resolved_modules.module_info(module_id).name == mod_desc.name { @@ -505,21 +486,21 @@ pub fn scan( entries.sort(); - let module = ModuleDB { - source_dir: dunce::canonicalize(source_dir).unwrap(), - name: mod_desc.name.to_string(), + let module = ModuleDB::new( + dunce::canonicalize(source_dir).unwrap(), + mod_desc.name.to_string(), packages, entries, deps, graph, - backend: moonc_opt.link_opt.target_backend.to_backend_ext().into(), - opt_level: if moonc_opt.build_opt.debug_flag { + moonc_opt.link_opt.target_backend.to_backend_ext().into(), + if moonc_opt.build_opt.debug_flag { "debug".to_string() } else { "release".to_string() }, - source: mod_desc.source, - }; + mod_desc.source, + ); module.validate()?; @@ -531,36 +512,6 @@ pub fn scan( Ok(module) } -fn get_pkg_and_its_deps(pkg: &Package, packages: &IndexMap) -> HashSet { - let mut resolved = HashSet::new(); - resolved.insert(pkg.full_name().clone()); - resolve_deps_of_pkg(&pkg.full_name(), packages, &mut resolved); - resolved -} - -// resolve deps of the given pkg in dfs way -fn resolve_deps_of_pkg( - pkg_name: &String, - packages: &IndexMap, - res: &mut HashSet, -) { - let pkg = packages.get(pkg_name); - if let Some(pkg) = pkg { - for dep in pkg - .imports - .iter() - .chain(pkg.wbtest_imports.iter()) - .chain(pkg.test_imports.iter()) - { - let dep = &dep.path.make_full_path(); - if !res.contains(dep) { - res.insert(dep.clone()); - resolve_deps_of_pkg(dep, packages, res); - } - } - } -} - #[cfg(test)] mod test { use expect_test::expect;