diff options
author | Bartek IwaĆczuk <biwanczuk@gmail.com> | 2023-01-25 21:13:40 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-01-25 21:13:40 +0100 |
commit | c6c8c91a6e4b7a2b6eed02d3e2f5db25c124d9a0 (patch) | |
tree | 1fe8e9ab2175154d44e78d153dd760e56dc1c860 /cli/lsp/language_server.rs | |
parent | b5b4887c4a5fefdeb5592ebaadcc941281d0c4d5 (diff) |
feat: embed import map in the config file (#17478)
This commit changes handling of config file to enable
specifying "imports" and "scopes" objects effectively making
the configuration file an import map.
"imports" and "scopes" take precedence over "importMap" configuration,
but have lower priority than "--importmap" CLI flag.
Co-authored-by: David Sherret <dsherret@users.noreply.github.com>
Co-authored-by: David Sherret <dsherret@gmail.com>
Diffstat (limited to 'cli/lsp/language_server.rs')
-rw-r--r-- | cli/lsp/language_server.rs | 177 |
1 files changed, 108 insertions, 69 deletions
diff --git a/cli/lsp/language_server.rs b/cli/lsp/language_server.rs index 0941fe0fb..7f53b17f3 100644 --- a/cli/lsp/language_server.rs +++ b/cli/lsp/language_server.rs @@ -57,6 +57,7 @@ use super::tsc::AssetsSnapshot; use super::tsc::TsServer; use super::urls; use crate::args::get_root_cert_store; +use crate::args::import_map_from_value; use crate::args::CaData; use crate::args::CacheSetting; use crate::args::CliOptions; @@ -72,7 +73,6 @@ use crate::http_util::HttpClient; use crate::npm::NpmCache; use crate::npm::NpmPackageResolver; use crate::npm::RealNpmRegistryApi; -use crate::proc_state::import_map_from_text; use crate::proc_state::ProcState; use crate::tools::fmt::format_file; use crate::tools::fmt::format_parsed_source; @@ -601,47 +601,84 @@ impl Inner { pub async fn update_import_map(&mut self) -> Result<(), AnyError> { let mark = self.performance.mark("update_import_map", None::<()>); - let maybe_import_map_url = if let Some(import_map_str) = self - .config - .get_workspace_settings() - .import_map - .and_then(|s| if s.is_empty() { None } else { Some(s) }) - { - lsp_log!( - "Setting import map from workspace settings: \"{}\"", - import_map_str - ); - if let Some(config_file) = &self.maybe_config_file { - if let Some(import_map_path) = config_file.to_import_map_path() { - lsp_log!("Warning: Import map \"{}\" configured in \"{}\" being ignored due to an import map being explicitly configured in workspace settings.", import_map_path, config_file.specifier); - } - } - if let Ok(url) = Url::from_file_path(&import_map_str) { - Some(url) - } else if import_map_str.starts_with("data:") { - Some(Url::parse(&import_map_str).map_err(|_| { - anyhow!("Bad data url for import map: {}", import_map_str) - })?) - } else if let Some(root_uri) = &self.config.root_uri { - let root_path = specifier_to_file_path(root_uri)?; - let import_map_path = root_path.join(&import_map_str); - Some(Url::from_file_path(import_map_path).map_err(|_| { - anyhow!("Bad file path for import map: {}", import_map_str) - })?) - } else { - return Err(anyhow!( - "The path to the import map (\"{}\") is not resolvable.", - import_map_str - )); - } - } else if let Some(config_file) = &self.maybe_config_file { - if let Some(import_map_path) = config_file.to_import_map_path() { + let maybe_import_map_url = self.resolve_import_map_specifier()?; + if let Some(import_map_url) = maybe_import_map_url { + let import_map = self + .resolve_import_map_from_specifier(&import_map_url) + .await + .map_err(|err| { + anyhow!( + "Failed to load the import map at: {}. {:#}", + import_map_url, + err + ) + })?; + self.maybe_import_map_uri = Some(import_map_url); + self.maybe_import_map = Some(Arc::new(import_map)); + } else { + self.maybe_import_map_uri = None; + self.maybe_import_map = None; + } + self.performance.measure(mark); + Ok(()) + } + + fn resolve_import_map_specifier( + &self, + ) -> Result<Option<ModuleSpecifier>, AnyError> { + Ok( + if let Some(import_map_str) = self + .config + .get_workspace_settings() + .import_map + .and_then(|s| if s.is_empty() { None } else { Some(s) }) + { lsp_log!( - "Setting import map from configuration file: \"{}\"", - import_map_path + "Setting import map from workspace settings: \"{}\"", + import_map_str ); - let specifier = - if let Ok(config_file_path) = config_file.specifier.to_file_path() { + if let Some(config_file) = &self.maybe_config_file { + if let Some(import_map_path) = config_file.to_import_map_path() { + lsp_log!("Warning: Import map \"{}\" configured in \"{}\" being ignored due to an import map being explicitly configured in workspace settings.", import_map_path, config_file.specifier); + } + } + if let Ok(url) = Url::from_file_path(&import_map_str) { + Some(url) + } else if import_map_str.starts_with("data:") { + let import_map_url = Url::parse(&import_map_str).map_err(|_| { + anyhow!("Bad data url for import map: {}", import_map_str) + })?; + Some(import_map_url) + } else if let Some(root_uri) = &self.config.root_uri { + let root_path = specifier_to_file_path(root_uri)?; + let import_map_path = root_path.join(&import_map_str); + let import_map_url = + Url::from_file_path(import_map_path).map_err(|_| { + anyhow!("Bad file path for import map: {}", import_map_str) + })?; + Some(import_map_url) + } else { + return Err(anyhow!( + "The path to the import map (\"{}\") is not resolvable.", + import_map_str + )); + } + } else if let Some(config_file) = &self.maybe_config_file { + if config_file.is_an_import_map() { + lsp_log!( + "Setting import map defined in configuration file: \"{}\"", + config_file.specifier + ); + let import_map_url = config_file.specifier.clone(); + Some(import_map_url) + } else if let Some(import_map_path) = config_file.to_import_map_path() { + lsp_log!( + "Setting import map from configuration file: \"{}\"", + import_map_path + ); + let specifier = if let Ok(config_file_path) = + config_file.specifier.to_file_path() + { let import_map_file_path = config_file_path .parent() .ok_or_else(|| { @@ -655,39 +692,41 @@ impl Inner { config_file.specifier.as_str(), )? }; - Some(specifier) + Some(specifier) + } else { + None + } } else { None - } + }, + ) + } + + async fn resolve_import_map_from_specifier( + &self, + import_map_url: &ModuleSpecifier, + ) -> Result<ImportMap, AnyError> { + let import_map_json: Value = if import_map_url.scheme() == "data" { + serde_json::from_str(&get_source_from_data_url(import_map_url)?.0)? } else { - None + let import_map_path = specifier_to_file_path(import_map_url)?; + lsp_log!( + " Resolved import map: \"{}\"", + import_map_path.to_string_lossy() + ); + let import_map_config_file = self + .maybe_config_file + .as_ref() + .filter(|c| c.specifier == *import_map_url); + match import_map_config_file { + Some(c) => c.to_import_map_value(), + None => { + serde_json::from_str(&fs::read_to_string(import_map_path).await?)? + } + } }; - if let Some(import_map_url) = maybe_import_map_url { - let import_map_json = if import_map_url.scheme() == "data" { - get_source_from_data_url(&import_map_url)?.0 - } else { - let import_map_path = specifier_to_file_path(&import_map_url)?; - lsp_log!( - " Resolved import map: \"{}\"", - import_map_path.to_string_lossy() - ); - fs::read_to_string(import_map_path).await.map_err(|err| { - anyhow!( - "Failed to load the import map at: {}. [{}]", - import_map_url, - err - ) - })? - }; - let import_map = import_map_from_text(&import_map_url, &import_map_json)?; - self.maybe_import_map_uri = Some(import_map_url); - self.maybe_import_map = Some(Arc::new(import_map)); - } else { - self.maybe_import_map_uri = None; - self.maybe_import_map = None; - } - self.performance.measure(mark); - Ok(()) + + import_map_from_value(import_map_url, import_map_json) } pub fn update_debug_flag(&self) { |