Use textDocument/codeLens data in the actions menu when applicable #2 (#26848)

Re-applies what's been reverted in
https://github.com/zed-industries/zed/pull/26832 with an action-related
fix in
https://github.com/zed-industries/zed/commit/64b5d37d324176cc7b819418f46724cd4c67393d

Before, actions were resolved only if `data` is present and either of
the possible fields is empty:

https://github.com/zed-industries/zed/blob/e842b4eade368127f01944f1b442016edd6b292d/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:

https://github.com/rust-lang/rust-analyzer/blob/220d913cbcd05f9b7635179a98c685f31821a572/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:
Kirill Bulatov
2025-03-15 20:09:32 +00:00
committed by GitHub
parent ef91e7afae
commit 8a31dcaeb0
13 changed files with 618 additions and 17 deletions
+23 -9
View File
@@ -69,7 +69,7 @@ pub use element::{
CursorLayout, EditorElement, HighlightedRange, HighlightedRangeLine, PointForPosition,
};
use futures::{
future::{self, Shared},
future::{self, join, Shared},
FutureExt,
};
use fuzzy::StringMatchCandidate;
@@ -82,10 +82,10 @@ use code_context_menus::{
use git::blame::GitBlame;
use gpui::{
div, impl_actions, point, prelude::*, pulsating_between, px, relative, size, Action, Animation,
AnimationExt, AnyElement, App, AsyncWindowContext, AvailableSpace, Background, Bounds,
ClipboardEntry, ClipboardItem, Context, DispatchPhase, Edges, Entity, EntityInputHandler,
EventEmitter, FocusHandle, FocusOutEvent, Focusable, FontId, FontWeight, Global,
HighlightStyle, Hsla, KeyContext, Modifiers, MouseButton, MouseDownEvent, PaintQuad,
AnimationExt, AnyElement, App, AppContext, AsyncWindowContext, AvailableSpace, Background,
Bounds, ClipboardEntry, ClipboardItem, Context, DispatchPhase, Edges, Entity,
EntityInputHandler, EventEmitter, FocusHandle, FocusOutEvent, Focusable, FontId, FontWeight,
Global, HighlightStyle, Hsla, KeyContext, Modifiers, MouseButton, MouseDownEvent, PaintQuad,
ParentElement, Pixels, Render, SharedString, Size, Stateful, Styled, StyledText, Subscription,
Task, TextStyle, TextStyleRefinement, UTF16Selection, UnderlineStyle, UniformListScrollHandle,
WeakEntity, WeakFocusHandle, Window,
@@ -1233,11 +1233,15 @@ impl Editor {
project_subscriptions.push(cx.subscribe_in(
project,
window,
|editor, _, event, window, cx| {
if let project::Event::RefreshInlayHints = event {
|editor, _, event, window, cx| match event {
project::Event::RefreshCodeLens => {
// we always query lens with actions, without storing them, always refreshing them
}
project::Event::RefreshInlayHints => {
editor
.refresh_inlay_hints(InlayHintRefreshReason::RefreshRequested, cx);
} else if let project::Event::SnippetEdit(id, snippet_edits) = event {
}
project::Event::SnippetEdit(id, snippet_edits) => {
if let Some(buffer) = editor.buffer.read(cx).buffer(*id) {
let focus_handle = editor.focus_handle(cx);
if focus_handle.is_focused(window) {
@@ -1257,6 +1261,7 @@ impl Editor {
}
}
}
_ => {}
},
));
if let Some(task_inventory) = project
@@ -17027,7 +17032,16 @@ impl CodeActionProvider for Entity<Project> {
cx: &mut App,
) -> Task<Result<Vec<CodeAction>>> {
self.update(cx, |project, cx| {
project.code_actions(buffer, range, None, cx)
let code_lens = project.code_lens(buffer, range.clone(), cx);
let code_actions = project.code_actions(buffer, range, None, cx);
cx.background_spawn(async move {
let (code_lens, code_actions) = join(code_lens, code_actions).await;
Ok(code_lens
.context("code lens fetch")?
.into_iter()
.chain(code_actions.context("code action fetch")?)
.collect())
})
})
}