mirror of
https://github.com/denoland/deno.git
synced 2024-12-25 16:49:18 -05:00
refactor(cli/tools): move flag and config logic to CliOptions (#17008)
Co-authored-by: David Sherret <dsherret@gmail.com>
This commit is contained in:
parent
fac6447815
commit
84ef26ac9b
15 changed files with 914 additions and 772 deletions
|
@ -295,43 +295,45 @@ impl SerializedFilesConfig {
|
||||||
include: self
|
include: self
|
||||||
.include
|
.include
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|p| config_dir.join(&p))
|
.map(|p| {
|
||||||
.collect::<Result<Vec<ModuleSpecifier>, _>>()?,
|
let url = config_dir.join(&p)?;
|
||||||
|
specifier_to_file_path(&url)
|
||||||
|
})
|
||||||
|
.collect::<Result<Vec<_>, _>>()?,
|
||||||
exclude: self
|
exclude: self
|
||||||
.exclude
|
.exclude
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|p| config_dir.join(&p))
|
.map(|p| {
|
||||||
.collect::<Result<Vec<ModuleSpecifier>, _>>()?,
|
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 struct FilesConfig {
|
||||||
pub include: Vec<ModuleSpecifier>,
|
pub include: Vec<PathBuf>,
|
||||||
pub exclude: Vec<ModuleSpecifier>,
|
pub exclude: Vec<PathBuf>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FilesConfig {
|
impl FilesConfig {
|
||||||
/// Gets if the provided specifier is allowed based on the includes
|
/// Gets if the provided specifier is allowed based on the includes
|
||||||
/// and excludes in the configuration file.
|
/// and excludes in the configuration file.
|
||||||
pub fn matches_specifier(&self, specifier: &ModuleSpecifier) -> bool {
|
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.
|
// Skip files which is in the exclude list.
|
||||||
let specifier_text = specifier.as_str();
|
if self.exclude.iter().any(|i| file_path.starts_with(i)) {
|
||||||
if self
|
|
||||||
.exclude
|
|
||||||
.iter()
|
|
||||||
.any(|i| specifier_text.starts_with(i.as_str()))
|
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ignore files not in the include list if it's not empty.
|
// Ignore files not in the include list if it's not empty.
|
||||||
self.include.is_empty()
|
self.include.is_empty()
|
||||||
|| self
|
|| self.include.iter().any(|i| file_path.starts_with(i))
|
||||||
.include
|
|
||||||
.iter()
|
|
||||||
.any(|i| specifier_text.starts_with(i.as_str()))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -663,6 +665,16 @@ impl ConfigFile {
|
||||||
self.json.import_map.clone()
|
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> {
|
pub fn to_lint_config(&self) -> Result<Option<LintConfig>, AnyError> {
|
||||||
if let Some(config) = self.json.lint.clone() {
|
if let Some(config) = self.json.lint.clone() {
|
||||||
let lint_config: SerializedLintConfig = serde_json::from_value(config)
|
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(
|
pub fn resolve_tasks_config(
|
||||||
&self,
|
&self,
|
||||||
) -> Result<BTreeMap<String, String>, AnyError> {
|
) -> Result<BTreeMap<String, String>, AnyError> {
|
||||||
|
@ -1068,13 +1070,10 @@ mod tests {
|
||||||
.to_lint_config()
|
.to_lint_config()
|
||||||
.expect("error parsing lint object")
|
.expect("error parsing lint object")
|
||||||
.expect("lint object should be defined");
|
.expect("lint object should be defined");
|
||||||
assert_eq!(
|
assert_eq!(lint_config.files.include, vec![PathBuf::from("/deno/src/")]);
|
||||||
lint_config.files.include,
|
|
||||||
vec![config_dir.join("src/").unwrap()]
|
|
||||||
);
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
lint_config.files.exclude,
|
lint_config.files.exclude,
|
||||||
vec![config_dir.join("src/testdata/").unwrap()]
|
vec![PathBuf::from("/deno/src/testdata/")]
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
lint_config.rules.include,
|
lint_config.rules.include,
|
||||||
|
@ -1090,13 +1089,10 @@ mod tests {
|
||||||
.to_fmt_config()
|
.to_fmt_config()
|
||||||
.expect("error parsing fmt object")
|
.expect("error parsing fmt object")
|
||||||
.expect("fmt object should be defined");
|
.expect("fmt object should be defined");
|
||||||
assert_eq!(
|
assert_eq!(fmt_config.files.include, vec![PathBuf::from("/deno/src/")]);
|
||||||
fmt_config.files.include,
|
|
||||||
vec![config_dir.join("src/").unwrap()]
|
|
||||||
);
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
fmt_config.files.exclude,
|
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.use_tabs, Some(true));
|
||||||
assert_eq!(fmt_config.options.line_width, Some(80));
|
assert_eq!(fmt_config.options.line_width, Some(80));
|
||||||
|
@ -1190,6 +1186,8 @@ mod tests {
|
||||||
let expected_exclude = ModuleSpecifier::from_file_path(
|
let expected_exclude = ModuleSpecifier::from_file_path(
|
||||||
testdata.join("fmt/with_config/subdir/b.ts"),
|
testdata.join("fmt/with_config/subdir/b.ts"),
|
||||||
)
|
)
|
||||||
|
.unwrap()
|
||||||
|
.to_file_path()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(fmt_config.files.exclude, vec![expected_exclude]);
|
assert_eq!(fmt_config.files.exclude, vec![expected_exclude]);
|
||||||
|
|
||||||
|
|
|
@ -6,8 +6,6 @@ use clap::ColorChoice;
|
||||||
use clap::Command;
|
use clap::Command;
|
||||||
use clap::ValueHint;
|
use clap::ValueHint;
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
use deno_core::serde::Deserialize;
|
|
||||||
use deno_core::serde::Serialize;
|
|
||||||
use deno_core::url::Url;
|
use deno_core::url::Url;
|
||||||
use deno_runtime::permissions::parse_sys_kind;
|
use deno_runtime::permissions::parse_sys_kind;
|
||||||
use log::debug;
|
use log::debug;
|
||||||
|
@ -46,30 +44,35 @@ static SHORT_VERSION: Lazy<String> = Lazy::new(|| {
|
||||||
.to_string()
|
.to_string()
|
||||||
});
|
});
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
|
#[derive(Clone, Debug, Default, Eq, PartialEq)]
|
||||||
pub struct BenchFlags {
|
pub struct FileFlags {
|
||||||
pub ignore: Vec<PathBuf>,
|
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>,
|
pub filter: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub struct BundleFlags {
|
pub struct BundleFlags {
|
||||||
pub source_file: String,
|
pub source_file: String,
|
||||||
pub out_file: Option<PathBuf>,
|
pub out_file: Option<PathBuf>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub struct CacheFlags {
|
pub struct CacheFlags {
|
||||||
pub files: Vec<String>,
|
pub files: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub struct CheckFlags {
|
pub struct CheckFlags {
|
||||||
pub files: Vec<String>,
|
pub files: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub struct CompileFlags {
|
pub struct CompileFlags {
|
||||||
pub source_file: String,
|
pub source_file: String,
|
||||||
pub output: Option<PathBuf>,
|
pub output: Option<PathBuf>,
|
||||||
|
@ -77,12 +80,12 @@ pub struct CompileFlags {
|
||||||
pub target: Option<String>,
|
pub target: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub struct CompletionsFlags {
|
pub struct CompletionsFlags {
|
||||||
pub buf: Box<[u8]>,
|
pub buf: Box<[u8]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub struct CoverageFlags {
|
pub struct CoverageFlags {
|
||||||
pub files: Vec<PathBuf>,
|
pub files: Vec<PathBuf>,
|
||||||
pub output: Option<PathBuf>,
|
pub output: Option<PathBuf>,
|
||||||
|
@ -92,7 +95,7 @@ pub struct CoverageFlags {
|
||||||
pub lcov: bool,
|
pub lcov: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub struct DocFlags {
|
pub struct DocFlags {
|
||||||
pub private: bool,
|
pub private: bool,
|
||||||
pub json: bool,
|
pub json: bool,
|
||||||
|
@ -100,19 +103,18 @@ pub struct DocFlags {
|
||||||
pub filter: Option<String>,
|
pub filter: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub struct EvalFlags {
|
pub struct EvalFlags {
|
||||||
pub print: bool,
|
pub print: bool,
|
||||||
pub code: String,
|
pub code: String,
|
||||||
pub ext: String,
|
pub ext: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub struct FmtFlags {
|
pub struct FmtFlags {
|
||||||
pub check: bool,
|
pub check: bool,
|
||||||
pub files: Vec<PathBuf>,
|
|
||||||
pub ignore: Vec<PathBuf>,
|
|
||||||
pub ext: String,
|
pub ext: String,
|
||||||
|
pub files: FileFlags,
|
||||||
pub use_tabs: Option<bool>,
|
pub use_tabs: Option<bool>,
|
||||||
pub line_width: Option<NonZeroU32>,
|
pub line_width: Option<NonZeroU32>,
|
||||||
pub indent_width: Option<NonZeroU8>,
|
pub indent_width: Option<NonZeroU8>,
|
||||||
|
@ -120,18 +122,18 @@ pub struct FmtFlags {
|
||||||
pub prose_wrap: Option<String>,
|
pub prose_wrap: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub struct InitFlags {
|
pub struct InitFlags {
|
||||||
pub dir: Option<String>,
|
pub dir: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub struct InfoFlags {
|
pub struct InfoFlags {
|
||||||
pub json: bool,
|
pub json: bool,
|
||||||
pub file: Option<String>,
|
pub file: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub struct InstallFlags {
|
pub struct InstallFlags {
|
||||||
pub module_url: String,
|
pub module_url: String,
|
||||||
pub args: Vec<String>,
|
pub args: Vec<String>,
|
||||||
|
@ -140,16 +142,15 @@ pub struct InstallFlags {
|
||||||
pub force: bool,
|
pub force: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub struct UninstallFlags {
|
pub struct UninstallFlags {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub root: Option<PathBuf>,
|
pub root: Option<PathBuf>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub struct LintFlags {
|
pub struct LintFlags {
|
||||||
pub files: Vec<PathBuf>,
|
pub files: FileFlags,
|
||||||
pub ignore: Vec<PathBuf>,
|
|
||||||
pub rules: bool,
|
pub rules: bool,
|
||||||
pub maybe_rules_tags: Option<Vec<String>>,
|
pub maybe_rules_tags: Option<Vec<String>>,
|
||||||
pub maybe_rules_include: Option<Vec<String>>,
|
pub maybe_rules_include: Option<Vec<String>>,
|
||||||
|
@ -158,14 +159,14 @@ pub struct LintFlags {
|
||||||
pub compact: bool,
|
pub compact: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub struct ReplFlags {
|
pub struct ReplFlags {
|
||||||
pub eval_files: Option<Vec<String>>,
|
pub eval_files: Option<Vec<String>>,
|
||||||
pub eval: Option<String>,
|
pub eval: Option<String>,
|
||||||
pub is_default_command: bool,
|
pub is_default_command: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub struct RunFlags {
|
pub struct RunFlags {
|
||||||
pub script: String,
|
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 struct TaskFlags {
|
||||||
pub cwd: Option<String>,
|
pub cwd: Option<String>,
|
||||||
pub task: String,
|
pub task: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
|
#[derive(Clone, Debug, Default, Eq, PartialEq)]
|
||||||
pub struct TestFlags {
|
pub struct TestFlags {
|
||||||
pub ignore: Vec<PathBuf>,
|
|
||||||
pub doc: bool,
|
pub doc: bool,
|
||||||
pub no_run: bool,
|
pub no_run: bool,
|
||||||
pub fail_fast: Option<NonZeroUsize>,
|
pub fail_fast: Option<NonZeroUsize>,
|
||||||
|
pub files: FileFlags,
|
||||||
pub allow_none: bool,
|
pub allow_none: bool,
|
||||||
pub include: Vec<String>,
|
|
||||||
pub filter: Option<String>,
|
pub filter: Option<String>,
|
||||||
pub shuffle: Option<u64>,
|
pub shuffle: Option<u64>,
|
||||||
pub concurrent_jobs: NonZeroUsize,
|
pub concurrent_jobs: Option<NonZeroUsize>,
|
||||||
pub trace_ops: bool,
|
pub trace_ops: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub struct UpgradeFlags {
|
pub struct UpgradeFlags {
|
||||||
pub dry_run: bool,
|
pub dry_run: bool,
|
||||||
pub force: bool,
|
pub force: bool,
|
||||||
|
@ -205,14 +205,14 @@ pub struct UpgradeFlags {
|
||||||
pub output: Option<PathBuf>,
|
pub output: Option<PathBuf>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub struct VendorFlags {
|
pub struct VendorFlags {
|
||||||
pub specifiers: Vec<String>,
|
pub specifiers: Vec<String>,
|
||||||
pub output_path: Option<PathBuf>,
|
pub output_path: Option<PathBuf>,
|
||||||
pub force: bool,
|
pub force: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub enum DenoSubcommand {
|
pub enum DenoSubcommand {
|
||||||
Bench(BenchFlags),
|
Bench(BenchFlags),
|
||||||
Bundle(BundleFlags),
|
Bundle(BundleFlags),
|
||||||
|
@ -455,9 +455,9 @@ impl Flags {
|
||||||
pub fn config_path_args(&self) -> Option<Vec<PathBuf>> {
|
pub fn config_path_args(&self) -> Option<Vec<PathBuf>> {
|
||||||
use DenoSubcommand::*;
|
use DenoSubcommand::*;
|
||||||
if let Fmt(FmtFlags { files, .. }) = &self.subcommand {
|
if let Fmt(FmtFlags { files, .. }) = &self.subcommand {
|
||||||
Some(files.clone())
|
Some(files.include.clone())
|
||||||
} else if let Lint(LintFlags { files, .. }) = &self.subcommand {
|
} else if let Lint(LintFlags { files, .. }) = &self.subcommand {
|
||||||
Some(files.clone())
|
Some(files.include.clone())
|
||||||
} else if let Run(RunFlags { script }) = &self.subcommand {
|
} else if let Run(RunFlags { script }) = &self.subcommand {
|
||||||
if let Ok(module_specifier) = deno_core::resolve_url_or_path(script) {
|
if let Ok(module_specifier) = deno_core::resolve_url_or_path(script) {
|
||||||
if module_specifier.scheme() == "file"
|
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 include = if matches.is_present("files") {
|
||||||
let files: Vec<String> = matches
|
let files = matches
|
||||||
.values_of("files")
|
.values_of("files")
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.map(String::from)
|
.map(PathBuf::from)
|
||||||
.collect();
|
.collect();
|
||||||
Some(files)
|
files
|
||||||
} else {
|
} else {
|
||||||
None
|
Vec::new()
|
||||||
};
|
};
|
||||||
|
|
||||||
watch_arg_parse(flags, matches, false);
|
watch_arg_parse(flags, matches, false);
|
||||||
flags.subcommand = DenoSubcommand::Bench(BenchFlags {
|
flags.subcommand = DenoSubcommand::Bench(BenchFlags {
|
||||||
include,
|
files: FileFlags { include, ignore },
|
||||||
ignore,
|
|
||||||
filter,
|
filter,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -2493,7 +2492,7 @@ fn fmt_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
|
||||||
config_args_parse(flags, matches);
|
config_args_parse(flags, matches);
|
||||||
watch_arg_parse(flags, matches, false);
|
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(),
|
Some(f) => f.map(PathBuf::from).collect(),
|
||||||
None => vec![],
|
None => vec![],
|
||||||
};
|
};
|
||||||
|
@ -2544,8 +2543,7 @@ fn fmt_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
|
||||||
flags.subcommand = DenoSubcommand::Fmt(FmtFlags {
|
flags.subcommand = DenoSubcommand::Fmt(FmtFlags {
|
||||||
check: matches.is_present("check"),
|
check: matches.is_present("check"),
|
||||||
ext,
|
ext,
|
||||||
files,
|
files: FileFlags { include, ignore },
|
||||||
ignore,
|
|
||||||
use_tabs,
|
use_tabs,
|
||||||
line_width,
|
line_width,
|
||||||
indent_width,
|
indent_width,
|
||||||
|
@ -2647,12 +2645,15 @@ fn lint_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
|
||||||
let json = matches.is_present("json");
|
let json = matches.is_present("json");
|
||||||
let compact = matches.is_present("compact");
|
let compact = matches.is_present("compact");
|
||||||
flags.subcommand = DenoSubcommand::Lint(LintFlags {
|
flags.subcommand = DenoSubcommand::Lint(LintFlags {
|
||||||
files,
|
files: FileFlags {
|
||||||
|
include: files,
|
||||||
|
ignore,
|
||||||
|
},
|
||||||
rules,
|
rules,
|
||||||
maybe_rules_tags,
|
maybe_rules_tags,
|
||||||
maybe_rules_include,
|
maybe_rules_include,
|
||||||
maybe_rules_exclude,
|
maybe_rules_exclude,
|
||||||
ignore,
|
|
||||||
json,
|
json,
|
||||||
compact,
|
compact,
|
||||||
});
|
});
|
||||||
|
@ -2811,12 +2812,9 @@ fn test_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
|
||||||
|
|
||||||
let concurrent_jobs = if matches.is_present("parallel") {
|
let concurrent_jobs = if matches.is_present("parallel") {
|
||||||
if let Ok(value) = env::var("DENO_JOBS") {
|
if let Ok(value) = env::var("DENO_JOBS") {
|
||||||
value
|
value.parse::<NonZeroUsize>().ok()
|
||||||
.parse::<NonZeroUsize>()
|
|
||||||
.unwrap_or(NonZeroUsize::new(1).unwrap())
|
|
||||||
} else {
|
} else {
|
||||||
std::thread::available_parallelism()
|
std::thread::available_parallelism().ok()
|
||||||
.unwrap_or(NonZeroUsize::new(1).unwrap())
|
|
||||||
}
|
}
|
||||||
} else if matches.is_present("jobs") {
|
} else if matches.is_present("jobs") {
|
||||||
// We can't change this to use the log crate because its not configured
|
// 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."),
|
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") {
|
if let Some(value) = matches.value_of("jobs") {
|
||||||
value.parse().unwrap()
|
Some(value.parse().unwrap())
|
||||||
} else {
|
} else {
|
||||||
std::thread::available_parallelism()
|
std::thread::available_parallelism().ok()
|
||||||
.unwrap_or(NonZeroUsize::new(1).unwrap())
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
NonZeroUsize::new(1).unwrap()
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
let include: Vec<String> = if matches.is_present("files") {
|
let include = if matches.is_present("files") {
|
||||||
matches
|
matches
|
||||||
.values_of("files")
|
.values_of("files")
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.map(String::from)
|
.map(PathBuf::from)
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
} else {
|
} else {
|
||||||
Vec::new()
|
Vec::new()
|
||||||
|
@ -2853,8 +2850,7 @@ fn test_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
|
||||||
no_run,
|
no_run,
|
||||||
doc,
|
doc,
|
||||||
fail_fast,
|
fail_fast,
|
||||||
include,
|
files: FileFlags { include, ignore },
|
||||||
ignore,
|
|
||||||
filter,
|
filter,
|
||||||
shuffle,
|
shuffle,
|
||||||
allow_none,
|
allow_none,
|
||||||
|
@ -3267,6 +3263,7 @@ mod tests {
|
||||||
fn global_flags() {
|
fn global_flags() {
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
let r = flags_from_vec(svec!["deno", "--unstable", "--log-level", "debug", "--quiet", "run", "script.ts"]);
|
let r = flags_from_vec(svec!["deno", "--unstable", "--log-level", "debug", "--quiet", "run", "script.ts"]);
|
||||||
|
|
||||||
let flags = r.unwrap();
|
let flags = r.unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
flags,
|
flags,
|
||||||
|
@ -3562,13 +3559,15 @@ mod tests {
|
||||||
r.unwrap(),
|
r.unwrap(),
|
||||||
Flags {
|
Flags {
|
||||||
subcommand: DenoSubcommand::Fmt(FmtFlags {
|
subcommand: DenoSubcommand::Fmt(FmtFlags {
|
||||||
ignore: vec![],
|
|
||||||
check: false,
|
check: false,
|
||||||
files: vec![
|
ext: "ts".to_string(),
|
||||||
|
files: FileFlags {
|
||||||
|
include: vec![
|
||||||
PathBuf::from("script_1.ts"),
|
PathBuf::from("script_1.ts"),
|
||||||
PathBuf::from("script_2.ts")
|
PathBuf::from("script_2.ts")
|
||||||
],
|
],
|
||||||
ext: "ts".to_string(),
|
ignore: vec![],
|
||||||
|
},
|
||||||
use_tabs: None,
|
use_tabs: None,
|
||||||
line_width: None,
|
line_width: None,
|
||||||
indent_width: None,
|
indent_width: None,
|
||||||
|
@ -3584,10 +3583,12 @@ mod tests {
|
||||||
r.unwrap(),
|
r.unwrap(),
|
||||||
Flags {
|
Flags {
|
||||||
subcommand: DenoSubcommand::Fmt(FmtFlags {
|
subcommand: DenoSubcommand::Fmt(FmtFlags {
|
||||||
ignore: vec![],
|
|
||||||
check: true,
|
check: true,
|
||||||
files: vec![],
|
|
||||||
ext: "ts".to_string(),
|
ext: "ts".to_string(),
|
||||||
|
files: FileFlags {
|
||||||
|
include: vec![],
|
||||||
|
ignore: vec![],
|
||||||
|
},
|
||||||
use_tabs: None,
|
use_tabs: None,
|
||||||
line_width: None,
|
line_width: None,
|
||||||
indent_width: None,
|
indent_width: None,
|
||||||
|
@ -3603,10 +3604,12 @@ mod tests {
|
||||||
r.unwrap(),
|
r.unwrap(),
|
||||||
Flags {
|
Flags {
|
||||||
subcommand: DenoSubcommand::Fmt(FmtFlags {
|
subcommand: DenoSubcommand::Fmt(FmtFlags {
|
||||||
ignore: vec![],
|
|
||||||
check: false,
|
check: false,
|
||||||
files: vec![],
|
|
||||||
ext: "ts".to_string(),
|
ext: "ts".to_string(),
|
||||||
|
files: FileFlags {
|
||||||
|
include: vec![],
|
||||||
|
ignore: vec![],
|
||||||
|
},
|
||||||
use_tabs: None,
|
use_tabs: None,
|
||||||
line_width: None,
|
line_width: None,
|
||||||
indent_width: None,
|
indent_width: None,
|
||||||
|
@ -3622,10 +3625,12 @@ mod tests {
|
||||||
r.unwrap(),
|
r.unwrap(),
|
||||||
Flags {
|
Flags {
|
||||||
subcommand: DenoSubcommand::Fmt(FmtFlags {
|
subcommand: DenoSubcommand::Fmt(FmtFlags {
|
||||||
ignore: vec![],
|
|
||||||
check: false,
|
check: false,
|
||||||
files: vec![],
|
|
||||||
ext: "ts".to_string(),
|
ext: "ts".to_string(),
|
||||||
|
files: FileFlags {
|
||||||
|
include: vec![],
|
||||||
|
ignore: vec![],
|
||||||
|
},
|
||||||
use_tabs: None,
|
use_tabs: None,
|
||||||
line_width: None,
|
line_width: None,
|
||||||
indent_width: None,
|
indent_width: None,
|
||||||
|
@ -3643,10 +3648,12 @@ mod tests {
|
||||||
r.unwrap(),
|
r.unwrap(),
|
||||||
Flags {
|
Flags {
|
||||||
subcommand: DenoSubcommand::Fmt(FmtFlags {
|
subcommand: DenoSubcommand::Fmt(FmtFlags {
|
||||||
ignore: vec![],
|
|
||||||
check: false,
|
check: false,
|
||||||
files: vec![],
|
|
||||||
ext: "ts".to_string(),
|
ext: "ts".to_string(),
|
||||||
|
files: FileFlags {
|
||||||
|
include: vec![],
|
||||||
|
ignore: vec![],
|
||||||
|
},
|
||||||
use_tabs: None,
|
use_tabs: None,
|
||||||
line_width: None,
|
line_width: None,
|
||||||
indent_width: None,
|
indent_width: None,
|
||||||
|
@ -3671,10 +3678,12 @@ mod tests {
|
||||||
r.unwrap(),
|
r.unwrap(),
|
||||||
Flags {
|
Flags {
|
||||||
subcommand: DenoSubcommand::Fmt(FmtFlags {
|
subcommand: DenoSubcommand::Fmt(FmtFlags {
|
||||||
ignore: vec![PathBuf::from("bar.js")],
|
|
||||||
check: true,
|
check: true,
|
||||||
files: vec![PathBuf::from("foo.ts")],
|
|
||||||
ext: "ts".to_string(),
|
ext: "ts".to_string(),
|
||||||
|
files: FileFlags {
|
||||||
|
include: vec![PathBuf::from("foo.ts")],
|
||||||
|
ignore: vec![PathBuf::from("bar.js")],
|
||||||
|
},
|
||||||
use_tabs: None,
|
use_tabs: None,
|
||||||
line_width: None,
|
line_width: None,
|
||||||
indent_width: None,
|
indent_width: None,
|
||||||
|
@ -3691,10 +3700,12 @@ mod tests {
|
||||||
r.unwrap(),
|
r.unwrap(),
|
||||||
Flags {
|
Flags {
|
||||||
subcommand: DenoSubcommand::Fmt(FmtFlags {
|
subcommand: DenoSubcommand::Fmt(FmtFlags {
|
||||||
ignore: vec![],
|
|
||||||
check: false,
|
check: false,
|
||||||
files: vec![],
|
|
||||||
ext: "ts".to_string(),
|
ext: "ts".to_string(),
|
||||||
|
files: FileFlags {
|
||||||
|
include: vec![],
|
||||||
|
ignore: vec![],
|
||||||
|
},
|
||||||
use_tabs: None,
|
use_tabs: None,
|
||||||
line_width: None,
|
line_width: None,
|
||||||
indent_width: None,
|
indent_width: None,
|
||||||
|
@ -3718,10 +3729,12 @@ mod tests {
|
||||||
r.unwrap(),
|
r.unwrap(),
|
||||||
Flags {
|
Flags {
|
||||||
subcommand: DenoSubcommand::Fmt(FmtFlags {
|
subcommand: DenoSubcommand::Fmt(FmtFlags {
|
||||||
ignore: vec![],
|
|
||||||
check: false,
|
check: false,
|
||||||
files: vec![PathBuf::from("foo.ts")],
|
|
||||||
ext: "ts".to_string(),
|
ext: "ts".to_string(),
|
||||||
|
files: FileFlags {
|
||||||
|
include: vec![PathBuf::from("foo.ts")],
|
||||||
|
ignore: vec![],
|
||||||
|
},
|
||||||
use_tabs: None,
|
use_tabs: None,
|
||||||
line_width: None,
|
line_width: None,
|
||||||
indent_width: None,
|
indent_width: None,
|
||||||
|
@ -3750,10 +3763,12 @@ mod tests {
|
||||||
r.unwrap(),
|
r.unwrap(),
|
||||||
Flags {
|
Flags {
|
||||||
subcommand: DenoSubcommand::Fmt(FmtFlags {
|
subcommand: DenoSubcommand::Fmt(FmtFlags {
|
||||||
ignore: vec![],
|
|
||||||
check: false,
|
check: false,
|
||||||
files: vec![],
|
|
||||||
ext: "ts".to_string(),
|
ext: "ts".to_string(),
|
||||||
|
files: FileFlags {
|
||||||
|
include: vec![],
|
||||||
|
ignore: vec![],
|
||||||
|
},
|
||||||
use_tabs: Some(true),
|
use_tabs: Some(true),
|
||||||
line_width: Some(NonZeroU32::new(60).unwrap()),
|
line_width: Some(NonZeroU32::new(60).unwrap()),
|
||||||
indent_width: Some(NonZeroU8::new(4).unwrap()),
|
indent_width: Some(NonZeroU8::new(4).unwrap()),
|
||||||
|
@ -3772,17 +3787,19 @@ mod tests {
|
||||||
r.unwrap(),
|
r.unwrap(),
|
||||||
Flags {
|
Flags {
|
||||||
subcommand: DenoSubcommand::Lint(LintFlags {
|
subcommand: DenoSubcommand::Lint(LintFlags {
|
||||||
files: vec![
|
files: FileFlags {
|
||||||
|
include: vec![
|
||||||
PathBuf::from("script_1.ts"),
|
PathBuf::from("script_1.ts"),
|
||||||
PathBuf::from("script_2.ts")
|
PathBuf::from("script_2.ts")
|
||||||
],
|
],
|
||||||
|
ignore: vec![],
|
||||||
|
},
|
||||||
rules: false,
|
rules: false,
|
||||||
maybe_rules_tags: None,
|
maybe_rules_tags: None,
|
||||||
maybe_rules_include: None,
|
maybe_rules_include: None,
|
||||||
maybe_rules_exclude: None,
|
maybe_rules_exclude: None,
|
||||||
json: false,
|
json: false,
|
||||||
compact: false,
|
compact: false,
|
||||||
ignore: vec![],
|
|
||||||
}),
|
}),
|
||||||
..Flags::default()
|
..Flags::default()
|
||||||
}
|
}
|
||||||
|
@ -3799,17 +3816,19 @@ mod tests {
|
||||||
r.unwrap(),
|
r.unwrap(),
|
||||||
Flags {
|
Flags {
|
||||||
subcommand: DenoSubcommand::Lint(LintFlags {
|
subcommand: DenoSubcommand::Lint(LintFlags {
|
||||||
files: vec![
|
files: FileFlags {
|
||||||
|
include: vec![
|
||||||
PathBuf::from("script_1.ts"),
|
PathBuf::from("script_1.ts"),
|
||||||
PathBuf::from("script_2.ts")
|
PathBuf::from("script_2.ts")
|
||||||
],
|
],
|
||||||
|
ignore: vec![],
|
||||||
|
},
|
||||||
rules: false,
|
rules: false,
|
||||||
maybe_rules_tags: None,
|
maybe_rules_tags: None,
|
||||||
maybe_rules_include: None,
|
maybe_rules_include: None,
|
||||||
maybe_rules_exclude: None,
|
maybe_rules_exclude: None,
|
||||||
json: false,
|
json: false,
|
||||||
compact: false,
|
compact: false,
|
||||||
ignore: vec![],
|
|
||||||
}),
|
}),
|
||||||
watch: Some(vec![]),
|
watch: Some(vec![]),
|
||||||
..Flags::default()
|
..Flags::default()
|
||||||
|
@ -3828,17 +3847,19 @@ mod tests {
|
||||||
r.unwrap(),
|
r.unwrap(),
|
||||||
Flags {
|
Flags {
|
||||||
subcommand: DenoSubcommand::Lint(LintFlags {
|
subcommand: DenoSubcommand::Lint(LintFlags {
|
||||||
files: vec![
|
files: FileFlags {
|
||||||
|
include: vec![
|
||||||
PathBuf::from("script_1.ts"),
|
PathBuf::from("script_1.ts"),
|
||||||
PathBuf::from("script_2.ts")
|
PathBuf::from("script_2.ts")
|
||||||
],
|
],
|
||||||
|
ignore: vec![],
|
||||||
|
},
|
||||||
rules: false,
|
rules: false,
|
||||||
maybe_rules_tags: None,
|
maybe_rules_tags: None,
|
||||||
maybe_rules_include: None,
|
maybe_rules_include: None,
|
||||||
maybe_rules_exclude: None,
|
maybe_rules_exclude: None,
|
||||||
json: false,
|
json: false,
|
||||||
compact: false,
|
compact: false,
|
||||||
ignore: vec![],
|
|
||||||
}),
|
}),
|
||||||
watch: Some(vec![]),
|
watch: Some(vec![]),
|
||||||
no_clear_screen: true,
|
no_clear_screen: true,
|
||||||
|
@ -3852,17 +3873,19 @@ mod tests {
|
||||||
r.unwrap(),
|
r.unwrap(),
|
||||||
Flags {
|
Flags {
|
||||||
subcommand: DenoSubcommand::Lint(LintFlags {
|
subcommand: DenoSubcommand::Lint(LintFlags {
|
||||||
files: vec![],
|
files: FileFlags {
|
||||||
|
include: vec![],
|
||||||
|
ignore: vec![
|
||||||
|
PathBuf::from("script_1.ts"),
|
||||||
|
PathBuf::from("script_2.ts")
|
||||||
|
],
|
||||||
|
},
|
||||||
rules: false,
|
rules: false,
|
||||||
maybe_rules_tags: None,
|
maybe_rules_tags: None,
|
||||||
maybe_rules_include: None,
|
maybe_rules_include: None,
|
||||||
maybe_rules_exclude: None,
|
maybe_rules_exclude: None,
|
||||||
json: false,
|
json: false,
|
||||||
compact: false,
|
compact: false,
|
||||||
ignore: vec![
|
|
||||||
PathBuf::from("script_1.ts"),
|
|
||||||
PathBuf::from("script_2.ts")
|
|
||||||
],
|
|
||||||
}),
|
}),
|
||||||
..Flags::default()
|
..Flags::default()
|
||||||
}
|
}
|
||||||
|
@ -3873,14 +3896,16 @@ mod tests {
|
||||||
r.unwrap(),
|
r.unwrap(),
|
||||||
Flags {
|
Flags {
|
||||||
subcommand: DenoSubcommand::Lint(LintFlags {
|
subcommand: DenoSubcommand::Lint(LintFlags {
|
||||||
files: vec![],
|
files: FileFlags {
|
||||||
|
include: vec![],
|
||||||
|
ignore: vec![],
|
||||||
|
},
|
||||||
rules: true,
|
rules: true,
|
||||||
maybe_rules_tags: None,
|
maybe_rules_tags: None,
|
||||||
maybe_rules_include: None,
|
maybe_rules_include: None,
|
||||||
maybe_rules_exclude: None,
|
maybe_rules_exclude: None,
|
||||||
json: false,
|
json: false,
|
||||||
compact: false,
|
compact: false,
|
||||||
ignore: vec![],
|
|
||||||
}),
|
}),
|
||||||
..Flags::default()
|
..Flags::default()
|
||||||
}
|
}
|
||||||
|
@ -3897,14 +3922,16 @@ mod tests {
|
||||||
r.unwrap(),
|
r.unwrap(),
|
||||||
Flags {
|
Flags {
|
||||||
subcommand: DenoSubcommand::Lint(LintFlags {
|
subcommand: DenoSubcommand::Lint(LintFlags {
|
||||||
files: vec![],
|
files: FileFlags {
|
||||||
|
include: vec![],
|
||||||
|
ignore: vec![],
|
||||||
|
},
|
||||||
rules: false,
|
rules: false,
|
||||||
maybe_rules_tags: Some(svec![""]),
|
maybe_rules_tags: Some(svec![""]),
|
||||||
maybe_rules_include: Some(svec!["ban-untagged-todo", "no-undef"]),
|
maybe_rules_include: Some(svec!["ban-untagged-todo", "no-undef"]),
|
||||||
maybe_rules_exclude: Some(svec!["no-const-assign"]),
|
maybe_rules_exclude: Some(svec!["no-const-assign"]),
|
||||||
json: false,
|
json: false,
|
||||||
compact: false,
|
compact: false,
|
||||||
ignore: vec![],
|
|
||||||
}),
|
}),
|
||||||
..Flags::default()
|
..Flags::default()
|
||||||
}
|
}
|
||||||
|
@ -3915,14 +3942,16 @@ mod tests {
|
||||||
r.unwrap(),
|
r.unwrap(),
|
||||||
Flags {
|
Flags {
|
||||||
subcommand: DenoSubcommand::Lint(LintFlags {
|
subcommand: DenoSubcommand::Lint(LintFlags {
|
||||||
files: vec![PathBuf::from("script_1.ts")],
|
files: FileFlags {
|
||||||
|
include: vec![PathBuf::from("script_1.ts")],
|
||||||
|
ignore: vec![],
|
||||||
|
},
|
||||||
rules: false,
|
rules: false,
|
||||||
maybe_rules_tags: None,
|
maybe_rules_tags: None,
|
||||||
maybe_rules_include: None,
|
maybe_rules_include: None,
|
||||||
maybe_rules_exclude: None,
|
maybe_rules_exclude: None,
|
||||||
json: true,
|
json: true,
|
||||||
compact: false,
|
compact: false,
|
||||||
ignore: vec![],
|
|
||||||
}),
|
}),
|
||||||
..Flags::default()
|
..Flags::default()
|
||||||
}
|
}
|
||||||
|
@ -3940,14 +3969,16 @@ mod tests {
|
||||||
r.unwrap(),
|
r.unwrap(),
|
||||||
Flags {
|
Flags {
|
||||||
subcommand: DenoSubcommand::Lint(LintFlags {
|
subcommand: DenoSubcommand::Lint(LintFlags {
|
||||||
files: vec![PathBuf::from("script_1.ts")],
|
files: FileFlags {
|
||||||
|
include: vec![PathBuf::from("script_1.ts")],
|
||||||
|
ignore: vec![],
|
||||||
|
},
|
||||||
rules: false,
|
rules: false,
|
||||||
maybe_rules_tags: None,
|
maybe_rules_tags: None,
|
||||||
maybe_rules_include: None,
|
maybe_rules_include: None,
|
||||||
maybe_rules_exclude: None,
|
maybe_rules_exclude: None,
|
||||||
json: true,
|
json: true,
|
||||||
compact: false,
|
compact: false,
|
||||||
ignore: vec![],
|
|
||||||
}),
|
}),
|
||||||
config_flag: ConfigFlag::Path("Deno.jsonc".to_string()),
|
config_flag: ConfigFlag::Path("Deno.jsonc".to_string()),
|
||||||
..Flags::default()
|
..Flags::default()
|
||||||
|
@ -3966,14 +3997,16 @@ mod tests {
|
||||||
r.unwrap(),
|
r.unwrap(),
|
||||||
Flags {
|
Flags {
|
||||||
subcommand: DenoSubcommand::Lint(LintFlags {
|
subcommand: DenoSubcommand::Lint(LintFlags {
|
||||||
files: vec![PathBuf::from("script_1.ts")],
|
files: FileFlags {
|
||||||
|
include: vec![PathBuf::from("script_1.ts")],
|
||||||
|
ignore: vec![],
|
||||||
|
},
|
||||||
rules: false,
|
rules: false,
|
||||||
maybe_rules_tags: None,
|
maybe_rules_tags: None,
|
||||||
maybe_rules_include: None,
|
maybe_rules_include: None,
|
||||||
maybe_rules_exclude: None,
|
maybe_rules_exclude: None,
|
||||||
json: false,
|
json: false,
|
||||||
compact: true,
|
compact: true,
|
||||||
ignore: vec![],
|
|
||||||
}),
|
}),
|
||||||
config_flag: ConfigFlag::Path("Deno.jsonc".to_string()),
|
config_flag: ConfigFlag::Path("Deno.jsonc".to_string()),
|
||||||
..Flags::default()
|
..Flags::default()
|
||||||
|
@ -5510,10 +5543,12 @@ mod tests {
|
||||||
fail_fast: None,
|
fail_fast: None,
|
||||||
filter: Some("- foo".to_string()),
|
filter: Some("- foo".to_string()),
|
||||||
allow_none: true,
|
allow_none: true,
|
||||||
include: svec!["dir1/", "dir2/"],
|
files: FileFlags {
|
||||||
|
include: vec![PathBuf::from("dir1/"), PathBuf::from("dir2/")],
|
||||||
ignore: vec![],
|
ignore: vec![],
|
||||||
|
},
|
||||||
shuffle: None,
|
shuffle: None,
|
||||||
concurrent_jobs: NonZeroUsize::new(1).unwrap(),
|
concurrent_jobs: None,
|
||||||
trace_ops: true,
|
trace_ops: true,
|
||||||
}),
|
}),
|
||||||
unstable: true,
|
unstable: true,
|
||||||
|
@ -5582,9 +5617,11 @@ mod tests {
|
||||||
filter: None,
|
filter: None,
|
||||||
allow_none: false,
|
allow_none: false,
|
||||||
shuffle: None,
|
shuffle: None,
|
||||||
|
files: FileFlags {
|
||||||
include: vec![],
|
include: vec![],
|
||||||
ignore: vec![],
|
ignore: vec![],
|
||||||
concurrent_jobs: NonZeroUsize::new(4).unwrap(),
|
},
|
||||||
|
concurrent_jobs: Some(NonZeroUsize::new(4).unwrap()),
|
||||||
trace_ops: false,
|
trace_ops: false,
|
||||||
}),
|
}),
|
||||||
type_check_mode: TypeCheckMode::Local,
|
type_check_mode: TypeCheckMode::Local,
|
||||||
|
@ -5610,9 +5647,11 @@ mod tests {
|
||||||
filter: None,
|
filter: None,
|
||||||
allow_none: false,
|
allow_none: false,
|
||||||
shuffle: None,
|
shuffle: None,
|
||||||
|
files: FileFlags {
|
||||||
include: vec![],
|
include: vec![],
|
||||||
ignore: vec![],
|
ignore: vec![],
|
||||||
concurrent_jobs: NonZeroUsize::new(1).unwrap(),
|
},
|
||||||
|
concurrent_jobs: None,
|
||||||
trace_ops: false,
|
trace_ops: false,
|
||||||
}),
|
}),
|
||||||
type_check_mode: TypeCheckMode::Local,
|
type_check_mode: TypeCheckMode::Local,
|
||||||
|
@ -5642,9 +5681,11 @@ mod tests {
|
||||||
filter: None,
|
filter: None,
|
||||||
allow_none: false,
|
allow_none: false,
|
||||||
shuffle: None,
|
shuffle: None,
|
||||||
|
files: FileFlags {
|
||||||
include: vec![],
|
include: vec![],
|
||||||
ignore: vec![],
|
ignore: vec![],
|
||||||
concurrent_jobs: NonZeroUsize::new(1).unwrap(),
|
},
|
||||||
|
concurrent_jobs: None,
|
||||||
trace_ops: false,
|
trace_ops: false,
|
||||||
}),
|
}),
|
||||||
no_prompt: true,
|
no_prompt: true,
|
||||||
|
@ -5668,9 +5709,11 @@ mod tests {
|
||||||
filter: None,
|
filter: None,
|
||||||
allow_none: false,
|
allow_none: false,
|
||||||
shuffle: Some(1),
|
shuffle: Some(1),
|
||||||
|
files: FileFlags {
|
||||||
include: vec![],
|
include: vec![],
|
||||||
ignore: vec![],
|
ignore: vec![],
|
||||||
concurrent_jobs: NonZeroUsize::new(1).unwrap(),
|
},
|
||||||
|
concurrent_jobs: None,
|
||||||
trace_ops: false,
|
trace_ops: false,
|
||||||
}),
|
}),
|
||||||
no_prompt: true,
|
no_prompt: true,
|
||||||
|
@ -5694,9 +5737,38 @@ mod tests {
|
||||||
filter: None,
|
filter: None,
|
||||||
allow_none: false,
|
allow_none: false,
|
||||||
shuffle: None,
|
shuffle: None,
|
||||||
|
files: FileFlags {
|
||||||
include: vec![],
|
include: vec![],
|
||||||
ignore: vec![],
|
ignore: vec![],
|
||||||
concurrent_jobs: NonZeroUsize::new(1).unwrap(),
|
},
|
||||||
|
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,
|
trace_ops: false,
|
||||||
}),
|
}),
|
||||||
no_prompt: true,
|
no_prompt: true,
|
||||||
|
@ -5721,9 +5793,11 @@ mod tests {
|
||||||
filter: None,
|
filter: None,
|
||||||
allow_none: false,
|
allow_none: false,
|
||||||
shuffle: None,
|
shuffle: None,
|
||||||
|
files: FileFlags {
|
||||||
include: vec![],
|
include: vec![],
|
||||||
ignore: vec![],
|
ignore: vec![],
|
||||||
concurrent_jobs: NonZeroUsize::new(1).unwrap(),
|
},
|
||||||
|
concurrent_jobs: None,
|
||||||
trace_ops: false,
|
trace_ops: false,
|
||||||
}),
|
}),
|
||||||
watch: Some(vec![]),
|
watch: Some(vec![]),
|
||||||
|
@ -6372,8 +6446,10 @@ mod tests {
|
||||||
Flags {
|
Flags {
|
||||||
subcommand: DenoSubcommand::Bench(BenchFlags {
|
subcommand: DenoSubcommand::Bench(BenchFlags {
|
||||||
filter: Some("- foo".to_string()),
|
filter: Some("- foo".to_string()),
|
||||||
include: Some(svec!["dir1/", "dir2/"]),
|
files: FileFlags {
|
||||||
|
include: vec![PathBuf::from("dir1/"), PathBuf::from("dir2/")],
|
||||||
ignore: vec![],
|
ignore: vec![],
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
unstable: true,
|
unstable: true,
|
||||||
type_check_mode: TypeCheckMode::Local,
|
type_check_mode: TypeCheckMode::Local,
|
||||||
|
@ -6386,6 +6462,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]
|
#[test]
|
||||||
fn run_with_check() {
|
fn run_with_check() {
|
||||||
let r = flags_from_vec(svec!["deno", "run", "--check", "script.ts",]);
|
let r = flags_from_vec(svec!["deno", "run", "--check", "script.ts",]);
|
||||||
|
|
368
cli/args/mod.rs
368
cli/args/mod.rs
|
@ -10,23 +10,15 @@ pub use config_file::BenchConfig;
|
||||||
pub use config_file::CompilerOptions;
|
pub use config_file::CompilerOptions;
|
||||||
pub use config_file::ConfigFile;
|
pub use config_file::ConfigFile;
|
||||||
pub use config_file::EmitConfigOptions;
|
pub use config_file::EmitConfigOptions;
|
||||||
pub use config_file::FmtConfig;
|
pub use config_file::FilesConfig;
|
||||||
pub use config_file::FmtOptionsConfig;
|
pub use config_file::FmtOptionsConfig;
|
||||||
pub use config_file::IgnoredCompilerOptions;
|
|
||||||
pub use config_file::JsxImportSourceConfig;
|
pub use config_file::JsxImportSourceConfig;
|
||||||
pub use config_file::LintConfig;
|
|
||||||
pub use config_file::LintRulesConfig;
|
pub use config_file::LintRulesConfig;
|
||||||
pub use config_file::MaybeImportsResult;
|
|
||||||
pub use config_file::ProseWrap;
|
pub use config_file::ProseWrap;
|
||||||
pub use config_file::TestConfig;
|
|
||||||
pub use config_file::TsConfig;
|
pub use config_file::TsConfig;
|
||||||
pub use config_file::TsConfigForEmit;
|
pub use config_file::TsConfigForEmit;
|
||||||
pub use config_file::TsConfigType;
|
pub use config_file::TsConfigType;
|
||||||
pub use config_file::TsTypeLib;
|
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 flags::*;
|
||||||
pub use lockfile::Lockfile;
|
pub use lockfile::Lockfile;
|
||||||
pub use lockfile::LockfileError;
|
pub use lockfile::LockfileError;
|
||||||
|
@ -40,13 +32,18 @@ use deno_core::normalize_path;
|
||||||
use deno_core::parking_lot::Mutex;
|
use deno_core::parking_lot::Mutex;
|
||||||
use deno_core::url::Url;
|
use deno_core::url::Url;
|
||||||
use deno_runtime::colors;
|
use deno_runtime::colors;
|
||||||
|
use deno_runtime::deno_tls::rustls;
|
||||||
use deno_runtime::deno_tls::rustls::RootCertStore;
|
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::inspector_server::InspectorServer;
|
||||||
use deno_runtime::permissions::PermissionsOptions;
|
use deno_runtime::permissions::PermissionsOptions;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::io::BufReader;
|
use std::io::BufReader;
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
|
use std::num::NonZeroUsize;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
@ -54,6 +51,11 @@ use crate::cache::DenoDir;
|
||||||
use crate::util::fs::canonicalize_path_maybe_not_exists;
|
use crate::util::fs::canonicalize_path_maybe_not_exists;
|
||||||
use crate::version;
|
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.
|
/// Indicates how cached source files should be handled.
|
||||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||||
pub enum CacheSetting {
|
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
|
/// Create and populate a root cert store based on the passed options and
|
||||||
/// environment.
|
/// environment.
|
||||||
pub fn get_root_cert_store(
|
pub fn get_root_cert_store(
|
||||||
|
@ -394,36 +664,57 @@ impl CliOptions {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_lint_config(&self) -> Result<Option<LintConfig>, AnyError> {
|
pub fn get_maybe_config_file(&self) -> &Option<ConfigFile> {
|
||||||
if let Some(config_file) = &self.maybe_config_file {
|
&self.maybe_config_file
|
||||||
config_file.to_lint_config()
|
|
||||||
} else {
|
|
||||||
Ok(None)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_test_config(&self) -> Result<Option<TestConfig>, AnyError> {
|
pub fn resolve_fmt_options(
|
||||||
if let Some(config_file) = &self.maybe_config_file {
|
&self,
|
||||||
config_file.to_test_config()
|
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 {
|
} else {
|
||||||
Ok(None)
|
None
|
||||||
}
|
};
|
||||||
|
FmtOptions::resolve(maybe_fmt_config, Some(fmt_flags))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_bench_config(&self) -> Result<Option<BenchConfig>, AnyError> {
|
pub fn resolve_lint_options(
|
||||||
if let Some(config_file) = &self.maybe_config_file {
|
&self,
|
||||||
config_file.to_bench_config()
|
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 {
|
} else {
|
||||||
Ok(None)
|
None
|
||||||
}
|
};
|
||||||
|
LintOptions::resolve(maybe_lint_config, Some(lint_flags))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_fmt_config(&self) -> Result<Option<FmtConfig>, AnyError> {
|
pub fn resolve_test_options(
|
||||||
if let Some(config) = &self.maybe_config_file {
|
&self,
|
||||||
config.to_fmt_config()
|
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 {
|
} else {
|
||||||
Ok(None)
|
None
|
||||||
|
};
|
||||||
|
TestOptions::resolve(maybe_test_config, Some(test_flags))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
BenchOptions::resolve(maybe_bench_config, Some(bench_flags))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Vector of user script CLI arguments.
|
/// Vector of user script CLI arguments.
|
||||||
|
@ -639,6 +930,25 @@ fn resolve_import_map_specifier(
|
||||||
Ok(None)
|
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.
|
/// Resolves the no_prompt value based on the cli flags and environment.
|
||||||
pub fn resolve_no_prompt(flags: &Flags) -> bool {
|
pub fn resolve_no_prompt(flags: &Flags) -> bool {
|
||||||
flags.no_prompt || {
|
flags.no_prompt || {
|
||||||
|
|
|
@ -5,9 +5,7 @@ use super::documents::Documents;
|
||||||
use super::language_server;
|
use super::language_server;
|
||||||
use super::tsc;
|
use super::tsc;
|
||||||
|
|
||||||
use crate::args::LintConfig;
|
|
||||||
use crate::tools::lint::create_linter;
|
use crate::tools::lint::create_linter;
|
||||||
use crate::tools::lint::get_configured_rules;
|
|
||||||
|
|
||||||
use deno_ast::SourceRange;
|
use deno_ast::SourceRange;
|
||||||
use deno_ast::SourceRangedForSpanned;
|
use deno_ast::SourceRangedForSpanned;
|
||||||
|
@ -18,10 +16,12 @@ use deno_core::error::AnyError;
|
||||||
use deno_core::serde::Deserialize;
|
use deno_core::serde::Deserialize;
|
||||||
use deno_core::serde_json::json;
|
use deno_core::serde_json::json;
|
||||||
use deno_core::ModuleSpecifier;
|
use deno_core::ModuleSpecifier;
|
||||||
|
use deno_lint::rules::LintRule;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::sync::Arc;
|
||||||
use tower_lsp::lsp_types as lsp;
|
use tower_lsp::lsp_types as lsp;
|
||||||
use tower_lsp::lsp_types::Position;
|
use tower_lsp::lsp_types::Position;
|
||||||
use tower_lsp::lsp_types::Range;
|
use tower_lsp::lsp_types::Range;
|
||||||
|
@ -127,9 +127,8 @@ fn as_lsp_range(range: &deno_lint::diagnostic::Range) -> Range {
|
||||||
|
|
||||||
pub fn get_lint_references(
|
pub fn get_lint_references(
|
||||||
parsed_source: &deno_ast::ParsedSource,
|
parsed_source: &deno_ast::ParsedSource,
|
||||||
maybe_lint_config: Option<&LintConfig>,
|
lint_rules: Vec<Arc<dyn LintRule>>,
|
||||||
) -> Result<Vec<Reference>, AnyError> {
|
) -> Result<Vec<Reference>, AnyError> {
|
||||||
let lint_rules = get_configured_rules(maybe_lint_config, None, None, None)?;
|
|
||||||
let linter = create_linter(parsed_source.media_type(), lint_rules);
|
let linter = create_linter(parsed_source.media_type(), lint_rules);
|
||||||
let lint_diagnostics = linter.lint_with_ast(parsed_source);
|
let lint_diagnostics = linter.lint_with_ast(parsed_source);
|
||||||
|
|
||||||
|
|
|
@ -12,8 +12,9 @@ use super::performance::Performance;
|
||||||
use super::tsc;
|
use super::tsc;
|
||||||
use super::tsc::TsServer;
|
use super::tsc::TsServer;
|
||||||
|
|
||||||
use crate::args::LintConfig;
|
use crate::args::LintOptions;
|
||||||
use crate::npm::NpmPackageReference;
|
use crate::npm::NpmPackageReference;
|
||||||
|
use crate::tools::lint::get_configured_rules;
|
||||||
|
|
||||||
use deno_ast::MediaType;
|
use deno_ast::MediaType;
|
||||||
use deno_core::anyhow::anyhow;
|
use deno_core::anyhow::anyhow;
|
||||||
|
@ -24,6 +25,7 @@ use deno_core::serde_json;
|
||||||
use deno_core::serde_json::json;
|
use deno_core::serde_json::json;
|
||||||
use deno_core::ModuleSpecifier;
|
use deno_core::ModuleSpecifier;
|
||||||
use deno_graph::Resolved;
|
use deno_graph::Resolved;
|
||||||
|
use deno_lint::rules::LintRule;
|
||||||
use deno_runtime::tokio_util::create_basic_runtime;
|
use deno_runtime::tokio_util::create_basic_runtime;
|
||||||
use log::error;
|
use log::error;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
@ -36,7 +38,7 @@ use tokio_util::sync::CancellationToken;
|
||||||
use tower_lsp::lsp_types as lsp;
|
use tower_lsp::lsp_types as lsp;
|
||||||
|
|
||||||
pub type SnapshotForDiagnostics =
|
pub type SnapshotForDiagnostics =
|
||||||
(Arc<StateSnapshot>, Arc<ConfigSnapshot>, Option<LintConfig>);
|
(Arc<StateSnapshot>, Arc<ConfigSnapshot>, LintOptions);
|
||||||
pub type DiagnosticRecord =
|
pub type DiagnosticRecord =
|
||||||
(ModuleSpecifier, Option<i32>, Vec<lsp::Diagnostic>);
|
(ModuleSpecifier, Option<i32>, Vec<lsp::Diagnostic>);
|
||||||
pub type DiagnosticVec = Vec<DiagnosticRecord>;
|
pub type DiagnosticVec = Vec<DiagnosticRecord>;
|
||||||
|
@ -198,7 +200,7 @@ impl DiagnosticsServer {
|
||||||
match rx.recv().await {
|
match rx.recv().await {
|
||||||
// channel has closed
|
// channel has closed
|
||||||
None => break,
|
None => break,
|
||||||
Some((snapshot, config, maybe_lint_config)) => {
|
Some((snapshot, config, lint_options)) => {
|
||||||
// cancel the previous run
|
// cancel the previous run
|
||||||
token.cancel();
|
token.cancel();
|
||||||
token = CancellationToken::new();
|
token = CancellationToken::new();
|
||||||
|
@ -300,7 +302,7 @@ impl DiagnosticsServer {
|
||||||
let diagnostics = generate_lint_diagnostics(
|
let diagnostics = generate_lint_diagnostics(
|
||||||
&snapshot,
|
&snapshot,
|
||||||
&config,
|
&config,
|
||||||
maybe_lint_config,
|
&lint_options,
|
||||||
token.clone(),
|
token.clone(),
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
@ -443,12 +445,12 @@ fn ts_json_to_diagnostics(
|
||||||
async fn generate_lint_diagnostics(
|
async fn generate_lint_diagnostics(
|
||||||
snapshot: &language_server::StateSnapshot,
|
snapshot: &language_server::StateSnapshot,
|
||||||
config: &ConfigSnapshot,
|
config: &ConfigSnapshot,
|
||||||
maybe_lint_config: Option<LintConfig>,
|
lint_options: &LintOptions,
|
||||||
token: CancellationToken,
|
token: CancellationToken,
|
||||||
) -> DiagnosticVec {
|
) -> DiagnosticVec {
|
||||||
let documents = snapshot.documents.documents(true, true);
|
let documents = snapshot.documents.documents(true, true);
|
||||||
let workspace_settings = config.settings.workspace.clone();
|
let workspace_settings = config.settings.workspace.clone();
|
||||||
|
let lint_rules = get_configured_rules(lint_options.rules.clone());
|
||||||
let mut diagnostics_vec = Vec::new();
|
let mut diagnostics_vec = Vec::new();
|
||||||
if workspace_settings.lint {
|
if workspace_settings.lint {
|
||||||
for document in documents {
|
for document in documents {
|
||||||
|
@ -470,7 +472,8 @@ async fn generate_lint_diagnostics(
|
||||||
version,
|
version,
|
||||||
generate_document_lint_diagnostics(
|
generate_document_lint_diagnostics(
|
||||||
config,
|
config,
|
||||||
&maybe_lint_config,
|
lint_options,
|
||||||
|
lint_rules.clone(),
|
||||||
&document,
|
&document,
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
|
@ -481,23 +484,21 @@ async fn generate_lint_diagnostics(
|
||||||
|
|
||||||
fn generate_document_lint_diagnostics(
|
fn generate_document_lint_diagnostics(
|
||||||
config: &ConfigSnapshot,
|
config: &ConfigSnapshot,
|
||||||
maybe_lint_config: &Option<LintConfig>,
|
lint_options: &LintOptions,
|
||||||
|
lint_rules: Vec<Arc<dyn LintRule>>,
|
||||||
document: &Document,
|
document: &Document,
|
||||||
) -> Vec<lsp::Diagnostic> {
|
) -> Vec<lsp::Diagnostic> {
|
||||||
if !config.specifier_enabled(document.specifier()) {
|
if !config.specifier_enabled(document.specifier()) {
|
||||||
return Vec::new();
|
return Vec::new();
|
||||||
}
|
}
|
||||||
if let Some(lint_config) = &maybe_lint_config {
|
if !lint_options.files.matches_specifier(document.specifier()) {
|
||||||
if !lint_config.files.matches_specifier(document.specifier()) {
|
|
||||||
return Vec::new();
|
return Vec::new();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
match document.maybe_parsed_source() {
|
match document.maybe_parsed_source() {
|
||||||
Some(Ok(parsed_source)) => {
|
Some(Ok(parsed_source)) => {
|
||||||
if let Ok(references) = analysis::get_lint_references(
|
if let Ok(references) =
|
||||||
&parsed_source,
|
analysis::get_lint_references(&parsed_source, lint_rules)
|
||||||
maybe_lint_config.as_ref(),
|
{
|
||||||
) {
|
|
||||||
references
|
references
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|r| r.to_diagnostic())
|
.map(|r| r.to_diagnostic())
|
||||||
|
@ -1080,7 +1081,7 @@ let c: number = "a";
|
||||||
let diagnostics = generate_lint_diagnostics(
|
let diagnostics = generate_lint_diagnostics(
|
||||||
&snapshot,
|
&snapshot,
|
||||||
&enabled_config,
|
&enabled_config,
|
||||||
None,
|
&Default::default(),
|
||||||
Default::default(),
|
Default::default(),
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
@ -1121,7 +1122,7 @@ let c: number = "a";
|
||||||
let diagnostics = generate_lint_diagnostics(
|
let diagnostics = generate_lint_diagnostics(
|
||||||
&snapshot,
|
&snapshot,
|
||||||
&disabled_config,
|
&disabled_config,
|
||||||
None,
|
&Default::default(),
|
||||||
Default::default(),
|
Default::default(),
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
|
|
@ -62,8 +62,8 @@ use crate::args::CacheSetting;
|
||||||
use crate::args::CliOptions;
|
use crate::args::CliOptions;
|
||||||
use crate::args::ConfigFile;
|
use crate::args::ConfigFile;
|
||||||
use crate::args::Flags;
|
use crate::args::Flags;
|
||||||
use crate::args::FmtConfig;
|
use crate::args::FmtOptions;
|
||||||
use crate::args::LintConfig;
|
use crate::args::LintOptions;
|
||||||
use crate::args::TsConfig;
|
use crate::args::TsConfig;
|
||||||
use crate::cache::DenoDir;
|
use crate::cache::DenoDir;
|
||||||
use crate::file_fetcher::get_source_from_data_url;
|
use crate::file_fetcher::get_source_from_data_url;
|
||||||
|
@ -122,14 +122,14 @@ pub struct Inner {
|
||||||
/// An optional configuration file which has been specified in the client
|
/// An optional configuration file which has been specified in the client
|
||||||
/// options.
|
/// options.
|
||||||
maybe_config_file: Option<ConfigFile>,
|
maybe_config_file: Option<ConfigFile>,
|
||||||
/// An optional configuration for formatter which has been taken from specified config file.
|
|
||||||
maybe_fmt_config: Option<FmtConfig>,
|
|
||||||
/// An optional import map which is used to resolve modules.
|
/// An optional import map which is used to resolve modules.
|
||||||
pub maybe_import_map: Option<Arc<ImportMap>>,
|
pub maybe_import_map: Option<Arc<ImportMap>>,
|
||||||
/// The URL for the import map which is used to determine relative imports.
|
/// The URL for the import map which is used to determine relative imports.
|
||||||
maybe_import_map_uri: Option<Url>,
|
maybe_import_map_uri: Option<Url>,
|
||||||
|
/// Configuration for formatter which has been taken from specified config file.
|
||||||
|
fmt_options: FmtOptions,
|
||||||
/// An optional configuration for linter which has been taken from specified config file.
|
/// An optional configuration for linter which has been taken from specified config file.
|
||||||
pub maybe_lint_config: Option<LintConfig>,
|
lint_options: LintOptions,
|
||||||
/// A lazily create "server" for handling test run requests.
|
/// A lazily create "server" for handling test run requests.
|
||||||
maybe_testing_server: Option<testing::TestServer>,
|
maybe_testing_server: Option<testing::TestServer>,
|
||||||
/// Resolver for npm packages.
|
/// Resolver for npm packages.
|
||||||
|
@ -347,8 +347,8 @@ impl Inner {
|
||||||
maybe_config_file: None,
|
maybe_config_file: None,
|
||||||
maybe_import_map: None,
|
maybe_import_map: None,
|
||||||
maybe_import_map_uri: None,
|
maybe_import_map_uri: None,
|
||||||
maybe_lint_config: None,
|
fmt_options: Default::default(),
|
||||||
maybe_fmt_config: None,
|
lint_options: Default::default(),
|
||||||
maybe_testing_server: None,
|
maybe_testing_server: None,
|
||||||
module_registries,
|
module_registries,
|
||||||
module_registries_location,
|
module_registries_location,
|
||||||
|
@ -713,26 +713,30 @@ impl Inner {
|
||||||
|
|
||||||
fn update_config_file(&mut self) -> Result<(), AnyError> {
|
fn update_config_file(&mut self) -> Result<(), AnyError> {
|
||||||
self.maybe_config_file = None;
|
self.maybe_config_file = None;
|
||||||
self.maybe_fmt_config = None;
|
self.fmt_options = Default::default();
|
||||||
self.maybe_lint_config = None;
|
self.lint_options = Default::default();
|
||||||
|
|
||||||
if let Some(config_file) = self.get_config_file()? {
|
if let Some(config_file) = self.get_config_file()? {
|
||||||
let lint_config = config_file
|
let lint_options = config_file
|
||||||
.to_lint_config()
|
.to_lint_config()
|
||||||
|
.and_then(|maybe_lint_config| {
|
||||||
|
LintOptions::resolve(maybe_lint_config, None)
|
||||||
|
})
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
anyhow!("Unable to update lint configuration: {:?}", err)
|
anyhow!("Unable to update lint configuration: {:?}", err)
|
||||||
})?
|
})?;
|
||||||
.unwrap_or_default();
|
let fmt_options = config_file
|
||||||
let fmt_config = config_file
|
|
||||||
.to_fmt_config()
|
.to_fmt_config()
|
||||||
|
.and_then(|maybe_fmt_config| {
|
||||||
|
FmtOptions::resolve(maybe_fmt_config, None)
|
||||||
|
})
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
anyhow!("Unable to update formatter configuration: {:?}", err)
|
anyhow!("Unable to update formatter configuration: {:?}", err)
|
||||||
})?
|
})?;
|
||||||
.unwrap_or_default();
|
|
||||||
|
|
||||||
self.maybe_config_file = Some(config_file);
|
self.maybe_config_file = Some(config_file);
|
||||||
self.maybe_lint_config = Some(lint_config);
|
self.lint_options = lint_options;
|
||||||
self.maybe_fmt_config = Some(fmt_config);
|
self.fmt_options = fmt_options;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -1196,19 +1200,14 @@ impl Inner {
|
||||||
LspError::invalid_request()
|
LspError::invalid_request()
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let fmt_options = if let Some(fmt_config) = self.maybe_fmt_config.as_ref() {
|
|
||||||
// skip formatting any files ignored by the config file
|
// skip formatting any files ignored by the config file
|
||||||
if !fmt_config.files.matches_specifier(&specifier) {
|
if !self.fmt_options.files.matches_specifier(&specifier) {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
fmt_config.options.clone()
|
|
||||||
} else {
|
|
||||||
Default::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
let format_result = match document.maybe_parsed_source() {
|
let format_result = match document.maybe_parsed_source() {
|
||||||
Some(Ok(parsed_source)) => {
|
Some(Ok(parsed_source)) => {
|
||||||
format_parsed_source(&parsed_source, fmt_options)
|
format_parsed_source(&parsed_source, &self.fmt_options.options)
|
||||||
}
|
}
|
||||||
Some(Err(err)) => Err(anyhow!("{}", err)),
|
Some(Err(err)) => Err(anyhow!("{}", err)),
|
||||||
None => {
|
None => {
|
||||||
|
@ -1221,7 +1220,7 @@ impl Inner {
|
||||||
.map(|ext| file_path.with_extension(ext))
|
.map(|ext| file_path.with_extension(ext))
|
||||||
.unwrap_or(file_path);
|
.unwrap_or(file_path);
|
||||||
// it's not a js/ts file, so attempt to format its contents
|
// it's not a js/ts file, so attempt to format its contents
|
||||||
format_file(&file_path, &document.content(), &fmt_options)
|
format_file(&file_path, &document.content(), &self.fmt_options.options)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2521,7 +2520,7 @@ impl Inner {
|
||||||
let snapshot = (
|
let snapshot = (
|
||||||
self.snapshot(),
|
self.snapshot(),
|
||||||
self.config.snapshot(),
|
self.config.snapshot(),
|
||||||
self.maybe_lint_config.clone(),
|
self.lint_options.clone(),
|
||||||
);
|
);
|
||||||
if let Err(err) = self.diagnostics_server.update(snapshot) {
|
if let Err(err) = self.diagnostics_server.update(snapshot) {
|
||||||
error!("Cannot update diagnostics: {}", err);
|
error!("Cannot update diagnostics: {}", err);
|
||||||
|
|
|
@ -35,6 +35,7 @@ use deno_runtime::tokio_util::run_local;
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
use std::num::NonZeroUsize;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
|
@ -273,7 +274,13 @@ impl TestRun {
|
||||||
|
|
||||||
let (concurrent_jobs, fail_fast) =
|
let (concurrent_jobs, fail_fast) =
|
||||||
if let DenoSubcommand::Test(test_flags) = ps.options.sub_command() {
|
if let DenoSubcommand::Test(test_flags) = ps.options.sub_command() {
|
||||||
(test_flags.concurrent_jobs.into(), test_flags.fail_fast)
|
(
|
||||||
|
test_flags
|
||||||
|
.concurrent_jobs
|
||||||
|
.unwrap_or_else(|| NonZeroUsize::new(1).unwrap())
|
||||||
|
.into(),
|
||||||
|
test_flags.fail_fast,
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
unreachable!("Should always be Test subcommand.");
|
unreachable!("Should always be Test subcommand.");
|
||||||
};
|
};
|
||||||
|
|
37
cli/main.rs
37
cli/main.rs
|
@ -71,10 +71,13 @@ fn init_v8_flags(v8_flags: &[String]) {
|
||||||
async fn run_subcommand(flags: Flags) -> Result<i32, AnyError> {
|
async fn run_subcommand(flags: Flags) -> Result<i32, AnyError> {
|
||||||
match flags.subcommand.clone() {
|
match flags.subcommand.clone() {
|
||||||
DenoSubcommand::Bench(bench_flags) => {
|
DenoSubcommand::Bench(bench_flags) => {
|
||||||
if flags.watch.is_some() {
|
let cli_options = CliOptions::from_flags(flags)?;
|
||||||
tools::bench::run_benchmarks_with_watch(flags, bench_flags).await?;
|
let bench_options = cli_options.resolve_bench_options(bench_flags)?;
|
||||||
|
if cli_options.watch_paths().is_some() {
|
||||||
|
tools::bench::run_benchmarks_with_watch(cli_options, bench_options)
|
||||||
|
.await?;
|
||||||
} else {
|
} else {
|
||||||
tools::bench::run_benchmarks(flags, bench_flags).await?;
|
tools::bench::run_benchmarks(cli_options, bench_options).await?;
|
||||||
}
|
}
|
||||||
Ok(0)
|
Ok(0)
|
||||||
}
|
}
|
||||||
|
@ -109,19 +112,9 @@ async fn run_subcommand(flags: Flags) -> Result<i32, AnyError> {
|
||||||
Ok(0)
|
Ok(0)
|
||||||
}
|
}
|
||||||
DenoSubcommand::Fmt(fmt_flags) => {
|
DenoSubcommand::Fmt(fmt_flags) => {
|
||||||
let config = CliOptions::from_flags(flags)?;
|
let cli_options = CliOptions::from_flags(flags)?;
|
||||||
|
let fmt_options = cli_options.resolve_fmt_options(fmt_flags)?;
|
||||||
if fmt_flags.files.len() == 1
|
tools::fmt::format(cli_options, fmt_options).await?;
|
||||||
&& fmt_flags.files[0].to_string_lossy() == "-"
|
|
||||||
{
|
|
||||||
let maybe_fmt_config = config.to_fmt_config()?;
|
|
||||||
tools::fmt::format_stdin(
|
|
||||||
fmt_flags,
|
|
||||||
maybe_fmt_config.map(|c| c.options).unwrap_or_default(),
|
|
||||||
)?;
|
|
||||||
} else {
|
|
||||||
tools::fmt::format(&config, fmt_flags).await?;
|
|
||||||
}
|
|
||||||
Ok(0)
|
Ok(0)
|
||||||
}
|
}
|
||||||
DenoSubcommand::Init(init_flags) => {
|
DenoSubcommand::Init(init_flags) => {
|
||||||
|
@ -148,7 +141,9 @@ async fn run_subcommand(flags: Flags) -> Result<i32, AnyError> {
|
||||||
if lint_flags.rules {
|
if lint_flags.rules {
|
||||||
tools::lint::print_rules_list(lint_flags.json);
|
tools::lint::print_rules_list(lint_flags.json);
|
||||||
} else {
|
} else {
|
||||||
tools::lint::lint(flags, lint_flags).await?;
|
let cli_options = CliOptions::from_flags(flags)?;
|
||||||
|
let lint_options = cli_options.resolve_lint_options(lint_flags)?;
|
||||||
|
tools::lint::lint(cli_options, lint_options).await?;
|
||||||
}
|
}
|
||||||
Ok(0)
|
Ok(0)
|
||||||
}
|
}
|
||||||
|
@ -176,11 +171,13 @@ async fn run_subcommand(flags: Flags) -> Result<i32, AnyError> {
|
||||||
PathBuf::from(coverage_dir).canonicalize()?,
|
PathBuf::from(coverage_dir).canonicalize()?,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
let cli_options = CliOptions::from_flags(flags)?;
|
||||||
|
let test_options = cli_options.resolve_test_options(test_flags)?;
|
||||||
|
|
||||||
if flags.watch.is_some() {
|
if cli_options.watch_paths().is_some() {
|
||||||
tools::test::run_tests_with_watch(flags, test_flags).await?;
|
tools::test::run_tests_with_watch(cli_options, test_options).await?;
|
||||||
} else {
|
} else {
|
||||||
tools::test::run_tests(flags, test_flags).await?;
|
tools::test::run_tests(cli_options, test_options).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(0)
|
Ok(0)
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
use crate::args::BenchConfig;
|
use crate::args::BenchOptions;
|
||||||
use crate::args::BenchFlags;
|
use crate::args::CliOptions;
|
||||||
use crate::args::Flags;
|
|
||||||
use crate::args::TypeCheckMode;
|
use crate::args::TypeCheckMode;
|
||||||
use crate::colors;
|
use crate::colors;
|
||||||
use crate::graph_util::contains_specifier;
|
use crate::graph_util::contains_specifier;
|
||||||
|
@ -15,7 +14,6 @@ use crate::util::file_watcher;
|
||||||
use crate::util::file_watcher::ResolutionResult;
|
use crate::util::file_watcher::ResolutionResult;
|
||||||
use crate::util::fs::collect_specifiers;
|
use crate::util::fs::collect_specifiers;
|
||||||
use crate::util::path::is_supported_ext;
|
use crate::util::path::is_supported_ext;
|
||||||
use crate::util::path::specifier_to_file_path;
|
|
||||||
use crate::worker::create_main_worker_for_test_or_bench;
|
use crate::worker::create_main_worker_for_test_or_bench;
|
||||||
|
|
||||||
use deno_core::error::generic_error;
|
use deno_core::error::generic_error;
|
||||||
|
@ -37,6 +35,7 @@ use serde::Serialize;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
use std::sync::Arc;
|
||||||
use tokio::sync::mpsc::unbounded_channel;
|
use tokio::sync::mpsc::unbounded_channel;
|
||||||
use tokio::sync::mpsc::UnboundedSender;
|
use tokio::sync::mpsc::UnboundedSender;
|
||||||
|
|
||||||
|
@ -487,24 +486,18 @@ fn is_supported_bench_path(path: &Path) -> bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn run_benchmarks(
|
pub async fn run_benchmarks(
|
||||||
flags: Flags,
|
cli_options: CliOptions,
|
||||||
bench_flags: BenchFlags,
|
bench_options: BenchOptions,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), AnyError> {
|
||||||
let ps = ProcState::build(flags).await?;
|
let ps = ProcState::from_options(Arc::new(cli_options)).await?;
|
||||||
// Various bench files should not share the same permissions in terms of
|
// Various bench files should not share the same permissions in terms of
|
||||||
// `PermissionsContainer` - otherwise granting/revoking permissions in one
|
// `PermissionsContainer` - otherwise granting/revoking permissions in one
|
||||||
// file would have impact on other files, which is undesirable.
|
// file would have impact on other files, which is undesirable.
|
||||||
let permissions =
|
let permissions =
|
||||||
Permissions::from_options(&ps.options.permissions_options())?;
|
Permissions::from_options(&ps.options.permissions_options())?;
|
||||||
|
|
||||||
let selection =
|
let specifiers =
|
||||||
collect_include_ignore(&bench_flags, ps.options.to_bench_config()?);
|
collect_specifiers(&bench_options.files, is_supported_bench_path)?;
|
||||||
|
|
||||||
let specifiers = collect_specifiers(
|
|
||||||
selection.include,
|
|
||||||
&selection.ignore,
|
|
||||||
is_supported_bench_path,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
if specifiers.is_empty() {
|
if specifiers.is_empty() {
|
||||||
return Err(generic_error("No bench modules found"));
|
return Err(generic_error("No bench modules found"));
|
||||||
|
@ -517,7 +510,7 @@ pub async fn run_benchmarks(
|
||||||
permissions,
|
permissions,
|
||||||
specifiers,
|
specifiers,
|
||||||
BenchSpecifierOptions {
|
BenchSpecifierOptions {
|
||||||
filter: bench_flags.filter,
|
filter: bench_options.filter,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
@ -527,21 +520,22 @@ pub async fn run_benchmarks(
|
||||||
|
|
||||||
// TODO(bartlomieju): heavy duplication of code with `cli/tools/test.rs`
|
// TODO(bartlomieju): heavy duplication of code with `cli/tools/test.rs`
|
||||||
pub async fn run_benchmarks_with_watch(
|
pub async fn run_benchmarks_with_watch(
|
||||||
flags: Flags,
|
cli_options: CliOptions,
|
||||||
bench_flags: BenchFlags,
|
bench_options: BenchOptions,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), AnyError> {
|
||||||
let ps = ProcState::build(flags).await?;
|
let ps = ProcState::from_options(Arc::new(cli_options)).await?;
|
||||||
// Various bench files should not share the same permissions in terms of
|
// Various bench files should not share the same permissions in terms of
|
||||||
// `PermissionsContainer` - otherwise granting/revoking permissions in one
|
// `PermissionsContainer` - otherwise granting/revoking permissions in one
|
||||||
// file would have impact on other files, which is undesirable.
|
// file would have impact on other files, which is undesirable.
|
||||||
let permissions =
|
let permissions =
|
||||||
Permissions::from_options(&ps.options.permissions_options())?;
|
Permissions::from_options(&ps.options.permissions_options())?;
|
||||||
|
|
||||||
let selection =
|
let paths_to_watch: Vec<_> = bench_options
|
||||||
collect_include_ignore(&bench_flags, ps.options.to_bench_config()?);
|
.files
|
||||||
|
.include
|
||||||
let paths_to_watch: Vec<_> =
|
.iter()
|
||||||
selection.include.iter().map(PathBuf::from).collect();
|
.map(PathBuf::from)
|
||||||
|
.collect();
|
||||||
let no_check = ps.options.type_check_mode() == TypeCheckMode::None;
|
let no_check = ps.options.type_check_mode() == TypeCheckMode::None;
|
||||||
|
|
||||||
let resolver = |changed: Option<Vec<PathBuf>>| {
|
let resolver = |changed: Option<Vec<PathBuf>>| {
|
||||||
|
@ -549,13 +543,11 @@ pub async fn run_benchmarks_with_watch(
|
||||||
let paths_to_watch_clone = paths_to_watch.clone();
|
let paths_to_watch_clone = paths_to_watch.clone();
|
||||||
|
|
||||||
let files_changed = changed.is_some();
|
let files_changed = changed.is_some();
|
||||||
let include = selection.include.clone();
|
let files = bench_options.files.clone();
|
||||||
let ignore = selection.ignore.clone();
|
|
||||||
let ps = ps.clone();
|
let ps = ps.clone();
|
||||||
|
|
||||||
async move {
|
async move {
|
||||||
let bench_modules =
|
let bench_modules = collect_specifiers(&files, is_supported_bench_path)?;
|
||||||
collect_specifiers(include.clone(), &ignore, is_supported_bench_path)?;
|
|
||||||
|
|
||||||
let mut paths_to_watch = paths_to_watch_clone;
|
let mut paths_to_watch = paths_to_watch_clone;
|
||||||
let mut modules_to_reload = if files_changed {
|
let mut modules_to_reload = if files_changed {
|
||||||
|
@ -615,7 +607,6 @@ pub async fn run_benchmarks_with_watch(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This bench module and all it's dependencies
|
// This bench module and all it's dependencies
|
||||||
let mut modules = HashSet::new();
|
let mut modules = HashSet::new();
|
||||||
modules.insert(&specifier);
|
modules.insert(&specifier);
|
||||||
|
@ -664,15 +655,13 @@ pub async fn run_benchmarks_with_watch(
|
||||||
};
|
};
|
||||||
|
|
||||||
let operation = |modules_to_reload: Vec<(ModuleSpecifier, ModuleKind)>| {
|
let operation = |modules_to_reload: Vec<(ModuleSpecifier, ModuleKind)>| {
|
||||||
let filter = bench_flags.filter.clone();
|
|
||||||
let include = selection.include.clone();
|
|
||||||
let ignore = selection.ignore.clone();
|
|
||||||
let permissions = permissions.clone();
|
let permissions = permissions.clone();
|
||||||
let ps = ps.clone();
|
let ps = ps.clone();
|
||||||
|
let filter = bench_options.filter.clone();
|
||||||
|
let files = bench_options.files.clone();
|
||||||
|
|
||||||
async move {
|
async move {
|
||||||
let specifiers =
|
let specifiers = collect_specifiers(&files, is_supported_bench_path)?
|
||||||
collect_specifiers(include.clone(), &ignore, is_supported_bench_path)?
|
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|specifier| contains_specifier(&modules_to_reload, specifier))
|
.filter(|specifier| contains_specifier(&modules_to_reload, specifier))
|
||||||
.cloned()
|
.cloned()
|
||||||
|
@ -680,10 +669,12 @@ pub async fn run_benchmarks_with_watch(
|
||||||
|
|
||||||
check_specifiers(&ps, permissions.clone(), specifiers.clone()).await?;
|
check_specifiers(&ps, permissions.clone(), specifiers.clone()).await?;
|
||||||
|
|
||||||
let specifier_options = BenchSpecifierOptions {
|
bench_specifiers(
|
||||||
filter: filter.clone(),
|
ps,
|
||||||
};
|
permissions.clone(),
|
||||||
bench_specifiers(ps, permissions.clone(), specifiers, specifier_options)
|
specifiers,
|
||||||
|
BenchSpecifierOptions { filter },
|
||||||
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -702,42 +693,3 @@ pub async fn run_benchmarks_with_watch(
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
struct IncludeIgnoreCollection {
|
|
||||||
include: Vec<String>,
|
|
||||||
ignore: Vec<PathBuf>,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn collect_include_ignore(
|
|
||||||
bench_flags: &BenchFlags,
|
|
||||||
maybe_bench_config: Option<BenchConfig>,
|
|
||||||
) -> IncludeIgnoreCollection {
|
|
||||||
let mut include = bench_flags.include.clone().unwrap_or_default();
|
|
||||||
let mut ignore = bench_flags.ignore.clone();
|
|
||||||
|
|
||||||
if let Some(bench_config) = maybe_bench_config {
|
|
||||||
if include.is_empty() {
|
|
||||||
include = bench_config
|
|
||||||
.files
|
|
||||||
.include
|
|
||||||
.iter()
|
|
||||||
.map(|s| s.to_string())
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ignore.is_empty() {
|
|
||||||
ignore = bench_config
|
|
||||||
.files
|
|
||||||
.exclude
|
|
||||||
.iter()
|
|
||||||
.filter_map(|s| specifier_to_file_path(s).ok())
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if include.is_empty() {
|
|
||||||
include.push(".".to_string());
|
|
||||||
}
|
|
||||||
|
|
||||||
IncludeIgnoreCollection { include, ignore }
|
|
||||||
}
|
|
||||||
|
|
134
cli/tools/fmt.rs
134
cli/tools/fmt.rs
|
@ -8,7 +8,8 @@
|
||||||
//! the same functions as ops available in JS runtime.
|
//! the same functions as ops available in JS runtime.
|
||||||
|
|
||||||
use crate::args::CliOptions;
|
use crate::args::CliOptions;
|
||||||
use crate::args::FmtFlags;
|
use crate::args::FilesConfig;
|
||||||
|
use crate::args::FmtOptions;
|
||||||
use crate::args::FmtOptionsConfig;
|
use crate::args::FmtOptionsConfig;
|
||||||
use crate::args::ProseWrap;
|
use crate::args::ProseWrap;
|
||||||
use crate::colors;
|
use crate::colors;
|
||||||
|
@ -17,7 +18,6 @@ use crate::util::file_watcher;
|
||||||
use crate::util::file_watcher::ResolutionResult;
|
use crate::util::file_watcher::ResolutionResult;
|
||||||
use crate::util::fs::FileCollector;
|
use crate::util::fs::FileCollector;
|
||||||
use crate::util::path::get_extension;
|
use crate::util::path::get_extension;
|
||||||
use crate::util::path::specifier_to_file_path;
|
|
||||||
use crate::util::text_encoding;
|
use crate::util::text_encoding;
|
||||||
use deno_ast::ParsedSource;
|
use deno_ast::ParsedSource;
|
||||||
use deno_core::anyhow::bail;
|
use deno_core::anyhow::bail;
|
||||||
|
@ -44,60 +44,21 @@ use crate::cache::IncrementalCache;
|
||||||
|
|
||||||
/// Format JavaScript/TypeScript files.
|
/// Format JavaScript/TypeScript files.
|
||||||
pub async fn format(
|
pub async fn format(
|
||||||
config: &CliOptions,
|
cli_options: CliOptions,
|
||||||
fmt_flags: FmtFlags,
|
fmt_options: FmtOptions,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), AnyError> {
|
||||||
let maybe_fmt_config = config.to_fmt_config()?;
|
if fmt_options.is_stdin {
|
||||||
let deno_dir = config.resolve_deno_dir()?;
|
return format_stdin(fmt_options);
|
||||||
let FmtFlags {
|
|
||||||
files,
|
|
||||||
ignore,
|
|
||||||
check,
|
|
||||||
..
|
|
||||||
} = fmt_flags.clone();
|
|
||||||
|
|
||||||
// First, prepare final configuration.
|
|
||||||
// Collect included and ignored files. CLI flags take precendence
|
|
||||||
// over config file, ie. if there's `files.ignore` in config file
|
|
||||||
// and `--ignore` CLI flag, only the flag value is taken into account.
|
|
||||||
let mut include_files = files.clone();
|
|
||||||
let mut exclude_files = ignore;
|
|
||||||
|
|
||||||
if let Some(fmt_config) = maybe_fmt_config.as_ref() {
|
|
||||||
if include_files.is_empty() {
|
|
||||||
include_files = fmt_config
|
|
||||||
.files
|
|
||||||
.include
|
|
||||||
.iter()
|
|
||||||
.filter_map(|s| specifier_to_file_path(s).ok())
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if exclude_files.is_empty() {
|
let files = fmt_options.files;
|
||||||
exclude_files = fmt_config
|
let check = fmt_options.check;
|
||||||
.files
|
let fmt_config_options = fmt_options.options;
|
||||||
.exclude
|
|
||||||
.iter()
|
|
||||||
.filter_map(|s| specifier_to_file_path(s).ok())
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if include_files.is_empty() {
|
|
||||||
include_files = [std::env::current_dir()?].to_vec();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now do the same for options
|
|
||||||
let fmt_options = resolve_fmt_options(
|
|
||||||
&fmt_flags,
|
|
||||||
maybe_fmt_config.map(|c| c.options).unwrap_or_default(),
|
|
||||||
);
|
|
||||||
|
|
||||||
let resolver = |changed: Option<Vec<PathBuf>>| {
|
let resolver = |changed: Option<Vec<PathBuf>>| {
|
||||||
let files_changed = changed.is_some();
|
let files_changed = changed.is_some();
|
||||||
|
|
||||||
let result =
|
let result = collect_fmt_files(&files).map(|files| {
|
||||||
collect_fmt_files(&include_files, &exclude_files).map(|files| {
|
|
||||||
let refmt_files = if let Some(paths) = changed {
|
let refmt_files = if let Some(paths) = changed {
|
||||||
if check {
|
if check {
|
||||||
files
|
files
|
||||||
|
@ -114,10 +75,10 @@ pub async fn format(
|
||||||
} else {
|
} else {
|
||||||
files
|
files
|
||||||
};
|
};
|
||||||
(refmt_files, fmt_options.clone())
|
(refmt_files, fmt_config_options.clone())
|
||||||
});
|
});
|
||||||
|
|
||||||
let paths_to_watch = include_files.clone();
|
let paths_to_watch = files.include.clone();
|
||||||
async move {
|
async move {
|
||||||
if files_changed
|
if files_changed
|
||||||
&& matches!(result, Ok((ref files, _)) if files.is_empty())
|
&& matches!(result, Ok((ref files, _)) if files.is_empty())
|
||||||
|
@ -131,6 +92,7 @@ pub async fn format(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
let deno_dir = cli_options.resolve_deno_dir()?;
|
||||||
let deno_dir = &deno_dir;
|
let deno_dir = &deno_dir;
|
||||||
let operation = |(paths, fmt_options): (Vec<PathBuf>, FmtOptionsConfig)| async move {
|
let operation = |(paths, fmt_options): (Vec<PathBuf>, FmtOptionsConfig)| async move {
|
||||||
let incremental_cache = Arc::new(IncrementalCache::new(
|
let incremental_cache = Arc::new(IncrementalCache::new(
|
||||||
|
@ -148,40 +110,36 @@ pub async fn format(
|
||||||
Ok(())
|
Ok(())
|
||||||
};
|
};
|
||||||
|
|
||||||
if config.watch_paths().is_some() {
|
if cli_options.watch_paths().is_some() {
|
||||||
file_watcher::watch_func(
|
file_watcher::watch_func(
|
||||||
resolver,
|
resolver,
|
||||||
operation,
|
operation,
|
||||||
file_watcher::PrintConfig {
|
file_watcher::PrintConfig {
|
||||||
job_name: "Fmt".to_string(),
|
job_name: "Fmt".to_string(),
|
||||||
clear_screen: !config.no_clear_screen(),
|
clear_screen: !cli_options.no_clear_screen(),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
} else {
|
} else {
|
||||||
let files =
|
let files = collect_fmt_files(&files).and_then(|files| {
|
||||||
collect_fmt_files(&include_files, &exclude_files).and_then(|files| {
|
|
||||||
if files.is_empty() {
|
if files.is_empty() {
|
||||||
Err(generic_error("No target files found."))
|
Err(generic_error("No target files found."))
|
||||||
} else {
|
} else {
|
||||||
Ok(files)
|
Ok(files)
|
||||||
}
|
}
|
||||||
})?;
|
})?;
|
||||||
operation((files, fmt_options.clone())).await?;
|
operation((files, fmt_config_options)).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn collect_fmt_files(
|
fn collect_fmt_files(files: &FilesConfig) -> Result<Vec<PathBuf>, AnyError> {
|
||||||
include_files: &[PathBuf],
|
|
||||||
exclude_files: &[PathBuf],
|
|
||||||
) -> Result<Vec<PathBuf>, AnyError> {
|
|
||||||
FileCollector::new(is_supported_ext_fmt)
|
FileCollector::new(is_supported_ext_fmt)
|
||||||
.ignore_git_folder()
|
.ignore_git_folder()
|
||||||
.ignore_node_modules()
|
.ignore_node_modules()
|
||||||
.add_ignore_paths(exclude_files)
|
.add_ignore_paths(&files.exclude)
|
||||||
.collect_files(include_files)
|
.collect_files(&files.include)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Formats markdown (using <https://github.com/dprint/dprint-plugin-markdown>) and its code blocks
|
/// Formats markdown (using <https://github.com/dprint/dprint-plugin-markdown>) and its code blocks
|
||||||
|
@ -275,11 +233,11 @@ pub fn format_file(
|
||||||
|
|
||||||
pub fn format_parsed_source(
|
pub fn format_parsed_source(
|
||||||
parsed_source: &ParsedSource,
|
parsed_source: &ParsedSource,
|
||||||
fmt_options: FmtOptionsConfig,
|
fmt_options: &FmtOptionsConfig,
|
||||||
) -> Result<Option<String>, AnyError> {
|
) -> Result<Option<String>, AnyError> {
|
||||||
dprint_plugin_typescript::format_parsed_source(
|
dprint_plugin_typescript::format_parsed_source(
|
||||||
parsed_source,
|
parsed_source,
|
||||||
&get_resolved_typescript_config(&fmt_options),
|
&get_resolved_typescript_config(fmt_options),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -501,19 +459,14 @@ fn format_ensure_stable(
|
||||||
/// Format stdin and write result to stdout.
|
/// Format stdin and write result to stdout.
|
||||||
/// Treats input as TypeScript or as set by `--ext` flag.
|
/// Treats input as TypeScript or as set by `--ext` flag.
|
||||||
/// Compatible with `--check` flag.
|
/// Compatible with `--check` flag.
|
||||||
pub fn format_stdin(
|
fn format_stdin(fmt_options: FmtOptions) -> Result<(), AnyError> {
|
||||||
fmt_flags: FmtFlags,
|
|
||||||
fmt_options: FmtOptionsConfig,
|
|
||||||
) -> Result<(), AnyError> {
|
|
||||||
let mut source = String::new();
|
let mut source = String::new();
|
||||||
if stdin().read_to_string(&mut source).is_err() {
|
if stdin().read_to_string(&mut source).is_err() {
|
||||||
bail!("Failed to read from stdin");
|
bail!("Failed to read from stdin");
|
||||||
}
|
}
|
||||||
let file_path = PathBuf::from(format!("_stdin.{}", fmt_flags.ext));
|
let file_path = PathBuf::from(format!("_stdin.{}", fmt_options.ext));
|
||||||
let fmt_options = resolve_fmt_options(&fmt_flags, fmt_options);
|
let formatted_text = format_file(&file_path, &source, &fmt_options.options)?;
|
||||||
|
if fmt_options.check {
|
||||||
let formatted_text = format_file(&file_path, &source, &fmt_options)?;
|
|
||||||
if fmt_flags.check {
|
|
||||||
if formatted_text.is_some() {
|
if formatted_text.is_some() {
|
||||||
println!("Not formatted stdin");
|
println!("Not formatted stdin");
|
||||||
}
|
}
|
||||||
|
@ -531,41 +484,6 @@ fn files_str(len: usize) -> &'static str {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_fmt_options(
|
|
||||||
fmt_flags: &FmtFlags,
|
|
||||||
options: FmtOptionsConfig,
|
|
||||||
) -> FmtOptionsConfig {
|
|
||||||
let mut options = options;
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_resolved_typescript_config(
|
fn get_resolved_typescript_config(
|
||||||
options: &FmtOptionsConfig,
|
options: &FmtOptionsConfig,
|
||||||
) -> dprint_plugin_typescript::configuration::Configuration {
|
) -> dprint_plugin_typescript::configuration::Configuration {
|
||||||
|
|
|
@ -6,19 +6,19 @@
|
||||||
//! At the moment it is only consumed using CLI but in
|
//! At the moment it is only consumed using CLI but in
|
||||||
//! the future it can be easily extended to provide
|
//! the future it can be easily extended to provide
|
||||||
//! the same functions as ops available in JS runtime.
|
//! the same functions as ops available in JS runtime.
|
||||||
use crate::args::Flags;
|
use crate::args::CliOptions;
|
||||||
use crate::args::LintConfig;
|
use crate::args::FilesConfig;
|
||||||
use crate::args::LintFlags;
|
use crate::args::LintOptions;
|
||||||
|
use crate::args::LintReporterKind;
|
||||||
|
use crate::args::LintRulesConfig;
|
||||||
use crate::colors;
|
use crate::colors;
|
||||||
use crate::proc_state::ProcState;
|
|
||||||
use crate::tools::fmt::run_parallelized;
|
use crate::tools::fmt::run_parallelized;
|
||||||
use crate::util::file_watcher;
|
use crate::util::file_watcher;
|
||||||
use crate::util::file_watcher::ResolutionResult;
|
use crate::util::file_watcher::ResolutionResult;
|
||||||
use crate::util::fs::FileCollector;
|
use crate::util::fs::FileCollector;
|
||||||
use crate::util::path::is_supported_ext;
|
use crate::util::path::is_supported_ext;
|
||||||
use crate::util::path::specifier_to_file_path;
|
|
||||||
use deno_ast::MediaType;
|
use deno_ast::MediaType;
|
||||||
use deno_core::anyhow::anyhow;
|
use deno_core::anyhow::bail;
|
||||||
use deno_core::error::generic_error;
|
use deno_core::error::generic_error;
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
use deno_core::error::JsStackFrame;
|
use deno_core::error::JsStackFrame;
|
||||||
|
@ -45,13 +45,6 @@ use crate::cache::IncrementalCache;
|
||||||
|
|
||||||
static STDIN_FILE_NAME: &str = "_stdin.ts";
|
static STDIN_FILE_NAME: &str = "_stdin.ts";
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
pub enum LintReporterKind {
|
|
||||||
Pretty,
|
|
||||||
Json,
|
|
||||||
Compact,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn create_reporter(kind: LintReporterKind) -> Box<dyn LintReporter + Send> {
|
fn create_reporter(kind: LintReporterKind) -> Box<dyn LintReporter + Send> {
|
||||||
match kind {
|
match kind {
|
||||||
LintReporterKind::Pretty => Box::new(PrettyLintReporter::new()),
|
LintReporterKind::Pretty => Box::new(PrettyLintReporter::new()),
|
||||||
|
@ -60,90 +53,23 @@ fn create_reporter(kind: LintReporterKind) -> Box<dyn LintReporter + Send> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn lint(flags: Flags, lint_flags: LintFlags) -> Result<(), AnyError> {
|
pub async fn lint(
|
||||||
let LintFlags {
|
cli_options: CliOptions,
|
||||||
maybe_rules_tags,
|
lint_options: LintOptions,
|
||||||
maybe_rules_include,
|
) -> Result<(), AnyError> {
|
||||||
maybe_rules_exclude,
|
// Try to get lint rules. If none were set use recommended rules.
|
||||||
files: args,
|
let lint_rules = get_configured_rules(lint_options.rules);
|
||||||
ignore,
|
|
||||||
json,
|
|
||||||
compact,
|
|
||||||
..
|
|
||||||
} = lint_flags;
|
|
||||||
// First, prepare final configuration.
|
|
||||||
// Collect included and ignored files. CLI flags take precendence
|
|
||||||
// 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.
|
|
||||||
let mut include_files = args.clone();
|
|
||||||
let mut exclude_files = ignore.clone();
|
|
||||||
let mut maybe_reporter_kind = if json {
|
|
||||||
Some(LintReporterKind::Json)
|
|
||||||
} else if compact {
|
|
||||||
Some(LintReporterKind::Compact)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
let ps = ProcState::build(flags).await?;
|
if lint_rules.is_empty() {
|
||||||
let maybe_lint_config = ps.options.to_lint_config()?;
|
bail!("No rules have been configured")
|
||||||
|
|
||||||
if let Some(lint_config) = maybe_lint_config.as_ref() {
|
|
||||||
if include_files.is_empty() {
|
|
||||||
include_files = lint_config
|
|
||||||
.files
|
|
||||||
.include
|
|
||||||
.iter()
|
|
||||||
.filter_map(|s| specifier_to_file_path(s).ok())
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if exclude_files.is_empty() {
|
let files = lint_options.files;
|
||||||
exclude_files = lint_config
|
let reporter_kind = lint_options.reporter_kind;
|
||||||
.files
|
|
||||||
.exclude
|
|
||||||
.iter()
|
|
||||||
.filter_map(|s| specifier_to_file_path(s).ok())
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
}
|
|
||||||
|
|
||||||
if maybe_reporter_kind.is_none() {
|
|
||||||
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(_) => {
|
|
||||||
return Err(anyhow!("Invalid lint report type in config file"))
|
|
||||||
}
|
|
||||||
None => Some(LintReporterKind::Pretty),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if include_files.is_empty() {
|
|
||||||
include_files = [std::env::current_dir()?].to_vec();
|
|
||||||
}
|
|
||||||
|
|
||||||
let reporter_kind = match maybe_reporter_kind {
|
|
||||||
Some(report) => report,
|
|
||||||
None => LintReporterKind::Pretty,
|
|
||||||
};
|
|
||||||
|
|
||||||
let has_error = Arc::new(AtomicBool::new(false));
|
|
||||||
// Try to get configured rules. CLI flags take precendence
|
|
||||||
// over config file, ie. if there's `rules.include` in config file
|
|
||||||
// and `--rules-include` CLI flag, only the flag value is taken into account.
|
|
||||||
let lint_rules = get_configured_rules(
|
|
||||||
maybe_lint_config.as_ref(),
|
|
||||||
maybe_rules_tags,
|
|
||||||
maybe_rules_include,
|
|
||||||
maybe_rules_exclude,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let resolver = |changed: Option<Vec<PathBuf>>| {
|
let resolver = |changed: Option<Vec<PathBuf>>| {
|
||||||
let files_changed = changed.is_some();
|
let files_changed = changed.is_some();
|
||||||
let result =
|
let result = collect_lint_files(&files).map(|files| {
|
||||||
collect_lint_files(&include_files, &exclude_files).map(|files| {
|
|
||||||
if let Some(paths) = changed {
|
if let Some(paths) = changed {
|
||||||
files
|
files
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -155,7 +81,7 @@ pub async fn lint(flags: Flags, lint_flags: LintFlags) -> Result<(), AnyError> {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let paths_to_watch = include_files.clone();
|
let paths_to_watch = files.include.clone();
|
||||||
|
|
||||||
async move {
|
async move {
|
||||||
if files_changed && matches!(result, Ok(ref files) if files.is_empty()) {
|
if files_changed && matches!(result, Ok(ref files) if files.is_empty()) {
|
||||||
|
@ -169,9 +95,12 @@ pub async fn lint(flags: Flags, lint_flags: LintFlags) -> Result<(), AnyError> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let has_error = Arc::new(AtomicBool::new(false));
|
||||||
|
let deno_dir = cli_options.resolve_deno_dir()?;
|
||||||
|
|
||||||
let operation = |paths: Vec<PathBuf>| async {
|
let operation = |paths: Vec<PathBuf>| async {
|
||||||
let incremental_cache = Arc::new(IncrementalCache::new(
|
let incremental_cache = Arc::new(IncrementalCache::new(
|
||||||
&ps.dir.lint_incremental_cache_db_file_path(),
|
&deno_dir.lint_incremental_cache_db_file_path(),
|
||||||
// use a hash of the rule names in order to bust the cache
|
// use a hash of the rule names in order to bust the cache
|
||||||
&{
|
&{
|
||||||
// ensure this is stable by sorting it
|
// ensure this is stable by sorting it
|
||||||
|
@ -221,8 +150,8 @@ pub async fn lint(flags: Flags, lint_flags: LintFlags) -> Result<(), AnyError> {
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
};
|
};
|
||||||
if ps.options.watch_paths().is_some() {
|
if cli_options.watch_paths().is_some() {
|
||||||
if args.len() == 1 && args[0].to_string_lossy() == "-" {
|
if lint_options.is_stdin {
|
||||||
return Err(generic_error(
|
return Err(generic_error(
|
||||||
"Lint watch on standard input is not supported.",
|
"Lint watch on standard input is not supported.",
|
||||||
));
|
));
|
||||||
|
@ -232,12 +161,12 @@ pub async fn lint(flags: Flags, lint_flags: LintFlags) -> Result<(), AnyError> {
|
||||||
operation,
|
operation,
|
||||||
file_watcher::PrintConfig {
|
file_watcher::PrintConfig {
|
||||||
job_name: "Lint".to_string(),
|
job_name: "Lint".to_string(),
|
||||||
clear_screen: !ps.options.no_clear_screen(),
|
clear_screen: !cli_options.no_clear_screen(),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
} else {
|
} else {
|
||||||
if args.len() == 1 && args[0].to_string_lossy() == "-" {
|
if lint_options.is_stdin {
|
||||||
let reporter_lock =
|
let reporter_lock =
|
||||||
Arc::new(Mutex::new(create_reporter(reporter_kind.clone())));
|
Arc::new(Mutex::new(create_reporter(reporter_kind.clone())));
|
||||||
let r = lint_stdin(lint_rules);
|
let r = lint_stdin(lint_rules);
|
||||||
|
@ -249,8 +178,7 @@ pub async fn lint(flags: Flags, lint_flags: LintFlags) -> Result<(), AnyError> {
|
||||||
);
|
);
|
||||||
reporter_lock.lock().unwrap().close(1);
|
reporter_lock.lock().unwrap().close(1);
|
||||||
} else {
|
} else {
|
||||||
let target_files = collect_lint_files(&include_files, &exclude_files)
|
let target_files = collect_lint_files(&files).and_then(|files| {
|
||||||
.and_then(|files| {
|
|
||||||
if files.is_empty() {
|
if files.is_empty() {
|
||||||
Err(generic_error("No target files found."))
|
Err(generic_error("No target files found."))
|
||||||
} else {
|
} else {
|
||||||
|
@ -269,15 +197,12 @@ pub async fn lint(flags: Flags, lint_flags: LintFlags) -> Result<(), AnyError> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn collect_lint_files(
|
fn collect_lint_files(files: &FilesConfig) -> Result<Vec<PathBuf>, AnyError> {
|
||||||
include_files: &[PathBuf],
|
|
||||||
exclude_files: &[PathBuf],
|
|
||||||
) -> Result<Vec<PathBuf>, AnyError> {
|
|
||||||
FileCollector::new(is_supported_ext)
|
FileCollector::new(is_supported_ext)
|
||||||
.ignore_git_folder()
|
.ignore_git_folder()
|
||||||
.ignore_node_modules()
|
.ignore_node_modules()
|
||||||
.add_ignore_paths(exclude_files)
|
.add_ignore_paths(&files.exclude)
|
||||||
.collect_files(include_files)
|
.collect_files(&files.include)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn print_rules_list(json: bool) {
|
pub fn print_rules_list(json: bool) {
|
||||||
|
@ -606,60 +531,17 @@ fn sort_diagnostics(diagnostics: &mut [LintDiagnostic]) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_configured_rules(
|
pub fn get_configured_rules(rules: LintRulesConfig) -> Vec<Arc<dyn LintRule>> {
|
||||||
maybe_lint_config: Option<&LintConfig>,
|
if rules.tags.is_none() && rules.include.is_none() && rules.exclude.is_none()
|
||||||
maybe_rules_tags: Option<Vec<String>>,
|
|
||||||
maybe_rules_include: Option<Vec<String>>,
|
|
||||||
maybe_rules_exclude: Option<Vec<String>>,
|
|
||||||
) -> Result<Vec<Arc<dyn LintRule>>, AnyError> {
|
|
||||||
if maybe_lint_config.is_none()
|
|
||||||
&& maybe_rules_tags.is_none()
|
|
||||||
&& maybe_rules_include.is_none()
|
|
||||||
&& maybe_rules_exclude.is_none()
|
|
||||||
{
|
{
|
||||||
return Ok(rules::get_recommended_rules());
|
rules::get_recommended_rules()
|
||||||
}
|
} else {
|
||||||
|
rules::get_filtered_rules(
|
||||||
let (config_file_tags, config_file_include, config_file_exclude) =
|
rules.tags.or_else(|| Some(vec!["recommended".to_string()])),
|
||||||
if let Some(lint_config) = maybe_lint_config {
|
rules.exclude,
|
||||||
(
|
rules.include,
|
||||||
lint_config.rules.tags.clone(),
|
|
||||||
lint_config.rules.include.clone(),
|
|
||||||
lint_config.rules.exclude.clone(),
|
|
||||||
)
|
)
|
||||||
} else {
|
|
||||||
(None, None, None)
|
|
||||||
};
|
|
||||||
|
|
||||||
let maybe_configured_include = if maybe_rules_include.is_some() {
|
|
||||||
maybe_rules_include
|
|
||||||
} else {
|
|
||||||
config_file_include
|
|
||||||
};
|
|
||||||
|
|
||||||
let maybe_configured_exclude = if maybe_rules_exclude.is_some() {
|
|
||||||
maybe_rules_exclude
|
|
||||||
} else {
|
|
||||||
config_file_exclude
|
|
||||||
};
|
|
||||||
|
|
||||||
let maybe_configured_tags = if maybe_rules_tags.is_some() {
|
|
||||||
maybe_rules_tags
|
|
||||||
} else {
|
|
||||||
config_file_tags
|
|
||||||
};
|
|
||||||
|
|
||||||
let configured_rules = rules::get_filtered_rules(
|
|
||||||
maybe_configured_tags.or_else(|| Some(vec!["recommended".to_string()])),
|
|
||||||
maybe_configured_exclude,
|
|
||||||
maybe_configured_include,
|
|
||||||
);
|
|
||||||
|
|
||||||
if configured_rules.is_empty() {
|
|
||||||
return Err(anyhow!("No rules have been configured"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(configured_rules)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -671,15 +553,12 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn recommended_rules_when_no_tags_in_config() {
|
fn recommended_rules_when_no_tags_in_config() {
|
||||||
let lint_config = LintConfig {
|
let rules_config = LintRulesConfig {
|
||||||
rules: LintRulesConfig {
|
|
||||||
exclude: Some(vec!["no-debugger".to_string()]),
|
exclude: Some(vec!["no-debugger".to_string()]),
|
||||||
..Default::default()
|
include: None,
|
||||||
},
|
tags: None,
|
||||||
..Default::default()
|
|
||||||
};
|
};
|
||||||
let rules =
|
let rules = get_configured_rules(rules_config);
|
||||||
get_configured_rules(Some(&lint_config), None, None, None).unwrap();
|
|
||||||
let mut rule_names = rules
|
let mut rule_names = rules
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|r| r.code().to_string())
|
.map(|r| r.code().to_string())
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
use crate::args::Flags;
|
use crate::args::CliOptions;
|
||||||
use crate::args::TestFlags;
|
use crate::args::FilesConfig;
|
||||||
|
use crate::args::TestOptions;
|
||||||
use crate::args::TypeCheckMode;
|
use crate::args::TypeCheckMode;
|
||||||
use crate::colors;
|
use crate::colors;
|
||||||
use crate::display;
|
use crate::display;
|
||||||
|
@ -16,7 +17,6 @@ use crate::util::file_watcher::ResolutionResult;
|
||||||
use crate::util::fs::collect_specifiers;
|
use crate::util::fs::collect_specifiers;
|
||||||
use crate::util::path::get_extension;
|
use crate::util::path::get_extension;
|
||||||
use crate::util::path::is_supported_ext;
|
use crate::util::path::is_supported_ext;
|
||||||
use crate::util::path::specifier_to_file_path;
|
|
||||||
use crate::worker::create_main_worker_for_test_or_bench;
|
use crate::worker::create_main_worker_for_test_or_bench;
|
||||||
|
|
||||||
use deno_ast::swc::common::comments::CommentKind;
|
use deno_ast::swc::common::comments::CommentKind;
|
||||||
|
@ -1237,15 +1237,13 @@ fn is_supported_test_ext(path: &Path) -> bool {
|
||||||
/// - Specifiers matching the `is_supported_test_path` are marked as `TestMode::Executable`.
|
/// - Specifiers matching the `is_supported_test_path` are marked as `TestMode::Executable`.
|
||||||
/// - Specifiers matching both predicates are marked as `TestMode::Both`
|
/// - Specifiers matching both predicates are marked as `TestMode::Both`
|
||||||
fn collect_specifiers_with_test_mode(
|
fn collect_specifiers_with_test_mode(
|
||||||
include: Vec<String>,
|
files: FilesConfig,
|
||||||
ignore: Vec<PathBuf>,
|
|
||||||
include_inline: bool,
|
include_inline: bool,
|
||||||
) -> Result<Vec<(ModuleSpecifier, TestMode)>, AnyError> {
|
) -> Result<Vec<(ModuleSpecifier, TestMode)>, AnyError> {
|
||||||
let module_specifiers =
|
let module_specifiers = collect_specifiers(&files, is_supported_test_path)?;
|
||||||
collect_specifiers(include.clone(), &ignore, is_supported_test_path)?;
|
|
||||||
|
|
||||||
if include_inline {
|
if include_inline {
|
||||||
return collect_specifiers(include, &ignore, is_supported_test_ext).map(
|
return collect_specifiers(&files, is_supported_test_ext).map(
|
||||||
|specifiers| {
|
|specifiers| {
|
||||||
specifiers
|
specifiers
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
@ -1281,44 +1279,10 @@ fn collect_specifiers_with_test_mode(
|
||||||
/// as well.
|
/// as well.
|
||||||
async fn fetch_specifiers_with_test_mode(
|
async fn fetch_specifiers_with_test_mode(
|
||||||
ps: &ProcState,
|
ps: &ProcState,
|
||||||
include: Vec<String>,
|
files: FilesConfig,
|
||||||
ignore: Vec<PathBuf>,
|
doc: bool,
|
||||||
include_inline: bool,
|
|
||||||
) -> Result<Vec<(ModuleSpecifier, TestMode)>, AnyError> {
|
) -> Result<Vec<(ModuleSpecifier, TestMode)>, AnyError> {
|
||||||
let maybe_test_config = ps.options.to_test_config()?;
|
let mut specifiers_with_mode = collect_specifiers_with_test_mode(files, doc)?;
|
||||||
|
|
||||||
let mut include_files = include.clone();
|
|
||||||
let mut exclude_files = ignore.clone();
|
|
||||||
|
|
||||||
if let Some(test_config) = maybe_test_config.as_ref() {
|
|
||||||
if include_files.is_empty() {
|
|
||||||
include_files = test_config
|
|
||||||
.files
|
|
||||||
.include
|
|
||||||
.iter()
|
|
||||||
.map(|s| s.to_string())
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
}
|
|
||||||
|
|
||||||
if exclude_files.is_empty() {
|
|
||||||
exclude_files = test_config
|
|
||||||
.files
|
|
||||||
.exclude
|
|
||||||
.iter()
|
|
||||||
.filter_map(|s| specifier_to_file_path(s).ok())
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if include_files.is_empty() {
|
|
||||||
include_files.push(".".to_string());
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut specifiers_with_mode = collect_specifiers_with_test_mode(
|
|
||||||
include_files,
|
|
||||||
exclude_files,
|
|
||||||
include_inline,
|
|
||||||
)?;
|
|
||||||
for (specifier, mode) in &mut specifiers_with_mode {
|
for (specifier, mode) in &mut specifiers_with_mode {
|
||||||
let file = ps
|
let file = ps
|
||||||
.file_fetcher
|
.file_fetcher
|
||||||
|
@ -1336,31 +1300,28 @@ async fn fetch_specifiers_with_test_mode(
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn run_tests(
|
pub async fn run_tests(
|
||||||
flags: Flags,
|
cli_options: CliOptions,
|
||||||
test_flags: TestFlags,
|
test_options: TestOptions,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), AnyError> {
|
||||||
let ps = ProcState::build(flags).await?;
|
let ps = ProcState::from_options(Arc::new(cli_options)).await?;
|
||||||
// Various test files should not share the same permissions in terms of
|
// Various test files should not share the same permissions in terms of
|
||||||
// `PermissionsContainer` - otherwise granting/revoking permissions in one
|
// `PermissionsContainer` - otherwise granting/revoking permissions in one
|
||||||
// file would have impact on other files, which is undesirable.
|
// file would have impact on other files, which is undesirable.
|
||||||
let permissions =
|
let permissions =
|
||||||
Permissions::from_options(&ps.options.permissions_options())?;
|
Permissions::from_options(&ps.options.permissions_options())?;
|
||||||
let specifiers_with_mode = fetch_specifiers_with_test_mode(
|
|
||||||
&ps,
|
let specifiers_with_mode =
|
||||||
test_flags.include,
|
fetch_specifiers_with_test_mode(&ps, test_options.files, test_options.doc)
|
||||||
test_flags.ignore.clone(),
|
|
||||||
test_flags.doc,
|
|
||||||
)
|
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
if !test_flags.allow_none && specifiers_with_mode.is_empty() {
|
if !test_options.allow_none && specifiers_with_mode.is_empty() {
|
||||||
return Err(generic_error("No test modules found"));
|
return Err(generic_error("No test modules found"));
|
||||||
}
|
}
|
||||||
|
|
||||||
check_specifiers(&ps, permissions.clone(), specifiers_with_mode.clone())
|
check_specifiers(&ps, permissions.clone(), specifiers_with_mode.clone())
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
if test_flags.no_run {
|
if test_options.no_run {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1369,9 +1330,9 @@ pub async fn run_tests(
|
||||||
permissions,
|
permissions,
|
||||||
specifiers_with_mode,
|
specifiers_with_mode,
|
||||||
TestSpecifierOptions {
|
TestSpecifierOptions {
|
||||||
concurrent_jobs: test_flags.concurrent_jobs,
|
concurrent_jobs: test_options.concurrent_jobs,
|
||||||
fail_fast: test_flags.fail_fast,
|
fail_fast: test_options.fail_fast,
|
||||||
filter: TestFilter::from_flag(&test_flags.filter),
|
filter: TestFilter::from_flag(&test_options.filter),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
@ -1380,35 +1341,32 @@ pub async fn run_tests(
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn run_tests_with_watch(
|
pub async fn run_tests_with_watch(
|
||||||
flags: Flags,
|
cli_options: CliOptions,
|
||||||
test_flags: TestFlags,
|
test_options: TestOptions,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), AnyError> {
|
||||||
let ps = ProcState::build(flags).await?;
|
let ps = ProcState::from_options(Arc::new(cli_options)).await?;
|
||||||
// Various test files should not share the same permissions in terms of
|
// Various test files should not share the same permissions in terms of
|
||||||
// `PermissionsContainer` - otherwise granting/revoking permissions in one
|
// `PermissionsContainer` - otherwise granting/revoking permissions in one
|
||||||
// file would have impact on other files, which is undesirable.
|
// file would have impact on other files, which is undesirable.
|
||||||
let permissions =
|
let permissions =
|
||||||
Permissions::from_options(&ps.options.permissions_options())?;
|
Permissions::from_options(&ps.options.permissions_options())?;
|
||||||
|
|
||||||
let include = test_flags.include;
|
let paths_to_watch: Vec<_> = test_options.files.include.clone();
|
||||||
let ignore = test_flags.ignore.clone();
|
|
||||||
let paths_to_watch: Vec<_> = include.iter().map(PathBuf::from).collect();
|
|
||||||
let no_check = ps.options.type_check_mode() == TypeCheckMode::None;
|
let no_check = ps.options.type_check_mode() == TypeCheckMode::None;
|
||||||
|
let test_options = &test_options;
|
||||||
|
|
||||||
let resolver = |changed: Option<Vec<PathBuf>>| {
|
let resolver = |changed: Option<Vec<PathBuf>>| {
|
||||||
let paths_to_watch = paths_to_watch.clone();
|
let paths_to_watch = paths_to_watch.clone();
|
||||||
let paths_to_watch_clone = paths_to_watch.clone();
|
let paths_to_watch_clone = paths_to_watch.clone();
|
||||||
|
|
||||||
let files_changed = changed.is_some();
|
let files_changed = changed.is_some();
|
||||||
let include = include.clone();
|
|
||||||
let ignore = ignore.clone();
|
|
||||||
let ps = ps.clone();
|
let ps = ps.clone();
|
||||||
|
|
||||||
async move {
|
async move {
|
||||||
let test_modules = if test_flags.doc {
|
let test_modules = if test_options.doc {
|
||||||
collect_specifiers(include.clone(), &ignore, is_supported_test_ext)
|
collect_specifiers(&test_options.files, is_supported_test_ext)
|
||||||
} else {
|
} else {
|
||||||
collect_specifiers(include.clone(), &ignore, is_supported_test_path)
|
collect_specifiers(&test_options.files, is_supported_test_path)
|
||||||
}?;
|
}?;
|
||||||
|
|
||||||
let mut paths_to_watch = paths_to_watch_clone;
|
let mut paths_to_watch = paths_to_watch_clone;
|
||||||
|
@ -1517,20 +1475,16 @@ pub async fn run_tests_with_watch(
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
let cli_options = ps.options.clone();
|
|
||||||
let operation = |modules_to_reload: Vec<(ModuleSpecifier, ModuleKind)>| {
|
let operation = |modules_to_reload: Vec<(ModuleSpecifier, ModuleKind)>| {
|
||||||
let filter = test_flags.filter.clone();
|
|
||||||
let include = include.clone();
|
|
||||||
let ignore = ignore.clone();
|
|
||||||
let permissions = permissions.clone();
|
let permissions = permissions.clone();
|
||||||
let ps = ps.clone();
|
let ps = ps.clone();
|
||||||
|
let test_options = test_options.clone();
|
||||||
|
|
||||||
async move {
|
async move {
|
||||||
let specifiers_with_mode = fetch_specifiers_with_test_mode(
|
let specifiers_with_mode = fetch_specifiers_with_test_mode(
|
||||||
&ps,
|
&ps,
|
||||||
include.clone(),
|
test_options.files,
|
||||||
ignore.clone(),
|
test_options.doc,
|
||||||
test_flags.doc,
|
|
||||||
)
|
)
|
||||||
.await?
|
.await?
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -1543,7 +1497,7 @@ pub async fn run_tests_with_watch(
|
||||||
check_specifiers(&ps, permissions.clone(), specifiers_with_mode.clone())
|
check_specifiers(&ps, permissions.clone(), specifiers_with_mode.clone())
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
if test_flags.no_run {
|
if test_options.no_run {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1552,9 +1506,9 @@ pub async fn run_tests_with_watch(
|
||||||
permissions.clone(),
|
permissions.clone(),
|
||||||
specifiers_with_mode,
|
specifiers_with_mode,
|
||||||
TestSpecifierOptions {
|
TestSpecifierOptions {
|
||||||
concurrent_jobs: test_flags.concurrent_jobs,
|
concurrent_jobs: test_options.concurrent_jobs,
|
||||||
fail_fast: test_flags.fail_fast,
|
fail_fast: test_options.fail_fast,
|
||||||
filter: TestFilter::from_flag(&filter),
|
filter: TestFilter::from_flag(&test_options.filter),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
@ -1568,7 +1522,7 @@ pub async fn run_tests_with_watch(
|
||||||
operation,
|
operation,
|
||||||
file_watcher::PrintConfig {
|
file_watcher::PrintConfig {
|
||||||
job_name: "Test".to_string(),
|
job_name: "Test".to_string(),
|
||||||
clear_screen: !cli_options.no_clear_screen(),
|
clear_screen: !ps.options.no_clear_screen(),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
5
cli/tools/vendor/mod.rs
vendored
5
cli/tools/vendor/mod.rs
vendored
|
@ -153,9 +153,12 @@ fn maybe_update_config_file(output_dir: &Path, ps: &ProcState) -> bool {
|
||||||
Some(f) => f,
|
Some(f) => f,
|
||||||
None => return false,
|
None => return false,
|
||||||
};
|
};
|
||||||
|
|
||||||
let fmt_config = ps
|
let fmt_config = ps
|
||||||
.options
|
.options
|
||||||
.to_fmt_config()
|
.get_maybe_config_file()
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|config| config.to_fmt_config().ok())
|
||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
let result = update_config_file(
|
let result = update_config_file(
|
||||||
|
|
|
@ -107,9 +107,13 @@ where
|
||||||
log::debug!("File change ignored")
|
log::debug!("File change ignored")
|
||||||
}
|
}
|
||||||
ResolutionResult::Restart {
|
ResolutionResult::Restart {
|
||||||
paths_to_watch,
|
mut paths_to_watch,
|
||||||
result,
|
result,
|
||||||
} => {
|
} => {
|
||||||
|
// watch the current directory when empty
|
||||||
|
if paths_to_watch.is_empty() {
|
||||||
|
paths_to_watch.push(PathBuf::from("."));
|
||||||
|
}
|
||||||
return (paths_to_watch, result);
|
return (paths_to_watch, result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -190,9 +194,13 @@ where
|
||||||
print_after_restart();
|
print_after_restart();
|
||||||
}
|
}
|
||||||
ResolutionResult::Restart {
|
ResolutionResult::Restart {
|
||||||
paths_to_watch: paths,
|
paths_to_watch: mut paths,
|
||||||
result,
|
result,
|
||||||
} => {
|
} => {
|
||||||
|
// watch the current directory when empty
|
||||||
|
if paths.is_empty() {
|
||||||
|
paths.push(PathBuf::from("."));
|
||||||
|
}
|
||||||
paths_to_watch = paths;
|
paths_to_watch = paths;
|
||||||
resolution_result = result;
|
resolution_result = result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ pub use deno_core::normalize_path;
|
||||||
use deno_core::ModuleSpecifier;
|
use deno_core::ModuleSpecifier;
|
||||||
use deno_runtime::deno_crypto::rand;
|
use deno_runtime::deno_crypto::rand;
|
||||||
use deno_runtime::deno_node::PathClean;
|
use deno_runtime::deno_node::PathClean;
|
||||||
|
use std::borrow::Cow;
|
||||||
use std::env::current_dir;
|
use std::env::current_dir;
|
||||||
use std::fs::OpenOptions;
|
use std::fs::OpenOptions;
|
||||||
use std::io::Error;
|
use std::io::Error;
|
||||||
|
@ -16,6 +17,8 @@ use std::path::PathBuf;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use walkdir::WalkDir;
|
use walkdir::WalkDir;
|
||||||
|
|
||||||
|
use crate::args::FilesConfig;
|
||||||
|
|
||||||
use super::path::specifier_to_file_path;
|
use super::path::specifier_to_file_path;
|
||||||
|
|
||||||
pub fn atomic_write_file<T: AsRef<[u8]>>(
|
pub fn atomic_write_file<T: AsRef<[u8]>>(
|
||||||
|
@ -181,6 +184,7 @@ impl<TFilter: Fn(&Path) -> bool> FileCollector<TFilter> {
|
||||||
ignore_node_modules: false,
|
ignore_node_modules: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_ignore_paths(mut self, paths: &[PathBuf]) -> Self {
|
pub fn add_ignore_paths(mut self, paths: &[PathBuf]) -> Self {
|
||||||
// retain only the paths which exist and ignore the rest
|
// retain only the paths which exist and ignore the rest
|
||||||
self
|
self
|
||||||
|
@ -204,7 +208,13 @@ impl<TFilter: Fn(&Path) -> bool> FileCollector<TFilter> {
|
||||||
files: &[PathBuf],
|
files: &[PathBuf],
|
||||||
) -> Result<Vec<PathBuf>, AnyError> {
|
) -> Result<Vec<PathBuf>, AnyError> {
|
||||||
let mut target_files = Vec::new();
|
let mut target_files = Vec::new();
|
||||||
for file in files {
|
let files = if files.is_empty() {
|
||||||
|
// collect files in the current directory when empty
|
||||||
|
Cow::Owned(vec![PathBuf::from(".")])
|
||||||
|
} else {
|
||||||
|
Cow::Borrowed(files)
|
||||||
|
};
|
||||||
|
for file in files.iter() {
|
||||||
if let Ok(file) = canonicalize_path(file) {
|
if let Ok(file) = canonicalize_path(file) {
|
||||||
// use an iterator like this in order to minimize the number of file system operations
|
// use an iterator like this in order to minimize the number of file system operations
|
||||||
let mut iterator = WalkDir::new(&file).into_iter();
|
let mut iterator = WalkDir::new(&file).into_iter();
|
||||||
|
@ -254,18 +264,24 @@ impl<TFilter: Fn(&Path) -> bool> FileCollector<TFilter> {
|
||||||
/// Specifiers that start with http and https are left intact.
|
/// Specifiers that start with http and https are left intact.
|
||||||
/// Note: This ignores all .git and node_modules folders.
|
/// Note: This ignores all .git and node_modules folders.
|
||||||
pub fn collect_specifiers(
|
pub fn collect_specifiers(
|
||||||
include: Vec<String>,
|
files: &FilesConfig,
|
||||||
ignore: &[PathBuf],
|
|
||||||
predicate: impl Fn(&Path) -> bool,
|
predicate: impl Fn(&Path) -> bool,
|
||||||
) -> Result<Vec<ModuleSpecifier>, AnyError> {
|
) -> Result<Vec<ModuleSpecifier>, AnyError> {
|
||||||
let mut prepared = vec![];
|
let mut prepared = vec![];
|
||||||
let file_collector = FileCollector::new(predicate)
|
let file_collector = FileCollector::new(predicate)
|
||||||
.add_ignore_paths(ignore)
|
.add_ignore_paths(&files.exclude)
|
||||||
.ignore_git_folder()
|
.ignore_git_folder()
|
||||||
.ignore_node_modules();
|
.ignore_node_modules();
|
||||||
|
|
||||||
let root_path = current_dir()?;
|
let root_path = current_dir()?;
|
||||||
for path in include {
|
let include_files = if files.include.is_empty() {
|
||||||
|
// collect files in the current directory when empty
|
||||||
|
Cow::Owned(vec![root_path.clone()])
|
||||||
|
} else {
|
||||||
|
Cow::Borrowed(&files.include)
|
||||||
|
};
|
||||||
|
for path in include_files.iter() {
|
||||||
|
let path = path.to_string_lossy();
|
||||||
let lowercase_path = path.to_lowercase();
|
let lowercase_path = path.to_lowercase();
|
||||||
if lowercase_path.starts_with("http://")
|
if lowercase_path.starts_with("http://")
|
||||||
|| lowercase_path.starts_with("https://")
|
|| lowercase_path.starts_with("https://")
|
||||||
|
@ -278,7 +294,7 @@ pub fn collect_specifiers(
|
||||||
let p = if lowercase_path.starts_with("file://") {
|
let p = if lowercase_path.starts_with("file://") {
|
||||||
specifier_to_file_path(&ModuleSpecifier::parse(&path)?)?
|
specifier_to_file_path(&ModuleSpecifier::parse(&path)?)?
|
||||||
} else {
|
} else {
|
||||||
root_path.join(path)
|
root_path.join(path.as_ref())
|
||||||
};
|
};
|
||||||
let p = normalize_path(p);
|
let p = normalize_path(p);
|
||||||
if p.is_dir() {
|
if p.is_dir() {
|
||||||
|
@ -675,12 +691,14 @@ mod tests {
|
||||||
};
|
};
|
||||||
|
|
||||||
let result = collect_specifiers(
|
let result = collect_specifiers(
|
||||||
vec![
|
&FilesConfig {
|
||||||
"http://localhost:8080".to_string(),
|
include: vec![
|
||||||
root_dir_path.to_str().unwrap().to_string(),
|
PathBuf::from("http://localhost:8080"),
|
||||||
"https://localhost:8080".to_string(),
|
root_dir_path.clone(),
|
||||||
|
PathBuf::from("https://localhost:8080".to_string()),
|
||||||
],
|
],
|
||||||
&[ignore_dir_path],
|
exclude: vec![ignore_dir_path],
|
||||||
|
},
|
||||||
predicate,
|
predicate,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -713,7 +731,8 @@ mod tests {
|
||||||
"file://"
|
"file://"
|
||||||
};
|
};
|
||||||
let result = collect_specifiers(
|
let result = collect_specifiers(
|
||||||
vec![format!(
|
&FilesConfig {
|
||||||
|
include: vec![PathBuf::from(format!(
|
||||||
"{}{}",
|
"{}{}",
|
||||||
scheme,
|
scheme,
|
||||||
root_dir_path
|
root_dir_path
|
||||||
|
@ -721,8 +740,9 @@ mod tests {
|
||||||
.to_str()
|
.to_str()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.replace('\\', "/")
|
.replace('\\', "/")
|
||||||
)],
|
))],
|
||||||
&[],
|
exclude: vec![],
|
||||||
|
},
|
||||||
predicate,
|
predicate,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
Loading…
Reference in a new issue