summaryrefslogtreecommitdiff
path: root/cli/module_graph.rs
diff options
context:
space:
mode:
authorKitson Kelly <me@kitsonkelly.com>2021-06-22 07:18:32 +1000
committerGitHub <noreply@github.com>2021-06-22 07:18:32 +1000
commit281c4cd8fcf5fd54f558a6922736def2c7804529 (patch)
tree65ac91c5a41a64dc0b85ee9c5949d7086e8620ef /cli/module_graph.rs
parentcda15f2a98b10330422d1c8352d163d703ee6a49 (diff)
feat(cli): support "types" when type checking (#10999)
Fixes #10677
Diffstat (limited to 'cli/module_graph.rs')
-rw-r--r--cli/module_graph.rs117
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.