1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-11-29 16:30:56 -05:00

perf(lsp): use LanguageServiceHost::getProjectVersion() (#21719)

This commit is contained in:
Nayeem Rahman 2023-12-28 00:13:57 +00:00 committed by Bartek Iwańczuk
parent 69cc117015
commit 730835498c
No known key found for this signature in database
GPG key ID: 0C6BCDDC3B3AD750
4 changed files with 50 additions and 1 deletions

View file

@ -1346,6 +1346,7 @@ impl Inner {
self self
.diagnostics_server .diagnostics_server
.invalidate(&self.documents.dependents(&specifier)); .invalidate(&self.documents.dependents(&specifier));
self.ts_server.increment_project_version();
self.send_diagnostics_update(); self.send_diagnostics_update();
self.send_testing_update(); self.send_testing_update();
} }
@ -1390,6 +1391,7 @@ impl Inner {
let mut specifiers = self.documents.dependents(&specifier); let mut specifiers = self.documents.dependents(&specifier);
specifiers.push(specifier.clone()); specifiers.push(specifier.clone());
self.diagnostics_server.invalidate(&specifiers); self.diagnostics_server.invalidate(&specifiers);
self.ts_server.increment_project_version();
self.send_diagnostics_update(); self.send_diagnostics_update();
self.send_testing_update(); self.send_testing_update();
} }
@ -1442,6 +1444,7 @@ impl Inner {
self.refresh_documents_config().await; self.refresh_documents_config().await;
self.diagnostics_server.invalidate_all(); self.diagnostics_server.invalidate_all();
self.ts_server.increment_project_version();
self.send_diagnostics_update(); self.send_diagnostics_update();
self.send_testing_update(); self.send_testing_update();
} }
@ -3303,6 +3306,7 @@ impl tower_lsp::LanguageServer for LanguageServer {
inner.refresh_npm_specifiers().await; inner.refresh_npm_specifiers().await;
let specifiers = inner.documents.dependents(&specifier); let specifiers = inner.documents.dependents(&specifier);
inner.diagnostics_server.invalidate(&specifiers); inner.diagnostics_server.invalidate(&specifiers);
inner.ts_server.increment_project_version();
inner.send_diagnostics_update(); inner.send_diagnostics_update();
inner.send_testing_update(); inner.send_testing_update();
} }
@ -3393,6 +3397,7 @@ impl tower_lsp::LanguageServer for LanguageServer {
let mut ls = self.0.write().await; let mut ls = self.0.write().await;
ls.refresh_documents_config().await; ls.refresh_documents_config().await;
ls.diagnostics_server.invalidate_all(); ls.diagnostics_server.invalidate_all();
ls.ts_server.increment_project_version();
ls.send_diagnostics_update(); ls.send_diagnostics_update();
} }
performance.measure(mark); performance.measure(mark);

View file

