1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-01-22 06:09:25 -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 { enum ConfigRequest {
All,
Specifier(ModuleSpecifier, ModuleSpecifier), Specifier(ModuleSpecifier, ModuleSpecifier),
Workspace,
} }
#[derive(Debug, Default, Clone)] #[derive(Debug, Default, Clone)]
@ -197,12 +197,8 @@ impl Config {
loop { loop {
match rx.recv().await { match rx.recv().await {
None => break, None => break,
Some(ConfigRequest::Workspace) => { Some(ConfigRequest::All) => {
let mut items = vec![lsp::ConfigurationItem { let (specifier_uri_map, items): (
scope_uri: None,
section: Some(SETTINGS_SECTION.to_string()),
}];
let (specifier_uri_map, mut specifier_items): (
Vec<(ModuleSpecifier, ModuleSpecifier)>, Vec<(ModuleSpecifier, ModuleSpecifier)>,
Vec<lsp::ConfigurationItem>, Vec<lsp::ConfigurationItem>,
) = { ) = {
@ -223,40 +219,18 @@ impl Config {
.collect(), .collect(),
) )
}; };
items.append(&mut specifier_items);
if let Ok(configs) = client.configuration(items).await { if let Ok(configs) = client.configuration(items).await {
let mut settings = settings_ref.write().unwrap(); let mut settings = settings_ref.write().unwrap();
for (i, value) in configs.into_iter().enumerate() { for (i, value) in configs.into_iter().enumerate() {
match i { match serde_json::from_value::<SpecifierSettings>(value) {
0 => { Ok(specifier_settings) => {
match serde_json::from_value::<WorkspaceSettings>(value) { let (specifier, uri) = specifier_uri_map[i].clone();
Ok(workspace_settings) => { settings
settings.workspace = workspace_settings; .specifiers
} .insert(specifier, (uri, specifier_settings));
Err(err) => {
error!(
"Error converting workspace settings: {}",
err
);
}
}
} }
_ => { Err(err) => {
match serde_json::from_value::<SpecifierSettings>(value) { error!("Error converting specifier settings: {}", err);
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
);
}
}
} }
} }
} }
@ -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( pub async fn update_specifier_settings(
&self, &self,
specifier: &ModuleSpecifier, specifier: &ModuleSpecifier,
@ -387,14 +371,6 @@ impl Config {
.await .await
.map_err(|_| anyhow!("Error sending config update task.")) .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)] #[cfg(test)]

View file

@ -677,18 +677,36 @@ impl Inner {
.performance .performance
.mark("did_change_configuration", Some(&params)); .mark("did_change_configuration", Some(&params));
if self.config.client_capabilities.workspace_configuration { let maybe_config =
if let Err(err) = self.config.update_workspace_settings().await { if self.config.client_capabilities.workspace_configuration {
error!("Error updating workspace settings: {}", err); let config_response = self
} .client
} else if let Some(config) = params .configuration(vec![ConfigurationItem {
.settings scope_uri: None,
.as_object() section: Some(SETTINGS_SECTION.to_string()),
.map(|settings| settings.get(SETTINGS_SECTION)) }])
.flatten() .await;
.cloned() if let Err(err) = self.config.update_all_settings().await {
{ error!("Cannot request updating all settings: {}", err);
if let Err(err) = self.config.set_workspace_settings(config) { }
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); error!("failed to update settings: {}", err);
} }
} }

View file

@ -2125,3 +2125,93 @@ fn lsp_format_markdown() {
); );
shutdown(&mut client); 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
}
}
}