mirror of
https://github.com/denoland/deno.git
synced 2025-03-03 17:34:47 -05:00
feat(cli): json option for "deno info" (#6372)
This commit is contained in:
parent
a2bf61d1ae
commit
cbbd944359
7 changed files with 213 additions and 93 deletions
41
cli/flags.rs
41
cli/flags.rs
|
@ -41,6 +41,7 @@ pub enum DenoSubcommand {
|
||||||
},
|
},
|
||||||
Help,
|
Help,
|
||||||
Info {
|
Info {
|
||||||
|
json: bool,
|
||||||
file: Option<String>,
|
file: Option<String>,
|
||||||
},
|
},
|
||||||
Install {
|
Install {
|
||||||
|
@ -454,10 +455,11 @@ fn eval_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
|
||||||
fn info_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
|
fn info_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
|
||||||
ca_file_arg_parse(flags, matches);
|
ca_file_arg_parse(flags, matches);
|
||||||
unstable_arg_parse(flags, matches);
|
unstable_arg_parse(flags, matches);
|
||||||
|
let json = matches.is_present("json");
|
||||||
no_check_arg_parse(flags, matches);
|
no_check_arg_parse(flags, matches);
|
||||||
|
|
||||||
flags.subcommand = DenoSubcommand::Info {
|
flags.subcommand = DenoSubcommand::Info {
|
||||||
file: matches.value_of("file").map(|f| f.to_string()),
|
file: matches.value_of("file").map(|f| f.to_string()),
|
||||||
|
json,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -824,6 +826,12 @@ TypeScript compiler cache: Subdirectory containing TS compiler output.",
|
||||||
.arg(ca_file_arg())
|
.arg(ca_file_arg())
|
||||||
.arg(no_check_arg())
|
.arg(no_check_arg())
|
||||||
.arg(unstable_arg())
|
.arg(unstable_arg())
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("json")
|
||||||
|
.long("json")
|
||||||
|
.help("Outputs the information in JSON format")
|
||||||
|
.takes_value(false),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cache_subcommand<'a, 'b>() -> App<'a, 'b> {
|
fn cache_subcommand<'a, 'b>() -> App<'a, 'b> {
|
||||||
|
@ -1784,6 +1792,19 @@ mod tests {
|
||||||
r.unwrap(),
|
r.unwrap(),
|
||||||
Flags {
|
Flags {
|
||||||
subcommand: DenoSubcommand::Info {
|
subcommand: DenoSubcommand::Info {
|
||||||
|
json: false,
|
||||||
|
file: Some("script.ts".to_string()),
|
||||||
|
},
|
||||||
|
..Flags::default()
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
let r = flags_from_vec_safe(svec!["deno", "info", "--json", "script.ts"]);
|
||||||
|
assert_eq!(
|
||||||
|
r.unwrap(),
|
||||||
|
Flags {
|
||||||
|
subcommand: DenoSubcommand::Info {
|
||||||
|
json: true,
|
||||||
file: Some("script.ts".to_string()),
|
file: Some("script.ts".to_string()),
|
||||||
},
|
},
|
||||||
..Flags::default()
|
..Flags::default()
|
||||||
|
@ -1794,7 +1815,22 @@ mod tests {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
r.unwrap(),
|
r.unwrap(),
|
||||||
Flags {
|
Flags {
|
||||||
subcommand: DenoSubcommand::Info { file: None },
|
subcommand: DenoSubcommand::Info {
|
||||||
|
json: false,
|
||||||
|
file: None
|
||||||
|
},
|
||||||
|
..Flags::default()
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
let r = flags_from_vec_safe(svec!["deno", "info", "--json"]);
|
||||||
|
assert_eq!(
|
||||||
|
r.unwrap(),
|
||||||
|
Flags {
|
||||||
|
subcommand: DenoSubcommand::Info {
|
||||||
|
json: true,
|
||||||
|
file: None
|
||||||
|
},
|
||||||
..Flags::default()
|
..Flags::default()
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -2790,6 +2826,7 @@ mod tests {
|
||||||
r.unwrap(),
|
r.unwrap(),
|
||||||
Flags {
|
Flags {
|
||||||
subcommand: DenoSubcommand::Info {
|
subcommand: DenoSubcommand::Info {
|
||||||
|
json: false,
|
||||||
file: Some("https://example.com".to_string()),
|
file: Some("https://example.com".to_string()),
|
||||||
},
|
},
|
||||||
ca_file: Some("example.crt".to_owned()),
|
ca_file: Some("example.crt".to_owned()),
|
||||||
|
|
121
cli/main.rs
121
cli/main.rs
|
@ -81,6 +81,7 @@ use crate::permissions::Permissions;
|
||||||
use crate::tsc::TargetLib;
|
use crate::tsc::TargetLib;
|
||||||
use crate::worker::MainWorker;
|
use crate::worker::MainWorker;
|
||||||
use deno_core::v8_set_flags;
|
use deno_core::v8_set_flags;
|
||||||
|
use deno_core::Deps;
|
||||||
use deno_core::ErrBox;
|
use deno_core::ErrBox;
|
||||||
use deno_core::EsIsolate;
|
use deno_core::EsIsolate;
|
||||||
use deno_core::ModuleSpecifier;
|
use deno_core::ModuleSpecifier;
|
||||||
|
@ -91,6 +92,7 @@ use futures::Future;
|
||||||
use log::Level;
|
use log::Level;
|
||||||
use log::Metadata;
|
use log::Metadata;
|
||||||
use log::Record;
|
use log::Record;
|
||||||
|
use state::exit_unstable;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
|
@ -140,22 +142,47 @@ fn write_to_stdout_ignore_sigpipe(bytes: &[u8]) -> Result<(), std::io::Error> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_cache_info(state: &GlobalState) {
|
fn write_json_to_stdout<T>(value: &T) -> Result<(), ErrBox>
|
||||||
println!(
|
where
|
||||||
"{} {:?}",
|
T: ?Sized + serde::ser::Serialize,
|
||||||
colors::bold("DENO_DIR location:"),
|
{
|
||||||
state.dir.root
|
let writer = std::io::BufWriter::new(std::io::stdout());
|
||||||
);
|
serde_json::to_writer_pretty(writer, value).map_err(ErrBox::from)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn print_cache_info(state: &GlobalState, json: bool) -> Result<(), ErrBox> {
|
||||||
|
let deno_dir = &state.dir.root;
|
||||||
|
let modules_cache = &state.file_fetcher.http_cache.location;
|
||||||
|
let typescript_cache = &state.dir.gen_cache.location;
|
||||||
|
if json {
|
||||||
|
let output = json!({
|
||||||
|
"denoDir": deno_dir,
|
||||||
|
"modulesCache": modules_cache,
|
||||||
|
"typescriptCache": typescript_cache,
|
||||||
|
});
|
||||||
|
write_json_to_stdout(&output)
|
||||||
|
} else {
|
||||||
|
println!("{} {:?}", colors::bold("DENO_DIR location:"), deno_dir);
|
||||||
println!(
|
println!(
|
||||||
"{} {:?}",
|
"{} {:?}",
|
||||||
colors::bold("Remote modules cache:"),
|
colors::bold("Remote modules cache:"),
|
||||||
state.file_fetcher.http_cache.location
|
modules_cache
|
||||||
);
|
);
|
||||||
println!(
|
println!(
|
||||||
"{} {:?}",
|
"{} {:?}",
|
||||||
colors::bold("TypeScript compiler cache:"),
|
colors::bold("TypeScript compiler cache:"),
|
||||||
state.dir.gen_cache.location
|
typescript_cache
|
||||||
);
|
);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct FileInfoOutput<'a> {
|
||||||
|
local: &'a str,
|
||||||
|
file_type: &'a str,
|
||||||
|
compiled: Option<String>,
|
||||||
|
map: Option<String>,
|
||||||
|
deps: Option<Deps>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(bartlomieju): this function de facto repeats
|
// TODO(bartlomieju): this function de facto repeats
|
||||||
|
@ -163,6 +190,7 @@ fn print_cache_info(state: &GlobalState) {
|
||||||
async fn print_file_info(
|
async fn print_file_info(
|
||||||
worker: &MainWorker,
|
worker: &MainWorker,
|
||||||
module_specifier: ModuleSpecifier,
|
module_specifier: ModuleSpecifier,
|
||||||
|
json: bool,
|
||||||
) -> Result<(), ErrBox> {
|
) -> Result<(), ErrBox> {
|
||||||
let global_state = worker.state.borrow().global_state.clone();
|
let global_state = worker.state.borrow().global_state.clone();
|
||||||
|
|
||||||
|
@ -171,17 +199,13 @@ async fn print_file_info(
|
||||||
.fetch_source_file(&module_specifier, None, Permissions::allow_all())
|
.fetch_source_file(&module_specifier, None, Permissions::allow_all())
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
println!(
|
let mut output = FileInfoOutput {
|
||||||
"{} {}",
|
local: out.filename.to_str().unwrap(),
|
||||||
colors::bold("local:"),
|
file_type: msg::enum_name_media_type(out.media_type),
|
||||||
out.filename.to_str().unwrap()
|
compiled: None,
|
||||||
);
|
map: None,
|
||||||
|
deps: None,
|
||||||
println!(
|
};
|
||||||
"{} {}",
|
|
||||||
colors::bold("type:"),
|
|
||||||
msg::enum_name_media_type(out.media_type)
|
|
||||||
);
|
|
||||||
|
|
||||||
let module_specifier_ = module_specifier.clone();
|
let module_specifier_ = module_specifier.clone();
|
||||||
|
|
||||||
|
@ -208,12 +232,8 @@ async fn print_file_info(
|
||||||
.ts_compiler
|
.ts_compiler
|
||||||
.get_compiled_source_file(&out.url)
|
.get_compiled_source_file(&out.url)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
output.compiled =
|
||||||
println!(
|
compiled_source_file.filename.to_str().map(|s| s.to_owned());
|
||||||
"{} {}",
|
|
||||||
colors::bold("compiled:"),
|
|
||||||
compiled_source_file.filename.to_str().unwrap(),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Ok(source_map) = global_state
|
if let Ok(source_map) = global_state
|
||||||
|
@ -221,17 +241,34 @@ async fn print_file_info(
|
||||||
.ts_compiler
|
.ts_compiler
|
||||||
.get_source_map_file(&module_specifier)
|
.get_source_map_file(&module_specifier)
|
||||||
{
|
{
|
||||||
println!(
|
output.map = source_map.filename.to_str().map(|s| s.to_owned());
|
||||||
"{} {}",
|
|
||||||
colors::bold("map:"),
|
|
||||||
source_map.filename.to_str().unwrap()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let es_state_rc = EsIsolate::state(&worker.isolate);
|
let es_state_rc = EsIsolate::state(&worker.isolate);
|
||||||
let es_state = es_state_rc.borrow();
|
let es_state = es_state_rc.borrow();
|
||||||
|
|
||||||
if let Some(deps) = es_state.modules.deps(&module_specifier) {
|
if let Some(deps) = es_state.modules.deps(&module_specifier) {
|
||||||
|
output.deps = Some(deps);
|
||||||
|
}
|
||||||
|
|
||||||
|
if json {
|
||||||
|
let output = json!({
|
||||||
|
"local": output.local,
|
||||||
|
"fileType": output.file_type,
|
||||||
|
"compiled": output.compiled,
|
||||||
|
"map": output.map,
|
||||||
|
"deps": output.deps.map(|x| x.to_json())
|
||||||
|
});
|
||||||
|
write_json_to_stdout(&output)
|
||||||
|
} else {
|
||||||
|
println!("{} {}", colors::bold("local:"), output.local);
|
||||||
|
println!("{} {}", colors::bold("type:"), output.file_type);
|
||||||
|
if let Some(compiled) = output.compiled {
|
||||||
|
println!("{} {}", colors::bold("compiled:"), compiled);
|
||||||
|
}
|
||||||
|
if let Some(map) = output.map {
|
||||||
|
println!("{} {}", colors::bold("map:"), map);
|
||||||
|
}
|
||||||
|
if let Some(deps) = output.deps {
|
||||||
println!("{}{}", colors::bold("deps:\n"), deps.name);
|
println!("{}{}", colors::bold("deps:\n"), deps.name);
|
||||||
if let Some(ref depsdeps) = deps.deps {
|
if let Some(ref depsdeps) = deps.deps {
|
||||||
for d in depsdeps {
|
for d in depsdeps {
|
||||||
|
@ -244,8 +281,8 @@ async fn print_file_info(
|
||||||
colors::bold("deps:"),
|
colors::bold("deps:"),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_types(unstable: bool) -> String {
|
fn get_types(unstable: bool) -> String {
|
||||||
|
@ -270,18 +307,21 @@ fn get_types(unstable: bool) -> String {
|
||||||
async fn info_command(
|
async fn info_command(
|
||||||
flags: Flags,
|
flags: Flags,
|
||||||
file: Option<String>,
|
file: Option<String>,
|
||||||
|
json: bool,
|
||||||
) -> Result<(), ErrBox> {
|
) -> Result<(), ErrBox> {
|
||||||
|
if json && !flags.unstable {
|
||||||
|
exit_unstable("--json");
|
||||||
|
}
|
||||||
let global_state = GlobalState::new(flags)?;
|
let global_state = GlobalState::new(flags)?;
|
||||||
// If it was just "deno info" print location of caches and exit
|
// If it was just "deno info" print location of caches and exit
|
||||||
if file.is_none() {
|
if file.is_none() {
|
||||||
print_cache_info(&global_state);
|
print_cache_info(&global_state, json)
|
||||||
return Ok(());
|
} else {
|
||||||
}
|
|
||||||
|
|
||||||
let main_module = ModuleSpecifier::resolve_url_or_path(&file.unwrap())?;
|
let main_module = ModuleSpecifier::resolve_url_or_path(&file.unwrap())?;
|
||||||
let mut worker = MainWorker::create(global_state, main_module.clone())?;
|
let mut worker = MainWorker::create(global_state, main_module.clone())?;
|
||||||
worker.preload_module(&main_module).await?;
|
worker.preload_module(&main_module).await?;
|
||||||
print_file_info(&worker, main_module.clone()).await
|
print_file_info(&worker, main_module.clone(), json).await
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn install_command(
|
async fn install_command(
|
||||||
|
@ -525,8 +565,7 @@ async fn doc_command(
|
||||||
};
|
};
|
||||||
|
|
||||||
if json {
|
if json {
|
||||||
let writer = std::io::BufWriter::new(std::io::stdout());
|
write_json_to_stdout(&doc_nodes)
|
||||||
serde_json::to_writer_pretty(writer, &doc_nodes).map_err(ErrBox::from)
|
|
||||||
} else {
|
} else {
|
||||||
let details = if let Some(filter) = maybe_filter {
|
let details = if let Some(filter) = maybe_filter {
|
||||||
let nodes =
|
let nodes =
|
||||||
|
@ -691,7 +730,9 @@ pub fn main() {
|
||||||
DenoSubcommand::Fmt { check, files } => {
|
DenoSubcommand::Fmt { check, files } => {
|
||||||
fmt::format(files, check).boxed_local()
|
fmt::format(files, check).boxed_local()
|
||||||
}
|
}
|
||||||
DenoSubcommand::Info { file } => info_command(flags, file).boxed_local(),
|
DenoSubcommand::Info { file, json } => {
|
||||||
|
info_command(flags, file, json).boxed_local()
|
||||||
|
}
|
||||||
DenoSubcommand::Install {
|
DenoSubcommand::Install {
|
||||||
module_url,
|
module_url,
|
||||||
args,
|
args,
|
||||||
|
|
25
cli/tests/055_info_file_json.out
Normal file
25
cli/tests/055_info_file_json.out
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
{
|
||||||
|
"local": "[WILDCARD]005_more_imports.ts",
|
||||||
|
"fileType": "TypeScript",
|
||||||
|
"compiled": "[WILDCARD]005_more_imports.ts.js",
|
||||||
|
"map": null,
|
||||||
|
"deps": [
|
||||||
|
"file://[WILDCARD]/005_more_imports.ts",
|
||||||
|
[
|
||||||
|
[
|
||||||
|
"file://[WILDCARD]/subdir/mod1.ts",
|
||||||
|
[
|
||||||
|
[
|
||||||
|
"file://[WILDCARD]/subdir/subdir2/mod2.ts",
|
||||||
|
[
|
||||||
|
[
|
||||||
|
"file://[WILDCARD]/subdir/print_hello.ts",
|
||||||
|
[]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
5
cli/tests/info_json.out
Normal file
5
cli/tests/info_json.out
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"denoDir": "[WILDCARD]",
|
||||||
|
"modulesCache": "[WILDCARD]deps",
|
||||||
|
"typescriptCache": "[WILDCARD]gen"
|
||||||
|
}
|
|
@ -1499,6 +1499,11 @@ itest!(_041_info_flag {
|
||||||
output: "041_info_flag.out",
|
output: "041_info_flag.out",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
itest!(info_json {
|
||||||
|
args: "info --json --unstable",
|
||||||
|
output: "info_json.out",
|
||||||
|
});
|
||||||
|
|
||||||
itest!(_042_dyn_import_evalcontext {
|
itest!(_042_dyn_import_evalcontext {
|
||||||
args: "run --quiet --allow-read --reload 042_dyn_import_evalcontext.ts",
|
args: "run --quiet --allow-read --reload 042_dyn_import_evalcontext.ts",
|
||||||
output: "042_dyn_import_evalcontext.ts.out",
|
output: "042_dyn_import_evalcontext.ts.out",
|
||||||
|
@ -1552,6 +1557,12 @@ itest!(_054_info_local_imports {
|
||||||
exit_code: 0,
|
exit_code: 0,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
itest!(_055_info_file_json {
|
||||||
|
args: "info --quiet --json --unstable 005_more_imports.ts",
|
||||||
|
output: "055_info_file_json.out",
|
||||||
|
exit_code: 0,
|
||||||
|
});
|
||||||
|
|
||||||
itest!(_056_make_temp_file_write_perm {
|
itest!(_056_make_temp_file_write_perm {
|
||||||
args:
|
args:
|
||||||
"run --quiet --allow-read --allow-write=./subdir/ 056_make_temp_file_write_perm.ts",
|
"run --quiet --allow-read --allow-write=./subdir/ 056_make_temp_file_write_perm.ts",
|
||||||
|
|
|
@ -36,6 +36,7 @@ pub use crate::es_isolate::EsIsolateState;
|
||||||
pub use crate::flags::v8_set_flags;
|
pub use crate::flags::v8_set_flags;
|
||||||
pub use crate::module_specifier::ModuleResolutionError;
|
pub use crate::module_specifier::ModuleResolutionError;
|
||||||
pub use crate::module_specifier::ModuleSpecifier;
|
pub use crate::module_specifier::ModuleSpecifier;
|
||||||
|
pub use crate::modules::Deps;
|
||||||
pub use crate::modules::ModuleId;
|
pub use crate::modules::ModuleId;
|
||||||
pub use crate::modules::ModuleLoadId;
|
pub use crate::modules::ModuleLoadId;
|
||||||
pub use crate::modules::ModuleLoader;
|
pub use crate::modules::ModuleLoader;
|
||||||
|
|
|
@ -484,20 +484,14 @@ impl Deps {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_json(&self) -> String {
|
pub fn to_json(&self) -> serde_json::Value {
|
||||||
let mut children = "[".to_string();
|
let children;
|
||||||
|
if let Some(deps) = &self.deps {
|
||||||
if let Some(ref deps) = self.deps {
|
children = deps.iter().map(|c| c.to_json()).collect();
|
||||||
for d in deps {
|
} else {
|
||||||
children.push_str(&d.to_json());
|
children = Vec::new()
|
||||||
if !d.is_last {
|
|
||||||
children.push_str(",");
|
|
||||||
}
|
}
|
||||||
}
|
serde_json::json!([&self.name, children])
|
||||||
}
|
|
||||||
children.push_str("]");
|
|
||||||
|
|
||||||
format!("[\"{}\",{}]", self.name, children)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1056,6 +1050,29 @@ mod tests {
|
||||||
assert!(modules.deps(&specifier).is_none());
|
assert!(modules.deps(&specifier).is_none());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn deps_to_json() {
|
||||||
|
fn dep(name: &str, deps: Option<Vec<Deps>>) -> Deps {
|
||||||
|
Deps {
|
||||||
|
name: name.to_string(),
|
||||||
|
deps,
|
||||||
|
prefix: "".to_string(),
|
||||||
|
is_last: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let deps = dep(
|
||||||
|
"a",
|
||||||
|
Some(vec![
|
||||||
|
dep("b", Some(vec![dep("b2", None)])),
|
||||||
|
dep("c", Some(vec![])),
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
serde_json::json!(["a", [["b", [["b2", []]]], ["c", []]]]),
|
||||||
|
deps.to_json()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/* TODO(bartlomieju): reenable
|
/* TODO(bartlomieju): reenable
|
||||||
#[test]
|
#[test]
|
||||||
fn deps() {
|
fn deps() {
|
||||||
|
@ -1076,22 +1093,5 @@ mod tests {
|
||||||
assert_eq!(bar_deps.deps, Some(vec![]));
|
assert_eq!(bar_deps.deps, Some(vec![]));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_deps_to_json() {
|
|
||||||
let mut modules = Modules::new();
|
|
||||||
modules.register(1, "foo");
|
|
||||||
modules.register(2, "bar");
|
|
||||||
modules.register(3, "baz");
|
|
||||||
modules.register(4, "zuh");
|
|
||||||
modules.add_child(1, "bar");
|
|
||||||
modules.add_child(1, "baz");
|
|
||||||
modules.add_child(3, "zuh");
|
|
||||||
let maybe_deps = modules.deps("foo");
|
|
||||||
assert!(maybe_deps.is_some());
|
|
||||||
assert_eq!(
|
|
||||||
"[\"foo\",[[\"bar\",[]],[\"baz\",[[\"zuh\",[]]]]]]",
|
|
||||||
maybe_deps.unwrap().to_json()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue