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