1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-01-21 04:52:26 -05:00

WorkspaceFileContainer

This commit is contained in:
Nayeem Rahman 2024-12-05 08:04:31 +00:00
parent 6499ad6ae7
commit de4e641360
5 changed files with 165 additions and 98 deletions

2
Cargo.lock generated
View file

@ -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",

View file

@ -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"

View file

@ -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>,

View file

@ -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())
}
}

View file

@ -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);