@ -70,6 +70,8 @@ use std::net::SocketAddr;
use std::ops::Range; use std::ops::Range;
use std::path::Path; use std::path::Path;
use std::rc::Rc; use std::rc::Rc;
use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering;
use std::sync::Arc; use std::sync::Arc;
use std::thread; use std::thread;
use text_size::TextRange; use text_size::TextRange;
@ -220,6 +222,7 @@ pub struct TsServer {
sender: mpsc::UnboundedSender<Request>, sender: mpsc::UnboundedSender<Request>,
receiver: Mutex<Option<mpsc::UnboundedReceiver<Request>>>, receiver: Mutex<Option<mpsc::UnboundedReceiver<Request>>>,
specifier_map: Arc<TscSpecifierMap>, specifier_map: Arc<TscSpecifierMap>,
project_version: Arc<AtomicUsize>,
inspector_server: Mutex<Option<Arc<InspectorServer>>>, inspector_server: Mutex<Option<Arc<InspectorServer>>>,
} }
@ -231,6 +234,7 @@ impl std::fmt::Debug for TsServer {
.field("sender", &self.sender) .field("sender", &self.sender)
.field("receiver", &self.receiver) .field("receiver", &self.receiver)
.field("specifier_map", &self.specifier_map) .field("specifier_map", &self.specifier_map)
.field("project_version", &self.project_version)
.field("inspector_server", &self.inspector_server.lock().is_some()) .field("inspector_server", &self.inspector_server.lock().is_some())
.finish() .finish()
} }
@ -245,6 +249,7 @@ impl TsServer {
sender: tx, sender: tx,
receiver: Mutex::new(Some(request_rx)), receiver: Mutex::new(Some(request_rx)),
specifier_map: Arc::new(TscSpecifierMap::new()), specifier_map: Arc::new(TscSpecifierMap::new()),
project_version: Arc::new(AtomicUsize::new(1)),
inspector_server: Mutex::new(None), inspector_server: Mutex::new(None),
} }
} }
@ -267,12 +272,14 @@ impl TsServer {
let performance = self.performance.clone(); let performance = self.performance.clone();
let cache = self.cache.clone(); let cache = self.cache.clone();
let specifier_map = self.specifier_map.clone(); let specifier_map = self.specifier_map.clone();
let project_version = self.project_version.clone();
let _join_handle = thread::spawn(move || { let _join_handle = thread::spawn(move || {
run_tsc_thread( run_tsc_thread(
receiver, receiver,
performance.clone(), performance.clone(),
cache.clone(), cache.clone(),
specifier_map.clone(), specifier_map.clone(),
project_version,
maybe_inspector_server, maybe_inspector_server,
) )
}); });
@ -354,6 +361,10 @@ impl TsServer {
self.request(snapshot, req).await 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( pub async fn get_supported_code_fixes(
&self, &self,
snapshot: Arc<StateSnapshot>, snapshot: Arc<StateSnapshot>,
@ -3830,6 +3841,7 @@ struct State {
response: Option<Response>, response: Option<Response>,
state_snapshot: Arc<StateSnapshot>, state_snapshot: Arc<StateSnapshot>,
specifier_map: Arc<TscSpecifierMap>, specifier_map: Arc<TscSpecifierMap>,
project_version: Arc<AtomicUsize>,
token: CancellationToken, token: CancellationToken,
} }
@ -3838,6 +3850,7 @@ impl State {
state_snapshot: Arc<StateSnapshot>, state_snapshot: Arc<StateSnapshot>,
specifier_map: Arc<TscSpecifierMap>, specifier_map: Arc<TscSpecifierMap>,
performance: Arc<Performance>, performance: Arc<Performance>,
project_version: Arc<AtomicUsize>,
) -> Self { ) -> Self {
Self { Self {
last_id: 1, last_id: 1,
@ -3845,6 +3858,7 @@ impl State {
response: None, response: None,
state_snapshot, state_snapshot,
specifier_map, specifier_map,
project_version,
token: Default::default(), token: Default::default(),
} }
} }
@ -4058,11 +4072,22 @@ fn op_script_version(
Ok(r) Ok(r)
} }
#[op2]
#[string]
fn op_project_version(state: &mut OpState) -> String {
let state = state.borrow_mut::<State>();
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( fn run_tsc_thread(
mut request_rx: UnboundedReceiver<Request>, mut request_rx: UnboundedReceiver<Request>,
performance: Arc<Performance>, performance: Arc<Performance>,
cache: Arc<dyn HttpCache>, cache: Arc<dyn HttpCache>,
specifier_map: Arc<TscSpecifierMap>, specifier_map: Arc<TscSpecifierMap>,
project_version: Arc<AtomicUsize>,
maybe_inspector_server: Option<Arc<InspectorServer>>, maybe_inspector_server: Option<Arc<InspectorServer>>,
) { ) {
let has_inspector_server = maybe_inspector_server.is_some(); 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 // supplied snapshot is an isolate that contains the TypeScript language
// server. // server.
let mut tsc_runtime = JsRuntime::new(RuntimeOptions { 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()), startup_snapshot: Some(tsc::compiler_snapshot()),
inspector: maybe_inspector_server.is_some(), inspector: maybe_inspector_server.is_some(),
..Default::default() ..Default::default()
@ -4137,11 +4167,13 @@ deno_core::extension!(deno_tsc,
op_respond, op_respond,
op_script_names, op_script_names,
op_script_version, op_script_version,
op_project_version,
], ],
options = { options = {
performance: Arc<Performance>, performance: Arc<Performance>,
cache: Arc<dyn HttpCache>, cache: Arc<dyn HttpCache>,
specifier_map: Arc<TscSpecifierMap>, specifier_map: Arc<TscSpecifierMap>,
project_version: Arc<AtomicUsize>,
}, },
state = |state, options| { state = |state, options| {
state.put(State::new( state.put(State::new(
@ -4155,6 +4187,7 @@ deno_core::extension!(deno_tsc,
}), }),
options.specifier_map, options.specifier_map,
options.performance, options.performance,
options.project_version,
)); ));
}, },
); );
@ -5082,6 +5115,7 @@ mod tests {
b"export const b = \"b\";\n\nexport const a = \"b\";\n", b"export const b = \"b\";\n\nexport const a = \"b\";\n",
) )
.unwrap(); .unwrap();
ts_server.increment_project_version();
let specifier = resolve_url("file:///a.ts").unwrap(); let specifier = resolve_url("file:///a.ts").unwrap();
let diagnostics = ts_server let diagnostics = ts_server
.get_diagnostics(snapshot.clone(), vec![specifier], Default::default()) .get_diagnostics(snapshot.clone(), vec![specifier], Default::default())

View file

@ -8269,6 +8269,7 @@ fn lsp_performance() {
"tsc.host.getQuickInfoAtPosition", "tsc.host.getQuickInfoAtPosition",
"tsc.op.op_is_node_file", "tsc.op.op_is_node_file",
"tsc.op.op_load", "tsc.op.op_load",
"tsc.op.op_project_version",
"tsc.op.op_script_names", "tsc.op.op_script_names",
"tsc.op.op_script_version", "tsc.op.op_script_version",
"tsc.request.$configure", "tsc.request.$configure",

View file

@ -534,6 +534,9 @@ delete Object.prototype.__proto__;
// createLanguageService will call this immediately and cache it // createLanguageService will call this immediately and cache it
return new CancellationToken(); return new CancellationToken();
}, },
getProjectVersion() {
return ops.op_project_version();
},
getSourceFile( getSourceFile(
specifier, specifier,
languageVersion, languageVersion,
@ -584,6 +587,9 @@ delete Object.prototype.__proto__;
); );
sourceFile.moduleName = specifier; sourceFile.moduleName = specifier;
sourceFile.version = version; sourceFile.version = version;
if (specifier.startsWith(ASSETS_URL_PREFIX)) {
sourceFile.version = "1";
}
sourceFileCache.set(specifier, sourceFile); sourceFileCache.set(specifier, sourceFile);
scriptVersionCache.set(specifier, version); scriptVersionCache.set(specifier, version);
return sourceFile; return sourceFile;
@ -721,6 +727,9 @@ delete Object.prototype.__proto__;
if (logDebug) { if (logDebug) {
debug(`host.getScriptVersion("${specifier}")`); debug(`host.getScriptVersion("${specifier}")`);
} }
if (specifier.startsWith(ASSETS_URL_PREFIX)) {
return "1";
}
// tsc requests the script version multiple times even though it can't // 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. // possibly have changed, so we will memoize it on a per request basis.
if (scriptVersionCache.has(specifier)) { if (scriptVersionCache.has(specifier)) {