Re-applies what's been reverted in https://github.com/zed-industries/zed/pull/26832 with an action-related fix in64b5d37d32
Before, actions were resolved only if `data` is present and either of the possible fields is empty:e842b4eade/crates/project/src/lsp_store.rs (L1632-L1633)
But Zed resolves completions and inlays once, unconditionally, and the reverted PR applied the same strategy to actions. That did not work despite the spec not forbidding `data`-less actions to be resolved. Soon, it starts to work due to https://github.com/rust-lang/rust-analyzer/pull/19369 but it seems safer to restore the original filtering code. Code lens have no issues with `data`-less resolves:220d913cbc/crates/rust-analyzer/src/handlers/request.rs (L1618-L1620)
so the same approach as completions and inlays is kept: resolve once. Release Notes: - N/A
This commit is contained in:
parent
ef91e7afae
commit
8a31dcaeb0
13 changed files with 618 additions and 17 deletions
|
@ -807,6 +807,27 @@ impl LocalLspStore {
|
|||
})
|
||||
.detach();
|
||||
|
||||
language_server
|
||||
.on_request::<lsp::request::CodeLensRefresh, _, _>({
|
||||
let this = this.clone();
|
||||
move |(), mut cx| {
|
||||
let this = this.clone();
|
||||
async move {
|
||||
this.update(&mut cx, |this, cx| {
|
||||
cx.emit(LspStoreEvent::RefreshCodeLens);
|
||||
this.downstream_client.as_ref().map(|(client, project_id)| {
|
||||
client.send(proto::RefreshCodeLens {
|
||||
project_id: *project_id,
|
||||
})
|
||||
})
|
||||
})?
|
||||
.transpose()?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
|
||||
language_server
|
||||
.on_request::<lsp::request::ShowMessageRequest, _, _>({
|
||||
let this = this.clone();
|
||||
|
@ -1628,7 +1649,8 @@ impl LocalLspStore {
|
|||
) -> anyhow::Result<()> {
|
||||
match &mut action.lsp_action {
|
||||
LspAction::Action(lsp_action) => {
|
||||
if GetCodeActions::can_resolve_actions(&lang_server.capabilities())
|
||||
if !action.resolved
|
||||
&& GetCodeActions::can_resolve_actions(&lang_server.capabilities())
|
||||
&& lsp_action.data.is_some()
|
||||
&& (lsp_action.command.is_none() || lsp_action.edit.is_none())
|
||||
{
|
||||
|
@ -1639,8 +1661,17 @@ impl LocalLspStore {
|
|||
);
|
||||
}
|
||||
}
|
||||
LspAction::CodeLens(lens) => {
|
||||
if !action.resolved && GetCodeLens::can_resolve_lens(&lang_server.capabilities()) {
|
||||
*lens = lang_server
|
||||
.request::<lsp::request::CodeLensResolve>(lens.clone())
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
LspAction::Command(_) => {}
|
||||
}
|
||||
|
||||
action.resolved = true;
|
||||
anyhow::Ok(())
|
||||
}
|
||||
|
||||
|
@ -2887,6 +2918,7 @@ pub enum LspStoreEvent {
|
|||
},
|
||||
Notification(String),
|
||||
RefreshInlayHints,
|
||||
RefreshCodeLens,
|
||||
DiagnosticsUpdated {
|
||||
language_server_id: LanguageServerId,
|
||||
path: ProjectPath,
|
||||
|
@ -2942,6 +2974,7 @@ impl LspStore {
|
|||
client.add_entity_request_handler(Self::handle_resolve_inlay_hint);
|
||||
client.add_entity_request_handler(Self::handle_open_buffer_for_symbol);
|
||||
client.add_entity_request_handler(Self::handle_refresh_inlay_hints);
|
||||
client.add_entity_request_handler(Self::handle_refresh_code_lens);
|
||||
client.add_entity_request_handler(Self::handle_on_type_formatting);
|
||||
client.add_entity_request_handler(Self::handle_apply_additional_edits_for_completion);
|
||||
client.add_entity_request_handler(Self::handle_register_buffer_with_language_servers);
|
||||
|
@ -4316,6 +4349,7 @@ impl LspStore {
|
|||
cx,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn code_actions(
|
||||
&mut self,
|
||||
buffer_handle: &Entity<Buffer>,
|
||||
|
@ -4395,6 +4429,66 @@ impl LspStore {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn code_lens(
|
||||
&mut self,
|
||||
buffer_handle: &Entity<Buffer>,
|
||||
cx: &mut Context<Self>,
|
||||
) -> Task<Result<Vec<CodeAction>>> {
|
||||
if let Some((upstream_client, project_id)) = self.upstream_client() {
|
||||
let request_task = upstream_client.request(proto::MultiLspQuery {
|
||||
buffer_id: buffer_handle.read(cx).remote_id().into(),
|
||||
version: serialize_version(&buffer_handle.read(cx).version()),
|
||||
project_id,
|
||||
strategy: Some(proto::multi_lsp_query::Strategy::All(
|
||||
proto::AllLanguageServers {},
|
||||
)),
|
||||
request: Some(proto::multi_lsp_query::Request::GetCodeLens(
|
||||
GetCodeLens.to_proto(project_id, buffer_handle.read(cx)),
|
||||
)),
|
||||
});
|
||||
let buffer = buffer_handle.clone();
|
||||
cx.spawn(|weak_project, cx| async move {
|
||||
let Some(project) = weak_project.upgrade() else {
|
||||
return Ok(Vec::new());
|
||||
};
|
||||
let responses = request_task.await?.responses;
|
||||
let code_lens = join_all(
|
||||
responses
|
||||
.into_iter()
|
||||
.filter_map(|lsp_response| match lsp_response.response? {
|
||||
proto::lsp_response::Response::GetCodeLensResponse(response) => {
|
||||
Some(response)
|
||||
}
|
||||
unexpected => {
|
||||
debug_panic!("Unexpected response: {unexpected:?}");
|
||||
None
|
||||
}
|
||||
})
|
||||
.map(|code_lens_response| {
|
||||
GetCodeLens.response_from_proto(
|
||||
code_lens_response,
|
||||
project.clone(),
|
||||
buffer.clone(),
|
||||
cx.clone(),
|
||||
)
|
||||
}),
|
||||
)
|
||||
.await;
|
||||
|
||||
Ok(code_lens
|
||||
.into_iter()
|
||||
.collect::<Result<Vec<Vec<_>>>>()?
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.collect())
|
||||
})
|
||||
} else {
|
||||
let code_lens_task =
|
||||
self.request_multiple_lsp_locally(buffer_handle, None::<usize>, GetCodeLens, cx);
|
||||
cx.spawn(|_, _| async move { Ok(code_lens_task.await.into_iter().flatten().collect()) })
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
pub fn completions(
|
||||
&self,
|
||||
|
@ -6308,6 +6402,43 @@ impl LspStore {
|
|||
.collect(),
|
||||
})
|
||||
}
|
||||
Some(proto::multi_lsp_query::Request::GetCodeLens(get_code_lens)) => {
|
||||
let get_code_lens = GetCodeLens::from_proto(
|
||||
get_code_lens,
|
||||
this.clone(),
|
||||
buffer.clone(),
|
||||
cx.clone(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
let code_lens_actions = this
|
||||
.update(&mut cx, |project, cx| {
|
||||
project.request_multiple_lsp_locally(
|
||||
&buffer,
|
||||
None::<usize>,
|
||||
get_code_lens,
|
||||
cx,
|
||||
)
|
||||
})?
|
||||
.await
|
||||
.into_iter();
|
||||
|
||||
this.update(&mut cx, |project, cx| proto::MultiLspQueryResponse {
|
||||
responses: code_lens_actions
|
||||
.map(|actions| proto::LspResponse {
|
||||
response: Some(proto::lsp_response::Response::GetCodeLensResponse(
|
||||
GetCodeLens::response_to_proto(
|
||||
actions,
|
||||
project,
|
||||
sender_id,
|
||||
&buffer_version,
|
||||
cx,
|
||||
),
|
||||
)),
|
||||
})
|
||||
.collect(),
|
||||
})
|
||||
}
|
||||
None => anyhow::bail!("empty multi lsp query request"),
|
||||
}
|
||||
}
|
||||
|
@ -7211,6 +7342,17 @@ impl LspStore {
|
|||
})
|
||||
}
|
||||
|
||||
async fn handle_refresh_code_lens(
|
||||
this: Entity<Self>,
|
||||
_: TypedEnvelope<proto::RefreshCodeLens>,
|
||||
mut cx: AsyncApp,
|
||||
) -> Result<proto::Ack> {
|
||||
this.update(&mut cx, |_, cx| {
|
||||
cx.emit(LspStoreEvent::RefreshCodeLens);
|
||||
})?;
|
||||
Ok(proto::Ack {})
|
||||
}
|
||||
|
||||
async fn handle_open_buffer_for_symbol(
|
||||
this: Entity<Self>,
|
||||
envelope: TypedEnvelope<proto::OpenBufferForSymbol>,
|
||||
|
@ -8434,6 +8576,10 @@ impl LspStore {
|
|||
proto::code_action::Kind::Command as i32,
|
||||
serde_json::to_vec(command).unwrap(),
|
||||
),
|
||||
LspAction::CodeLens(code_lens) => (
|
||||
proto::code_action::Kind::CodeLens as i32,
|
||||
serde_json::to_vec(code_lens).unwrap(),
|
||||
),
|
||||
};
|
||||
|
||||
proto::CodeAction {
|
||||
|
@ -8442,6 +8588,7 @@ impl LspStore {
|
|||
end: Some(serialize_anchor(&action.range.end)),
|
||||
lsp_action,
|
||||
kind,
|
||||
resolved: action.resolved,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8449,11 +8596,11 @@ impl LspStore {
|
|||
let start = action
|
||||
.start
|
||||
.and_then(deserialize_anchor)
|
||||
.ok_or_else(|| anyhow!("invalid start"))?;
|
||||
.context("invalid start")?;
|
||||
let end = action
|
||||
.end
|
||||
.and_then(deserialize_anchor)
|
||||
.ok_or_else(|| anyhow!("invalid end"))?;
|
||||
.context("invalid end")?;
|
||||
let lsp_action = match proto::code_action::Kind::from_i32(action.kind) {
|
||||
Some(proto::code_action::Kind::Action) => {
|
||||
LspAction::Action(serde_json::from_slice(&action.lsp_action)?)
|
||||
|
@ -8461,11 +8608,15 @@ impl LspStore {
|
|||
Some(proto::code_action::Kind::Command) => {
|
||||
LspAction::Command(serde_json::from_slice(&action.lsp_action)?)
|
||||
}
|
||||
Some(proto::code_action::Kind::CodeLens) => {
|
||||
LspAction::CodeLens(serde_json::from_slice(&action.lsp_action)?)
|
||||
}
|
||||
None => anyhow::bail!("Unknown action kind {}", action.kind),
|
||||
};
|
||||
Ok(CodeAction {
|
||||
server_id: LanguageServerId(action.server_id as usize),
|
||||
range: start..end,
|
||||
resolved: action.resolved,
|
||||
lsp_action,
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue