lsp: Query first capable language server for requests using primary LS (#25591)

Release Notes:

- Improved Zed's handling of the following requests when the first
language server in language server settings for a given language is not
capable of handling them:
  - Perform Rename
  - Prepare Rename
  - Document Highlights
  - Find all references
  - Go to implementation
  - Go to definition
  - Go to declaration
  - Go to type definition
This commit is contained in:
Piotr Osiewicz 2025-02-25 22:12:13 +01:00 committed by GitHub
parent e5b6194914
commit 0066071a89
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 105 additions and 99 deletions

View file

@ -3505,13 +3505,21 @@ impl LspStore {
} }
let Some(language_server) = buffer_handle.update(cx, |buffer, cx| match server { let Some(language_server) = buffer_handle.update(cx, |buffer, cx| match server {
LanguageServerToQuery::Primary => self LanguageServerToQuery::FirstCapable => self.as_local().and_then(|local| {
.as_local() local
.and_then(|local| local.primary_language_server_for_buffer(buffer, cx)) .language_servers_for_buffer(buffer, cx)
.map(|(_, server)| server.clone()), .find(|(_, server)| {
request.check_capabilities(server.adapter_server_capabilities())
})
.map(|(_, server)| server.clone())
}),
LanguageServerToQuery::Other(id) => self LanguageServerToQuery::Other(id) => self
.language_server_for_local_buffer(buffer, id, cx) .language_server_for_local_buffer(buffer, id, cx)
.map(|(_, server)| Arc::clone(server)), .and_then(|(_, server)| {
request
.check_capabilities(server.adapter_server_capabilities())
.then(|| Arc::clone(server))
}),
}) else { }) else {
return Task::ready(Ok(Default::default())); return Task::ready(Ok(Default::default()));
}; };
@ -3519,7 +3527,10 @@ impl LspStore {
let buffer = buffer_handle.read(cx); let buffer = buffer_handle.read(cx);
let file = File::from_dyn(buffer.file()).and_then(File::as_local); let file = File::from_dyn(buffer.file()).and_then(File::as_local);
if let Some(file) = file { let Some(file) = file else {
return Task::ready(Ok(Default::default()));
};
let lsp_params = match request.to_lsp_params_or_response( let lsp_params = match request.to_lsp_params_or_response(
&file.abs_path(cx), &file.abs_path(cx),
buffer, buffer,
@ -3572,11 +3583,7 @@ impl LspStore {
Some(defer(|| { Some(defer(|| {
cx.update(|cx| { cx.update(|cx| {
this.update(cx, |this, cx| { this.update(cx, |this, cx| {
this.on_lsp_work_end( this.on_lsp_work_end(language_server.server_id(), id.to_string(), cx);
language_server.server_id(),
id.to_string(),
cx,
);
}) })
}) })
.log_err(); .log_err();
@ -3611,9 +3618,6 @@ impl LspStore {
}); });
} }
Task::ready(Ok(Default::default()))
}
fn on_settings_changed(&mut self, cx: &mut Context<Self>) { fn on_settings_changed(&mut self, cx: &mut Context<Self>) {
let mut language_formatters_to_check = Vec::new(); let mut language_formatters_to_check = Vec::new();
for buffer in self.buffer_store.read(cx).buffers() { for buffer in self.buffer_store.read(cx).buffers() {
@ -3950,7 +3954,7 @@ impl LspStore {
.or_else(|| { .or_else(|| {
self.upstream_client() self.upstream_client()
.is_some() .is_some()
.then_some(LanguageServerToQuery::Primary) .then_some(LanguageServerToQuery::FirstCapable)
}) })
.filter(|_| { .filter(|_| {
maybe!({ maybe!({
@ -4061,7 +4065,7 @@ impl LspStore {
}); });
self.request_lsp( self.request_lsp(
buffer.clone(), buffer.clone(),
LanguageServerToQuery::Primary, LanguageServerToQuery::FirstCapable,
OnTypeFormatting { OnTypeFormatting {
position, position,
trigger, trigger,
@ -4660,7 +4664,7 @@ impl LspStore {
} else { } else {
let lsp_request_task = self.request_lsp( let lsp_request_task = self.request_lsp(
buffer_handle.clone(), buffer_handle.clone(),
LanguageServerToQuery::Primary, LanguageServerToQuery::FirstCapable,
lsp_request, lsp_request,
cx, cx,
); );
@ -5774,7 +5778,7 @@ impl LspStore {
.update(&mut cx, |this, cx| { .update(&mut cx, |this, cx| {
this.request_lsp( this.request_lsp(
buffer_handle.clone(), buffer_handle.clone(),
LanguageServerToQuery::Primary, LanguageServerToQuery::FirstCapable,
request, request,
cx, cx,
) )
@ -8069,7 +8073,9 @@ async fn populate_labels_for_completions(
#[derive(Debug)] #[derive(Debug)]
pub enum LanguageServerToQuery { pub enum LanguageServerToQuery {
Primary, /// Query language servers in order of users preference, up until one capable of handling the request is found.
FirstCapable,
/// Query a specific language server.
Other(LanguageServerId), Other(LanguageServerId),
} }

View file

@ -2777,7 +2777,7 @@ impl Project {
) -> Task<Result<Vec<LocationLink>>> { ) -> Task<Result<Vec<LocationLink>>> {
self.request_lsp( self.request_lsp(
buffer.clone(), buffer.clone(),
LanguageServerToQuery::Primary, LanguageServerToQuery::FirstCapable,
GetDefinition { position }, GetDefinition { position },
cx, cx,
) )
@ -2800,7 +2800,7 @@ impl Project {
) -> Task<Result<Vec<LocationLink>>> { ) -> Task<Result<Vec<LocationLink>>> {
self.request_lsp( self.request_lsp(
buffer.clone(), buffer.clone(),
LanguageServerToQuery::Primary, LanguageServerToQuery::FirstCapable,
GetDeclaration { position }, GetDeclaration { position },
cx, cx,
) )
@ -2824,7 +2824,7 @@ impl Project {
) -> Task<Result<Vec<LocationLink>>> { ) -> Task<Result<Vec<LocationLink>>> {
self.request_lsp( self.request_lsp(
buffer.clone(), buffer.clone(),
LanguageServerToQuery::Primary, LanguageServerToQuery::FirstCapable,
GetTypeDefinition { position }, GetTypeDefinition { position },
cx, cx,
) )
@ -2849,7 +2849,7 @@ impl Project {
let position = position.to_point_utf16(buffer.read(cx)); let position = position.to_point_utf16(buffer.read(cx));
self.request_lsp( self.request_lsp(
buffer.clone(), buffer.clone(),
LanguageServerToQuery::Primary, LanguageServerToQuery::FirstCapable,
GetImplementation { position }, GetImplementation { position },
cx, cx,
) )
@ -2864,7 +2864,7 @@ impl Project {
let position = position.to_point_utf16(buffer.read(cx)); let position = position.to_point_utf16(buffer.read(cx));
self.request_lsp( self.request_lsp(
buffer.clone(), buffer.clone(),
LanguageServerToQuery::Primary, LanguageServerToQuery::FirstCapable,
GetReferences { position }, GetReferences { position },
cx, cx,
) )
@ -2878,7 +2878,7 @@ impl Project {
) -> Task<Result<Vec<DocumentHighlight>>> { ) -> Task<Result<Vec<DocumentHighlight>>> {
self.request_lsp( self.request_lsp(
buffer.clone(), buffer.clone(),
LanguageServerToQuery::Primary, LanguageServerToQuery::FirstCapable,
GetDocumentHighlights { position }, GetDocumentHighlights { position },
cx, cx,
) )
@ -3037,7 +3037,7 @@ impl Project {
) -> Task<Result<PrepareRenameResponse>> { ) -> Task<Result<PrepareRenameResponse>> {
self.request_lsp( self.request_lsp(
buffer, buffer,
LanguageServerToQuery::Primary, LanguageServerToQuery::FirstCapable,
PrepareRename { position }, PrepareRename { position },
cx, cx,
) )
@ -3063,7 +3063,7 @@ impl Project {
let position = position.to_point_utf16(buffer.read(cx)); let position = position.to_point_utf16(buffer.read(cx));
self.request_lsp( self.request_lsp(
buffer, buffer,
LanguageServerToQuery::Primary, LanguageServerToQuery::FirstCapable,
PerformRename { PerformRename {
position, position,
new_name, new_name,