diff options
Diffstat (limited to 'cli/modules.rs')
-rw-r--r-- | cli/modules.rs | 204 |
1 files changed, 204 insertions, 0 deletions
diff --git a/cli/modules.rs b/cli/modules.rs new file mode 100644 index 000000000..908c31b6d --- /dev/null +++ b/cli/modules.rs @@ -0,0 +1,204 @@ +// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license. +use crate::ansi; +use crate::deno_dir::DenoDir; +use crate::msg; +use deno_core::deno_mod; +use std::collections::HashMap; +use std::collections::HashSet; +use std::fmt; + +pub struct ModuleInfo { + name: String, + children: Vec<deno_mod>, +} + +/// A collection of JS modules. +#[derive(Default)] +pub struct Modules { + pub info: HashMap<deno_mod, ModuleInfo>, + pub by_name: HashMap<String, deno_mod>, +} + +impl Modules { + pub fn new() -> Modules { + Self { + info: HashMap::new(), + by_name: HashMap::new(), + } + } + + pub fn get_id(&self, name: &str) -> Option<deno_mod> { + self.by_name.get(name).cloned() + } + + pub fn get_children(&self, id: deno_mod) -> Option<&Vec<deno_mod>> { + self.info.get(&id).map(|i| &i.children) + } + + pub fn get_name(&self, id: deno_mod) -> Option<&String> { + self.info.get(&id).map(|i| &i.name) + } + + pub fn is_registered(&self, name: &str) -> bool { + self.by_name.get(name).is_some() + } + + pub fn register(&mut self, id: deno_mod, name: &str) { + let name = String::from(name); + debug!("register {}", name); + self.by_name.insert(name.clone(), id); + self.info.insert( + id, + ModuleInfo { + name, + children: Vec::new(), + }, + ); + } + + pub fn resolve_cb( + &mut self, + deno_dir: &DenoDir, + specifier: &str, + referrer: deno_mod, + ) -> deno_mod { + debug!("resolve_cb {}", specifier); + + let maybe_info = self.info.get_mut(&referrer); + if maybe_info.is_none() { + debug!("cant find referrer {}", referrer); + return 0; + } + let info = maybe_info.unwrap(); + let referrer_name = &info.name; + let r = deno_dir.resolve_module(specifier, referrer_name); + if let Err(err) = r { + debug!("potentially swallowed err: {}", err); + return 0; + } + let (name, _local_filename) = r.unwrap(); + + if let Some(id) = self.by_name.get(&name) { + let child_id = *id; + info.children.push(child_id); + return child_id; + } else { + return 0; + } + } + + pub fn print_file_info(&self, deno_dir: &DenoDir, filename: String) { + let maybe_out = deno_dir.fetch_module_meta_data(&filename, "."); + if maybe_out.is_err() { + println!("{}", maybe_out.unwrap_err()); + return; + } + let out = maybe_out.unwrap(); + + println!("{} {}", ansi::bold("local:".to_string()), &(out.filename)); + println!( + "{} {}", + ansi::bold("type:".to_string()), + msg::enum_name_media_type(out.media_type) + ); + if out.maybe_output_code_filename.is_some() { + println!( + "{} {}", + ansi::bold("compiled:".to_string()), + out.maybe_output_code_filename.as_ref().unwrap(), + ); + } + if out.maybe_source_map_filename.is_some() { + println!( + "{} {}", + ansi::bold("map:".to_string()), + out.maybe_source_map_filename.as_ref().unwrap() + ); + } + + let deps = Deps::new(self, &out.module_name); + println!("{}{}", ansi::bold("deps:\n".to_string()), deps.name); + if let Some(ref depsdeps) = deps.deps { + for d in depsdeps { + println!("{}", d); + } + } + } +} + +pub struct Deps { + pub name: String, + pub deps: Option<Vec<Deps>>, + prefix: String, + is_last: bool, +} + +impl Deps { + pub fn new(modules: &Modules, module_name: &str) -> Deps { + let mut seen = HashSet::new(); + let id = modules.get_id(module_name).unwrap(); + Self::helper(&mut seen, "".to_string(), true, modules, id) + } + + fn helper( + seen: &mut HashSet<deno_mod>, + prefix: String, + is_last: bool, + modules: &Modules, + id: deno_mod, + ) -> Deps { + let name = modules.get_name(id).unwrap().to_string(); + if seen.contains(&id) { + Deps { + name, + prefix, + deps: None, + is_last, + } + } else { + seen.insert(id); + let child_ids = modules.get_children(id).unwrap(); + let child_count = child_ids.iter().count(); + let deps = child_ids + .iter() + .enumerate() + .map(|(index, dep_id)| { + let new_is_last = index == child_count - 1; + let mut new_prefix = prefix.clone(); + new_prefix.push(if is_last { ' ' } else { '│' }); + new_prefix.push(' '); + Self::helper(seen, new_prefix, new_is_last, modules, *dep_id) + }).collect(); + Deps { + name, + prefix, + deps: Some(deps), + is_last, + } + } + } +} + +impl fmt::Display for Deps { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let mut has_children = false; + if let Some(ref deps) = self.deps { + has_children = !deps.is_empty(); + } + write!( + f, + "{}{}─{} {}", + self.prefix, + if self.is_last { "└" } else { "├" }, + if has_children { "┬" } else { "─" }, + self.name + )?; + + if let Some(ref deps) = self.deps { + for d in deps { + write!(f, "\n{}", d)?; + } + } + Ok(()) + } +} |