diff options
Diffstat (limited to 'cli/lsp')
-rw-r--r-- | cli/lsp/cache.rs | 22 | ||||
-rw-r--r-- | cli/lsp/completions.rs | 5 | ||||
-rw-r--r-- | cli/lsp/config.rs | 6 | ||||
-rw-r--r-- | cli/lsp/diagnostics.rs | 12 | ||||
-rw-r--r-- | cli/lsp/documents.rs | 32 | ||||
-rw-r--r-- | cli/lsp/language_server.rs | 59 | ||||
-rw-r--r-- | cli/lsp/registries.rs | 13 | ||||
-rw-r--r-- | cli/lsp/tsc.rs | 16 | ||||
-rw-r--r-- | cli/lsp/urls.rs | 5 |
9 files changed, 102 insertions, 68 deletions
diff --git a/cli/lsp/cache.rs b/cli/lsp/cache.rs index e14497156..15b909672 100644 --- a/cli/lsp/cache.rs +++ b/cli/lsp/cache.rs @@ -8,12 +8,11 @@ use deno_core::ModuleSpecifier; use std::collections::HashMap; use std::fs; use std::path::Path; -use std::path::PathBuf; use std::sync::Arc; use std::time::SystemTime; pub fn calculate_fs_version( - cache: &HttpCache, + cache: &Arc<dyn HttpCache>, specifier: &ModuleSpecifier, ) -> Option<String> { match specifier.scheme() { @@ -40,10 +39,13 @@ pub fn calculate_fs_version_at_path(path: &Path) -> Option<String> { } fn calculate_fs_version_in_cache( - cache: &HttpCache, + cache: &Arc<dyn HttpCache>, specifier: &ModuleSpecifier, ) -> Option<String> { - match cache.get_modified_time(specifier) { + let Ok(cache_key) = cache.cache_item_key(specifier) else { + return Some("1".to_string()); + }; + match cache.read_modified_time(&cache_key) { Ok(Some(modified)) => { match modified.duration_since(SystemTime::UNIX_EPOCH) { Ok(n) => Some(n.as_millis().to_string()), @@ -80,12 +82,12 @@ struct Metadata { #[derive(Debug, Clone)] pub struct CacheMetadata { - cache: HttpCache, + cache: Arc<dyn HttpCache>, metadata: Arc<Mutex<HashMap<ModuleSpecifier, Metadata>>>, } impl CacheMetadata { - pub fn new(cache: HttpCache) -> Self { + pub fn new(cache: Arc<dyn HttpCache>) -> Self { Self { cache, metadata: Default::default(), @@ -120,8 +122,8 @@ impl CacheMetadata { ) { return None; } - let specifier_metadata = - self.cache.get(specifier).ok()?.read_metadata().ok()??; + let cache_key = self.cache.cache_item_key(specifier).ok()?; + let specifier_metadata = self.cache.read_metadata(&cache_key).ok()??; let values = Arc::new(parse_metadata(&specifier_metadata.headers)); let version = calculate_fs_version_in_cache(&self.cache, specifier); let mut metadata_map = self.metadata.lock(); @@ -130,8 +132,8 @@ impl CacheMetadata { Some(metadata) } - pub fn set_location(&mut self, location: PathBuf) { - self.cache = HttpCache::new(location); + pub fn set_cache(&mut self, cache: Arc<dyn HttpCache>) { + self.cache = cache; self.metadata.lock().clear(); } } diff --git a/cli/lsp/completions.rs b/cli/lsp/completions.rs index 73ec5a918..a895239a6 100644 --- a/cli/lsp/completions.rs +++ b/cli/lsp/completions.rs @@ -505,6 +505,7 @@ fn get_workspace_completions( #[cfg(test)] mod tests { use super::*; + use crate::cache::GlobalHttpCache; use crate::cache::HttpCache; use crate::lsp::documents::Documents; use crate::lsp::documents::LanguageId; @@ -519,14 +520,14 @@ mod tests { source_fixtures: &[(&str, &str)], location: &Path, ) -> Documents { - let cache = HttpCache::new(location.to_path_buf()); + let cache = Arc::new(GlobalHttpCache::new(location.to_path_buf())); let mut documents = Documents::new(cache); for (specifier, source, version, language_id) in fixtures { let specifier = resolve_url(specifier).expect("failed to create specifier"); documents.open(specifier, *version, *language_id, (*source).into()); } - let http_cache = HttpCache::new(location.to_path_buf()); + let http_cache = GlobalHttpCache::new(location.to_path_buf()); for (specifier, source) in source_fixtures { let specifier = resolve_url(specifier).expect("failed to create specifier"); diff --git a/cli/lsp/config.rs b/cli/lsp/config.rs index 2438e8a85..b84f63edc 100644 --- a/cli/lsp/config.rs +++ b/cli/lsp/config.rs @@ -475,6 +475,12 @@ impl Config { .and_then(|p| p.maybe_node_modules_dir.as_ref()) } + pub fn maybe_deno_modules_dir_path(&self) -> Option<PathBuf> { + self + .maybe_config_file() + .and_then(|c| c.deno_modules_dir_path()) + } + pub fn maybe_config_file(&self) -> Option<&ConfigFile> { self .maybe_config_file_info diff --git a/cli/lsp/diagnostics.rs b/cli/lsp/diagnostics.rs index ea2c4e12c..7f65c0948 100644 --- a/cli/lsp/diagnostics.rs +++ b/cli/lsp/diagnostics.rs @@ -1302,7 +1302,7 @@ fn generate_deno_diagnostics( #[cfg(test)] mod tests { use super::*; - use crate::cache::HttpCache; + use crate::cache::GlobalHttpCache; use crate::lsp::config::ConfigSnapshot; use crate::lsp::config::Settings; use crate::lsp::config::SpecifierSettings; @@ -1321,7 +1321,7 @@ mod tests { location: &Path, maybe_import_map: Option<(&str, &str)>, ) -> StateSnapshot { - let cache = HttpCache::new(location.to_path_buf()); + let cache = Arc::new(GlobalHttpCache::new(location.to_path_buf())); let mut documents = Documents::new(cache); for (specifier, source, version, language_id) in fixtures { let specifier = @@ -1345,8 +1345,8 @@ mod tests { documents, maybe_import_map, assets: Default::default(), - cache_metadata: cache::CacheMetadata::new(HttpCache::new( - location.to_path_buf(), + cache_metadata: cache::CacheMetadata::new(Arc::new( + GlobalHttpCache::new(location.to_path_buf()), )), maybe_node_resolver: None, maybe_npm_resolver: None, @@ -1396,7 +1396,7 @@ let c: number = "a"; None, ); let snapshot = Arc::new(snapshot); - let cache = HttpCache::new(cache_location); + let cache = Arc::new(GlobalHttpCache::new(cache_location)); let ts_server = TsServer::new(Default::default(), cache); // test enabled @@ -1489,7 +1489,7 @@ let c: number = "a"; None, ); let snapshot = Arc::new(snapshot); - let cache = HttpCache::new(cache_location); + let cache = Arc::new(GlobalHttpCache::new(cache_location)); let ts_server = TsServer::new(Default::default(), cache); let config = mock_config(); diff --git a/cli/lsp/documents.rs b/cli/lsp/documents.rs index 2d3bed57a..c39c81a41 100644 --- a/cli/lsp/documents.rs +++ b/cli/lsp/documents.rs @@ -658,12 +658,12 @@ fn recurse_dependents( #[derive(Debug)] struct SpecifierResolver { - cache: HttpCache, + cache: Arc<dyn HttpCache>, redirects: Mutex<HashMap<ModuleSpecifier, ModuleSpecifier>>, } impl SpecifierResolver { - pub fn new(cache: HttpCache) -> Self { + pub fn new(cache: Arc<dyn HttpCache>) -> Self { Self { cache, redirects: Mutex::new(HashMap::new()), @@ -699,11 +699,12 @@ impl SpecifierResolver { redirect_limit: usize, ) -> Option<ModuleSpecifier> { if redirect_limit > 0 { + let cache_key = self.cache.cache_item_key(specifier).ok()?; let headers = self .cache - .get(specifier) + .read_metadata(&cache_key) .ok() - .and_then(|i| i.read_metadata().ok()?) + .flatten() .map(|m| m.headers)?; if let Some(location) = headers.get("location") { let redirect = @@ -727,7 +728,7 @@ struct FileSystemDocuments { impl FileSystemDocuments { pub fn get( &mut self, - cache: &HttpCache, + cache: &Arc<dyn HttpCache>, resolver: &dyn deno_graph::source::Resolver, specifier: &ModuleSpecifier, ) -> Option<Document> { @@ -749,7 +750,7 @@ impl FileSystemDocuments { /// returning the document. fn refresh_document( &mut self, - cache: &HttpCache, + cache: &Arc<dyn HttpCache>, resolver: &dyn deno_graph::source::Resolver, specifier: &ModuleSpecifier, ) -> Option<Document> { @@ -778,9 +779,9 @@ impl FileSystemDocuments { ) } else { let fs_version = calculate_fs_version(cache, specifier)?; - let cache_item = cache.get(specifier).ok()?; - let bytes = cache_item.read_to_bytes().ok()??; - let specifier_metadata = cache_item.read_metadata().ok()??; + let cache_key = cache.cache_item_key(specifier).ok()?; + let bytes = cache.read_file_bytes(&cache_key).ok()??; + let specifier_metadata = cache.read_metadata(&cache_key).ok()??; let maybe_content_type = specifier_metadata.headers.get("content-type"); let (_, maybe_charset) = map_content_type(specifier, maybe_content_type); let maybe_headers = Some(specifier_metadata.headers); @@ -823,7 +824,7 @@ pub enum DocumentsFilter { #[derive(Debug, Clone)] pub struct Documents { /// The DENO_DIR that the documents looks for non-file based modules. - cache: HttpCache, + cache: Arc<dyn HttpCache>, /// A flag that indicates that stated data is potentially invalid and needs to /// be recalculated before being considered valid. dirty: bool, @@ -853,7 +854,7 @@ pub struct Documents { } impl Documents { - pub fn new(cache: HttpCache) -> Self { + pub fn new(cache: Arc<dyn HttpCache>) -> Self { Self { cache: cache.clone(), dirty: true, @@ -1139,9 +1140,8 @@ impl Documents { } /// Update the location of the on disk cache for the document store. - pub fn set_location(&mut self, location: PathBuf) { + pub fn set_cache(&mut self, cache: Arc<dyn HttpCache>) { // TODO update resolved dependencies? - let cache = HttpCache::new(location); self.cache = cache.clone(); self.specifier_resolver = Arc::new(SpecifierResolver::new(cache)); self.dirty = true; @@ -1177,6 +1177,7 @@ impl Documents { document_preload_limit: usize, maybe_import_map: Option<&import_map::ImportMap>, maybe_jsx_config: Option<&JsxImportSourceConfig>, + maybe_deno_modules_dir: Option<bool>, maybe_package_json_deps: Option<&PackageJsonDeps>, ) -> u64 { let mut hasher = FastInsecureHasher::default(); @@ -1191,6 +1192,7 @@ impl Documents { hasher.write_str(&import_map.to_json()); hasher.write_str(import_map.base_url().as_str()); } + hasher.write_hashable(maybe_deno_modules_dir); hasher.write_hashable(maybe_jsx_config); if let Some(package_json_deps) = &maybe_package_json_deps { // We need to ensure the hashing is deterministic so explicitly type @@ -1225,6 +1227,7 @@ impl Documents { options.document_preload_limit, options.maybe_import_map.as_deref(), maybe_jsx_config.as_ref(), + options.maybe_config_file.and_then(|c| c.deno_modules_dir()), maybe_package_json_deps.as_ref(), ); let deps_provider = @@ -1840,6 +1843,7 @@ fn sort_and_remove_non_leaf_dirs(mut dirs: Vec<PathBuf>) -> Vec<PathBuf> { #[cfg(test)] mod tests { + use crate::cache::GlobalHttpCache; use crate::npm::NpmResolution; use super::*; @@ -1850,7 +1854,7 @@ mod tests { fn setup(temp_dir: &TempDir) -> (Documents, PathRef) { let location = temp_dir.path().join("deps"); - let cache = HttpCache::new(location.to_path_buf()); + let cache = Arc::new(GlobalHttpCache::new(location.to_path_buf())); let documents = Documents::new(cache); (documents, location) } diff --git a/cli/lsp/language_server.rs b/cli/lsp/language_server.rs index 2fef8cfa0..a6f686ed2 100644 --- a/cli/lsp/language_server.rs +++ b/cli/lsp/language_server.rs @@ -86,7 +86,9 @@ use crate::args::LintOptions; use crate::args::TsConfig; use crate::cache::DenoDir; use crate::cache::FastInsecureHasher; +use crate::cache::GlobalHttpCache; use crate::cache::HttpCache; +use crate::cache::LocalHttpCache; use crate::factory::CliFactory; use crate::file_fetcher::FileFetcher; use crate::graph_util; @@ -134,7 +136,7 @@ impl LspNpmConfigHash { pub fn from_inner(inner: &Inner) -> Self { let mut hasher = FastInsecureHasher::new(); hasher.write_hashable(inner.config.maybe_node_modules_dir_path()); - hasher.write_hashable(&inner.maybe_cache_path); + hasher.write_hashable(&inner.maybe_global_cache_path); if let Some(lockfile) = inner.config.maybe_lockfile() { hasher.write_hashable(&*lockfile.lock()); } @@ -168,7 +170,7 @@ pub struct Inner { pub client: Client, /// Configuration information. pub config: Config, - deps_http_cache: HttpCache, + deps_http_cache: Arc<dyn HttpCache>, diagnostics_server: diagnostics::DiagnosticsServer, /// The collection of documents that the server is currently handling, either /// on disk or "open" within the client. @@ -180,7 +182,7 @@ pub struct Inner { module_registries_location: PathBuf, /// An optional path to the DENO_DIR which has been specified in the client /// options. - maybe_cache_path: Option<PathBuf>, + maybe_global_cache_path: Option<PathBuf>, /// An optional import map which is used to resolve modules. maybe_import_map: Option<Arc<ImportMap>>, /// The URL for the import map which is used to determine relative imports. @@ -202,7 +204,7 @@ pub struct Inner { /// An abstraction that handles interactions with TypeScript. pub ts_server: Arc<TsServer>, /// A map of specifiers and URLs used to translate over the LSP. - pub url_map: urls::LspUrlMap, + pub url_map: Arc<urls::LspUrlMap>, } impl LanguageServer { @@ -553,7 +555,7 @@ impl Inner { http_client.clone(), ); let location = dir.deps_folder_path(); - let deps_http_cache = HttpCache::new(location); + let deps_http_cache = Arc::new(GlobalHttpCache::new(location)); let documents = Documents::new(deps_http_cache.clone()); let cache_metadata = cache::CacheMetadata::new(deps_http_cache.clone()); let performance = Arc::new(Performance::default()); @@ -593,7 +595,7 @@ impl Inner { diagnostics_server, documents, http_client, - maybe_cache_path: None, + maybe_global_cache_path: None, maybe_import_map: None, maybe_import_map_uri: None, maybe_package_json: None, @@ -829,8 +831,8 @@ impl Inner { let mark = self.performance.mark("update_cache", None::<()>); self.performance.measure(mark); let maybe_cache = &self.config.workspace_settings().cache; - let maybe_cache_path = if let Some(cache_str) = maybe_cache { - lsp_log!("Setting cache path from: \"{}\"", cache_str); + let maybe_global_cache_path = if let Some(cache_str) = maybe_cache { + lsp_log!("Setting global cache path from: \"{}\"", cache_str); let cache_url = if let Ok(url) = Url::from_file_path(cache_str) { Ok(url) } else if let Some(root_uri) = &self.config.root_uri { @@ -847,24 +849,32 @@ impl Inner { }?; let cache_path = specifier_to_file_path(&cache_url)?; lsp_log!( - " Resolved cache path: \"{}\"", + " Resolved global cache path: \"{}\"", cache_path.to_string_lossy() ); Some(cache_path) } else { None }; - if self.maybe_cache_path != maybe_cache_path { + if self.maybe_global_cache_path != maybe_global_cache_path { self - .recreate_http_client_and_dependents(maybe_cache_path) + .set_new_global_cache_path(maybe_global_cache_path) .await?; } Ok(()) } - /// Recreates the http client and all dependent structs. async fn recreate_http_client_and_dependents( &mut self, + ) -> Result<(), AnyError> { + self + .set_new_global_cache_path(self.maybe_global_cache_path.clone()) + .await + } + + /// Recreates the http client and all dependent structs. + async fn set_new_global_cache_path( + &mut self, new_cache_path: Option<PathBuf>, ) -> Result<(), AnyError> { let dir = DenoDir::new(new_cache_path.clone())?; @@ -894,15 +904,23 @@ impl Inner { ); self.module_registries_location = module_registries_location; // update the cache path - let location = dir.deps_folder_path(); - self.documents.set_location(location.clone()); - self.cache_metadata.set_location(location); - self.maybe_cache_path = new_cache_path; + let global_cache = Arc::new(GlobalHttpCache::new(dir.deps_folder_path())); + let cache: Arc<dyn HttpCache> = + match self.config.maybe_deno_modules_dir_path() { + Some(local_path) => { + Arc::new(LocalHttpCache::new(local_path, global_cache)) + } + None => global_cache, + }; + self.deps_http_cache = cache.clone(); + self.documents.set_cache(cache.clone()); + self.cache_metadata.set_cache(cache); + self.maybe_global_cache_path = new_cache_path; Ok(()) } async fn recreate_npm_services_if_necessary(&mut self) { - let deno_dir = match DenoDir::new(self.maybe_cache_path.clone()) { + let deno_dir = match DenoDir::new(self.maybe_global_cache_path.clone()) { Ok(deno_dir) => deno_dir, Err(err) => { lsp_warn!("Error getting deno dir: {}", err); @@ -1090,9 +1108,7 @@ impl Inner { async fn update_registries(&mut self) -> Result<(), AnyError> { let mark = self.performance.mark("update_registries", None::<()>); - self - .recreate_http_client_and_dependents(self.maybe_cache_path.clone()) - .await?; + self.recreate_http_client_and_dependents().await?; let workspace_settings = self.config.workspace_settings(); for (registry, enabled) in workspace_settings.suggest.imports.hosts.iter() { if *enabled { @@ -1131,6 +1147,7 @@ impl Inner { self.config.set_config_file(config_file); self.lint_options = lint_options; self.fmt_options = fmt_options; + self.recreate_http_client_and_dependents().await?; } Ok(()) @@ -3372,7 +3389,7 @@ impl Inner { let workspace_settings = self.config.workspace_settings(); let mut cli_options = CliOptions::new( Flags { - cache_path: self.maybe_cache_path.clone(), + cache_path: self.maybe_global_cache_path.clone(), ca_stores: workspace_settings.certificate_stores.clone(), ca_data: workspace_settings.tls_certificate.clone().map(CaData::File), unsafely_ignore_certificate_errors: workspace_settings diff --git a/cli/lsp/registries.rs b/cli/lsp/registries.rs index 9586997c5..0219653bd 100644 --- a/cli/lsp/registries.rs +++ b/cli/lsp/registries.rs @@ -13,6 +13,7 @@ use super::path_to_regex::StringOrVec; use super::path_to_regex::Token; use crate::args::CacheSetting; +use crate::cache::GlobalHttpCache; use crate::cache::HttpCache; use crate::file_fetcher::FileFetcher; use crate::http_util::HttpClient; @@ -415,13 +416,15 @@ enum VariableItems { pub struct ModuleRegistry { origins: HashMap<String, Vec<RegistryConfiguration>>, file_fetcher: FileFetcher, + http_cache: Arc<GlobalHttpCache>, } impl ModuleRegistry { pub fn new(location: PathBuf, http_client: Arc<HttpClient>) -> Self { - let http_cache = HttpCache::new(location); + // the http cache should always be the global one for registry completions + let http_cache = Arc::new(GlobalHttpCache::new(location)); let mut file_fetcher = FileFetcher::new( - http_cache, + http_cache.clone(), CacheSetting::RespectHeaders, true, http_client, @@ -433,6 +436,7 @@ impl ModuleRegistry { Self { origins: HashMap::new(), file_fetcher, + http_cache, } } @@ -517,10 +521,7 @@ impl ModuleRegistry { "cache-control".to_string(), "max-age=604800, immutable".to_string(), ); - self - .file_fetcher - .http_cache - .set(specifier, headers_map, &[])?; + self.http_cache.set(specifier, headers_map, &[])?; } let file = fetch_result?; let config: RegistryConfigurationJson = serde_json::from_str(&file.source)?; diff --git a/cli/lsp/tsc.rs b/cli/lsp/tsc.rs index 662b48061..b26fa57bc 100644 --- a/cli/lsp/tsc.rs +++ b/cli/lsp/tsc.rs @@ -99,7 +99,7 @@ type Request = ( pub struct TsServer(mpsc::UnboundedSender<Request>); impl TsServer { - pub fn new(performance: Arc<Performance>, cache: HttpCache) -> Self { + pub fn new(performance: Arc<Performance>, cache: Arc<dyn HttpCache>) -> Self { let (tx, mut rx) = mpsc::unbounded_channel::<Request>(); let _join_handle = thread::spawn(move || { let mut ts_runtime = js_runtime(performance, cache); @@ -3245,7 +3245,10 @@ fn op_script_version( /// Create and setup a JsRuntime based on a snapshot. It is expected that the /// supplied snapshot is an isolate that contains the TypeScript language /// server. -fn js_runtime(performance: Arc<Performance>, cache: HttpCache) -> JsRuntime { +fn js_runtime( + performance: Arc<Performance>, + cache: Arc<dyn HttpCache>, +) -> JsRuntime { JsRuntime::new(RuntimeOptions { extensions: vec![deno_tsc::init_ops(performance, cache)], startup_snapshot: Some(tsc::compiler_snapshot()), @@ -3265,7 +3268,7 @@ deno_core::extension!(deno_tsc, ], options = { performance: Arc<Performance>, - cache: HttpCache, + cache: Arc<dyn HttpCache>, }, state = |state, options| { state.put(State::new( @@ -3906,6 +3909,7 @@ fn request( #[cfg(test)] mod tests { use super::*; + use crate::cache::GlobalHttpCache; use crate::cache::HttpCache; use crate::http_util::HeadersMap; use crate::lsp::cache::CacheMetadata; @@ -3923,7 +3927,7 @@ mod tests { fixtures: &[(&str, &str, i32, LanguageId)], location: &Path, ) -> StateSnapshot { - let cache = HttpCache::new(location.to_path_buf()); + let cache = Arc::new(GlobalHttpCache::new(location.to_path_buf())); let mut documents = Documents::new(cache.clone()); for (specifier, source, version, language_id) in fixtures { let specifier = @@ -3952,7 +3956,7 @@ mod tests { sources: &[(&str, &str, i32, LanguageId)], ) -> (JsRuntime, Arc<StateSnapshot>, PathBuf) { let location = temp_dir.path().join("deps").to_path_buf(); - let cache = HttpCache::new(location.clone()); + let cache = Arc::new(GlobalHttpCache::new(location.clone())); let state_snapshot = Arc::new(mock_state_snapshot(sources, &location)); let mut runtime = js_runtime(Default::default(), cache); start(&mut runtime, debug).unwrap(); @@ -4432,7 +4436,7 @@ mod tests { LanguageId::TypeScript, )], ); - let cache = HttpCache::new(location); + let cache = Arc::new(GlobalHttpCache::new(location)); let specifier_dep = resolve_url("https://deno.land/x/example/a.ts").unwrap(); cache diff --git a/cli/lsp/urls.rs b/cli/lsp/urls.rs index dee89c977..ee9684f64 100644 --- a/cli/lsp/urls.rs +++ b/cli/lsp/urls.rs @@ -12,7 +12,6 @@ use deno_core::url::Url; use deno_core::ModuleSpecifier; use once_cell::sync::Lazy; use std::collections::HashMap; -use std::sync::Arc; /// Used in situations where a default URL needs to be used where otherwise a /// panic is undesired. @@ -120,8 +119,8 @@ pub enum LspUrlKind { /// A bi-directional map of URLs sent to the LSP client and internal module /// specifiers. We need to map internal specifiers into `deno:` schema URLs /// to allow the Deno language server to manage these as virtual documents. -#[derive(Debug, Default, Clone)] -pub struct LspUrlMap(Arc<Mutex<LspUrlMapInner>>); +#[derive(Debug, Default)] +pub struct LspUrlMap(Mutex<LspUrlMapInner>); impl LspUrlMap { /// Normalize a specifier that is used internally within Deno (or tsc) to a |