diff options
Diffstat (limited to 'cli/lsp/cache.rs')
-rw-r--r-- | cli/lsp/cache.rs | 82 |
1 files changed, 63 insertions, 19 deletions
diff --git a/cli/lsp/cache.rs b/cli/lsp/cache.rs index d899cd796..e6186030a 100644 --- a/cli/lsp/cache.rs +++ b/cli/lsp/cache.rs @@ -11,6 +11,7 @@ use deno_runtime::fs_util::specifier_to_file_path; use deno_core::url::Url; use deno_core::ModuleSpecifier; +use std::collections::BTreeMap; use std::fs; use std::path::Path; use std::sync::Arc; @@ -29,13 +30,14 @@ pub const LSP_DISALLOW_GLOBAL_TO_LOCAL_COPY: deno_cache_dir::GlobalToLocalCopy = pub fn calculate_fs_version( cache: &LspCache, specifier: &ModuleSpecifier, + file_referrer: Option<&ModuleSpecifier>, ) -> Option<String> { match specifier.scheme() { "npm" | "node" | "data" | "blob" => None, "file" => specifier_to_file_path(specifier) .ok() .and_then(|path| calculate_fs_version_at_path(&path)), - _ => calculate_fs_version_in_cache(cache, specifier), + _ => calculate_fs_version_in_cache(cache, specifier, file_referrer), } } @@ -56,8 +58,9 @@ pub fn calculate_fs_version_at_path(path: &Path) -> Option<String> { fn calculate_fs_version_in_cache( cache: &LspCache, specifier: &ModuleSpecifier, + file_referrer: Option<&ModuleSpecifier>, ) -> Option<String> { - let http_cache = cache.root_vendor_or_global(); + let http_cache = cache.for_specifier(file_referrer); let Ok(cache_key) = http_cache.cache_item_key(specifier) else { return Some("1".to_string()); }; @@ -77,7 +80,7 @@ fn calculate_fs_version_in_cache( pub struct LspCache { deno_dir: DenoDir, global: Arc<GlobalHttpCache>, - root_vendor: Option<Arc<LocalLspHttpCache>>, + vendors_by_scope: BTreeMap<ModuleSpecifier, Option<Arc<LocalLspHttpCache>>>, } impl Default for LspCache { @@ -107,18 +110,24 @@ impl LspCache { Self { deno_dir, global, - root_vendor: None, + vendors_by_scope: Default::default(), } } pub fn update_config(&mut self, config: &Config) { - self.root_vendor = config.tree.root_data().and_then(|data| { - let vendor_dir = data.vendor_dir.as_ref()?; - Some(Arc::new(LocalLspHttpCache::new( - vendor_dir.clone(), - self.global.clone(), - ))) - }); + self.vendors_by_scope = config + .tree + .data_by_scope() + .iter() + .map(|(scope, config_data)| { + ( + scope.clone(), + config_data.vendor_dir.as_ref().map(|v| { + Arc::new(LocalLspHttpCache::new(v.clone(), self.global.clone())) + }), + ) + }) + .collect(); } pub fn deno_dir(&self) -> &DenoDir { @@ -129,15 +138,50 @@ impl LspCache { &self.global } - pub fn root_vendor(&self) -> Option<&Arc<LocalLspHttpCache>> { - self.root_vendor.as_ref() - } - - pub fn root_vendor_or_global(&self) -> Arc<dyn HttpCache> { + pub fn for_specifier( + &self, + file_referrer: Option<&ModuleSpecifier>, + ) -> Arc<dyn HttpCache> { + let Some(file_referrer) = file_referrer else { + return self.global.clone(); + }; self - .root_vendor - .as_ref() - .map(|v| v.clone() as _) + .vendors_by_scope + .iter() + .rfind(|(s, _)| file_referrer.as_str().starts_with(s.as_str())) + .and_then(|(_, v)| v.clone().map(|v| v as _)) .unwrap_or(self.global.clone() as _) } + + pub fn vendored_specifier( + &self, + specifier: &ModuleSpecifier, + file_referrer: Option<&ModuleSpecifier>, + ) -> Option<ModuleSpecifier> { + let file_referrer = file_referrer?; + if !matches!(specifier.scheme(), "http" | "https") { + return None; + } + let vendor = self + .vendors_by_scope + .iter() + .rfind(|(s, _)| file_referrer.as_str().starts_with(s.as_str()))? + .1 + .as_ref()?; + vendor.get_file_url(specifier) + } + + pub fn unvendored_specifier( + &self, + specifier: &ModuleSpecifier, + ) -> Option<ModuleSpecifier> { + let path = specifier_to_file_path(specifier).ok()?; + let vendor = self + .vendors_by_scope + .iter() + .rfind(|(s, _)| specifier.as_str().starts_with(s.as_str()))? + .1 + .as_ref()?; + vendor.get_remote_url(&path) + } } |