mirror of
https://github.com/denoland/deno.git
synced 2025-01-21 04:52:26 -05:00
Compare commits
54 commits
12c1350cad
...
2f95718c6a
Author | SHA1 | Date | |
---|---|---|---|
|
2f95718c6a | ||
|
01fb217e9b | ||
|
f61286bf4b | ||
|
e91b0efd17 | ||
|
60de9fa6b1 | ||
|
03cb9732a7 | ||
|
1c2fb5cde1 | ||
|
9f8d83356f | ||
|
c7f28998d9 | ||
|
f5b258cfdb | ||
|
5807b53dae | ||
|
5d76fc9d3e | ||
|
9a6263c1ce | ||
|
161468a0f5 | ||
|
ff1f921c1d | ||
|
f45d39b20b | ||
|
0e2f9e7c10 | ||
|
8f5d50c787 | ||
|
f8be309def | ||
|
de37f41e13 | ||
|
83ee4c9a73 | ||
|
37d45d0e84 | ||
|
b8b9eea548 | ||
|
0c188ebab9 | ||
|
1af0cdee0a | ||
|
78de1fb248 | ||
|
0c44814e21 | ||
|
61aa023d92 | ||
|
42eb554edf | ||
|
c22b0e4954 | ||
|
655190e82b | ||
|
dab83524b8 | ||
|
4d081d2cfc | ||
|
7ceeb0ba20 | ||
|
59511cba6a | ||
|
e33d51dea9 | ||
|
f36d70d194 | ||
|
871750aaae | ||
|
b3bd581919 | ||
|
de4e641360 | ||
|
6499ad6ae7 | ||
|
14b3eb2789 | ||
|
c521bfbc44 | ||
|
6b73819d12 | ||
|
3e9a63f8ce | ||
|
6e3ceddf17 | ||
|
874260d0ce | ||
|
b71605088a | ||
|
27561dd485 | ||
|
7a3a73c782 | ||
|
9707974671 | ||
|
8f5465e5ef | ||
|
88f7510b95 | ||
|
d52ccd2834 |
26 changed files with 876 additions and 732 deletions
3
Cargo.lock
generated
3
Cargo.lock
generated
|
@ -1495,8 +1495,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "deno_config"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b45aaf31e58ca915d5c0746bf8e2d07b94635154ad9e5afe5ff265cae6187b19"
|
||||
source = "git+https://github.com/denoland/deno_config.git?rev=4cbb63704442a7834dc6bed2e7e310a0d46ade09#4cbb63704442a7834dc6bed2e7e310a0d46ade09"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"deno_package_json",
|
||||
|
|
|
@ -51,7 +51,8 @@ deno_ast = { version = "=0.44.0", features = ["transpiling"] }
|
|||
deno_core = { version = "0.327.0" }
|
||||
|
||||
deno_bench_util = { version = "0.178.0", path = "./bench_util" }
|
||||
deno_config = { version = "=0.42.0", features = ["workspace", "sync"] }
|
||||
# TODO(nayeemrmn): Use proper version when https://github.com/denoland/deno_config/pull/143 lands!
|
||||
deno_config = { git = "https://github.com/denoland/deno_config.git", rev = "4cbb63704442a7834dc6bed2e7e310a0d46ade09", features = ["workspace", "sync"] }
|
||||
deno_lockfile = "=0.24.0"
|
||||
deno_media_type = { version = "0.2.3", features = ["module_specifier"] }
|
||||
deno_npm = "=0.27.0"
|
||||
|
|
|
@ -1095,6 +1095,14 @@ impl Flags {
|
|||
Ok(PathOrPatternSet::default())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_discovered_config(&self) -> bool {
|
||||
match self.config_flag {
|
||||
ConfigFlag::Discover => true,
|
||||
ConfigFlag::Path(_) => false,
|
||||
ConfigFlag::Disabled => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static ENV_VARIABLES_HELP: &str = cstr!(
|
||||
|
|
262
cli/args/mod.rs
262
cli/args/mod.rs
|
@ -8,6 +8,7 @@ mod lockfile;
|
|||
mod package_json;
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::collections::BTreeSet;
|
||||
use std::collections::HashMap;
|
||||
use std::env;
|
||||
use std::io::BufReader;
|
||||
|
@ -15,7 +16,6 @@ use std::io::Cursor;
|
|||
use std::io::Read;
|
||||
use std::io::Seek;
|
||||
use std::net::SocketAddr;
|
||||
use std::num::NonZeroUsize;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
|
@ -218,22 +218,6 @@ pub fn ts_config_to_transpile_and_emit_options(
|
|||
))
|
||||
}
|
||||
|
||||
pub struct WorkspaceBenchOptions {
|
||||
pub filter: Option<String>,
|
||||
pub json: bool,
|
||||
pub no_run: bool,
|
||||
}
|
||||
|
||||
impl WorkspaceBenchOptions {
|
||||
pub fn resolve(bench_flags: &BenchFlags) -> Self {
|
||||
Self {
|
||||
filter: bench_flags.filter.clone(),
|
||||
json: bench_flags.json,
|
||||
no_run: bench_flags.no_run,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct BenchOptions {
|
||||
pub files: FilePatterns,
|
||||
|
@ -329,41 +313,6 @@ fn resolve_fmt_options(
|
|||
options
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct WorkspaceTestOptions {
|
||||
pub doc: bool,
|
||||
pub no_run: bool,
|
||||
pub fail_fast: Option<NonZeroUsize>,
|
||||
pub permit_no_files: bool,
|
||||
pub filter: Option<String>,
|
||||
pub shuffle: Option<u64>,
|
||||
pub concurrent_jobs: NonZeroUsize,
|
||||
pub trace_leaks: bool,
|
||||
pub reporter: TestReporterConfig,
|
||||
pub junit_path: Option<String>,
|
||||
pub hide_stacktraces: bool,
|
||||
}
|
||||
|
||||
impl WorkspaceTestOptions {
|
||||
pub fn resolve(test_flags: &TestFlags) -> Self {
|
||||
Self {
|
||||
permit_no_files: test_flags.permit_no_files,
|
||||
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.clone(),
|
||||
no_run: test_flags.no_run,
|
||||
shuffle: test_flags.shuffle,
|
||||
trace_leaks: test_flags.trace_leaks,
|
||||
reporter: test_flags.reporter,
|
||||
junit_path: test_flags.junit_path.clone(),
|
||||
hide_stacktraces: test_flags.hide_stacktraces,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct TestOptions {
|
||||
pub files: FilePatterns,
|
||||
|
@ -752,6 +701,30 @@ struct CliOptionOverrides {
|
|||
import_map_specifier: Option<Option<ModuleSpecifier>>,
|
||||
}
|
||||
|
||||
/// Overrides for the options below that when set will
|
||||
/// use these values over the values derived from the
|
||||
/// CLI flags or config file.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ScopeOptions {
|
||||
pub scope: Option<Arc<ModuleSpecifier>>,
|
||||
pub all_scopes: Arc<BTreeSet<Arc<ModuleSpecifier>>>,
|
||||
}
|
||||
|
||||
fn load_external_import_map(
|
||||
deno_json: &ConfigFile,
|
||||
) -> Result<Option<(PathBuf, serde_json::Value)>, AnyError> {
|
||||
if !deno_json.is_an_import_map() {
|
||||
if let Some(path) = deno_json.to_import_map_path()? {
|
||||
let contents = std::fs::read_to_string(&path).with_context(|| {
|
||||
format!("Unable to read import map at '{}'", path.display())
|
||||
})?;
|
||||
let map = serde_json::from_str(&contents)?;
|
||||
return Ok(Some((path, map)));
|
||||
}
|
||||
}
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
/// Holds the resolved options of many sources used by subcommands
|
||||
/// and provides some helper function for creating common objects.
|
||||
pub struct CliOptions {
|
||||
|
@ -764,9 +737,11 @@ pub struct CliOptions {
|
|||
npmrc: Arc<ResolvedNpmRc>,
|
||||
maybe_lockfile: Option<Arc<CliLockfile>>,
|
||||
maybe_external_import_map: Option<(PathBuf, serde_json::Value)>,
|
||||
sys: CliSys,
|
||||
overrides: CliOptionOverrides,
|
||||
pub start_dir: Arc<WorkspaceDirectory>,
|
||||
pub deno_dir_provider: Arc<DenoDirProvider>,
|
||||
pub scope_options: Option<Arc<ScopeOptions>>,
|
||||
}
|
||||
|
||||
impl CliOptions {
|
||||
|
@ -780,6 +755,7 @@ impl CliOptions {
|
|||
start_dir: Arc<WorkspaceDirectory>,
|
||||
force_global_cache: bool,
|
||||
maybe_external_import_map: Option<(PathBuf, serde_json::Value)>,
|
||||
scope_options: Option<Arc<ScopeOptions>>,
|
||||
) -> Result<Self, AnyError> {
|
||||
if let Some(insecure_allowlist) =
|
||||
flags.unsafely_ignore_certificate_errors.as_ref()
|
||||
|
@ -822,6 +798,8 @@ impl CliOptions {
|
|||
maybe_external_import_map,
|
||||
start_dir,
|
||||
deno_dir_provider,
|
||||
sys: sys.clone(),
|
||||
scope_options,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -896,21 +874,6 @@ impl CliOptions {
|
|||
|
||||
let (npmrc, _) = discover_npmrc_from_workspace(&start_dir.workspace)?;
|
||||
|
||||
fn load_external_import_map(
|
||||
deno_json: &ConfigFile,
|
||||
) -> Result<Option<(PathBuf, serde_json::Value)>, AnyError> {
|
||||
if !deno_json.is_an_import_map() {
|
||||
if let Some(path) = deno_json.to_import_map_path()? {
|
||||
let contents = std::fs::read_to_string(&path).with_context(|| {
|
||||
format!("Unable to read import map at '{}'", path.display())
|
||||
})?;
|
||||
let map = serde_json::from_str(&contents)?;
|
||||
return Ok(Some((path, map)));
|
||||
}
|
||||
}
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
let external_import_map =
|
||||
if let Some(deno_json) = start_dir.workspace.root_deno_json() {
|
||||
load_external_import_map(deno_json)?
|
||||
|
@ -936,6 +899,38 @@ impl CliOptions {
|
|||
Arc::new(start_dir),
|
||||
false,
|
||||
external_import_map,
|
||||
None,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn with_new_start_dir_and_scope_options(
|
||||
&self,
|
||||
start_dir: Arc<WorkspaceDirectory>,
|
||||
scope_options: Option<ScopeOptions>,
|
||||
) -> Result<Self, AnyError> {
|
||||
let (npmrc, _) = discover_npmrc_from_workspace(&start_dir.workspace)?;
|
||||
let external_import_map =
|
||||
if let Some(deno_json) = start_dir.workspace.root_deno_json() {
|
||||
load_external_import_map(deno_json)?
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let lockfile = CliLockfile::discover(
|
||||
&self.sys,
|
||||
&self.flags,
|
||||
&start_dir.workspace,
|
||||
external_import_map.as_ref().map(|(_, v)| v),
|
||||
)?;
|
||||
Self::new(
|
||||
&self.sys,
|
||||
self.flags.clone(),
|
||||
self.initial_cwd().to_path_buf(),
|
||||
lockfile.map(Arc::new),
|
||||
npmrc,
|
||||
start_dir,
|
||||
false,
|
||||
external_import_map,
|
||||
scope_options.map(Arc::new),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -1261,7 +1256,7 @@ impl CliOptions {
|
|||
&self,
|
||||
config_type: TsConfigType,
|
||||
) -> Result<TsConfigForEmit, AnyError> {
|
||||
self.workspace().resolve_ts_config_for_emit(config_type)
|
||||
self.start_dir.to_ts_config_for_emit(config_type)
|
||||
}
|
||||
|
||||
pub fn resolve_inspector_server(
|
||||
|
@ -1291,7 +1286,7 @@ impl CliOptions {
|
|||
&self,
|
||||
) -> Result<Vec<deno_graph::ReferrerImports>, AnyError> {
|
||||
self
|
||||
.workspace()
|
||||
.start_dir
|
||||
.to_compiler_option_types()
|
||||
.map(|maybe_imports| {
|
||||
maybe_imports
|
||||
|
@ -1311,12 +1306,22 @@ impl CliOptions {
|
|||
pub fn resolve_fmt_options_for_members(
|
||||
&self,
|
||||
fmt_flags: &FmtFlags,
|
||||
) -> Result<Vec<(WorkspaceDirectory, FmtOptions)>, AnyError> {
|
||||
) -> Result<Vec<(Arc<WorkspaceDirectory>, FmtOptions)>, AnyError> {
|
||||
let cli_arg_patterns =
|
||||
fmt_flags.files.as_file_patterns(self.initial_cwd())?;
|
||||
let member_configs = self
|
||||
.workspace()
|
||||
.resolve_fmt_config_for_members(&cli_arg_patterns)?;
|
||||
let member_configs = if self.flags.is_discovered_config() {
|
||||
self
|
||||
.workspace()
|
||||
.resolve_fmt_config_for_members(&cli_arg_patterns)?
|
||||
.into_iter()
|
||||
.map(|(d, c)| (Arc::new(d), c))
|
||||
.collect::<Vec<_>>()
|
||||
} else {
|
||||
vec![(
|
||||
self.start_dir.clone(),
|
||||
self.start_dir.to_fmt_config(cli_arg_patterns)?,
|
||||
)]
|
||||
};
|
||||
let unstable = self.resolve_config_unstable_fmt_options();
|
||||
let mut result = Vec::with_capacity(member_configs.len());
|
||||
for (ctx, config) in member_configs {
|
||||
|
@ -1342,15 +1347,46 @@ impl CliOptions {
|
|||
WorkspaceLintOptions::resolve(&lint_config, lint_flags)
|
||||
}
|
||||
|
||||
pub fn resolve_file_flags_for_members(
|
||||
&self,
|
||||
file_flags: &FileFlags,
|
||||
) -> Result<Vec<(Arc<WorkspaceDirectory>, FilePatterns)>, AnyError> {
|
||||
let cli_arg_patterns = file_flags.as_file_patterns(self.initial_cwd())?;
|
||||
let member_patterns = if self.flags.is_discovered_config() {
|
||||
self
|
||||
.workspace()
|
||||
.resolve_file_patterns_for_members(&cli_arg_patterns)?
|
||||
.into_iter()
|
||||
.map(|(d, p)| (Arc::new(d), p))
|
||||
.collect::<Vec<_>>()
|
||||
} else {
|
||||
vec![(
|
||||
self.start_dir.clone(),
|
||||
self.start_dir.to_resolved_file_patterns(cli_arg_patterns)?,
|
||||
)]
|
||||
};
|
||||
Ok(member_patterns)
|
||||
}
|
||||
|
||||
pub fn resolve_lint_options_for_members(
|
||||
&self,
|
||||
lint_flags: &LintFlags,
|
||||
) -> Result<Vec<(WorkspaceDirectory, LintOptions)>, AnyError> {
|
||||
) -> Result<Vec<(Arc<WorkspaceDirectory>, LintOptions)>, AnyError> {
|
||||
let cli_arg_patterns =
|
||||
lint_flags.files.as_file_patterns(self.initial_cwd())?;
|
||||
let member_configs = self
|
||||
.workspace()
|
||||
.resolve_lint_config_for_members(&cli_arg_patterns)?;
|
||||
let member_configs = if self.flags.is_discovered_config() {
|
||||
self
|
||||
.workspace()
|
||||
.resolve_lint_config_for_members(&cli_arg_patterns)?
|
||||
.into_iter()
|
||||
.map(|(d, c)| (Arc::new(d), c))
|
||||
.collect::<Vec<_>>()
|
||||
} else {
|
||||
vec![(
|
||||
self.start_dir.clone(),
|
||||
self.start_dir.to_lint_config(cli_arg_patterns)?,
|
||||
)]
|
||||
};
|
||||
let mut result = Vec::with_capacity(member_configs.len());
|
||||
for (ctx, config) in member_configs {
|
||||
let options = LintOptions::resolve(config, lint_flags);
|
||||
|
@ -1376,52 +1412,54 @@ impl CliOptions {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn resolve_workspace_test_options(
|
||||
&self,
|
||||
test_flags: &TestFlags,
|
||||
) -> WorkspaceTestOptions {
|
||||
WorkspaceTestOptions::resolve(test_flags)
|
||||
}
|
||||
|
||||
pub fn resolve_test_options_for_members(
|
||||
&self,
|
||||
test_flags: &TestFlags,
|
||||
) -> Result<Vec<(WorkspaceDirectory, TestOptions)>, AnyError> {
|
||||
) -> Result<Vec<(Arc<WorkspaceDirectory>, TestOptions)>, AnyError> {
|
||||
let cli_arg_patterns =
|
||||
test_flags.files.as_file_patterns(self.initial_cwd())?;
|
||||
let workspace_dir_configs = self
|
||||
.workspace()
|
||||
.resolve_test_config_for_members(&cli_arg_patterns)?;
|
||||
let mut result = Vec::with_capacity(workspace_dir_configs.len());
|
||||
for (member_dir, config) in workspace_dir_configs {
|
||||
let options = TestOptions::resolve(config, test_flags);
|
||||
result.push((member_dir, options));
|
||||
}
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
pub fn resolve_workspace_bench_options(
|
||||
&self,
|
||||
bench_flags: &BenchFlags,
|
||||
) -> WorkspaceBenchOptions {
|
||||
WorkspaceBenchOptions::resolve(bench_flags)
|
||||
let member_options = if self.flags.is_discovered_config() {
|
||||
self
|
||||
.workspace()
|
||||
.resolve_test_config_for_members(&cli_arg_patterns)?
|
||||
.into_iter()
|
||||
.map(|(d, c)| (Arc::new(d), TestOptions::resolve(c, test_flags)))
|
||||
.collect::<Vec<_>>()
|
||||
} else {
|
||||
vec![(
|
||||
self.start_dir.clone(),
|
||||
TestOptions::resolve(
|
||||
self.start_dir.to_test_config(cli_arg_patterns)?,
|
||||
test_flags,
|
||||
),
|
||||
)]
|
||||
};
|
||||
Ok(member_options)
|
||||
}
|
||||
|
||||
pub fn resolve_bench_options_for_members(
|
||||
&self,
|
||||
bench_flags: &BenchFlags,
|
||||
) -> Result<Vec<(WorkspaceDirectory, BenchOptions)>, AnyError> {
|
||||
) -> Result<Vec<(Arc<WorkspaceDirectory>, BenchOptions)>, AnyError> {
|
||||
let cli_arg_patterns =
|
||||
bench_flags.files.as_file_patterns(self.initial_cwd())?;
|
||||
let workspace_dir_configs = self
|
||||
.workspace()
|
||||
.resolve_bench_config_for_members(&cli_arg_patterns)?;
|
||||
let mut result = Vec::with_capacity(workspace_dir_configs.len());
|
||||
for (member_dir, config) in workspace_dir_configs {
|
||||
let options = BenchOptions::resolve(config, bench_flags);
|
||||
result.push((member_dir, options));
|
||||
}
|
||||
Ok(result)
|
||||
let member_options = if self.flags.is_discovered_config() {
|
||||
self
|
||||
.workspace()
|
||||
.resolve_bench_config_for_members(&cli_arg_patterns)?
|
||||
.into_iter()
|
||||
.map(|(d, c)| (Arc::new(d), BenchOptions::resolve(c, bench_flags)))
|
||||
.collect::<Vec<_>>()
|
||||
} else {
|
||||
vec![(
|
||||
self.start_dir.clone(),
|
||||
BenchOptions::resolve(
|
||||
self.start_dir.to_bench_config(cli_arg_patterns)?,
|
||||
bench_flags,
|
||||
),
|
||||
)]
|
||||
};
|
||||
Ok(member_options)
|
||||
}
|
||||
|
||||
/// Vector of user script CLI arguments.
|
||||
|
@ -1438,7 +1476,7 @@ impl CliOptions {
|
|||
}
|
||||
|
||||
pub fn check_js(&self) -> bool {
|
||||
self.workspace().check_js()
|
||||
self.start_dir.check_js()
|
||||
}
|
||||
|
||||
pub fn coverage_dir(&self) -> Option<String> {
|
||||
|
|
256
cli/factory.rs
256
cli/factory.rs
|
@ -1,15 +1,23 @@
|
|||
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||
|
||||
use std::collections::BTreeSet;
|
||||
use std::collections::HashSet;
|
||||
use std::future::Future;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
|
||||
use deno_ast::ModuleSpecifier;
|
||||
use deno_cache_dir::file_fetcher::File;
|
||||
use deno_cache_dir::npm::NpmCacheDir;
|
||||
use deno_config::glob::FilePatterns;
|
||||
use deno_config::workspace::PackageJsonDepResolution;
|
||||
use deno_config::workspace::WorkspaceDirectory;
|
||||
use deno_config::workspace::WorkspaceResolver;
|
||||
use deno_core::anyhow::anyhow;
|
||||
use deno_core::error::AnyError;
|
||||
use deno_core::futures::FutureExt;
|
||||
use deno_core::FeatureChecker;
|
||||
use deno_path_util::url_to_file_path;
|
||||
use deno_resolver::cjs::IsCjsResolutionMode;
|
||||
use deno_resolver::npm::NpmReqResolverOptions;
|
||||
use deno_resolver::DenoResolverOptions;
|
||||
|
@ -19,6 +27,7 @@ use deno_runtime::deno_fs::RealFs;
|
|||
use deno_runtime::deno_node::RealIsBuiltInNodeModuleChecker;
|
||||
use deno_runtime::deno_permissions::Permissions;
|
||||
use deno_runtime::deno_permissions::PermissionsContainer;
|
||||
use deno_runtime::deno_permissions::PermissionsOptions;
|
||||
use deno_runtime::deno_tls::rustls::RootCertStore;
|
||||
use deno_runtime::deno_tls::RootCertStoreProvider;
|
||||
use deno_runtime::deno_web::BlobStore;
|
||||
|
@ -36,6 +45,7 @@ use crate::args::CliOptions;
|
|||
use crate::args::DenoSubcommand;
|
||||
use crate::args::Flags;
|
||||
use crate::args::NpmInstallDepsProvider;
|
||||
use crate::args::ScopeOptions;
|
||||
use crate::args::StorageKeyResolver;
|
||||
use crate::args::TsConfigType;
|
||||
use crate::cache::Caches;
|
||||
|
@ -83,12 +93,15 @@ use crate::resolver::NpmModuleLoader;
|
|||
use crate::resolver::SloppyImportsCachedFs;
|
||||
use crate::standalone::binary::DenoCompileBinaryWriter;
|
||||
use crate::sys::CliSys;
|
||||
use crate::tools::check::MaybeDiagnostics;
|
||||
use crate::tools::check::TypeChecker;
|
||||
use crate::tools::coverage::CoverageCollector;
|
||||
use crate::tools::lint::LintRuleProvider;
|
||||
use crate::tools::run::hmr::HmrRunner;
|
||||
use crate::tsc::Diagnostics;
|
||||
use crate::tsc::TypeCheckingCjsTracker;
|
||||
use crate::util::file_watcher::WatcherCommunicator;
|
||||
use crate::util::fs::canonicalize_path;
|
||||
use crate::util::fs::canonicalize_path_maybe_not_exists;
|
||||
use crate::util::progress_bar::ProgressBar;
|
||||
use crate::util::progress_bar::ProgressBarStyle;
|
||||
|
@ -1075,3 +1088,246 @@ impl CliFactory {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct SpecifierInfo {
|
||||
/// Type check as an ES module.
|
||||
pub check: bool,
|
||||
/// Type check virtual modules from doc snippets. If this is set but `check`
|
||||
/// is not, this may be a markdown file for example.
|
||||
pub check_doc: bool,
|
||||
}
|
||||
|
||||
pub struct WorkspaceDirFilesFactory {
|
||||
specifiers: Vec<(ModuleSpecifier, SpecifierInfo)>,
|
||||
doc_snippet_specifiers: Vec<ModuleSpecifier>,
|
||||
cli_options: Arc<CliOptions>,
|
||||
cli_factory: CliFactory,
|
||||
permissions_options: Deferred<PermissionsOptions>,
|
||||
}
|
||||
|
||||
impl WorkspaceDirFilesFactory {
|
||||
pub fn checked_specifiers(&self) -> impl Iterator<Item = &ModuleSpecifier> {
|
||||
self
|
||||
.specifiers
|
||||
.iter()
|
||||
.filter_map(|(s, i)| i.check.then_some(s))
|
||||
.chain(self.doc_snippet_specifiers.iter())
|
||||
}
|
||||
|
||||
pub async fn dependent_checked_specifiers(
|
||||
&self,
|
||||
canonicalized_dep_paths: &HashSet<PathBuf>,
|
||||
) -> Result<Vec<&ModuleSpecifier>, AnyError> {
|
||||
let graph_kind = self
|
||||
.cli_factory
|
||||
.cli_options()?
|
||||
.type_check_mode()
|
||||
.as_graph_kind();
|
||||
let module_graph_creator = self.cli_factory.module_graph_creator().await?;
|
||||
let specifiers = self.checked_specifiers().cloned().collect::<Vec<_>>();
|
||||
let graph = module_graph_creator
|
||||
.create_graph(
|
||||
graph_kind,
|
||||
specifiers.clone(),
|
||||
crate::graph_util::NpmCachingStrategy::Eager,
|
||||
)
|
||||
.await?;
|
||||
module_graph_creator.graph_valid(&graph)?;
|
||||
let dependent_specifiers = self
|
||||
.checked_specifiers()
|
||||
.filter(|s| {
|
||||
let mut dependency_specifiers = graph.walk(
|
||||
std::iter::once(*s),
|
||||
deno_graph::WalkOptions {
|
||||
follow_dynamic: true,
|
||||
kind: deno_graph::GraphKind::All,
|
||||
prefer_fast_check_graph: true,
|
||||
check_js: true,
|
||||
},
|
||||
);
|
||||
while let Some((s, _)) = dependency_specifiers.next() {
|
||||
if let Ok(path) = url_to_file_path(s) {
|
||||
if let Ok(path) = canonicalize_path(&path) {
|
||||
if canonicalized_dep_paths.contains(&path) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// skip walking this remote module's dependencies
|
||||
dependency_specifiers.skip_previous_dependencies();
|
||||
}
|
||||
}
|
||||
false
|
||||
})
|
||||
.collect();
|
||||
Ok(dependent_specifiers)
|
||||
}
|
||||
|
||||
pub fn permissions_options(&self) -> &PermissionsOptions {
|
||||
self
|
||||
.permissions_options
|
||||
.get_or_init(|| self.cli_options.permissions_options())
|
||||
}
|
||||
|
||||
pub fn permission_desc_parser(
|
||||
&self,
|
||||
) -> Result<&Arc<RuntimePermissionDescriptorParser<CliSys>>, AnyError> {
|
||||
self.cli_factory.permission_desc_parser()
|
||||
}
|
||||
|
||||
pub async fn create_cli_main_worker_factory(
|
||||
&self,
|
||||
) -> Result<CliMainWorkerFactory, AnyError> {
|
||||
self.cli_factory.create_cli_main_worker_factory().await
|
||||
}
|
||||
}
|
||||
|
||||
pub struct WorkspaceFilesFactory {
|
||||
dirs: Vec<WorkspaceDirFilesFactory>,
|
||||
initial_cwd: PathBuf,
|
||||
}
|
||||
|
||||
impl WorkspaceFilesFactory {
|
||||
#[allow(clippy::type_complexity)]
|
||||
pub async fn from_workspace_dirs_with_files<T: Clone>(
|
||||
mut workspace_dirs_with_files: Vec<(Arc<WorkspaceDirectory>, FilePatterns)>,
|
||||
collect_specifiers: fn(
|
||||
FilePatterns,
|
||||
Arc<CliOptions>,
|
||||
Arc<CliFileFetcher>,
|
||||
T,
|
||||
) -> std::pin::Pin<
|
||||
Box<
|
||||
dyn Future<
|
||||
Output = Result<Vec<(ModuleSpecifier, SpecifierInfo)>, AnyError>,
|
||||
>,
|
||||
>,
|
||||
>,
|
||||
args: T,
|
||||
extract_doc_files: Option<fn(File) -> Result<Vec<File>, AnyError>>,
|
||||
cli_options: &CliOptions,
|
||||
watcher_communicator: Option<&Arc<WatcherCommunicator>>,
|
||||
) -> Result<Self, AnyError> {
|
||||
let initial_cwd = cli_options.initial_cwd().to_path_buf();
|
||||
if let Some(watcher_communicator) = watcher_communicator {
|
||||
let _ = watcher_communicator.watch_paths(cli_options.watch_paths());
|
||||
}
|
||||
workspace_dirs_with_files.sort_by_cached_key(|(d, _)| d.dir_url().clone());
|
||||
let all_scopes = Arc::new(
|
||||
workspace_dirs_with_files
|
||||
.iter()
|
||||
.filter(|(d, _)| d.has_deno_or_pkg_json())
|
||||
.map(|(d, _)| d.dir_url().clone())
|
||||
.collect::<BTreeSet<_>>(),
|
||||
);
|
||||
let dir_count = workspace_dirs_with_files.len();
|
||||
let mut dirs = Vec::with_capacity(dir_count);
|
||||
for (workspace_dir, files) in workspace_dirs_with_files {
|
||||
if let Some(watcher_communicator) = watcher_communicator {
|
||||
let _ = watcher_communicator.watch_paths(
|
||||
files
|
||||
.include
|
||||
.iter()
|
||||
.flat_map(|set| set.base_paths())
|
||||
.collect(),
|
||||
);
|
||||
}
|
||||
let scope_options = (dir_count > 1).then(|| ScopeOptions {
|
||||
scope: workspace_dir
|
||||
.has_deno_or_pkg_json()
|
||||
.then(|| workspace_dir.dir_url().clone()),
|
||||
all_scopes: all_scopes.clone(),
|
||||
});
|
||||
let cli_options = Arc::new(
|
||||
cli_options
|
||||
.with_new_start_dir_and_scope_options(workspace_dir, scope_options)?,
|
||||
);
|
||||
let mut factory = CliFactory::from_cli_options(cli_options.clone());
|
||||
factory.watcher_communicator = watcher_communicator.cloned();
|
||||
let file_fetcher = factory.file_fetcher()?;
|
||||
let specifiers = collect_specifiers(
|
||||
files,
|
||||
cli_options.clone(),
|
||||
file_fetcher.clone(),
|
||||
args.clone(),
|
||||
)
|
||||
.await?;
|
||||
let mut doc_snippet_specifiers = vec![];
|
||||
if let Some(extract_doc_files) = extract_doc_files {
|
||||
let root_permissions = factory.root_permissions_container()?;
|
||||
for (s, _) in specifiers.iter().filter(|(_, i)| i.check_doc) {
|
||||
let file = file_fetcher.fetch(s, root_permissions).await?;
|
||||
let snippet_files = extract_doc_files(file)?;
|
||||
for snippet_file in snippet_files {
|
||||
doc_snippet_specifiers.push(snippet_file.url.clone());
|
||||
file_fetcher.insert_memory_files(snippet_file);
|
||||
}
|
||||
}
|
||||
}
|
||||
dirs.push(WorkspaceDirFilesFactory {
|
||||
specifiers,
|
||||
doc_snippet_specifiers,
|
||||
cli_options,
|
||||
cli_factory: factory,
|
||||
permissions_options: Default::default(),
|
||||
});
|
||||
}
|
||||
Ok(Self { dirs, initial_cwd })
|
||||
}
|
||||
|
||||
pub fn dirs(&self) -> &Vec<WorkspaceDirFilesFactory> {
|
||||
&self.dirs
|
||||
}
|
||||
|
||||
pub fn initial_cwd(&self) -> &PathBuf {
|
||||
&self.initial_cwd
|
||||
}
|
||||
|
||||
pub fn found_specifiers(&self) -> bool {
|
||||
self.dirs.iter().any(|e| !e.specifiers.is_empty())
|
||||
}
|
||||
|
||||
pub async fn check(&self) -> Result<(), AnyError> {
|
||||
let mut diagnostics = vec![];
|
||||
let mut all_errors = vec![];
|
||||
for entry in &self.dirs {
|
||||
let main_graph_container = entry
|
||||
.cli_factory
|
||||
.main_module_graph_container()
|
||||
.await?
|
||||
.clone();
|
||||
let specifiers_for_typecheck =
|
||||
entry.checked_specifiers().cloned().collect::<Vec<_>>();
|
||||
if specifiers_for_typecheck.is_empty() {
|
||||
continue;
|
||||
}
|
||||
let ext_flag = entry.cli_factory.cli_options()?.ext_flag().as_ref();
|
||||
if let Err(err) = main_graph_container
|
||||
.check_specifiers(&specifiers_for_typecheck, ext_flag)
|
||||
.await
|
||||
{
|
||||
match err {
|
||||
MaybeDiagnostics::Diagnostics(Diagnostics(d)) => {
|
||||
diagnostics.extend(d)
|
||||
}
|
||||
MaybeDiagnostics::Other(err) => all_errors.push(err),
|
||||
}
|
||||
}
|
||||
}
|
||||
if !diagnostics.is_empty() {
|
||||
all_errors.push(AnyError::from(Diagnostics(diagnostics)));
|
||||
}
|
||||
if !all_errors.is_empty() {
|
||||
return Err(anyhow!(
|
||||
"{}",
|
||||
all_errors
|
||||
.into_iter()
|
||||
.map(|e| e.to_string())
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n\n"),
|
||||
));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ use deno_runtime::deno_permissions::PermissionsContainer;
|
|||
|
||||
use crate::args::CliOptions;
|
||||
use crate::module_loader::ModuleLoadPreparer;
|
||||
use crate::tools::check::MaybeDiagnostics;
|
||||
use crate::util::fs::collect_specifiers;
|
||||
use crate::util::path::is_script_ext;
|
||||
|
||||
|
@ -69,7 +70,7 @@ impl MainModuleGraphContainer {
|
|||
&self,
|
||||
specifiers: &[ModuleSpecifier],
|
||||
ext_overwrite: Option<&String>,
|
||||
) -> Result<(), AnyError> {
|
||||
) -> Result<(), MaybeDiagnostics> {
|
||||
let mut graph_permit = self.acquire_update_permit().await;
|
||||
let graph = graph_permit.graph_mut();
|
||||
self
|
||||
|
@ -99,7 +100,7 @@ impl MainModuleGraphContainer {
|
|||
log::warn!("{} No matching files found.", colors::yellow("Warning"));
|
||||
}
|
||||
|
||||
self.check_specifiers(&specifiers, None).await
|
||||
Ok(self.check_specifiers(&specifiers, None).await?)
|
||||
}
|
||||
|
||||
pub fn collect_specifiers(
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||
|
||||
use std::collections::HashSet;
|
||||
use std::error::Error;
|
||||
use std::ops::Deref;
|
||||
use std::path::PathBuf;
|
||||
|
@ -27,7 +26,6 @@ use deno_graph::ModuleLoadError;
|
|||
use deno_graph::ResolutionError;
|
||||
use deno_graph::SpecifierError;
|
||||
use deno_graph::WorkspaceFastCheckOption;
|
||||
use deno_path_util::url_to_file_path;
|
||||
use deno_resolver::sloppy_imports::SloppyImportsResolutionKind;
|
||||
use deno_runtime::deno_node;
|
||||
use deno_runtime::deno_permissions::PermissionsContainer;
|
||||
|
@ -61,7 +59,6 @@ use crate::sys::CliSys;
|
|||
use crate::tools::check;
|
||||
use crate::tools::check::TypeChecker;
|
||||
use crate::util::file_watcher::WatcherCommunicator;
|
||||
use crate::util::fs::canonicalize_path;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct GraphValidOptions {
|
||||
|
@ -458,6 +455,7 @@ impl ModuleGraphCreator {
|
|||
},
|
||||
)
|
||||
.await
|
||||
.map_err(AnyError::from)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -835,7 +833,7 @@ impl ModuleGraphBuilder {
|
|||
fn create_graph_resolver(&self) -> Result<CliGraphResolver, AnyError> {
|
||||
let jsx_import_source_config = self
|
||||
.cli_options
|
||||
.workspace()
|
||||
.start_dir
|
||||
.to_maybe_jsx_import_source_config()?;
|
||||
Ok(CliGraphResolver {
|
||||
cjs_tracker: &self.cjs_tracker,
|
||||
|
@ -1060,37 +1058,6 @@ fn get_import_prefix_missing_error(error: &ResolutionError) -> Option<&str> {
|
|||
maybe_specifier.map(|s| s.as_str())
|
||||
}
|
||||
|
||||
/// Gets if any of the specified root's "file:" dependents are in the
|
||||
/// provided changed set.
|
||||
pub fn has_graph_root_local_dependent_changed(
|
||||
graph: &ModuleGraph,
|
||||
root: &ModuleSpecifier,
|
||||
canonicalized_changed_paths: &HashSet<PathBuf>,
|
||||
) -> bool {
|
||||
let mut dependent_specifiers = graph.walk(
|
||||
std::iter::once(root),
|
||||
deno_graph::WalkOptions {
|
||||
follow_dynamic: true,
|
||||
kind: GraphKind::All,
|
||||
prefer_fast_check_graph: true,
|
||||
check_js: true,
|
||||
},
|
||||
);
|
||||
while let Some((s, _)) = dependent_specifiers.next() {
|
||||
if let Ok(path) = url_to_file_path(s) {
|
||||
if let Ok(path) = canonicalize_path(&path) {
|
||||
if canonicalized_changed_paths.contains(&path) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// skip walking this remote module's dependencies
|
||||
dependent_specifiers.skip_previous_dependencies();
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct FileWatcherReporter {
|
||||
watcher_communicator: Arc<WatcherCommunicator>,
|
||||
|
|
|
@ -1426,7 +1426,9 @@ impl ConfigData {
|
|||
);
|
||||
|
||||
let ts_config = LspTsConfig::new(
|
||||
member_dir.workspace.root_deno_json().map(|c| c.as_ref()),
|
||||
member_dir
|
||||
.deno_json_for_compiler_options()
|
||||
.map(|c| c.as_ref()),
|
||||
);
|
||||
|
||||
let deno_lint_config =
|
||||
|
@ -1673,7 +1675,6 @@ impl ConfigData {
|
|||
) -> Option<JsxImportSourceConfig> {
|
||||
self
|
||||
.member_dir
|
||||
.workspace
|
||||
.to_maybe_jsx_import_source_config()
|
||||
.ok()
|
||||
.flatten()
|
||||
|
|
|
@ -3669,6 +3669,7 @@ impl Inner {
|
|||
workspace,
|
||||
force_global_cache,
|
||||
None,
|
||||
None,
|
||||
)?;
|
||||
|
||||
let open_docs = self.documents.documents(DocumentsFilter::OpenDiagnosable);
|
||||
|
|
|
@ -138,7 +138,7 @@ impl LspScopeResolver {
|
|||
let maybe_jsx_import_source_config =
|
||||
config_data.and_then(|d| d.maybe_jsx_import_source_config());
|
||||
let graph_imports = config_data
|
||||
.and_then(|d| d.member_dir.workspace.to_compiler_option_types().ok())
|
||||
.and_then(|d| d.member_dir.to_compiler_option_types().ok())
|
||||
.map(|imports| {
|
||||
Arc::new(
|
||||
imports
|
||||
|
|
|
@ -79,6 +79,7 @@ use crate::resolver::NotSupportedKindInNpmError;
|
|||
use crate::resolver::NpmModuleLoader;
|
||||
use crate::sys::CliSys;
|
||||
use crate::tools::check;
|
||||
use crate::tools::check::MaybeDiagnostics;
|
||||
use crate::tools::check::TypeChecker;
|
||||
use crate::util::progress_bar::ProgressBar;
|
||||
use crate::util::text_encoding::code_without_source_map;
|
||||
|
@ -125,7 +126,7 @@ impl ModuleLoadPreparer {
|
|||
lib: TsTypeLib,
|
||||
permissions: PermissionsContainer,
|
||||
ext_overwrite: Option<&String>,
|
||||
) -> Result<(), AnyError> {
|
||||
) -> Result<(), MaybeDiagnostics> {
|
||||
log::debug!("Preparing module load.");
|
||||
let _pb_clear_guard = self.progress_bar.clear_guard();
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
use std::collections::HashSet;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
|
@ -11,6 +12,7 @@ use deno_core::error::AnyError;
|
|||
use deno_core::error::JsError;
|
||||
use deno_core::futures::future;
|
||||
use deno_core::futures::stream;
|
||||
use deno_core::futures::FutureExt;
|
||||
use deno_core::futures::StreamExt;
|
||||
use deno_core::serde_v8;
|
||||
use deno_core::unsync::spawn;
|
||||
|
@ -20,7 +22,6 @@ use deno_core::ModuleSpecifier;
|
|||
use deno_core::PollEventLoopOptions;
|
||||
use deno_runtime::deno_permissions::Permissions;
|
||||
use deno_runtime::deno_permissions::PermissionsContainer;
|
||||
use deno_runtime::permissions::RuntimePermissionDescriptorParser;
|
||||
use deno_runtime::tokio_util::create_and_run_current_thread;
|
||||
use deno_runtime::WorkerExecutionMode;
|
||||
use indexmap::IndexMap;
|
||||
|
@ -32,11 +33,12 @@ use tokio::sync::mpsc::unbounded_channel;
|
|||
use tokio::sync::mpsc::UnboundedSender;
|
||||
|
||||
use crate::args::BenchFlags;
|
||||
use crate::args::CliOptions;
|
||||
use crate::args::Flags;
|
||||
use crate::colors;
|
||||
use crate::display::write_json_to_stdout;
|
||||
use crate::factory::CliFactory;
|
||||
use crate::graph_util::has_graph_root_local_dependent_changed;
|
||||
use crate::factory::SpecifierInfo;
|
||||
use crate::factory::WorkspaceFilesFactory;
|
||||
use crate::ops;
|
||||
use crate::sys::CliSys;
|
||||
use crate::tools::test::format_test_error;
|
||||
|
@ -265,35 +267,57 @@ async fn bench_specifier_inner(
|
|||
|
||||
/// Test a collection of specifiers with test modes concurrently.
|
||||
async fn bench_specifiers(
|
||||
worker_factory: Arc<CliMainWorkerFactory>,
|
||||
permissions: &Permissions,
|
||||
permissions_desc_parser: &Arc<RuntimePermissionDescriptorParser<CliSys>>,
|
||||
specifiers: Vec<ModuleSpecifier>,
|
||||
workspace_files_factory: &WorkspaceFilesFactory,
|
||||
changed_paths: Option<&HashSet<PathBuf>>,
|
||||
options: BenchSpecifierOptions,
|
||||
) -> Result<(), AnyError> {
|
||||
let mut specifiers_with_services = vec![];
|
||||
for factory in workspace_files_factory.dirs() {
|
||||
let worker_factory =
|
||||
Arc::new(factory.create_cli_main_worker_factory().await?);
|
||||
let permission_desc_parser = factory.permission_desc_parser()?;
|
||||
let permissions = Arc::new(Permissions::from_options(
|
||||
permission_desc_parser.as_ref(),
|
||||
factory.permissions_options(),
|
||||
)?);
|
||||
let specifiers = if let Some(changed_paths) = changed_paths {
|
||||
factory.dependent_checked_specifiers(changed_paths).await?
|
||||
} else {
|
||||
factory.checked_specifiers().collect()
|
||||
};
|
||||
specifiers_with_services.extend(specifiers.into_iter().map(|s| {
|
||||
(
|
||||
s.clone(),
|
||||
worker_factory.clone(),
|
||||
permission_desc_parser.clone(),
|
||||
permissions.clone(),
|
||||
)
|
||||
}));
|
||||
}
|
||||
let (sender, mut receiver) = unbounded_channel::<BenchEvent>();
|
||||
let log_level = options.log_level;
|
||||
let option_for_handles = options.clone();
|
||||
|
||||
let join_handles = specifiers.into_iter().map(move |specifier| {
|
||||
let worker_factory = worker_factory.clone();
|
||||
let permissions_container = PermissionsContainer::new(
|
||||
permissions_desc_parser.clone(),
|
||||
permissions.clone(),
|
||||
);
|
||||
let sender = sender.clone();
|
||||
let options = option_for_handles.clone();
|
||||
spawn_blocking(move || {
|
||||
let future = bench_specifier(
|
||||
worker_factory,
|
||||
permissions_container,
|
||||
specifier,
|
||||
sender,
|
||||
options.filter,
|
||||
let join_handles = specifiers_with_services.into_iter().map(
|
||||
move |(specifier, worker_factory, permissions_desc_parser, permissions)| {
|
||||
let permissions_container = PermissionsContainer::new(
|
||||
permissions_desc_parser.clone(),
|
||||
permissions.as_ref().clone(),
|
||||
);
|
||||
create_and_run_current_thread(future)
|
||||
})
|
||||
});
|
||||
let sender = sender.clone();
|
||||
let options = option_for_handles.clone();
|
||||
spawn_blocking(move || {
|
||||
let future = bench_specifier(
|
||||
worker_factory,
|
||||
permissions_container,
|
||||
specifier,
|
||||
sender,
|
||||
options.filter,
|
||||
);
|
||||
create_and_run_current_thread(future)
|
||||
})
|
||||
},
|
||||
);
|
||||
|
||||
let join_stream = stream::iter(join_handles)
|
||||
.buffer_unordered(1)
|
||||
|
@ -410,59 +434,53 @@ pub async fn run_benchmarks(
|
|||
flags: Arc<Flags>,
|
||||
bench_flags: BenchFlags,
|
||||
) -> Result<(), AnyError> {
|
||||
let factory = CliFactory::from_flags(flags);
|
||||
let cli_options = factory.cli_options()?;
|
||||
let workspace_bench_options =
|
||||
cli_options.resolve_workspace_bench_options(&bench_flags);
|
||||
// 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 permission_desc_parser = factory.permission_desc_parser()?.clone();
|
||||
let permissions = Permissions::from_options(
|
||||
permission_desc_parser.as_ref(),
|
||||
&cli_options.permissions_options(),
|
||||
)?;
|
||||
|
||||
let members_with_bench_options =
|
||||
cli_options.resolve_bench_options_for_members(&bench_flags)?;
|
||||
let specifiers = members_with_bench_options
|
||||
.iter()
|
||||
.map(|(_, bench_options)| {
|
||||
collect_specifiers(
|
||||
bench_options.files.clone(),
|
||||
cli_options.vendor_dir_path().map(ToOwned::to_owned),
|
||||
is_supported_bench_path,
|
||||
)
|
||||
})
|
||||
.collect::<Result<Vec<_>, _>>()?
|
||||
let log_level = flags.log_level;
|
||||
let cli_options = CliOptions::from_flags(&CliSys::default(), flags)?;
|
||||
let workspace_dirs_with_files = cli_options
|
||||
.resolve_bench_options_for_members(&bench_flags)?
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
if specifiers.is_empty() {
|
||||
return Err(generic_error("No bench modules found"));
|
||||
.map(|(d, o)| (d, o.files))
|
||||
.collect();
|
||||
let workspace_files_factory =
|
||||
WorkspaceFilesFactory::from_workspace_dirs_with_files(
|
||||
workspace_dirs_with_files,
|
||||
|patterns, cli_options, _, _| {
|
||||
async move {
|
||||
let info = SpecifierInfo {
|
||||
check: true,
|
||||
check_doc: false,
|
||||
};
|
||||
collect_specifiers(
|
||||
patterns,
|
||||
cli_options.vendor_dir_path().map(ToOwned::to_owned),
|
||||
is_supported_bench_path,
|
||||
)
|
||||
.map(|s| s.into_iter().map(|s| (s, info)).collect())
|
||||
}
|
||||
.boxed_local()
|
||||
},
|
||||
(),
|
||||
None,
|
||||
&cli_options,
|
||||
None,
|
||||
)
|
||||
.await?;
|
||||
if !workspace_files_factory.found_specifiers() {
|
||||
return Err(generic_error("No test modules found"));
|
||||
}
|
||||
|
||||
let main_graph_container = factory.main_module_graph_container().await?;
|
||||
main_graph_container
|
||||
.check_specifiers(&specifiers, cli_options.ext_flag().as_ref())
|
||||
.await?;
|
||||
workspace_files_factory.check().await?;
|
||||
|
||||
if workspace_bench_options.no_run {
|
||||
if bench_flags.no_run {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let log_level = cli_options.log_level();
|
||||
let worker_factory =
|
||||
Arc::new(factory.create_cli_main_worker_factory().await?);
|
||||
bench_specifiers(
|
||||
worker_factory,
|
||||
&permissions,
|
||||
&permission_desc_parser,
|
||||
specifiers,
|
||||
&workspace_files_factory,
|
||||
None,
|
||||
BenchSpecifierOptions {
|
||||
filter: TestFilter::from_flag(&workspace_bench_options.filter),
|
||||
json: workspace_bench_options.json,
|
||||
filter: TestFilter::from_flag(&bench_flags.filter),
|
||||
json: bench_flags.json,
|
||||
log_level,
|
||||
},
|
||||
)
|
||||
|
@ -471,7 +489,6 @@ pub async fn run_benchmarks(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
// TODO(bartlomieju): heavy duplication of code with `cli/tools/test.rs`
|
||||
pub async fn run_benchmarks_with_watch(
|
||||
flags: Arc<Flags>,
|
||||
bench_flags: BenchFlags,
|
||||
|
@ -490,110 +507,50 @@ pub async fn run_benchmarks_with_watch(
|
|||
let bench_flags = bench_flags.clone();
|
||||
watcher_communicator.show_path_changed(changed_paths.clone());
|
||||
Ok(async move {
|
||||
let factory = CliFactory::from_flags_for_watcher(
|
||||
flags,
|
||||
watcher_communicator.clone(),
|
||||
);
|
||||
let cli_options = factory.cli_options()?;
|
||||
let workspace_bench_options =
|
||||
cli_options.resolve_workspace_bench_options(&bench_flags);
|
||||
|
||||
let _ = watcher_communicator.watch_paths(cli_options.watch_paths());
|
||||
|
||||
let graph_kind = cli_options.type_check_mode().as_graph_kind();
|
||||
let module_graph_creator = factory.module_graph_creator().await?;
|
||||
let members_with_bench_options =
|
||||
cli_options.resolve_bench_options_for_members(&bench_flags)?;
|
||||
let watch_paths = members_with_bench_options
|
||||
.iter()
|
||||
.filter_map(|(_, bench_options)| {
|
||||
bench_options
|
||||
.files
|
||||
.include
|
||||
.as_ref()
|
||||
.map(|set| set.base_paths())
|
||||
})
|
||||
.flatten()
|
||||
.collect::<Vec<_>>();
|
||||
let _ = watcher_communicator.watch_paths(watch_paths);
|
||||
let collected_bench_modules = members_with_bench_options
|
||||
.iter()
|
||||
.map(|(_, bench_options)| {
|
||||
collect_specifiers(
|
||||
bench_options.files.clone(),
|
||||
cli_options.vendor_dir_path().map(ToOwned::to_owned),
|
||||
is_supported_bench_path,
|
||||
)
|
||||
})
|
||||
.collect::<Result<Vec<_>, _>>()?
|
||||
let log_level: Option<Level> = flags.log_level;
|
||||
let cli_options = CliOptions::from_flags(&CliSys::default(), flags)?;
|
||||
let workspace_dirs_with_files = cli_options
|
||||
.resolve_bench_options_for_members(&bench_flags)?
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.map(|(d, o)| (d, o.files))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
// 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 permission_desc_parser = factory.permission_desc_parser()?.clone();
|
||||
let permissions = Permissions::from_options(
|
||||
permission_desc_parser.as_ref(),
|
||||
&cli_options.permissions_options(),
|
||||
)?;
|
||||
|
||||
let graph = module_graph_creator
|
||||
.create_graph(
|
||||
graph_kind,
|
||||
collected_bench_modules.clone(),
|
||||
crate::graph_util::NpmCachingStrategy::Eager,
|
||||
let workspace_files_factory =
|
||||
WorkspaceFilesFactory::from_workspace_dirs_with_files(
|
||||
workspace_dirs_with_files,
|
||||
|patterns, cli_options, _, _| {
|
||||
async move {
|
||||
let info = SpecifierInfo {
|
||||
check: true,
|
||||
check_doc: false,
|
||||
};
|
||||
collect_specifiers(
|
||||
patterns,
|
||||
cli_options.vendor_dir_path().map(ToOwned::to_owned),
|
||||
is_supported_bench_path,
|
||||
)
|
||||
.map(|s| s.into_iter().map(|s| (s, info)).collect())
|
||||
}
|
||||
.boxed_local()
|
||||
},
|
||||
(),
|
||||
None,
|
||||
&cli_options,
|
||||
Some(&watcher_communicator),
|
||||
)
|
||||
.await?;
|
||||
module_graph_creator.graph_valid(&graph)?;
|
||||
let bench_modules = &graph.roots;
|
||||
|
||||
let bench_modules_to_reload = if let Some(changed_paths) = changed_paths
|
||||
{
|
||||
let changed_paths = changed_paths.into_iter().collect::<HashSet<_>>();
|
||||
let mut result = IndexSet::with_capacity(bench_modules.len());
|
||||
for bench_module_specifier in bench_modules {
|
||||
if has_graph_root_local_dependent_changed(
|
||||
&graph,
|
||||
bench_module_specifier,
|
||||
&changed_paths,
|
||||
) {
|
||||
result.insert(bench_module_specifier.clone());
|
||||
}
|
||||
}
|
||||
result
|
||||
} else {
|
||||
bench_modules.clone()
|
||||
};
|
||||
workspace_files_factory.check().await?;
|
||||
|
||||
let worker_factory =
|
||||
Arc::new(factory.create_cli_main_worker_factory().await?);
|
||||
|
||||
let specifiers = collected_bench_modules
|
||||
.into_iter()
|
||||
.filter(|specifier| bench_modules_to_reload.contains(specifier))
|
||||
.collect::<Vec<ModuleSpecifier>>();
|
||||
|
||||
factory
|
||||
.main_module_graph_container()
|
||||
.await?
|
||||
.check_specifiers(&specifiers, cli_options.ext_flag().as_ref())
|
||||
.await?;
|
||||
|
||||
if workspace_bench_options.no_run {
|
||||
if bench_flags.no_run {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let log_level = cli_options.log_level();
|
||||
bench_specifiers(
|
||||
worker_factory,
|
||||
&permissions,
|
||||
&permission_desc_parser,
|
||||
specifiers,
|
||||
&workspace_files_factory,
|
||||
changed_paths.map(|p| p.into_iter().collect()).as_ref(),
|
||||
BenchSpecifierOptions {
|
||||
filter: TestFilter::from_flag(&workspace_bench_options.filter),
|
||||
json: workspace_bench_options.json,
|
||||
filter: TestFilter::from_flag(&bench_flags.filter),
|
||||
json: bench_flags.json,
|
||||
log_level,
|
||||
},
|
||||
)
|
||||
|
|
|
@ -2,11 +2,14 @@
|
|||
|
||||
use std::collections::HashSet;
|
||||
use std::collections::VecDeque;
|
||||
use std::error::Error;
|
||||
use std::fmt;
|
||||
use std::sync::Arc;
|
||||
|
||||
use deno_ast::MediaType;
|
||||
use deno_ast::ModuleSpecifier;
|
||||
use deno_core::error::AnyError;
|
||||
use deno_core::futures::FutureExt;
|
||||
use deno_graph::Module;
|
||||
use deno_graph::ModuleError;
|
||||
use deno_graph::ModuleGraph;
|
||||
|
@ -18,6 +21,7 @@ use regex::Regex;
|
|||
use crate::args::check_warn_tsconfig;
|
||||
use crate::args::CheckFlags;
|
||||
use crate::args::CliOptions;
|
||||
use crate::args::FileFlags;
|
||||
use crate::args::Flags;
|
||||
use crate::args::TsConfig;
|
||||
use crate::args::TsConfigType;
|
||||
|
@ -27,7 +31,8 @@ use crate::cache::CacheDBHash;
|
|||
use crate::cache::Caches;
|
||||
use crate::cache::FastInsecureHasher;
|
||||
use crate::cache::TypeCheckCache;
|
||||
use crate::factory::CliFactory;
|
||||
use crate::factory::SpecifierInfo;
|
||||
use crate::factory::WorkspaceFilesFactory;
|
||||
use crate::graph_util::maybe_additional_sloppy_imports_message;
|
||||
use crate::graph_util::BuildFastCheckGraphOptions;
|
||||
use crate::graph_util::ModuleGraphBuilder;
|
||||
|
@ -37,50 +42,49 @@ use crate::sys::CliSys;
|
|||
use crate::tsc;
|
||||
use crate::tsc::Diagnostics;
|
||||
use crate::tsc::TypeCheckingCjsTracker;
|
||||
use crate::util::extract;
|
||||
use crate::util::extract::extract_snippet_files;
|
||||
use crate::util::fs::collect_specifiers;
|
||||
use crate::util::path::is_script_ext;
|
||||
use crate::util::path::to_percent_decoded_str;
|
||||
|
||||
pub async fn check(
|
||||
flags: Arc<Flags>,
|
||||
check_flags: CheckFlags,
|
||||
) -> Result<(), AnyError> {
|
||||
let factory = CliFactory::from_flags(flags);
|
||||
|
||||
let main_graph_container = factory.main_module_graph_container().await?;
|
||||
|
||||
let specifiers =
|
||||
main_graph_container.collect_specifiers(&check_flags.files)?;
|
||||
if specifiers.is_empty() {
|
||||
let cli_options = CliOptions::from_flags(&CliSys::default(), flags)?;
|
||||
let workspace_dirs_with_files =
|
||||
cli_options.resolve_file_flags_for_members(&FileFlags {
|
||||
ignore: Default::default(),
|
||||
include: check_flags.files,
|
||||
})?;
|
||||
let workspace_files_factory =
|
||||
WorkspaceFilesFactory::from_workspace_dirs_with_files(
|
||||
workspace_dirs_with_files,
|
||||
|patterns, cli_options, _, (doc, doc_only)| {
|
||||
async move {
|
||||
let info = SpecifierInfo {
|
||||
check: !doc_only,
|
||||
check_doc: doc || doc_only,
|
||||
};
|
||||
collect_specifiers(
|
||||
patterns,
|
||||
cli_options.vendor_dir_path().map(ToOwned::to_owned),
|
||||
|e| is_script_ext(e.path),
|
||||
)
|
||||
.map(|s| s.into_iter().map(|s| (s, info)).collect())
|
||||
}
|
||||
.boxed_local()
|
||||
},
|
||||
(check_flags.doc, check_flags.doc_only),
|
||||
Some(extract_snippet_files),
|
||||
&cli_options,
|
||||
None,
|
||||
)
|
||||
.await?;
|
||||
if !workspace_files_factory.found_specifiers() {
|
||||
log::warn!("{} No matching files found.", colors::yellow("Warning"));
|
||||
}
|
||||
|
||||
let specifiers_for_typecheck = if check_flags.doc || check_flags.doc_only {
|
||||
let file_fetcher = factory.file_fetcher()?;
|
||||
let root_permissions = factory.root_permissions_container()?;
|
||||
|
||||
let mut specifiers_for_typecheck = if check_flags.doc {
|
||||
specifiers.clone()
|
||||
} else {
|
||||
vec![]
|
||||
};
|
||||
|
||||
for s in specifiers {
|
||||
let file = file_fetcher.fetch(&s, root_permissions).await?;
|
||||
let snippet_files = extract::extract_snippet_files(file)?;
|
||||
for snippet_file in snippet_files {
|
||||
specifiers_for_typecheck.push(snippet_file.url.clone());
|
||||
file_fetcher.insert_memory_files(snippet_file);
|
||||
}
|
||||
}
|
||||
|
||||
specifiers_for_typecheck
|
||||
} else {
|
||||
specifiers
|
||||
};
|
||||
|
||||
main_graph_container
|
||||
.check_specifiers(&specifiers_for_typecheck, None)
|
||||
.await
|
||||
workspace_files_factory.check().await
|
||||
}
|
||||
|
||||
/// Options for performing a check of a module graph. Note that the decision to
|
||||
|
@ -102,6 +106,29 @@ pub struct CheckOptions {
|
|||
pub type_check_mode: TypeCheckMode,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum MaybeDiagnostics {
|
||||
Diagnostics(Diagnostics),
|
||||
Other(AnyError),
|
||||
}
|
||||
|
||||
impl fmt::Display for MaybeDiagnostics {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
MaybeDiagnostics::Diagnostics(d) => d.fmt(f),
|
||||
MaybeDiagnostics::Other(err) => err.fmt(f),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for MaybeDiagnostics {}
|
||||
|
||||
impl From<AnyError> for MaybeDiagnostics {
|
||||
fn from(err: AnyError) -> Self {
|
||||
MaybeDiagnostics::Other(err)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TypeChecker {
|
||||
caches: Arc<Caches>,
|
||||
cjs_tracker: Arc<TypeCheckingCjsTracker>,
|
||||
|
@ -141,14 +168,14 @@ impl TypeChecker {
|
|||
&self,
|
||||
graph: ModuleGraph,
|
||||
options: CheckOptions,
|
||||
) -> Result<Arc<ModuleGraph>, AnyError> {
|
||||
) -> Result<Arc<ModuleGraph>, MaybeDiagnostics> {
|
||||
let (graph, mut diagnostics) =
|
||||
self.check_diagnostics(graph, options).await?;
|
||||
diagnostics.emit_warnings();
|
||||
if diagnostics.is_empty() {
|
||||
Ok(graph)
|
||||
} else {
|
||||
Err(diagnostics.into())
|
||||
Err(MaybeDiagnostics::Diagnostics(diagnostics))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -197,12 +224,35 @@ impl TypeChecker {
|
|||
)?;
|
||||
}
|
||||
|
||||
let filter_remote_diagnostics = |d: &tsc::Diagnostic| {
|
||||
let is_visible_diagnostic = |d: &tsc::Diagnostic| {
|
||||
if self.is_remote_diagnostic(d) {
|
||||
type_check_mode == TypeCheckMode::All && d.include_when_remote()
|
||||
} else {
|
||||
true
|
||||
return type_check_mode == TypeCheckMode::All
|
||||
&& d.include_when_remote()
|
||||
&& self
|
||||
.cli_options
|
||||
.scope_options
|
||||
.as_ref()
|
||||
.map(|o| o.scope.is_none())
|
||||
.unwrap_or(true);
|
||||
}
|
||||
let Some(scope_options) = &self.cli_options.scope_options else {
|
||||
return true;
|
||||
};
|
||||
let Some(specifier) = d
|
||||
.file_name
|
||||
.as_ref()
|
||||
.and_then(|s| ModuleSpecifier::parse(s).ok())
|
||||
else {
|
||||
return true;
|
||||
};
|
||||
if specifier.scheme() != "file" {
|
||||
return true;
|
||||
}
|
||||
let scope = scope_options
|
||||
.all_scopes
|
||||
.iter()
|
||||
.rfind(|s| specifier.as_str().starts_with(s.as_str()));
|
||||
scope == scope_options.scope.as_ref()
|
||||
};
|
||||
let TscRoots {
|
||||
roots: root_names,
|
||||
|
@ -217,8 +267,7 @@ impl TypeChecker {
|
|||
&ts_config,
|
||||
);
|
||||
|
||||
let missing_diagnostics =
|
||||
missing_diagnostics.filter(filter_remote_diagnostics);
|
||||
let missing_diagnostics = missing_diagnostics.filter(is_visible_diagnostic);
|
||||
|
||||
if root_names.is_empty() && missing_diagnostics.is_empty() {
|
||||
return Ok((graph.into(), Default::default()));
|
||||
|
@ -273,7 +322,7 @@ impl TypeChecker {
|
|||
})?;
|
||||
|
||||
let response_diagnostics =
|
||||
response.diagnostics.filter(filter_remote_diagnostics);
|
||||
response.diagnostics.filter(is_visible_diagnostic);
|
||||
|
||||
let mut diagnostics = missing_diagnostics;
|
||||
diagnostics.extend(response_diagnostics);
|
||||
|
|
|
@ -209,7 +209,7 @@ async fn lint_with_watch(
|
|||
}
|
||||
|
||||
struct PathsWithOptions {
|
||||
dir: WorkspaceDirectory,
|
||||
dir: Arc<WorkspaceDirectory>,
|
||||
paths: Vec<PathBuf>,
|
||||
options: LintOptions,
|
||||
}
|
||||
|
@ -279,7 +279,7 @@ impl WorkspaceLinter {
|
|||
cli_options: &Arc<CliOptions>,
|
||||
lint_options: LintOptions,
|
||||
lint_config: DenoLintConfig,
|
||||
member_dir: WorkspaceDirectory,
|
||||
member_dir: Arc<WorkspaceDirectory>,
|
||||
paths: Vec<PathBuf>,
|
||||
) -> Result<(), AnyError> {
|
||||
self.file_count += paths.len();
|
||||
|
|
|
@ -12,6 +12,7 @@ use std::future::poll_fn;
|
|||
use std::io::Write;
|
||||
use std::num::NonZeroUsize;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::atomic::AtomicUsize;
|
||||
use std::sync::atomic::Ordering;
|
||||
|
@ -21,7 +22,6 @@ use std::time::Duration;
|
|||
use std::time::Instant;
|
||||
|
||||
use deno_ast::MediaType;
|
||||
use deno_cache_dir::file_fetcher::File;
|
||||
use deno_config::glob::FilePatterns;
|
||||
use deno_config::glob::WalkEntry;
|
||||
use deno_core::anyhow;
|
||||
|
@ -54,7 +54,6 @@ use deno_runtime::deno_io::StdioPipe;
|
|||
use deno_runtime::deno_permissions::Permissions;
|
||||
use deno_runtime::deno_permissions::PermissionsContainer;
|
||||
use deno_runtime::fmt_errors::format_js_error;
|
||||
use deno_runtime::permissions::RuntimePermissionDescriptorParser;
|
||||
use deno_runtime::tokio_util::create_and_run_current_thread;
|
||||
use deno_runtime::worker::MainWorker;
|
||||
use deno_runtime::WorkerExecutionMode;
|
||||
|
@ -74,9 +73,9 @@ use crate::args::TestFlags;
|
|||
use crate::args::TestReporterConfig;
|
||||
use crate::colors;
|
||||
use crate::display;
|
||||
use crate::factory::CliFactory;
|
||||
use crate::factory::SpecifierInfo;
|
||||
use crate::factory::WorkspaceFilesFactory;
|
||||
use crate::file_fetcher::CliFileFetcher;
|
||||
use crate::graph_util::has_graph_root_local_dependent_changed;
|
||||
use crate::ops;
|
||||
use crate::sys::CliSys;
|
||||
use crate::util::extract::extract_doc_tests;
|
||||
|
@ -138,32 +137,6 @@ fn get_sanitizer_item_ref(
|
|||
}
|
||||
}
|
||||
|
||||
/// The test mode is used to determine how a specifier is to be tested.
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub enum TestMode {
|
||||
/// Test as documentation, type-checking fenced code blocks.
|
||||
Documentation,
|
||||
/// Test as an executable module, loading the module into the isolate and running each test it
|
||||
/// defines.
|
||||
Executable,
|
||||
/// Test as both documentation and an executable module.
|
||||
Both,
|
||||
}
|
||||
|
||||
impl TestMode {
|
||||
/// Returns `true` if the test mode indicates that code snippet extraction is
|
||||
/// needed.
|
||||
fn needs_test_extraction(&self) -> bool {
|
||||
matches!(self, Self::Documentation | Self::Both)
|
||||
}
|
||||
|
||||
/// Returns `true` if the test mode indicates that the test should be
|
||||
/// type-checked and run.
|
||||
fn needs_test_run(&self) -> bool {
|
||||
matches!(self, Self::Executable | Self::Both)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct TestFilter {
|
||||
pub substring: Option<String>,
|
||||
|
@ -1194,21 +1167,38 @@ static HAS_TEST_RUN_SIGINT_HANDLER: AtomicBool = AtomicBool::new(false);
|
|||
|
||||
/// Test a collection of specifiers with test modes concurrently.
|
||||
async fn test_specifiers(
|
||||
worker_factory: Arc<CliMainWorkerFactory>,
|
||||
permissions: &Permissions,
|
||||
permission_desc_parser: &Arc<RuntimePermissionDescriptorParser<CliSys>>,
|
||||
specifiers: Vec<ModuleSpecifier>,
|
||||
workspace_files_factory: &WorkspaceFilesFactory,
|
||||
changed_paths: Option<&HashSet<PathBuf>>,
|
||||
options: TestSpecifiersOptions,
|
||||
) -> Result<(), AnyError> {
|
||||
let specifiers = if let Some(seed) = options.specifier.shuffle {
|
||||
let mut specifiers_with_services = vec![];
|
||||
for factory in workspace_files_factory.dirs() {
|
||||
let worker_factory =
|
||||
Arc::new(factory.create_cli_main_worker_factory().await?);
|
||||
let permission_desc_parser = factory.permission_desc_parser()?;
|
||||
let permissions = Arc::new(Permissions::from_options(
|
||||
permission_desc_parser.as_ref(),
|
||||
factory.permissions_options(),
|
||||
)?);
|
||||
let specifiers = if let Some(changed_paths) = changed_paths {
|
||||
factory.dependent_checked_specifiers(changed_paths).await?
|
||||
} else {
|
||||
factory.checked_specifiers().collect()
|
||||
};
|
||||
specifiers_with_services.extend(specifiers.into_iter().map(|s| {
|
||||
(
|
||||
s.clone(),
|
||||
worker_factory.clone(),
|
||||
permission_desc_parser.clone(),
|
||||
permissions.clone(),
|
||||
)
|
||||
}));
|
||||
}
|
||||
if let Some(seed) = options.specifier.shuffle {
|
||||
let mut rng = SmallRng::seed_from_u64(seed);
|
||||
let mut specifiers = specifiers;
|
||||
specifiers.sort();
|
||||
specifiers.shuffle(&mut rng);
|
||||
specifiers
|
||||
} else {
|
||||
specifiers
|
||||
};
|
||||
specifiers_with_services.sort_by_cached_key(|(s, ..)| s.to_string());
|
||||
specifiers_with_services.shuffle(&mut rng);
|
||||
}
|
||||
|
||||
let (test_event_sender_factory, receiver) = create_test_event_channel();
|
||||
let concurrent_jobs = options.concurrent_jobs;
|
||||
|
@ -1222,26 +1212,27 @@ async fn test_specifiers(
|
|||
let reporter = get_test_reporter(&options);
|
||||
let fail_fast_tracker = FailFastTracker::new(options.fail_fast);
|
||||
|
||||
let join_handles = specifiers.into_iter().map(move |specifier| {
|
||||
let worker_factory = worker_factory.clone();
|
||||
let permissions_container = PermissionsContainer::new(
|
||||
permission_desc_parser.clone(),
|
||||
permissions.clone(),
|
||||
);
|
||||
let worker_sender = test_event_sender_factory.worker();
|
||||
let fail_fast_tracker = fail_fast_tracker.clone();
|
||||
let specifier_options = options.specifier.clone();
|
||||
spawn_blocking(move || {
|
||||
create_and_run_current_thread(test_specifier(
|
||||
worker_factory,
|
||||
permissions_container,
|
||||
specifier,
|
||||
worker_sender,
|
||||
fail_fast_tracker,
|
||||
specifier_options,
|
||||
))
|
||||
})
|
||||
});
|
||||
let join_handles = specifiers_with_services.into_iter().map(
|
||||
move |(specifier, worker_factory, permission_desc_parser, permissions)| {
|
||||
let permissions_container = PermissionsContainer::new(
|
||||
permission_desc_parser,
|
||||
permissions.as_ref().clone(),
|
||||
);
|
||||
let worker_sender = test_event_sender_factory.worker();
|
||||
let fail_fast_tracker = fail_fast_tracker.clone();
|
||||
let specifier_options = options.specifier.clone();
|
||||
spawn_blocking(move || {
|
||||
create_and_run_current_thread(test_specifier(
|
||||
worker_factory,
|
||||
permissions_container,
|
||||
specifier,
|
||||
worker_sender,
|
||||
fail_fast_tracker,
|
||||
specifier_options,
|
||||
))
|
||||
})
|
||||
},
|
||||
);
|
||||
|
||||
let join_stream = stream::iter(join_handles)
|
||||
.buffer_unordered(concurrent_jobs.get())
|
||||
|
@ -1459,175 +1450,113 @@ fn is_supported_test_ext(path: &Path) -> bool {
|
|||
}
|
||||
}
|
||||
|
||||
/// Collects specifiers marking them with the appropriate test mode while maintaining the natural
|
||||
/// input order.
|
||||
///
|
||||
/// - Specifiers matching the `is_supported_test_ext` predicate are marked as
|
||||
/// `TestMode::Documentation`.
|
||||
/// - 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(
|
||||
cli_options: &CliOptions,
|
||||
files: FilePatterns,
|
||||
include_inline: &bool,
|
||||
) -> Result<Vec<(ModuleSpecifier, TestMode)>, AnyError> {
|
||||
// todo(dsherret): there's no need to collect twice as it's slow
|
||||
pub async fn collect_specifiers_for_tests(
|
||||
patterns: FilePatterns,
|
||||
cli_options: Arc<CliOptions>,
|
||||
file_fetcher: Arc<CliFileFetcher>,
|
||||
doc: bool,
|
||||
) -> Result<Vec<(ModuleSpecifier, SpecifierInfo)>, AnyError> {
|
||||
let vendor_folder = cli_options.vendor_dir_path();
|
||||
let module_specifiers = collect_specifiers(
|
||||
files.clone(),
|
||||
patterns.clone(),
|
||||
vendor_folder.map(ToOwned::to_owned),
|
||||
is_supported_test_path_predicate,
|
||||
)?;
|
||||
|
||||
if *include_inline {
|
||||
return collect_specifiers(
|
||||
files,
|
||||
vendor_folder.map(ToOwned::to_owned),
|
||||
|e| is_supported_test_ext(e.path),
|
||||
)
|
||||
let mut specifiers = if doc {
|
||||
collect_specifiers(patterns, vendor_folder.map(ToOwned::to_owned), |e| {
|
||||
is_supported_test_ext(e.path)
|
||||
})
|
||||
.map(|specifiers| {
|
||||
specifiers
|
||||
.into_iter()
|
||||
.map(|specifier| {
|
||||
let mode = if module_specifiers.contains(&specifier) {
|
||||
TestMode::Both
|
||||
} else {
|
||||
TestMode::Documentation
|
||||
let info = SpecifierInfo {
|
||||
check: module_specifiers.contains(&specifier),
|
||||
check_doc: true,
|
||||
};
|
||||
|
||||
(specifier, mode)
|
||||
(specifier, info)
|
||||
})
|
||||
.collect()
|
||||
});
|
||||
}
|
||||
|
||||
let specifiers_with_mode = module_specifiers
|
||||
.into_iter()
|
||||
.map(|specifier| (specifier, TestMode::Executable))
|
||||
.collect();
|
||||
|
||||
Ok(specifiers_with_mode)
|
||||
}
|
||||
|
||||
/// Collects module and document specifiers with test modes via
|
||||
/// `collect_specifiers_with_test_mode` which are then pre-fetched and adjusted
|
||||
/// based on the media type.
|
||||
///
|
||||
/// Specifiers that do not have a known media type that can be executed as a
|
||||
/// module are marked as `TestMode::Documentation`. Type definition files
|
||||
/// cannot be run, and therefore need to be marked as `TestMode::Documentation`
|
||||
/// as well.
|
||||
async fn fetch_specifiers_with_test_mode(
|
||||
cli_options: &CliOptions,
|
||||
file_fetcher: &CliFileFetcher,
|
||||
member_patterns: impl Iterator<Item = FilePatterns>,
|
||||
doc: &bool,
|
||||
) -> Result<Vec<(ModuleSpecifier, TestMode)>, AnyError> {
|
||||
let mut specifiers_with_mode = member_patterns
|
||||
.map(|files| {
|
||||
collect_specifiers_with_test_mode(cli_options, files.clone(), doc)
|
||||
})
|
||||
.collect::<Result<Vec<_>, _>>()?
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
for (specifier, mode) in &mut specifiers_with_mode {
|
||||
.collect::<Vec<_>>()
|
||||
})?
|
||||
} else {
|
||||
let info = SpecifierInfo {
|
||||
check: true,
|
||||
check_doc: false,
|
||||
};
|
||||
module_specifiers
|
||||
.into_iter()
|
||||
.map(|specifier| (specifier, info))
|
||||
.collect::<Vec<_>>()
|
||||
};
|
||||
for (specifier, info) in &mut specifiers {
|
||||
let file = file_fetcher.fetch_bypass_permissions(specifier).await?;
|
||||
|
||||
let (media_type, _) = file.resolve_media_type_and_charset();
|
||||
if matches!(media_type, MediaType::Unknown | MediaType::Dts) {
|
||||
*mode = TestMode::Documentation
|
||||
info.check = false;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(specifiers_with_mode)
|
||||
Ok(specifiers)
|
||||
}
|
||||
|
||||
pub async fn run_tests(
|
||||
flags: Arc<Flags>,
|
||||
test_flags: TestFlags,
|
||||
) -> Result<(), AnyError> {
|
||||
let factory = CliFactory::from_flags(flags);
|
||||
let cli_options = factory.cli_options()?;
|
||||
let workspace_test_options =
|
||||
cli_options.resolve_workspace_test_options(&test_flags);
|
||||
let file_fetcher = factory.file_fetcher()?;
|
||||
// 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 permission_desc_parser = factory.permission_desc_parser()?;
|
||||
let permissions = Permissions::from_options(
|
||||
permission_desc_parser.as_ref(),
|
||||
&cli_options.permissions_options(),
|
||||
)?;
|
||||
let log_level = cli_options.log_level();
|
||||
|
||||
let members_with_test_options =
|
||||
cli_options.resolve_test_options_for_members(&test_flags)?;
|
||||
let specifiers_with_mode = fetch_specifiers_with_test_mode(
|
||||
cli_options,
|
||||
file_fetcher,
|
||||
members_with_test_options.into_iter().map(|(_, v)| v.files),
|
||||
&workspace_test_options.doc,
|
||||
)
|
||||
.await?;
|
||||
|
||||
if !workspace_test_options.permit_no_files && specifiers_with_mode.is_empty()
|
||||
let log_level = flags.log_level;
|
||||
let cli_options = CliOptions::from_flags(&CliSys::default(), flags)?;
|
||||
let workspace_dirs_with_files = cli_options
|
||||
.resolve_test_options_for_members(&test_flags)?
|
||||
.into_iter()
|
||||
.map(|(d, o)| (d, o.files))
|
||||
.collect();
|
||||
let workspace_files_factory =
|
||||
WorkspaceFilesFactory::from_workspace_dirs_with_files(
|
||||
workspace_dirs_with_files,
|
||||
|patterns, cli_options, file_fetcher, doc| {
|
||||
collect_specifiers_for_tests(patterns, cli_options, file_fetcher, doc)
|
||||
.boxed_local()
|
||||
},
|
||||
test_flags.doc,
|
||||
Some(extract_doc_tests),
|
||||
&cli_options,
|
||||
None,
|
||||
)
|
||||
.await?;
|
||||
if !test_flags.permit_no_files && !workspace_files_factory.found_specifiers()
|
||||
{
|
||||
return Err(generic_error("No test modules found"));
|
||||
}
|
||||
|
||||
let doc_tests = get_doc_tests(&specifiers_with_mode, file_fetcher).await?;
|
||||
let specifiers_for_typecheck_and_test =
|
||||
get_target_specifiers(specifiers_with_mode, &doc_tests);
|
||||
for doc_test in doc_tests {
|
||||
file_fetcher.insert_memory_files(doc_test);
|
||||
}
|
||||
workspace_files_factory.check().await?;
|
||||
|
||||
let main_graph_container = factory.main_module_graph_container().await?;
|
||||
|
||||
// Typecheck
|
||||
main_graph_container
|
||||
.check_specifiers(
|
||||
&specifiers_for_typecheck_and_test,
|
||||
cli_options.ext_flag().as_ref(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
if workspace_test_options.no_run {
|
||||
if test_flags.no_run {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let worker_factory =
|
||||
Arc::new(factory.create_cli_main_worker_factory().await?);
|
||||
|
||||
// Run tests
|
||||
let initial_cwd = workspace_files_factory.initial_cwd();
|
||||
test_specifiers(
|
||||
worker_factory,
|
||||
&permissions,
|
||||
permission_desc_parser,
|
||||
specifiers_for_typecheck_and_test,
|
||||
&workspace_files_factory,
|
||||
None,
|
||||
TestSpecifiersOptions {
|
||||
cwd: Url::from_directory_path(cli_options.initial_cwd()).map_err(
|
||||
|_| {
|
||||
generic_error(format!(
|
||||
"Unable to construct URL from the path of cwd: {}",
|
||||
cli_options.initial_cwd().to_string_lossy(),
|
||||
))
|
||||
},
|
||||
)?,
|
||||
concurrent_jobs: workspace_test_options.concurrent_jobs,
|
||||
fail_fast: workspace_test_options.fail_fast,
|
||||
cwd: Url::from_directory_path(initial_cwd).map_err(|_| {
|
||||
generic_error(format!(
|
||||
"Unable to construct URL from the path of cwd: {}",
|
||||
initial_cwd.to_string_lossy(),
|
||||
))
|
||||
})?,
|
||||
concurrent_jobs: test_flags
|
||||
.concurrent_jobs
|
||||
.unwrap_or_else(|| NonZeroUsize::new(1).unwrap()),
|
||||
fail_fast: test_flags.fail_fast,
|
||||
log_level,
|
||||
filter: workspace_test_options.filter.is_some(),
|
||||
reporter: workspace_test_options.reporter,
|
||||
junit_path: workspace_test_options.junit_path,
|
||||
hide_stacktraces: workspace_test_options.hide_stacktraces,
|
||||
filter: test_flags.filter.is_some(),
|
||||
reporter: test_flags.reporter,
|
||||
junit_path: test_flags.junit_path,
|
||||
hide_stacktraces: test_flags.hide_stacktraces,
|
||||
specifier: TestSpecifierOptions {
|
||||
filter: TestFilter::from_flag(&workspace_test_options.filter),
|
||||
shuffle: workspace_test_options.shuffle,
|
||||
trace_leaks: workspace_test_options.trace_leaks,
|
||||
filter: TestFilter::from_flag(&test_flags.filter),
|
||||
shuffle: test_flags.shuffle,
|
||||
trace_leaks: test_flags.trace_leaks,
|
||||
},
|
||||
},
|
||||
)
|
||||
|
@ -1668,148 +1597,62 @@ pub async fn run_tests_with_watch(
|
|||
let test_flags = test_flags.clone();
|
||||
watcher_communicator.show_path_changed(changed_paths.clone());
|
||||
Ok(async move {
|
||||
let factory = CliFactory::from_flags_for_watcher(
|
||||
flags,
|
||||
watcher_communicator.clone(),
|
||||
);
|
||||
let cli_options = factory.cli_options()?;
|
||||
let workspace_test_options =
|
||||
cli_options.resolve_workspace_test_options(&test_flags);
|
||||
|
||||
let _ = watcher_communicator.watch_paths(cli_options.watch_paths());
|
||||
let graph_kind = cli_options.type_check_mode().as_graph_kind();
|
||||
let log_level = cli_options.log_level();
|
||||
let cli_options = cli_options.clone();
|
||||
let module_graph_creator = factory.module_graph_creator().await?;
|
||||
let file_fetcher = factory.file_fetcher()?;
|
||||
let members_with_test_options =
|
||||
cli_options.resolve_test_options_for_members(&test_flags)?;
|
||||
let watch_paths = members_with_test_options
|
||||
.iter()
|
||||
.filter_map(|(_, test_options)| {
|
||||
test_options
|
||||
.files
|
||||
.include
|
||||
.as_ref()
|
||||
.map(|set| set.base_paths())
|
||||
})
|
||||
.flatten()
|
||||
.collect::<Vec<_>>();
|
||||
let _ = watcher_communicator.watch_paths(watch_paths);
|
||||
let test_modules = members_with_test_options
|
||||
.iter()
|
||||
.map(|(_, test_options)| {
|
||||
collect_specifiers(
|
||||
test_options.files.clone(),
|
||||
cli_options.vendor_dir_path().map(ToOwned::to_owned),
|
||||
if workspace_test_options.doc {
|
||||
Box::new(|e: WalkEntry| is_supported_test_ext(e.path))
|
||||
as Box<dyn Fn(WalkEntry) -> bool>
|
||||
} else {
|
||||
Box::new(is_supported_test_path_predicate)
|
||||
},
|
||||
)
|
||||
})
|
||||
.collect::<Result<Vec<_>, _>>()?
|
||||
let log_level = flags.log_level;
|
||||
let cli_options = CliOptions::from_flags(&CliSys::default(), flags)?;
|
||||
let workspace_dirs_with_files = cli_options
|
||||
.resolve_test_options_for_members(&test_flags)?
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.map(|(d, o)| (d, o.files))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let permission_desc_parser = factory.permission_desc_parser()?;
|
||||
let permissions = Permissions::from_options(
|
||||
permission_desc_parser.as_ref(),
|
||||
&cli_options.permissions_options(),
|
||||
)?;
|
||||
let graph = module_graph_creator
|
||||
.create_graph(
|
||||
graph_kind,
|
||||
test_modules,
|
||||
crate::graph_util::NpmCachingStrategy::Eager,
|
||||
)
|
||||
.await?;
|
||||
module_graph_creator.graph_valid(&graph)?;
|
||||
let test_modules = &graph.roots;
|
||||
|
||||
let test_modules_to_reload = if let Some(changed_paths) = changed_paths
|
||||
{
|
||||
let mut result = IndexSet::with_capacity(test_modules.len());
|
||||
let changed_paths = changed_paths.into_iter().collect::<HashSet<_>>();
|
||||
for test_module_specifier in test_modules {
|
||||
if has_graph_root_local_dependent_changed(
|
||||
&graph,
|
||||
test_module_specifier,
|
||||
&changed_paths,
|
||||
) {
|
||||
result.insert(test_module_specifier.clone());
|
||||
}
|
||||
}
|
||||
result
|
||||
} else {
|
||||
test_modules.clone()
|
||||
};
|
||||
|
||||
let specifiers_with_mode = fetch_specifiers_with_test_mode(
|
||||
&cli_options,
|
||||
file_fetcher,
|
||||
members_with_test_options.into_iter().map(|(_, v)| v.files),
|
||||
&workspace_test_options.doc,
|
||||
)
|
||||
.await?
|
||||
.into_iter()
|
||||
.filter(|(specifier, _)| test_modules_to_reload.contains(specifier))
|
||||
.collect::<Vec<(ModuleSpecifier, TestMode)>>();
|
||||
|
||||
let doc_tests =
|
||||
get_doc_tests(&specifiers_with_mode, file_fetcher).await?;
|
||||
let specifiers_for_typecheck_and_test =
|
||||
get_target_specifiers(specifiers_with_mode, &doc_tests);
|
||||
for doc_test in doc_tests {
|
||||
file_fetcher.insert_memory_files(doc_test);
|
||||
}
|
||||
|
||||
let main_graph_container =
|
||||
factory.main_module_graph_container().await?;
|
||||
|
||||
// Typecheck
|
||||
main_graph_container
|
||||
.check_specifiers(
|
||||
&specifiers_for_typecheck_and_test,
|
||||
cli_options.ext_flag().as_ref(),
|
||||
let workspace_files_factory =
|
||||
WorkspaceFilesFactory::from_workspace_dirs_with_files(
|
||||
workspace_dirs_with_files,
|
||||
|patterns, cli_options, file_fetcher, doc| {
|
||||
collect_specifiers_for_tests(
|
||||
patterns,
|
||||
cli_options,
|
||||
file_fetcher,
|
||||
doc,
|
||||
)
|
||||
.boxed_local()
|
||||
},
|
||||
test_flags.doc,
|
||||
Some(extract_doc_tests),
|
||||
&cli_options,
|
||||
Some(&watcher_communicator),
|
||||
)
|
||||
.await?;
|
||||
|
||||
if workspace_test_options.no_run {
|
||||
workspace_files_factory.check().await?;
|
||||
|
||||
if test_flags.no_run {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let worker_factory =
|
||||
Arc::new(factory.create_cli_main_worker_factory().await?);
|
||||
|
||||
let initial_cwd = workspace_files_factory.initial_cwd();
|
||||
test_specifiers(
|
||||
worker_factory,
|
||||
&permissions,
|
||||
permission_desc_parser,
|
||||
specifiers_for_typecheck_and_test,
|
||||
&workspace_files_factory,
|
||||
changed_paths.map(|p| p.into_iter().collect()).as_ref(),
|
||||
TestSpecifiersOptions {
|
||||
cwd: Url::from_directory_path(cli_options.initial_cwd()).map_err(
|
||||
|_| {
|
||||
generic_error(format!(
|
||||
"Unable to construct URL from the path of cwd: {}",
|
||||
cli_options.initial_cwd().to_string_lossy(),
|
||||
))
|
||||
},
|
||||
)?,
|
||||
concurrent_jobs: workspace_test_options.concurrent_jobs,
|
||||
fail_fast: workspace_test_options.fail_fast,
|
||||
cwd: Url::from_directory_path(initial_cwd).map_err(|_| {
|
||||
generic_error(format!(
|
||||
"Unable to construct URL from the path of cwd: {}",
|
||||
initial_cwd.to_string_lossy(),
|
||||
))
|
||||
})?,
|
||||
concurrent_jobs: test_flags
|
||||
.concurrent_jobs
|
||||
.unwrap_or_else(|| NonZeroUsize::new(1).unwrap()),
|
||||
fail_fast: test_flags.fail_fast,
|
||||
log_level,
|
||||
filter: workspace_test_options.filter.is_some(),
|
||||
reporter: workspace_test_options.reporter,
|
||||
junit_path: workspace_test_options.junit_path,
|
||||
hide_stacktraces: workspace_test_options.hide_stacktraces,
|
||||
filter: test_flags.filter.is_some(),
|
||||
reporter: test_flags.reporter,
|
||||
junit_path: test_flags.junit_path,
|
||||
hide_stacktraces: test_flags.hide_stacktraces,
|
||||
specifier: TestSpecifierOptions {
|
||||
filter: TestFilter::from_flag(&workspace_test_options.filter),
|
||||
shuffle: workspace_test_options.shuffle,
|
||||
trace_leaks: workspace_test_options.trace_leaks,
|
||||
filter: TestFilter::from_flag(&test_flags.filter),
|
||||
shuffle: test_flags.shuffle,
|
||||
trace_leaks: test_flags.trace_leaks,
|
||||
},
|
||||
},
|
||||
)
|
||||
|
@ -1824,38 +1667,6 @@ pub async fn run_tests_with_watch(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Extracts doc tests from files specified by the given specifiers.
|
||||
async fn get_doc_tests(
|
||||
specifiers_with_mode: &[(Url, TestMode)],
|
||||
file_fetcher: &CliFileFetcher,
|
||||
) -> Result<Vec<File>, AnyError> {
|
||||
let specifiers_needing_extraction = specifiers_with_mode
|
||||
.iter()
|
||||
.filter(|(_, mode)| mode.needs_test_extraction())
|
||||
.map(|(s, _)| s);
|
||||
|
||||
let mut doc_tests = Vec::new();
|
||||
for s in specifiers_needing_extraction {
|
||||
let file = file_fetcher.fetch_bypass_permissions(s).await?;
|
||||
doc_tests.extend(extract_doc_tests(file)?);
|
||||
}
|
||||
|
||||
Ok(doc_tests)
|
||||
}
|
||||
|
||||
/// Get a list of specifiers that we need to perform typecheck and run tests on.
|
||||
/// The result includes "pseudo specifiers" for doc tests.
|
||||
fn get_target_specifiers(
|
||||
specifiers_with_mode: Vec<(Url, TestMode)>,
|
||||
doc_tests: &[File],
|
||||
) -> Vec<Url> {
|
||||
specifiers_with_mode
|
||||
.into_iter()
|
||||
.filter_map(|(s, mode)| mode.needs_test_run().then_some(s))
|
||||
.chain(doc_tests.iter().map(|d| d.url.clone()))
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Tracks failures for the `--fail-fast` argument in
|
||||
/// order to tell when to stop running tests.
|
||||
#[derive(Clone, Default)]
|
||||
|
|
|
@ -321,7 +321,7 @@ impl fmt::Display for Diagnostic {
|
|||
}
|
||||
|
||||
#[derive(Clone, Debug, Default, Eq, PartialEq)]
|
||||
pub struct Diagnostics(Vec<Diagnostic>);
|
||||
pub struct Diagnostics(pub Vec<Diagnostic>);
|
||||
|
||||
impl Diagnostics {
|
||||
#[cfg(test)]
|
||||
|
|
14
tests/specs/check/check_workspace/__test__.jsonc
Normal file
14
tests/specs/check/check_workspace/__test__.jsonc
Normal file
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"tests": {
|
||||
"discover": {
|
||||
"args": "check --quiet main.ts member/mod.ts",
|
||||
"output": "check_discover.out",
|
||||
"exitCode": 1
|
||||
},
|
||||
"config_flag": {
|
||||
"args": "check --quiet --config deno.json main.ts member/mod.ts",
|
||||
"output": "check_config_flag.out",
|
||||
"exitCode": 1
|
||||
}
|
||||
}
|
||||
}
|
11
tests/specs/check/check_workspace/check_config_flag.out
Normal file
11
tests/specs/check/check_workspace/check_config_flag.out
Normal file
|
@ -0,0 +1,11 @@
|
|||
error: TS2304 [ERROR]: Cannot find name 'onmessage'.
|
||||
onmessage;
|
||||
~~~~~~~~~
|
||||
at file:///[WILDCARD]/main.ts:8:1
|
||||
|
||||
TS2304 [ERROR]: Cannot find name 'onmessage'.
|
||||
onmessage;
|
||||
~~~~~~~~~
|
||||
at file:///[WILDCARD]/member/mod.ts:5:1
|
||||
|
||||
Found 2 errors.
|
11
tests/specs/check/check_workspace/check_discover.out
Normal file
11
tests/specs/check/check_workspace/check_discover.out
Normal file
|
@ -0,0 +1,11 @@
|
|||
error: TS2304 [ERROR]: Cannot find name 'onmessage'.
|
||||
onmessage;
|
||||
~~~~~~~~~
|
||||
at file:///[WILDCARD]/main.ts:8:1
|
||||
|
||||
TS2304 [ERROR]: Cannot find name 'localStorage'.
|
||||
localStorage;
|
||||
~~~~~~~~~~~~
|
||||
at file:///[WILDCARD]/member/mod.ts:2:1
|
||||
|
||||
Found 2 errors.
|
3
tests/specs/check/check_workspace/deno.json
Normal file
3
tests/specs/check/check_workspace/deno.json
Normal file
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"workspace": ["member"]
|
||||
}
|
8
tests/specs/check/check_workspace/main.ts
Normal file
8
tests/specs/check/check_workspace/main.ts
Normal file
|
@ -0,0 +1,8 @@
|
|||
// We shouldn't get diagnostics from this import under this check scope.
|
||||
import "./member/mod.ts";
|
||||
|
||||
// Only defined for window.
|
||||
localStorage;
|
||||
|
||||
// Only defined for worker.
|
||||
onmessage;
|
5
tests/specs/check/check_workspace/member/deno.json
Normal file
5
tests/specs/check/check_workspace/member/deno.json
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"lib": ["deno.worker"]
|
||||
}
|
||||
}
|
5
tests/specs/check/check_workspace/member/mod.ts
Normal file
5
tests/specs/check/check_workspace/member/mod.ts
Normal file
|
@ -0,0 +1,5 @@
|
|||
// Only defined for window.
|
||||
localStorage;
|
||||
|
||||
// Only defined for worker.
|
||||
onmessage;
|
|
@ -1,5 +1,4 @@
|
|||
Check file:///[WILDLINE]/integration.test.ts
|
||||
Check file:///[WILDLINE]/pkg/mod.test.ts
|
||||
running 1 test from ./integration.test.ts
|
||||
should add ... ok ([WILDLINE])
|
||||
running 1 test from ./pkg/mod.test.ts
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
Warning "compilerOptions" field can only be specified in the workspace root deno.json file.
|
||||
Warning "lock" field can only be specified in the workspace root deno.json file.
|
||||
at file:///[WILDLINE]/sub/deno.json
|
||||
Warning "lint.report" field can only be specified in the workspace root deno.json file.
|
||||
at file:///[WILDLINE]/sub/deno.json
|
||||
|
|
|
@ -2,7 +2,5 @@
|
|||
"lint": {
|
||||
"report": "compact"
|
||||
},
|
||||
"compilerOptions": {
|
||||
"strict": true
|
||||
}
|
||||
"lock": false
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue