diff options
author | Kitson Kelly <me@kitsonkelly.com> | 2021-06-22 07:18:32 +1000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-06-22 07:18:32 +1000 |
commit | 281c4cd8fcf5fd54f558a6922736def2c7804529 (patch) | |
tree | 65ac91c5a41a64dc0b85ee9c5949d7086e8620ef /cli/module_graph.rs | |
parent | cda15f2a98b10330422d1c8352d163d703ee6a49 (diff) |
feat(cli): support "types" when type checking (#10999)
Fixes #10677
Diffstat (limited to 'cli/module_graph.rs')
-rw-r--r-- | cli/module_graph.rs | 117 |
1 files changed, 97 insertions, 20 deletions
diff --git a/cli/module_graph.rs b/cli/module_graph.rs index 770f8b872..8ea8b7f88 100644 --- a/cli/module_graph.rs +++ b/cli/module_graph.rs @@ -7,6 +7,7 @@ use crate::ast::Location; use crate::ast::ParsedModule; use crate::checksum; use crate::colors; +use crate::config_file::CompilerOptions; use crate::config_file::ConfigFile; use crate::config_file::IgnoredCompilerOptions; use crate::config_file::TsConfig; @@ -31,11 +32,13 @@ use deno_core::error::AnyError; use deno_core::error::Context; use deno_core::futures::stream::FuturesUnordered; use deno_core::futures::stream::StreamExt; +use deno_core::resolve_import; use deno_core::resolve_url_or_path; use deno_core::serde::Deserialize; use deno_core::serde::Deserializer; use deno_core::serde::Serialize; use deno_core::serde::Serializer; +use deno_core::serde_json; use deno_core::serde_json::json; use deno_core::serde_json::Value; use deno_core::url::Url; @@ -890,11 +893,20 @@ impl Graph { vec![config.as_bytes(), version::deno().as_bytes().to_owned()]; let graph = Arc::new(Mutex::new(self)); + let maybe_config_specifier = + if let Some(config_file) = &options.maybe_config_file { + ModuleSpecifier::from_file_path(&config_file.path).ok() + } else { + None + }; + debug!("maybe_config_specifier: {:?}", maybe_config_specifier); + let response = tsc::exec(tsc::Request { config: config.clone(), debug: options.debug, graph: graph.clone(), hash_data, + maybe_config_specifier, maybe_tsbuildinfo, root_names, })?; @@ -958,6 +970,11 @@ impl Graph { }) } + /// Indicates if the module graph contains the supplied specifier or not. + pub fn contains(&self, specifier: &ModuleSpecifier) -> bool { + matches!(self.get_module(specifier), ModuleSlot::Module(_)) + } + /// Emit the module graph in a specific format. This is specifically designed /// to be an "all-in-one" API for access by the runtime, allowing both /// emitting single modules as well as bundles, using Deno module resolution @@ -1025,6 +1042,7 @@ impl Graph { debug: options.debug, graph: graph.clone(), hash_data, + maybe_config_specifier: None, maybe_tsbuildinfo: None, root_names, })?; @@ -1829,26 +1847,7 @@ impl GraphBuilder { specifier: &ModuleSpecifier, is_dynamic: bool, ) -> Result<(), AnyError> { - self.fetch(specifier, &None, is_dynamic); - - loop { - match self.pending.next().await { - Some(Err((specifier, err))) => { - self - .graph - .modules - .insert(specifier, ModuleSlot::Err(Arc::new(err))); - } - Some(Ok(cached_module)) => { - let is_root = &cached_module.specifier == specifier; - self.visit(cached_module, is_root, is_dynamic)?; - } - _ => {} - } - if self.pending.is_empty() { - break; - } - } + self.insert(specifier, is_dynamic).await?; if !self.graph.roots.contains(specifier) { self.graph.roots.push(specifier.clone()); @@ -1862,6 +1861,53 @@ impl GraphBuilder { Ok(()) } + /// Analyze compiler options, identifying any specifiers that need to be + /// resolved and added to the graph. + pub async fn analyze_compiler_options( + &mut self, + maybe_compiler_options: &Option<HashMap<String, Value>>, + ) -> Result<(), AnyError> { + if let Some(user_config) = maybe_compiler_options { + if let Some(value) = user_config.get("types") { + let types: Vec<String> = serde_json::from_value(value.clone())?; + for specifier in types { + if let Ok(specifier) = resolve_url_or_path(&specifier) { + self.insert(&specifier, false).await?; + } + } + } + } + Ok(()) + } + + /// Analyze a config file, identifying any specifiers that need to be resolved + /// and added to the graph. + pub async fn analyze_config_file( + &mut self, + maybe_config_file: &Option<ConfigFile>, + ) -> Result<(), AnyError> { + if let Some(config_file) = maybe_config_file { + let referrer = ModuleSpecifier::from_file_path(&config_file.path) + .map_err(|_| { + anyhow!("Could not convert file path: \"{:?}\"", config_file.path) + })?; + if let Some(compiler_options) = &config_file.json.compiler_options { + let compiler_options: CompilerOptions = + serde_json::from_value(compiler_options.clone())?; + if let Some(types) = compiler_options.types { + for specifier in types { + if let Ok(specifier) = + resolve_import(&specifier, &referrer.to_string()) + { + self.insert(&specifier, false).await?; + } + } + } + } + } + Ok(()) + } + /// Request a module to be fetched from the handler and queue up its future /// to be awaited to be resolved. fn fetch( @@ -1882,6 +1928,37 @@ impl GraphBuilder { } } + /// An internal method that fetches the specifier and recursively fetches any + /// of the dependencies, adding them to the graph. + async fn insert( + &mut self, + specifier: &ModuleSpecifier, + is_dynamic: bool, + ) -> Result<(), AnyError> { + self.fetch(specifier, &None, is_dynamic); + + loop { + match self.pending.next().await { + Some(Err((specifier, err))) => { + self + .graph + .modules + .insert(specifier, ModuleSlot::Err(Arc::new(err))); + } + Some(Ok(cached_module)) => { + let is_root = &cached_module.specifier == specifier; + self.visit(cached_module, is_root, is_dynamic)?; + } + _ => {} + } + if self.pending.is_empty() { + break; + } + } + + Ok(()) + } + /// Visit a module that has been fetched, hydrating the module, analyzing its /// dependencies if required, fetching those dependencies, and inserting the /// module into the graph. |