mirror of
https://github.com/denoland/deno.git
synced 2025-01-21 04:52:26 -05:00
WorkspaceFileContainer
This commit is contained in:
parent
6499ad6ae7
commit
de4e641360
5 changed files with 165 additions and 98 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -1432,7 +1432,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "deno_config"
|
||||
version = "0.39.3"
|
||||
source = "git+https://github.com/denoland/deno_config.git?branch=compiler-options-from-workspace-member#81d8e844624a8f6b3961213d1480dcc923d08b11"
|
||||
source = "git+https://github.com/denoland/deno_config.git?rev=81d8e844624a8f6b3961213d1480dcc923d08b11#81d8e844624a8f6b3961213d1480dcc923d08b11"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"deno_package_json",
|
||||
|
|
|
@ -52,7 +52,7 @@ deno_core = { version = "0.323.0" }
|
|||
|
||||
deno_bench_util = { version = "0.174.0", path = "./bench_util" }
|
||||
# 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", branch = "compiler-options-from-workspace-member", features = ["workspace", "sync"] }
|
||||
deno_config = { git = "https://github.com/denoland/deno_config.git", rev = "81d8e844624a8f6b3961213d1480dcc923d08b11", features = ["workspace", "sync"] }
|
||||
deno_lockfile = "=0.23.2"
|
||||
deno_media_type = { version = "0.2.0", features = ["module_specifier"] }
|
||||
deno_npm = "=0.26.0"
|
||||
|
|
|
@ -811,7 +811,7 @@ pub struct ScopeOptions {
|
|||
pub struct CliOptions {
|
||||
// the source of the options is a detail the rest of the
|
||||
// application need not concern itself with, so keep these private
|
||||
flags: Arc<Flags>,
|
||||
pub flags: Arc<Flags>,
|
||||
initial_cwd: PathBuf,
|
||||
main_module_cell: std::sync::OnceLock<Result<ModuleSpecifier, AnyError>>,
|
||||
maybe_node_modules_folder: Option<PathBuf>,
|
||||
|
|
142
cli/factory.rs
142
cli/factory.rs
|
@ -1,12 +1,15 @@
|
|||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
use crate::args::check_warn_tsconfig;
|
||||
use crate::args::discover_npmrc_from_workspace;
|
||||
use crate::args::get_root_cert_store;
|
||||
use crate::args::CaData;
|
||||
use crate::args::CliLockfile;
|
||||
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;
|
||||
|
@ -51,22 +54,30 @@ use crate::resolver::CliSloppyImportsResolver;
|
|||
use crate::resolver::NpmModuleLoader;
|
||||
use crate::resolver::SloppyImportsCachedFs;
|
||||
use crate::standalone::DenoCompileBinaryWriter;
|
||||
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::extract;
|
||||
use crate::util::file_watcher::WatcherCommunicator;
|
||||
use crate::util::fs::canonicalize_path_maybe_not_exists;
|
||||
use crate::util::progress_bar::ProgressBar;
|
||||
use crate::util::progress_bar::ProgressBarStyle;
|
||||
use crate::worker::CliMainWorkerFactory;
|
||||
use crate::worker::CliMainWorkerOptions;
|
||||
use std::collections::BTreeSet;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use deno_ast::ModuleSpecifier;
|
||||
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;
|
||||
|
@ -1052,3 +1063,134 @@ impl CliFactory {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub struct WorkspaceFileContainerEntry<T> {
|
||||
main_graph_container: Arc<MainModuleGraphContainer>,
|
||||
specifiers: Vec<(ModuleSpecifier, T)>,
|
||||
snippet_file_specifiers: Option<Vec<ModuleSpecifier>>,
|
||||
}
|
||||
|
||||
pub struct WorkspaceFileContainer<T> {
|
||||
entries: Vec<WorkspaceFileContainerEntry<T>>,
|
||||
}
|
||||
|
||||
impl<T> WorkspaceFileContainer<T> {
|
||||
#[allow(clippy::type_complexity)]
|
||||
pub async fn from_workspace_dirs_with_files(
|
||||
mut workspace_dirs_with_files: Vec<(Arc<WorkspaceDirectory>, FilePatterns)>,
|
||||
collect_files: fn(
|
||||
FilePatterns,
|
||||
Arc<CliOptions>,
|
||||
Arc<FileFetcher>,
|
||||
) -> std::pin::Pin<
|
||||
Box<dyn Future<Output = Result<Vec<(ModuleSpecifier, T)>, AnyError>>>,
|
||||
>,
|
||||
cli_options: &CliOptions,
|
||||
check_doc: bool,
|
||||
) -> Result<Self, AnyError> {
|
||||
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 entries = Vec::with_capacity(dir_count);
|
||||
for (workspace_dir, files) in workspace_dirs_with_files {
|
||||
let (npmrc, _) = discover_npmrc_from_workspace(&workspace_dir.workspace)?;
|
||||
let lockfile =
|
||||
CliLockfile::discover(&cli_options.flags, &workspace_dir.workspace)?;
|
||||
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(CliOptions::new(
|
||||
cli_options.flags.clone(),
|
||||
cli_options.initial_cwd().to_path_buf(),
|
||||
lockfile.map(Arc::new),
|
||||
npmrc,
|
||||
workspace_dir,
|
||||
false,
|
||||
scope_options.map(Arc::new),
|
||||
)?);
|
||||
let factory = CliFactory::from_cli_options(cli_options.clone());
|
||||
let file_fetcher = factory.file_fetcher()?;
|
||||
let main_graph_container =
|
||||
factory.main_module_graph_container().await?.clone();
|
||||
let specifiers =
|
||||
collect_files(files, cli_options, file_fetcher.clone()).await?;
|
||||
let snippet_file_specifiers = if check_doc {
|
||||
let root_permissions = factory.root_permissions_container()?;
|
||||
let mut snippet_file_specifiers = Vec::new();
|
||||
for (s, _) in specifiers.iter() {
|
||||
let file = file_fetcher.fetch(s, root_permissions).await?;
|
||||
let snippet_files = extract::extract_snippet_files(file)?;
|
||||
for snippet_file in snippet_files {
|
||||
snippet_file_specifiers.push(snippet_file.specifier.clone());
|
||||
file_fetcher.insert_memory_files(snippet_file);
|
||||
}
|
||||
}
|
||||
Some(snippet_file_specifiers)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
entries.push(WorkspaceFileContainerEntry {
|
||||
main_graph_container,
|
||||
specifiers,
|
||||
snippet_file_specifiers,
|
||||
});
|
||||
}
|
||||
Ok(Self { entries })
|
||||
}
|
||||
|
||||
pub async fn check(&self) -> Result<(), AnyError> {
|
||||
let mut diagnostics = vec![];
|
||||
let mut all_errors = vec![];
|
||||
for entry in &self.entries {
|
||||
let specifiers_for_typecheck = entry
|
||||
.specifiers
|
||||
.iter()
|
||||
.map(|(s, _)| s)
|
||||
.chain(entry.snippet_file_specifiers.iter().flatten())
|
||||
.cloned()
|
||||
.collect::<Vec<_>>();
|
||||
if specifiers_for_typecheck.is_empty() {
|
||||
continue;
|
||||
}
|
||||
if let Err(err) = entry
|
||||
.main_graph_container
|
||||
.check_specifiers(&specifiers_for_typecheck, None)
|
||||
.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(())
|
||||
}
|
||||
|
||||
pub fn has_specifiers(&self) -> bool {
|
||||
self.entries.iter().any(|e| !e.specifiers.is_empty())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
use std::collections::BTreeSet;
|
||||
use std::collections::HashSet;
|
||||
use std::collections::VecDeque;
|
||||
use std::error::Error;
|
||||
|
@ -12,8 +11,8 @@ use deno_ast::MediaType;
|
|||
use deno_ast::ModuleSpecifier;
|
||||
use deno_config::glob::FilePatterns;
|
||||
use deno_config::glob::PathOrPattern;
|
||||
use deno_core::anyhow::anyhow;
|
||||
use deno_core::error::AnyError;
|
||||
use deno_core::futures::FutureExt;
|
||||
use deno_graph::Module;
|
||||
use deno_graph::ModuleGraph;
|
||||
use deno_runtime::deno_node::NodeResolver;
|
||||
|
@ -22,14 +21,11 @@ use once_cell::sync::Lazy;
|
|||
use regex::Regex;
|
||||
|
||||
use crate::args::check_warn_tsconfig;
|
||||
use crate::args::discover_npmrc_from_workspace;
|
||||
use crate::args::CheckFlags;
|
||||
use crate::args::CliLockfile;
|
||||
use crate::args::CliOptions;
|
||||
use crate::args::ConfigFlag;
|
||||
use crate::args::FileFlags;
|
||||
use crate::args::Flags;
|
||||
use crate::args::ScopeOptions;
|
||||
use crate::args::TsConfig;
|
||||
use crate::args::TsConfigType;
|
||||
use crate::args::TsTypeLib;
|
||||
|
@ -39,6 +35,7 @@ use crate::cache::Caches;
|
|||
use crate::cache::FastInsecureHasher;
|
||||
use crate::cache::TypeCheckCache;
|
||||
use crate::factory::CliFactory;
|
||||
use crate::factory::WorkspaceFileContainer;
|
||||
use crate::graph_util::BuildFastCheckGraphOptions;
|
||||
use crate::graph_util::ModuleGraphBuilder;
|
||||
use crate::npm::CliNpmResolver;
|
||||
|
@ -101,99 +98,27 @@ pub async fn check(
|
|||
.map(PathOrPattern::RemoteUrl),
|
||||
);
|
||||
}
|
||||
let all_scopes = Arc::new(
|
||||
by_workspace_directory
|
||||
.iter()
|
||||
.filter(|(_, (d, _))| d.has_deno_or_pkg_json())
|
||||
.map(|(s, (_, _))| s.clone())
|
||||
.collect::<BTreeSet<_>>(),
|
||||
);
|
||||
let dir_count = by_workspace_directory.len();
|
||||
let mut diagnostics = vec![];
|
||||
let mut all_errors = vec![];
|
||||
let mut found_specifiers = false;
|
||||
for (dir_url, (workspace_directory, patterns)) in by_workspace_directory {
|
||||
let (npmrc, _) =
|
||||
discover_npmrc_from_workspace(&workspace_directory.workspace)?;
|
||||
let lockfile =
|
||||
CliLockfile::discover(&flags, &workspace_directory.workspace)?;
|
||||
let scope_options = (dir_count > 1).then(|| ScopeOptions {
|
||||
scope: workspace_directory
|
||||
.has_deno_or_pkg_json()
|
||||
.then(|| dir_url.clone()),
|
||||
all_scopes: all_scopes.clone(),
|
||||
});
|
||||
let cli_options = CliOptions::new(
|
||||
flags.clone(),
|
||||
cli_options.initial_cwd().to_path_buf(),
|
||||
lockfile.map(Arc::new),
|
||||
npmrc,
|
||||
workspace_directory,
|
||||
false,
|
||||
scope_options.map(Arc::new),
|
||||
)?;
|
||||
let specifiers = collect_specifiers(
|
||||
patterns,
|
||||
cli_options.vendor_dir_path().map(ToOwned::to_owned),
|
||||
|e| is_script_ext(e.path),
|
||||
)?;
|
||||
if specifiers.is_empty() {
|
||||
continue;
|
||||
} else {
|
||||
found_specifiers = true;
|
||||
}
|
||||
let factory = CliFactory::from_cli_options(Arc::new(cli_options));
|
||||
let main_graph_container = factory.main_module_graph_container().await?;
|
||||
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.specifier.clone());
|
||||
file_fetcher.insert_memory_files(snippet_file);
|
||||
}
|
||||
let container = WorkspaceFileContainer::from_workspace_dirs_with_files(
|
||||
by_workspace_directory.into_values().collect(),
|
||||
|patterns, cli_options, _| {
|
||||
async move {
|
||||
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, ())).collect())
|
||||
}
|
||||
specifiers_for_typecheck
|
||||
} else {
|
||||
specifiers
|
||||
};
|
||||
if let Err(err) = main_graph_container
|
||||
.check_specifiers(&specifiers_for_typecheck, None)
|
||||
.await
|
||||
{
|
||||
match err {
|
||||
MaybeDiagnostics::Diagnostics(Diagnostics(d)) => {
|
||||
diagnostics.extend(d)
|
||||
}
|
||||
MaybeDiagnostics::Other(err) => all_errors.push(err),
|
||||
}
|
||||
}
|
||||
}
|
||||
if !found_specifiers {
|
||||
.boxed_local()
|
||||
},
|
||||
cli_options,
|
||||
check_flags.doc || check_flags.doc_only,
|
||||
)
|
||||
.await?;
|
||||
if !container.has_specifiers() {
|
||||
log::warn!("{} No matching files found.", colors::yellow("Warning"));
|
||||
}
|
||||
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"),
|
||||
));
|
||||
}
|
||||
return Ok(());
|
||||
return container.check().await;
|
||||
}
|
||||
|
||||
let factory = CliFactory::from_flags(flags);
|
||||
|
|
Loading…
Add table
Reference in a new issue