1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-01-21 21:50:00 -05:00

fix(lsp): updates to workspace config are processed sync (#10812)

This commit is contained in:
Kitson Kelly 2021-06-01 19:24:36 +10:00 committed by GitHub
parent e466a6fc9a
commit 9abb899f5f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 203 additions and 57 deletions

View file

@ -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,6 +350,16 @@ impl Config {
}
}
/// Update all currently cached specifier settings
pub async fn update_all_settings(&self) -> Result<(), AnyError> {
self
.tx
.send(ConfigRequest::All)
.await
.map_err(|_| anyhow!("Error sending config update task."))
}
/// Update a specific specifiers settings from the client.
pub async fn update_specifier_settings(
&self,
specifier: &ModuleSpecifier,
@ -387,14 +371,6 @@ impl Config {
.await
.map_err(|_| anyhow!("Error sending config update task."))
}
pub async fn update_workspace_settings(&self) -> Result<(), AnyError> {
self
.tx
.send(ConfigRequest::Workspace)
.await
.map_err(|_| anyhow!("Error sending config update task."))
}
}
#[cfg(test)]

View file

@ -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);
}
}

View file

@ -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);
}

View file

@ -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
}
}
}