Implement LSP workspace/configuration
and workspace/didChangeConfiguration
(#1684)
* Implement LSP `workspace/configuration` request * Implement LSP `workspace/didChangeConfiguration` notification. * Simplify retrieval of LSP configuration * Implement suggestions from PR discussion Co-authored-by: Triton171 <triton0171@gmail.com>
This commit is contained in:
parent
c15996aff5
commit
f044059a2a
3 changed files with 66 additions and 0 deletions
|
@ -113,6 +113,10 @@ impl Client {
|
||||||
self.offset_encoding
|
self.offset_encoding
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn config(&self) -> Option<&Value> {
|
||||||
|
self.config.as_ref()
|
||||||
|
}
|
||||||
|
|
||||||
/// Execute a RPC request on the language server.
|
/// Execute a RPC request on the language server.
|
||||||
async fn request<R: lsp::request::Request>(&self, params: R::Params) -> Result<R::Result>
|
async fn request<R: lsp::request::Request>(&self, params: R::Params) -> Result<R::Result>
|
||||||
where
|
where
|
||||||
|
@ -246,6 +250,13 @@ impl Client {
|
||||||
root_uri: root,
|
root_uri: root,
|
||||||
initialization_options: self.config.clone(),
|
initialization_options: self.config.clone(),
|
||||||
capabilities: lsp::ClientCapabilities {
|
capabilities: lsp::ClientCapabilities {
|
||||||
|
workspace: Some(lsp::WorkspaceClientCapabilities {
|
||||||
|
configuration: Some(true),
|
||||||
|
did_change_configuration: Some(lsp::DynamicRegistrationClientCapabilities {
|
||||||
|
dynamic_registration: Some(false),
|
||||||
|
}),
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
text_document: Some(lsp::TextDocumentClientCapabilities {
|
text_document: Some(lsp::TextDocumentClientCapabilities {
|
||||||
completion: Some(lsp::CompletionClientCapabilities {
|
completion: Some(lsp::CompletionClientCapabilities {
|
||||||
completion_item: Some(lsp::CompletionItemCapability {
|
completion_item: Some(lsp::CompletionItemCapability {
|
||||||
|
@ -330,6 +341,16 @@ impl Client {
|
||||||
self.exit().await
|
self.exit().await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------------------------
|
||||||
|
// Workspace
|
||||||
|
// -------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
pub fn did_change_configuration(&self, settings: Value) -> impl Future<Output = Result<()>> {
|
||||||
|
self.notify::<lsp::notification::DidChangeConfiguration>(
|
||||||
|
lsp::DidChangeConfigurationParams { settings },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------------------------------
|
// -------------------------------------------------------------------------------------------
|
||||||
// Text document
|
// Text document
|
||||||
// -------------------------------------------------------------------------------------------
|
// -------------------------------------------------------------------------------------------
|
||||||
|
|
|
@ -191,6 +191,7 @@ pub mod util {
|
||||||
pub enum MethodCall {
|
pub enum MethodCall {
|
||||||
WorkDoneProgressCreate(lsp::WorkDoneProgressCreateParams),
|
WorkDoneProgressCreate(lsp::WorkDoneProgressCreateParams),
|
||||||
ApplyWorkspaceEdit(lsp::ApplyWorkspaceEditParams),
|
ApplyWorkspaceEdit(lsp::ApplyWorkspaceEditParams),
|
||||||
|
WorkspaceConfiguration(lsp::ConfigurationParams),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MethodCall {
|
impl MethodCall {
|
||||||
|
@ -209,6 +210,12 @@ impl MethodCall {
|
||||||
.expect("Failed to parse ApplyWorkspaceEdit params");
|
.expect("Failed to parse ApplyWorkspaceEdit params");
|
||||||
Self::ApplyWorkspaceEdit(params)
|
Self::ApplyWorkspaceEdit(params)
|
||||||
}
|
}
|
||||||
|
lsp::request::WorkspaceConfiguration::METHOD => {
|
||||||
|
let params: lsp::ConfigurationParams = params
|
||||||
|
.parse()
|
||||||
|
.expect("Failed to parse WorkspaceConfiguration params");
|
||||||
|
Self::WorkspaceConfiguration(params)
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
log::warn!("unhandled lsp request: {}", method);
|
log::warn!("unhandled lsp request: {}", method);
|
||||||
return None;
|
return None;
|
||||||
|
|
|
@ -532,6 +532,13 @@ impl Application {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Trigger a workspace/didChangeConfiguration notification after initialization.
|
||||||
|
// This might not be required by the spec but Neovim does this as well, so it's
|
||||||
|
// probably a good idea for compatibility.
|
||||||
|
if let Some(config) = language_server.config() {
|
||||||
|
tokio::spawn(language_server.did_change_configuration(config.clone()));
|
||||||
|
}
|
||||||
|
|
||||||
let docs = self.editor.documents().filter(|doc| {
|
let docs = self.editor.documents().filter(|doc| {
|
||||||
doc.language_server().map(|server| server.id()) == Some(server_id)
|
doc.language_server().map(|server| server.id()) == Some(server_id)
|
||||||
});
|
});
|
||||||
|
@ -788,6 +795,37 @@ impl Application {
|
||||||
})),
|
})),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
MethodCall::WorkspaceConfiguration(params) => {
|
||||||
|
let language_server =
|
||||||
|
match self.editor.language_servers.get_by_id(server_id) {
|
||||||
|
Some(language_server) => language_server,
|
||||||
|
None => {
|
||||||
|
warn!("can't find language server with id `{}`", server_id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let result: Vec<_> = params
|
||||||
|
.items
|
||||||
|
.iter()
|
||||||
|
.map(|item| {
|
||||||
|
let mut config = match &item.scope_uri {
|
||||||
|
Some(scope) => {
|
||||||
|
let path = scope.to_file_path().ok()?;
|
||||||
|
let doc = self.editor.document_by_path(path)?;
|
||||||
|
doc.language_config()?.config.as_ref()?
|
||||||
|
}
|
||||||
|
None => language_server.config()?,
|
||||||
|
};
|
||||||
|
if let Some(section) = item.section.as_ref() {
|
||||||
|
for part in section.split('.') {
|
||||||
|
config = config.get(part)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some(config)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
tokio::spawn(language_server.reply(id, Ok(json!(result))));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
e => unreachable!("{:?}", e),
|
e => unreachable!("{:?}", e),
|
||||||
|
|
Loading…
Reference in a new issue