summaryrefslogtreecommitdiff
path: root/cli/args
diff options
context:
space:
mode:
authorGeert-Jan Zwiers <geertjanzwiers@protonmail.com>2023-01-07 21:22:09 +0100
committerGitHub <noreply@github.com>2023-01-07 15:22:09 -0500
commit84ef26ac9b5f0e1199d77837cd97cb203baa8729 (patch)
treeeb8f3422d397724d004dba0e9667b3f6c2b49a57 /cli/args
parentfac64478157ee563b185edb5734688e4523df3a1 (diff)
refactor(cli/tools): move flag and config logic to CliOptions (#17008)
Co-authored-by: David Sherret <dsherret@gmail.com>
Diffstat (limited to 'cli/args')
-rw-r--r--cli/args/config_file.rs72
-rw-r--r--cli/args/flags.rs363
-rw-r--r--cli/args/mod.rs368
3 files changed, 604 insertions, 199 deletions
diff --git a/cli/args/config_file.rs b/cli/args/config_file.rs
index 0c0e5d2fa..47f8e9daa 100644
--- a/cli/args/config_file.rs
+++ b/cli/args/config_file.rs
@@ -295,43 +295,45 @@ impl SerializedFilesConfig {
include: self
.include
.into_iter()
- .map(|p| config_dir.join(&p))
- .collect::<Result<Vec<ModuleSpecifier>, _>>()?,
+ .map(|p| {
+ let url = config_dir.join(&p)?;
+ specifier_to_file_path(&url)
+ })
+ .collect::<Result<Vec<_>, _>>()?,
exclude: self
.exclude
.into_iter()
- .map(|p| config_dir.join(&p))
- .collect::<Result<Vec<ModuleSpecifier>, _>>()?,
+ .map(|p| {
+ let url = config_dir.join(&p)?;
+ specifier_to_file_path(&url)
+ })
+ .collect::<Result<Vec<_>, _>>()?,
})
}
}
-#[derive(Clone, Debug, Default)]
+#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct FilesConfig {
- pub include: Vec<ModuleSpecifier>,
- pub exclude: Vec<ModuleSpecifier>,
+ pub include: Vec<PathBuf>,
+ pub exclude: Vec<PathBuf>,
}
impl FilesConfig {
/// Gets if the provided specifier is allowed based on the includes
/// and excludes in the configuration file.
pub fn matches_specifier(&self, specifier: &ModuleSpecifier) -> bool {
+ let file_path = match specifier_to_file_path(specifier) {
+ Ok(file_path) => file_path,
+ Err(_) => return false,
+ };
// Skip files which is in the exclude list.
- let specifier_text = specifier.as_str();
- if self
- .exclude
- .iter()
- .any(|i| specifier_text.starts_with(i.as_str()))
- {
+ if self.exclude.iter().any(|i| file_path.starts_with(i)) {
return false;
}
// Ignore files not in the include list if it's not empty.
self.include.is_empty()
- || self
- .include
- .iter()
- .any(|i| specifier_text.starts_with(i.as_str()))
+ || self.include.iter().any(|i| file_path.starts_with(i))
}
}
@@ -663,6 +665,16 @@ impl ConfigFile {
self.json.import_map.clone()
}
+ pub fn to_fmt_config(&self) -> Result<Option<FmtConfig>, AnyError> {
+ if let Some(config) = self.json.fmt.clone() {
+ let fmt_config: SerializedFmtConfig = serde_json::from_value(config)
+ .context("Failed to parse \"fmt\" configuration")?;
+ Ok(Some(fmt_config.into_resolved(&self.specifier)?))
+ } else {
+ Ok(None)
+ }
+ }
+
pub fn to_lint_config(&self) -> Result<Option<LintConfig>, AnyError> {
if let Some(config) = self.json.lint.clone() {
let lint_config: SerializedLintConfig = serde_json::from_value(config)
@@ -767,16 +779,6 @@ impl ConfigFile {
})
}
- pub fn to_fmt_config(&self) -> Result<Option<FmtConfig>, AnyError> {
- if let Some(config) = self.json.fmt.clone() {
- let fmt_config: SerializedFmtConfig = serde_json::from_value(config)
- .context("Failed to parse \"fmt\" configuration")?;
- Ok(Some(fmt_config.into_resolved(&self.specifier)?))
- } else {
- Ok(None)
- }
- }
-
pub fn resolve_tasks_config(
&self,
) -> Result<BTreeMap<String, String>, AnyError> {
@@ -1068,13 +1070,10 @@ mod tests {
.to_lint_config()
.expect("error parsing lint object")
.expect("lint object should be defined");
- assert_eq!(
- lint_config.files.include,
- vec![config_dir.join("src/").unwrap()]
- );
+ assert_eq!(lint_config.files.include, vec![PathBuf::from("/deno/src/")]);
assert_eq!(
lint_config.files.exclude,
- vec![config_dir.join("src/testdata/").unwrap()]
+ vec![PathBuf::from("/deno/src/testdata/")]
);
assert_eq!(
lint_config.rules.include,
@@ -1090,13 +1089,10 @@ mod tests {
.to_fmt_config()
.expect("error parsing fmt object")
.expect("fmt object should be defined");
- assert_eq!(
- fmt_config.files.include,
- vec![config_dir.join("src/").unwrap()]
- );
+ assert_eq!(fmt_config.files.include, vec![PathBuf::from("/deno/src/")]);
assert_eq!(
fmt_config.files.exclude,
- vec![config_dir.join("src/testdata/").unwrap()]
+ vec![PathBuf::from("/deno/src/testdata/")],
);
assert_eq!(fmt_config.options.use_tabs, Some(true));
assert_eq!(fmt_config.options.line_width, Some(80));
@@ -1190,6 +1186,8 @@ mod tests {
let expected_exclude = ModuleSpecifier::from_file_path(
testdata.join("fmt/with_config/subdir/b.ts"),
)
+ .unwrap()
+ .to_file_path()
.unwrap();
assert_eq!(fmt_config.files.exclude, vec![expected_exclude]);
diff --git a/cli/args/flags.rs b/cli/args/flags.rs
index bae6bb0d5..b5753c00b 100644
--- a/cli/args/flags.rs
+++ b/cli/args/flags.rs
@@ -6,8 +6,6 @@ use clap::ColorChoice;
use clap::Command;
use clap::ValueHint;
use deno_core::error::AnyError;
-use deno_core::serde::Deserialize;
-use deno_core::serde::Serialize;
use deno_core::url::Url;
use deno_runtime::permissions::parse_sys_kind;
use log::debug;
@@ -46,30 +44,35 @@ static SHORT_VERSION: Lazy<String> = Lazy::new(|| {
.to_string()
});
-#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
-pub struct BenchFlags {
+#[derive(Clone, Debug, Default, Eq, PartialEq)]
+pub struct FileFlags {
pub ignore: Vec<PathBuf>,
- pub include: Option<Vec<String>>,
+ pub include: Vec<PathBuf>,
+}
+
+#[derive(Clone, Debug, Default, Eq, PartialEq)]
+pub struct BenchFlags {
+ pub files: FileFlags,
pub filter: Option<String>,
}
-#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
+#[derive(Clone, Debug, Eq, PartialEq)]
pub struct BundleFlags {
pub source_file: String,
pub out_file: Option<PathBuf>,
}
-#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
+#[derive(Clone, Debug, Eq, PartialEq)]
pub struct CacheFlags {
pub files: Vec<String>,
}
-#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
+#[derive(Clone, Debug, Eq, PartialEq)]
pub struct CheckFlags {
pub files: Vec<String>,
}
-#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
+#[derive(Clone, Debug, Eq, PartialEq)]
pub struct CompileFlags {
pub source_file: String,
pub output: Option<PathBuf>,
@@ -77,12 +80,12 @@ pub struct CompileFlags {
pub target: Option<String>,
}
-#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
+#[derive(Clone, Debug, Eq, PartialEq)]
pub struct CompletionsFlags {
pub buf: Box<[u8]>,
}
-#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
+#[derive(Clone, Debug, Eq, PartialEq)]
pub struct CoverageFlags {
pub files: Vec<PathBuf>,
pub output: Option<PathBuf>,
@@ -92,7 +95,7 @@ pub struct CoverageFlags {
pub lcov: bool,
}
-#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
+#[derive(Clone, Debug, Eq, PartialEq)]
pub struct DocFlags {
pub private: bool,
pub json: bool,
@@ -100,19 +103,18 @@ pub struct DocFlags {
pub filter: Option<String>,
}
-#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
+#[derive(Clone, Debug, Eq, PartialEq)]
pub struct EvalFlags {
pub print: bool,
pub code: String,
pub ext: String,
}
-#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
+#[derive(Clone, Debug, Eq, PartialEq)]
pub struct FmtFlags {
pub check: bool,
- pub files: Vec<PathBuf>,
- pub ignore: Vec<PathBuf>,
pub ext: String,
+ pub files: FileFlags,
pub use_tabs: Option<bool>,
pub line_width: Option<NonZeroU32>,
pub indent_width: Option<NonZeroU8>,
@@ -120,18 +122,18 @@ pub struct FmtFlags {
pub prose_wrap: Option<String>,
}
-#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
+#[derive(Clone, Debug, Eq, PartialEq)]
pub struct InitFlags {
pub dir: Option<String>,
}
-#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
+#[derive(Clone, Debug, Eq, PartialEq)]
pub struct InfoFlags {
pub json: bool,
pub file: Option<String>,
}
-#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
+#[derive(Clone, Debug, Eq, PartialEq)]
pub struct InstallFlags {
pub module_url: String,
pub args: Vec<String>,
@@ -140,16 +142,15 @@ pub struct InstallFlags {
pub force: bool,
}
-#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
+#[derive(Clone, Debug, Eq, PartialEq)]
pub struct UninstallFlags {
pub name: String,
pub root: Option<PathBuf>,
}
-#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
+#[derive(Clone, Debug, Eq, PartialEq)]
pub struct LintFlags {
- pub files: Vec<PathBuf>,
- pub ignore: Vec<PathBuf>,
+ pub files: FileFlags,
pub rules: bool,
pub maybe_rules_tags: Option<Vec<String>>,
pub maybe_rules_include: Option<Vec<String>>,
@@ -158,14 +159,14 @@ pub struct LintFlags {
pub compact: bool,
}
-#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
+#[derive(Clone, Debug, Eq, PartialEq)]
pub struct ReplFlags {
pub eval_files: Option<Vec<String>>,
pub eval: Option<String>,
pub is_default_command: bool,
}
-#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
+#[derive(Clone, Debug, Eq, PartialEq)]
pub struct RunFlags {
pub script: String,
}
@@ -176,27 +177,26 @@ impl RunFlags {
}
}
-#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
+#[derive(Clone, Debug, Eq, PartialEq)]
pub struct TaskFlags {
pub cwd: Option<String>,
pub task: String,
}
-#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
+#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct TestFlags {
- pub ignore: Vec<PathBuf>,
pub doc: bool,
pub no_run: bool,
pub fail_fast: Option<NonZeroUsize>,
+ pub files: FileFlags,
pub allow_none: bool,
- pub include: Vec<String>,
pub filter: Option<String>,
pub shuffle: Option<u64>,
- pub concurrent_jobs: NonZeroUsize,
+ pub concurrent_jobs: Option<NonZeroUsize>,
pub trace_ops: bool,
}
-#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
+#[derive(Clone, Debug, Eq, PartialEq)]
pub struct UpgradeFlags {
pub dry_run: bool,
pub force: bool,
@@ -205,14 +205,14 @@ pub struct UpgradeFlags {
pub output: Option<PathBuf>,
}
-#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
+#[derive(Clone, Debug, Eq, PartialEq)]
pub struct VendorFlags {
pub specifiers: Vec<String>,
pub output_path: Option<PathBuf>,
pub force: bool,
}
-#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
+#[derive(Clone, Debug, Eq, PartialEq)]
pub enum DenoSubcommand {
Bench(BenchFlags),
Bundle(BundleFlags),
@@ -455,9 +455,9 @@ impl Flags {
pub fn config_path_args(&self) -> Option<Vec<PathBuf>> {
use DenoSubcommand::*;
if let Fmt(FmtFlags { files, .. }) = &self.subcommand {
- Some(files.clone())
+ Some(files.include.clone())
} else if let Lint(LintFlags { files, .. }) = &self.subcommand {
- Some(files.clone())
+ Some(files.include.clone())
} else if let Run(RunFlags { script }) = &self.subcommand {
if let Ok(module_specifier) = deno_core::resolve_url_or_path(script) {
if module_specifier.scheme() == "file"
@@ -2298,20 +2298,19 @@ fn bench_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
}
let include = if matches.is_present("files") {
- let files: Vec<String> = matches
+ let files = matches
.values_of("files")
.unwrap()
- .map(String::from)
+ .map(PathBuf::from)
.collect();
- Some(files)
+ files
} else {
- None
+ Vec::new()
};
watch_arg_parse(flags, matches, false);
flags.subcommand = DenoSubcommand::Bench(BenchFlags {
- include,
- ignore,
+ files: FileFlags { include, ignore },
filter,
});
}
@@ -2493,7 +2492,7 @@ fn fmt_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
config_args_parse(flags, matches);
watch_arg_parse(flags, matches, false);
- let files = match matches.values_of("files") {
+ let include = match matches.values_of("files") {
Some(f) => f.map(PathBuf::from).collect(),
None => vec![],
};
@@ -2544,8 +2543,7 @@ fn fmt_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
flags.subcommand = DenoSubcommand::Fmt(FmtFlags {
check: matches.is_present("check"),
ext,
- files,
- ignore,
+ files: FileFlags { include, ignore },
use_tabs,
line_width,
indent_width,
@@ -2647,12 +2645,15 @@ fn lint_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
let json = matches.is_present("json");
let compact = matches.is_present("compact");
flags.subcommand = DenoSubcommand::Lint(LintFlags {
- files,
+ files: FileFlags {
+ include: files,
+ ignore,
+ },
rules,
maybe_rules_tags,
maybe_rules_include,
maybe_rules_exclude,
- ignore,
+
json,
compact,
});
@@ -2811,12 +2812,9 @@ fn test_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
let concurrent_jobs = if matches.is_present("parallel") {
if let Ok(value) = env::var("DENO_JOBS") {
- value
- .parse::<NonZeroUsize>()
- .unwrap_or(NonZeroUsize::new(1).unwrap())
+ value.parse::<NonZeroUsize>().ok()
} else {
- std::thread::available_parallelism()
- .unwrap_or(NonZeroUsize::new(1).unwrap())
+ std::thread::available_parallelism().ok()
}
} else if matches.is_present("jobs") {
// We can't change this to use the log crate because its not configured
@@ -2828,20 +2826,19 @@ fn test_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
crate::colors::yellow("Warning: --jobs flag is deprecated. Use the --parallel flag with possibly the 'DENO_JOBS' environment variable."),
);
if let Some(value) = matches.value_of("jobs") {
- value.parse().unwrap()
+ Some(value.parse().unwrap())
} else {
- std::thread::available_parallelism()
- .unwrap_or(NonZeroUsize::new(1).unwrap())
+ std::thread::available_parallelism().ok()
}
} else {
- NonZeroUsize::new(1).unwrap()
+ None
};
- let include: Vec<String> = if matches.is_present("files") {
+ let include = if matches.is_present("files") {
matches
.values_of("files")
.unwrap()
- .map(String::from)
+ .map(PathBuf::from)
.collect::<Vec<_>>()
} else {
Vec::new()
@@ -2853,8 +2850,7 @@ fn test_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
no_run,
doc,
fail_fast,
- include,
- ignore,
+ files: FileFlags { include, ignore },
filter,
shuffle,
allow_none,
@@ -3267,6 +3263,7 @@ mod tests {
fn global_flags() {
#[rustfmt::skip]
let r = flags_from_vec(svec!["deno", "--unstable", "--log-level", "debug", "--quiet", "run", "script.ts"]);
+
let flags = r.unwrap();
assert_eq!(
flags,
@@ -3562,13 +3559,15 @@ mod tests {
r.unwrap(),
Flags {
subcommand: DenoSubcommand::Fmt(FmtFlags {
- ignore: vec![],
check: false,
- files: vec![
- PathBuf::from("script_1.ts"),
- PathBuf::from("script_2.ts")
- ],
ext: "ts".to_string(),
+ files: FileFlags {
+ include: vec![
+ PathBuf::from("script_1.ts"),
+ PathBuf::from("script_2.ts")
+ ],
+ ignore: vec![],
+ },
use_tabs: None,
line_width: None,
indent_width: None,
@@ -3584,10 +3583,12 @@ mod tests {
r.unwrap(),
Flags {
subcommand: DenoSubcommand::Fmt(FmtFlags {
- ignore: vec![],
check: true,
- files: vec![],
ext: "ts".to_string(),
+ files: FileFlags {
+ include: vec![],
+ ignore: vec![],
+ },
use_tabs: None,
line_width: None,
indent_width: None,
@@ -3603,10 +3604,12 @@ mod tests {
r.unwrap(),
Flags {
subcommand: DenoSubcommand::Fmt(FmtFlags {
- ignore: vec![],
check: false,
- files: vec![],
ext: "ts".to_string(),
+ files: FileFlags {
+ include: vec![],
+ ignore: vec![],
+ },
use_tabs: None,
line_width: None,
indent_width: None,
@@ -3622,10 +3625,12 @@ mod tests {
r.unwrap(),
Flags {
subcommand: DenoSubcommand::Fmt(FmtFlags {
- ignore: vec![],
check: false,
- files: vec![],
ext: "ts".to_string(),
+ files: FileFlags {
+ include: vec![],
+ ignore: vec![],
+ },
use_tabs: None,
line_width: None,
indent_width: None,
@@ -3643,10 +3648,12 @@ mod tests {
r.unwrap(),
Flags {
subcommand: DenoSubcommand::Fmt(FmtFlags {
- ignore: vec![],
check: false,
- files: vec![],
ext: "ts".to_string(),
+ files: FileFlags {
+ include: vec![],
+ ignore: vec![],
+ },
use_tabs: None,
line_width: None,
indent_width: None,
@@ -3671,10 +3678,12 @@ mod tests {
r.unwrap(),
Flags {
subcommand: DenoSubcommand::Fmt(FmtFlags {
- ignore: vec![PathBuf::from("bar.js")],
check: true,
- files: vec![PathBuf::from("foo.ts")],
ext: "ts".to_string(),
+ files: FileFlags {
+ include: vec![PathBuf::from("foo.ts")],
+ ignore: vec![PathBuf::from("bar.js")],
+ },
use_tabs: None,
line_width: None,
indent_width: None,
@@ -3691,10 +3700,12 @@ mod tests {
r.unwrap(),
Flags {
subcommand: DenoSubcommand::Fmt(FmtFlags {
- ignore: vec![],
check: false,
- files: vec![],
ext: "ts".to_string(),
+ files: FileFlags {
+ include: vec![],
+ ignore: vec![],
+ },
use_tabs: None,
line_width: None,
indent_width: None,
@@ -3718,10 +3729,12 @@ mod tests {
r.unwrap(),
Flags {
subcommand: DenoSubcommand::Fmt(FmtFlags {
- ignore: vec![],
check: false,
- files: vec![PathBuf::from("foo.ts")],
ext: "ts".to_string(),
+ files: FileFlags {
+ include: vec![PathBuf::from("foo.ts")],
+ ignore: vec![],
+ },
use_tabs: None,
line_width: None,
indent_width: None,
@@ -3750,10 +3763,12 @@ mod tests {
r.unwrap(),
Flags {
subcommand: DenoSubcommand::Fmt(FmtFlags {
- ignore: vec![],
check: false,
- files: vec![],
ext: "ts".to_string(),
+ files: FileFlags {
+ include: vec![],
+ ignore: vec![],
+ },
use_tabs: Some(true),
line_width: Some(NonZeroU32::new(60).unwrap()),
indent_width: Some(NonZeroU8::new(4).unwrap()),
@@ -3772,17 +3787,19 @@ mod tests {
r.unwrap(),
Flags {
subcommand: DenoSubcommand::Lint(LintFlags {
- files: vec![
- PathBuf::from("script_1.ts"),
- PathBuf::from("script_2.ts")
- ],
+ files: FileFlags {
+ include: vec![
+ PathBuf::from("script_1.ts"),
+ PathBuf::from("script_2.ts")
+ ],
+ ignore: vec![],
+ },
rules: false,
maybe_rules_tags: None,
maybe_rules_include: None,
maybe_rules_exclude: None,
json: false,
compact: false,
- ignore: vec![],
}),
..Flags::default()
}
@@ -3799,17 +3816,19 @@ mod tests {
r.unwrap(),
Flags {
subcommand: DenoSubcommand::Lint(LintFlags {
- files: vec![
- PathBuf::from("script_1.ts"),
- PathBuf::from("script_2.ts")
- ],
+ files: FileFlags {
+ include: vec![
+ PathBuf::from("script_1.ts"),
+ PathBuf::from("script_2.ts")
+ ],
+ ignore: vec![],
+ },
rules: false,
maybe_rules_tags: None,
maybe_rules_include: None,
maybe_rules_exclude: None,
json: false,
compact: false,
- ignore: vec![],
}),
watch: Some(vec![]),
..Flags::default()
@@ -3828,17 +3847,19 @@ mod tests {
r.unwrap(),
Flags {
subcommand: DenoSubcommand::Lint(LintFlags {
- files: vec![
- PathBuf::from("script_1.ts"),
- PathBuf::from("script_2.ts")
- ],
+ files: FileFlags {
+ include: vec![
+ PathBuf::from("script_1.ts"),
+ PathBuf::from("script_2.ts")
+ ],
+ ignore: vec![],
+ },
rules: false,
maybe_rules_tags: None,
maybe_rules_include: None,
maybe_rules_exclude: None,
json: false,
compact: false,
- ignore: vec![],
}),
watch: Some(vec![]),
no_clear_screen: true,
@@ -3852,17 +3873,19 @@ mod tests {
r.unwrap(),
Flags {
subcommand: DenoSubcommand::Lint(LintFlags {
- files: vec![],
+ files: FileFlags {
+ include: vec![],
+ ignore: vec![
+ PathBuf::from("script_1.ts"),
+ PathBuf::from("script_2.ts")
+ ],
+ },
rules: false,
maybe_rules_tags: None,
maybe_rules_include: None,
maybe_rules_exclude: None,
json: false,
compact: false,
- ignore: vec![
- PathBuf::from("script_1.ts"),
- PathBuf::from("script_2.ts")
- ],
}),
..Flags::default()
}
@@ -3873,14 +3896,16 @@ mod tests {
r.unwrap(),
Flags {
subcommand: DenoSubcommand::Lint(LintFlags {
- files: vec![],
+ files: FileFlags {
+ include: vec![],
+ ignore: vec![],
+ },
rules: true,
maybe_rules_tags: None,
maybe_rules_include: None,
maybe_rules_exclude: None,
json: false,
compact: false,
- ignore: vec![],
}),
..Flags::default()
}
@@ -3897,14 +3922,16 @@ mod tests {
r.unwrap(),
Flags {
subcommand: DenoSubcommand::Lint(LintFlags {
- files: vec![],
+ files: FileFlags {
+ include: vec![],
+ ignore: vec![],
+ },
rules: false,
maybe_rules_tags: Some(svec![""]),
maybe_rules_include: Some(svec!["ban-untagged-todo", "no-undef"]),
maybe_rules_exclude: Some(svec!["no-const-assign"]),
json: false,
compact: false,
- ignore: vec![],
}),
..Flags::default()
}
@@ -3915,14 +3942,16 @@ mod tests {
r.unwrap(),
Flags {
subcommand: DenoSubcommand::Lint(LintFlags {
- files: vec![PathBuf::from("script_1.ts")],
+ files: FileFlags {
+ include: vec![PathBuf::from("script_1.ts")],
+ ignore: vec![],
+ },
rules: false,
maybe_rules_tags: None,
maybe_rules_include: None,
maybe_rules_exclude: None,
json: true,
compact: false,
- ignore: vec![],
}),
..Flags::default()
}
@@ -3940,14 +3969,16 @@ mod tests {
r.unwrap(),
Flags {
subcommand: DenoSubcommand::Lint(LintFlags {
- files: vec![PathBuf::from("script_1.ts")],
+ files: FileFlags {
+ include: vec![PathBuf::from("script_1.ts")],
+ ignore: vec![],
+ },
rules: false,
maybe_rules_tags: None,
maybe_rules_include: None,
maybe_rules_exclude: None,
json: true,
compact: false,
- ignore: vec![],
}),
config_flag: ConfigFlag::Path("Deno.jsonc".to_string()),
..Flags::default()
@@ -3966,14 +3997,16 @@ mod tests {
r.unwrap(),
Flags {
subcommand: DenoSubcommand::Lint(LintFlags {
- files: vec![PathBuf::from("script_1.ts")],
+ files: FileFlags {
+ include: vec![PathBuf::from("script_1.ts")],
+ ignore: vec![],
+ },
rules: false,
maybe_rules_tags: None,
maybe_rules_include: None,
maybe_rules_exclude: None,
json: false,
compact: true,
- ignore: vec![],
}),
config_flag: ConfigFlag::Path("Deno.jsonc".to_string()),
..Flags::default()
@@ -5510,10 +5543,12 @@ mod tests {
fail_fast: None,
filter: Some("- foo".to_string()),
allow_none: true,
- include: svec!["dir1/", "dir2/"],
- ignore: vec![],
+ files: FileFlags {
+ include: vec![PathBuf::from("dir1/"), PathBuf::from("dir2/")],
+ ignore: vec![],
+ },
shuffle: None,
- concurrent_jobs: NonZeroUsize::new(1).unwrap(),
+ concurrent_jobs: None,
trace_ops: true,
}),
unstable: true,
@@ -5582,9 +5617,11 @@ mod tests {
filter: None,
allow_none: false,
shuffle: None,
- include: vec![],
- ignore: vec![],
- concurrent_jobs: NonZeroUsize::new(4).unwrap(),
+ files: FileFlags {
+ include: vec![],
+ ignore: vec![],
+ },
+ concurrent_jobs: Some(NonZeroUsize::new(4).unwrap()),
trace_ops: false,
}),
type_check_mode: TypeCheckMode::Local,
@@ -5610,9 +5647,11 @@ mod tests {
filter: None,
allow_none: false,
shuffle: None,
- include: vec![],
- ignore: vec![],
- concurrent_jobs: NonZeroUsize::new(1).unwrap(),
+ files: FileFlags {
+ include: vec![],
+ ignore: vec![],
+ },
+ concurrent_jobs: None,
trace_ops: false,
}),
type_check_mode: TypeCheckMode::Local,
@@ -5642,9 +5681,11 @@ mod tests {
filter: None,
allow_none: false,
shuffle: None,
- include: vec![],
- ignore: vec![],
- concurrent_jobs: NonZeroUsize::new(1).unwrap(),
+ files: FileFlags {
+ include: vec![],
+ ignore: vec![],
+ },
+ concurrent_jobs: None,
trace_ops: false,
}),
no_prompt: true,
@@ -5668,9 +5709,11 @@ mod tests {
filter: None,
allow_none: false,
shuffle: Some(1),
- include: vec![],
- ignore: vec![],
- concurrent_jobs: NonZeroUsize::new(1).unwrap(),
+ files: FileFlags {
+ include: vec![],
+ ignore: vec![],
+ },
+ concurrent_jobs: None,
trace_ops: false,
}),
no_prompt: true,
@@ -5694,9 +5737,38 @@ mod tests {
filter: None,
allow_none: false,
shuffle: None,
- include: vec![],
- ignore: vec![],
- concurrent_jobs: NonZeroUsize::new(1).unwrap(),
+ files: FileFlags {
+ include: vec![],
+ ignore: vec![],
+ },
+ concurrent_jobs: None,
+ trace_ops: false,
+ }),
+ no_prompt: true,
+ type_check_mode: TypeCheckMode::Local,
+ watch: Some(vec![]),
+ ..Flags::default()
+ }
+ );
+ }
+ #[test]
+ fn test_watch_explicit_cwd() {
+ let r = flags_from_vec(svec!["deno", "test", "--watch", "./"]);
+ assert_eq!(
+ r.unwrap(),
+ Flags {
+ subcommand: DenoSubcommand::Test(TestFlags {
+ no_run: false,
+ doc: false,
+ fail_fast: None,
+ filter: None,
+ allow_none: false,
+ shuffle: None,
+ files: FileFlags {
+ include: vec![PathBuf::from("./")],
+ ignore: vec![],
+ },
+ concurrent_jobs: None,
trace_ops: false,
}),
no_prompt: true,
@@ -5721,9 +5793,11 @@ mod tests {
filter: None,
allow_none: false,
shuffle: None,
- include: vec![],
- ignore: vec![],
- concurrent_jobs: NonZeroUsize::new(1).unwrap(),
+ files: FileFlags {
+ include: vec![],
+ ignore: vec![],
+ },
+ concurrent_jobs: None,
trace_ops: false,
}),
watch: Some(vec![]),
@@ -6372,8 +6446,10 @@ mod tests {
Flags {
subcommand: DenoSubcommand::Bench(BenchFlags {
filter: Some("- foo".to_string()),
- include: Some(svec!["dir1/", "dir2/"]),
- ignore: vec![],
+ files: FileFlags {
+ include: vec![PathBuf::from("dir1/"), PathBuf::from("dir2/")],
+ ignore: vec![],
+ },
}),
unstable: true,
type_check_mode: TypeCheckMode::Local,
@@ -6387,6 +6463,27 @@ mod tests {
}
#[test]
+ fn bench_watch() {
+ let r = flags_from_vec(svec!["deno", "bench", "--watch"]);
+ assert_eq!(
+ r.unwrap(),
+ Flags {
+ subcommand: DenoSubcommand::Bench(BenchFlags {
+ filter: None,
+ files: FileFlags {
+ include: vec![],
+ ignore: vec![],
+ },
+ }),
+ no_prompt: true,
+ type_check_mode: TypeCheckMode::Local,
+ watch: Some(vec![]),
+ ..Flags::default()
+ }
+ );
+ }
+
+ #[test]
fn run_with_check() {
let r = flags_from_vec(svec!["deno", "run", "--check", "script.ts",]);
assert_eq!(
diff --git a/cli/args/mod.rs b/cli/args/mod.rs
index d677cf832..0f60d09c3 100644
--- a/cli/args/mod.rs
+++ b/cli/args/mod.rs
@@ -10,23 +10,15 @@ pub use config_file::BenchConfig;
pub use config_file::CompilerOptions;
pub use config_file::ConfigFile;
pub use config_file::EmitConfigOptions;
-pub use config_file::FmtConfig;
+pub use config_file::FilesConfig;
pub use config_file::FmtOptionsConfig;
-pub use config_file::IgnoredCompilerOptions;
pub use config_file::JsxImportSourceConfig;
-pub use config_file::LintConfig;
pub use config_file::LintRulesConfig;
-pub use config_file::MaybeImportsResult;
pub use config_file::ProseWrap;
-pub use config_file::TestConfig;
pub use config_file::TsConfig;
pub use config_file::TsConfigForEmit;
pub use config_file::TsConfigType;
pub use config_file::TsTypeLib;
-use deno_runtime::deno_tls::rustls;
-use deno_runtime::deno_tls::rustls_native_certs::load_native_certs;
-use deno_runtime::deno_tls::rustls_pemfile;
-use deno_runtime::deno_tls::webpki_roots;
pub use flags::*;
pub use lockfile::Lockfile;
pub use lockfile::LockfileError;
@@ -40,13 +32,18 @@ use deno_core::normalize_path;
use deno_core::parking_lot::Mutex;
use deno_core::url::Url;
use deno_runtime::colors;
+use deno_runtime::deno_tls::rustls;
use deno_runtime::deno_tls::rustls::RootCertStore;
+use deno_runtime::deno_tls::rustls_native_certs::load_native_certs;
+use deno_runtime::deno_tls::rustls_pemfile;
+use deno_runtime::deno_tls::webpki_roots;
use deno_runtime::inspector_server::InspectorServer;
use deno_runtime::permissions::PermissionsOptions;
use std::collections::BTreeMap;
use std::env;
use std::io::BufReader;
use std::net::SocketAddr;
+use std::num::NonZeroUsize;
use std::path::PathBuf;
use std::sync::Arc;
@@ -54,6 +51,11 @@ use crate::cache::DenoDir;
use crate::util::fs::canonicalize_path_maybe_not_exists;
use crate::version;
+use self::config_file::FmtConfig;
+use self::config_file::LintConfig;
+use self::config_file::MaybeImportsResult;
+use self::config_file::TestConfig;
+
/// Indicates how cached source files should be handled.
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum CacheSetting {
@@ -95,6 +97,274 @@ impl CacheSetting {
}
}
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct BenchOptions {
+ pub files: FilesConfig,
+ pub filter: Option<String>,
+}
+
+impl BenchOptions {
+ pub fn resolve(
+ maybe_bench_config: Option<BenchConfig>,
+ maybe_bench_flags: Option<BenchFlags>,
+ ) -> Result<Self, AnyError> {
+ let bench_flags = maybe_bench_flags.unwrap_or_default();
+ Ok(Self {
+ files: resolve_files(
+ maybe_bench_config.map(|c| c.files),
+ Some(bench_flags.files),
+ ),
+ filter: bench_flags.filter,
+ })
+ }
+}
+
+#[derive(Clone, Debug, Default)]
+pub struct FmtOptions {
+ pub is_stdin: bool,
+ pub check: bool,
+ pub ext: String,
+ pub options: FmtOptionsConfig,
+ pub files: FilesConfig,
+}
+
+impl FmtOptions {
+ pub fn resolve(
+ maybe_fmt_config: Option<FmtConfig>,
+ mut maybe_fmt_flags: Option<FmtFlags>,
+ ) -> Result<Self, AnyError> {
+ let is_stdin = if let Some(fmt_flags) = maybe_fmt_flags.as_mut() {
+ let args = &mut fmt_flags.files.include;
+ if args.len() == 1 && args[0].to_string_lossy() == "-" {
+ args.pop(); // remove the "-" arg
+ true
+ } else {
+ false
+ }
+ } else {
+ false
+ };
+ let (maybe_config_options, maybe_config_files) =
+ maybe_fmt_config.map(|c| (c.options, c.files)).unzip();
+
+ 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,
+ ),
+ files: resolve_files(
+ maybe_config_files,
+ maybe_fmt_flags.map(|f| f.files),
+ ),
+ })
+ }
+}
+
+fn resolve_fmt_options(
+ fmt_flags: Option<&FmtFlags>,
+ options: Option<FmtOptionsConfig>,
+) -> FmtOptionsConfig {
+ let mut options = options.unwrap_or_default();
+
+ if let Some(fmt_flags) = fmt_flags {
+ if let Some(use_tabs) = fmt_flags.use_tabs {
+ options.use_tabs = Some(use_tabs);
+ }
+
+ if let Some(line_width) = fmt_flags.line_width {
+ options.line_width = Some(line_width.get());
+ }
+
+ if let Some(indent_width) = fmt_flags.indent_width {
+ options.indent_width = Some(indent_width.get());
+ }
+
+ if let Some(single_quote) = fmt_flags.single_quote {
+ options.single_quote = Some(single_quote);
+ }
+
+ if let Some(prose_wrap) = &fmt_flags.prose_wrap {
+ options.prose_wrap = Some(match prose_wrap.as_str() {
+ "always" => ProseWrap::Always,
+ "never" => ProseWrap::Never,
+ "preserve" => ProseWrap::Preserve,
+ // validators in `flags.rs` makes other values unreachable
+ _ => unreachable!(),
+ });
+ }
+ }
+
+ options
+}
+
+#[derive(Clone)]
+pub struct TestOptions {
+ pub files: FilesConfig,
+ pub doc: bool,
+ pub no_run: bool,
+ pub fail_fast: Option<NonZeroUsize>,
+ pub allow_none: bool,
+ pub filter: Option<String>,
+ pub shuffle: Option<u64>,
+ pub concurrent_jobs: NonZeroUsize,
+ pub trace_ops: bool,
+}
+
+impl TestOptions {
+ pub fn resolve(
+ maybe_test_config: Option<TestConfig>,
+ maybe_test_flags: Option<TestFlags>,
+ ) -> Result<Self, AnyError> {
+ let test_flags = maybe_test_flags.unwrap_or_default();
+
+ Ok(Self {
+ files: resolve_files(
+ maybe_test_config.map(|c| c.files),
+ Some(test_flags.files),
+ ),
+ allow_none: test_flags.allow_none,
+ concurrent_jobs: test_flags
+ .concurrent_jobs
+ .unwrap_or_else(|| NonZeroUsize::new(1).unwrap()),
+ doc: test_flags.doc,
+ fail_fast: test_flags.fail_fast,
+ filter: test_flags.filter,
+ no_run: test_flags.no_run,
+ shuffle: test_flags.shuffle,
+ trace_ops: test_flags.trace_ops,
+ })
+ }
+}
+
+#[derive(Clone, Debug)]
+pub enum LintReporterKind {
+ Pretty,
+ Json,
+ Compact,
+}
+
+impl Default for LintReporterKind {
+ fn default() -> Self {
+ LintReporterKind::Pretty
+ }
+}
+
+#[derive(Clone, Debug, Default)]
+pub struct LintOptions {
+ pub rules: LintRulesConfig,
+ pub files: FilesConfig,
+ pub is_stdin: bool,
+ pub reporter_kind: LintReporterKind,
+}
+
+impl LintOptions {
+ pub fn resolve(
+ maybe_lint_config: Option<LintConfig>,
+ mut maybe_lint_flags: Option<LintFlags>,
+ ) -> Result<Self, AnyError> {
+ let is_stdin = if let Some(lint_flags) = maybe_lint_flags.as_mut() {
+ let args = &mut lint_flags.files.include;
+ if args.len() == 1 && args[0].to_string_lossy() == "-" {
+ args.pop(); // remove the "-" arg
+ true
+ } else {
+ false
+ }
+ } else {
+ false
+ };
+
+ let mut maybe_reporter_kind =
+ maybe_lint_flags.as_ref().and_then(|lint_flags| {
+ if lint_flags.json {
+ Some(LintReporterKind::Json)
+ } else if lint_flags.compact {
+ Some(LintReporterKind::Compact)
+ } else {
+ None
+ }
+ });
+
+ if maybe_reporter_kind.is_none() {
+ // Flag not set, so try to get lint reporter from the config file.
+ if let Some(lint_config) = &maybe_lint_config {
+ maybe_reporter_kind = match lint_config.report.as_deref() {
+ Some("json") => Some(LintReporterKind::Json),
+ Some("compact") => Some(LintReporterKind::Compact),
+ Some("pretty") => Some(LintReporterKind::Pretty),
+ Some(_) => {
+ bail!("Invalid lint report type in config file")
+ }
+ None => None,
+ }
+ }
+ }
+
+ let (
+ maybe_file_flags,
+ maybe_rules_tags,
+ maybe_rules_include,
+ maybe_rules_exclude,
+ ) = maybe_lint_flags
+ .map(|f| {
+ (
+ f.files,
+ f.maybe_rules_tags,
+ f.maybe_rules_include,
+ f.maybe_rules_exclude,
+ )
+ })
+ .unwrap_or_default();
+
+ let (maybe_config_files, maybe_config_rules) =
+ maybe_lint_config.map(|c| (c.files, c.rules)).unzip();
+ Ok(Self {
+ reporter_kind: maybe_reporter_kind.unwrap_or_default(),
+ is_stdin,
+ files: resolve_files(maybe_config_files, Some(maybe_file_flags)),
+ rules: resolve_lint_rules_options(
+ maybe_config_rules,
+ maybe_rules_tags,
+ maybe_rules_include,
+ maybe_rules_exclude,
+ ),
+ })
+ }
+}
+
+fn resolve_lint_rules_options(
+ maybe_lint_rules_config: Option<LintRulesConfig>,
+ mut maybe_rules_tags: Option<Vec<String>>,
+ mut maybe_rules_include: Option<Vec<String>>,
+ mut maybe_rules_exclude: Option<Vec<String>>,
+) -> LintRulesConfig {
+ if let Some(config_rules) = maybe_lint_rules_config {
+ // Try to get configured rules. CLI flags take precedence
+ // over config file, i.e. if there's `rules.include` in config file
+ // and `--rules-include` CLI flag, only the flag value is taken into account.
+ if maybe_rules_include.is_none() {
+ maybe_rules_include = config_rules.include;
+ }
+ if maybe_rules_exclude.is_none() {
+ maybe_rules_exclude = config_rules.exclude;
+ }
+ if maybe_rules_tags.is_none() {
+ maybe_rules_tags = config_rules.tags;
+ }
+ }
+ LintRulesConfig {
+ exclude: maybe_rules_exclude,
+ include: maybe_rules_include,
+ tags: maybe_rules_tags,
+ }
+}
+
/// Create and populate a root cert store based on the passed options and
/// environment.
pub fn get_root_cert_store(
@@ -394,36 +664,57 @@ impl CliOptions {
}
}
- pub fn to_lint_config(&self) -> Result<Option<LintConfig>, AnyError> {
- if let Some(config_file) = &self.maybe_config_file {
- config_file.to_lint_config()
+ pub fn get_maybe_config_file(&self) -> &Option<ConfigFile> {
+ &self.maybe_config_file
+ }
+
+ pub fn resolve_fmt_options(
+ &self,
+ fmt_flags: FmtFlags,
+ ) -> Result<FmtOptions, AnyError> {
+ let maybe_fmt_config = if let Some(config_file) = &self.maybe_config_file {
+ config_file.to_fmt_config()?
} else {
- Ok(None)
- }
+ None
+ };
+ FmtOptions::resolve(maybe_fmt_config, Some(fmt_flags))
}
- pub fn to_test_config(&self) -> Result<Option<TestConfig>, AnyError> {
- if let Some(config_file) = &self.maybe_config_file {
- config_file.to_test_config()
+ pub fn resolve_lint_options(
+ &self,
+ lint_flags: LintFlags,
+ ) -> Result<LintOptions, AnyError> {
+ let maybe_lint_config = if let Some(config_file) = &self.maybe_config_file {
+ config_file.to_lint_config()?
} else {
- Ok(None)
- }
+ None
+ };
+ LintOptions::resolve(maybe_lint_config, Some(lint_flags))
}
- pub fn to_bench_config(&self) -> Result<Option<BenchConfig>, AnyError> {
- if let Some(config_file) = &self.maybe_config_file {
- config_file.to_bench_config()
+ pub fn resolve_test_options(
+ &self,
+ test_flags: TestFlags,
+ ) -> Result<TestOptions, AnyError> {
+ let maybe_test_config = if let Some(config_file) = &self.maybe_config_file {
+ config_file.to_test_config()?
} else {
- Ok(None)
- }
+ None
+ };
+ TestOptions::resolve(maybe_test_config, Some(test_flags))
}
- pub fn to_fmt_config(&self) -> Result<Option<FmtConfig>, AnyError> {
- if let Some(config) = &self.maybe_config_file {
- config.to_fmt_config()
+ pub fn resolve_bench_options(
+ &self,
+ bench_flags: BenchFlags,
+ ) -> Result<BenchOptions, AnyError> {
+ let maybe_bench_config = if let Some(config_file) = &self.maybe_config_file
+ {
+ config_file.to_bench_config()?
} else {
- Ok(None)
- }
+ None
+ };
+ BenchOptions::resolve(maybe_bench_config, Some(bench_flags))
}
/// Vector of user script CLI arguments.
@@ -639,6 +930,25 @@ fn resolve_import_map_specifier(
Ok(None)
}
+/// Collect included and ignored files. CLI flags take precedence
+/// over config file, i.e. if there's `files.ignore` in config file
+/// and `--ignore` CLI flag, only the flag value is taken into account.
+fn resolve_files(
+ maybe_files_config: Option<FilesConfig>,
+ maybe_file_flags: Option<FileFlags>,
+) -> FilesConfig {
+ let mut result = maybe_files_config.unwrap_or_default();
+ if let Some(file_flags) = maybe_file_flags {
+ if !file_flags.include.is_empty() {
+ result.include = file_flags.include;
+ }
+ if !file_flags.ignore.is_empty() {
+ result.exclude = file_flags.ignore;
+ }
+ }
+ result
+}
+
/// Resolves the no_prompt value based on the cli flags and environment.
pub fn resolve_no_prompt(flags: &Flags) -> bool {
flags.no_prompt || {