Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

perf(lsp): cancellation checks in blocking code #27997

Merged
merged 34 commits into from
Feb 10, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
5c20c03
perf(lsp): cancellation checks in blocking code
nayeemrmn Feb 6, 2025
bc0fb76
plumb token to tsc
nayeemrmn Feb 6, 2025
20d74ee
reenable resolution cache
nayeemrmn Feb 6, 2025
5c3e988
add helpers, use for notification handlers
nayeemrmn Feb 6, 2025
a398ad6
document_symbol
nayeemrmn Feb 6, 2025
05437ae
formatting
nayeemrmn Feb 6, 2025
f40a42d
fixup! formatting
nayeemrmn Feb 6, 2025
f2c0d82
hover
nayeemrmn Feb 6, 2025
8d637fb
inlay_hint
nayeemrmn Feb 6, 2025
142a3af
code_action
nayeemrmn Feb 6, 2025
a0bea12
code_action_resolve
nayeemrmn Feb 6, 2025
b668958
code_lens
nayeemrmn Feb 6, 2025
c5302cf
more requests, more checks, refactor
nayeemrmn Feb 7, 2025
ff287c1
more requests
nayeemrmn Feb 7, 2025
de55d9f
last requests
nayeemrmn Feb 7, 2025
b02a071
cleanup
nayeemrmn Feb 7, 2025
9d9c4e5
WorkerThread, fix runtime flavor
nayeemrmn Feb 7, 2025
85fca86
cleanup an error message, add comment
nayeemrmn Feb 7, 2025
2560c0a
Merge remote-tracking branch 'upstream/main' into lsp-cancellation-fo…
nayeemrmn Feb 7, 2025
399a00a
fix missing cancellations and tests
nayeemrmn Feb 7, 2025
2aee089
fix
nayeemrmn Feb 7, 2025
2cd6b78
fix
nayeemrmn Feb 7, 2025
e7d2a92
fix
nayeemrmn Feb 7, 2025
a18abde
always get diagnostics after caching
nayeemrmn Feb 7, 2025
022bdb2
read diagnostics in change_configuration()
nayeemrmn Feb 7, 2025
f80f166
remove redundant drop guard from tsc request
nayeemrmn Feb 7, 2025
bc8bd5f
fix more logs on cancellation errors
nayeemrmn Feb 7, 2025
b48e57f
move custom requests to worker thread
nayeemrmn Feb 7, 2025
c57e8ef
read diagnostics after did_change_watched_files()
nayeemrmn Feb 7, 2025
02c9bda
check cancellation when walking navigation tree
nayeemrmn Feb 7, 2025
97b730e
Merge remote-tracking branch 'upstream/main' into lsp-cancellation-fo…
nayeemrmn Feb 7, 2025
9df3db4
fixup! check cancellation when walking navigation tree
nayeemrmn Feb 7, 2025
2bec93c
fix more logs on cancellation errors
nayeemrmn Feb 7, 2025
7ab5421
create_basic_runtime()
nayeemrmn Feb 10, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions cli/lsp/analysis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use std::path::Path;
use deno_ast::SourceRange;
use deno_ast::SourceRangedForSpanned;
use deno_ast::SourceTextInfo;
use deno_core::anyhow::anyhow;
use deno_core::error::AnyError;
use deno_core::serde::Deserialize;
use deno_core::serde::Serialize;
Expand Down Expand Up @@ -620,9 +621,13 @@ fn try_reverse_map_package_json_exports(
pub fn fix_ts_import_changes(
changes: &[tsc::FileTextChanges],
language_server: &language_server::Inner,
token: &CancellationToken,
) -> Result<Vec<tsc::FileTextChanges>, AnyError> {
let mut r = Vec::new();
for change in changes {
if token.is_cancelled() {
return Err(anyhow!("request cancelled"));
nayeemrmn marked this conversation as resolved.
Show resolved Hide resolved
}
let Ok(referrer) = ModuleSpecifier::parse(&change.file_name) else {
continue;
};
Expand Down
49 changes: 38 additions & 11 deletions cli/lsp/code_lens.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use deno_ast::swc::visit::VisitWith;
use deno_ast::ParsedSource;
use deno_ast::SourceRange;
use deno_ast::SourceRangedForSpanned;
use deno_core::anyhow::anyhow;
use deno_core::error::AnyError;
use deno_core::resolve_url;
use deno_core::serde::Deserialize;
Expand All @@ -21,7 +22,7 @@ use deno_core::ModuleSpecifier;
use lazy_regex::lazy_regex;
use once_cell::sync::Lazy;
use regex::Regex;
use tower_lsp::jsonrpc::Error as LspError;
use tokio_util::sync::CancellationToken;
use tower_lsp::lsp_types as lsp;

use super::analysis::source_range_to_lsp_range;
Expand All @@ -30,7 +31,6 @@ use super::language_server;
use super::text::LineIndex;
use super::tsc;
use super::tsc::NavigationTree;
use crate::lsp::logging::lsp_warn;

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

Expand Down Expand Up @@ -253,6 +253,7 @@ async fn resolve_implementation_code_lens(
code_lens: lsp::CodeLens,
data: CodeLensData,
language_server: &language_server::Inner,
token: &CancellationToken,
) -> Result<lsp::CodeLens, AnyError> {
let asset_or_doc = language_server.get_asset_or_document(&data.specifier)?;
let line_index = asset_or_doc.line_index();
Expand All @@ -262,15 +263,25 @@ async fn resolve_implementation_code_lens(
language_server.snapshot(),
data.specifier.clone(),
line_index.offset_tsc(code_lens.range.start)?,
token,
)
.await
.map_err(|err| {
lsp_warn!("{err}");
LspError::internal_error()
if token.is_cancelled() {
anyhow!("request cancelled")
} else {
anyhow!(
"Unable to get implementation locations from TypeScript: {:#}",
err
)
}
})?;
if let Some(implementations) = maybe_implementations {
let mut locations = Vec::new();
for implementation in implementations {
if token.is_cancelled() {
break;
}
let implementation_specifier =
resolve_url(&implementation.document_span.file_name)?;
let implementation_location =
Expand Down Expand Up @@ -326,17 +337,22 @@ async fn resolve_references_code_lens(
code_lens: lsp::CodeLens,
data: CodeLensData,
language_server: &language_server::Inner,
token: &CancellationToken,
) -> Result<lsp::CodeLens, AnyError> {
fn get_locations(
maybe_referenced_symbols: Option<Vec<tsc::ReferencedSymbol>>,
language_server: &language_server::Inner,
token: &CancellationToken,
) -> Result<Vec<lsp::Location>, AnyError> {
let symbols = match maybe_referenced_symbols {
Some(symbols) => symbols,
None => return Ok(Vec::new()),
};
let mut locations = Vec::new();
for reference in symbols.iter().flat_map(|s| &s.references) {
if token.is_cancelled() {
break;
}
if reference.is_definition {
continue;
}
Expand All @@ -363,13 +379,18 @@ async fn resolve_references_code_lens(
language_server.snapshot(),
data.specifier.clone(),
line_index.offset_tsc(code_lens.range.start)?,
token,
)
.await
.map_err(|err| {
lsp_warn!("Unable to find references: {err}");
LspError::internal_error()
if token.is_cancelled() {
anyhow!("request cancelled")
} else {
anyhow!("Unable to get references from TypeScript: {:#}", err)
}
})?;
let locations = get_locations(maybe_referenced_symbols, language_server)?;
let locations =
get_locations(maybe_referenced_symbols, language_server, token)?;
let title = if locations.len() == 1 {
"1 reference".to_string()
} else {
Expand Down Expand Up @@ -402,23 +423,28 @@ async fn resolve_references_code_lens(
pub async fn resolve_code_lens(
code_lens: lsp::CodeLens,
language_server: &language_server::Inner,
token: &CancellationToken,
) -> Result<lsp::CodeLens, AnyError> {
let data: CodeLensData =
serde_json::from_value(code_lens.data.clone().unwrap())?;
match data.source {
CodeLensSource::Implementations => {
resolve_implementation_code_lens(code_lens, data, language_server).await
resolve_implementation_code_lens(code_lens, data, language_server, token)
.await
}
CodeLensSource::References => {
resolve_references_code_lens(code_lens, data, language_server).await
resolve_references_code_lens(code_lens, data, language_server, token)
.await
}
}
}

pub fn collect_test(
specifier: &ModuleSpecifier,
parsed_source: &ParsedSource,
_token: &CancellationToken,
) -> Result<Vec<lsp::CodeLens>, AnyError> {
// TODO(nayeemrmn): Do cancellation checks while collecting tests.
let mut collector =
DenoTestCollector::new(specifier.clone(), parsed_source.clone());
parsed_source.program().visit_with(&mut collector);
Expand All @@ -431,9 +457,10 @@ pub fn collect_tsc(
code_lens_settings: &CodeLensSettings,
line_index: Arc<LineIndex>,
navigation_tree: &NavigationTree,
token: &CancellationToken,
) -> Result<Vec<lsp::CodeLens>, AnyError> {
let code_lenses = Rc::new(RefCell::new(Vec::new()));
navigation_tree.walk(&|i, mp| {
navigation_tree.walk(token, &|i, mp| {
let mut code_lenses = code_lenses.borrow_mut();

// TSC Implementations Code Lens
Expand Down Expand Up @@ -541,7 +568,7 @@ pub fn collect_tsc(
_ => (),
}
}
});
})?;
Ok(Rc::try_unwrap(code_lenses).unwrap().into_inner())
}

Expand Down
2 changes: 1 addition & 1 deletion cli/lsp/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1087,7 +1087,7 @@ async fn generate_ts_diagnostics(
let (ts_diagnostics_map, ambient_modules_by_scope) =
if !enabled_specifiers.is_empty() {
ts_server
.get_diagnostics(snapshot.clone(), enabled_specifiers, token)
.get_diagnostics(snapshot.clone(), enabled_specifiers, &token)
.await?
} else {
Default::default()
Expand Down
Loading