summaryrefslogtreecommitdiff
path: root/cli/lsp/language_server.rs
diff options
context:
space:
mode:
authorNayeem Rahman <nayeemrmn99@gmail.com>2023-09-08 00:50:34 +0100
committerGitHub <noreply@github.com>2023-09-08 00:50:34 +0100
commit4a11603c76b13ecf92ce3141ec317a42ae9f8d1d (patch)
tree00718c6131da9cd353335731ea78e37ca5ce5e92 /cli/lsp/language_server.rs
parent9d6584c16f8c759f321ab82a3b9d03d0e2e1d363 (diff)
refactor(lsp): clean up "enablePaths" handling (#20388)
Previously we pre-computed enabled paths into `Config::enabled_paths`, and had to keep updating it. Now we determine enabled paths directly from `Config::settings` on demand as a single source of truth. Removes `Config::root_uri`. If `InitializeParams::rootUri` is given, and it doesn't correspond to a folder in `InitializeParams::workspaceFolders`, prepend it to `Config::workspace_folders` as a mocked folder. Includes groundwork for https://github.com/denoland/vscode_deno/issues/908. In a minor version cycle or two we can fix that in vscode_deno, and it won't break for Deno versions post this patch due to the corrected deserialization logic for `enablePaths`.
Diffstat (limited to 'cli/lsp/language_server.rs')
-rw-r--r--cli/lsp/language_server.rs144
1 files changed, 67 insertions, 77 deletions
diff --git a/cli/lsp/language_server.rs b/cli/lsp/language_server.rs
index a893308ae..3b19d9288 100644
--- a/cli/lsp/language_server.rs
+++ b/cli/lsp/language_server.rs
@@ -403,48 +403,33 @@ impl LanguageServer {
}
pub async fn refresh_specifiers_from_client(&self) -> bool {
- let (client, specifiers) =
+ let (client, specifiers) = {
+ let ls = self.0.read().await;
+ let specifiers = if ls.config.client_capabilities.workspace_configuration
{
- let ls = self.0.read().await;
- let specifiers =
- if ls.config.client_capabilities.workspace_configuration {
- let root_capacity = match &ls.config.workspace_folders {
- Some(folder) => folder.len(),
- None => 1,
- };
- let config_specifiers = ls.config.get_specifiers();
- let mut specifiers =
- HashMap::with_capacity(root_capacity + config_specifiers.len());
- match &ls.config.workspace_folders {
- Some(entry) => {
- for (specifier, folder) in entry {
- specifiers.insert(
- specifier.clone(),
- LspClientUrl::new(folder.uri.clone()),
- );
- }
- }
- None => {
- if let Some(root_uri) = &ls.config.root_uri {
- specifiers.insert(
- root_uri.clone(),
- ls.url_map.normalize_specifier(root_uri).unwrap(),
- );
- }
- }
- }
- specifiers.extend(ls.config.get_specifiers().iter().map(|s| {
- (s.clone(), ls.url_map.normalize_specifier(s).unwrap())
- }));
-
- Some(specifiers.into_iter().collect::<Vec<_>>())
- } else {
- None
- };
+ let root_capacity = std::cmp::max(ls.config.workspace_folders.len(), 1);
+ let config_specifiers = ls.config.get_specifiers();
+ let mut specifiers =
+ HashMap::with_capacity(root_capacity + config_specifiers.len());
+ for (specifier, folder) in &ls.config.workspace_folders {
+ specifiers
+ .insert(specifier.clone(), LspClientUrl::new(folder.uri.clone()));
+ }
+ specifiers.extend(
+ ls.config
+ .get_specifiers()
+ .iter()
+ .map(|s| (s.clone(), ls.url_map.normalize_specifier(s).unwrap())),
+ );
- (ls.client.clone(), specifiers)
+ Some(specifiers.into_iter().collect::<Vec<_>>())
+ } else {
+ None
};
+ (ls.client.clone(), specifiers)
+ };
+
let mut touched = false;
if let Some(specifiers) = specifiers {
let configs_result = client
@@ -477,10 +462,6 @@ impl LanguageServer {
}
}
}
-
- if ls.config.update_enabled_paths() {
- touched = true;
- }
}
touched
}
@@ -701,7 +682,7 @@ impl Inner {
lsp_log!("Setting Deno configuration from: \"{}\"", config_str);
let config_url = if let Ok(url) = Url::from_file_path(config_str) {
Ok(url)
- } else if let Some(root_uri) = &self.config.root_uri {
+ } else if let Some(root_uri) = self.config.root_uri() {
root_uri.join(config_str).map_err(|_| {
anyhow!("Bad file path for configuration file: \"{}\"", config_str)
})
@@ -723,7 +704,7 @@ impl Inner {
// It is possible that root_uri is not set, for example when having a single
// file open and not a workspace. In those situations we can't
// automatically discover the configuration
- if let Some(root_uri) = &self.config.root_uri {
+ if let Some(root_uri) = self.config.root_uri() {
let root_path = specifier_to_file_path(root_uri)?;
let mut checked = std::collections::HashSet::new();
let maybe_config = ConfigFile::discover_from(&root_path, &mut checked)?;
@@ -747,7 +728,7 @@ impl Inner {
// It is possible that root_uri is not set, for example when having a single
// file open and not a workspace. In those situations we can't
// automatically discover the configuration
- if let Some(root_uri) = &self.config.root_uri {
+ if let Some(root_uri) = self.config.root_uri() {
let root_path = specifier_to_file_path(root_uri)?;
let maybe_package_json = package_json::discover_from(
&root_path,
@@ -846,7 +827,7 @@ impl Inner {
lsp_log!("Setting global 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) = &self.config.root_uri {
+ } else if let Some(root_uri) = self.config.root_uri() {
let root_path = specifier_to_file_path(root_uri)?;
let cache_path = root_path.join(cache_str);
Url::from_file_path(cache_path).map_err(|_| {
@@ -892,8 +873,7 @@ impl Inner {
let workspace_settings = self.config.workspace_settings();
let maybe_root_path = self
.config
- .root_uri
- .as_ref()
+ .root_uri()
.and_then(|uri| specifier_to_file_path(uri).ok());
let root_cert_store = get_root_cert_store(
maybe_root_path,
@@ -1074,7 +1054,7 @@ impl Inner {
anyhow!("Bad data url for import map: {}", import_map_str)
})?;
Some(import_map_url)
- } else if let Some(root_uri) = &self.config.root_uri {
+ } else if let Some(root_uri) = self.config.root_uri() {
let root_path = specifier_to_file_path(root_uri)?;
let import_map_path = root_path.join(&import_map_str);
let import_map_url =
@@ -1282,20 +1262,14 @@ impl Inner {
}
{
- // sometimes this root uri may not have a trailing slash, so force it to
- self.config.root_uri = params
- .root_uri
- .map(|s| self.url_map.normalize_url(&s, LspUrlKind::Folder));
-
if let Some(value) = params.initialization_options {
self.config.set_workspace_settings(value).map_err(|err| {
error!("Cannot set workspace settings: {}", err);
LspError::internal_error()
})?;
- self.config.update_enabled_paths();
}
- self.config.workspace_folders = params.workspace_folders.map(|folders| {
- folders
+ if let Some(folders) = params.workspace_folders {
+ self.config.workspace_folders = folders
.into_iter()
.map(|folder| {
(
@@ -1303,8 +1277,31 @@ impl Inner {
folder,
)
})
- .collect()
- });
+ .collect();
+ }
+ // rootUri is deprecated by the LSP spec. If it's specified, merge it into
+ // workspace_folders.
+ if let Some(root_uri) = params.root_uri {
+ if !self
+ .config
+ .workspace_folders
+ .iter()
+ .any(|(_, f)| f.uri == root_uri)
+ {
+ let name = root_uri.path_segments().and_then(|s| s.last());
+ let name = name.unwrap_or_default().to_string();
+ self.config.workspace_folders.insert(
+ 0,
+ (
+ self.url_map.normalize_url(&root_uri, LspUrlKind::Folder),
+ WorkspaceFolder {
+ uri: root_uri,
+ name,
+ },
+ ),
+ );
+ }
+ }
self.config.update_capabilities(&params.capabilities);
}
@@ -1489,7 +1486,6 @@ impl Inner {
if let Err(err) = self.config.set_workspace_settings(value) {
error!("failed to update settings: {}", err);
}
- self.config.update_enabled_paths();
}
self.update_debug_flag();
@@ -1656,18 +1652,16 @@ impl Inner {
)
})
.collect::<Vec<(ModuleSpecifier, WorkspaceFolder)>>();
- if let Some(current_folders) = &self.config.workspace_folders {
- for (specifier, folder) in current_folders {
- if !params.event.removed.is_empty()
- && params.event.removed.iter().any(|f| f.uri == folder.uri)
- {
- continue;
- }
- workspace_folders.push((specifier.clone(), folder.clone()));
+ for (specifier, folder) in &self.config.workspace_folders {
+ if !params.event.removed.is_empty()
+ && params.event.removed.iter().any(|f| f.uri == folder.uri)
+ {
+ continue;
}
+ workspace_folders.push((specifier.clone(), folder.clone()));
}
- self.config.workspace_folders = Some(workspace_folders);
+ self.config.workspace_folders = workspace_folders;
}
async fn document_symbol(
@@ -2627,8 +2621,7 @@ impl Inner {
let maybe_root_path_owned = self
.config
- .root_uri
- .as_ref()
+ .root_uri()
.and_then(|uri| specifier_to_file_path(uri).ok());
let mut resolved_items = Vec::<CallHierarchyIncomingCall>::new();
for item in incoming_calls.iter() {
@@ -2671,8 +2664,7 @@ impl Inner {
let maybe_root_path_owned = self
.config
- .root_uri
- .as_ref()
+ .root_uri()
.and_then(|uri| specifier_to_file_path(uri).ok());
let mut resolved_items = Vec::<CallHierarchyOutgoingCall>::new();
for item in outgoing_calls.iter() {
@@ -2720,8 +2712,7 @@ 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()
+ .root_uri()
.and_then(|uri| specifier_to_file_path(uri).ok());
let mut resolved_items = Vec::<CallHierarchyItem>::new();
match one_or_many {
@@ -3131,7 +3122,7 @@ impl tower_lsp::LanguageServer for LanguageServer {
let test_server = testing::TestServer::new(
ls.client.clone(),
ls.performance.clone(),
- ls.config.root_uri.clone(),
+ ls.config.root_uri().cloned(),
);
ls.maybe_testing_server = Some(test_server);
}
@@ -3208,7 +3199,6 @@ impl tower_lsp::LanguageServer for LanguageServer {
Ok(specifier_settings) => {
ls.config
.set_specifier_settings(specifier.clone(), specifier_settings);
- ls.config.update_enabled_paths();
}
Err(err) => {
error!("{}", err);