summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cli/lsp/config.rs66
-rw-r--r--cli/lsp/language_server.rs42
-rw-r--r--cli/tests/integration_tests_lsp.rs90
-rw-r--r--cli/tests/lsp/initialize_params_did_config_change.json62
4 files changed, 203 insertions, 57 deletions
diff --git a/cli/lsp/config.rs b/cli/lsp/config.rs
index 3e1b9fe85..33f9122da 100644
--- a/cli/lsp/config.rs
+++ b/cli/lsp/config.rs
@@ -165,8 +165,8 @@ impl ConfigSnapshot {
}
enum ConfigRequest {
+ All,
Specifier(ModuleSpecifier, ModuleSpecifier),
- Workspace,
}
#[derive(Debug, Default, Clone)]
@@ -197,12 +197,8 @@ impl Config {
loop {
match rx.recv().await {
None => break,
- Some(ConfigRequest::Workspace) => {
- let mut items = vec![lsp::ConfigurationItem {
- scope_uri: None,
- section: Some(SETTINGS_SECTION.to_string()),
- }];
- let (specifier_uri_map, mut specifier_items): (
+ Some(ConfigRequest::All) => {
+ let (specifier_uri_map, items): (
Vec<(ModuleSpecifier, ModuleSpecifier)>,
Vec<lsp::ConfigurationItem>,
) = {
@@ -223,40 +219,18 @@ impl Config {
.collect(),
)
};
- items.append(&mut specifier_items);
if let Ok(configs) = client.configuration(items).await {
let mut settings = settings_ref.write().unwrap();
for (i, value) in configs.into_iter().enumerate() {
- match i {
- 0 => {
- match serde_json::from_value::<WorkspaceSettings>(value) {
- Ok(workspace_settings) => {
- settings.workspace = workspace_settings;
- }
- Err(err) => {
- error!(
- "Error converting workspace settings: {}",
- err
- );
- }
- }
+ match serde_json::from_value::<SpecifierSettings>(value) {
+ Ok(specifier_settings) => {
+ let (specifier, uri) = specifier_uri_map[i].clone();
+ settings
+ .specifiers
+ .insert(specifier, (uri, specifier_settings));
}
- _ => {
- match serde_json::from_value::<SpecifierSettings>(value) {
- Ok(specifier_settings) => {
- let (specifier, uri) =
- specifier_uri_map[i - 1].clone();
- settings
- .specifiers
- .insert(specifier, (uri, specifier_settings));
- }
- Err(err) => {
- error!(
- "Error converting specifier settings: {}",
- err
- );
- }
- }
+ Err(err) => {
+ error!("Error converting specifier settings: {}", err);
}
}
}
@@ -376,22 +350,24 @@ impl Config {
}
}
- pub async fn update_specifier_settings(
- &self,
- specifier: &ModuleSpecifier,
- uri: &ModuleSpecifier,
- ) -> Result<(), AnyError> {
+ /// Update all currently cached specifier settings
+ pub async fn update_all_settings(&self) -> Result<(), AnyError> {
self
.tx
- .send(ConfigRequest::Specifier(specifier.clone(), uri.clone()))
+ .send(ConfigRequest::All)
.await
.map_err(|_| anyhow!("Error sending config update task."))
}
- pub async fn update_workspace_settings(&self) -> Result<(), AnyError> {
+ /// Update a specific specifiers settings from the client.
+ pub async fn update_specifier_settings(
+ &self,
+ specifier: &ModuleSpecifier,
+ uri: &ModuleSpecifier,
+ ) -> Result<(), AnyError> {
self
.tx
- .send(ConfigRequest::Workspace)
+ .send(ConfigRequest::Specifier(specifier.clone(), uri.clone()))
.await
.map_err(|_| anyhow!("Error sending config update task."))
}
diff --git a/cli/lsp/language_server.rs b/cli/lsp/language_server.rs
index ebcb6b9e3..c8b959596 100644
--- a/cli/lsp/language_server.rs
+++ b/cli/lsp/language_server.rs
@@ -677,18 +677,36 @@ impl Inner {
.performance
.mark("did_change_configuration", Some(&params));
- if self.config.client_capabilities.workspace_configuration {
- if let Err(err) = self.config.update_workspace_settings().await {
- error!("Error updating workspace settings: {}", err);
- }
- } else if let Some(config) = params
- .settings
- .as_object()
- .map(|settings| settings.get(SETTINGS_SECTION))
- .flatten()
- .cloned()
- {
- if let Err(err) = self.config.set_workspace_settings(config) {
+ let maybe_config =
+ if self.config.client_capabilities.workspace_configuration {
+ let config_response = self
+ .client
+ .configuration(vec![ConfigurationItem {
+ scope_uri: None,
+ section: Some(SETTINGS_SECTION.to_string()),
+ }])
+ .await;
+ if let Err(err) = self.config.update_all_settings().await {
+ error!("Cannot request updating all settings: {}", err);
+ }
+ match config_response {
+ Ok(value_vec) => value_vec.get(0).cloned(),
+ Err(err) => {
+ error!("Error getting workspace configuration: {}", err);
+ None
+ }
+ }
+ } else {
+ params
+ .settings
+ .as_object()
+ .map(|settings| settings.get(SETTINGS_SECTION))
+ .flatten()
+ .cloned()
+ };
+
+ if let Some(value) = maybe_config {
+ if let Err(err) = self.config.set_workspace_settings(value) {
error!("failed to update settings: {}", err);
}
}
diff --git a/cli/tests/integration_tests_lsp.rs b/cli/tests/integration_tests_lsp.rs
index 744b8d387..999d2de71 100644
--- a/cli/tests/integration_tests_lsp.rs
+++ b/cli/tests/integration_tests_lsp.rs
@@ -2125,3 +2125,93 @@ fn lsp_format_markdown() {
);
shutdown(&mut client);
}
+
+#[test]
+fn lsp_configuration_did_change() {
+ let _g = http_server();
+ let mut client = init("initialize_params_did_config_change.json");
+ did_open(
+ &mut client,
+ json!({
+ "textDocument": {
+ "uri": "file:///a/file.ts",
+ "languageId": "typescript",
+ "version": 1,
+ "text": "import * as a from \"http://localhost:4545/x/a@\""
+ }
+ }),
+ );
+ client
+ .write_notification(
+ "workspace/didChangeConfiguration",
+ json!({
+ "settings": {}
+ }),
+ )
+ .unwrap();
+ let (id, method, _) = client.read_request::<Value>().unwrap();
+ assert_eq!(method, "workspace/configuration");
+ client
+ .write_response(
+ id,
+ json!([{
+ "enable": true,
+ "codeLens": {
+ "implementations": true,
+ "references": true
+ },
+ "importMap": null,
+ "lint": true,
+ "suggest": {
+ "autoImports": true,
+ "completeFunctionCalls": false,
+ "names": true,
+ "paths": true,
+ "imports": {
+ "hosts": {
+ "http://localhost:4545/": true
+ }
+ }
+ },
+ "unstable": false
+ }]),
+ )
+ .unwrap();
+ let (maybe_res, maybe_err) = client
+ .write_request(
+ "textDocument/completion",
+ json!({
+ "textDocument": {
+ "uri": "file:///a/file.ts"
+ },
+ "position": {
+ "line": 0,
+ "character": 46
+ },
+ "context": {
+ "triggerKind": 2,
+ "triggerCharacter": "@"
+ }
+ }),
+ )
+ .unwrap();
+ assert!(maybe_err.is_none());
+ if let Some(lsp::CompletionResponse::List(list)) = maybe_res {
+ assert!(!list.is_incomplete);
+ assert_eq!(list.items.len(), 3);
+ } else {
+ panic!("unexpected response");
+ }
+ let (maybe_res, maybe_err) = client
+ .write_request(
+ "completionItem/resolve",
+ load_fixture("completion_resolve_params_registry.json"),
+ )
+ .unwrap();
+ assert!(maybe_err.is_none());
+ assert_eq!(
+ maybe_res,
+ Some(load_fixture("completion_resolve_response_registry.json"))
+ );
+ shutdown(&mut client);
+}
diff --git a/cli/tests/lsp/initialize_params_did_config_change.json b/cli/tests/lsp/initialize_params_did_config_change.json
new file mode 100644
index 000000000..02237c788
--- /dev/null
+++ b/cli/tests/lsp/initialize_params_did_config_change.json
@@ -0,0 +1,62 @@
+{
+ "processId": 0,
+ "clientInfo": {
+ "name": "test-harness",
+ "version": "1.0.0"
+ },
+ "rootUri": null,
+ "initializationOptions": {
+ "enable": true,
+ "codeLens": {
+ "implementations": true,
+ "references": true
+ },
+ "importMap": null,
+ "lint": true,
+ "suggest": {
+ "autoImports": true,
+ "completeFunctionCalls": false,
+ "names": true,
+ "paths": true,
+ "imports": {
+ "hosts": {
+ "http://localhost:4545/": false
+ }
+ }
+ },
+ "unstable": false
+ },
+ "capabilities": {
+ "textDocument": {
+ "codeAction": {
+ "codeActionLiteralSupport": {
+ "codeActionKind": {
+ "valueSet": [
+ "quickfix"
+ ]
+ }
+ },
+ "isPreferredSupport": true,
+ "dataSupport": true,
+ "resolveSupport": {
+ "properties": [
+ "edit"
+ ]
+ }
+ },
+ "foldingRange": {
+ "lineFoldingOnly": true
+ },
+ "synchronization": {
+ "dynamicRegistration": true,
+ "willSave": true,
+ "willSaveWaitUntil": true,
+ "didSave": true
+ }
+ },
+ "workspace": {
+ "configuration": true,
+ "workspaceFolders": true
+ }
+ }
+}