0
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-03-03 17:34:47 -05:00

perf(lsp): avoid redundant getNavigationTree() calls (#21396)

This commit is contained in:
Nayeem Rahman 2023-11-30 16:23:47 +00:00 committed by GitHub
parent c803c0eaab
commit 91626bac49
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 58 additions and 87 deletions

View file

@ -1,8 +1,7 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
use super::analysis::source_range_to_lsp_range; use super::analysis::source_range_to_lsp_range;
use super::config::Config; use super::config::CodeLensSettings;
use super::config::WorkspaceSettings;
use super::language_server; use super::language_server;
use super::text::LineIndex; use super::text::LineIndex;
use super::tsc; use super::tsc;
@ -381,63 +380,29 @@ pub async fn resolve_code_lens(
} }
} }
pub async fn collect( pub fn collect_test(
specifier: &ModuleSpecifier, specifier: &ModuleSpecifier,
parsed_source: Option<ParsedSource>, parsed_source: ParsedSource,
config: &Config,
line_index: Arc<LineIndex>,
navigation_tree: &NavigationTree,
) -> Result<Vec<lsp::CodeLens>, AnyError> { ) -> Result<Vec<lsp::CodeLens>, AnyError> {
let mut code_lenses = collect_test(specifier, parsed_source, config)?; let mut collector =
code_lenses.extend( DenoTestCollector::new(specifier.clone(), parsed_source.clone());
collect_tsc( parsed_source.module().visit_with(&mut collector);
specifier, Ok(collector.take())
config.workspace_settings(),
line_index,
navigation_tree,
)
.await?,
);
Ok(code_lenses)
}
fn collect_test(
specifier: &ModuleSpecifier,
parsed_source: Option<ParsedSource>,
config: &Config,
) -> Result<Vec<lsp::CodeLens>, AnyError> {
if config.specifier_enabled_for_test(specifier)
&& config.enabled_code_lens_test_for_specifier(specifier)
{
if let Some(parsed_source) = parsed_source {
let mut collector =
DenoTestCollector::new(specifier.clone(), parsed_source.clone());
parsed_source.module().visit_with(&mut collector);
return Ok(collector.take());
}
}
Ok(Vec::new())
} }
/// Return tsc navigation tree code lenses. /// Return tsc navigation tree code lenses.
async fn collect_tsc( pub async fn collect_tsc(
specifier: &ModuleSpecifier, specifier: &ModuleSpecifier,
workspace_settings: &WorkspaceSettings, code_lens_settings: &CodeLensSettings,
line_index: Arc<LineIndex>, line_index: Arc<LineIndex>,
navigation_tree: &NavigationTree, navigation_tree: &NavigationTree,
) -> Result<Vec<lsp::CodeLens>, AnyError> { ) -> Result<Vec<lsp::CodeLens>, AnyError> {
if !workspace_settings.code_lens.implementations
&& !workspace_settings.code_lens.references
{
return Ok(vec![]);
}
let code_lenses = Rc::new(RefCell::new(Vec::new())); let code_lenses = Rc::new(RefCell::new(Vec::new()));
navigation_tree.walk(&|i, mp| { navigation_tree.walk(&|i, mp| {
let mut code_lenses = code_lenses.borrow_mut(); let mut code_lenses = code_lenses.borrow_mut();
// TSC Implementations Code Lens // TSC Implementations Code Lens
if workspace_settings.code_lens.implementations { if code_lens_settings.implementations {
let source = CodeLensSource::Implementations; let source = CodeLensSource::Implementations;
match i.kind { match i.kind {
tsc::ScriptElementKind::InterfaceElement => { tsc::ScriptElementKind::InterfaceElement => {
@ -465,7 +430,7 @@ async fn collect_tsc(
} }
// TSC References Code Lens // TSC References Code Lens
if workspace_settings.code_lens.references { if code_lens_settings.references {
let source = CodeLensSource::References; let source = CodeLensSource::References;
if let Some(parent) = &mp { if let Some(parent) = &mp {
if parent.kind == tsc::ScriptElementKind::EnumElement { if parent.kind == tsc::ScriptElementKind::EnumElement {
@ -478,7 +443,7 @@ async fn collect_tsc(
} }
match i.kind { match i.kind {
tsc::ScriptElementKind::FunctionElement => { tsc::ScriptElementKind::FunctionElement => {
if workspace_settings.code_lens.references_all_functions { if code_lens_settings.references_all_functions {
code_lenses.push(i.to_code_lens( code_lenses.push(i.to_code_lens(
line_index.clone(), line_index.clone(),
specifier, specifier,

View file

@ -898,26 +898,6 @@ impl Config {
|| settings.inlay_hints.enum_member_values.enabled || settings.inlay_hints.enum_member_values.enabled
} }
/// Determine if any code lenses are enabled at all. This allows short
/// circuiting when there are no code lenses enabled.
pub fn enabled_code_lens_for_specifier(
&self,
specifier: &ModuleSpecifier,
) -> bool {
let settings = self.workspace_settings_for_specifier(specifier);
settings.code_lens.implementations
|| settings.code_lens.references
|| settings.code_lens.test
}
pub fn enabled_code_lens_test_for_specifier(
&self,
specifier: &ModuleSpecifier,
) -> bool {
let settings = self.workspace_settings_for_specifier(specifier);
settings.code_lens.test
}
pub fn root_uri(&self) -> Option<&Url> { pub fn root_uri(&self) -> Option<&Url> {
self.workspace_folders.get(0).map(|p| &p.0) self.workspace_folders.get(0).map(|p| &p.0)
} }

View file

@ -2147,34 +2147,60 @@ impl Inner {
.normalize_url(&params.text_document.uri, LspUrlKind::File); .normalize_url(&params.text_document.uri, LspUrlKind::File);
if !self.is_diagnosable(&specifier) if !self.is_diagnosable(&specifier)
|| !self.config.specifier_enabled(&specifier) || !self.config.specifier_enabled(&specifier)
|| !self.config.enabled_code_lens_for_specifier(&specifier)
{ {
return Ok(None); return Ok(None);
} }
let mark = self.performance.mark("code_lens", Some(&params)); let mark = self.performance.mark("code_lens", Some(&params));
let asset_or_doc = self.get_asset_or_document(&specifier)?; let asset_or_doc = self.get_asset_or_document(&specifier)?;
let navigation_tree = let settings = self.config.workspace_settings_for_specifier(&specifier);
self.get_navigation_tree(&specifier).await.map_err(|err| { let mut code_lenses = Vec::new();
error!("Error getting code lenses for \"{}\": {}", specifier, err); if settings.code_lens.test
LspError::internal_error() && self.config.specifier_enabled_for_test(&specifier)
})?; {
let parsed_source = asset_or_doc.maybe_parsed_source().and_then(|r| r.ok()); if let Some(Ok(parsed_source)) = asset_or_doc.maybe_parsed_source() {
let line_index = asset_or_doc.line_index(); code_lenses.extend(
let code_lenses = code_lens::collect( code_lens::collect_test(&specifier, parsed_source).map_err(
&specifier, |err| {
parsed_source, error!(
&self.config, "Error getting test code lenses for \"{}\": {}",
line_index, &specifier, err
&navigation_tree, );
) LspError::internal_error()
.await },
.map_err(|err| { )?,
error!("Error getting code lenses for \"{}\": {}", specifier, err); );
LspError::internal_error() }
})?; }
if settings.code_lens.implementations || settings.code_lens.references {
let navigation_tree =
self.get_navigation_tree(&specifier).await.map_err(|err| {
error!("Error getting code lenses for \"{}\": {}", specifier, err);
LspError::internal_error()
})?;
let line_index = asset_or_doc.line_index();
code_lenses.extend(
code_lens::collect_tsc(
&specifier,
&settings.code_lens,
line_index,
&navigation_tree,
)
.await
.map_err(|err| {
error!(
"Error getting ts code lenses for \"{}\": {}",
&specifier, err
);
LspError::internal_error()
})?,
);
}
self.performance.measure(mark); self.performance.measure(mark);
if code_lenses.is_empty() {
return Ok(None);
}
Ok(Some(code_lenses)) Ok(Some(code_lenses))
} }