diff options
Diffstat (limited to 'cli/lsp')
-rw-r--r-- | cli/lsp/config.rs | 21 | ||||
-rw-r--r-- | cli/lsp/jsr.rs | 18 | ||||
-rw-r--r-- | cli/lsp/language_server.rs | 23 | ||||
-rw-r--r-- | cli/lsp/npm.rs | 17 | ||||
-rw-r--r-- | cli/lsp/registries.rs | 181 | ||||
-rw-r--r-- | cli/lsp/resolver.rs | 12 |
6 files changed, 170 insertions, 102 deletions
diff --git a/cli/lsp/config.rs b/cli/lsp/config.rs index d3cdd2a94..449051931 100644 --- a/cli/lsp/config.rs +++ b/cli/lsp/config.rs @@ -1112,7 +1112,7 @@ impl ConfigData { scope: &ModuleSpecifier, parent: Option<(&ModuleSpecifier, &ConfigData)>, settings: &Settings, - file_fetcher: Option<&FileFetcher>, + file_fetcher: Option<&Arc<FileFetcher>>, ) -> Self { if let Some(specifier) = config_file_specifier { match ConfigFile::from_specifier( @@ -1167,7 +1167,7 @@ impl ConfigData { scope: &ModuleSpecifier, parent: Option<(&ModuleSpecifier, &ConfigData)>, settings: &Settings, - file_fetcher: Option<&FileFetcher>, + file_fetcher: Option<&Arc<FileFetcher>>, ) -> Self { let (settings, workspace_folder) = settings.get_for_specifier(scope); let mut watched_files = HashMap::with_capacity(6); @@ -1411,9 +1411,18 @@ impl ConfigData { } if import_map_value.is_none() { if let Some(file_fetcher) = file_fetcher { - let fetch_result = file_fetcher - .fetch(specifier, &PermissionsContainer::allow_all()) - .await; + // spawn due to the lsp's `Send` requirement + let fetch_result = deno_core::unsync::spawn({ + let file_fetcher = file_fetcher.clone(); + let specifier = specifier.clone(); + async move { + file_fetcher + .fetch(&specifier, &PermissionsContainer::allow_all()) + .await + } + }) + .await + .unwrap(); let value_result = fetch_result.and_then(|f| { serde_json::from_slice::<Value>(&f.source).map_err(|e| e.into()) }); @@ -1601,7 +1610,7 @@ impl ConfigTree { &mut self, settings: &Settings, workspace_files: &BTreeSet<ModuleSpecifier>, - file_fetcher: &FileFetcher, + file_fetcher: &Arc<FileFetcher>, ) { lsp_log!("Refreshing configuration tree..."); let mut scopes = BTreeMap::new(); diff --git a/cli/lsp/jsr.rs b/cli/lsp/jsr.rs index 75906f8ab..a7b2f46ac 100644 --- a/cli/lsp/jsr.rs +++ b/cli/lsp/jsr.rs @@ -17,7 +17,7 @@ use super::search::PackageSearchApi; #[derive(Debug)] pub struct CliJsrSearchApi { - file_fetcher: FileFetcher, + file_fetcher: Arc<FileFetcher>, resolver: JsrFetchResolver, search_cache: DashMap<String, Arc<Vec<String>>>, versions_cache: DashMap<String, Arc<Vec<Version>>>, @@ -25,7 +25,7 @@ pub struct CliJsrSearchApi { } impl CliJsrSearchApi { - pub fn new(file_fetcher: FileFetcher) -> Self { + pub fn new(file_fetcher: Arc<FileFetcher>) -> Self { let resolver = JsrFetchResolver::new(file_fetcher.clone()); Self { file_fetcher, @@ -56,11 +56,15 @@ impl PackageSearchApi for CliJsrSearchApi { } let mut search_url = jsr_api_url().join("packages")?; search_url.query_pairs_mut().append_pair("query", query); - let file = self - .file_fetcher - .fetch(&search_url, &PermissionsContainer::allow_all()) - .await? - .into_text_decoded()?; + let file_fetcher = self.file_fetcher.clone(); + // spawn due to the lsp's `Send` requirement + let file = deno_core::unsync::spawn(async move { + file_fetcher + .fetch(&search_url, &PermissionsContainer::allow_all()) + .await? + .into_text_decoded() + }) + .await??; let names = Arc::new(parse_jsr_search_response(&file.source)?); self.search_cache.insert(query.to_string(), names.clone()); Ok(names) diff --git a/cli/lsp/language_server.rs b/cli/lsp/language_server.rs index 45b691b3f..e362a9e7e 100644 --- a/cli/lsp/language_server.rs +++ b/cli/lsp/language_server.rs @@ -92,7 +92,7 @@ use crate::args::Flags; use crate::factory::CliFactory; use crate::file_fetcher::FileFetcher; use crate::graph_util; -use crate::http_util::HttpClient; +use crate::http_util::HttpClientProvider; use crate::lsp::config::ConfigWatchedFileType; use crate::lsp::logging::init_log_file; use crate::lsp::tsc::file_text_changes_to_workspace_edit; @@ -191,7 +191,7 @@ pub struct Inner { /// The collection of documents that the server is currently handling, either /// on disk or "open" within the client. pub documents: Documents, - http_client: Arc<HttpClient>, + http_client_provider: Arc<HttpClientProvider>, initial_cwd: PathBuf, jsr_search_api: CliJsrSearchApi, /// Handles module registries, which allow discovery of modules @@ -475,10 +475,10 @@ impl LanguageServer { impl Inner { fn new(client: Client) -> Self { let cache = LspCache::default(); - let http_client = Arc::new(HttpClient::new(None, None)); + let http_client_provider = Arc::new(HttpClientProvider::new(None, None)); let module_registry = ModuleRegistry::new( cache.deno_dir().registries_folder_path(), - http_client.clone(), + http_client_provider.clone(), ); let jsr_search_api = CliJsrSearchApi::new(module_registry.file_fetcher.clone()); @@ -508,7 +508,7 @@ impl Inner { diagnostics_state, diagnostics_server, documents, - http_client, + http_client_provider, initial_cwd: initial_cwd.clone(), jsr_search_api, project_version: 0, @@ -652,7 +652,7 @@ impl Inner { .unwrap_or_else(|_| RootCertStore::empty()); let root_cert_store_provider = Arc::new(LspRootCertStoreProvider(root_cert_store)); - self.http_client = Arc::new(HttpClient::new( + self.http_client_provider = Arc::new(HttpClientProvider::new( Some(root_cert_store_provider), workspace_settings .unsafely_ignore_certificate_errors @@ -660,7 +660,7 @@ impl Inner { )); self.module_registry = ModuleRegistry::new( deno_dir.registries_folder_path(), - self.http_client.clone(), + self.http_client_provider.clone(), ); let workspace_settings = self.config.workspace_settings(); for (registry, enabled) in workspace_settings.suggest.imports.hosts.iter() { @@ -939,11 +939,12 @@ impl Inner { self.cache.global().clone(), CacheSetting::RespectHeaders, true, - self.http_client.clone(), + self.http_client_provider.clone(), Default::default(), None, ); file_fetcher.set_download_log_level(super::logging::lsp_log_level()); + let file_fetcher = Arc::new(file_fetcher); self .config .tree @@ -983,7 +984,7 @@ impl Inner { LspResolver::from_config( &self.config, &self.cache, - Some(&self.http_client), + Some(&self.http_client_provider), ) .await, ); @@ -1108,7 +1109,7 @@ impl Inner { async fn refresh_npm_specifiers(&mut self) { let package_reqs = self.documents.npm_package_reqs(); let resolver = self.resolver.clone(); - // spawn to avoid the LSP's Send requirements + // spawn due to the lsp's `Send` requirement let handle = spawn(async move { resolver.set_npm_package_reqs(&package_reqs).await }); if let Err(err) = handle.await.unwrap() { @@ -2966,7 +2967,7 @@ impl tower_lsp::LanguageServer for LanguageServer { ); } - (inner.client.clone(), inner.http_client.clone()) + (inner.client.clone(), inner.http_client_provider.clone()) }; for registration in registrations { diff --git a/cli/lsp/npm.rs b/cli/lsp/npm.rs index 6cd6882b4..d051237fb 100644 --- a/cli/lsp/npm.rs +++ b/cli/lsp/npm.rs @@ -18,14 +18,14 @@ use super::search::PackageSearchApi; #[derive(Debug)] pub struct CliNpmSearchApi { - file_fetcher: FileFetcher, + file_fetcher: Arc<FileFetcher>, resolver: NpmFetchResolver, search_cache: DashMap<String, Arc<Vec<String>>>, versions_cache: DashMap<String, Arc<Vec<Version>>>, } impl CliNpmSearchApi { - pub fn new(file_fetcher: FileFetcher) -> Self { + pub fn new(file_fetcher: Arc<FileFetcher>) -> Self { let resolver = NpmFetchResolver::new(file_fetcher.clone()); Self { file_fetcher, @@ -52,11 +52,14 @@ impl PackageSearchApi for CliNpmSearchApi { search_url .query_pairs_mut() .append_pair("text", &format!("{} boost-exact:false", query)); - let file = self - .file_fetcher - .fetch(&search_url, &PermissionsContainer::allow_all()) - .await? - .into_text_decoded()?; + let file_fetcher = self.file_fetcher.clone(); + let file = deno_core::unsync::spawn(async move { + file_fetcher + .fetch(&search_url, &PermissionsContainer::allow_all()) + .await? + .into_text_decoded() + }) + .await??; let names = Arc::new(parse_npm_search_response(&file.source)?); self.search_cache.insert(query.to_string(), names.clone()); Ok(names) diff --git a/cli/lsp/registries.rs b/cli/lsp/registries.rs index a17cd1228..9a0ad6ddd 100644 --- a/cli/lsp/registries.rs +++ b/cli/lsp/registries.rs @@ -17,7 +17,7 @@ use crate::cache::GlobalHttpCache; use crate::cache::HttpCache; use crate::file_fetcher::FetchOptions; use crate::file_fetcher::FileFetcher; -use crate::http_util::HttpClient; +use crate::http_util::HttpClientProvider; use deno_core::anyhow::anyhow; use deno_core::error::AnyError; @@ -417,12 +417,15 @@ enum VariableItems { pub struct ModuleRegistry { origins: HashMap<String, Vec<RegistryConfiguration>>, pub location: PathBuf, - pub file_fetcher: FileFetcher, + pub file_fetcher: Arc<FileFetcher>, http_cache: Arc<GlobalHttpCache>, } impl ModuleRegistry { - pub fn new(location: PathBuf, http_client: Arc<HttpClient>) -> Self { + pub fn new( + location: PathBuf, + http_client_provider: Arc<HttpClientProvider>, + ) -> Self { // the http cache should always be the global one for registry completions let http_cache = Arc::new(GlobalHttpCache::new( location.clone(), @@ -432,7 +435,7 @@ impl ModuleRegistry { http_cache.clone(), CacheSetting::RespectHeaders, true, - http_client, + http_client_provider, Default::default(), None, ); @@ -441,7 +444,7 @@ impl ModuleRegistry { Self { origins: HashMap::new(), location, - file_fetcher, + file_fetcher: Arc::new(file_fetcher), http_cache, } } @@ -512,15 +515,21 @@ impl ModuleRegistry { &self, specifier: &ModuleSpecifier, ) -> Result<Vec<RegistryConfiguration>, AnyError> { - let fetch_result = self - .file_fetcher - .fetch_with_options(FetchOptions { - specifier, - permissions: &PermissionsContainer::allow_all(), - maybe_accept: Some("application/vnd.deno.reg.v2+json, application/vnd.deno.reg.v1+json;q=0.9, application/json;q=0.8"), - maybe_cache_setting: None, - }) - .await; + // spawn due to the lsp's `Send` requirement + let fetch_result = deno_core::unsync::spawn({ + let file_fetcher = self.file_fetcher.clone(); + let specifier = specifier.clone(); + async move { + file_fetcher + .fetch_with_options(FetchOptions { + specifier: &specifier, + permissions: &PermissionsContainer::allow_all(), + maybe_accept: Some("application/vnd.deno.reg.v2+json, application/vnd.deno.reg.v1+json;q=0.9, application/json;q=0.8"), + maybe_cache_setting: None, + }) + .await + } + }).await?; // if there is an error fetching, we will cache an empty file, so that // subsequent requests they are just an empty doc which will error without // needing to connect to the remote URL. We will cache it for 1 week. @@ -612,13 +621,20 @@ impl ModuleRegistry { None, ) .ok()?; - let file = self - .file_fetcher - .fetch(&endpoint, &PermissionsContainer::allow_all()) - .await - .ok()? - .into_text_decoded() - .ok()?; + let file_fetcher = self.file_fetcher.clone(); + // spawn due to the lsp's `Send` requirement + let file = deno_core::unsync::spawn({ + async move { + file_fetcher + .fetch(&endpoint, &PermissionsContainer::allow_all()) + .await + .ok()? + .into_text_decoded() + .ok() + } + }) + .await + .ok()??; let documentation: lsp::Documentation = serde_json::from_str(&file.source).ok()?; return match documentation { @@ -978,13 +994,18 @@ impl ModuleRegistry { url: &str, ) -> Option<lsp::Documentation> { let specifier = Url::parse(url).ok()?; - let file = self - .file_fetcher - .fetch(&specifier, &PermissionsContainer::allow_all()) - .await - .ok()? - .into_text_decoded() - .ok()?; + let file_fetcher = self.file_fetcher.clone(); + // spawn due to the lsp's `Send` requirement + let file = deno_core::unsync::spawn(async move { + file_fetcher + .fetch(&specifier, &PermissionsContainer::allow_all()) + .await + .ok()? + .into_text_decoded() + .ok() + }) + .await + .ok()??; serde_json::from_str(&file.source).ok() } @@ -1037,19 +1058,27 @@ impl ModuleRegistry { async fn get_items(&self, url: &str) -> Option<VariableItems> { let specifier = ModuleSpecifier::parse(url).ok()?; - let file = self - .file_fetcher - .fetch(&specifier, &PermissionsContainer::allow_all()) - .await - .map_err(|err| { - error!( - "Internal error fetching endpoint \"{}\". {}", - specifier, err - ); - }) - .ok()? - .into_text_decoded() - .ok()?; + // spawn due to the lsp's `Send` requirement + let file = deno_core::unsync::spawn({ + let file_fetcher = self.file_fetcher.clone(); + let specifier = specifier.clone(); + async move { + file_fetcher + .fetch(&specifier, &PermissionsContainer::allow_all()) + .await + .map_err(|err| { + error!( + "Internal error fetching endpoint \"{}\". {}", + specifier, err + ); + }) + .ok()? + .into_text_decoded() + .ok() + } + }) + .await + .ok()??; let items: VariableItems = serde_json::from_str(&file.source) .map_err(|err| { error!( @@ -1075,19 +1104,27 @@ impl ModuleRegistry { error!("Internal error mapping endpoint \"{}\". {}", url, err); }) .ok()?; - let file = self - .file_fetcher - .fetch(&specifier, &PermissionsContainer::allow_all()) - .await - .map_err(|err| { - error!( - "Internal error fetching endpoint \"{}\". {}", - specifier, err - ); - }) - .ok()? - .into_text_decoded() - .ok()?; + // spawn due to the lsp's `Send` requirement + let file = deno_core::unsync::spawn({ + let file_fetcher = self.file_fetcher.clone(); + let specifier = specifier.clone(); + async move { + file_fetcher + .fetch(&specifier, &PermissionsContainer::allow_all()) + .await + .map_err(|err| { + error!( + "Internal error fetching endpoint \"{}\". {}", + specifier, err + ); + }) + .ok()? + .into_text_decoded() + .ok() + } + }) + .await + .ok()??; let items: VariableItems = serde_json::from_str(&file.source) .map_err(|err| { error!( @@ -1264,8 +1301,10 @@ mod tests { let _g = test_util::http_server(); let temp_dir = TempDir::new(); let location = temp_dir.path().join("registries").to_path_buf(); - let mut module_registry = - ModuleRegistry::new(location, Arc::new(HttpClient::new(None, None))); + let mut module_registry = ModuleRegistry::new( + location, + Arc::new(HttpClientProvider::new(None, None)), + ); module_registry.enable("http://localhost:4545/").await; let range = lsp::Range { start: lsp::Position { @@ -1322,8 +1361,10 @@ mod tests { let _g = test_util::http_server(); let temp_dir = TempDir::new(); let location = temp_dir.path().join("registries").to_path_buf(); - let mut module_registry = - ModuleRegistry::new(location, Arc::new(HttpClient::new(None, None))); + let mut module_registry = ModuleRegistry::new( + location, + Arc::new(HttpClientProvider::new(None, None)), + ); module_registry.enable("http://localhost:4545/").await; let range = lsp::Range { start: lsp::Position { @@ -1542,8 +1583,10 @@ mod tests { let _g = test_util::http_server(); let temp_dir = TempDir::new(); let location = temp_dir.path().join("registries").to_path_buf(); - let mut module_registry = - ModuleRegistry::new(location, Arc::new(HttpClient::new(None, None))); + let mut module_registry = ModuleRegistry::new( + location, + Arc::new(HttpClientProvider::new(None, None)), + ); module_registry .enable_custom("http://localhost:4545/lsp/registries/deno-import-intellisense-key-first.json") .await @@ -1612,8 +1655,10 @@ mod tests { let _g = test_util::http_server(); let temp_dir = TempDir::new(); let location = temp_dir.path().join("registries").to_path_buf(); - let mut module_registry = - ModuleRegistry::new(location, Arc::new(HttpClient::new(None, None))); + let mut module_registry = ModuleRegistry::new( + location, + Arc::new(HttpClientProvider::new(None, None)), + ); module_registry .enable_custom("http://localhost:4545/lsp/registries/deno-import-intellisense-complex.json") .await @@ -1663,8 +1708,10 @@ mod tests { let _g = test_util::http_server(); let temp_dir = TempDir::new(); let location = temp_dir.path().join("registries").to_path_buf(); - let module_registry = - ModuleRegistry::new(location, Arc::new(HttpClient::new(None, None))); + let module_registry = ModuleRegistry::new( + location, + Arc::new(HttpClientProvider::new(None, None)), + ); let result = module_registry.check_origin("http://localhost:4545").await; assert!(result.is_ok()); } @@ -1674,8 +1721,10 @@ mod tests { let _g = test_util::http_server(); let temp_dir = TempDir::new(); let location = temp_dir.path().join("registries").to_path_buf(); - let module_registry = - ModuleRegistry::new(location, Arc::new(HttpClient::new(None, None))); + let module_registry = ModuleRegistry::new( + location, + Arc::new(HttpClientProvider::new(None, None)), + ); let result = module_registry.check_origin("https://example.com").await; assert!(result.is_err()); let err = result.unwrap_err().to_string(); diff --git a/cli/lsp/resolver.rs b/cli/lsp/resolver.rs index 5c6708c79..599db4876 100644 --- a/cli/lsp/resolver.rs +++ b/cli/lsp/resolver.rs @@ -4,7 +4,7 @@ use crate::args::create_default_npmrc; use crate::args::package_json; use crate::args::CacheSetting; use crate::graph_util::CliJsrUrlProvider; -use crate::http_util::HttpClient; +use crate::http_util::HttpClientProvider; use crate::jsr::JsrCacheResolver; use crate::lsp::config::Config; use crate::lsp::config::ConfigData; @@ -82,12 +82,14 @@ impl LspResolver { pub async fn from_config( config: &Config, cache: &LspCache, - http_client: Option<&Arc<HttpClient>>, + http_client_provider: Option<&Arc<HttpClientProvider>>, ) -> Self { let config_data = config.tree.root_data(); let mut npm_resolver = None; let mut node_resolver = None; - if let (Some(http_client), Some(config_data)) = (http_client, config_data) { + if let (Some(http_client), Some(config_data)) = + (http_client_provider, config_data) + { npm_resolver = create_npm_resolver(config_data, cache, http_client).await; node_resolver = create_node_resolver(npm_resolver.as_ref()); } @@ -313,7 +315,7 @@ impl LspResolver { async fn create_npm_resolver( config_data: &ConfigData, cache: &LspCache, - http_client: &Arc<HttpClient>, + http_client_provider: &Arc<HttpClientProvider>, ) -> Option<Arc<dyn CliNpmResolver>> { let node_modules_dir = config_data .node_modules_dir @@ -326,7 +328,7 @@ async fn create_npm_resolver( }) } else { CliNpmResolverCreateOptions::Managed(CliNpmResolverManagedCreateOptions { - http_client: http_client.clone(), + http_client_provider: http_client_provider.clone(), snapshot: match config_data.lockfile.as_ref() { Some(lockfile) => { CliNpmResolverManagedSnapshotOption::ResolveFromLockfile( |