summaryrefslogtreecommitdiff
path: root/cli/lsp/language_server.rs
diff options
context:
space:
mode:
authorDavid Sherret <dsherret@users.noreply.github.com>2022-01-19 17:10:14 -0500
committerGitHub <noreply@github.com>2022-01-19 17:10:14 -0500
commitf73a5fbc89c1e1255ae886b1dfe23329d7ad8713 (patch)
tree9e5054ef3ff6ef2ba3d55283ca8b6ec6cdb764de /cli/lsp/language_server.rs
parent6cf05220e3370365a2c6ce8116d1c5624004ca59 (diff)
refactor(lsp): reduce data stored in `StateSnapshot` (#13426)
Diffstat (limited to 'cli/lsp/language_server.rs')
-rw-r--r--cli/lsp/language_server.rs155
1 files changed, 62 insertions, 93 deletions
diff --git a/cli/lsp/language_server.rs b/cli/lsp/language_server.rs
index be4b23ff7..e33ffc93a 100644
--- a/cli/lsp/language_server.rs
+++ b/cli/lsp/language_server.rs
@@ -74,15 +74,12 @@ const CACHE_PATH: &str = "deps";
#[derive(Debug, Clone)]
pub struct LanguageServer(Arc<tokio::sync::Mutex<Inner>>);
+/// Snapshot of the state used by TSC.
#[derive(Debug, Default)]
pub(crate) struct StateSnapshot {
pub assets: AssetsSnapshot,
- pub config: ConfigSnapshot,
pub documents: Documents,
- pub maybe_lint_config: Option<LintConfig>,
- pub maybe_fmt_config: Option<FmtConfig>,
- pub module_registries: registries::ModuleRegistry,
- pub url_map: urls::LspUrlMap,
+ pub root_uri: Option<Url>,
}
#[derive(Debug)]
@@ -97,7 +94,7 @@ pub(crate) struct Inner {
diagnostics_server: diagnostics::DiagnosticsServer,
/// The collection of documents that the server is currently handling, either
/// on disk or "open" within the client.
- documents: Documents,
+ pub(crate) documents: Documents,
/// Handles module registries, which allow discovery of modules
module_registries: registries::ModuleRegistry,
/// The path to the module registries cache
@@ -111,7 +108,7 @@ pub(crate) struct Inner {
/// options.
maybe_config_file: Option<ConfigFile>,
/// An optional configuration for linter which has been taken from specified config file.
- maybe_lint_config: Option<LintConfig>,
+ pub(crate) maybe_lint_config: Option<LintConfig>,
/// An optional configuration for formatter which has been taken from specified config file.
maybe_fmt_config: Option<FmtConfig>,
/// An optional import map which is used to resolve modules.
@@ -120,6 +117,8 @@ pub(crate) struct Inner {
maybe_import_map_uri: Option<Url>,
/// A collection of measurements which instrument that performance of the LSP.
performance: Arc<Performance>,
+ /// Root provided by the initialization parameters.
+ root_uri: Option<Url>,
/// A memoized version of fixable diagnostic codes retrieved from TypeScript.
ts_fixable_diagnostics: Vec<String>,
/// An abstraction that handles interactions with TypeScript.
@@ -169,6 +168,7 @@ impl Inner {
maybe_import_map_uri: None,
module_registries,
module_registries_location,
+ root_uri: None,
performance,
ts_fixable_diagnostics: Default::default(),
ts_server,
@@ -248,12 +248,8 @@ impl Inner {
self
.assets
.get_cached(specifier)
- .map(|maybe_asset| {
- maybe_asset
- .as_ref()
- .map(|asset| AssetOrDocument::Asset(asset.clone()))
- })
.flatten()
+ .map(AssetOrDocument::Asset)
} else {
self.documents.get(specifier).map(AssetOrDocument::Document)
}
@@ -275,7 +271,7 @@ impl Inner {
let navigation_tree: tsc::NavigationTree = self
.ts_server
.request(
- self.snapshot()?,
+ self.snapshot(),
tsc::RequestMethod::GetNavigationTree(specifier.clone()),
)
.await?;
@@ -302,7 +298,7 @@ impl Inner {
/// If there's no config file specified in settings returns `None`.
fn get_config_file(&self) -> Result<Option<ConfigFile>, AnyError> {
let workspace_settings = self.config.get_workspace_settings();
- let maybe_root_uri = self.config.root_uri.clone();
+ let maybe_root_uri = self.root_uri.clone();
let maybe_config = workspace_settings.config;
if let Some(config_str) = &maybe_config {
if !config_str.is_empty() {
@@ -387,39 +383,24 @@ impl Inner {
Ok(())
}
- pub(crate) fn snapshot(&self) -> LspResult<Arc<StateSnapshot>> {
- Ok(Arc::new(StateSnapshot {
+ pub(crate) fn snapshot(&self) -> Arc<StateSnapshot> {
+ Arc::new(StateSnapshot {
assets: self.assets.snapshot(),
- config: self.config.snapshot().map_err(|err| {
- error!("{}", err);
- LspError::internal_error()
- })?,
documents: self.documents.clone(),
- maybe_lint_config: self.maybe_lint_config.clone(),
- maybe_fmt_config: self.maybe_fmt_config.clone(),
- module_registries: self.module_registries.clone(),
- // it's ok to get an Arc to the url map because the url_map is a cache
- // that does not change once the mapping for a specifier is set
- url_map: self.url_map.clone(),
- }))
+ root_uri: self.root_uri.clone(),
+ })
}
pub fn update_cache(&mut self) -> Result<(), AnyError> {
let mark = self.performance.mark("update_cache", None::<()>);
self.performance.measure(mark);
self.maybe_cache_server = None;
- let (maybe_cache, maybe_root_uri) = {
- let config = &self.config;
- (
- config.get_workspace_settings().cache,
- config.root_uri.clone(),
- )
- };
+ let maybe_cache = self.config.get_workspace_settings().cache;
let maybe_cache_path = if let Some(cache_str) = &maybe_cache {
lsp_log!("Setting cache path from: \"{}\"", cache_str);
let cache_url = if let Ok(url) = Url::from_file_path(cache_str) {
Ok(url)
- } else if let Some(root_uri) = &maybe_root_uri {
+ } else if let Some(root_uri) = &self.root_uri {
let root_path = fs_util::specifier_to_file_path(root_uri)?;
let cache_path = root_path.join(cache_str);
Url::from_file_path(cache_path).map_err(|_| {
@@ -459,13 +440,7 @@ impl Inner {
pub async fn update_import_map(&mut self) -> Result<(), AnyError> {
let mark = self.performance.mark("update_import_map", None::<()>);
self.maybe_cache_server = None;
- let (maybe_import_map, maybe_root_uri) = {
- let config = &self.config;
- (
- config.get_workspace_settings().import_map,
- config.root_uri.clone(),
- )
- };
+ let maybe_import_map = self.config.get_workspace_settings().import_map;
if let Some(import_map_str) = &maybe_import_map {
lsp_log!("Setting import map from: \"{}\"", import_map_str);
let import_map_url = if let Ok(url) = Url::from_file_path(import_map_str)
@@ -475,7 +450,7 @@ impl Inner {
Url::parse(import_map_str).map_err(|_| {
anyhow!("Bad data url for import map: {:?}", import_map_str)
})
- } else if let Some(root_uri) = &maybe_root_uri {
+ } else if let Some(root_uri) = &self.root_uri {
let root_path = fs_util::specifier_to_file_path(root_uri)?;
let import_map_path = root_path.join(import_map_str);
Url::from_file_path(import_map_path).map_err(|_| {
@@ -598,7 +573,7 @@ impl Inner {
}
let _ok: bool = self
.ts_server
- .request(self.snapshot()?, tsc::RequestMethod::Configure(tsconfig))
+ .request(self.snapshot(), tsc::RequestMethod::Configure(tsconfig))
.await?;
self.performance.measure(mark);
Ok(())
@@ -646,20 +621,19 @@ impl Inner {
}
{
- let config = &mut self.config;
// sometimes this root uri may not have a trailing slash, so force it to
- config.root_uri = params
+ self.root_uri = params
.root_uri
.map(|s| self.url_map.normalize_url(&s))
.map(fs_util::ensure_directory_specifier);
if let Some(value) = params.initialization_options {
- config.set_workspace_settings(value).map_err(|err| {
+ self.config.set_workspace_settings(value).map_err(|err| {
error!("Cannot set workspace settings: {}", err);
LspError::internal_error()
})?;
}
- config.update_capabilities(&params.capabilities);
+ self.config.update_capabilities(&params.capabilities);
}
self.update_debug_flag();
@@ -677,7 +651,7 @@ impl Inner {
if capabilities.code_action_provider.is_some() {
let fixable_diagnostics: Vec<String> = self
.ts_server
- .request(self.snapshot()?, tsc::RequestMethod::GetSupportedCodeFixes)
+ .request(self.snapshot(), tsc::RequestMethod::GetSupportedCodeFixes)
.await
.map_err(|err| {
error!("Unable to get fixable diagnostics: {}", err);
@@ -1136,7 +1110,7 @@ impl Inner {
));
let maybe_quick_info: Option<tsc::QuickInfo> = self
.ts_server
- .request(self.snapshot()?, req)
+ .request(self.snapshot(), req)
.await
.map_err(|err| {
error!("Unable to get quick info: {}", err);
@@ -1216,7 +1190,7 @@ impl Inner {
codes,
));
let actions: Vec<tsc::CodeFixAction> =
- match self.ts_server.request(self.snapshot()?, req).await {
+ match self.ts_server.request(self.snapshot(), req).await {
Ok(items) => items,
Err(err) => {
// sometimes tsc reports errors when retrieving code actions
@@ -1289,7 +1263,7 @@ impl Inner {
));
let refactor_infos: Vec<tsc::ApplicableRefactorInfo> = self
.ts_server
- .request(self.snapshot()?, req)
+ .request(self.snapshot(), req)
.await
.map_err(|err| {
error!("Failed to request to tsserver {}", err);
@@ -1336,6 +1310,7 @@ impl Inner {
let result = if kind.as_str().starts_with(CodeActionKind::QUICKFIX.as_str())
{
+ let snapshot = self.snapshot();
let code_action_data: CodeActionData =
from_value(data).map_err(|err| {
error!("Unable to decode code action data: {}", err);
@@ -1347,7 +1322,7 @@ impl Inner {
));
let combined_code_actions: tsc::CombinedCodeActions = self
.ts_server
- .request(self.snapshot()?, req)
+ .request(snapshot.clone(), req)
.await
.map_err(|err| {
error!("Unable to get combined fix from TypeScript: {}", err);
@@ -1362,7 +1337,7 @@ impl Inner {
fix_ts_import_changes(
&code_action_data.specifier,
&combined_code_actions.changes,
- self,
+ &self.documents,
)
.map_err(|err| {
error!("Unable to remap changes: {}", err);
@@ -1379,6 +1354,7 @@ impl Inner {
})?;
code_action
} else if kind.as_str().starts_with(CodeActionKind::REFACTOR.as_str()) {
+ let snapshot = self.snapshot();
let mut code_action = params.clone();
let action_data: refactor::RefactorCodeActionData = from_value(data)
.map_err(|err| {
@@ -1396,11 +1372,8 @@ impl Inner {
action_data.refactor_name.clone(),
action_data.action_name.clone(),
));
- let refactor_edit_info: tsc::RefactorEditInfo = self
- .ts_server
- .request(self.snapshot()?, req)
- .await
- .map_err(|err| {
+ let refactor_edit_info: tsc::RefactorEditInfo =
+ self.ts_server.request(snapshot, req).await.map_err(|err| {
error!("Failed to request to tsserver {}", err);
LspError::invalid_request()
})?;
@@ -1506,7 +1479,7 @@ impl Inner {
));
let maybe_document_highlights: Option<Vec<tsc::DocumentHighlights>> = self
.ts_server
- .request(self.snapshot()?, req)
+ .request(self.snapshot(), req)
.await
.map_err(|err| {
error!("Unable to get document highlights from TypeScript: {}", err);
@@ -1549,7 +1522,7 @@ impl Inner {
));
let maybe_references: Option<Vec<tsc::ReferenceEntry>> = self
.ts_server
- .request(self.snapshot()?, req)
+ .request(self.snapshot(), req)
.await
.map_err(|err| {
error!("Unable to get references from TypeScript: {}", err);
@@ -1571,7 +1544,8 @@ impl Inner {
self.get_asset_or_document(&reference_specifier).await?;
asset_or_doc.line_index()
};
- results.push(reference.to_location(reference_line_index, self));
+ results
+ .push(reference.to_location(reference_line_index, &self.url_map));
}
self.performance.measure(mark);
@@ -1604,7 +1578,7 @@ impl Inner {
));
let maybe_definition: Option<tsc::DefinitionInfoAndBoundSpan> = self
.ts_server
- .request(self.snapshot()?, req)
+ .request(self.snapshot(), req)
.await
.map_err(|err| {
error!("Unable to get definition from TypeScript: {}", err);
@@ -1644,7 +1618,7 @@ impl Inner {
};
let maybe_definition_info: Option<Vec<tsc::DefinitionInfo>> = self
.ts_server
- .request(self.snapshot()?, req)
+ .request(self.snapshot(), req)
.await
.map_err(|err| {
error!("Unable to get type definition from TypeScript: {}", err);
@@ -1688,12 +1662,13 @@ impl Inner {
// completions, we will use internal logic and if there are completions
// for imports, we will return those and not send a message into tsc, where
// other completions come from.
- let snapshot = self.snapshot()?;
let response = if let Some(response) = completions::get_import_completions(
&specifier,
&params.text_document_position.position,
- &snapshot,
+ &self.config.snapshot(),
self.client.clone(),
+ &self.module_registries,
+ &self.documents,
)
.await
{
@@ -1722,11 +1697,9 @@ impl Inner {
trigger_character,
},
));
- let maybe_completion_info: Option<tsc::CompletionInfo> = self
- .ts_server
- .request(self.snapshot()?, req)
- .await
- .map_err(|err| {
+ let snapshot = self.snapshot();
+ let maybe_completion_info: Option<tsc::CompletionInfo> =
+ self.ts_server.request(snapshot, req).await.map_err(|err| {
error!("Unable to get completion info from TypeScript: {}", err);
LspError::internal_error()
})?;
@@ -1762,14 +1735,13 @@ impl Inner {
})?;
if let Some(data) = data.tsc {
let req = tsc::RequestMethod::GetCompletionDetails(data.into());
- let maybe_completion_info: Option<tsc::CompletionEntryDetails> = self
- .ts_server
- .request(self.snapshot()?, req)
- .await
- .map_err(|err| {
- error!("Unable to get completion info from TypeScript: {}", err);
- LspError::internal_error()
- })?;
+ let maybe_completion_info: Option<tsc::CompletionEntryDetails> =
+ self.ts_server.request(self.snapshot(), req).await.map_err(
+ |err| {
+ error!("Unable to get completion info from TypeScript: {}", err);
+ LspError::internal_error()
+ },
+ )?;
if let Some(completion_info) = maybe_completion_info {
completion_info.as_completion_item(&params)
} else {
@@ -1817,7 +1789,7 @@ impl Inner {
));
let maybe_implementations: Option<Vec<tsc::ImplementationLocation>> = self
.ts_server
- .request(self.snapshot()?, req)
+ .request(self.snapshot(), req)
.await
.map_err(|err| {
error!("Failed to request to tsserver {}", err);
@@ -1859,7 +1831,7 @@ impl Inner {
let req = tsc::RequestMethod::GetOutliningSpans(specifier.clone());
let outlining_spans: Vec<tsc::OutliningSpan> = self
.ts_server
- .request(self.snapshot()?, req)
+ .request(self.snapshot(), req)
.await
.map_err(|err| {
error!("Failed to request to tsserver {}", err);
@@ -1907,7 +1879,7 @@ impl Inner {
));
let incoming_calls: Vec<tsc::CallHierarchyIncomingCall> = self
.ts_server
- .request(self.snapshot()?, req)
+ .request(self.snapshot(), req)
.await
.map_err(|err| {
error!("Failed to request to tsserver {}", err);
@@ -1915,7 +1887,6 @@ impl Inner {
})?;
let maybe_root_path_owned = self
- .config
.root_uri
.as_ref()
.and_then(|uri| fs_util::specifier_to_file_path(uri).ok());
@@ -1956,7 +1927,7 @@ impl Inner {
));
let outgoing_calls: Vec<tsc::CallHierarchyOutgoingCall> = self
.ts_server
- .request(self.snapshot()?, req)
+ .request(self.snapshot(), req)
.await
.map_err(|err| {
error!("Failed to request to tsserver {}", err);
@@ -1964,7 +1935,6 @@ impl Inner {
})?;
let maybe_root_path_owned = self
- .config
.root_uri
.as_ref()
.and_then(|uri| fs_util::specifier_to_file_path(uri).ok());
@@ -2011,7 +1981,7 @@ impl Inner {
let maybe_one_or_many: Option<tsc::OneOrMany<tsc::CallHierarchyItem>> =
self
.ts_server
- .request(self.snapshot()?, req)
+ .request(self.snapshot(), req)
.await
.map_err(|err| {
error!("Failed to request to tsserver {}", err);
@@ -2020,7 +1990,6 @@ impl Inner {
let response = if let Some(one_or_many) = maybe_one_or_many {
let maybe_root_path_owned = self
- .config
.root_uri
.as_ref()
.and_then(|uri| fs_util::specifier_to_file_path(uri).ok());
@@ -2087,7 +2056,7 @@ impl Inner {
let maybe_locations: Option<Vec<tsc::RenameLocation>> = self
.ts_server
- .request(self.snapshot()?, req)
+ .request(self.snapshot(), req)
.await
.map_err(|err| {
error!("Failed to request to tsserver {}", err);
@@ -2173,7 +2142,7 @@ impl Inner {
let selection_range: tsc::SelectionRange = self
.ts_server
- .request(self.snapshot()?, req)
+ .request(self.snapshot(), req)
.await
.map_err(|err| {
error!("Failed to request to tsserver {}", err);
@@ -2211,7 +2180,7 @@ impl Inner {
));
let semantic_classification: tsc::Classifications = self
.ts_server
- .request(self.snapshot()?, req)
+ .request(self.snapshot(), req)
.await
.map_err(|err| {
error!("Failed to request to tsserver {}", err);
@@ -2254,7 +2223,7 @@ impl Inner {
));
let semantic_classification: tsc::Classifications = self
.ts_server
- .request(self.snapshot()?, req)
+ .request(self.snapshot(), req)
.await
.map_err(|err| {
error!("Failed to request to tsserver {}", err);
@@ -2307,7 +2276,7 @@ impl Inner {
));
let maybe_signature_help_items: Option<tsc::SignatureHelpItems> = self
.ts_server
- .request(self.snapshot()?, req)
+ .request(self.snapshot(), req)
.await
.map_err(|err| {
error!("Failed to request to tsserver: {}", err);
@@ -2339,7 +2308,7 @@ impl Inner {
let navigate_to_items: Vec<tsc::NavigateToItem> = self
.ts_server
- .request(self.snapshot()?, req)
+ .request(self.snapshot(), req)
.await
.map_err(|err| {
error!("Failed request to tsserver: {}", err);