Skip to content

Commit 7d139dd

Browse files
authored
perf(lsp): cancellation checks in blocking code (#27997)
1 parent e94581d commit 7d139dd

File tree

8 files changed

+1338
-448
lines changed

8 files changed

+1338
-448
lines changed

cli/lsp/analysis.rs

+5
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use std::path::Path;
99
use deno_ast::SourceRange;
1010
use deno_ast::SourceRangedForSpanned;
1111
use deno_ast::SourceTextInfo;
12+
use deno_core::anyhow::anyhow;
1213
use deno_core::error::AnyError;
1314
use deno_core::serde::Deserialize;
1415
use deno_core::serde::Serialize;
@@ -620,9 +621,13 @@ fn try_reverse_map_package_json_exports(
620621
pub fn fix_ts_import_changes(
621622
changes: &[tsc::FileTextChanges],
622623
language_server: &language_server::Inner,
624+
token: &CancellationToken,
623625
) -> Result<Vec<tsc::FileTextChanges>, AnyError> {
624626
let mut r = Vec::new();
625627
for change in changes {
628+
if token.is_cancelled() {
629+
return Err(anyhow!("request cancelled"));
630+
}
626631
let Ok(referrer) = ModuleSpecifier::parse(&change.file_name) else {
627632
continue;
628633
};

cli/lsp/code_lens.rs

+38-11
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use deno_ast::swc::visit::VisitWith;
1111
use deno_ast::ParsedSource;
1212
use deno_ast::SourceRange;
1313
use deno_ast::SourceRangedForSpanned;
14+
use deno_core::anyhow::anyhow;
1415
use deno_core::error::AnyError;
1516
use deno_core::resolve_url;
1617
use deno_core::serde::Deserialize;
@@ -21,7 +22,7 @@ use deno_core::ModuleSpecifier;
2122
use lazy_regex::lazy_regex;
2223
use once_cell::sync::Lazy;
2324
use regex::Regex;
24-
use tower_lsp::jsonrpc::Error as LspError;
25+
use tokio_util::sync::CancellationToken;
2526
use tower_lsp::lsp_types as lsp;
2627

2728
use super::analysis::source_range_to_lsp_range;
@@ -30,7 +31,6 @@ use super::language_server;
3031
use super::text::LineIndex;
3132
use super::tsc;
3233
use super::tsc::NavigationTree;
33-
use crate::lsp::logging::lsp_warn;
3434

3535
static ABSTRACT_MODIFIER: Lazy<Regex> = lazy_regex!(r"\babstract\b");
3636

@@ -253,6 +253,7 @@ async fn resolve_implementation_code_lens(
253253
code_lens: lsp::CodeLens,
254254
data: CodeLensData,
255255
language_server: &language_server::Inner,
256+
token: &CancellationToken,
256257
) -> Result<lsp::CodeLens, AnyError> {
257258
let asset_or_doc = language_server.get_asset_or_document(&data.specifier)?;
258259
let line_index = asset_or_doc.line_index();
@@ -262,15 +263,25 @@ async fn resolve_implementation_code_lens(
262263
language_server.snapshot(),
263264
data.specifier.clone(),
264265
line_index.offset_tsc(code_lens.range.start)?,
266+
token,
265267
)
266268
.await
267269
.map_err(|err| {
268-
lsp_warn!("{err}");
269-
LspError::internal_error()
270+
if token.is_cancelled() {
271+
anyhow!("request cancelled")
272+
} else {
273+
anyhow!(
274+
"Unable to get implementation locations from TypeScript: {:#}",
275+
err
276+
)
277+
}
270278
})?;
271279
if let Some(implementations) = maybe_implementations {
272280
let mut locations = Vec::new();
273281
for implementation in implementations {
282+
if token.is_cancelled() {
283+
break;
284+
}
274285
let implementation_specifier =
275286
resolve_url(&implementation.document_span.file_name)?;
276287
let implementation_location =
@@ -326,17 +337,22 @@ async fn resolve_references_code_lens(
326337
code_lens: lsp::CodeLens,
327338
data: CodeLensData,
328339
language_server: &language_server::Inner,
340+
token: &CancellationToken,
329341
) -> Result<lsp::CodeLens, AnyError> {
330342
fn get_locations(
331343
maybe_referenced_symbols: Option<Vec<tsc::ReferencedSymbol>>,
332344
language_server: &language_server::Inner,
345+
token: &CancellationToken,
333346
) -> Result<Vec<lsp::Location>, AnyError> {
334347
let symbols = match maybe_referenced_symbols {
335348
Some(symbols) => symbols,
336349
None => return Ok(Vec::new()),
337350
};
338351
let mut locations = Vec::new();
339352
for reference in symbols.iter().flat_map(|s| &s.references) {
353+
if token.is_cancelled() {
354+
break;
355+
}
340356
if reference.is_definition {
341357
continue;
342358
}
@@ -363,13 +379,18 @@ async fn resolve_references_code_lens(
363379
language_server.snapshot(),
364380
data.specifier.clone(),
365381
line_index.offset_tsc(code_lens.range.start)?,
382+
token,
366383
)
367384
.await
368385
.map_err(|err| {
369-
lsp_warn!("Unable to find references: {err}");
370-
LspError::internal_error()
386+
if token.is_cancelled() {
387+
anyhow!("request cancelled")
388+
} else {
389+
anyhow!("Unable to get references from TypeScript: {:#}", err)
390+
}
371391
})?;
372-
let locations = get_locations(maybe_referenced_symbols, language_server)?;
392+
let locations =
393+
get_locations(maybe_referenced_symbols, language_server, token)?;
373394
let title = if locations.len() == 1 {
374395
"1 reference".to_string()
375396
} else {
@@ -402,23 +423,28 @@ async fn resolve_references_code_lens(
402423
pub async fn resolve_code_lens(
403424
code_lens: lsp::CodeLens,
404425
language_server: &language_server::Inner,
426+
token: &CancellationToken,
405427
) -> Result<lsp::CodeLens, AnyError> {
406428
let data: CodeLensData =
407429
serde_json::from_value(code_lens.data.clone().unwrap())?;
408430
match data.source {
409431
CodeLensSource::Implementations => {
410-
resolve_implementation_code_lens(code_lens, data, language_server).await
432+
resolve_implementation_code_lens(code_lens, data, language_server, token)
433+
.await
411434
}
412435
CodeLensSource::References => {
413-
resolve_references_code_lens(code_lens, data, language_server).await
436+
resolve_references_code_lens(code_lens, data, language_server, token)
437+
.await
414438
}
415439
}
416440
}
417441

418442
pub fn collect_test(
419443
specifier: &ModuleSpecifier,
420444
parsed_source: &ParsedSource,
445+
_token: &CancellationToken,
421446
) -> Result<Vec<lsp::CodeLens>, AnyError> {
447+
// TODO(nayeemrmn): Do cancellation checks while collecting tests.
422448
let mut collector =
423449
DenoTestCollector::new(specifier.clone(), parsed_source.clone());
424450
parsed_source.program().visit_with(&mut collector);
@@ -431,9 +457,10 @@ pub fn collect_tsc(
431457
code_lens_settings: &CodeLensSettings,
432458
line_index: Arc<LineIndex>,
433459
navigation_tree: &NavigationTree,
460+
token: &CancellationToken,
434461
) -> Result<Vec<lsp::CodeLens>, AnyError> {
435462
let code_lenses = Rc::new(RefCell::new(Vec::new()));
436-
navigation_tree.walk(&|i, mp| {
463+
navigation_tree.walk(token, &|i, mp| {
437464
let mut code_lenses = code_lenses.borrow_mut();
438465

439466
// TSC Implementations Code Lens
@@ -541,7 +568,7 @@ pub fn collect_tsc(
541568
_ => (),
542569
}
543570
}
544-
});
571+
})?;
545572
Ok(Rc::try_unwrap(code_lenses).unwrap().into_inner())
546573
}
547574

cli/lsp/diagnostics.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1087,7 +1087,7 @@ async fn generate_ts_diagnostics(
10871087
let (ts_diagnostics_map, ambient_modules_by_scope) =
10881088
if !enabled_specifiers.is_empty() {
10891089
ts_server
1090-
.get_diagnostics(snapshot.clone(), enabled_specifiers, token)
1090+
.get_diagnostics(snapshot.clone(), enabled_specifiers, &token)
10911091
.await?
10921092
} else {
10931093
Default::default()

0 commit comments

Comments
 (0)