summaryrefslogtreecommitdiff
path: root/cli
diff options
context:
space:
mode:
Diffstat (limited to 'cli')
-rw-r--r--cli/info.rs648
-rw-r--r--cli/main.rs33
-rw-r--r--cli/media_type.rs125
-rw-r--r--cli/module_graph2.rs189
-rw-r--r--cli/specifier_handler.rs22
-rw-r--r--cli/tests/022_info_flag_script.out13
-rw-r--r--cli/tests/049_info_flag_script_jsx.out13
-rw-r--r--cli/tests/054_info_local_imports.out1
-rw-r--r--cli/tests/055_info_file_json.out42
-rw-r--r--cli/tests/cafile_info.ts.out13
-rw-r--r--cli/tests/info_recursive_imports_test.out7
11 files changed, 558 insertions, 548 deletions
diff --git a/cli/info.rs b/cli/info.rs
index 6701aafbe..9ca294287 100644
--- a/cli/info.rs
+++ b/cli/info.rs
@@ -1,404 +1,197 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
use crate::colors;
-use crate::global_state::GlobalState;
-use crate::module_graph::{ModuleGraph, ModuleGraphFile, ModuleGraphLoader};
+use crate::media_type::serialize_media_type;
+use crate::MediaType;
use crate::ModuleSpecifier;
-use crate::Permissions;
-use deno_core::error::AnyError;
-use serde::ser::Serializer;
-use serde::Serialize;
-use std::collections::{BTreeMap, HashMap, HashSet};
-use std::sync::Arc;
-// TODO(bartlomieju): rename
-/// Struct containing a module's dependency information.
-#[derive(Serialize)]
+use serde::Serialize;
+use serde::Serializer;
+use std::cmp::Ordering;
+use std::collections::BTreeMap;
+use std::collections::HashMap;
+use std::fmt;
+use std::path::PathBuf;
+
+/// The core structure representing information about a specific "root" file in
+/// a module graph. This is used to represent information as part of the `info`
+/// subcommand.
+#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
-pub struct ModuleDepInfo {
- module: String,
- local: String,
- file_type: String,
- compiled: Option<String>,
- map: Option<String>,
- dep_count: usize,
+pub struct ModuleGraphInfo {
+ pub compiled: Option<PathBuf>,
+ pub dep_count: usize,
+ #[serde(serialize_with = "serialize_media_type")]
+ pub file_type: MediaType,
+ pub files: ModuleInfoMap,
#[serde(skip_serializing)]
- deps: FileInfoDepTree,
- total_size: Option<usize>,
- files: FileInfoDepFlatGraph,
-}
-
-impl ModuleDepInfo {
- /// Creates a new `ModuleDepInfo` struct for the module with the provided `ModuleSpecifier`.
- pub async fn new(
- global_state: &Arc<GlobalState>,
- module_specifier: ModuleSpecifier,
- ) -> Result<Self, AnyError> {
- // First load module as if it was to be executed by worker
- // including compilation step
- let mut module_graph_loader = ModuleGraphLoader::new(
- global_state.file_fetcher.clone(),
- global_state.maybe_import_map.clone(),
- Permissions::allow_all(),
- false,
- true,
- );
- module_graph_loader
- .add_to_graph(&module_specifier, None)
- .await?;
- let module_graph = module_graph_loader.get_graph();
-
- let ts_compiler = &global_state.ts_compiler;
- let file_fetcher = &global_state.file_fetcher;
- let out = file_fetcher
- .fetch_cached_source_file(&module_specifier, Permissions::allow_all())
- .expect("Source file should already be cached");
- let local_filename = out.filename.to_string_lossy().to_string();
- let compiled_filename = ts_compiler
- .get_compiled_source_file(&out.url)
- .ok()
- .map(|file| file.filename.to_string_lossy().to_string());
- let map_filename = ts_compiler
- .get_source_map_file(&module_specifier)
- .ok()
- .map(|file| file.filename.to_string_lossy().to_string());
- let file_type =
- crate::media_type::enum_name_media_type(out.media_type).to_string();
-
- let deps = FileInfoDepTree::new(&module_graph, &module_specifier);
- let total_size = deps.total_size;
- let dep_count = get_unique_dep_count(&module_graph) - 1;
- let files = FileInfoDepFlatGraph::new(&module_graph);
-
- let info = Self {
- module: module_specifier.to_string(),
- local: local_filename,
- file_type,
- compiled: compiled_filename,
- map: map_filename,
- dep_count,
- deps,
- total_size,
- files,
- };
-
- Ok(info)
- }
-}
-
-/// Counts the number of dependencies in the graph.
-///
-/// We are counting only the dependencies that are not http redirects to other files.
-fn get_unique_dep_count(graph: &ModuleGraph) -> usize {
- graph.iter().fold(
- 0,
- |acc, e| {
- if e.1.redirect.is_none() {
- acc + 1
- } else {
- acc
- }
- },
- )
+ pub info: ModuleInfo,
+ pub local: PathBuf,
+ pub map: Option<PathBuf>,
+ pub module: ModuleSpecifier,
+ pub total_size: usize,
}
-impl std::fmt::Display for ModuleDepInfo {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- f.write_fmt(format_args!("{} {}\n", colors::bold("local:"), self.local))?;
- f.write_fmt(format_args!(
- "{} {}\n",
- colors::bold("type:"),
- self.file_type
- ))?;
+impl fmt::Display for ModuleGraphInfo {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ writeln!(
+ f,
+ "{} {}",
+ colors::bold("local:"),
+ self.local.to_string_lossy()
+ )?;
+ writeln!(f, "{} {}", colors::bold("type:"), self.file_type)?;
if let Some(ref compiled) = self.compiled {
- f.write_fmt(format_args!(
- "{} {}\n",
+ writeln!(
+ f,
+ "{} {}",
colors::bold("compiled:"),
- compiled
- ))?;
+ compiled.to_string_lossy()
+ )?;
}
if let Some(ref map) = self.map {
- f.write_fmt(format_args!("{} {}\n", colors::bold("map:"), map))?;
+ writeln!(f, "{} {}", colors::bold("map:"), map.to_string_lossy())?;
}
-
- f.write_fmt(format_args!(
- "{} {} unique {}\n",
+ writeln!(
+ f,
+ "{} {} unique {}",
colors::bold("deps:"),
self.dep_count,
colors::gray(&format!(
"(total {})",
- human_size(self.deps.total_size.unwrap_or(0) as f64),
+ human_size(self.info.total_size.unwrap_or(0) as f64)
))
- ))?;
- f.write_fmt(format_args!(
- "{} {}\n",
- self.deps.name,
- colors::gray(&format!("({})", human_size(self.deps.size as f64)))
- ))?;
-
- for (idx, dep) in self.deps.deps.iter().enumerate() {
- print_file_dep_info(&dep, "", idx == self.deps.deps.len() - 1, f)?;
+ )?;
+ writeln!(f)?;
+ writeln!(
+ f,
+ "{} {}",
+ self.info.name,
+ colors::gray(&format!("({})", human_size(self.info.size as f64)))
+ )?;
+
+ let dep_count = self.info.deps.len();
+ for (idx, dep) in self.info.deps.iter().enumerate() {
+ dep.write_info(f, "", idx == dep_count - 1)?;
}
Ok(())
}
}
-/// A dependency tree of the basic module information.
-///
-/// Constructed from a `ModuleGraph` and `ModuleSpecifier` that
-/// acts as the root of the tree.
-#[derive(Serialize)]
+/// Represents a unique dependency within the graph of the the dependencies for
+/// a given module.
+#[derive(Debug, Serialize, Eq, PartialEq)]
#[serde(rename_all = "camelCase")]
-struct FileInfoDepTree {
- name: String,
- size: usize,
- total_size: Option<usize>,
- deps: Vec<FileInfoDepTree>,
+pub struct ModuleInfo {
+ pub deps: Vec<ModuleInfo>,
+ pub name: ModuleSpecifier,
+ pub size: usize,
+ pub total_size: Option<usize>,
}
-impl FileInfoDepTree {
- /// Create a `FileInfoDepTree` tree from a `ModuleGraph` and the root `ModuleSpecifier`.
- pub fn new(
- module_graph: &ModuleGraph,
- root_specifier: &ModuleSpecifier,
- ) -> Self {
- let mut seen = HashSet::new();
- let mut total_sizes = HashMap::new();
-
- Self::visit_module(
- &mut seen,
- &mut total_sizes,
- module_graph,
- root_specifier,
- )
+impl PartialOrd for ModuleInfo {
+ fn partial_cmp(&self, other: &ModuleInfo) -> Option<Ordering> {
+ Some(self.cmp(other))
}
+}
- /// Visit modules recursively.
- ///
- /// If currently visited module has not yet been seen it will be annotated with dependencies
- /// and cumulative size of those deps.
- fn visit_module(
- seen: &mut HashSet<String>,
- total_sizes: &mut HashMap<String, usize>,
- graph: &ModuleGraph,
- specifier: &ModuleSpecifier,
- ) -> Self {
- let name = specifier.to_string();
- let never_seen = seen.insert(name.clone());
- let file = get_resolved_file(&graph, &specifier);
- let size = file.size();
- let mut deps = vec![];
- let mut total_size = None;
-
- if never_seen {
- let mut seen_deps = HashSet::new();
- deps = file
- .imports
- .iter()
- .map(|import| &import.resolved_specifier)
- .filter(|module_specifier| {
- seen_deps.insert(module_specifier.as_str().to_string())
- })
- .map(|specifier| {
- Self::visit_module(seen, total_sizes, graph, specifier)
- })
- .collect::<Vec<_>>();
-
- total_size = if let Some(total_size) = total_sizes.get(&name) {
- Some(total_size.to_owned())
- } else {
- let total: usize = deps
- .iter()
- .map(|dep| {
- if let Some(total_size) = dep.total_size {
- total_size
- } else {
- 0
- }
- })
- .sum();
- let total = size + total;
+impl Ord for ModuleInfo {
+ fn cmp(&self, other: &ModuleInfo) -> Ordering {
+ self.name.to_string().cmp(&other.name.to_string())
+ }
+}
- total_sizes.insert(name.clone(), total);
+impl ModuleInfo {
+ pub fn write_info(
+ &self,
+ f: &mut fmt::Formatter<'_>,
+ prefix: &str,
+ last: bool,
+ ) -> fmt::Result {
+ let sibling_connector = if last { '└' } else { '├' };
+ let child_connector = if self.deps.is_empty() { '─' } else { '┬' };
+ let totals = if self.total_size.is_some() {
+ colors::gray(&format!(" ({})", human_size(self.size as f64)))
+ } else {
+ colors::gray(" *")
+ };
- Some(total)
- };
+ writeln!(
+ f,
+ "{} {}{}",
+ colors::gray(&format!(
+ "{}{}─{}",
+ prefix, sibling_connector, child_connector
+ )),
+ self.name,
+ totals
+ )?;
+
+ let mut prefix = prefix.to_string();
+ if last {
+ prefix.push(' ');
+ } else {
+ prefix.push('│');
}
+ prefix.push(' ');
- Self {
- name,
- size,
- total_size,
- deps,
+ let dep_count = self.deps.len();
+ for (idx, dep) in self.deps.iter().enumerate() {
+ dep.write_info(f, &prefix, idx == dep_count - 1)?;
}
- }
-}
-/// Flat graph vertex with all shallow dependencies
-#[derive(Serialize)]
-#[serde(rename_all = "camelCase")]
-struct FileInfoVertex {
- size: usize,
- deps: Vec<String>,
-}
-
-impl FileInfoVertex {
- /// Creates new `FileInfoVertex` that is a single vertex dependency module
- fn new(size: usize, deps: Vec<String>) -> Self {
- Self { size, deps }
+ Ok(())
}
}
-struct FileInfoDepFlatGraph(HashMap<String, FileInfoVertex>);
+/// A flat map of dependencies for a given module graph.
+#[derive(Debug)]
+pub struct ModuleInfoMap(pub HashMap<ModuleSpecifier, ModuleInfoMapItem>);
-impl FileInfoDepFlatGraph {
- /// Creates new `FileInfoDepFlatGraph`, flat graph of a shallow module dependencies
- ///
- /// Each graph vertex represents unique dependency with its all shallow dependencies
- fn new(module_graph: &ModuleGraph) -> Self {
- let mut inner = HashMap::new();
- module_graph
- .iter()
- .for_each(|(module_name, module_graph_file)| {
- let size = module_graph_file.size();
- let mut deps = Vec::new();
- module_graph_file.imports.iter().for_each(|import| {
- deps.push(import.resolved_specifier.to_string());
- });
- inner.insert(module_name.clone(), FileInfoVertex::new(size, deps));
- });
- Self(inner)
+impl ModuleInfoMap {
+ pub fn new(map: HashMap<ModuleSpecifier, ModuleInfoMapItem>) -> Self {
+ ModuleInfoMap(map)
}
}
-impl Serialize for FileInfoDepFlatGraph {
+impl Serialize for ModuleInfoMap {
/// Serializes inner hash map which is ordered by the key
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
- let ordered: BTreeMap<_, _> = self.0.iter().collect();
+ let ordered: BTreeMap<_, _> =
+ self.0.iter().map(|(k, v)| (k.to_string(), v)).collect();
ordered.serialize(serializer)
}
}
-/// Returns a `ModuleGraphFile` associated to the provided `ModuleSpecifier`.
-///
-/// If the `specifier` is associated with a file that has a populated redirect field,
-/// it returns the file associated to the redirect, otherwise the file associated to `specifier`.
-fn get_resolved_file<'a>(
- graph: &'a ModuleGraph,
- specifier: &ModuleSpecifier,
-) -> &'a ModuleGraphFile {
- // Note(kc): This code is dependent on how we are injecting a dummy ModuleGraphFile
- // into the graph with a "redirect" property.
- let result = graph.get(specifier.as_str()).unwrap();
-
- if let Some(ref import) = result.redirect {
- graph.get(import).unwrap()
- } else {
- result
- }
-}
-
-/// Prints the `FileInfoDepTree` tree to stdout.
-fn print_file_dep_info(
- info: &FileInfoDepTree,
- prefix: &str,
- is_last: bool,
- formatter: &mut std::fmt::Formatter<'_>,
-) -> std::fmt::Result {
- print_dep(prefix, is_last, info, formatter)?;
-
- let prefix = &get_new_prefix(prefix, is_last);
- let child_count = info.deps.len();
- for (idx, dep) in info.deps.iter().enumerate() {
- print_file_dep_info(dep, prefix, idx == child_count - 1, formatter)?;
- }
-
- Ok(())
-}
-
-/// Prints a single `FileInfoDepTree` to stdout.
-fn print_dep(
- prefix: &str,
- is_last: bool,
- info: &FileInfoDepTree,
- formatter: &mut std::fmt::Formatter<'_>,
-) -> std::fmt::Result {
- let has_children = !info.deps.is_empty();
-
- formatter.write_fmt(format_args!(
- "{} {}{}\n",
- colors::gray(&format!(
- "{}{}─{}",
- prefix,
- get_sibling_connector(is_last),
- get_child_connector(has_children),
- ))
- .to_string(),
- info.name,
- get_formatted_totals(info)
- ))
-}
-
-/// Gets the formatted totals for the provided `FileInfoDepTree`.
-///
-/// If the total size is reported as 0 then an empty string is returned.
-fn get_formatted_totals(info: &FileInfoDepTree) -> String {
- if let Some(_total_size) = info.total_size {
- colors::gray(&format!(" ({})", human_size(info.size as f64),)).to_string()
- } else {
- // This dependency has already been displayed somewhere else in the tree.
- colors::gray(" *").to_string()
- }
-}
-
-/// Gets the sibling portion of the tree branch.
-fn get_sibling_connector(is_last: bool) -> char {
- if is_last {
- '└'
- } else {
- '├'
- }
-}
-
-/// Gets the child connector for the branch.
-fn get_child_connector(has_children: bool) -> char {
- if has_children {
- '┬'
- } else {
- '─'
- }
-}
-
-/// Creates a new prefix for a dependency tree item.
-fn get_new_prefix(prefix: &str, is_last: bool) -> String {
- let mut prefix = prefix.to_string();
- if is_last {
- prefix.push(' ');
- } else {
- prefix.push('│');
- }
-
- prefix.push(' ');
- prefix
+/// 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,
}
-pub fn human_size(bytse: f64) -> String {
- let negative = if bytse.is_sign_positive() { "" } else { "-" };
- let bytse = bytse.abs();
+/// 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 bytse < 1_f64 {
- return format!("{}{}{}", negative, bytse, "B");
+ if size < 1_f64 {
+ return format!("{}{}{}", negative, size, "B");
}
let delimiter = 1024_f64;
let exponent = std::cmp::min(
- (bytse.ln() / delimiter.ln()).floor() as i32,
+ (size.ln() / delimiter.ln()).floor() as i32,
(units.len() - 1) as i32,
);
- let pretty_bytes = format!("{:.2}", bytse / delimiter.powi(exponent))
+ let pretty_bytes = format!("{:.2}", size / delimiter.powi(exponent))
.parse::<f64>()
.unwrap()
* 1_f64;
@@ -409,10 +202,7 @@ pub fn human_size(bytse: f64) -> String {
#[cfg(test)]
mod test {
use super::*;
- use crate::ast::Location;
- use crate::media_type::MediaType;
- use crate::module_graph::ImportDescriptor;
- use deno_core::url::Url;
+ use deno_core::serde_json::json;
#[test]
fn human_size_test() {
@@ -427,105 +217,89 @@ mod test {
assert_eq!(human_size(16_f64 * 1024_f64.powf(8.0)), "16YB");
}
- #[test]
- fn get_new_prefix_adds_spaces_if_is_last() {
- let prefix = get_new_prefix("", true);
-
- assert_eq!(prefix, " ".to_string());
- }
-
- #[test]
- fn get_new_prefix_adds_a_vertical_bar_if_not_is_last() {
- let prefix = get_new_prefix("", false);
-
- assert_eq!(prefix, "│ ".to_string());
- }
-
- fn create_mock_file(
- name: &str,
- imports: Vec<ModuleSpecifier>,
- redirect: Option<ModuleSpecifier>,
- ) -> (ModuleGraphFile, ModuleSpecifier) {
- let spec =
- ModuleSpecifier::from(Url::parse(&format!("http://{}", name)).unwrap());
- let file = ModuleGraphFile {
- filename: "name".to_string(),
- imports: imports
- .iter()
- .map(|import| ImportDescriptor {
- specifier: import.to_string(),
- resolved_specifier: import.clone(),
- resolved_type_directive: None,
- type_directive: None,
- location: Location {
- col: 0,
- filename: "".to_string(),
- line: 0,
- },
- })
- .collect(),
- lib_directives: vec![],
- media_type: MediaType::TypeScript,
- redirect: redirect.map(|x| x.to_string()),
- referenced_files: vec![],
- source_code: "".to_string(),
- specifier: spec.to_string(),
- type_headers: vec![],
- types_directives: vec![],
- version_hash: "".to_string(),
- url: "".to_string(),
+ fn get_fixture() -> ModuleGraphInfo {
+ let spec_c =
+ ModuleSpecifier::resolve_url_or_path("https://deno.land/x/a/b/c.ts")
+ .unwrap();
+ let spec_d =
+ ModuleSpecifier::resolve_url_or_path("https://deno.land/x/a/b/c.ts")
+ .unwrap();
+ let deps = vec![ModuleInfo {
+ deps: Vec::new(),
+ name: spec_d.clone(),
+ size: 12345,
+ total_size: None,
+ }];
+ let info = ModuleInfo {
+ deps,
+ name: spec_c.clone(),
+ size: 12345,
+ total_size: Some(12345),
};
+ let mut items = HashMap::new();
+ items.insert(
+ spec_c,
+ ModuleInfoMapItem {
+ deps: vec![spec_d.clone()],
+ size: 12345,
+ },
+ );
+ items.insert(
+ spec_d,
+ ModuleInfoMapItem {
+ deps: Vec::new(),
+ size: 12345,
+ },
+ );
+ let files = ModuleInfoMap(items);
- (file, spec)
- }
-
- #[test]
- fn get_resolved_file_test() {
- let (test_file_redirect, redirect) =
- create_mock_file("test_redirect", vec![], None);
- let (test_file, original) =
- create_mock_file("test", vec![], Some(redirect.clone()));
-
- let mut graph = ModuleGraph::new();
- graph.insert(original.to_string(), test_file);
- graph.insert(redirect.to_string(), test_file_redirect);
-
- let file = get_resolved_file(&graph, &original);
-
- assert_eq!(file.specifier, redirect.to_string());
+ ModuleGraphInfo {
+ compiled: Some(PathBuf::from("/a/b/c.js")),
+ dep_count: 99,
+ file_type: MediaType::TypeScript,
+ files,
+ info,
+ local: PathBuf::from("/a/b/c.ts"),
+ map: None,
+ module: ModuleSpecifier::resolve_url_or_path(
+ "https://deno.land/x/a/b/c.ts",
+ )
+ .unwrap(),
+ total_size: 999999,
+ }
}
#[test]
- fn dependency_count_no_redirects() {
- let (a, aspec) = create_mock_file("a", vec![], None);
- let (b, bspec) = create_mock_file("b", vec![aspec.clone()], None);
- let (c, cspec) = create_mock_file("c", vec![bspec.clone()], None);
-
- let mut graph = ModuleGraph::new();
-
- graph.insert(aspec.to_string(), a);
- graph.insert(bspec.to_string(), b);
- graph.insert(cspec.to_string(), c);
-
- let count = get_unique_dep_count(&graph);
-
- assert_eq!(graph.len(), count);
+ fn test_module_graph_info_display() {
+ let fixture = get_fixture();
+ let actual = format!("{}", fixture);
+ assert!(actual.contains(" /a/b/c.ts"));
+ assert!(actual.contains(" 99 unique"));
+ assert!(actual.contains("(12.06KB)"));
+ assert!(actual.contains("\n\nhttps://deno.land/x/a/b/c.ts"));
}
#[test]
- fn dependency_count_with_redirects() {
- let (a, aspec) = create_mock_file("a", vec![], None);
- let (b, bspec) = create_mock_file("b", vec![], Some(aspec.clone()));
- let (c, cspec) = create_mock_file("c", vec![bspec.clone()], None);
-
- let mut graph = ModuleGraph::new();
-
- graph.insert(aspec.to_string(), a);
- graph.insert(bspec.to_string(), b);
- graph.insert(cspec.to_string(), c);
-
- let count = get_unique_dep_count(&graph);
-
- assert_eq!(graph.len() - 1, count);
+ fn test_module_graph_info_json() {
+ let fixture = get_fixture();
+ let actual = json!(fixture);
+ assert_eq!(
+ actual,
+ json!({
+ "compiled": "/a/b/c.js",
+ "depCount": 99,
+ "fileType": "TypeScript",
+ "files": {
+ "https://deno.land/x/a/b/c.ts":{
+ "deps": [],
+ "size": 12345
+ }
+ },
+ "local": "/a/b/c.ts",
+ "map": null,
+ "module": "https://deno.land/x/a/b/c.ts",
+ "totalSize": 999999
+ })
+ );
}
}
diff --git a/cli/main.rs b/cli/main.rs
index 7a370d555..96cef4d77 100644
--- a/cli/main.rs
+++ b/cli/main.rs
@@ -81,12 +81,14 @@ use global_state::exit_unstable;
use import_map::ImportMap;
use log::Level;
use log::LevelFilter;
+use std::cell::RefCell;
use std::env;
use std::io::Read;
use std::io::Write;
use std::iter::once;
use std::path::PathBuf;
use std::pin::Pin;
+use std::rc::Rc;
use std::sync::Arc;
use upgrade::upgrade_command;
@@ -159,27 +161,36 @@ fn get_types(unstable: bool) -> String {
async fn info_command(
flags: Flags,
- file: Option<String>,
+ maybe_specifier: Option<String>,
json: bool,
) -> Result<(), AnyError> {
if json && !flags.unstable {
exit_unstable("--json");
}
let global_state = GlobalState::new(flags)?;
- // If it was just "deno info" print location of caches and exit
- if file.is_none() {
- print_cache_info(&global_state, json)
- } else {
- let main_module = ModuleSpecifier::resolve_url_or_path(&file.unwrap())?;
- let info =
- info::ModuleDepInfo::new(&global_state, main_module.clone()).await?;
+ if let Some(specifier) = maybe_specifier {
+ let specifier = ModuleSpecifier::resolve_url_or_path(&specifier)?;
+ let handler = Rc::new(RefCell::new(specifier_handler::FetchHandler::new(
+ &global_state,
+ Permissions::allow_all(),
+ )?));
+ let mut builder = module_graph2::GraphBuilder2::new(
+ handler,
+ global_state.maybe_import_map.clone(),
+ );
+ builder.insert(&specifier).await?;
+ let graph = builder.get_graph(&global_state.lockfile)?;
+ let info = graph.info()?;
if json {
- write_json_to_stdout(&json!(info))
+ write_json_to_stdout(&json!(info))?;
} else {
- write_to_stdout_ignore_sigpipe(format!("{}", info).as_bytes())
- .map_err(AnyError::from)
+ write_to_stdout_ignore_sigpipe(format!("{}", info).as_bytes())?;
}
+ Ok(())
+ } else {
+ // If it was just "deno info" print location of caches and exit
+ print_cache_info(&global_state, json)
}
}
diff --git a/cli/media_type.rs b/cli/media_type.rs
index 84e6fbe8e..823112fa2 100644
--- a/cli/media_type.rs
+++ b/cli/media_type.rs
@@ -2,6 +2,7 @@
use serde::Serialize;
use serde::Serializer;
+use std::fmt;
use std::path::Path;
use std::path::PathBuf;
@@ -22,6 +23,23 @@ pub enum MediaType {
Unknown = 8,
}
+impl fmt::Display for MediaType {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ let value = match self {
+ MediaType::JavaScript => "JavaScript",
+ MediaType::JSX => "JSX",
+ MediaType::TypeScript => "TypeScript",
+ MediaType::Dts => "Dts",
+ MediaType::TSX => "TSX",
+ MediaType::Json => "Json",
+ MediaType::Wasm => "Wasm",
+ MediaType::BuildInfo => "BuildInfo",
+ MediaType::Unknown => "Unknown",
+ };
+ write!(f, "{}", value)
+ }
+}
+
impl<'a> From<&'a Path> for MediaType {
fn from(path: &'a Path) -> Self {
MediaType::from_path(path)
@@ -103,45 +121,74 @@ impl Serialize for MediaType {
}
}
-pub fn enum_name_media_type(mt: MediaType) -> &'static str {
- match mt {
- MediaType::JavaScript => "JavaScript",
- MediaType::JSX => "JSX",
- MediaType::TypeScript => "TypeScript",
- MediaType::Dts => "Dts",
- MediaType::TSX => "TSX",
- MediaType::Json => "Json",
- MediaType::Wasm => "Wasm",
- MediaType::BuildInfo => "BuildInfo",
- MediaType::Unknown => "Unknown",
- }
+/// Serialize a `MediaType` enum into a human readable string. The default
+/// serialization for media types is and integer.
+///
+/// TODO(@kitsonk) remove this once we stop sending MediaType into tsc.
+pub fn serialize_media_type<S>(mt: &MediaType, s: S) -> Result<S::Ok, S::Error>
+where
+ S: Serializer,
+{
+ s.serialize_str(&format!("{}", mt))
}
-#[test]
-fn test_map_file_extension() {
- assert_eq!(
- MediaType::from(Path::new("foo/bar.ts")),
- MediaType::TypeScript
- );
- assert_eq!(MediaType::from(Path::new("foo/bar.tsx")), MediaType::TSX);
- assert_eq!(
- MediaType::from(Path::new("foo/bar.d.ts")),
- MediaType::TypeScript
- );
- assert_eq!(
- MediaType::from(Path::new("foo/bar.js")),
- MediaType::JavaScript
- );
- assert_eq!(MediaType::from(Path::new("foo/bar.jsx")), MediaType::JSX);
- assert_eq!(MediaType::from(Path::new("foo/bar.json")), MediaType::Json);
- assert_eq!(MediaType::from(Path::new("foo/bar.wasm")), MediaType::Wasm);
- assert_eq!(
- MediaType::from(Path::new("foo/bar.cjs")),
- MediaType::JavaScript
- );
- assert_eq!(
- MediaType::from(Path::new("foo/bar.txt")),
- MediaType::Unknown
- );
- assert_eq!(MediaType::from(Path::new("foo/bar")), MediaType::Unknown);
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use deno_core::serde_json::json;
+
+ #[test]
+ fn test_map_file_extension() {
+ assert_eq!(
+ MediaType::from(Path::new("foo/bar.ts")),
+ MediaType::TypeScript
+ );
+ assert_eq!(MediaType::from(Path::new("foo/bar.tsx")), MediaType::TSX);
+ assert_eq!(
+ MediaType::from(Path::new("foo/bar.d.ts")),
+ MediaType::TypeScript
+ );
+ assert_eq!(
+ MediaType::from(Path::new("foo/bar.js")),
+ MediaType::JavaScript
+ );
+ assert_eq!(MediaType::from(Path::new("foo/bar.jsx")), MediaType::JSX);
+ assert_eq!(MediaType::from(Path::new("foo/bar.json")), MediaType::Json);
+ assert_eq!(MediaType::from(Path::new("foo/bar.wasm")), MediaType::Wasm);
+ assert_eq!(
+ MediaType::from(Path::new("foo/bar.cjs")),
+ MediaType::JavaScript
+ );
+ assert_eq!(
+ MediaType::from(Path::new("foo/bar.txt")),
+ MediaType::Unknown
+ );
+ assert_eq!(MediaType::from(Path::new("foo/bar")), MediaType::Unknown);
+ }
+
+ #[test]
+ fn test_serialization() {
+ assert_eq!(json!(MediaType::JavaScript), json!(0));
+ assert_eq!(json!(MediaType::JSX), json!(1));
+ assert_eq!(json!(MediaType::TypeScript), json!(2));
+ assert_eq!(json!(MediaType::Dts), json!(3));
+ assert_eq!(json!(MediaType::TSX), json!(4));
+ assert_eq!(json!(MediaType::Json), json!(5));
+ assert_eq!(json!(MediaType::Wasm), json!(6));
+ assert_eq!(json!(MediaType::BuildInfo), json!(7));
+ assert_eq!(json!(MediaType::Unknown), json!(8));
+ }
+
+ #[test]
+ fn test_display() {
+ assert_eq!(format!("{}", MediaType::JavaScript), "JavaScript");
+ assert_eq!(format!("{}", MediaType::JSX), "JSX");
+ assert_eq!(format!("{}", MediaType::TypeScript), "TypeScript");
+ assert_eq!(format!("{}", MediaType::Dts), "Dts");
+ assert_eq!(format!("{}", MediaType::TSX), "TSX");
+ assert_eq!(format!("{}", MediaType::Json), "Json");
+ assert_eq!(format!("{}", MediaType::Wasm), "Wasm");
+ assert_eq!(format!("{}", MediaType::BuildInfo), "BuildInfo");
+ assert_eq!(format!("{}", MediaType::Unknown), "Unknown");
+ }
}
diff --git a/cli/module_graph2.rs b/cli/module_graph2.rs
index 738fe188d..698586413 100644
--- a/cli/module_graph2.rs
+++ b/cli/module_graph2.rs
@@ -5,6 +5,10 @@ use crate::ast::parse;
use crate::ast::Location;
use crate::ast::ParsedModule;
use crate::import_map::ImportMap;
+use crate::info::ModuleGraphInfo;
+use crate::info::ModuleInfo;
+use crate::info::ModuleInfoMap;
+use crate::info::ModuleInfoMapItem;
use crate::lockfile::Lockfile;
use crate::media_type::MediaType;
use crate::specifier_handler::CachedModule;
@@ -30,6 +34,7 @@ use std::collections::HashMap;
use std::collections::HashSet;
use std::error::Error;
use std::fmt;
+use std::path::PathBuf;
use std::rc::Rc;
use std::result;
use std::sync::Mutex;
@@ -162,13 +167,16 @@ struct Module {
is_dirty: bool,
is_hydrated: bool,
is_parsed: bool,
+ maybe_emit_path: Option<PathBuf>,
maybe_import_map: Option<Rc<RefCell<ImportMap>>>,
+ maybe_map_path: Option<PathBuf>,
maybe_parsed_module: Option<ParsedModule>,
maybe_types: Option<(String, ModuleSpecifier)>,
maybe_version: Option<String>,
media_type: MediaType,
specifier: ModuleSpecifier,
source: String,
+ source_path: PathBuf,
}
impl Default for Module {
@@ -179,13 +187,16 @@ impl Default for Module {
is_dirty: false,
is_hydrated: false,
is_parsed: false,
+ maybe_emit_path: None,
maybe_import_map: None,
+ maybe_map_path: None,
maybe_parsed_module: None,
maybe_types: None,
maybe_version: None,
media_type: MediaType::Unknown,
specifier: ModuleSpecifier::resolve_url("https://deno.land/x/").unwrap(),
source: "".to_string(),
+ source_path: PathBuf::new(),
}
}
}
@@ -215,6 +226,9 @@ impl Module {
pub fn hydrate(&mut self, cached_module: CachedModule) {
self.media_type = cached_module.media_type;
self.source = cached_module.source;
+ self.source_path = cached_module.source_path;
+ self.maybe_emit_path = cached_module.maybe_emit_path;
+ self.maybe_map_path = cached_module.maybe_map_path;
if self.maybe_import_map.is_none() {
if let Some(dependencies) = cached_module.maybe_dependencies {
self.dependencies = dependencies;
@@ -359,6 +373,10 @@ impl Module {
pub fn set_version(&mut self, config: &[u8]) {
self.maybe_version = Some(get_version(&self.source, version::DENO, config))
}
+
+ pub fn size(&self) -> usize {
+ self.source.as_bytes().len()
+ }
}
#[derive(Clone, Debug, PartialEq)]
@@ -421,6 +439,115 @@ impl Graph2 {
}
}
+ fn get_info(
+ &self,
+ specifier: &ModuleSpecifier,
+ seen: &mut HashSet<ModuleSpecifier>,
+ totals: &mut HashMap<ModuleSpecifier, usize>,
+ ) -> ModuleInfo {
+ let not_seen = seen.insert(specifier.clone());
+ let module = self.modules.get(specifier).unwrap();
+ let mut deps = Vec::new();
+ let mut total_size = None;
+
+ if not_seen {
+ let mut seen_deps = HashSet::new();
+ // TODO(@kitsonk) https://github.com/denoland/deno/issues/7927
+ for (_, dep) in module.dependencies.iter() {
+ // Check the runtime code dependency
+ if let Some(code_dep) = &dep.maybe_code {
+ if seen_deps.insert(code_dep.clone()) {
+ deps.push(self.get_info(code_dep, seen, totals));
+ }
+ }
+ }
+ deps.sort();
+ total_size = if let Some(total) = totals.get(specifier) {
+ Some(total.to_owned())
+ } else {
+ let mut total = deps
+ .iter()
+ .map(|d| {
+ if let Some(total_size) = d.total_size {
+ total_size
+ } else {
+ 0
+ }
+ })
+ .sum();
+ total += module.size();
+ totals.insert(specifier.clone(), total);
+ Some(total)
+ };
+ }
+
+ ModuleInfo {
+ deps,
+ name: specifier.clone(),
+ size: module.size(),
+ total_size,
+ }
+ }
+
+ fn get_info_map(&self) -> ModuleInfoMap {
+ let map = self
+ .modules
+ .iter()
+ .map(|(specifier, module)| {
+ let mut deps = HashSet::new();
+ for (_, dep) in module.dependencies.iter() {
+ if let Some(code_dep) = &dep.maybe_code {
+ deps.insert(code_dep.clone());
+ }
+ if let Some(type_dep) = &dep.maybe_type {
+ deps.insert(type_dep.clone());
+ }
+ }
+ if let Some((_, types_dep)) = &module.maybe_types {
+ deps.insert(types_dep.clone());
+ }
+ let item = ModuleInfoMapItem {
+ deps: deps.into_iter().collect(),
+ size: module.size(),
+ };
+ (specifier.clone(), item)
+ })
+ .collect();
+
+ ModuleInfoMap::new(map)
+ }
+
+ /// Return a structure which provides information about the module graph and
+ /// the relationship of the modules in the graph. This structure is used to
+ /// provide information for the `info` subcommand.
+ pub fn info(&self) -> Result<ModuleGraphInfo, AnyError> {
+ if self.roots.is_empty() || self.roots.len() > 1 {
+ return Err(NotSupported(format!("Info is only supported when there is a single root module in the graph. Found: {}", self.roots.len())).into());
+ }
+
+ let module = self.roots[0].clone();
+ let m = self.modules.get(&module).unwrap();
+
+ let mut seen = HashSet::new();
+ let mut totals = HashMap::new();
+ let info = self.get_info(&module, &mut seen, &mut totals);
+
+ let files = self.get_info_map();
+ let total_size = totals.get(&module).unwrap_or(&m.size()).to_owned();
+
+ Ok(ModuleGraphInfo {
+ compiled: m.maybe_emit_path.clone(),
+ dep_count: self.modules.len() - 1,
+ file_type: m.media_type,
+ files,
+ info,
+ local: m.source_path.clone(),
+ map: m.maybe_map_path.clone(),
+ module,
+ total_size,
+ })
+ }
+
/// Update the handler with any modules that are marked as _dirty_ and update
/// any build info if present.
fn flush(&mut self, emit_type: &EmitType) -> Result<(), AnyError> {
@@ -713,25 +840,26 @@ mod tests {
.replace(":///", "_")
.replace("://", "_")
.replace("/", "-");
- let specifier_path = self.fixtures.join(specifier_text);
- let media_type =
- match specifier_path.extension().unwrap().to_str().unwrap() {
- "ts" => {
- if specifier_path.to_string_lossy().ends_with(".d.ts") {
- MediaType::Dts
- } else {
- MediaType::TypeScript
- }
+ let source_path = self.fixtures.join(specifier_text);
+ let media_type = match source_path.extension().unwrap().to_str().unwrap()
+ {
+ "ts" => {
+ if source_path.to_string_lossy().ends_with(".d.ts") {
+ MediaType::Dts
+ } else {
+ MediaType::TypeScript
}
- "tsx" => MediaType::TSX,
- "js" => MediaType::JavaScript,
- "jsx" => MediaType::JSX,
- _ => MediaType::Unknown,
- };
- let source = fs::read_to_string(specifier_path)?;
+ }
+ "tsx" => MediaType::TSX,
+ "js" => MediaType::JavaScript,
+ "jsx" => MediaType::JSX,
+ _ => MediaType::Unknown,
+ };
+ let source = fs::read_to_string(&source_path)?;
Ok(CachedModule {
source,
+ source_path,
specifier,
media_type,
..CachedModule::default()
@@ -880,6 +1008,37 @@ mod tests {
}
#[tokio::test]
+ async fn test_graph_info() {
+ let c = PathBuf::from(env::var_os("CARGO_MANIFEST_DIR").unwrap());
+ let fixtures = c.join("tests/module_graph");
+ let handler = Rc::new(RefCell::new(MockSpecifierHandler {
+ fixtures,
+ ..MockSpecifierHandler::default()
+ }));
+ let mut builder = GraphBuilder2::new(handler.clone(), None);
+ let specifier =
+ ModuleSpecifier::resolve_url_or_path("file:///tests/main.ts")
+ .expect("could not resolve module");
+ builder
+ .insert(&specifier)
+ .await
+ .expect("module not inserted");
+ let graph = builder.get_graph(&None).expect("could not get graph");
+ let info = graph.info().expect("could not get info");
+ assert!(info.compiled.is_none());
+ assert_eq!(info.dep_count, 6);
+ assert_eq!(info.file_type, MediaType::TypeScript);
+ assert_eq!(info.files.0.len(), 7);
+ assert!(info.local.to_string_lossy().ends_with("file_tests-main.ts"));
+ assert!(info.map.is_none());
+ assert_eq!(
+ info.module,
+ ModuleSpecifier::resolve_url_or_path("file:///tests/main.ts").unwrap()
+ );
+ assert_eq!(info.total_size, 344);
+ }
+
+ #[tokio::test]
async fn test_graph_transpile() {
// This is a complex scenario of transpiling, where we have TypeScript
// importing a JavaScript file (with type definitions) which imports
diff --git a/cli/specifier_handler.rs b/cli/specifier_handler.rs
index 92999632a..e392a3c3a 100644
--- a/cli/specifier_handler.rs
+++ b/cli/specifier_handler.rs
@@ -18,6 +18,7 @@ use std::collections::HashMap;
use std::env;
use std::error::Error;
use std::fmt;
+use std::path::PathBuf;
use std::pin::Pin;
use std::sync::Arc;
@@ -30,10 +31,13 @@ pub type FetchFuture =
pub struct CachedModule {
pub emits: EmitMap,
pub maybe_dependencies: Option<DependencyMap>,
+ pub maybe_emit_path: Option<PathBuf>,
+ pub maybe_map_path: Option<PathBuf>,
pub maybe_types: Option<String>,
pub maybe_version: Option<String>,
pub media_type: MediaType,
pub source: String,
+ pub source_path: PathBuf,
pub specifier: ModuleSpecifier,
}
@@ -43,10 +47,13 @@ impl Default for CachedModule {
CachedModule {
emits: HashMap::new(),
maybe_dependencies: None,
+ maybe_emit_path: None,
+ maybe_map_path: None,
maybe_types: None,
maybe_version: None,
media_type: MediaType::Unknown,
source: "".to_string(),
+ source_path: PathBuf::new(),
specifier: ModuleSpecifier::resolve_url("https://deno.land/x/mod.ts")
.unwrap(),
}
@@ -242,27 +249,34 @@ impl SpecifierHandler for FetchHandler {
None
};
- let filename =
+ let mut maybe_map_path: Option<PathBuf> = None;
+ let map_path =
disk_cache.get_cache_filename_with_extension(&url, "js.map");
- let maybe_map: Option<String> = if let Ok(map) = disk_cache.get(&filename)
+ let maybe_map: Option<String> = if let Ok(map) = disk_cache.get(&map_path)
{
+ maybe_map_path = Some(disk_cache.location.join(map_path));
Some(String::from_utf8(map)?)
} else {
None
};
let mut emits = HashMap::new();
- let filename = disk_cache.get_cache_filename_with_extension(&url, "js");
- if let Ok(code) = disk_cache.get(&filename) {
+ let mut maybe_emit_path: Option<PathBuf> = None;
+ let emit_path = disk_cache.get_cache_filename_with_extension(&url, "js");
+ if let Ok(code) = disk_cache.get(&emit_path) {
+ maybe_emit_path = Some(disk_cache.location.join(emit_path));
emits.insert(EmitType::Cli, (String::from_utf8(code)?, maybe_map));
};
Ok(CachedModule {
emits,
maybe_dependencies: None,
+ maybe_emit_path,
+ maybe_map_path,
maybe_types: source_file.types_header,
maybe_version,
media_type: source_file.media_type,
source: source_file.source_code,
+ source_path: source_file.filename,
specifier,
})
}
diff --git a/cli/tests/022_info_flag_script.out b/cli/tests/022_info_flag_script.out
index e84c253e9..83425f09f 100644
--- a/cli/tests/022_info_flag_script.out
+++ b/cli/tests/022_info_flag_script.out
@@ -2,12 +2,13 @@
local: [WILDCARD]http[WILDCARD]127.0.0.1_PORT4545[WILDCARD]
type: TypeScript
deps: 8 unique (total [WILDCARD])
+
http://127.0.0.1:4545/cli/tests/019_media_types.ts ([WILDCARD])
-├── http://localhost:4545/cli/tests/subdir/mt_text_typescript.t1.ts ([WILDCARD])
-├── http://localhost:4545/cli/tests/subdir/mt_video_vdn.t2.ts ([WILDCARD])
-├── http://localhost:4545/cli/tests/subdir/mt_video_mp2t.t3.ts ([WILDCARD])
-├── http://localhost:4545/cli/tests/subdir/mt_application_x_typescript.t4.ts ([WILDCARD])
-├── http://localhost:4545/cli/tests/subdir/mt_text_javascript.j1.js ([WILDCARD])
├── http://localhost:4545/cli/tests/subdir/mt_application_ecmascript.j2.js ([WILDCARD])
+├── http://localhost:4545/cli/tests/subdir/mt_application_x_javascript.j4.js ([WILDCARD])
+├── http://localhost:4545/cli/tests/subdir/mt_application_x_typescript.t4.ts ([WILDCARD])
├── http://localhost:4545/cli/tests/subdir/mt_text_ecmascript.j3.js ([WILDCARD])
-└── http://localhost:4545/cli/tests/subdir/mt_application_x_javascript.j4.js ([WILDCARD])
+├── http://localhost:4545/cli/tests/subdir/mt_text_javascript.j1.js ([WILDCARD])
+├── http://localhost:4545/cli/tests/subdir/mt_text_typescript.t1.ts ([WILDCARD])
+├── http://localhost:4545/cli/tests/subdir/mt_video_mp2t.t3.ts ([WILDCARD])
+└── http://localhost:4545/cli/tests/subdir/mt_video_vdn.t2.ts ([WILDCARD])
diff --git a/cli/tests/049_info_flag_script_jsx.out b/cli/tests/049_info_flag_script_jsx.out
index b5fdd980a..9260e8f67 100644
--- a/cli/tests/049_info_flag_script_jsx.out
+++ b/cli/tests/049_info_flag_script_jsx.out
@@ -2,12 +2,13 @@
local: [WILDCARD]http[WILDCARD]127.0.0.1_PORT4545[WILDCARD]
type: TypeScript
deps: 8 unique (total [WILDCARD])
+
http://127.0.0.1:4545/cli/tests/048_media_types_jsx.ts ([WILDCARD])
-├── http://localhost:4545/cli/tests/subdir/mt_text_typescript_tsx.t1.tsx ([WILDCARD])
-├── http://localhost:4545/cli/tests/subdir/mt_video_vdn_tsx.t2.tsx ([WILDCARD])
-├── http://localhost:4545/cli/tests/subdir/mt_video_mp2t_tsx.t3.tsx ([WILDCARD])
-├── http://localhost:4545/cli/tests/subdir/mt_application_x_typescript_tsx.t4.tsx ([WILDCARD])
-├── http://localhost:4545/cli/tests/subdir/mt_text_javascript_jsx.j1.jsx ([WILDCARD])
├── http://localhost:4545/cli/tests/subdir/mt_application_ecmascript_jsx.j2.jsx ([WILDCARD])
+├── http://localhost:4545/cli/tests/subdir/mt_application_x_javascript_jsx.j4.jsx ([WILDCARD])
+├── http://localhost:4545/cli/tests/subdir/mt_application_x_typescript_tsx.t4.tsx ([WILDCARD])
├── http://localhost:4545/cli/tests/subdir/mt_text_ecmascript_jsx.j3.jsx ([WILDCARD])
-└── http://localhost:4545/cli/tests/subdir/mt_application_x_javascript_jsx.j4.jsx ([WILDCARD])
+├── http://localhost:4545/cli/tests/subdir/mt_text_javascript_jsx.j1.jsx ([WILDCARD])
+├── http://localhost:4545/cli/tests/subdir/mt_text_typescript_tsx.t1.tsx ([WILDCARD])
+├── http://localhost:4545/cli/tests/subdir/mt_video_mp2t_tsx.t3.tsx ([WILDCARD])
+└── http://localhost:4545/cli/tests/subdir/mt_video_vdn_tsx.t2.tsx ([WILDCARD])
diff --git a/cli/tests/054_info_local_imports.out b/cli/tests/054_info_local_imports.out
index d199dccb3..1933a0c9c 100644
--- a/cli/tests/054_info_local_imports.out
+++ b/cli/tests/054_info_local_imports.out
@@ -1,6 +1,7 @@
local: [WILDCARD]005_more_imports.ts
type: TypeScript
deps: 3 unique (total [WILDCARD])
+
file://[WILDCARD]/005_more_imports.ts ([WILDCARD])
└─┬ file://[WILDCARD]/subdir/mod1.ts ([WILDCARD])
└─┬ file://[WILDCARD]/subdir/subdir2/mod2.ts ([WILDCARD])
diff --git a/cli/tests/055_info_file_json.out b/cli/tests/055_info_file_json.out
index 7c7bfabb9..d0274b0b8 100644
--- a/cli/tests/055_info_file_json.out
+++ b/cli/tests/055_info_file_json.out
@@ -1,33 +1,33 @@
{
- "module": "file://[WILDCARD]005_more_imports.ts",
- "local": "[WILDCARD]005_more_imports.ts",
- "fileType": "TypeScript",
"compiled": null,
- "map": null,
"depCount": 3,
- "totalSize": 757,
+ "fileType": "TypeScript",
"files": {
- "file://[WILDCARD]005_more_imports.ts": {
- "size": 211,
+ "file:///[WILDCARD]/cli/tests/005_more_imports.ts": {
"deps": [
- "file://[WILDCARD]/subdir/mod1.ts"
- ]
+ "file:///[WILDCARD]/cli/tests/subdir/mod1.ts"
+ ],
+ "size": 211
},
- "file://[WILDCARD]/subdir/mod1.ts": {
- "size": 320,
+ "file:///[WILDCARD]/cli/tests/subdir/mod1.ts": {
"deps": [
- "file://[WILDCARD]/subdir/subdir2/mod2.ts"
- ]
+ "file:///[WILDCARD]/cli/tests/subdir/subdir2/mod2.ts"
+ ],
+ "size": 320
},
- "file://[WILDCARD]/subdir/print_hello.ts": {
- "size": 63,
- "deps": []
+ "file:///[WILDCARD]/cli/tests/subdir/print_hello.ts": {
+ "deps": [],
+ "size": 63
},
- "file://[WILDCARD]/subdir/subdir2/mod2.ts": {
- "size": 163,
+ "file:///[WILDCARD]/cli/tests/subdir/subdir2/mod2.ts": {
"deps": [
- "file://[WILDCARD]/subdir/print_hello.ts"
- ]
+ "file:///[WILDCARD]/cli/tests/subdir/print_hello.ts"
+ ],
+ "size": 163
}
- }
+ },
+ "local": "[WILDCARD]005_more_imports.ts",
+ "map": null,
+ "module": "file:///[WILDCARD]/cli/tests/005_more_imports.ts",
+ "totalSize": 757
} \ No newline at end of file
diff --git a/cli/tests/cafile_info.ts.out b/cli/tests/cafile_info.ts.out
index 98b82df38..62fc631f1 100644
--- a/cli/tests/cafile_info.ts.out
+++ b/cli/tests/cafile_info.ts.out
@@ -1,12 +1,13 @@
local: [WILDCARD]https[WILDCARD]localhost_PORT5545[WILDCARD]
type: TypeScript
deps: 8 unique (total [WILDCARD])
+
https://localhost:5545/cli/tests/cafile_info.ts ([WILDCARD])
-├── https://localhost:5545/cli/tests/subdir/mt_text_typescript.t1.ts ([WILDCARD])
-├── https://localhost:5545/cli/tests/subdir/mt_video_vdn.t2.ts ([WILDCARD])
-├── https://localhost:5545/cli/tests/subdir/mt_video_mp2t.t3.ts ([WILDCARD])
-├── https://localhost:5545/cli/tests/subdir/mt_application_x_typescript.t4.ts ([WILDCARD])
-├── https://localhost:5545/cli/tests/subdir/mt_text_javascript.j1.js ([WILDCARD])
├── https://localhost:5545/cli/tests/subdir/mt_application_ecmascript.j2.js ([WILDCARD])
+├── https://localhost:5545/cli/tests/subdir/mt_application_x_javascript.j4.js ([WILDCARD])
+├── https://localhost:5545/cli/tests/subdir/mt_application_x_typescript.t4.ts ([WILDCARD])
├── https://localhost:5545/cli/tests/subdir/mt_text_ecmascript.j3.js ([WILDCARD])
-└── https://localhost:5545/cli/tests/subdir/mt_application_x_javascript.j4.js ([WILDCARD])
+├── https://localhost:5545/cli/tests/subdir/mt_text_javascript.j1.js ([WILDCARD])
+├── https://localhost:5545/cli/tests/subdir/mt_text_typescript.t1.ts ([WILDCARD])
+├── https://localhost:5545/cli/tests/subdir/mt_video_mp2t.t3.ts ([WILDCARD])
+└── https://localhost:5545/cli/tests/subdir/mt_video_vdn.t2.ts ([WILDCARD])
diff --git a/cli/tests/info_recursive_imports_test.out b/cli/tests/info_recursive_imports_test.out
index 12fb0e7d3..4afd00544 100644
--- a/cli/tests/info_recursive_imports_test.out
+++ b/cli/tests/info_recursive_imports_test.out
@@ -1,11 +1,12 @@
local: [WILDCARD]info_recursive_imports_test.ts
type: TypeScript
deps: 4 unique (total [WILDCARD])
+
file://[WILDCARD]cli/tests/info_recursive_imports_test.ts ([WILDCARD])
└─┬ file://[WILDCARD]cli/tests/recursive_imports/A.ts ([WILDCARD])
├─┬ file://[WILDCARD]cli/tests/recursive_imports/B.ts ([WILDCARD])
│ ├─┬ file://[WILDCARD]cli/tests/recursive_imports/C.ts ([WILDCARD])
│ │ ├── file://[WILDCARD]cli/tests/recursive_imports/A.ts *
- │ │ └── file://[WILDCARD]cli/tests/recursive_imports/common.ts ([WILDCARD])
- │ └── file://[WILDCARD]cli/tests/recursive_imports/common.ts *
- └── file://[WILDCARD]cli/tests/recursive_imports/common.ts *
+ │ │ └── file://[WILDCARD]cli/tests/recursive_imports/common.ts [WILDCARD]
+ │ └── file://[WILDCARD]cli/tests/recursive_imports/common.ts [WILDCARD]
+ └── file://[WILDCARD]cli/tests/recursive_imports/common.ts [WILDCARD]