summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cli/lsp/config.rs330
-rw-r--r--cli/lsp/diagnostics.rs10
-rw-r--r--cli/lsp/language_server.rs144
-rw-r--r--cli/lsp/repl.rs2
-rw-r--r--test_util/src/lsp.rs15
5 files changed, 241 insertions, 260 deletions
diff --git a/cli/lsp/config.rs b/cli/lsp/config.rs
index 4aafe0238..c00d453b3 100644
--- a/cli/lsp/config.rs
+++ b/cli/lsp/config.rs
@@ -239,7 +239,8 @@ pub struct SpecifierSettings {
pub enable: Option<bool>,
/// A list of paths, using the workspace folder as a base that should be Deno
/// enabled.
- pub enable_paths: Option<Vec<String>>,
+ #[serde(default)]
+ pub enable_paths: Vec<String>,
/// Code lens specific settings for the resource.
#[serde(default)]
pub code_lens: CodeLensSpecifierSettings,
@@ -285,7 +286,8 @@ pub struct WorkspaceSettings {
pub enable: Option<bool>,
/// A list of paths, using the root_uri as a base that should be Deno enabled.
- pub enable_paths: Option<Vec<String>>,
+ #[serde(default)]
+ pub enable_paths: Vec<String>,
/// An option that points to a path string of the path to utilise as the
/// cache/DENO_DIR for the language server.
@@ -352,7 +354,7 @@ impl Default for WorkspaceSettings {
fn default() -> Self {
WorkspaceSettings {
enable: None,
- enable_paths: None,
+ enable_paths: vec![],
cache: None,
certificate_stores: None,
config: None,
@@ -395,21 +397,21 @@ impl WorkspaceSettings {
#[derive(Debug, Clone, Default)]
pub struct ConfigSnapshot {
pub client_capabilities: ClientCapabilities,
+ pub enabled_paths: HashMap<Url, Vec<Url>>,
pub excluded_paths: Option<Vec<Url>>,
pub has_config_file: bool,
pub settings: Settings,
- pub workspace_folders: Vec<(ModuleSpecifier, lsp::WorkspaceFolder)>,
}
impl ConfigSnapshot {
/// Determine if the provided specifier is enabled or not.
pub fn specifier_enabled(&self, specifier: &ModuleSpecifier) -> bool {
specifier_enabled(
- specifier,
- &self.settings,
+ &self.enabled_paths,
self.excluded_paths.as_ref(),
- &self.workspace_folders,
+ &self.settings,
self.has_config_file,
+ specifier,
)
}
}
@@ -441,8 +443,10 @@ struct LspConfigFileInfo {
#[derive(Debug)]
pub struct Config {
pub client_capabilities: ClientCapabilities,
+ enabled_paths: HashMap<Url, Vec<Url>>,
+ pub root_uri: Option<ModuleSpecifier>,
settings: Settings,
- pub workspace_folders: Vec<(ModuleSpecifier, lsp::WorkspaceFolder)>,
+ pub workspace_folders: Option<Vec<(ModuleSpecifier, lsp::WorkspaceFolder)>>,
/// An optional configuration file which has been specified in the client
/// options along with some data that is computed after the config file is set.
maybe_config_file_info: Option<LspConfigFileInfo>,
@@ -452,32 +456,15 @@ impl Config {
pub fn new() -> Self {
Self {
client_capabilities: ClientCapabilities::default(),
+ enabled_paths: Default::default(),
/// Root provided by the initialization parameters.
+ root_uri: None,
settings: Default::default(),
- workspace_folders: vec![],
+ workspace_folders: None,
maybe_config_file_info: None,
}
}
- #[cfg(test)]
- pub fn new_with_root(root_uri: Url) -> Self {
- let mut config = Self::new();
- let name = root_uri.path_segments().and_then(|s| s.last());
- let name = name.unwrap_or_default().to_string();
- config.workspace_folders = vec![(
- root_uri.clone(),
- lsp::WorkspaceFolder {
- uri: root_uri,
- name,
- },
- )];
- config
- }
-
- pub fn root_uri(&self) -> Option<&Url> {
- self.workspace_folders.get(0).map(|p| &p.0)
- }
-
pub fn maybe_node_modules_dir_path(&self) -> Option<&PathBuf> {
self
.maybe_config_file_info
@@ -582,24 +569,21 @@ impl Config {
&mut self,
value: Value,
) -> Result<(), AnyError> {
- self.settings.workspace = serde_json::from_value(value)?;
- // See https://github.com/denoland/vscode_deno/issues/908.
- if self.settings.workspace.enable_paths == Some(vec![]) {
- self.settings.workspace.enable_paths = None;
- }
+ let workspace_settings = serde_json::from_value(value)?;
+ self.settings.workspace = workspace_settings;
Ok(())
}
pub fn snapshot(&self) -> Arc<ConfigSnapshot> {
Arc::new(ConfigSnapshot {
client_capabilities: self.client_capabilities.clone(),
+ enabled_paths: self.enabled_paths.clone(),
excluded_paths: self
.maybe_config_file_info
.as_ref()
.map(|i| i.excluded_paths.clone()),
has_config_file: self.has_config_file(),
settings: self.settings.clone(),
- workspace_folders: self.workspace_folders.clone(),
})
}
@@ -607,16 +591,24 @@ impl Config {
self.settings.specifiers.contains_key(specifier)
}
+ pub fn enabled(&self) -> bool {
+ self
+ .settings
+ .workspace
+ .enable
+ .unwrap_or_else(|| self.has_config_file())
+ }
+
pub fn specifier_enabled(&self, specifier: &ModuleSpecifier) -> bool {
specifier_enabled(
- specifier,
- &self.settings,
+ &self.enabled_paths,
self
.maybe_config_file_info
.as_ref()
.map(|i| &i.excluded_paths),
- &self.workspace_folders,
+ &self.settings,
self.has_config_file(),
+ specifier,
)
}
@@ -626,31 +618,24 @@ impl Config {
/// WARNING: This may incorrectly have some directory urls as being
/// represented as file urls.
pub fn enabled_urls(&self) -> Vec<Url> {
- let mut urls = vec![];
- for (workspace_uri, _) in &self.workspace_folders {
- let specifier_settings = self.settings.specifiers.get(workspace_uri);
- let enable = specifier_settings
- .and_then(|s| s.enable)
- .or(self.settings.workspace.enable)
- .unwrap_or(self.has_config_file());
- let enable_paths = specifier_settings
- .and_then(|s| s.enable_paths.as_ref())
- .or(self.settings.workspace.enable_paths.as_ref());
- if let Some(enable_paths) = enable_paths {
- let Ok(scope_path) = specifier_to_file_path(workspace_uri) else {
- lsp_log!("Unable to convert uri \"{}\" to path.", workspace_uri);
- return vec![];
- };
- for path in enable_paths {
- let path = scope_path.join(path);
- let Ok(path_uri) = Url::from_file_path(&path) else {
- lsp_log!("Unable to convert path \"{}\" to uri.", path.display());
- continue;
- };
- urls.push(path_uri);
- }
- } else if enable {
- urls.push(workspace_uri.clone());
+ let mut urls: Vec<Url> = Vec::new();
+
+ if !self.enabled() && self.enabled_paths.is_empty() {
+ // do not return any urls when disabled
+ return urls;
+ }
+
+ for (workspace, enabled_paths) in &self.enabled_paths {
+ if !enabled_paths.is_empty() {
+ urls.extend(enabled_paths.iter().cloned());
+ } else {
+ urls.push(workspace.clone());
+ }
+ }
+
+ if urls.is_empty() {
+ if let Some(root_dir) = &self.root_uri {
+ urls.push(root_dir.clone())
}
}
@@ -722,6 +707,64 @@ impl Config {
}
}
+ /// Given the configured workspaces or root URI and the their settings,
+ /// update and resolve any paths that should be enabled
+ pub fn update_enabled_paths(&mut self) -> bool {
+ if let Some(workspace_folders) = self.workspace_folders.clone() {
+ let mut touched = false;
+ for (workspace, _) in workspace_folders {
+ let enabled_paths = match self.settings.specifiers.get(&workspace) {
+ Some(settings) => settings.enable_paths.clone(),
+ None => self.settings.workspace.enable_paths.clone(),
+ };
+ if self.update_enabled_paths_entry(workspace, enabled_paths) {
+ touched = true;
+ }
+ }
+ touched
+ } else if let Some(root_uri) = self.root_uri.clone() {
+ self.update_enabled_paths_entry(
+ root_uri,
+ self.settings.workspace.enable_paths.clone(),
+ )
+ } else {
+ false
+ }
+ }
+
+ /// Update a specific entry in the enabled paths for a given workspace.
+ fn update_enabled_paths_entry(
+ &mut self,
+ workspace: ModuleSpecifier,
+ enabled_paths: Vec<String>,
+ ) -> bool {
+ let mut touched = false;
+ if !enabled_paths.is_empty() {
+ if let Ok(workspace_path) = specifier_to_file_path(&workspace) {
+ let mut paths = Vec::new();
+ for path in &enabled_paths {
+ let fs_path = workspace_path.join(path);
+ match ModuleSpecifier::from_file_path(fs_path) {
+ Ok(path_uri) => {
+ paths.push(path_uri);
+ }
+ Err(_) => {
+ lsp_log!("Unable to resolve a file path for `deno.enablePath` from \"{}\" for workspace \"{}\".", path, workspace);
+ }
+ }
+ }
+ if !paths.is_empty() {
+ touched = true;
+ self.enabled_paths.insert(workspace.clone(), paths);
+ }
+ }
+ } else {
+ touched = true;
+ self.enabled_paths.remove(&workspace);
+ }
+ touched
+ }
+
pub fn get_specifiers(&self) -> Vec<ModuleSpecifier> {
self.settings.specifiers.keys().cloned().collect()
}
@@ -729,13 +772,8 @@ impl Config {
pub fn set_specifier_settings(
&mut self,
specifier: ModuleSpecifier,
- mut settings: SpecifierSettings,
+ settings: SpecifierSettings,
) -> bool {
- // See https://github.com/denoland/vscode_deno/issues/908.
- if settings.enable_paths == Some(vec![]) {
- settings.enable_paths = None;
- }
-
if let Some(existing) = self.settings.specifiers.get(&specifier) {
if *existing == settings {
return false;
@@ -748,63 +786,33 @@ impl Config {
}
fn specifier_enabled(
- specifier: &Url,
+ enabled_paths: &HashMap<Url, Vec<Url>>,
+ excluded_paths: Option<&Vec<Url>>,
settings: &Settings,
- excluded_urls: Option<&Vec<Url>>,
- workspace_folders: &Vec<(Url, lsp::WorkspaceFolder)>,
workspace_has_config_file: bool,
+ specifier: &Url,
) -> bool {
- if let Some(excluded_urls) = excluded_urls {
- for excluded_path in excluded_urls {
- if specifier.as_str().starts_with(excluded_path.as_str()) {
- return false;
- }
- }
- }
-
- let root_enable = settings
- .workspace
- .enable
- .unwrap_or(workspace_has_config_file);
-
- if let Some(settings) = settings.specifiers.get(specifier) {
- // TODO(nayeemrmn): We don't know from where to resolve `enable_paths` in
- // this case. If it's detected, instead defer to workspace scopes.
- if settings.enable_paths.is_none() {
- return settings.enable.unwrap_or(root_enable);
+ let specifier_str = specifier.as_str();
+ for (workspace, enabled_paths) in enabled_paths.iter() {
+ if specifier_str.starts_with(workspace.as_str()) {
+ return enabled_paths
+ .iter()
+ .any(|path| specifier_str.starts_with(path.as_str()));
}
}
- for (workspace_uri, _) in workspace_folders {
- if specifier.as_str().starts_with(workspace_uri.as_str()) {
- let specifier_settings = settings.specifiers.get(workspace_uri);
- let enable_paths = specifier_settings
- .and_then(|s| s.enable_paths.as_ref())
- .or(settings.workspace.enable_paths.as_ref());
- if let Some(enable_paths) = enable_paths {
- let Ok(scope_path) = specifier_to_file_path(workspace_uri) else {
- lsp_log!("Unable to convert uri \"{}\" to path.", workspace_uri);
- return false;
- };
- for path in enable_paths {
- let path = scope_path.join(path);
- let Ok(path_uri) = Url::from_file_path(&path) else {
- lsp_log!("Unable to convert path \"{}\" to uri.", path.display());
- continue;
- };
- if specifier.as_str().starts_with(path_uri.as_str()) {
- return true;
- }
- }
+ if let Some(excluded_paths) = excluded_paths {
+ for excluded_path in excluded_paths {
+ if specifier_str.starts_with(excluded_path.as_str()) {
return false;
- } else {
- return specifier_settings
- .and_then(|s| s.enable)
- .unwrap_or(root_enable);
}
}
}
-
- root_enable
+ settings
+ .specifiers
+ .get(specifier)
+ .and_then(|settings| settings.enable)
+ .or(settings.workspace.enable)
+ .unwrap_or(workspace_has_config_file)
}
fn resolve_lockfile_from_config(config_file: &ConfigFile) -> Option<Lockfile> {
@@ -865,8 +873,7 @@ mod tests {
#[test]
fn test_config_specifier_enabled() {
- let root_uri = resolve_url("file:///").unwrap();
- let mut config = Config::new_with_root(root_uri);
+ let mut config = Config::new();
let specifier = resolve_url("file:///a.ts").unwrap();
assert!(!config.specifier_enabled(&specifier));
config
@@ -879,8 +886,7 @@ mod tests {
#[test]
fn test_config_snapshot_specifier_enabled() {
- let root_uri = resolve_url("file:///").unwrap();
- let mut config = Config::new_with_root(root_uri);
+ let mut config = Config::new();
let specifier = resolve_url("file:///a.ts").unwrap();
assert!(!config.specifier_enabled(&specifier));
config
@@ -894,15 +900,17 @@ mod tests {
#[test]
fn test_config_specifier_enabled_path() {
- let root_uri = resolve_url("file:///project/").unwrap();
- let mut config = Config::new_with_root(root_uri);
+ let mut config = Config::new();
let specifier_a = resolve_url("file:///project/worker/a.ts").unwrap();
let specifier_b = resolve_url("file:///project/other/b.ts").unwrap();
assert!(!config.specifier_enabled(&specifier_a));
assert!(!config.specifier_enabled(&specifier_b));
- let workspace_settings =
- serde_json::from_str(r#"{ "enablePaths": ["worker"] }"#).unwrap();
- config.set_workspace_settings(workspace_settings).unwrap();
+ let mut enabled_paths = HashMap::new();
+ enabled_paths.insert(
+ Url::parse("file:///project/").unwrap(),
+ vec![Url::parse("file:///project/worker/").unwrap()],
+ );
+ config.enabled_paths = enabled_paths;
assert!(config.specifier_enabled(&specifier_a));
assert!(!config.specifier_enabled(&specifier_b));
let config_snapshot = config.snapshot();
@@ -920,7 +928,7 @@ mod tests {
config.workspace_settings().clone(),
WorkspaceSettings {
enable: None,
- enable_paths: None,
+ enable_paths: Vec::new(),
cache: None,
certificate_stores: None,
config: None,
@@ -1024,10 +1032,11 @@ mod tests {
#[test]
fn config_enabled_urls() {
- let root_dir = resolve_url("file:///example/").unwrap();
- let mut config = Config::new_with_root(root_dir.clone());
+ let mut config = Config::new();
+ let root_dir = Url::parse("file:///example/").unwrap();
+ config.root_uri = Some(root_dir.clone());
config.settings.workspace.enable = Some(false);
- config.settings.workspace.enable_paths = None;
+ config.settings.workspace.enable_paths = Vec::new();
assert_eq!(config.enabled_urls(), vec![]);
config.settings.workspace.enable = Some(true);
@@ -1037,60 +1046,24 @@ mod tests {
let root_dir1 = Url::parse("file:///root1/").unwrap();
let root_dir2 = Url::parse("file:///root2/").unwrap();
let root_dir3 = Url::parse("file:///root3/").unwrap();
- config.workspace_folders = vec![
+ config.enabled_paths = HashMap::from([
(
root_dir1.clone(),
- lsp::WorkspaceFolder {
- uri: root_dir1.clone(),
- name: "1".to_string(),
- },
+ vec![
+ root_dir1.join("sub_dir/").unwrap(),
+ root_dir1.join("sub_dir/other/").unwrap(),
+ root_dir1.join("test.ts").unwrap(),
+ ],
),
- (
- root_dir2.clone(),
- lsp::WorkspaceFolder {
- uri: root_dir2.clone(),
- name: "2".to_string(),
- },
- ),
- (
- root_dir3.clone(),
- lsp::WorkspaceFolder {
- uri: root_dir3.clone(),
- name: "3".to_string(),
- },
- ),
- ];
- config.set_specifier_settings(
- root_dir1.clone(),
- SpecifierSettings {
- enable_paths: Some(vec![
- "sub_dir".to_string(),
- "sub_dir/other".to_string(),
- "test.ts".to_string(),
- ]),
- ..Default::default()
- },
- );
- config.set_specifier_settings(
- root_dir2.clone(),
- SpecifierSettings {
- enable_paths: Some(vec!["other.ts".to_string()]),
- ..Default::default()
- },
- );
- config.set_specifier_settings(
- root_dir3.clone(),
- SpecifierSettings {
- enable: Some(true),
- ..Default::default()
- },
- );
+ (root_dir2.clone(), vec![root_dir2.join("other.ts").unwrap()]),
+ (root_dir3.clone(), vec![]),
+ ]);
assert_eq!(
config.enabled_urls(),
vec![
- root_dir1.join("sub_dir").unwrap(),
- root_dir1.join("sub_dir/other").unwrap(),
+ root_dir1.join("sub_dir/").unwrap(),
+ root_dir1.join("sub_dir/other/").unwrap(),
root_dir1.join("test.ts").unwrap(),
root_dir2.join("other.ts").unwrap(),
root_dir3
@@ -1100,8 +1073,9 @@ mod tests {
#[test]
fn config_enable_via_config_file_detection() {
- let root_uri = resolve_url("file:///root/").unwrap();
- let mut config = Config::new_with_root(root_uri.clone());
+ let mut config = Config::new();
+ let root_uri = Url::parse("file:///root/").unwrap();
+ config.root_uri = Some(root_uri.clone());
config.settings.workspace.enable = None;
assert_eq!(config.enabled_urls(), vec![]);
diff --git a/cli/lsp/diagnostics.rs b/cli/lsp/diagnostics.rs
index 7d8368b27..fd4142fd9 100644
--- a/cli/lsp/diagnostics.rs
+++ b/cli/lsp/diagnostics.rs
@@ -1388,7 +1388,6 @@ mod tests {
}
fn mock_config() -> ConfigSnapshot {
- let root_uri = resolve_url("file:///").unwrap();
ConfigSnapshot {
settings: Settings {
workspace: WorkspaceSettings {
@@ -1398,13 +1397,6 @@ mod tests {
},
..Default::default()
},
- workspace_folders: vec![(
- root_uri.clone(),
- lsp::WorkspaceFolder {
- uri: root_uri,
- name: "".to_string(),
- },
- )],
..Default::default()
}
}
@@ -1476,7 +1468,7 @@ let c: number = "a";
specifier.clone(),
SpecifierSettings {
enable: Some(false),
- enable_paths: None,
+ enable_paths: Vec::new(),
code_lens: Default::default(),
},
);
diff --git a/cli/lsp/language_server.rs b/cli/lsp/language_server.rs
index 3b19d9288..a893308ae 100644
--- a/cli/lsp/language_server.rs
+++ b/cli/lsp/language_server.rs
@@ -403,32 +403,47 @@ impl LanguageServer {
}
pub async fn refresh_specifiers_from_client(&self) -> bool {
- let (client, specifiers) = {
- let ls = self.0.read().await;
- let specifiers = if ls.config.client_capabilities.workspace_configuration
+ let (client, specifiers) =
{
- 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())),
- );
+ 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
- };
+ Some(specifiers.into_iter().collect::<Vec<_>>())
+ } else {
+ None
+ };
- (ls.client.clone(), specifiers)
- };
+ (ls.client.clone(), specifiers)
+ };
let mut touched = false;
if let Some(specifiers) = specifiers {
@@ -462,6 +477,10 @@ impl LanguageServer {
}
}
}
+
+ if ls.config.update_enabled_paths() {
+ touched = true;
+ }
}
touched
}
@@ -682,7 +701,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)
})
@@ -704,7 +723,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)?;
@@ -728,7 +747,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,
@@ -827,7 +846,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(|_| {
@@ -873,7 +892,8 @@ impl Inner {
let workspace_settings = self.config.workspace_settings();
let maybe_root_path = self
.config
- .root_uri()
+ .root_uri
+ .as_ref()
.and_then(|uri| specifier_to_file_path(uri).ok());
let root_cert_store = get_root_cert_store(
maybe_root_path,
@@ -1054,7 +1074,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 =
@@ -1262,14 +1282,20 @@ 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();
}
- if let Some(folders) = params.workspace_folders {
- self.config.workspace_folders = folders
+ self.config.workspace_folders = params.workspace_folders.map(|folders| {
+ folders
.into_iter()
.map(|folder| {
(
@@ -1277,31 +1303,8 @@ impl Inner {
folder,
)
})
- .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,
- },
- ),
- );
- }
- }
+ .collect()
+ });
self.config.update_capabilities(&params.capabilities);
}
@@ -1486,6 +1489,7 @@ 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();
@@ -1652,16 +1656,18 @@ impl Inner {
)
})
.collect::<Vec<(ModuleSpecifier, WorkspaceFolder)>>();
- 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;
+ 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()));
}
- workspace_folders.push((specifier.clone(), folder.clone()));
}
- self.config.workspace_folders = workspace_folders;
+ self.config.workspace_folders = Some(workspace_folders);
}
async fn document_symbol(
@@ -2621,7 +2627,8 @@ impl Inner {
let maybe_root_path_owned = self
.config
- .root_uri()
+ .root_uri
+ .as_ref()
.and_then(|uri| specifier_to_file_path(uri).ok());
let mut resolved_items = Vec::<CallHierarchyIncomingCall>::new();
for item in incoming_calls.iter() {
@@ -2664,7 +2671,8 @@ impl Inner {
let maybe_root_path_owned = self
.config
- .root_uri()
+ .root_uri
+ .as_ref()
.and_then(|uri| specifier_to_file_path(uri).ok());
let mut resolved_items = Vec::<CallHierarchyOutgoingCall>::new();
for item in outgoing_calls.iter() {
@@ -2712,7 +2720,8 @@ impl Inner {
let response = if let Some(one_or_many) = maybe_one_or_many {
let maybe_root_path_owned = self
.config
- .root_uri()
+ .root_uri
+ .as_ref()
.and_then(|uri| specifier_to_file_path(uri).ok());
let mut resolved_items = Vec::<CallHierarchyItem>::new();
match one_or_many {
@@ -3122,7 +3131,7 @@ impl tower_lsp::LanguageServer for LanguageServer {
let test_server = testing::TestServer::new(
ls.client.clone(),
ls.performance.clone(),
- ls.config.root_uri().cloned(),
+ ls.config.root_uri.clone(),
);
ls.maybe_testing_server = Some(test_server);
}
@@ -3199,6 +3208,7 @@ 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);
diff --git a/cli/lsp/repl.rs b/cli/lsp/repl.rs
index c21e2e3fb..b12de4cab 100644
--- a/cli/lsp/repl.rs
+++ b/cli/lsp/repl.rs
@@ -285,7 +285,7 @@ fn get_cwd_uri() -> Result<ModuleSpecifier, AnyError> {
pub fn get_repl_workspace_settings() -> WorkspaceSettings {
WorkspaceSettings {
enable: Some(true),
- enable_paths: None,
+ enable_paths: Vec::new(),
config: None,
certificate_stores: None,
cache: None,
diff --git a/test_util/src/lsp.rs b/test_util/src/lsp.rs
index d276e3ed3..5369d6361 100644
--- a/test_util/src/lsp.rs
+++ b/test_util/src/lsp.rs
@@ -591,7 +591,6 @@ impl LspClientBuilder {
writer,
deno_dir,
stderr_lines_rx,
- config: json!("{}"),
supports_workspace_configuration: false,
})
}
@@ -606,7 +605,6 @@ pub struct LspClient {
deno_dir: TempDir,
context: TestContext,
stderr_lines_rx: Option<mpsc::Receiver<String>>,
- config: serde_json::Value,
supports_workspace_configuration: bool,
}
@@ -701,14 +699,21 @@ impl LspClient {
};
self.write_request("initialize", params);
self.write_notification("initialized", json!({}));
- self.config = config;
if self.supports_workspace_configuration {
- self.handle_configuration_request(self.config.clone());
+ self.handle_configuration_request(config);
}
}
pub fn did_open(&mut self, params: Value) -> CollectedDiagnostics {
- self.did_open_with_config(params, self.config.clone())
+ self.did_open_with_config(
+ params,
+ json!([{
+ "enable": true,
+ "codeLens": {
+ "test": true
+ }
+ }]),
+ )
}
pub fn did_open_with_config(