diff options
Diffstat (limited to 'cli/lsp')
-rw-r--r-- | cli/lsp/diagnostics.rs | 1 | ||||
-rw-r--r-- | cli/lsp/language_server.rs | 45 | ||||
-rw-r--r-- | cli/lsp/tsc.rs | 57 |
3 files changed, 97 insertions, 6 deletions
diff --git a/cli/lsp/diagnostics.rs b/cli/lsp/diagnostics.rs index b5f079b04..13bb04ac3 100644 --- a/cli/lsp/diagnostics.rs +++ b/cli/lsp/diagnostics.rs @@ -514,6 +514,7 @@ impl DiagnosticsServer { "Error generating TypeScript diagnostics: {}", err ); + token.cancel(); } }) .unwrap_or_default(); diff --git a/cli/lsp/language_server.rs b/cli/lsp/language_server.rs index 17c8cc5ba..2e1386fd0 100644 --- a/cli/lsp/language_server.rs +++ b/cli/lsp/language_server.rs @@ -84,6 +84,7 @@ use super::text; use super::tsc; use super::tsc::Assets; use super::tsc::AssetsSnapshot; +use super::tsc::ChangeKind; use super::tsc::GetCompletionDetailsArgs; use super::tsc::TsServer; use super::urls; @@ -1183,13 +1184,23 @@ impl Inner { // refresh the npm specifiers because it might have discovered // a @types/node package and now's a good time to do that anyway self.refresh_npm_specifiers().await; + + self + .ts_server + .project_changed( + self.snapshot(), + &[], + self.documents.project_version(), + true, + ) + .await; } fn shutdown(&self) -> LspResult<()> { Ok(()) } - fn did_open( + async fn did_open( &mut self, specifier: &ModuleSpecifier, params: DidOpenTextDocumentParams, @@ -1217,6 +1228,16 @@ impl Inner { params.text_document.language_id.parse().unwrap(), params.text_document.text.into(), ); + let version = self.documents.project_version(); + self + .ts_server + .project_changed( + self.snapshot(), + &[(document.specifier(), ChangeKind::Opened)], + version, + false, + ) + .await; self.performance.measure(mark); document @@ -1234,6 +1255,16 @@ impl Inner { ) { Ok(document) => { if document.is_diagnosable() { + let version = self.documents.project_version(); + self + .ts_server + .project_changed( + self.snapshot(), + &[(document.specifier(), ChangeKind::Modified)], + version, + false, + ) + .await; self.refresh_npm_specifiers().await; self.diagnostics_server.invalidate(&[specifier]); self.send_diagnostics_update(); @@ -1284,6 +1315,16 @@ impl Inner { if let Err(err) = self.documents.close(&specifier) { error!("{:#}", err); } + let version = self.documents.project_version(); + self + .ts_server + .project_changed( + self.snapshot(), + &[(&specifier, ChangeKind::Closed)], + version, + false, + ) + .await; self.performance.measure(mark); } @@ -3174,7 +3215,7 @@ impl tower_lsp::LanguageServer for LanguageServer { let specifier = inner .url_map .normalize_url(¶ms.text_document.uri, LspUrlKind::File); - let document = inner.did_open(&specifier, params); + let document = inner.did_open(&specifier, params).await; if document.is_diagnosable() { inner.refresh_npm_specifiers().await; inner.diagnostics_server.invalidate(&[specifier]); diff --git a/cli/lsp/tsc.rs b/cli/lsp/tsc.rs index 923a0d443..53a35c484 100644 --- a/cli/lsp/tsc.rs +++ b/cli/lsp/tsc.rs @@ -237,6 +237,23 @@ impl std::fmt::Debug for TsServer { } } +#[derive(Debug, Clone, Copy)] +#[repr(u8)] +pub enum ChangeKind { + Opened = 0, + Modified = 1, + Closed = 2, +} + +impl Serialize for ChangeKind { + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where + S: serde::Serializer, + { + serializer.serialize_i32(*self as i32) + } +} + impl TsServer { pub fn new(performance: Arc<Performance>, cache: Arc<dyn HttpCache>) -> Self { let (tx, request_rx) = mpsc::unbounded_channel::<Request>(); @@ -279,6 +296,27 @@ impl TsServer { }); } + pub async fn project_changed( + &self, + snapshot: Arc<StateSnapshot>, + modified_scripts: &[(&ModuleSpecifier, ChangeKind)], + new_project_version: String, + config_changed: bool, + ) { + let req = TscRequest { + method: "$projectChanged", + args: json!([modified_scripts, new_project_version, config_changed,]), + }; + self + .request::<()>(snapshot, req) + .await + .map_err(|err| { + log::error!("Failed to request to tsserver {}", err); + LspError::invalid_request() + }) + .ok(); + } + pub async fn get_diagnostics( &self, snapshot: Arc<StateSnapshot>, @@ -287,10 +325,13 @@ impl TsServer { ) -> Result<HashMap<String, Vec<crate::tsc::Diagnostic>>, AnyError> { let req = TscRequest { method: "$getDiagnostics", - args: json!([specifiers - .into_iter() - .map(|s| self.specifier_map.denormalize(&s)) - .collect::<Vec<String>>(),]), + args: json!([ + specifiers + .into_iter() + .map(|s| self.specifier_map.denormalize(&s)) + .collect::<Vec<String>>(), + snapshot.documents.project_version() + ]), }; let raw_diagnostics = self.request_with_cancellation::<HashMap<String, Vec<crate::tsc::Diagnostic>>>(snapshot, req, token).await?; let mut diagnostics_map = HashMap::with_capacity(raw_diagnostics.len()); @@ -5135,6 +5176,14 @@ mod tests { ..snapshot.as_ref().clone() }) }; + ts_server + .project_changed( + snapshot.clone(), + &[(&specifier_dep, ChangeKind::Opened)], + snapshot.documents.project_version(), + false, + ) + .await; let specifier = resolve_url("file:///a.ts").unwrap(); let diagnostics = ts_server .get_diagnostics(snapshot.clone(), vec![specifier], Default::default()) |