diff options
Diffstat (limited to 'cli/args')
-rw-r--r-- | cli/args/flags.rs | 91 | ||||
-rw-r--r-- | cli/args/mod.rs | 79 |
2 files changed, 130 insertions, 40 deletions
diff --git a/cli/args/flags.rs b/cli/args/flags.rs index 9650b9612..236352f24 100644 --- a/cli/args/flags.rs +++ b/cli/args/flags.rs @@ -124,13 +124,11 @@ pub struct DocFlags { pub struct EvalFlags { pub print: bool, pub code: String, - pub ext: String, } #[derive(Clone, Debug, Eq, PartialEq)] pub struct FmtFlags { pub check: bool, - pub ext: String, pub files: FileFlags, pub use_tabs: Option<bool>, pub line_width: Option<NonZeroU32>, @@ -335,6 +333,7 @@ pub struct Flags { pub node_modules_dir: Option<bool>, pub coverage_dir: Option<String>, pub enable_testing_features: bool, + pub ext: Option<String>, pub ignore: Vec<PathBuf>, pub import_map_path: Option<String>, pub inspect_brk: Option<SocketAddr>, @@ -837,6 +836,7 @@ fn bundle_subcommand<'a>() -> Command<'a> { ) .arg(watch_arg(false)) .arg(no_clear_screen_arg()) + .arg(executable_ext_arg()) .about("Bundle module and dependencies into single file") .long_about( "Output a single JavaScript file with all dependencies. @@ -943,6 +943,7 @@ fn compile_subcommand<'a>() -> Command<'a> { "aarch64-apple-darwin", ]), ) + .arg(executable_ext_arg()) .about("UNSTABLE: Compile the script into a self contained executable") .long_about( "UNSTABLE: Compiles the given script into a self contained executable. @@ -1164,22 +1165,16 @@ This command has implicit access to all permissions (--allow-all).", .arg( // TODO(@satyarohith): remove this argument in 2.0. Arg::new("ts") + .conflicts_with("ext") .long("ts") .short('T') - .help("Treat eval input as TypeScript") + .help("deprecated: Treat eval input as TypeScript") .takes_value(false) .multiple_occurrences(false) .multiple_values(false) .hide(true), ) - .arg( - Arg::new("ext") - .long("ext") - .help("Set standard input (stdin) content type") - .takes_value(true) - .default_value("js") - .possible_values(["ts", "tsx", "js", "jsx"]), - ) + .arg(executable_ext_arg()) .arg( Arg::new("print") .long("print") @@ -1232,8 +1227,9 @@ Ignore formatting a file by adding an ignore comment at the top of the file: .arg( Arg::new("ext") .long("ext") - .help("Set standard input (stdin) content type") + .help("Set content type of the supplied file") .takes_value(true) + // prefer using ts for formatting instead of js because ts works in more scenarios .default_value("ts") .possible_values(["ts", "tsx", "js", "jsx", "md", "json", "jsonc"]), ) @@ -1615,6 +1611,7 @@ fn run_subcommand<'a>() -> Command<'a> { .conflicts_with("inspect-brk"), ) .arg(no_clear_screen_arg()) + .arg(executable_ext_arg()) .trailing_var_arg(true) .arg(script_arg().required(true)) .about("Run a JavaScript or TypeScript program") @@ -2168,6 +2165,18 @@ fn cached_only_arg<'a>() -> Arg<'a> { .help("Require that remote dependencies are already cached") } +/// Used for subcommands that operate on executable scripts only. +/// `deno fmt` has its own `--ext` arg because its possible values differ. +/// If --ext is not provided and the script doesn't have a file extension, +/// deno_graph::parse_module() defaults to js. +fn executable_ext_arg<'a>() -> Arg<'a> { + Arg::new("ext") + .long("ext") + .help("Set content type of the supplied file") + .takes_value(true) + .possible_values(["ts", "tsx", "js", "jsx"]) +} + fn location_arg<'a>() -> Arg<'a> { Arg::new("location") .long("location") @@ -2456,6 +2465,7 @@ fn bundle_parse(flags: &mut Flags, matches: &clap::ArgMatches) { }; watch_arg_parse(flags, matches, false); + ext_arg_parse(flags, matches); flags.subcommand = DenoSubcommand::Bundle(BundleFlags { source_file, @@ -2505,6 +2515,7 @@ fn compile_parse(flags: &mut Flags, matches: &clap::ArgMatches) { Some(f) => f.map(String::from).collect(), None => vec![], }; + ext_arg_parse(flags, matches); flags.subcommand = DenoSubcommand::Compile(CompileFlags { source_file, @@ -2614,13 +2625,22 @@ fn eval_parse(flags: &mut Flags, matches: &clap::ArgMatches) { flags.allow_write = Some(vec![]); flags.allow_ffi = Some(vec![]); flags.allow_hrtime = true; + + ext_arg_parse(flags, matches); + // TODO(@satyarohith): remove this flag in 2.0. let as_typescript = matches.is_present("ts"); - let ext = if as_typescript { - "ts".to_string() - } else { - matches.value_of("ext").unwrap().to_string() - }; + + if as_typescript { + eprintln!( + "{}", + crate::colors::yellow( + "Warning: --ts/-T flag is deprecated. Use --ext=ts instead." + ), + ); + + flags.ext = Some("ts".to_string()); + } let print = matches.is_present("print"); let mut code: Vec<String> = matches @@ -2634,12 +2654,13 @@ fn eval_parse(flags: &mut Flags, matches: &clap::ArgMatches) { for v in code_args { flags.argv.push(v); } - flags.subcommand = DenoSubcommand::Eval(EvalFlags { print, code, ext }); + flags.subcommand = DenoSubcommand::Eval(EvalFlags { print, code }); } fn fmt_parse(flags: &mut Flags, matches: &clap::ArgMatches) { config_args_parse(flags, matches); watch_arg_parse(flags, matches, false); + ext_arg_parse(flags, matches); let include = match matches.values_of("files") { Some(f) => f.map(PathBuf::from).collect(), @@ -2649,7 +2670,6 @@ fn fmt_parse(flags: &mut Flags, matches: &clap::ArgMatches) { Some(f) => f.map(PathBuf::from).collect(), None => vec![], }; - let ext = matches.value_of("ext").unwrap().to_string(); let use_tabs = optional_bool_parse(matches, "use-tabs"); let line_width = if matches.is_present("line-width") { @@ -2674,7 +2694,6 @@ fn fmt_parse(flags: &mut Flags, matches: &clap::ArgMatches) { flags.subcommand = DenoSubcommand::Fmt(FmtFlags { check: matches.is_present("check"), - ext, files: FileFlags { include, ignore }, use_tabs, line_width, @@ -2827,6 +2846,8 @@ fn run_parse(flags: &mut Flags, matches: &clap::ArgMatches) { flags.argv.push(v); } + ext_arg_parse(flags, matches); + watch_arg_parse(flags, matches, true); flags.subcommand = DenoSubcommand::Run(RunFlags { script }); } @@ -3228,6 +3249,10 @@ fn cached_only_arg_parse(flags: &mut Flags, matches: &ArgMatches) { } } +fn ext_arg_parse(flags: &mut Flags, matches: &clap::ArgMatches) { + flags.ext = matches.value_of("ext").map(String::from); +} + fn location_arg_parse(flags: &mut Flags, matches: &clap::ArgMatches) { flags.location = matches .value_of("location") @@ -3694,7 +3719,6 @@ mod tests { Flags { subcommand: DenoSubcommand::Fmt(FmtFlags { check: false, - ext: "ts".to_string(), files: FileFlags { include: vec![ PathBuf::from("script_1.ts"), @@ -3709,6 +3733,7 @@ mod tests { prose_wrap: None, no_semicolons: None, }), + ext: Some("ts".to_string()), ..Flags::default() } ); @@ -3719,7 +3744,6 @@ mod tests { Flags { subcommand: DenoSubcommand::Fmt(FmtFlags { check: true, - ext: "ts".to_string(), files: FileFlags { include: vec![], ignore: vec![], @@ -3731,6 +3755,7 @@ mod tests { prose_wrap: None, no_semicolons: None, }), + ext: Some("ts".to_string()), ..Flags::default() } ); @@ -3741,7 +3766,6 @@ mod tests { Flags { subcommand: DenoSubcommand::Fmt(FmtFlags { check: false, - ext: "ts".to_string(), files: FileFlags { include: vec![], ignore: vec![], @@ -3753,6 +3777,7 @@ mod tests { prose_wrap: None, no_semicolons: None, }), + ext: Some("ts".to_string()), ..Flags::default() } ); @@ -3763,7 +3788,6 @@ mod tests { Flags { subcommand: DenoSubcommand::Fmt(FmtFlags { check: false, - ext: "ts".to_string(), files: FileFlags { include: vec![], ignore: vec![], @@ -3775,6 +3799,7 @@ mod tests { prose_wrap: None, no_semicolons: None, }), + ext: Some("ts".to_string()), watch: Some(vec![]), ..Flags::default() } @@ -3787,7 +3812,6 @@ mod tests { Flags { subcommand: DenoSubcommand::Fmt(FmtFlags { check: false, - ext: "ts".to_string(), files: FileFlags { include: vec![], ignore: vec![], @@ -3799,6 +3823,7 @@ mod tests { prose_wrap: None, no_semicolons: None, }), + ext: Some("ts".to_string()), watch: Some(vec![]), no_clear_screen: true, ..Flags::default() @@ -3818,7 +3843,6 @@ mod tests { Flags { subcommand: DenoSubcommand::Fmt(FmtFlags { check: true, - ext: "ts".to_string(), files: FileFlags { include: vec![PathBuf::from("foo.ts")], ignore: vec![PathBuf::from("bar.js")], @@ -3830,6 +3854,7 @@ mod tests { prose_wrap: None, no_semicolons: None, }), + ext: Some("ts".to_string()), watch: Some(vec![]), ..Flags::default() } @@ -3841,7 +3866,6 @@ mod tests { Flags { subcommand: DenoSubcommand::Fmt(FmtFlags { check: false, - ext: "ts".to_string(), files: FileFlags { include: vec![], ignore: vec![], @@ -3853,6 +3877,7 @@ mod tests { prose_wrap: None, no_semicolons: None, }), + ext: Some("ts".to_string()), config_flag: ConfigFlag::Path("deno.jsonc".to_string()), ..Flags::default() } @@ -3871,7 +3896,6 @@ mod tests { Flags { subcommand: DenoSubcommand::Fmt(FmtFlags { check: false, - ext: "ts".to_string(), files: FileFlags { include: vec![PathBuf::from("foo.ts")], ignore: vec![], @@ -3884,6 +3908,7 @@ mod tests { no_semicolons: None, }), config_flag: ConfigFlag::Path("deno.jsonc".to_string()), + ext: Some("ts".to_string()), watch: Some(vec![]), ..Flags::default() } @@ -3907,7 +3932,6 @@ mod tests { Flags { subcommand: DenoSubcommand::Fmt(FmtFlags { check: false, - ext: "ts".to_string(), files: FileFlags { include: vec![], ignore: vec![], @@ -3919,6 +3943,7 @@ mod tests { prose_wrap: Some("never".to_string()), no_semicolons: Some(true), }), + ext: Some("ts".to_string()), ..Flags::default() } ); @@ -3936,7 +3961,6 @@ mod tests { Flags { subcommand: DenoSubcommand::Fmt(FmtFlags { check: false, - ext: "ts".to_string(), files: FileFlags { include: vec![], ignore: vec![], @@ -3948,6 +3972,7 @@ mod tests { prose_wrap: None, no_semicolons: Some(false), }), + ext: Some("ts".to_string()), ..Flags::default() } ); @@ -4362,7 +4387,6 @@ mod tests { subcommand: DenoSubcommand::Eval(EvalFlags { print: false, code: "'console.log(\"hello\")'".to_string(), - ext: "js".to_string(), }), allow_net: Some(vec![]), allow_env: Some(vec![]), @@ -4386,7 +4410,6 @@ mod tests { subcommand: DenoSubcommand::Eval(EvalFlags { print: true, code: "1+2".to_string(), - ext: "js".to_string(), }), allow_net: Some(vec![]), allow_env: Some(vec![]), @@ -4411,7 +4434,6 @@ mod tests { subcommand: DenoSubcommand::Eval(EvalFlags { print: false, code: "'console.log(\"hello\")'".to_string(), - ext: "ts".to_string(), }), allow_net: Some(vec![]), allow_env: Some(vec![]), @@ -4421,6 +4443,7 @@ mod tests { allow_write: Some(vec![]), allow_ffi: Some(vec![]), allow_hrtime: true, + ext: Some("ts".to_string()), ..Flags::default() } ); @@ -4436,7 +4459,6 @@ mod tests { subcommand: DenoSubcommand::Eval(EvalFlags { print: false, code: "42".to_string(), - ext: "js".to_string(), }), import_map_path: Some("import_map.json".to_string()), no_remote: true, @@ -4479,7 +4501,6 @@ mod tests { subcommand: DenoSubcommand::Eval(EvalFlags { print: false, code: "console.log(Deno.args)".to_string(), - ext: "js".to_string(), }), argv: svec!["arg1", "arg2"], allow_net: Some(vec![]), diff --git a/cli/args/mod.rs b/cli/args/mod.rs index 848f50eb4..fb44c0a8f 100644 --- a/cli/args/mod.rs +++ b/cli/args/mod.rs @@ -10,6 +10,8 @@ pub mod package_json; pub use self::import_map::resolve_import_map_from_specifier; use self::package_json::PackageJsonDeps; use ::import_map::ImportMap; +use deno_core::resolve_url_or_path; +use deno_graph::npm::NpmPackageReqReference; use indexmap::IndexMap; use crate::npm::NpmRegistryApi; @@ -50,6 +52,7 @@ use deno_runtime::deno_tls::webpki_roots; use deno_runtime::inspector_server::InspectorServer; use deno_runtime::permissions::PermissionsOptions; use once_cell::sync::Lazy; +use std::collections::HashMap; use std::env; use std::io::BufReader; use std::io::Cursor; @@ -139,7 +142,6 @@ impl BenchOptions { pub struct FmtOptions { pub is_stdin: bool, pub check: bool, - pub ext: String, pub options: FmtOptionsConfig, pub files: FilesConfig, } @@ -166,10 +168,6 @@ impl FmtOptions { Ok(Self { is_stdin, check: maybe_fmt_flags.as_ref().map(|f| f.check).unwrap_or(false), - ext: maybe_fmt_flags - .as_ref() - .map(|f| f.ext.to_string()) - .unwrap_or_else(|| "ts".to_string()), options: resolve_fmt_options( maybe_fmt_flags.as_ref(), maybe_config_options, @@ -675,6 +673,73 @@ impl CliOptions { .map(Some) } + pub fn resolve_main_module(&self) -> Result<ModuleSpecifier, AnyError> { + match &self.flags.subcommand { + DenoSubcommand::Bundle(bundle_flags) => { + resolve_url_or_path(&bundle_flags.source_file, self.initial_cwd()) + .map_err(AnyError::from) + } + DenoSubcommand::Compile(compile_flags) => { + resolve_url_or_path(&compile_flags.source_file, self.initial_cwd()) + .map_err(AnyError::from) + } + DenoSubcommand::Eval(_) => { + resolve_url_or_path("./$deno$eval", self.initial_cwd()) + .map_err(AnyError::from) + } + DenoSubcommand::Repl(_) => { + resolve_url_or_path("./$deno$repl.ts", self.initial_cwd()) + .map_err(AnyError::from) + } + DenoSubcommand::Run(run_flags) => { + if run_flags.is_stdin() { + std::env::current_dir() + .context("Unable to get CWD") + .and_then(|cwd| { + resolve_url_or_path("./$deno$stdin", &cwd).map_err(AnyError::from) + }) + } else if self.flags.watch.is_some() { + resolve_url_or_path(&run_flags.script, self.initial_cwd()) + .map_err(AnyError::from) + } else if NpmPackageReqReference::from_str(&run_flags.script).is_ok() { + ModuleSpecifier::parse(&run_flags.script).map_err(AnyError::from) + } else { + resolve_url_or_path(&run_flags.script, self.initial_cwd()) + .map_err(AnyError::from) + } + } + _ => { + bail!("No main module.") + } + } + } + + pub fn resolve_file_header_overrides( + &self, + ) -> HashMap<ModuleSpecifier, HashMap<String, String>> { + let maybe_main_specifier = self.resolve_main_module().ok(); + // TODO(Cre3per): This mapping moved to deno_ast with https://github.com/denoland/deno_ast/issues/133 and should be available in deno_ast >= 0.25.0 via `MediaType::from_path(...).as_media_type()` + let maybe_content_type = + self.flags.ext.as_ref().and_then(|el| match el.as_str() { + "ts" => Some("text/typescript"), + "tsx" => Some("text/tsx"), + "js" => Some("text/javascript"), + "jsx" => Some("text/jsx"), + _ => None, + }); + + if let (Some(main_specifier), Some(content_type)) = + (maybe_main_specifier, maybe_content_type) + { + HashMap::from([( + main_specifier, + HashMap::from([("content-type".to_string(), content_type.to_string())]), + )]) + } else { + HashMap::default() + } + } + pub async fn resolve_npm_resolution_snapshot( &self, api: &NpmRegistryApi, @@ -936,6 +1001,10 @@ impl CliOptions { self.flags.enable_testing_features } + pub fn ext_flag(&self) -> &Option<String> { + &self.flags.ext + } + /// If the --inspect or --inspect-brk flags are used. pub fn is_inspecting(&self) -> bool { self.flags.inspect.is_some() |