summaryrefslogtreecommitdiff
path: root/cli/lsp
diff options
context:
space:
mode:
Diffstat (limited to 'cli/lsp')
-rw-r--r--cli/lsp/config.rs21
-rw-r--r--cli/lsp/jsr.rs18
-rw-r--r--cli/lsp/language_server.rs23
-rw-r--r--cli/lsp/npm.rs17
-rw-r--r--cli/lsp/registries.rs181
-rw-r--r--cli/lsp/resolver.rs12
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(