diff options
Diffstat (limited to 'cli/lsp')
-rw-r--r-- | cli/lsp/client.rs | 7 | ||||
-rw-r--r-- | cli/lsp/diagnostics.rs | 38 | ||||
-rw-r--r-- | cli/lsp/documents.rs | 9 | ||||
-rw-r--r-- | cli/lsp/language_server.rs | 21 | ||||
-rw-r--r-- | cli/lsp/tsc.rs | 10 | ||||
-rw-r--r-- | cli/lsp/urls.rs | 33 |
6 files changed, 94 insertions, 24 deletions
diff --git a/cli/lsp/client.rs b/cli/lsp/client.rs index 5f1a7fcef..13347a772 100644 --- a/cli/lsp/client.rs +++ b/cli/lsp/client.rs @@ -154,11 +154,14 @@ impl OutsideLockClient { pub async fn publish_diagnostics( &self, - uri: lsp::Url, + uri: LspClientUrl, diags: Vec<lsp::Diagnostic>, version: Option<i32>, ) { - self.0.publish_diagnostics(uri, diags, version).await; + self + .0 + .publish_diagnostics(uri.into_url(), diags, version) + .await; } } diff --git a/cli/lsp/diagnostics.rs b/cli/lsp/diagnostics.rs index 7f65c0948..88c4c91cb 100644 --- a/cli/lsp/diagnostics.rs +++ b/cli/lsp/diagnostics.rs @@ -12,6 +12,8 @@ use super::language_server::StateSnapshot; use super::performance::Performance; use super::tsc; use super::tsc::TsServer; +use super::urls::LspClientUrl; +use super::urls::LspUrlMap; use crate::args::LintOptions; use crate::graph_util; @@ -54,6 +56,7 @@ pub struct DiagnosticServerUpdateMessage { pub snapshot: Arc<StateSnapshot>, pub config: Arc<ConfigSnapshot>, pub lint_options: LintOptions, + pub url_map: LspUrlMap, } struct DiagnosticRecord { @@ -107,6 +110,7 @@ impl DiagnosticsPublisher { &self, source: DiagnosticSource, diagnostics: DiagnosticVec, + url_map: &LspUrlMap, token: &CancellationToken, ) -> usize { let mut diagnostics_by_specifier = @@ -141,7 +145,9 @@ impl DiagnosticsPublisher { .client .when_outside_lsp_lock() .publish_diagnostics( - record.specifier, + url_map + .normalize_specifier(&record.specifier) + .unwrap_or(LspClientUrl::new(record.specifier)), all_specifier_diagnostics, version, ) @@ -169,7 +175,9 @@ impl DiagnosticsPublisher { .client .when_outside_lsp_lock() .publish_diagnostics( - specifier.clone(), + url_map + .normalize_specifier(specifier) + .unwrap_or_else(|_| LspClientUrl::new(specifier.clone())), Vec::new(), removed_value.version, ) @@ -366,9 +374,11 @@ impl DiagnosticsServer { snapshot, config, lint_options, + url_map, }, batch_index, } = message; + let url_map = Arc::new(url_map); // cancel the previous run token.cancel(); @@ -383,6 +393,7 @@ impl DiagnosticsServer { let ts_diagnostics_store = ts_diagnostics_store.clone(); let snapshot = snapshot.clone(); let config = config.clone(); + let url_map = url_map.clone(); async move { if let Some(previous_handle) = previous_ts_handle { // Wait on the previous run to complete in order to prevent @@ -419,7 +430,12 @@ impl DiagnosticsServer { if !token.is_cancelled() { ts_diagnostics_store.update(&diagnostics); messages_len = diagnostics_publisher - .publish(DiagnosticSource::Ts, diagnostics, &token) + .publish( + DiagnosticSource::Ts, + diagnostics, + &url_map, + &token, + ) .await; if !token.is_cancelled() { @@ -447,6 +463,7 @@ impl DiagnosticsServer { let token = token.clone(); let snapshot = snapshot.clone(); let config = config.clone(); + let url_map = url_map.clone(); async move { if let Some(previous_handle) = previous_deps_handle { previous_handle.await; @@ -463,7 +480,12 @@ impl DiagnosticsServer { let mut messages_len = 0; if !token.is_cancelled() { messages_len = diagnostics_publisher - .publish(DiagnosticSource::Deno, diagnostics, &token) + .publish( + DiagnosticSource::Deno, + diagnostics, + &url_map, + &token, + ) .await; if !token.is_cancelled() { @@ -491,6 +513,7 @@ impl DiagnosticsServer { let token = token.clone(); let snapshot = snapshot.clone(); let config = config.clone(); + let url_map = url_map.clone(); async move { if let Some(previous_handle) = previous_lint_handle { previous_handle.await; @@ -514,7 +537,12 @@ impl DiagnosticsServer { let mut messages_len = 0; if !token.is_cancelled() { messages_len = diagnostics_publisher - .publish(DiagnosticSource::Lint, diagnostics, &token) + .publish( + DiagnosticSource::Lint, + diagnostics, + &url_map, + &token, + ) .await; if !token.is_cancelled() { diff --git a/cli/lsp/documents.rs b/cli/lsp/documents.rs index c39c81a41..dbaecb95c 100644 --- a/cli/lsp/documents.rs +++ b/cli/lsp/documents.rs @@ -969,6 +969,13 @@ impl Documents { } } + pub fn resolve_redirected( + &self, + specifier: &ModuleSpecifier, + ) -> Option<ModuleSpecifier> { + self.specifier_resolver.resolve(specifier) + } + /// Return `true` if the specifier can be resolved to a document. pub fn exists(&self, specifier: &ModuleSpecifier) -> bool { let specifier = self.specifier_resolver.resolve(specifier); @@ -1498,7 +1505,7 @@ impl Documents { self.resolve_dependency(specifier, maybe_node_resolver) } else { let media_type = doc.media_type(); - Some((specifier.clone(), media_type)) + Some((doc.specifier().clone(), media_type)) } } diff --git a/cli/lsp/language_server.rs b/cli/lsp/language_server.rs index 4c3ee1013..06fefcaeb 100644 --- a/cli/lsp/language_server.rs +++ b/cli/lsp/language_server.rs @@ -88,7 +88,7 @@ use crate::cache::DenoDir; use crate::cache::FastInsecureHasher; use crate::cache::GlobalHttpCache; use crate::cache::HttpCache; -use crate::cache::LocalHttpCache; +use crate::cache::LocalLspHttpCache; use crate::factory::CliFactory; use crate::file_fetcher::FileFetcher; use crate::graph_util; @@ -204,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: Arc<urls::LspUrlMap>, + pub url_map: urls::LspUrlMap, } impl LanguageServer { @@ -905,16 +905,18 @@ impl Inner { self.module_registries_location = module_registries_location; // update the 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, - }; + let maybe_local_cache = + self.config.maybe_deno_modules_dir_path().map(|local_path| { + Arc::new(LocalLspHttpCache::new(local_path, global_cache.clone())) + }); + let cache: Arc<dyn HttpCache> = maybe_local_cache + .clone() + .map(|c| c as Arc<dyn HttpCache>) + .unwrap_or(global_cache); self.deps_http_cache = cache.clone(); self.documents.set_cache(cache.clone()); self.cache_metadata.set_cache(cache); + self.url_map.set_cache(maybe_local_cache); self.maybe_global_cache_path = new_cache_path; Ok(()) } @@ -2946,6 +2948,7 @@ impl Inner { snapshot: self.snapshot(), config: self.config.snapshot(), lint_options: self.lint_options.clone(), + url_map: self.url_map.clone(), }; if let Err(err) = self.diagnostics_server.update(snapshot) { error!("Cannot update diagnostics: {}", err); diff --git a/cli/lsp/tsc.rs b/cli/lsp/tsc.rs index b26fa57bc..353866513 100644 --- a/cli/lsp/tsc.rs +++ b/cli/lsp/tsc.rs @@ -3214,9 +3214,13 @@ fn op_script_names(state: &mut OpState) -> Vec<String> { .filter_map(|dep| dep.get_type().or_else(|| dep.get_code())), ); for specifier in specifiers { - if seen.insert(specifier.as_str()) && documents.exists(specifier) { - // only include dependencies we know to exist otherwise typescript will error - result.push(specifier.to_string()); + if seen.insert(specifier.as_str()) { + if let Some(specifier) = documents.resolve_redirected(specifier) { + // only include dependencies we know to exist otherwise typescript will error + if documents.exists(&specifier) { + result.push(specifier.to_string()); + } + } } } } diff --git a/cli/lsp/urls.rs b/cli/lsp/urls.rs index ee9684f64..8b16292e9 100644 --- a/cli/lsp/urls.rs +++ b/cli/lsp/urls.rs @@ -1,5 +1,6 @@ // Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. +use crate::cache::LocalLspHttpCache; use crate::file_fetcher::map_content_type; use data_url::DataUrl; @@ -12,6 +13,7 @@ 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. @@ -119,17 +121,31 @@ 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)] -pub struct LspUrlMap(Mutex<LspUrlMapInner>); +#[derive(Debug, Default, Clone)] +pub struct LspUrlMap { + local_http_cache: Option<Arc<LocalLspHttpCache>>, + inner: Arc<Mutex<LspUrlMapInner>>, +} impl LspUrlMap { + pub fn set_cache(&mut self, http_cache: Option<Arc<LocalLspHttpCache>>) { + self.local_http_cache = http_cache; + } + /// Normalize a specifier that is used internally within Deno (or tsc) to a /// URL that can be handled as a "virtual" document by an LSP client. pub fn normalize_specifier( &self, specifier: &ModuleSpecifier, ) -> Result<LspClientUrl, AnyError> { - let mut inner = self.0.lock(); + if let Some(cache) = &self.local_http_cache { + if matches!(specifier.scheme(), "http" | "https") { + if let Some(file_url) = cache.get_file_url(specifier) { + return Ok(LspClientUrl(file_url)); + } + } + } + let mut inner = self.inner.lock(); if let Some(url) = inner.get_url(specifier).cloned() { Ok(url) } else { @@ -183,7 +199,16 @@ impl LspUrlMap { /// so we need to force it to in the mapping and nee to explicitly state whether /// this is a file or directory url. pub fn normalize_url(&self, url: &Url, kind: LspUrlKind) -> ModuleSpecifier { - let mut inner = self.0.lock(); + if let Some(cache) = &self.local_http_cache { + if url.scheme() == "file" { + if let Ok(path) = url.to_file_path() { + if let Some(remote_url) = cache.get_remote_url(&path) { + return remote_url; + } + } + } + } + let mut inner = self.inner.lock(); if let Some(specifier) = inner.get_specifier(url).cloned() { specifier } else { |