diff --git a/cli/lsp/language_server.rs b/cli/lsp/language_server.rs index e730e145fe..ca9c8838db 100644 --- a/cli/lsp/language_server.rs +++ b/cli/lsp/language_server.rs @@ -1346,6 +1346,7 @@ impl Inner { self .diagnostics_server .invalidate(&self.documents.dependents(&specifier)); + self.ts_server.increment_project_version(); self.send_diagnostics_update(); self.send_testing_update(); } @@ -1390,6 +1391,7 @@ 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(); } @@ -1442,6 +1444,7 @@ 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(); } @@ -3303,6 +3306,7 @@ 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(); } @@ -3393,6 +3397,7 @@ 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 c3d16f038a..32421ba697 100644 --- a/cli/lsp/tsc.rs +++ b/cli/lsp/tsc.rs @@ -70,6 +70,8 @@ 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; @@ -220,6 +222,7 @@ pub struct TsServer { sender: mpsc::UnboundedSender, receiver: Mutex>>, specifier_map: Arc, + project_version: Arc, inspector_server: Mutex>>, } @@ -231,6 +234,7 @@ 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() } @@ -245,6 +249,7 @@ 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), } } @@ -267,12 +272,14 @@ 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, ) }); @@ -354,6 +361,10 @@ 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, @@ -3830,6 +3841,7 @@ struct State { response: Option, state_snapshot: Arc, specifier_map: Arc, + project_version: Arc, token: CancellationToken, } @@ -3838,6 +3850,7 @@ impl State { state_snapshot: Arc, specifier_map: Arc, performance: Arc, + project_version: Arc, ) -> Self { Self { last_id: 1, @@ -3845,6 +3858,7 @@ impl State { response: None, state_snapshot, specifier_map, + project_version, token: Default::default(), } } @@ -4058,11 +4072,22 @@ fn op_script_version( Ok(r) } +#[op2] +#[string] +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(); + state.performance.measure(mark); + r +} + fn run_tsc_thread( mut request_rx: UnboundedReceiver, performance: Arc, cache: Arc, specifier_map: Arc, + project_version: Arc, maybe_inspector_server: Option>, ) { let has_inspector_server = maybe_inspector_server.is_some(); @@ -4070,7 +4095,12 @@ 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)], + extensions: vec![deno_tsc::init_ops( + performance, + cache, + specifier_map, + project_version, + )], startup_snapshot: Some(tsc::compiler_snapshot()), inspector: maybe_inspector_server.is_some(), ..Default::default() @@ -4137,11 +4167,13 @@ deno_core::extension!(deno_tsc, op_respond, op_script_names, op_script_version, + op_project_version, ], options = { performance: Arc, cache: Arc, specifier_map: Arc, + project_version: Arc, }, state = |state, options| { state.put(State::new( @@ -4155,6 +4187,7 @@ deno_core::extension!(deno_tsc, }), options.specifier_map, options.performance, + options.project_version, )); }, ); @@ -5082,6 +5115,7 @@ mod tests { b"export const b = \"b\";\n\nexport const a = \"b\";\n", ) .unwrap(); + ts_server.increment_project_version(); let specifier = resolve_url("file:///a.ts").unwrap(); let diagnostics = ts_server .get_diagnostics(snapshot.clone(), vec![specifier], Default::default()) diff --git a/cli/tests/integration/lsp_tests.rs b/cli/tests/integration/lsp_tests.rs index 0e8bbd2afd..badc3b7efe 100644 --- a/cli/tests/integration/lsp_tests.rs +++ b/cli/tests/integration/lsp_tests.rs @@ -8269,6 +8269,7 @@ fn lsp_performance() { "tsc.host.getQuickInfoAtPosition", "tsc.op.op_is_node_file", "tsc.op.op_load", + "tsc.op.op_project_version", "tsc.op.op_script_names", "tsc.op.op_script_version", "tsc.request.$configure", diff --git a/cli/tsc/99_main_compiler.js b/cli/tsc/99_main_compiler.js index e1b7b462c6..b4b5398bcf 100644 --- a/cli/tsc/99_main_compiler.js +++ b/cli/tsc/99_main_compiler.js @@ -534,6 +534,9 @@ delete Object.prototype.__proto__; // createLanguageService will call this immediately and cache it return new CancellationToken(); }, + getProjectVersion() { + return ops.op_project_version(); + }, getSourceFile( specifier, languageVersion, @@ -584,6 +587,9 @@ delete Object.prototype.__proto__; ); sourceFile.moduleName = specifier; sourceFile.version = version; + if (specifier.startsWith(ASSETS_URL_PREFIX)) { + sourceFile.version = "1"; + } sourceFileCache.set(specifier, sourceFile); scriptVersionCache.set(specifier, version); return sourceFile; @@ -721,6 +727,9 @@ delete Object.prototype.__proto__; if (logDebug) { debug(`host.getScriptVersion("${specifier}")`); } + if (specifier.startsWith(ASSETS_URL_PREFIX)) { + return "1"; + } // tsc requests the script version multiple times even though it can't // possibly have changed, so we will memoize it on a per request basis. if (scriptVersionCache.has(specifier)) {