mirror of
https://github.com/denoland/deno.git
synced 2025-01-03 04:48:52 -05:00
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`.
This commit is contained in:
parent
9d6584c16f
commit
4a11603c76
5 changed files with 264 additions and 245 deletions
|
@ -239,8 +239,7 @@ pub struct SpecifierSettings {
|
||||||
pub enable: Option<bool>,
|
pub enable: Option<bool>,
|
||||||
/// A list of paths, using the workspace folder as a base that should be Deno
|
/// A list of paths, using the workspace folder as a base that should be Deno
|
||||||
/// enabled.
|
/// enabled.
|
||||||
#[serde(default)]
|
pub enable_paths: Option<Vec<String>>,
|
||||||
pub enable_paths: Vec<String>,
|
|
||||||
/// Code lens specific settings for the resource.
|
/// Code lens specific settings for the resource.
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub code_lens: CodeLensSpecifierSettings,
|
pub code_lens: CodeLensSpecifierSettings,
|
||||||
|
@ -291,8 +290,7 @@ pub struct WorkspaceSettings {
|
||||||
pub enable: Option<bool>,
|
pub enable: Option<bool>,
|
||||||
|
|
||||||
/// A list of paths, using the root_uri as a base that should be Deno enabled.
|
/// A list of paths, using the root_uri as a base that should be Deno enabled.
|
||||||
#[serde(default)]
|
pub enable_paths: Option<Vec<String>>,
|
||||||
pub enable_paths: Vec<String>,
|
|
||||||
|
|
||||||
/// An option that points to a path string of the path to utilise as the
|
/// An option that points to a path string of the path to utilise as the
|
||||||
/// cache/DENO_DIR for the language server.
|
/// cache/DENO_DIR for the language server.
|
||||||
|
@ -359,7 +357,7 @@ impl Default for WorkspaceSettings {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
WorkspaceSettings {
|
WorkspaceSettings {
|
||||||
enable: None,
|
enable: None,
|
||||||
enable_paths: vec![],
|
enable_paths: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
certificate_stores: None,
|
certificate_stores: None,
|
||||||
config: None,
|
config: None,
|
||||||
|
@ -402,21 +400,21 @@ impl WorkspaceSettings {
|
||||||
#[derive(Debug, Clone, Default)]
|
#[derive(Debug, Clone, Default)]
|
||||||
pub struct ConfigSnapshot {
|
pub struct ConfigSnapshot {
|
||||||
pub client_capabilities: ClientCapabilities,
|
pub client_capabilities: ClientCapabilities,
|
||||||
pub enabled_paths: HashMap<Url, Vec<Url>>,
|
|
||||||
pub excluded_paths: Option<Vec<Url>>,
|
pub excluded_paths: Option<Vec<Url>>,
|
||||||
pub has_config_file: bool,
|
pub has_config_file: bool,
|
||||||
pub settings: Settings,
|
pub settings: Settings,
|
||||||
|
pub workspace_folders: Vec<(ModuleSpecifier, lsp::WorkspaceFolder)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ConfigSnapshot {
|
impl ConfigSnapshot {
|
||||||
/// Determine if the provided specifier is enabled or not.
|
/// Determine if the provided specifier is enabled or not.
|
||||||
pub fn specifier_enabled(&self, specifier: &ModuleSpecifier) -> bool {
|
pub fn specifier_enabled(&self, specifier: &ModuleSpecifier) -> bool {
|
||||||
specifier_enabled(
|
specifier_enabled(
|
||||||
&self.enabled_paths,
|
|
||||||
self.excluded_paths.as_ref(),
|
|
||||||
&self.settings,
|
|
||||||
self.has_config_file,
|
|
||||||
specifier,
|
specifier,
|
||||||
|
&self.settings,
|
||||||
|
self.excluded_paths.as_ref(),
|
||||||
|
&self.workspace_folders,
|
||||||
|
self.has_config_file,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -448,10 +446,8 @@ struct LspConfigFileInfo {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
pub client_capabilities: ClientCapabilities,
|
pub client_capabilities: ClientCapabilities,
|
||||||
enabled_paths: HashMap<Url, Vec<Url>>,
|
|
||||||
pub root_uri: Option<ModuleSpecifier>,
|
|
||||||
settings: Settings,
|
settings: Settings,
|
||||||
pub workspace_folders: Option<Vec<(ModuleSpecifier, lsp::WorkspaceFolder)>>,
|
pub workspace_folders: Vec<(ModuleSpecifier, lsp::WorkspaceFolder)>,
|
||||||
/// An optional configuration file which has been specified in the client
|
/// 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.
|
/// options along with some data that is computed after the config file is set.
|
||||||
maybe_config_file_info: Option<LspConfigFileInfo>,
|
maybe_config_file_info: Option<LspConfigFileInfo>,
|
||||||
|
@ -461,15 +457,32 @@ impl Config {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
client_capabilities: ClientCapabilities::default(),
|
client_capabilities: ClientCapabilities::default(),
|
||||||
enabled_paths: Default::default(),
|
|
||||||
/// Root provided by the initialization parameters.
|
/// Root provided by the initialization parameters.
|
||||||
root_uri: None,
|
|
||||||
settings: Default::default(),
|
settings: Default::default(),
|
||||||
workspace_folders: None,
|
workspace_folders: vec![],
|
||||||
maybe_config_file_info: 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> {
|
pub fn maybe_node_modules_dir_path(&self) -> Option<&PathBuf> {
|
||||||
self
|
self
|
||||||
.maybe_config_file_info
|
.maybe_config_file_info
|
||||||
|
@ -574,21 +587,24 @@ impl Config {
|
||||||
&mut self,
|
&mut self,
|
||||||
value: Value,
|
value: Value,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), AnyError> {
|
||||||
let workspace_settings = serde_json::from_value(value)?;
|
self.settings.workspace = serde_json::from_value(value)?;
|
||||||
self.settings.workspace = workspace_settings;
|
// See https://github.com/denoland/vscode_deno/issues/908.
|
||||||
|
if self.settings.workspace.enable_paths == Some(vec![]) {
|
||||||
|
self.settings.workspace.enable_paths = None;
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn snapshot(&self) -> Arc<ConfigSnapshot> {
|
pub fn snapshot(&self) -> Arc<ConfigSnapshot> {
|
||||||
Arc::new(ConfigSnapshot {
|
Arc::new(ConfigSnapshot {
|
||||||
client_capabilities: self.client_capabilities.clone(),
|
client_capabilities: self.client_capabilities.clone(),
|
||||||
enabled_paths: self.enabled_paths.clone(),
|
|
||||||
excluded_paths: self
|
excluded_paths: self
|
||||||
.maybe_config_file_info
|
.maybe_config_file_info
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|i| i.excluded_paths.clone()),
|
.map(|i| i.excluded_paths.clone()),
|
||||||
has_config_file: self.has_config_file(),
|
has_config_file: self.has_config_file(),
|
||||||
settings: self.settings.clone(),
|
settings: self.settings.clone(),
|
||||||
|
workspace_folders: self.workspace_folders.clone(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -596,24 +612,16 @@ impl Config {
|
||||||
self.settings.specifiers.contains_key(specifier)
|
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 {
|
pub fn specifier_enabled(&self, specifier: &ModuleSpecifier) -> bool {
|
||||||
specifier_enabled(
|
specifier_enabled(
|
||||||
&self.enabled_paths,
|
specifier,
|
||||||
|
&self.settings,
|
||||||
self
|
self
|
||||||
.maybe_config_file_info
|
.maybe_config_file_info
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|i| &i.excluded_paths),
|
.map(|i| &i.excluded_paths),
|
||||||
&self.settings,
|
&self.workspace_folders,
|
||||||
self.has_config_file(),
|
self.has_config_file(),
|
||||||
specifier,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -623,24 +631,31 @@ impl Config {
|
||||||
/// WARNING: This may incorrectly have some directory urls as being
|
/// WARNING: This may incorrectly have some directory urls as being
|
||||||
/// represented as file urls.
|
/// represented as file urls.
|
||||||
pub fn enabled_urls(&self) -> Vec<Url> {
|
pub fn enabled_urls(&self) -> Vec<Url> {
|
||||||
let mut urls: Vec<Url> = Vec::new();
|
let mut urls = vec![];
|
||||||
|
for (workspace_uri, _) in &self.workspace_folders {
|
||||||
if !self.enabled() && self.enabled_paths.is_empty() {
|
let specifier_settings = self.settings.specifiers.get(workspace_uri);
|
||||||
// do not return any urls when disabled
|
let enable = specifier_settings
|
||||||
return urls;
|
.and_then(|s| s.enable)
|
||||||
}
|
.or(self.settings.workspace.enable)
|
||||||
|
.unwrap_or(self.has_config_file());
|
||||||
for (workspace, enabled_paths) in &self.enabled_paths {
|
let enable_paths = specifier_settings
|
||||||
if !enabled_paths.is_empty() {
|
.and_then(|s| s.enable_paths.as_ref())
|
||||||
urls.extend(enabled_paths.iter().cloned());
|
.or(self.settings.workspace.enable_paths.as_ref());
|
||||||
} else {
|
if let Some(enable_paths) = enable_paths {
|
||||||
urls.push(workspace.clone());
|
let Ok(scope_path) = specifier_to_file_path(workspace_uri) else {
|
||||||
}
|
lsp_log!("Unable to convert uri \"{}\" to path.", workspace_uri);
|
||||||
}
|
return vec![];
|
||||||
|
};
|
||||||
if urls.is_empty() {
|
for path in enable_paths {
|
||||||
if let Some(root_dir) = &self.root_uri {
|
let path = scope_path.join(path);
|
||||||
urls.push(root_dir.clone())
|
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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -712,64 +727,6 @@ 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> {
|
pub fn get_specifiers(&self) -> Vec<ModuleSpecifier> {
|
||||||
self.settings.specifiers.keys().cloned().collect()
|
self.settings.specifiers.keys().cloned().collect()
|
||||||
}
|
}
|
||||||
|
@ -777,8 +734,13 @@ impl Config {
|
||||||
pub fn set_specifier_settings(
|
pub fn set_specifier_settings(
|
||||||
&mut self,
|
&mut self,
|
||||||
specifier: ModuleSpecifier,
|
specifier: ModuleSpecifier,
|
||||||
settings: SpecifierSettings,
|
mut settings: SpecifierSettings,
|
||||||
) -> bool {
|
) -> 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 let Some(existing) = self.settings.specifiers.get(&specifier) {
|
||||||
if *existing == settings {
|
if *existing == settings {
|
||||||
return false;
|
return false;
|
||||||
|
@ -791,33 +753,63 @@ impl Config {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn specifier_enabled(
|
fn specifier_enabled(
|
||||||
enabled_paths: &HashMap<Url, Vec<Url>>,
|
|
||||||
excluded_paths: Option<&Vec<Url>>,
|
|
||||||
settings: &Settings,
|
|
||||||
workspace_has_config_file: bool,
|
|
||||||
specifier: &Url,
|
specifier: &Url,
|
||||||
|
settings: &Settings,
|
||||||
|
excluded_urls: Option<&Vec<Url>>,
|
||||||
|
workspace_folders: &Vec<(Url, lsp::WorkspaceFolder)>,
|
||||||
|
workspace_has_config_file: bool,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let specifier_str = specifier.as_str();
|
if let Some(excluded_urls) = excluded_urls {
|
||||||
for (workspace, enabled_paths) in enabled_paths.iter() {
|
for excluded_path in excluded_urls {
|
||||||
if specifier_str.starts_with(workspace.as_str()) {
|
if specifier.as_str().starts_with(excluded_path.as_str()) {
|
||||||
return enabled_paths
|
|
||||||
.iter()
|
|
||||||
.any(|path| specifier_str.starts_with(path.as_str()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if let Some(excluded_paths) = excluded_paths {
|
|
||||||
for excluded_path in excluded_paths {
|
|
||||||
if specifier_str.starts_with(excluded_path.as_str()) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
settings
|
|
||||||
.specifiers
|
let root_enable = settings
|
||||||
.get(specifier)
|
.workspace
|
||||||
.and_then(|settings| settings.enable)
|
.enable
|
||||||
.or(settings.workspace.enable)
|
.unwrap_or(workspace_has_config_file);
|
||||||
.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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return specifier_settings
|
||||||
|
.and_then(|s| s.enable)
|
||||||
|
.unwrap_or(root_enable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
root_enable
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_lockfile_from_config(config_file: &ConfigFile) -> Option<Lockfile> {
|
fn resolve_lockfile_from_config(config_file: &ConfigFile) -> Option<Lockfile> {
|
||||||
|
@ -878,7 +870,8 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_config_specifier_enabled() {
|
fn test_config_specifier_enabled() {
|
||||||
let mut config = Config::new();
|
let root_uri = resolve_url("file:///").unwrap();
|
||||||
|
let mut config = Config::new_with_root(root_uri);
|
||||||
let specifier = resolve_url("file:///a.ts").unwrap();
|
let specifier = resolve_url("file:///a.ts").unwrap();
|
||||||
assert!(!config.specifier_enabled(&specifier));
|
assert!(!config.specifier_enabled(&specifier));
|
||||||
config
|
config
|
||||||
|
@ -891,7 +884,8 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_config_snapshot_specifier_enabled() {
|
fn test_config_snapshot_specifier_enabled() {
|
||||||
let mut config = Config::new();
|
let root_uri = resolve_url("file:///").unwrap();
|
||||||
|
let mut config = Config::new_with_root(root_uri);
|
||||||
let specifier = resolve_url("file:///a.ts").unwrap();
|
let specifier = resolve_url("file:///a.ts").unwrap();
|
||||||
assert!(!config.specifier_enabled(&specifier));
|
assert!(!config.specifier_enabled(&specifier));
|
||||||
config
|
config
|
||||||
|
@ -905,17 +899,15 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_config_specifier_enabled_path() {
|
fn test_config_specifier_enabled_path() {
|
||||||
let mut config = Config::new();
|
let root_uri = resolve_url("file:///project/").unwrap();
|
||||||
|
let mut config = Config::new_with_root(root_uri);
|
||||||
let specifier_a = resolve_url("file:///project/worker/a.ts").unwrap();
|
let specifier_a = resolve_url("file:///project/worker/a.ts").unwrap();
|
||||||
let specifier_b = resolve_url("file:///project/other/b.ts").unwrap();
|
let specifier_b = resolve_url("file:///project/other/b.ts").unwrap();
|
||||||
assert!(!config.specifier_enabled(&specifier_a));
|
assert!(!config.specifier_enabled(&specifier_a));
|
||||||
assert!(!config.specifier_enabled(&specifier_b));
|
assert!(!config.specifier_enabled(&specifier_b));
|
||||||
let mut enabled_paths = HashMap::new();
|
let workspace_settings =
|
||||||
enabled_paths.insert(
|
serde_json::from_str(r#"{ "enablePaths": ["worker"] }"#).unwrap();
|
||||||
Url::parse("file:///project/").unwrap(),
|
config.set_workspace_settings(workspace_settings).unwrap();
|
||||||
vec![Url::parse("file:///project/worker/").unwrap()],
|
|
||||||
);
|
|
||||||
config.enabled_paths = enabled_paths;
|
|
||||||
assert!(config.specifier_enabled(&specifier_a));
|
assert!(config.specifier_enabled(&specifier_a));
|
||||||
assert!(!config.specifier_enabled(&specifier_b));
|
assert!(!config.specifier_enabled(&specifier_b));
|
||||||
let config_snapshot = config.snapshot();
|
let config_snapshot = config.snapshot();
|
||||||
|
@ -933,7 +925,7 @@ mod tests {
|
||||||
config.workspace_settings().clone(),
|
config.workspace_settings().clone(),
|
||||||
WorkspaceSettings {
|
WorkspaceSettings {
|
||||||
enable: None,
|
enable: None,
|
||||||
enable_paths: Vec::new(),
|
enable_paths: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
certificate_stores: None,
|
certificate_stores: None,
|
||||||
config: None,
|
config: None,
|
||||||
|
@ -1038,11 +1030,10 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn config_enabled_urls() {
|
fn config_enabled_urls() {
|
||||||
let mut config = Config::new();
|
let root_dir = resolve_url("file:///example/").unwrap();
|
||||||
let root_dir = Url::parse("file:///example/").unwrap();
|
let mut config = Config::new_with_root(root_dir.clone());
|
||||||
config.root_uri = Some(root_dir.clone());
|
|
||||||
config.settings.workspace.enable = Some(false);
|
config.settings.workspace.enable = Some(false);
|
||||||
config.settings.workspace.enable_paths = Vec::new();
|
config.settings.workspace.enable_paths = None;
|
||||||
assert_eq!(config.enabled_urls(), vec![]);
|
assert_eq!(config.enabled_urls(), vec![]);
|
||||||
|
|
||||||
config.settings.workspace.enable = Some(true);
|
config.settings.workspace.enable = Some(true);
|
||||||
|
@ -1052,24 +1043,60 @@ mod tests {
|
||||||
let root_dir1 = Url::parse("file:///root1/").unwrap();
|
let root_dir1 = Url::parse("file:///root1/").unwrap();
|
||||||
let root_dir2 = Url::parse("file:///root2/").unwrap();
|
let root_dir2 = Url::parse("file:///root2/").unwrap();
|
||||||
let root_dir3 = Url::parse("file:///root3/").unwrap();
|
let root_dir3 = Url::parse("file:///root3/").unwrap();
|
||||||
config.enabled_paths = HashMap::from([
|
config.workspace_folders = vec![
|
||||||
(
|
(
|
||||||
root_dir1.clone(),
|
root_dir1.clone(),
|
||||||
vec![
|
lsp::WorkspaceFolder {
|
||||||
root_dir1.join("sub_dir/").unwrap(),
|
uri: root_dir1.clone(),
|
||||||
root_dir1.join("sub_dir/other/").unwrap(),
|
name: "1".to_string(),
|
||||||
root_dir1.join("test.ts").unwrap(),
|
},
|
||||||
],
|
|
||||||
),
|
),
|
||||||
(root_dir2.clone(), vec![root_dir2.join("other.ts").unwrap()]),
|
(
|
||||||
(root_dir3.clone(), vec![]),
|
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()
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
config.enabled_urls(),
|
config.enabled_urls(),
|
||||||
vec![
|
vec![
|
||||||
root_dir1.join("sub_dir/").unwrap(),
|
root_dir1.join("sub_dir").unwrap(),
|
||||||
root_dir1.join("sub_dir/other/").unwrap(),
|
root_dir1.join("sub_dir/other").unwrap(),
|
||||||
root_dir1.join("test.ts").unwrap(),
|
root_dir1.join("test.ts").unwrap(),
|
||||||
root_dir2.join("other.ts").unwrap(),
|
root_dir2.join("other.ts").unwrap(),
|
||||||
root_dir3
|
root_dir3
|
||||||
|
@ -1079,9 +1106,8 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn config_enable_via_config_file_detection() {
|
fn config_enable_via_config_file_detection() {
|
||||||
let mut config = Config::new();
|
let root_uri = resolve_url("file:///root/").unwrap();
|
||||||
let root_uri = Url::parse("file:///root/").unwrap();
|
let mut config = Config::new_with_root(root_uri.clone());
|
||||||
config.root_uri = Some(root_uri.clone());
|
|
||||||
config.settings.workspace.enable = None;
|
config.settings.workspace.enable = None;
|
||||||
assert_eq!(config.enabled_urls(), vec![]);
|
assert_eq!(config.enabled_urls(), vec![]);
|
||||||
|
|
||||||
|
|
|
@ -1388,6 +1388,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mock_config() -> ConfigSnapshot {
|
fn mock_config() -> ConfigSnapshot {
|
||||||
|
let root_uri = resolve_url("file:///").unwrap();
|
||||||
ConfigSnapshot {
|
ConfigSnapshot {
|
||||||
settings: Settings {
|
settings: Settings {
|
||||||
workspace: WorkspaceSettings {
|
workspace: WorkspaceSettings {
|
||||||
|
@ -1397,6 +1398,13 @@ mod tests {
|
||||||
},
|
},
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
|
workspace_folders: vec![(
|
||||||
|
root_uri.clone(),
|
||||||
|
lsp::WorkspaceFolder {
|
||||||
|
uri: root_uri,
|
||||||
|
name: "".to_string(),
|
||||||
|
},
|
||||||
|
)],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1468,7 +1476,7 @@ let c: number = "a";
|
||||||
specifier.clone(),
|
specifier.clone(),
|
||||||
SpecifierSettings {
|
SpecifierSettings {
|
||||||
enable: Some(false),
|
enable: Some(false),
|
||||||
enable_paths: Vec::new(),
|
enable_paths: None,
|
||||||
code_lens: Default::default(),
|
code_lens: Default::default(),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
|
@ -403,48 +403,33 @@ impl LanguageServer {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn refresh_specifiers_from_client(&self) -> bool {
|
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 root_capacity = std::cmp::max(ls.config.workspace_folders.len(), 1);
|
||||||
let specifiers =
|
let config_specifiers = ls.config.get_specifiers();
|
||||||
if ls.config.client_capabilities.workspace_configuration {
|
let mut specifiers =
|
||||||
let root_capacity = match &ls.config.workspace_folders {
|
HashMap::with_capacity(root_capacity + config_specifiers.len());
|
||||||
Some(folder) => folder.len(),
|
for (specifier, folder) in &ls.config.workspace_folders {
|
||||||
None => 1,
|
specifiers
|
||||||
};
|
.insert(specifier.clone(), LspClientUrl::new(folder.uri.clone()));
|
||||||
let config_specifiers = ls.config.get_specifiers();
|
}
|
||||||
let mut specifiers =
|
specifiers.extend(
|
||||||
HashMap::with_capacity(root_capacity + config_specifiers.len());
|
ls.config
|
||||||
match &ls.config.workspace_folders {
|
.get_specifiers()
|
||||||
Some(entry) => {
|
.iter()
|
||||||
for (specifier, folder) in entry {
|
.map(|s| (s.clone(), ls.url_map.normalize_specifier(s).unwrap())),
|
||||||
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<_>>())
|
Some(specifiers.into_iter().collect::<Vec<_>>())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
|
||||||
|
|
||||||
(ls.client.clone(), specifiers)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
(ls.client.clone(), specifiers)
|
||||||
|
};
|
||||||
|
|
||||||
let mut touched = false;
|
let mut touched = false;
|
||||||
if let Some(specifiers) = specifiers {
|
if let Some(specifiers) = specifiers {
|
||||||
let configs_result = client
|
let configs_result = client
|
||||||
|
@ -477,10 +462,6 @@ impl LanguageServer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ls.config.update_enabled_paths() {
|
|
||||||
touched = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
touched
|
touched
|
||||||
}
|
}
|
||||||
|
@ -701,7 +682,7 @@ impl Inner {
|
||||||
lsp_log!("Setting Deno configuration from: \"{}\"", config_str);
|
lsp_log!("Setting Deno configuration from: \"{}\"", config_str);
|
||||||
let config_url = if let Ok(url) = Url::from_file_path(config_str) {
|
let config_url = if let Ok(url) = Url::from_file_path(config_str) {
|
||||||
Ok(url)
|
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(|_| {
|
root_uri.join(config_str).map_err(|_| {
|
||||||
anyhow!("Bad file path for configuration file: \"{}\"", config_str)
|
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
|
// 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
|
// file open and not a workspace. In those situations we can't
|
||||||
// automatically discover the configuration
|
// 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 root_path = specifier_to_file_path(root_uri)?;
|
||||||
let mut checked = std::collections::HashSet::new();
|
let mut checked = std::collections::HashSet::new();
|
||||||
let maybe_config = ConfigFile::discover_from(&root_path, &mut checked)?;
|
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
|
// 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
|
// file open and not a workspace. In those situations we can't
|
||||||
// automatically discover the configuration
|
// 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 root_path = specifier_to_file_path(root_uri)?;
|
||||||
let maybe_package_json = package_json::discover_from(
|
let maybe_package_json = package_json::discover_from(
|
||||||
&root_path,
|
&root_path,
|
||||||
|
@ -846,7 +827,7 @@ impl Inner {
|
||||||
lsp_log!("Setting global cache path from: \"{}\"", cache_str);
|
lsp_log!("Setting global cache path from: \"{}\"", cache_str);
|
||||||
let cache_url = if let Ok(url) = Url::from_file_path(cache_str) {
|
let cache_url = if let Ok(url) = Url::from_file_path(cache_str) {
|
||||||
Ok(url)
|
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 root_path = specifier_to_file_path(root_uri)?;
|
||||||
let cache_path = root_path.join(cache_str);
|
let cache_path = root_path.join(cache_str);
|
||||||
Url::from_file_path(cache_path).map_err(|_| {
|
Url::from_file_path(cache_path).map_err(|_| {
|
||||||
|
@ -892,8 +873,7 @@ impl Inner {
|
||||||
let workspace_settings = self.config.workspace_settings();
|
let workspace_settings = self.config.workspace_settings();
|
||||||
let maybe_root_path = self
|
let maybe_root_path = self
|
||||||
.config
|
.config
|
||||||
.root_uri
|
.root_uri()
|
||||||
.as_ref()
|
|
||||||
.and_then(|uri| specifier_to_file_path(uri).ok());
|
.and_then(|uri| specifier_to_file_path(uri).ok());
|
||||||
let root_cert_store = get_root_cert_store(
|
let root_cert_store = get_root_cert_store(
|
||||||
maybe_root_path,
|
maybe_root_path,
|
||||||
|
@ -1074,7 +1054,7 @@ impl Inner {
|
||||||
anyhow!("Bad data url for import map: {}", import_map_str)
|
anyhow!("Bad data url for import map: {}", import_map_str)
|
||||||
})?;
|
})?;
|
||||||
Some(import_map_url)
|
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 root_path = specifier_to_file_path(root_uri)?;
|
||||||
let import_map_path = root_path.join(&import_map_str);
|
let import_map_path = root_path.join(&import_map_str);
|
||||||
let import_map_url =
|
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 {
|
if let Some(value) = params.initialization_options {
|
||||||
self.config.set_workspace_settings(value).map_err(|err| {
|
self.config.set_workspace_settings(value).map_err(|err| {
|
||||||
error!("Cannot set workspace settings: {}", err);
|
error!("Cannot set workspace settings: {}", err);
|
||||||
LspError::internal_error()
|
LspError::internal_error()
|
||||||
})?;
|
})?;
|
||||||
self.config.update_enabled_paths();
|
|
||||||
}
|
}
|
||||||
self.config.workspace_folders = params.workspace_folders.map(|folders| {
|
if let Some(folders) = params.workspace_folders {
|
||||||
folders
|
self.config.workspace_folders = folders
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|folder| {
|
.map(|folder| {
|
||||||
(
|
(
|
||||||
|
@ -1303,8 +1277,31 @@ impl Inner {
|
||||||
folder,
|
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(¶ms.capabilities);
|
self.config.update_capabilities(¶ms.capabilities);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1489,7 +1486,6 @@ impl Inner {
|
||||||
if let Err(err) = self.config.set_workspace_settings(value) {
|
if let Err(err) = self.config.set_workspace_settings(value) {
|
||||||
error!("failed to update settings: {}", err);
|
error!("failed to update settings: {}", err);
|
||||||
}
|
}
|
||||||
self.config.update_enabled_paths();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.update_debug_flag();
|
self.update_debug_flag();
|
||||||
|
@ -1656,18 +1652,16 @@ impl Inner {
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.collect::<Vec<(ModuleSpecifier, WorkspaceFolder)>>();
|
.collect::<Vec<(ModuleSpecifier, WorkspaceFolder)>>();
|
||||||
if let Some(current_folders) = &self.config.workspace_folders {
|
for (specifier, folder) in &self.config.workspace_folders {
|
||||||
for (specifier, folder) in current_folders {
|
if !params.event.removed.is_empty()
|
||||||
if !params.event.removed.is_empty()
|
&& params.event.removed.iter().any(|f| f.uri == folder.uri)
|
||||||
&& params.event.removed.iter().any(|f| f.uri == folder.uri)
|
{
|
||||||
{
|
continue;
|
||||||
continue;
|
|
||||||
}
|
|
||||||
workspace_folders.push((specifier.clone(), folder.clone()));
|
|
||||||
}
|
}
|
||||||
|
workspace_folders.push((specifier.clone(), folder.clone()));
|
||||||
}
|
}
|
||||||
|
|
||||||
self.config.workspace_folders = Some(workspace_folders);
|
self.config.workspace_folders = workspace_folders;
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn document_symbol(
|
async fn document_symbol(
|
||||||
|
@ -2627,8 +2621,7 @@ impl Inner {
|
||||||
|
|
||||||
let maybe_root_path_owned = self
|
let maybe_root_path_owned = self
|
||||||
.config
|
.config
|
||||||
.root_uri
|
.root_uri()
|
||||||
.as_ref()
|
|
||||||
.and_then(|uri| specifier_to_file_path(uri).ok());
|
.and_then(|uri| specifier_to_file_path(uri).ok());
|
||||||
let mut resolved_items = Vec::<CallHierarchyIncomingCall>::new();
|
let mut resolved_items = Vec::<CallHierarchyIncomingCall>::new();
|
||||||
for item in incoming_calls.iter() {
|
for item in incoming_calls.iter() {
|
||||||
|
@ -2671,8 +2664,7 @@ impl Inner {
|
||||||
|
|
||||||
let maybe_root_path_owned = self
|
let maybe_root_path_owned = self
|
||||||
.config
|
.config
|
||||||
.root_uri
|
.root_uri()
|
||||||
.as_ref()
|
|
||||||
.and_then(|uri| specifier_to_file_path(uri).ok());
|
.and_then(|uri| specifier_to_file_path(uri).ok());
|
||||||
let mut resolved_items = Vec::<CallHierarchyOutgoingCall>::new();
|
let mut resolved_items = Vec::<CallHierarchyOutgoingCall>::new();
|
||||||
for item in outgoing_calls.iter() {
|
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 response = if let Some(one_or_many) = maybe_one_or_many {
|
||||||
let maybe_root_path_owned = self
|
let maybe_root_path_owned = self
|
||||||
.config
|
.config
|
||||||
.root_uri
|
.root_uri()
|
||||||
.as_ref()
|
|
||||||
.and_then(|uri| specifier_to_file_path(uri).ok());
|
.and_then(|uri| specifier_to_file_path(uri).ok());
|
||||||
let mut resolved_items = Vec::<CallHierarchyItem>::new();
|
let mut resolved_items = Vec::<CallHierarchyItem>::new();
|
||||||
match one_or_many {
|
match one_or_many {
|
||||||
|
@ -3131,7 +3122,7 @@ impl tower_lsp::LanguageServer for LanguageServer {
|
||||||
let test_server = testing::TestServer::new(
|
let test_server = testing::TestServer::new(
|
||||||
ls.client.clone(),
|
ls.client.clone(),
|
||||||
ls.performance.clone(),
|
ls.performance.clone(),
|
||||||
ls.config.root_uri.clone(),
|
ls.config.root_uri().cloned(),
|
||||||
);
|
);
|
||||||
ls.maybe_testing_server = Some(test_server);
|
ls.maybe_testing_server = Some(test_server);
|
||||||
}
|
}
|
||||||
|
@ -3208,7 +3199,6 @@ impl tower_lsp::LanguageServer for LanguageServer {
|
||||||
Ok(specifier_settings) => {
|
Ok(specifier_settings) => {
|
||||||
ls.config
|
ls.config
|
||||||
.set_specifier_settings(specifier.clone(), specifier_settings);
|
.set_specifier_settings(specifier.clone(), specifier_settings);
|
||||||
ls.config.update_enabled_paths();
|
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
error!("{}", err);
|
error!("{}", err);
|
||||||
|
|
|
@ -285,7 +285,7 @@ fn get_cwd_uri() -> Result<ModuleSpecifier, AnyError> {
|
||||||
pub fn get_repl_workspace_settings() -> WorkspaceSettings {
|
pub fn get_repl_workspace_settings() -> WorkspaceSettings {
|
||||||
WorkspaceSettings {
|
WorkspaceSettings {
|
||||||
enable: Some(true),
|
enable: Some(true),
|
||||||
enable_paths: Vec::new(),
|
enable_paths: None,
|
||||||
config: None,
|
config: None,
|
||||||
certificate_stores: None,
|
certificate_stores: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
|
|
|
@ -591,6 +591,7 @@ impl LspClientBuilder {
|
||||||
writer,
|
writer,
|
||||||
deno_dir,
|
deno_dir,
|
||||||
stderr_lines_rx,
|
stderr_lines_rx,
|
||||||
|
config: json!("{}"),
|
||||||
supports_workspace_configuration: false,
|
supports_workspace_configuration: false,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -605,6 +606,7 @@ pub struct LspClient {
|
||||||
deno_dir: TempDir,
|
deno_dir: TempDir,
|
||||||
context: TestContext,
|
context: TestContext,
|
||||||
stderr_lines_rx: Option<mpsc::Receiver<String>>,
|
stderr_lines_rx: Option<mpsc::Receiver<String>>,
|
||||||
|
config: serde_json::Value,
|
||||||
supports_workspace_configuration: bool,
|
supports_workspace_configuration: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -699,21 +701,14 @@ impl LspClient {
|
||||||
};
|
};
|
||||||
self.write_request("initialize", params);
|
self.write_request("initialize", params);
|
||||||
self.write_notification("initialized", json!({}));
|
self.write_notification("initialized", json!({}));
|
||||||
|
self.config = config;
|
||||||
if self.supports_workspace_configuration {
|
if self.supports_workspace_configuration {
|
||||||
self.handle_configuration_request(config);
|
self.handle_configuration_request(self.config.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn did_open(&mut self, params: Value) -> CollectedDiagnostics {
|
pub fn did_open(&mut self, params: Value) -> CollectedDiagnostics {
|
||||||
self.did_open_with_config(
|
self.did_open_with_config(params, self.config.clone())
|
||||||
params,
|
|
||||||
json!([{
|
|
||||||
"enable": true,
|
|
||||||
"codeLens": {
|
|
||||||
"test": true
|
|
||||||
}
|
|
||||||
}]),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn did_open_with_config(
|
pub fn did_open_with_config(
|
||||||
|
|
Loading…
Reference in a new issue