diff options
Diffstat (limited to 'cli/graph_util.rs')
-rw-r--r-- | cli/graph_util.rs | 300 |
1 files changed, 204 insertions, 96 deletions
diff --git a/cli/graph_util.rs b/cli/graph_util.rs index df4e5132d..60b1b80d0 100644 --- a/cli/graph_util.rs +++ b/cli/graph_util.rs @@ -6,21 +6,25 @@ use crate::args::TsConfigType; use crate::args::TsTypeLib; use crate::args::TypeCheckMode; use crate::cache; +use crate::cache::DenoDir; +use crate::cache::ParsedSourceCache; use crate::cache::TypeCheckCache; use crate::colors; use crate::errors::get_error_class_name; +use crate::file_fetcher::FileFetcher; use crate::npm::NpmPackageResolver; -use crate::proc_state::ProcState; use crate::resolver::CliGraphResolver; use crate::tools::check; use deno_core::anyhow::bail; use deno_core::error::custom_error; use deno_core::error::AnyError; +use deno_core::parking_lot::Mutex; use deno_core::parking_lot::RwLock; use deno_core::ModuleSpecifier; use deno_core::TaskQueue; use deno_core::TaskQueuePermit; +use deno_graph::source::Loader; use deno_graph::Module; use deno_graph::ModuleError; use deno_graph::ModuleGraph; @@ -160,115 +164,215 @@ pub fn graph_lock_or_exit(graph: &ModuleGraph, lockfile: &mut Lockfile) { } } -pub async fn create_graph_and_maybe_check( - roots: Vec<ModuleSpecifier>, - ps: &ProcState, -) -> Result<Arc<deno_graph::ModuleGraph>, AnyError> { - let mut cache = cache::FetchCacher::new( - ps.emit_cache.clone(), - ps.file_fetcher.clone(), - ps.options.resolve_file_header_overrides(), - PermissionsContainer::allow_all(), - PermissionsContainer::allow_all(), - ps.options.node_modules_dir_specifier(), - ); - let maybe_imports = ps.options.to_maybe_imports()?; - let cli_resolver = CliGraphResolver::new( - ps.options.to_maybe_jsx_import_source_config(), - ps.maybe_import_map.clone(), - ps.options.no_npm(), - ps.npm_api.clone(), - ps.npm_resolution.clone(), - ps.package_json_deps_installer.clone(), - ); - let graph_resolver = cli_resolver.as_graph_resolver(); - let graph_npm_resolver = cli_resolver.as_graph_npm_resolver(); - let analyzer = ps.parsed_source_cache.as_analyzer(); - let mut graph = ModuleGraph::default(); - build_graph_with_npm_resolution( - &mut graph, - &cli_resolver, - &ps.npm_resolver, - roots, - &mut cache, - deno_graph::BuildOptions { - is_dynamic: false, - imports: maybe_imports, - resolver: Some(graph_resolver), - npm_resolver: Some(graph_npm_resolver), - module_analyzer: Some(&*analyzer), - reporter: None, - }, - ) - .await?; +pub struct ModuleGraphBuilder { + options: Arc<CliOptions>, + resolver: Arc<CliGraphResolver>, + npm_resolver: Arc<NpmPackageResolver>, + parsed_source_cache: Arc<ParsedSourceCache>, + lockfile: Option<Arc<Mutex<Lockfile>>>, + caches: Arc<cache::Caches>, + emit_cache: cache::EmitCache, + file_fetcher: Arc<FileFetcher>, + deno_dir: DenoDir, +} - graph_valid_with_cli_options(&graph, &graph.roots, &ps.options)?; - let graph = Arc::new(graph); - if let Some(lockfile) = &ps.lockfile { - graph_lock_or_exit(&graph, &mut lockfile.lock()); +impl ModuleGraphBuilder { + #[allow(clippy::too_many_arguments)] + pub fn new( + options: Arc<CliOptions>, + resolver: Arc<CliGraphResolver>, + npm_resolver: Arc<NpmPackageResolver>, + parsed_source_cache: Arc<ParsedSourceCache>, + lockfile: Option<Arc<Mutex<Lockfile>>>, + caches: Arc<cache::Caches>, + emit_cache: cache::EmitCache, + file_fetcher: Arc<FileFetcher>, + deno_dir: DenoDir, + ) -> Self { + Self { + options, + resolver, + npm_resolver, + parsed_source_cache, + lockfile, + caches, + emit_cache, + file_fetcher, + deno_dir, + } } - if ps.options.type_check_mode() != TypeCheckMode::None { - // node built-in specifiers use the @types/node package to determine - // types, so inject that now after the lockfile has been written - if graph.has_node_specifier { - ps.npm_resolver + pub async fn create_graph_with_loader( + &self, + roots: Vec<ModuleSpecifier>, + loader: &mut dyn Loader, + ) -> Result<deno_graph::ModuleGraph, AnyError> { + let maybe_imports = self.options.to_maybe_imports()?; + + let cli_resolver = self.resolver.clone(); + let graph_resolver = cli_resolver.as_graph_resolver(); + let graph_npm_resolver = cli_resolver.as_graph_npm_resolver(); + let analyzer = self.parsed_source_cache.as_analyzer(); + + let mut graph = ModuleGraph::default(); + self + .build_graph_with_npm_resolution( + &mut graph, + roots, + loader, + deno_graph::BuildOptions { + is_dynamic: false, + imports: maybe_imports, + resolver: Some(graph_resolver), + npm_resolver: Some(graph_npm_resolver), + module_analyzer: Some(&*analyzer), + reporter: None, + }, + ) + .await?; + + if graph.has_node_specifier + && self.options.type_check_mode() != TypeCheckMode::None + { + self + .npm_resolver .inject_synthetic_types_node_package() .await?; } - let ts_config_result = - ps.options.resolve_ts_config_for_emit(TsConfigType::Check { - lib: ps.options.ts_type_lib_window(), - })?; - if let Some(ignored_options) = ts_config_result.maybe_ignored_options { - log::warn!("{}", ignored_options); + Ok(graph) + } + + pub async fn create_graph_and_maybe_check( + &self, + roots: Vec<ModuleSpecifier>, + ) -> Result<Arc<deno_graph::ModuleGraph>, AnyError> { + let mut cache = self.create_graph_loader(); + let maybe_imports = self.options.to_maybe_imports()?; + let cli_resolver = self.resolver.clone(); + let graph_resolver = cli_resolver.as_graph_resolver(); + let graph_npm_resolver = cli_resolver.as_graph_npm_resolver(); + let analyzer = self.parsed_source_cache.as_analyzer(); + let mut graph = ModuleGraph::default(); + self + .build_graph_with_npm_resolution( + &mut graph, + roots, + &mut cache, + deno_graph::BuildOptions { + is_dynamic: false, + imports: maybe_imports, + resolver: Some(graph_resolver), + npm_resolver: Some(graph_npm_resolver), + module_analyzer: Some(&*analyzer), + reporter: None, + }, + ) + .await?; + + graph_valid_with_cli_options(&graph, &graph.roots, &self.options)?; + let graph = Arc::new(graph); + if let Some(lockfile) = &self.lockfile { + graph_lock_or_exit(&graph, &mut lockfile.lock()); } - let maybe_config_specifier = ps.options.maybe_config_file_specifier(); - let cache = TypeCheckCache::new(ps.caches.type_checking_cache_db(&ps.dir)); - let check_result = check::check( - graph.clone(), - &cache, - &ps.npm_resolver, - check::CheckOptions { - type_check_mode: ps.options.type_check_mode(), - debug: ps.options.log_level() == Some(log::Level::Debug), - maybe_config_specifier, - ts_config: ts_config_result.ts_config, - log_checks: true, - reload: ps.options.reload_flag(), - }, - )?; - log::debug!("{}", check_result.stats); - if !check_result.diagnostics.is_empty() { - return Err(check_result.diagnostics.into()); + + if self.options.type_check_mode() != TypeCheckMode::None { + // node built-in specifiers use the @types/node package to determine + // types, so inject that now after the lockfile has been written + if graph.has_node_specifier { + self + .npm_resolver + .inject_synthetic_types_node_package() + .await?; + } + + let ts_config_result = + self + .options + .resolve_ts_config_for_emit(TsConfigType::Check { + lib: self.options.ts_type_lib_window(), + })?; + if let Some(ignored_options) = ts_config_result.maybe_ignored_options { + log::warn!("{}", ignored_options); + } + let maybe_config_specifier = self.options.maybe_config_file_specifier(); + let cache = + TypeCheckCache::new(self.caches.type_checking_cache_db(&self.deno_dir)); + let check_result = check::check( + graph.clone(), + &cache, + self.npm_resolver.clone(), + check::CheckOptions { + type_check_mode: self.options.type_check_mode(), + debug: self.options.log_level() == Some(log::Level::Debug), + maybe_config_specifier, + ts_config: ts_config_result.ts_config, + log_checks: true, + reload: self.options.reload_flag(), + }, + )?; + log::debug!("{}", check_result.stats); + if !check_result.diagnostics.is_empty() { + return Err(check_result.diagnostics.into()); + } } + + Ok(graph) } - Ok(graph) -} + pub async fn build_graph_with_npm_resolution<'a>( + &self, + graph: &mut ModuleGraph, + roots: Vec<ModuleSpecifier>, + loader: &mut dyn deno_graph::source::Loader, + options: deno_graph::BuildOptions<'a>, + ) -> Result<(), AnyError> { + graph.build(roots, loader, options).await; + + // ensure that the top level package.json is installed if a + // specifier was matched in the package.json + self + .resolver + .top_level_package_json_install_if_necessary() + .await?; + + // resolve the dependencies of any pending dependencies + // that were inserted by building the graph + self.npm_resolver.resolve_pending().await?; -pub async fn build_graph_with_npm_resolution<'a>( - graph: &mut ModuleGraph, - cli_graph_resolver: &CliGraphResolver, - npm_resolver: &NpmPackageResolver, - roots: Vec<ModuleSpecifier>, - loader: &mut dyn deno_graph::source::Loader, - options: deno_graph::BuildOptions<'a>, -) -> Result<(), AnyError> { - graph.build(roots, loader, options).await; + Ok(()) + } - // ensure that the top level package.json is installed if a - // specifier was matched in the package.json - cli_graph_resolver - .top_level_package_json_install_if_necessary() - .await?; + /// Creates the default loader used for creating a graph. + pub fn create_graph_loader(&self) -> cache::FetchCacher { + self.create_fetch_cacher( + PermissionsContainer::allow_all(), + PermissionsContainer::allow_all(), + ) + } - // resolve the dependencies of any pending dependencies - // that were inserted by building the graph - npm_resolver.resolve_pending().await?; + pub fn create_fetch_cacher( + &self, + root_permissions: PermissionsContainer, + dynamic_permissions: PermissionsContainer, + ) -> cache::FetchCacher { + cache::FetchCacher::new( + self.emit_cache.clone(), + self.file_fetcher.clone(), + self.options.resolve_file_header_overrides(), + root_permissions, + dynamic_permissions, + self.options.node_modules_dir_specifier(), + ) + } - Ok(()) + pub async fn create_graph( + &self, + roots: Vec<ModuleSpecifier>, + ) -> Result<deno_graph::ModuleGraph, AnyError> { + let mut cache = self.create_graph_loader(); + self.create_graph_with_loader(roots, &mut cache).await + } } pub fn error_for_any_npm_specifier( @@ -338,7 +442,7 @@ struct GraphData { } /// Holds the `ModuleGraph` and what parts of it are type checked. -#[derive(Clone, Default)] +#[derive(Default)] pub struct ModuleGraphContainer { // Allow only one request to update the graph data at a time, // but allow other requests to read from it at any time even @@ -348,6 +452,10 @@ pub struct ModuleGraphContainer { } impl ModuleGraphContainer { + pub fn clear(&self) { + self.graph_data.write().graph = Default::default(); + } + /// Acquires a permit to modify the module graph without other code /// having the chance to modify it. In the meantime, other code may /// still read from the existing module graph. |