From d8f86c8b9cf327db4d246c20cf60467cafe2ba64 Mon Sep 17 00:00:00 2001 From: Nayeem Rahman Date: Thu, 11 Jan 2024 17:07:44 +0000 Subject: [PATCH] refactor(lsp): store project version on documents (#21892) --- cli/lsp/documents.rs | 28 +++++++++++++++++++++++----- cli/lsp/language_server.rs | 9 ++------- cli/lsp/tsc.rs | 35 ++++++++++------------------------- 3 files changed, 35 insertions(+), 37 deletions(-) diff --git a/cli/lsp/documents.rs b/cli/lsp/documents.rs index 2084928004..bff56a6b8b 100644 --- a/cli/lsp/documents.rs +++ b/cli/lsp/documents.rs @@ -896,6 +896,7 @@ pub struct Documents { redirect_resolver: Arc, /// If --unstable-sloppy-imports is enabled. unstable_sloppy_imports: bool, + project_version: usize, } impl Documents { @@ -924,6 +925,7 @@ impl Documents { has_injected_types_node_package: false, redirect_resolver: Arc::new(RedirectResolver::new(cache)), unstable_sloppy_imports: false, + project_version: 0, } } @@ -935,6 +937,14 @@ impl Documents { .flat_map(|value| value.get_type().or_else(|| value.get_code())) } + pub fn project_version(&self) -> String { + self.project_version.to_string() + } + + pub fn increment_project_version(&mut self) { + self.project_version += 1; + } + /// "Open" a document from the perspective of the editor, meaning that /// requests for information from the document will come from the in-memory /// representation received from the language server client, versus reading @@ -957,10 +967,13 @@ impl Documents { resolver, npm_resolver, ); - let mut file_system_docs = self.file_system_docs.lock(); - file_system_docs.docs.remove(&specifier); - file_system_docs.dirty = true; + { + let mut file_system_docs = self.file_system_docs.lock(); + file_system_docs.docs.remove(&specifier); + file_system_docs.dirty = true; + } self.open_docs.insert(specifier, document.clone()); + self.increment_project_version(); self.dirty = true; document } @@ -995,6 +1008,7 @@ impl Documents { self.get_npm_resolver(), )?; self.open_docs.insert(doc.specifier().clone(), doc.clone()); + self.increment_project_version(); Ok(doc) } @@ -1016,8 +1030,11 @@ impl Documents { /// information about the document is required. pub fn close(&mut self, specifier: &ModuleSpecifier) -> Result<(), AnyError> { if let Some(document) = self.open_docs.remove(specifier) { - let mut file_system_docs = self.file_system_docs.lock(); - file_system_docs.docs.insert(specifier.clone(), document); + { + let mut file_system_docs = self.file_system_docs.lock(); + file_system_docs.docs.insert(specifier.clone(), document); + } + self.increment_project_version(); self.dirty = true; } Ok(()) @@ -1422,6 +1439,7 @@ impl Documents { ); self.resolver_config_hash = new_resolver_config_hash; + self.increment_project_version(); self.dirty = true; self.calculate_dependents_if_dirty(); } diff --git a/cli/lsp/language_server.rs b/cli/lsp/language_server.rs index 1271d8fd97..395053fa50 100644 --- a/cli/lsp/language_server.rs +++ b/cli/lsp/language_server.rs @@ -164,14 +164,14 @@ impl LspNpmConfigHash { #[derive(Debug, Clone)] pub struct LanguageServer(Arc>, CancellationToken); -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct StateNpmSnapshot { pub node_resolver: Arc, pub npm_resolver: Arc, } /// Snapshot of the state used by TSC. -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct StateSnapshot { pub assets: AssetsSnapshot, pub cache_metadata: cache::CacheMetadata, @@ -1427,7 +1427,6 @@ impl Inner { self .diagnostics_server .invalidate(&self.documents.dependents(&specifier)); - self.ts_server.increment_project_version(); self.send_diagnostics_update(); self.send_testing_update(); } @@ -1472,7 +1471,6 @@ impl Inner { let mut specifiers = self.documents.dependents(&specifier); specifiers.push(specifier.clone()); self.diagnostics_server.invalidate(&specifiers); - self.ts_server.increment_project_version(); self.send_diagnostics_update(); self.send_testing_update(); } @@ -1525,7 +1523,6 @@ impl Inner { self.refresh_documents_config().await; self.diagnostics_server.invalidate_all(); - self.ts_server.increment_project_version(); self.send_diagnostics_update(); self.send_testing_update(); } @@ -3388,7 +3385,6 @@ impl tower_lsp::LanguageServer for LanguageServer { inner.refresh_npm_specifiers().await; let specifiers = inner.documents.dependents(&specifier); inner.diagnostics_server.invalidate(&specifiers); - inner.ts_server.increment_project_version(); inner.send_diagnostics_update(); inner.send_testing_update(); } @@ -3479,7 +3475,6 @@ impl tower_lsp::LanguageServer for LanguageServer { let mut ls = self.0.write().await; ls.refresh_documents_config().await; ls.diagnostics_server.invalidate_all(); - ls.ts_server.increment_project_version(); ls.send_diagnostics_update(); } performance.measure(mark); diff --git a/cli/lsp/tsc.rs b/cli/lsp/tsc.rs index f8aaec90a6..de7c16588c 100644 --- a/cli/lsp/tsc.rs +++ b/cli/lsp/tsc.rs @@ -70,8 +70,6 @@ use std::net::SocketAddr; use std::ops::Range; use std::path::Path; use std::rc::Rc; -use std::sync::atomic::AtomicUsize; -use std::sync::atomic::Ordering; use std::sync::Arc; use std::thread; use text_size::TextRange; @@ -222,7 +220,6 @@ pub struct TsServer { sender: mpsc::UnboundedSender, receiver: Mutex>>, specifier_map: Arc, - project_version: Arc, inspector_server: Mutex>>, } @@ -234,7 +231,6 @@ impl std::fmt::Debug for TsServer { .field("sender", &self.sender) .field("receiver", &self.receiver) .field("specifier_map", &self.specifier_map) - .field("project_version", &self.project_version) .field("inspector_server", &self.inspector_server.lock().is_some()) .finish() } @@ -249,7 +245,6 @@ impl TsServer { sender: tx, receiver: Mutex::new(Some(request_rx)), specifier_map: Arc::new(TscSpecifierMap::new()), - project_version: Arc::new(AtomicUsize::new(1)), inspector_server: Mutex::new(None), } } @@ -272,14 +267,12 @@ impl TsServer { let performance = self.performance.clone(); let cache = self.cache.clone(); let specifier_map = self.specifier_map.clone(); - let project_version = self.project_version.clone(); let _join_handle = thread::spawn(move || { run_tsc_thread( receiver, performance.clone(), cache.clone(), specifier_map.clone(), - project_version, maybe_inspector_server, ) }); @@ -361,10 +354,6 @@ impl TsServer { self.request(snapshot, req).await } - pub fn increment_project_version(&self) { - self.project_version.fetch_add(1, Ordering::Relaxed); - } - pub async fn get_supported_code_fixes( &self, snapshot: Arc, @@ -3841,7 +3830,6 @@ struct State { response: Option, state_snapshot: Arc, specifier_map: Arc, - project_version: Arc, token: CancellationToken, } @@ -3850,7 +3838,6 @@ impl State { state_snapshot: Arc, specifier_map: Arc, performance: Arc, - project_version: Arc, ) -> Self { Self { last_id: 1, @@ -3858,7 +3845,6 @@ impl State { response: None, state_snapshot, specifier_map, - project_version, token: Default::default(), } } @@ -4077,7 +4063,7 @@ fn op_script_version( fn op_project_version(state: &mut OpState) -> String { let state = state.borrow_mut::(); let mark = state.performance.mark("tsc.op.op_project_version"); - let r = state.project_version.load(Ordering::Relaxed).to_string(); + let r = state.state_snapshot.documents.project_version(); state.performance.measure(mark); r } @@ -4087,7 +4073,6 @@ fn run_tsc_thread( performance: Arc, cache: Arc, specifier_map: Arc, - project_version: Arc, maybe_inspector_server: Option>, ) { let has_inspector_server = maybe_inspector_server.is_some(); @@ -4095,12 +4080,7 @@ fn run_tsc_thread( // supplied snapshot is an isolate that contains the TypeScript language // server. let mut tsc_runtime = JsRuntime::new(RuntimeOptions { - extensions: vec![deno_tsc::init_ops( - performance, - cache, - specifier_map, - project_version, - )], + extensions: vec![deno_tsc::init_ops(performance, cache, specifier_map)], startup_snapshot: Some(tsc::compiler_snapshot()), inspector: maybe_inspector_server.is_some(), ..Default::default() @@ -4173,7 +4153,6 @@ deno_core::extension!(deno_tsc, performance: Arc, cache: Arc, specifier_map: Arc, - project_version: Arc, }, state = |state, options| { state.put(State::new( @@ -4187,7 +4166,6 @@ deno_core::extension!(deno_tsc, }), options.specifier_map, options.performance, - options.project_version, )); }, ); @@ -5115,7 +5093,14 @@ mod tests { b"export const b = \"b\";\n\nexport const a = \"b\";\n", ) .unwrap(); - ts_server.increment_project_version(); + let snapshot = { + let mut documents = snapshot.documents.clone(); + documents.increment_project_version(); + Arc::new(StateSnapshot { + documents, + ..snapshot.as_ref().clone() + }) + }; let specifier = resolve_url("file:///a.ts").unwrap(); let diagnostics = ts_server .get_diagnostics(snapshot.clone(), vec![specifier], Default::default())