diff options
Diffstat (limited to 'cli/info.rs')
-rw-r--r-- | cli/info.rs | 513 |
1 files changed, 0 insertions, 513 deletions
diff --git a/cli/info.rs b/cli/info.rs deleted file mode 100644 index 0f062028e..000000000 --- a/cli/info.rs +++ /dev/null @@ -1,513 +0,0 @@ -// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. - -use crate::colors; - -use deno_ast::MediaType; -use deno_core::resolve_url; -use deno_core::serde::Serialize; -use deno_core::ModuleSpecifier; -use std::collections::HashSet; -use std::fmt; -use std::iter::Iterator; -use std::path::PathBuf; - -const SIBLING_CONNECTOR: char = '├'; -const LAST_SIBLING_CONNECTOR: char = '└'; -const CHILD_DEPS_CONNECTOR: char = '┬'; -const CHILD_NO_DEPS_CONNECTOR: char = '─'; -const VERTICAL_CONNECTOR: char = '│'; -const EMPTY_CONNECTOR: char = ' '; - -#[derive(Debug, Serialize, Ord, PartialOrd, Eq, PartialEq)] -#[serde(rename_all = "camelCase")] -pub struct ModuleGraphInfoDep { - pub specifier: String, - #[serde(skip_serializing_if = "is_false")] - pub is_dynamic: bool, - #[serde(rename = "code", skip_serializing_if = "Option::is_none")] - pub maybe_code: Option<ModuleSpecifier>, - #[serde(rename = "type", skip_serializing_if = "Option::is_none")] - pub maybe_type: Option<ModuleSpecifier>, -} - -fn is_false(b: &bool) -> bool { - !b -} - -impl ModuleGraphInfoDep { - fn write_info<S: AsRef<str> + fmt::Display + Clone>( - &self, - f: &mut fmt::Formatter, - prefix: S, - last: bool, - modules: &[ModuleGraphInfoMod], - seen: &mut HashSet<ModuleSpecifier>, - ) -> fmt::Result { - let maybe_code = self - .maybe_code - .as_ref() - .and_then(|s| modules.iter().find(|m| &m.specifier == s)); - let maybe_type = self - .maybe_type - .as_ref() - .and_then(|s| modules.iter().find(|m| &m.specifier == s)); - match (maybe_code, maybe_type) { - (Some(code), Some(types)) => { - code.write_info(f, prefix.clone(), false, false, modules, seen)?; - types.write_info(f, prefix, last, true, modules, seen) - } - (Some(code), None) => { - code.write_info(f, prefix, last, false, modules, seen) - } - (None, Some(types)) => { - types.write_info(f, prefix, last, true, modules, seen) - } - _ => Ok(()), - } - } -} - -#[derive(Debug, Serialize, Ord, PartialOrd, Eq, PartialEq)] -#[serde(rename_all = "camelCase")] -pub struct ModuleGraphInfoMod { - pub specifier: ModuleSpecifier, - pub dependencies: Vec<ModuleGraphInfoDep>, - #[serde(rename = "typeDependency", skip_serializing_if = "Option::is_none")] - pub maybe_type_dependency: Option<ModuleGraphInfoDep>, - #[serde(skip_serializing_if = "Option::is_none")] - pub size: Option<usize>, - #[serde(skip_serializing_if = "Option::is_none")] - pub media_type: Option<MediaType>, - #[serde(skip_serializing_if = "Option::is_none")] - pub local: Option<PathBuf>, - #[serde(skip_serializing_if = "Option::is_none")] - pub checksum: Option<String>, - #[serde(skip_serializing_if = "Option::is_none")] - pub emit: Option<PathBuf>, - #[serde(skip_serializing_if = "Option::is_none")] - pub map: Option<PathBuf>, - #[serde(skip_serializing_if = "Option::is_none")] - pub error: Option<String>, -} - -impl Default for ModuleGraphInfoMod { - fn default() -> Self { - ModuleGraphInfoMod { - specifier: resolve_url("https://deno.land/x/mod.ts").unwrap(), - dependencies: Vec::new(), - maybe_type_dependency: None, - size: None, - media_type: None, - local: None, - checksum: None, - emit: None, - map: None, - error: None, - } - } -} - -impl ModuleGraphInfoMod { - fn write_info<S: AsRef<str> + fmt::Display>( - &self, - f: &mut fmt::Formatter, - prefix: S, - last: bool, - type_dep: bool, - modules: &[ModuleGraphInfoMod], - seen: &mut HashSet<ModuleSpecifier>, - ) -> fmt::Result { - let was_seen = seen.contains(&self.specifier); - let sibling_connector = if last { - LAST_SIBLING_CONNECTOR - } else { - SIBLING_CONNECTOR - }; - let child_connector = if (self.dependencies.is_empty() - && self.maybe_type_dependency.is_none()) - || was_seen - { - CHILD_NO_DEPS_CONNECTOR - } else { - CHILD_DEPS_CONNECTOR - }; - let (size, specifier) = if self.error.is_some() { - ( - colors::red_bold(" (error)").to_string(), - colors::red(&self.specifier).to_string(), - ) - } else if was_seen { - let name = if type_dep { - colors::italic_gray(&self.specifier).to_string() - } else { - colors::gray(&self.specifier).to_string() - }; - (colors::gray(" *").to_string(), name) - } else { - let name = if type_dep { - colors::italic(&self.specifier).to_string() - } else { - self.specifier.to_string() - }; - ( - colors::gray(format!( - " ({})", - human_size(self.size.unwrap_or(0) as f64) - )) - .to_string(), - name, - ) - }; - - seen.insert(self.specifier.clone()); - - writeln!( - f, - "{} {}{}", - colors::gray(format!( - "{}{}─{}", - prefix, sibling_connector, child_connector - )), - specifier, - size - )?; - - if !was_seen { - let mut prefix = prefix.to_string(); - if last { - prefix.push(EMPTY_CONNECTOR); - } else { - prefix.push(VERTICAL_CONNECTOR); - } - prefix.push(EMPTY_CONNECTOR); - let dep_count = self.dependencies.len(); - for (idx, dep) in self.dependencies.iter().enumerate() { - dep.write_info( - f, - &prefix, - idx == dep_count - 1 && self.maybe_type_dependency.is_none(), - modules, - seen, - )?; - } - if let Some(dep) = &self.maybe_type_dependency { - dep.write_info(f, &prefix, true, modules, seen)?; - } - } - - Ok(()) - } -} - -#[derive(Debug, Serialize)] -#[serde(rename_all = "camelCase")] -pub struct ModuleGraphInfo { - pub root: ModuleSpecifier, - pub modules: Vec<ModuleGraphInfoMod>, - pub size: usize, -} - -impl fmt::Display for ModuleGraphInfo { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let root = self - .modules - .iter() - .find(|m| m.specifier == self.root) - .unwrap(); - if let Some(err) = &root.error { - writeln!(f, "{} {}", colors::red("error:"), err) - } else { - if let Some(local) = &root.local { - writeln!(f, "{} {}", colors::bold("local:"), local.to_string_lossy())?; - } - if let Some(media_type) = &root.media_type { - writeln!(f, "{} {}", colors::bold("type:"), media_type)?; - } - if let Some(emit) = &root.emit { - writeln!(f, "{} {}", colors::bold("emit:"), emit.to_string_lossy())?; - } - if let Some(map) = &root.map { - writeln!(f, "{} {}", colors::bold("map:"), map.to_string_lossy())?; - } - let dep_count = self.modules.len() - 1; - writeln!( - f, - "{} {} unique {}", - colors::bold("dependencies:"), - dep_count, - colors::gray(format!("(total {})", human_size(self.size as f64))) - )?; - writeln!( - f, - "\n{} {}", - self.root, - colors::gray(format!( - "({})", - human_size(root.size.unwrap_or(0) as f64) - )) - )?; - let mut seen = HashSet::new(); - let dep_len = root.dependencies.len(); - for (idx, dep) in root.dependencies.iter().enumerate() { - dep.write_info( - f, - "", - idx == dep_len - 1 && root.maybe_type_dependency.is_none(), - &self.modules, - &mut seen, - )?; - } - if let Some(dep) = &root.maybe_type_dependency { - dep.write_info(f, "", true, &self.modules, &mut seen)?; - } - Ok(()) - } - } -} - -/// An entry in the `ModuleInfoMap` the provides the size of the module and -/// a vector of its dependencies, which should also be available as entries -/// in the map. -#[derive(Debug, Serialize)] -#[serde(rename_all = "camelCase")] -pub struct ModuleInfoMapItem { - pub deps: Vec<ModuleSpecifier>, - pub size: usize, -} - -/// A function that converts a float to a string the represents a human -/// readable version of that number. -pub fn human_size(size: f64) -> String { - let negative = if size.is_sign_positive() { "" } else { "-" }; - let size = size.abs(); - let units = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"]; - if size < 1_f64 { - return format!("{}{}{}", negative, size, "B"); - } - let delimiter = 1024_f64; - let exponent = std::cmp::min( - (size.ln() / delimiter.ln()).floor() as i32, - (units.len() - 1) as i32, - ); - let pretty_bytes = format!("{:.2}", size / delimiter.powi(exponent)) - .parse::<f64>() - .unwrap() - * 1_f64; - let unit = units[exponent as usize]; - format!("{}{}{}", negative, pretty_bytes, unit) -} - -#[cfg(test)] -mod test { - use super::*; - use deno_core::resolve_url; - use deno_core::serde_json::json; - - #[test] - fn human_size_test() { - assert_eq!(human_size(16_f64), "16B"); - assert_eq!(human_size((16 * 1024) as f64), "16KB"); - assert_eq!(human_size((16 * 1024 * 1024) as f64), "16MB"); - assert_eq!(human_size(16_f64 * 1024_f64.powf(3.0)), "16GB"); - assert_eq!(human_size(16_f64 * 1024_f64.powf(4.0)), "16TB"); - assert_eq!(human_size(16_f64 * 1024_f64.powf(5.0)), "16PB"); - assert_eq!(human_size(16_f64 * 1024_f64.powf(6.0)), "16EB"); - assert_eq!(human_size(16_f64 * 1024_f64.powf(7.0)), "16ZB"); - assert_eq!(human_size(16_f64 * 1024_f64.powf(8.0)), "16YB"); - } - - fn get_fixture() -> ModuleGraphInfo { - let specifier_a = resolve_url("https://deno.land/x/a.ts").unwrap(); - let specifier_b = resolve_url("https://deno.land/x/b.ts").unwrap(); - let specifier_c_js = resolve_url("https://deno.land/x/c.js").unwrap(); - let specifier_c_dts = resolve_url("https://deno.land/x/c.d.ts").unwrap(); - let specifier_d_js = resolve_url("https://deno.land/x/d.js").unwrap(); - let specifier_d_dts = resolve_url("https://deno.land/x/d.d.ts").unwrap(); - let modules = vec![ - ModuleGraphInfoMod { - specifier: specifier_a.clone(), - dependencies: vec![ModuleGraphInfoDep { - specifier: "./b.ts".to_string(), - is_dynamic: false, - maybe_code: Some(specifier_b.clone()), - maybe_type: None, - }], - size: Some(123), - media_type: Some(MediaType::TypeScript), - local: Some(PathBuf::from("/cache/deps/https/deno.land/x/a.ts")), - checksum: Some("abcdef".to_string()), - emit: Some(PathBuf::from("/cache/emit/https/deno.land/x/a.js")), - ..Default::default() - }, - ModuleGraphInfoMod { - specifier: specifier_b, - dependencies: vec![ModuleGraphInfoDep { - specifier: "./c.js".to_string(), - is_dynamic: false, - maybe_code: Some(specifier_c_js.clone()), - maybe_type: Some(specifier_c_dts.clone()), - }], - size: Some(456), - media_type: Some(MediaType::TypeScript), - local: Some(PathBuf::from("/cache/deps/https/deno.land/x/b.ts")), - checksum: Some("def123".to_string()), - emit: Some(PathBuf::from("/cache/emit/https/deno.land/x/b.js")), - ..Default::default() - }, - ModuleGraphInfoMod { - specifier: specifier_c_js, - dependencies: vec![ModuleGraphInfoDep { - specifier: "./d.js".to_string(), - is_dynamic: false, - maybe_code: Some(specifier_d_js.clone()), - maybe_type: None, - }], - size: Some(789), - media_type: Some(MediaType::JavaScript), - local: Some(PathBuf::from("/cache/deps/https/deno.land/x/c.js")), - checksum: Some("9876abcef".to_string()), - ..Default::default() - }, - ModuleGraphInfoMod { - specifier: specifier_c_dts, - size: Some(999), - media_type: Some(MediaType::Dts), - local: Some(PathBuf::from("/cache/deps/https/deno.land/x/c.d.ts")), - checksum: Some("a2b3c4d5".to_string()), - ..Default::default() - }, - ModuleGraphInfoMod { - specifier: specifier_d_js, - size: Some(987), - maybe_type_dependency: Some(ModuleGraphInfoDep { - specifier: "/x/d.d.ts".to_string(), - is_dynamic: false, - maybe_code: None, - maybe_type: Some(specifier_d_dts.clone()), - }), - media_type: Some(MediaType::JavaScript), - local: Some(PathBuf::from("/cache/deps/https/deno.land/x/d.js")), - checksum: Some("5k6j7h8g".to_string()), - ..Default::default() - }, - ModuleGraphInfoMod { - specifier: specifier_d_dts, - size: Some(67), - media_type: Some(MediaType::Dts), - local: Some(PathBuf::from("/cache/deps/https/deno.land/x/d.d.ts")), - checksum: Some("0h0h0h0h0h".to_string()), - ..Default::default() - }, - ]; - ModuleGraphInfo { - root: specifier_a, - modules, - size: 99999, - } - } - - #[test] - fn text_module_graph_info_display() { - let fixture = get_fixture(); - let text = fixture.to_string(); - let actual = test_util::strip_ansi_codes(&text); - let expected = r#"local: /cache/deps/https/deno.land/x/a.ts -type: TypeScript -emit: /cache/emit/https/deno.land/x/a.js -dependencies: 5 unique (total 97.66KB) - -https://deno.land/x/a.ts (123B) -└─┬ https://deno.land/x/b.ts (456B) - ├─┬ https://deno.land/x/c.js (789B) - │ └─┬ https://deno.land/x/d.js (987B) - │ └── https://deno.land/x/d.d.ts (67B) - └── https://deno.land/x/c.d.ts (999B) -"#; - assert_eq!(actual, expected); - } - - #[test] - fn test_module_graph_info_json() { - let fixture = get_fixture(); - let actual = json!(fixture); - assert_eq!( - actual, - json!({ - "root": "https://deno.land/x/a.ts", - "modules": [ - { - "specifier": "https://deno.land/x/a.ts", - "dependencies": [ - { - "specifier": "./b.ts", - "code": "https://deno.land/x/b.ts" - } - ], - "size": 123, - "mediaType": "TypeScript", - "local": "/cache/deps/https/deno.land/x/a.ts", - "checksum": "abcdef", - "emit": "/cache/emit/https/deno.land/x/a.js" - }, - { - "specifier": "https://deno.land/x/b.ts", - "dependencies": [ - { - "specifier": "./c.js", - "code": "https://deno.land/x/c.js", - "type": "https://deno.land/x/c.d.ts" - } - ], - "size": 456, - "mediaType": "TypeScript", - "local": "/cache/deps/https/deno.land/x/b.ts", - "checksum": "def123", - "emit": "/cache/emit/https/deno.land/x/b.js" - }, - { - "specifier": "https://deno.land/x/c.js", - "dependencies": [ - { - "specifier": "./d.js", - "code": "https://deno.land/x/d.js" - } - ], - "size": 789, - "mediaType": "JavaScript", - "local": "/cache/deps/https/deno.land/x/c.js", - "checksum": "9876abcef" - }, - { - "specifier": "https://deno.land/x/c.d.ts", - "dependencies": [], - "size": 999, - "mediaType": "Dts", - "local": "/cache/deps/https/deno.land/x/c.d.ts", - "checksum": "a2b3c4d5" - }, - { - "specifier": "https://deno.land/x/d.js", - "dependencies": [], - "typeDependency": { - "specifier": "/x/d.d.ts", - "type": "https://deno.land/x/d.d.ts" - }, - "size": 987, - "mediaType": "JavaScript", - "local": "/cache/deps/https/deno.land/x/d.js", - "checksum": "5k6j7h8g" - }, - { - "specifier": "https://deno.land/x/d.d.ts", - "dependencies": [], - "size": 67, - "mediaType": "Dts", - "local": "/cache/deps/https/deno.land/x/d.d.ts", - "checksum": "0h0h0h0h0h" - } - ], - "size": 99999 - }) - ); - } -} |