WIP
Co-authored-by: Kirill <kirill@zed.dev>
This commit is contained in:
parent
a9e3d8c9a4
commit
575e193ea3
3 changed files with 435 additions and 361 deletions
|
@ -1555,6 +1555,106 @@ impl FormatProvider for ModelHandle<Formatter> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trait InlayHints {
|
||||||
|
fn refresh_inlay_hints(
|
||||||
|
&mut self,
|
||||||
|
reason: InlayHintRefreshReason,
|
||||||
|
editor: &mut Editor,
|
||||||
|
cx: &mut ViewContext<Editor>,
|
||||||
|
);
|
||||||
|
fn is_enabled(&self, cx: &AppContext) -> bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl InlayHints for ModelHandle<InlayHintCache> {
|
||||||
|
fn refresh_inlay_hints(
|
||||||
|
&mut self,
|
||||||
|
reason: InlayHintRefreshReason,
|
||||||
|
editor: &mut Editor,
|
||||||
|
cx: &mut ViewContext<Editor>,
|
||||||
|
) {
|
||||||
|
if editor.mode != EditorMode::Full {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let cache_handle = self.clone();
|
||||||
|
self.update(cx, |this, cx| {
|
||||||
|
let reason_description = reason.description();
|
||||||
|
let (invalidate_cache, required_languages) = match reason {
|
||||||
|
InlayHintRefreshReason::Toggle(enabled) => {
|
||||||
|
this.enabled = enabled;
|
||||||
|
if enabled {
|
||||||
|
(InvalidationStrategy::RefreshRequested, None)
|
||||||
|
} else {
|
||||||
|
this.clear();
|
||||||
|
editor.splice_inlay_hints(
|
||||||
|
editor
|
||||||
|
.visible_inlay_hints(cx)
|
||||||
|
.iter()
|
||||||
|
.map(|inlay| inlay.id)
|
||||||
|
.collect(),
|
||||||
|
Vec::new(),
|
||||||
|
cx,
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
InlayHintRefreshReason::SettingsChange(new_settings) => {
|
||||||
|
match this.update_settings(
|
||||||
|
&editor.buffer,
|
||||||
|
new_settings,
|
||||||
|
editor.visible_inlay_hints(cx),
|
||||||
|
cx,
|
||||||
|
) {
|
||||||
|
ControlFlow::Break(Some(InlaySplice {
|
||||||
|
to_remove,
|
||||||
|
to_insert,
|
||||||
|
})) => {
|
||||||
|
editor.splice_inlay_hints(to_remove, to_insert, cx);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ControlFlow::Break(None) => return,
|
||||||
|
ControlFlow::Continue(()) => (InvalidationStrategy::RefreshRequested, None),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
InlayHintRefreshReason::ExcerptsRemoved(excerpts_removed) => {
|
||||||
|
if let Some(InlaySplice {
|
||||||
|
to_remove,
|
||||||
|
to_insert,
|
||||||
|
}) = this.remove_excerpts(excerpts_removed)
|
||||||
|
{
|
||||||
|
editor.splice_inlay_hints(to_remove, to_insert, cx);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
InlayHintRefreshReason::NewLinesShown => (InvalidationStrategy::None, None),
|
||||||
|
InlayHintRefreshReason::BufferEdited(buffer_languages) => {
|
||||||
|
(InvalidationStrategy::BufferEdited, Some(buffer_languages))
|
||||||
|
}
|
||||||
|
InlayHintRefreshReason::RefreshRequested => {
|
||||||
|
(InvalidationStrategy::RefreshRequested, None)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(InlaySplice {
|
||||||
|
to_remove,
|
||||||
|
to_insert,
|
||||||
|
}) = this.spawn_hint_refresh(
|
||||||
|
reason_description,
|
||||||
|
editor.excerpt_visible_offsets(required_languages.as_ref(), cx),
|
||||||
|
invalidate_cache,
|
||||||
|
cache_handle,
|
||||||
|
cx,
|
||||||
|
) {
|
||||||
|
editor.splice_inlay_hints(to_remove, to_insert, cx);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_enabled(&self, cx: &AppContext) -> bool {
|
||||||
|
self.read(cx).enabled
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Editor {
|
pub struct Editor {
|
||||||
handle: WeakViewHandle<Self>,
|
handle: WeakViewHandle<Self>,
|
||||||
buffer: ModelHandle<MultiBuffer>,
|
buffer: ModelHandle<MultiBuffer>,
|
||||||
|
@ -1604,7 +1704,6 @@ pub struct Editor {
|
||||||
gutter_hovered: bool,
|
gutter_hovered: bool,
|
||||||
link_go_to_definition_state: LinkGoToDefinitionState,
|
link_go_to_definition_state: LinkGoToDefinitionState,
|
||||||
copilot_state: CopilotState,
|
copilot_state: CopilotState,
|
||||||
inlay_hint_cache: InlayHintCache,
|
|
||||||
next_inlay_id: usize,
|
next_inlay_id: usize,
|
||||||
_subscriptions: Vec<Subscription>,
|
_subscriptions: Vec<Subscription>,
|
||||||
pixel_position_of_newest_cursor: Option<Vector2F>,
|
pixel_position_of_newest_cursor: Option<Vector2F>,
|
||||||
|
@ -1613,6 +1712,7 @@ pub struct Editor {
|
||||||
go_to_definition_provider: Option<Box<dyn GoToDefinitionProvider>>,
|
go_to_definition_provider: Option<Box<dyn GoToDefinitionProvider>>,
|
||||||
rename_provider: Option<Box<dyn RenameProvider>>,
|
rename_provider: Option<Box<dyn RenameProvider>>,
|
||||||
format_provider: Option<Box<dyn FormatProvider>>,
|
format_provider: Option<Box<dyn FormatProvider>>,
|
||||||
|
inlay_hints: Option<ModelHandle<InlayHintCache>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct EditorSnapshot {
|
pub struct EditorSnapshot {
|
||||||
|
@ -2881,7 +2981,6 @@ impl Editor {
|
||||||
hover_state: Default::default(),
|
hover_state: Default::default(),
|
||||||
link_go_to_definition_state: Default::default(),
|
link_go_to_definition_state: Default::default(),
|
||||||
copilot_state: Default::default(),
|
copilot_state: Default::default(),
|
||||||
inlay_hint_cache: InlayHintCache::new(inlay_hint_settings),
|
|
||||||
gutter_hovered: false,
|
gutter_hovered: false,
|
||||||
pixel_position_of_newest_cursor: None,
|
pixel_position_of_newest_cursor: None,
|
||||||
_subscriptions: vec![
|
_subscriptions: vec![
|
||||||
|
@ -2906,6 +3005,9 @@ impl Editor {
|
||||||
go_to_definition_provider,
|
go_to_definition_provider,
|
||||||
rename_provider,
|
rename_provider,
|
||||||
format_provider,
|
format_provider,
|
||||||
|
inlay_hints: project
|
||||||
|
.clone()
|
||||||
|
.map(|project, _| InlayHintCache::new(project, inlay_hint_settings)),
|
||||||
};
|
};
|
||||||
|
|
||||||
this._subscriptions.extend(project_subscriptions);
|
this._subscriptions.extend(project_subscriptions);
|
||||||
|
@ -4255,87 +4357,23 @@ impl Editor {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn toggle_inlay_hints(&mut self, _: &ToggleInlayHints, cx: &mut ViewContext<Self>) {
|
pub fn toggle_inlay_hints(&mut self, _: &ToggleInlayHints, cx: &mut ViewContext<Self>) {
|
||||||
self.refresh_inlay_hints(
|
if let Some(enabled) = self.inlay_hints.map(|hints| hints.is_enabled(cx)) {
|
||||||
InlayHintRefreshReason::Toggle(!self.inlay_hint_cache.enabled),
|
self.refresh_inlay_hints(InlayHintRefreshReason::Toggle(!enabled), cx);
|
||||||
cx,
|
}
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn inlay_hints_enabled(&self) -> bool {
|
pub fn inlay_hints_enabled(&self) -> bool {
|
||||||
self.inlay_hint_cache.enabled
|
self.inlay_hints
|
||||||
|
.map(|hints| hints.is_enabled(cx))
|
||||||
|
.unwrap_or_default()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn refresh_inlay_hints(&mut self, reason: InlayHintRefreshReason, cx: &mut ViewContext<Self>) {
|
fn refresh_inlay_hints(&mut self, reason: InlayHintRefreshReason, cx: &mut ViewContext<Self>) {
|
||||||
if self.project.is_none() || self.mode != EditorMode::Full {
|
if let Some(inlay_hints) = &self.inlay_hints {
|
||||||
return;
|
cx.spawn(|editor, cx| {
|
||||||
}
|
inlay_hints.refresh_inlay_hints(reason, editor, cx);
|
||||||
|
})
|
||||||
let reason_description = reason.description();
|
.detach()
|
||||||
let (invalidate_cache, required_languages) = match reason {
|
|
||||||
InlayHintRefreshReason::Toggle(enabled) => {
|
|
||||||
self.inlay_hint_cache.enabled = enabled;
|
|
||||||
if enabled {
|
|
||||||
(InvalidationStrategy::RefreshRequested, None)
|
|
||||||
} else {
|
|
||||||
self.inlay_hint_cache.clear();
|
|
||||||
self.splice_inlay_hints(
|
|
||||||
self.visible_inlay_hints(cx)
|
|
||||||
.iter()
|
|
||||||
.map(|inlay| inlay.id)
|
|
||||||
.collect(),
|
|
||||||
Vec::new(),
|
|
||||||
cx,
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
InlayHintRefreshReason::SettingsChange(new_settings) => {
|
|
||||||
match self.inlay_hint_cache.update_settings(
|
|
||||||
&self.buffer,
|
|
||||||
new_settings,
|
|
||||||
self.visible_inlay_hints(cx),
|
|
||||||
cx,
|
|
||||||
) {
|
|
||||||
ControlFlow::Break(Some(InlaySplice {
|
|
||||||
to_remove,
|
|
||||||
to_insert,
|
|
||||||
})) => {
|
|
||||||
self.splice_inlay_hints(to_remove, to_insert, cx);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ControlFlow::Break(None) => return,
|
|
||||||
ControlFlow::Continue(()) => (InvalidationStrategy::RefreshRequested, None),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
InlayHintRefreshReason::ExcerptsRemoved(excerpts_removed) => {
|
|
||||||
if let Some(InlaySplice {
|
|
||||||
to_remove,
|
|
||||||
to_insert,
|
|
||||||
}) = self.inlay_hint_cache.remove_excerpts(excerpts_removed)
|
|
||||||
{
|
|
||||||
self.splice_inlay_hints(to_remove, to_insert, cx);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
InlayHintRefreshReason::NewLinesShown => (InvalidationStrategy::None, None),
|
|
||||||
InlayHintRefreshReason::BufferEdited(buffer_languages) => {
|
|
||||||
(InvalidationStrategy::BufferEdited, Some(buffer_languages))
|
|
||||||
}
|
|
||||||
InlayHintRefreshReason::RefreshRequested => {
|
|
||||||
(InvalidationStrategy::RefreshRequested, None)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(InlaySplice {
|
|
||||||
to_remove,
|
|
||||||
to_insert,
|
|
||||||
}) = self.inlay_hint_cache.spawn_hint_refresh(
|
|
||||||
reason_description,
|
|
||||||
self.excerpt_visible_offsets(required_languages.as_ref(), cx),
|
|
||||||
invalidate_cache,
|
|
||||||
cx,
|
|
||||||
) {
|
|
||||||
self.splice_inlay_hints(to_remove, to_insert, cx);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9353,10 +9391,6 @@ impl Editor {
|
||||||
cx.write_to_clipboard(ClipboardItem::new(lines));
|
cx.write_to_clipboard(ClipboardItem::new(lines));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn inlay_hint_cache(&self) -> &InlayHintCache {
|
|
||||||
&self.inlay_hint_cache
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn replay_insert_event(
|
pub fn replay_insert_event(
|
||||||
&mut self,
|
&mut self,
|
||||||
text: &str,
|
text: &str,
|
||||||
|
@ -9414,6 +9448,24 @@ impl Editor {
|
||||||
});
|
});
|
||||||
supports
|
supports
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(any(test, feature = "test-support"))]
|
||||||
|
fn inlay_hint_cache_version(&self, cx: &mut AppContext) -> usize {
|
||||||
|
self.inlay_hints
|
||||||
|
.expect("test code does not have hints enabled")
|
||||||
|
.update(cx, |hints, _| hints.version)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(any(test, feature = "test-support"))]
|
||||||
|
fn inlay_hint_cache_entries(
|
||||||
|
&self,
|
||||||
|
excerpt_id: ExcerptId,
|
||||||
|
cx: &mut AppContext,
|
||||||
|
) -> Option<&Arc<RwLock<CachedExcerptHints>>> {
|
||||||
|
self.inlay_hints
|
||||||
|
.expect("test code does not have hints enabled")
|
||||||
|
.update(cx, |hints, _| hints.hints.get(&excerpt_id).cloned())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait CollaborationHub {
|
pub trait CollaborationHub {
|
||||||
|
@ -9424,6 +9476,8 @@ pub trait CollaborationHub {
|
||||||
) -> &'a HashMap<u64, ParticipantIndex>;
|
) -> &'a HashMap<u64, ParticipantIndex>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Option<ModelHandle<Project>>
|
||||||
|
// Option<Box<dyn LspBridge>>
|
||||||
impl CollaborationHub for ModelHandle<Project> {
|
impl CollaborationHub for ModelHandle<Project> {
|
||||||
fn collaborators<'a>(&self, cx: &'a AppContext) -> &'a HashMap<PeerId, Collaborator> {
|
fn collaborators<'a>(&self, cx: &'a AppContext) -> &'a HashMap<PeerId, Collaborator> {
|
||||||
self.read(cx).collaborators()
|
self.read(cx).collaborators()
|
||||||
|
|
|
@ -11,10 +11,10 @@ use crate::{
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use clock::Global;
|
use clock::Global;
|
||||||
use futures::future;
|
use futures::future;
|
||||||
use gpui::{ModelContext, ModelHandle, Task, ViewContext};
|
use gpui::{Entity, ModelContext, ModelHandle, Task, ViewContext};
|
||||||
use language::{language_settings::InlayHintKind, Buffer, BufferSnapshot};
|
use language::{language_settings::InlayHintKind, Buffer, BufferSnapshot};
|
||||||
use parking_lot::RwLock;
|
use parking_lot::RwLock;
|
||||||
use project::{InlayHint, ResolveState};
|
use project::{InlayHint, Project, ResolveState};
|
||||||
|
|
||||||
use collections::{hash_map, HashMap, HashSet};
|
use collections::{hash_map, HashMap, HashSet};
|
||||||
use language::language_settings::InlayHintSettings;
|
use language::language_settings::InlayHintSettings;
|
||||||
|
@ -24,9 +24,11 @@ use text::{ToOffset, ToPoint};
|
||||||
use util::post_inc;
|
use util::post_inc;
|
||||||
|
|
||||||
pub struct InlayHintCache {
|
pub struct InlayHintCache {
|
||||||
hints: HashMap<ExcerptId, Arc<RwLock<CachedExcerptHints>>>,
|
// TODO kb consider weak handles
|
||||||
|
project: ModelHandle<Project>,
|
||||||
|
pub(super) hints: HashMap<ExcerptId, Arc<RwLock<CachedExcerptHints>>>,
|
||||||
allowed_hint_kinds: HashSet<Option<InlayHintKind>>,
|
allowed_hint_kinds: HashSet<Option<InlayHintKind>>,
|
||||||
version: usize,
|
pub(super) version: usize,
|
||||||
pub(super) enabled: bool,
|
pub(super) enabled: bool,
|
||||||
update_tasks: HashMap<ExcerptId, TasksForRanges>,
|
update_tasks: HashMap<ExcerptId, TasksForRanges>,
|
||||||
lsp_request_limiter: Arc<Semaphore>,
|
lsp_request_limiter: Arc<Semaphore>,
|
||||||
|
@ -236,9 +238,13 @@ impl TasksForRanges {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Entity for InlayHintCache {
|
||||||
|
type Event = ();
|
||||||
|
}
|
||||||
impl InlayHintCache {
|
impl InlayHintCache {
|
||||||
pub fn new(inlay_hint_settings: InlayHintSettings) -> Self {
|
pub fn new(project: ModelHandle<Project>, inlay_hint_settings: InlayHintSettings) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
project,
|
||||||
allowed_hint_kinds: inlay_hint_settings.enabled_inlay_hint_kinds(),
|
allowed_hint_kinds: inlay_hint_settings.enabled_inlay_hint_kinds(),
|
||||||
enabled: inlay_hint_settings.enabled,
|
enabled: inlay_hint_settings.enabled,
|
||||||
hints: HashMap::default(),
|
hints: HashMap::default(),
|
||||||
|
@ -304,6 +310,7 @@ impl InlayHintCache {
|
||||||
reason: &'static str,
|
reason: &'static str,
|
||||||
excerpts_to_query: HashMap<ExcerptId, (ModelHandle<Buffer>, Global, Range<usize>)>,
|
excerpts_to_query: HashMap<ExcerptId, (ModelHandle<Buffer>, Global, Range<usize>)>,
|
||||||
invalidate: InvalidationStrategy,
|
invalidate: InvalidationStrategy,
|
||||||
|
cache: ModelHandle<Self>,
|
||||||
cx: &mut ViewContext<Editor>,
|
cx: &mut ViewContext<Editor>,
|
||||||
) -> Option<InlaySplice> {
|
) -> Option<InlaySplice> {
|
||||||
if !self.enabled {
|
if !self.enabled {
|
||||||
|
@ -336,6 +343,7 @@ impl InlayHintCache {
|
||||||
excerpts_to_query,
|
excerpts_to_query,
|
||||||
invalidate,
|
invalidate,
|
||||||
cache_version,
|
cache_version,
|
||||||
|
cache,
|
||||||
cx,
|
cx,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
@ -538,7 +546,7 @@ impl InlayHintCache {
|
||||||
.read(cx)
|
.read(cx)
|
||||||
.buffer(buffer_id)
|
.buffer(buffer_id)
|
||||||
.and_then(|buffer| {
|
.and_then(|buffer| {
|
||||||
let project = editor.project.as_ref()?;
|
let project = self.project;
|
||||||
Some(project.update(cx, |project, cx| {
|
Some(project.update(cx, |project, cx| {
|
||||||
project.resolve_inlay_hint(
|
project.resolve_inlay_hint(
|
||||||
hint_to_resolve,
|
hint_to_resolve,
|
||||||
|
@ -582,6 +590,7 @@ fn spawn_new_update_tasks(
|
||||||
excerpts_to_query: HashMap<ExcerptId, (ModelHandle<Buffer>, Global, Range<usize>)>,
|
excerpts_to_query: HashMap<ExcerptId, (ModelHandle<Buffer>, Global, Range<usize>)>,
|
||||||
invalidate: InvalidationStrategy,
|
invalidate: InvalidationStrategy,
|
||||||
update_cache_version: usize,
|
update_cache_version: usize,
|
||||||
|
cache: ModelHandle<InlayHintCache>,
|
||||||
cx: &mut ViewContext<'_, '_, Editor>,
|
cx: &mut ViewContext<'_, '_, Editor>,
|
||||||
) {
|
) {
|
||||||
let visible_hints = Arc::new(editor.visible_inlay_hints(cx));
|
let visible_hints = Arc::new(editor.visible_inlay_hints(cx));
|
||||||
|
@ -601,7 +610,8 @@ fn spawn_new_update_tasks(
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let cached_excerpt_hints = editor.inlay_hint_cache.hints.get(&excerpt_id).cloned();
|
let cached_excerpt_hints =
|
||||||
|
cache.update(cx, |cache, _| cache.hints.get(&excerpt_id).cloned());
|
||||||
if let Some(cached_excerpt_hints) = &cached_excerpt_hints {
|
if let Some(cached_excerpt_hints) = &cached_excerpt_hints {
|
||||||
let cached_excerpt_hints = cached_excerpt_hints.read();
|
let cached_excerpt_hints = cached_excerpt_hints.read();
|
||||||
let cached_buffer_version = &cached_excerpt_hints.buffer_version;
|
let cached_buffer_version = &cached_excerpt_hints.buffer_version;
|
||||||
|
@ -636,35 +646,39 @@ fn spawn_new_update_tasks(
|
||||||
reason,
|
reason,
|
||||||
};
|
};
|
||||||
|
|
||||||
let new_update_task = |query_ranges| {
|
let cache_handle = cache.clone();
|
||||||
new_update_task(
|
cache.update(cx, |cache, _| {
|
||||||
query,
|
let new_update_task = |query_ranges| {
|
||||||
query_ranges,
|
new_update_task(
|
||||||
multi_buffer_snapshot,
|
query,
|
||||||
buffer_snapshot.clone(),
|
|
||||||
Arc::clone(&visible_hints),
|
|
||||||
cached_excerpt_hints,
|
|
||||||
Arc::clone(&editor.inlay_hint_cache.lsp_request_limiter),
|
|
||||||
cx,
|
|
||||||
)
|
|
||||||
};
|
|
||||||
|
|
||||||
match editor.inlay_hint_cache.update_tasks.entry(excerpt_id) {
|
|
||||||
hash_map::Entry::Occupied(mut o) => {
|
|
||||||
o.get_mut().update_cached_tasks(
|
|
||||||
&buffer_snapshot,
|
|
||||||
query_ranges,
|
query_ranges,
|
||||||
invalidate,
|
multi_buffer_snapshot,
|
||||||
new_update_task,
|
buffer_snapshot.clone(),
|
||||||
);
|
Arc::clone(&visible_hints),
|
||||||
|
cached_excerpt_hints,
|
||||||
|
Arc::clone(&cache.lsp_request_limiter),
|
||||||
|
cache_handle,
|
||||||
|
cx,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
match cache.update_tasks.entry(excerpt_id) {
|
||||||
|
hash_map::Entry::Occupied(mut o) => {
|
||||||
|
o.get_mut().update_cached_tasks(
|
||||||
|
&buffer_snapshot,
|
||||||
|
query_ranges,
|
||||||
|
invalidate,
|
||||||
|
new_update_task,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
hash_map::Entry::Vacant(v) => {
|
||||||
|
v.insert(TasksForRanges::new(
|
||||||
|
query_ranges.clone(),
|
||||||
|
new_update_task(query_ranges),
|
||||||
|
));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
hash_map::Entry::Vacant(v) => {
|
})
|
||||||
v.insert(TasksForRanges::new(
|
|
||||||
query_ranges.clone(),
|
|
||||||
new_update_task(query_ranges),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -760,6 +774,7 @@ fn new_update_task(
|
||||||
visible_hints: Arc<Vec<Inlay>>,
|
visible_hints: Arc<Vec<Inlay>>,
|
||||||
cached_excerpt_hints: Option<Arc<RwLock<CachedExcerptHints>>>,
|
cached_excerpt_hints: Option<Arc<RwLock<CachedExcerptHints>>>,
|
||||||
lsp_request_limiter: Arc<Semaphore>,
|
lsp_request_limiter: Arc<Semaphore>,
|
||||||
|
cache: ModelHandle<InlayHintCache>,
|
||||||
cx: &mut ViewContext<'_, '_, Editor>,
|
cx: &mut ViewContext<'_, '_, Editor>,
|
||||||
) -> Task<()> {
|
) -> Task<()> {
|
||||||
cx.spawn(|editor, mut cx| async move {
|
cx.spawn(|editor, mut cx| async move {
|
||||||
|
@ -775,6 +790,7 @@ fn new_update_task(
|
||||||
invalidate,
|
invalidate,
|
||||||
range,
|
range,
|
||||||
Arc::clone(&lsp_request_limiter),
|
Arc::clone(&lsp_request_limiter),
|
||||||
|
cache,
|
||||||
closure_cx.clone(),
|
closure_cx.clone(),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
@ -795,13 +811,9 @@ fn new_update_task(
|
||||||
|
|
||||||
let mut query_range_failed = |range: &Range<language::Anchor>, e: anyhow::Error| {
|
let mut query_range_failed = |range: &Range<language::Anchor>, e: anyhow::Error| {
|
||||||
log::error!("inlay hint update task for range {range:?} failed: {e:#}");
|
log::error!("inlay hint update task for range {range:?} failed: {e:#}");
|
||||||
editor
|
cache
|
||||||
.update(&mut cx, |editor, _| {
|
.update(&mut cx, |cache, _| {
|
||||||
if let Some(task_ranges) = editor
|
if let Some(task_ranges) = cache.update_tasks.get_mut(&query.excerpt_id) {
|
||||||
.inlay_hint_cache
|
|
||||||
.update_tasks
|
|
||||||
.get_mut(&query.excerpt_id)
|
|
||||||
{
|
|
||||||
task_ranges.invalidate_range(&buffer_snapshot, &range);
|
task_ranges.invalidate_range(&buffer_snapshot, &range);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -846,6 +858,7 @@ async fn fetch_and_update_hints(
|
||||||
invalidate: bool,
|
invalidate: bool,
|
||||||
fetch_range: Range<language::Anchor>,
|
fetch_range: Range<language::Anchor>,
|
||||||
lsp_request_limiter: Arc<Semaphore>,
|
lsp_request_limiter: Arc<Semaphore>,
|
||||||
|
cache: ModelHandle<InlayHintCache>,
|
||||||
mut cx: gpui::AsyncAppContext,
|
mut cx: gpui::AsyncAppContext,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
let (lsp_request_guard, got_throttled) = if query.invalidate.should_invalidate() {
|
let (lsp_request_guard, got_throttled) = if query.invalidate.should_invalidate() {
|
||||||
|
@ -880,13 +893,14 @@ async fn fetch_and_update_hints(
|
||||||
};
|
};
|
||||||
if query_not_around_visible_range {
|
if query_not_around_visible_range {
|
||||||
log::trace!("Fetching inlay hints for range {fetch_range_to_log:?} got throttled and fell off the current visible range, skipping.");
|
log::trace!("Fetching inlay hints for range {fetch_range_to_log:?} got throttled and fell off the current visible range, skipping.");
|
||||||
if let Some(task_ranges) = editor
|
cache.update(cx, |cache, _| {
|
||||||
.inlay_hint_cache
|
if let Some(task_ranges) = cache
|
||||||
.update_tasks
|
.update_tasks
|
||||||
.get_mut(&query.excerpt_id)
|
.get_mut(&query.excerpt_id)
|
||||||
{
|
{
|
||||||
task_ranges.invalidate_range(&buffer_snapshot, &fetch_range);
|
task_ranges.invalidate_range(&buffer_snapshot, &fetch_range);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -895,7 +909,7 @@ async fn fetch_and_update_hints(
|
||||||
.read(cx)
|
.read(cx)
|
||||||
.buffer(query.buffer_id)
|
.buffer(query.buffer_id)
|
||||||
.and_then(|buffer| {
|
.and_then(|buffer| {
|
||||||
let project = editor.project.as_ref()?;
|
let project = cache.read(cx).project;
|
||||||
Some(project.update(cx, |project, cx| {
|
Some(project.update(cx, |project, cx| {
|
||||||
project.inlay_hints(buffer, fetch_range.clone(), cx)
|
project.inlay_hints(buffer, fetch_range.clone(), cx)
|
||||||
}))
|
}))
|
||||||
|
@ -957,6 +971,7 @@ async fn fetch_and_update_hints(
|
||||||
invalidate,
|
invalidate,
|
||||||
buffer_snapshot,
|
buffer_snapshot,
|
||||||
multi_buffer_snapshot,
|
multi_buffer_snapshot,
|
||||||
|
cache,
|
||||||
cx,
|
cx,
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
|
@ -1071,13 +1086,11 @@ fn apply_hint_update(
|
||||||
invalidate: bool,
|
invalidate: bool,
|
||||||
buffer_snapshot: BufferSnapshot,
|
buffer_snapshot: BufferSnapshot,
|
||||||
multi_buffer_snapshot: MultiBufferSnapshot,
|
multi_buffer_snapshot: MultiBufferSnapshot,
|
||||||
|
cache: ModelHandle<InlayHintsCache>,
|
||||||
cx: &mut ViewContext<'_, '_, Editor>,
|
cx: &mut ViewContext<'_, '_, Editor>,
|
||||||
) {
|
) {
|
||||||
let cached_excerpt_hints = editor
|
cache.update(cx, |cache, cx| {
|
||||||
.inlay_hint_cache
|
let cached_excerpt_hints = cache.hints.entry(new_update.excerpt_id).or_insert_with(|| {
|
||||||
.hints
|
|
||||||
.entry(new_update.excerpt_id)
|
|
||||||
.or_insert_with(|| {
|
|
||||||
Arc::new(RwLock::new(CachedExcerptHints {
|
Arc::new(RwLock::new(CachedExcerptHints {
|
||||||
version: query.cache_version,
|
version: query.cache_version,
|
||||||
buffer_version: buffer_snapshot.version().clone(),
|
buffer_version: buffer_snapshot.version().clone(),
|
||||||
|
@ -1086,112 +1099,111 @@ fn apply_hint_update(
|
||||||
hints_by_id: HashMap::default(),
|
hints_by_id: HashMap::default(),
|
||||||
}))
|
}))
|
||||||
});
|
});
|
||||||
let mut cached_excerpt_hints = cached_excerpt_hints.write();
|
let mut cached_excerpt_hints = cached_excerpt_hints.write();
|
||||||
match query.cache_version.cmp(&cached_excerpt_hints.version) {
|
match query.cache_version.cmp(&cached_excerpt_hints.version) {
|
||||||
cmp::Ordering::Less => return,
|
cmp::Ordering::Less => return,
|
||||||
cmp::Ordering::Greater | cmp::Ordering::Equal => {
|
cmp::Ordering::Greater | cmp::Ordering::Equal => {
|
||||||
cached_excerpt_hints.version = query.cache_version;
|
cached_excerpt_hints.version = query.cache_version;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let mut cached_inlays_changed = !new_update.remove_from_cache.is_empty();
|
let mut cached_inlays_changed = !new_update.remove_from_cache.is_empty();
|
||||||
cached_excerpt_hints
|
cached_excerpt_hints
|
||||||
.ordered_hints
|
|
||||||
.retain(|hint_id| !new_update.remove_from_cache.contains(hint_id));
|
|
||||||
cached_excerpt_hints
|
|
||||||
.hints_by_id
|
|
||||||
.retain(|hint_id, _| !new_update.remove_from_cache.contains(hint_id));
|
|
||||||
let mut splice = InlaySplice {
|
|
||||||
to_remove: new_update.remove_from_visible,
|
|
||||||
to_insert: Vec::new(),
|
|
||||||
};
|
|
||||||
for new_hint in new_update.add_to_cache {
|
|
||||||
let insert_position = match cached_excerpt_hints
|
|
||||||
.ordered_hints
|
.ordered_hints
|
||||||
.binary_search_by(|probe| {
|
.retain(|hint_id| !new_update.remove_from_cache.contains(hint_id));
|
||||||
cached_excerpt_hints.hints_by_id[probe]
|
cached_excerpt_hints
|
||||||
.position
|
.hints_by_id
|
||||||
.cmp(&new_hint.position, &buffer_snapshot)
|
.retain(|hint_id, _| !new_update.remove_from_cache.contains(hint_id));
|
||||||
}) {
|
let mut splice = InlaySplice {
|
||||||
Ok(i) => {
|
to_remove: new_update.remove_from_visible,
|
||||||
let mut insert_position = Some(i);
|
to_insert: Vec::new(),
|
||||||
for id in &cached_excerpt_hints.ordered_hints[i..] {
|
|
||||||
let cached_hint = &cached_excerpt_hints.hints_by_id[id];
|
|
||||||
if new_hint
|
|
||||||
.position
|
|
||||||
.cmp(&cached_hint.position, &buffer_snapshot)
|
|
||||||
.is_gt()
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if cached_hint.text() == new_hint.text() {
|
|
||||||
insert_position = None;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
insert_position
|
|
||||||
}
|
|
||||||
Err(i) => Some(i),
|
|
||||||
};
|
};
|
||||||
|
for new_hint in new_update.add_to_cache {
|
||||||
|
let insert_position =
|
||||||
|
match cached_excerpt_hints
|
||||||
|
.ordered_hints
|
||||||
|
.binary_search_by(|probe| {
|
||||||
|
cached_excerpt_hints.hints_by_id[probe]
|
||||||
|
.position
|
||||||
|
.cmp(&new_hint.position, &buffer_snapshot)
|
||||||
|
}) {
|
||||||
|
Ok(i) => {
|
||||||
|
let mut insert_position = Some(i);
|
||||||
|
for id in &cached_excerpt_hints.ordered_hints[i..] {
|
||||||
|
let cached_hint = &cached_excerpt_hints.hints_by_id[id];
|
||||||
|
if new_hint
|
||||||
|
.position
|
||||||
|
.cmp(&cached_hint.position, &buffer_snapshot)
|
||||||
|
.is_gt()
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if cached_hint.text() == new_hint.text() {
|
||||||
|
insert_position = None;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
insert_position
|
||||||
|
}
|
||||||
|
Err(i) => Some(i),
|
||||||
|
};
|
||||||
|
|
||||||
if let Some(insert_position) = insert_position {
|
if let Some(insert_position) = insert_position {
|
||||||
let new_inlay_id = post_inc(&mut editor.next_inlay_id);
|
let new_inlay_id = post_inc(&mut editor.next_inlay_id);
|
||||||
if editor
|
if cache.allowed_hint_kinds.contains(&new_hint.kind) {
|
||||||
.inlay_hint_cache
|
let new_hint_position = multi_buffer_snapshot
|
||||||
.allowed_hint_kinds
|
.anchor_in_excerpt(query.excerpt_id, new_hint.position);
|
||||||
.contains(&new_hint.kind)
|
splice
|
||||||
{
|
.to_insert
|
||||||
let new_hint_position =
|
.push(Inlay::hint(new_inlay_id, new_hint_position, &new_hint));
|
||||||
multi_buffer_snapshot.anchor_in_excerpt(query.excerpt_id, new_hint.position);
|
}
|
||||||
splice
|
let new_id = InlayId::Hint(new_inlay_id);
|
||||||
.to_insert
|
cached_excerpt_hints.hints_by_id.insert(new_id, new_hint);
|
||||||
.push(Inlay::hint(new_inlay_id, new_hint_position, &new_hint));
|
cached_excerpt_hints
|
||||||
}
|
.ordered_hints
|
||||||
let new_id = InlayId::Hint(new_inlay_id);
|
.insert(insert_position, new_id);
|
||||||
cached_excerpt_hints.hints_by_id.insert(new_id, new_hint);
|
cached_inlays_changed = true;
|
||||||
cached_excerpt_hints
|
|
||||||
.ordered_hints
|
|
||||||
.insert(insert_position, new_id);
|
|
||||||
cached_inlays_changed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cached_excerpt_hints.buffer_version = buffer_snapshot.version().clone();
|
|
||||||
drop(cached_excerpt_hints);
|
|
||||||
|
|
||||||
if invalidate {
|
|
||||||
let mut outdated_excerpt_caches = HashSet::default();
|
|
||||||
for (excerpt_id, excerpt_hints) in &editor.inlay_hint_cache().hints {
|
|
||||||
let excerpt_hints = excerpt_hints.read();
|
|
||||||
if excerpt_hints.buffer_id == query.buffer_id
|
|
||||||
&& excerpt_id != &query.excerpt_id
|
|
||||||
&& buffer_snapshot
|
|
||||||
.version()
|
|
||||||
.changed_since(&excerpt_hints.buffer_version)
|
|
||||||
{
|
|
||||||
outdated_excerpt_caches.insert(*excerpt_id);
|
|
||||||
splice
|
|
||||||
.to_remove
|
|
||||||
.extend(excerpt_hints.ordered_hints.iter().copied());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cached_inlays_changed |= !outdated_excerpt_caches.is_empty();
|
cached_excerpt_hints.buffer_version = buffer_snapshot.version().clone();
|
||||||
editor
|
drop(cached_excerpt_hints);
|
||||||
.inlay_hint_cache
|
});
|
||||||
.hints
|
|
||||||
.retain(|excerpt_id, _| !outdated_excerpt_caches.contains(excerpt_id));
|
|
||||||
}
|
|
||||||
|
|
||||||
let InlaySplice {
|
cache.update(cx, |cache, _| {
|
||||||
to_remove,
|
if invalidate {
|
||||||
to_insert,
|
let mut outdated_excerpt_caches = HashSet::default();
|
||||||
} = splice;
|
for (excerpt_id, excerpt_hints) in &cache.hints {
|
||||||
let displayed_inlays_changed = !to_remove.is_empty() || !to_insert.is_empty();
|
let excerpt_hints = excerpt_hints.read();
|
||||||
if cached_inlays_changed || displayed_inlays_changed {
|
if excerpt_hints.buffer_id == query.buffer_id
|
||||||
editor.inlay_hint_cache.version += 1;
|
&& excerpt_id != &query.excerpt_id
|
||||||
}
|
&& buffer_snapshot
|
||||||
if displayed_inlays_changed {
|
.version()
|
||||||
editor.splice_inlay_hints(to_remove, to_insert, cx)
|
.changed_since(&excerpt_hints.buffer_version)
|
||||||
}
|
{
|
||||||
|
outdated_excerpt_caches.insert(*excerpt_id);
|
||||||
|
splice
|
||||||
|
.to_remove
|
||||||
|
.extend(excerpt_hints.ordered_hints.iter().copied());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cached_inlays_changed |= !outdated_excerpt_caches.is_empty();
|
||||||
|
cache
|
||||||
|
.hints
|
||||||
|
.retain(|excerpt_id, _| !outdated_excerpt_caches.contains(excerpt_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
let InlaySplice {
|
||||||
|
to_remove,
|
||||||
|
to_insert,
|
||||||
|
} = splice;
|
||||||
|
let displayed_inlays_changed = !to_remove.is_empty() || !to_insert.is_empty();
|
||||||
|
if cached_inlays_changed || displayed_inlays_changed {
|
||||||
|
cache.version += 1;
|
||||||
|
}
|
||||||
|
if displayed_inlays_changed {
|
||||||
|
editor.splice_inlay_hints(to_remove, to_insert, cx)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -1287,7 +1299,8 @@ pub mod tests {
|
||||||
"Cache should use editor settings to get the allowed hint kinds"
|
"Cache should use editor settings to get the allowed hint kinds"
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
inlay_cache.version, edits_made,
|
editor.inlay_hint_cache_version(),
|
||||||
|
edits_made,
|
||||||
"The editor update the cache version after every cache/view change"
|
"The editor update the cache version after every cache/view change"
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -1312,7 +1325,8 @@ pub mod tests {
|
||||||
"Cache should use editor settings to get the allowed hint kinds"
|
"Cache should use editor settings to get the allowed hint kinds"
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
inlay_cache.version, edits_made,
|
editor.inlay_hint_cache_version(),
|
||||||
|
edits_made,
|
||||||
"The editor update the cache version after every cache/view change"
|
"The editor update the cache version after every cache/view change"
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -1392,7 +1406,7 @@ pub mod tests {
|
||||||
);
|
);
|
||||||
assert_eq!(expected_hints, visible_hint_labels(editor, cx));
|
assert_eq!(expected_hints, visible_hint_labels(editor, cx));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
editor.inlay_hint_cache().version,
|
editor.inlay_hint_cache_version(),
|
||||||
edits_made,
|
edits_made,
|
||||||
"The editor update the cache version after every cache/view change"
|
"The editor update the cache version after every cache/view change"
|
||||||
);
|
);
|
||||||
|
@ -1423,7 +1437,7 @@ pub mod tests {
|
||||||
);
|
);
|
||||||
assert_eq!(expected_hints, visible_hint_labels(editor, cx));
|
assert_eq!(expected_hints, visible_hint_labels(editor, cx));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
editor.inlay_hint_cache().version,
|
editor.inlay_hint_cache_version(),
|
||||||
edits_made,
|
edits_made,
|
||||||
"Should not update the cache while the work task is running"
|
"Should not update the cache while the work task is running"
|
||||||
);
|
);
|
||||||
|
@ -1447,7 +1461,7 @@ pub mod tests {
|
||||||
);
|
);
|
||||||
assert_eq!(expected_hints, visible_hint_labels(editor, cx));
|
assert_eq!(expected_hints, visible_hint_labels(editor, cx));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
editor.inlay_hint_cache().version,
|
editor.inlay_hint_cache_version(),
|
||||||
edits_made,
|
edits_made,
|
||||||
"Cache version should udpate once after the work task is done"
|
"Cache version should udpate once after the work task is done"
|
||||||
);
|
);
|
||||||
|
@ -1566,7 +1580,7 @@ pub mod tests {
|
||||||
);
|
);
|
||||||
assert_eq!(expected_hints, visible_hint_labels(editor, cx));
|
assert_eq!(expected_hints, visible_hint_labels(editor, cx));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
editor.inlay_hint_cache().version,
|
editor.inlay_hint_cache_version(),
|
||||||
1,
|
1,
|
||||||
"Rust editor update the cache version after every cache/view change"
|
"Rust editor update the cache version after every cache/view change"
|
||||||
);
|
);
|
||||||
|
@ -1623,7 +1637,7 @@ pub mod tests {
|
||||||
"Markdown editor should have a separate verison, repeating Rust editor rules"
|
"Markdown editor should have a separate verison, repeating Rust editor rules"
|
||||||
);
|
);
|
||||||
assert_eq!(expected_hints, visible_hint_labels(editor, cx));
|
assert_eq!(expected_hints, visible_hint_labels(editor, cx));
|
||||||
assert_eq!(editor.inlay_hint_cache().version, 1);
|
assert_eq!(editor.inlay_hint_cache_version(), 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
rs_editor.update(cx, |editor, cx| {
|
rs_editor.update(cx, |editor, cx| {
|
||||||
|
@ -1640,7 +1654,7 @@ pub mod tests {
|
||||||
);
|
);
|
||||||
assert_eq!(expected_hints, visible_hint_labels(editor, cx));
|
assert_eq!(expected_hints, visible_hint_labels(editor, cx));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
editor.inlay_hint_cache().version,
|
editor.inlay_hint_cache_version(),
|
||||||
2,
|
2,
|
||||||
"Every time hint cache changes, cache version should be incremented"
|
"Every time hint cache changes, cache version should be incremented"
|
||||||
);
|
);
|
||||||
|
@ -1653,7 +1667,7 @@ pub mod tests {
|
||||||
"Markdown editor should not be affected by Rust editor changes"
|
"Markdown editor should not be affected by Rust editor changes"
|
||||||
);
|
);
|
||||||
assert_eq!(expected_hints, visible_hint_labels(editor, cx));
|
assert_eq!(expected_hints, visible_hint_labels(editor, cx));
|
||||||
assert_eq!(editor.inlay_hint_cache().version, 1);
|
assert_eq!(editor.inlay_hint_cache_version(), 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
md_editor.update(cx, |editor, cx| {
|
md_editor.update(cx, |editor, cx| {
|
||||||
|
@ -1669,7 +1683,7 @@ pub mod tests {
|
||||||
"Rust editor should not be affected by Markdown editor changes"
|
"Rust editor should not be affected by Markdown editor changes"
|
||||||
);
|
);
|
||||||
assert_eq!(expected_hints, visible_hint_labels(editor, cx));
|
assert_eq!(expected_hints, visible_hint_labels(editor, cx));
|
||||||
assert_eq!(editor.inlay_hint_cache().version, 2);
|
assert_eq!(editor.inlay_hint_cache_version(), 2);
|
||||||
});
|
});
|
||||||
rs_editor.update(cx, |editor, cx| {
|
rs_editor.update(cx, |editor, cx| {
|
||||||
let expected_hints = vec!["1".to_string()];
|
let expected_hints = vec!["1".to_string()];
|
||||||
|
@ -1679,7 +1693,7 @@ pub mod tests {
|
||||||
"Markdown editor should also change independently"
|
"Markdown editor should also change independently"
|
||||||
);
|
);
|
||||||
assert_eq!(expected_hints, visible_hint_labels(editor, cx));
|
assert_eq!(expected_hints, visible_hint_labels(editor, cx));
|
||||||
assert_eq!(editor.inlay_hint_cache().version, 2);
|
assert_eq!(editor.inlay_hint_cache_version(), 2);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1801,7 +1815,7 @@ pub mod tests {
|
||||||
visible_hint_labels(editor, cx)
|
visible_hint_labels(editor, cx)
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
editor.inlay_hint_cache().version,
|
editor.inlay_hint_cache_version(),
|
||||||
edits_made,
|
edits_made,
|
||||||
"Should not update cache version due to new loaded hints being the same"
|
"Should not update cache version due to new loaded hints being the same"
|
||||||
);
|
);
|
||||||
|
@ -1936,7 +1950,7 @@ pub mod tests {
|
||||||
assert!(cached_hint_labels(editor).is_empty());
|
assert!(cached_hint_labels(editor).is_empty());
|
||||||
assert!(visible_hint_labels(editor, cx).is_empty());
|
assert!(visible_hint_labels(editor, cx).is_empty());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
editor.inlay_hint_cache().version, edits_made,
|
editor.inlay_hint_cache_version(), edits_made,
|
||||||
"The editor should not update the cache version after /refresh query without updates"
|
"The editor should not update the cache version after /refresh query without updates"
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -2007,7 +2021,7 @@ pub mod tests {
|
||||||
vec!["parameter hint".to_string()],
|
vec!["parameter hint".to_string()],
|
||||||
visible_hint_labels(editor, cx),
|
visible_hint_labels(editor, cx),
|
||||||
);
|
);
|
||||||
assert_eq!(editor.inlay_hint_cache().version, edits_made);
|
assert_eq!(editor.inlay_hint_cache_version(), edits_made);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2086,7 +2100,7 @@ pub mod tests {
|
||||||
);
|
);
|
||||||
assert_eq!(expected_hints, visible_hint_labels(editor, cx));
|
assert_eq!(expected_hints, visible_hint_labels(editor, cx));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
editor.inlay_hint_cache().version, 1,
|
editor.inlay_hint_cache_version(), 1,
|
||||||
"Only one update should be registered in the cache after all cancellations"
|
"Only one update should be registered in the cache after all cancellations"
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -2131,7 +2145,7 @@ pub mod tests {
|
||||||
);
|
);
|
||||||
assert_eq!(expected_hints, visible_hint_labels(editor, cx));
|
assert_eq!(expected_hints, visible_hint_labels(editor, cx));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
editor.inlay_hint_cache().version,
|
editor.inlay_hint_cache_version(),
|
||||||
2,
|
2,
|
||||||
"Should update the cache version once more, for the new change"
|
"Should update the cache version once more, for the new change"
|
||||||
);
|
);
|
||||||
|
@ -2301,7 +2315,7 @@ pub mod tests {
|
||||||
);
|
);
|
||||||
assert_eq!(expected_hints, visible_hint_labels(editor, cx), "Should display only hints from the visible range");
|
assert_eq!(expected_hints, visible_hint_labels(editor, cx), "Should display only hints from the visible range");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
editor.inlay_hint_cache().version, requests_count,
|
editor.inlay_hint_cache_version(), requests_count,
|
||||||
"LSP queries should've bumped the cache version"
|
"LSP queries should've bumped the cache version"
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -2363,7 +2377,7 @@ pub mod tests {
|
||||||
);
|
);
|
||||||
assert_eq!(expected_hints, visible_hint_labels(editor, cx));
|
assert_eq!(expected_hints, visible_hint_labels(editor, cx));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
editor.inlay_hint_cache().version,
|
editor.inlay_hint_cache_version(),
|
||||||
lsp_requests,
|
lsp_requests,
|
||||||
"Should update the cache for every LSP response with hints added"
|
"Should update the cache for every LSP response with hints added"
|
||||||
);
|
);
|
||||||
|
@ -2427,7 +2441,7 @@ pub mod tests {
|
||||||
assert_eq!(expected_hints, cached_hint_labels(editor),
|
assert_eq!(expected_hints, cached_hint_labels(editor),
|
||||||
"Should have hints from the new LSP response after the edit");
|
"Should have hints from the new LSP response after the edit");
|
||||||
assert_eq!(expected_hints, visible_hint_labels(editor, cx));
|
assert_eq!(expected_hints, visible_hint_labels(editor, cx));
|
||||||
assert_eq!(editor.inlay_hint_cache().version, lsp_requests, "Should update the cache for every LSP response with hints added");
|
assert_eq!(editor.inlay_hint_cache_version(), lsp_requests, "Should update the cache for every LSP response with hints added");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2650,7 +2664,7 @@ pub mod tests {
|
||||||
"When scroll is at the edge of a multibuffer, its visible excerpts only should be queried for inlay hints"
|
"When scroll is at the edge of a multibuffer, its visible excerpts only should be queried for inlay hints"
|
||||||
);
|
);
|
||||||
assert_eq!(expected_hints, visible_hint_labels(editor, cx));
|
assert_eq!(expected_hints, visible_hint_labels(editor, cx));
|
||||||
assert_eq!(editor.inlay_hint_cache().version, expected_hints.len(), "Every visible excerpt hints should bump the verison");
|
assert_eq!(editor.inlay_hint_cache_version(), expected_hints.len(), "Every visible excerpt hints should bump the verison");
|
||||||
});
|
});
|
||||||
|
|
||||||
editor.update(cx, |editor, cx| {
|
editor.update(cx, |editor, cx| {
|
||||||
|
@ -2680,7 +2694,7 @@ pub mod tests {
|
||||||
assert_eq!(expected_hints, cached_hint_labels(editor),
|
assert_eq!(expected_hints, cached_hint_labels(editor),
|
||||||
"With more scrolls of the multibuffer, more hints should be added into the cache and nothing invalidated without edits");
|
"With more scrolls of the multibuffer, more hints should be added into the cache and nothing invalidated without edits");
|
||||||
assert_eq!(expected_hints, visible_hint_labels(editor, cx));
|
assert_eq!(expected_hints, visible_hint_labels(editor, cx));
|
||||||
assert_eq!(editor.inlay_hint_cache().version, expected_hints.len(),
|
assert_eq!(editor.inlay_hint_cache_version(), expected_hints.len(),
|
||||||
"Due to every excerpt having one hint, we update cache per new excerpt scrolled");
|
"Due to every excerpt having one hint, we update cache per new excerpt scrolled");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -2711,7 +2725,7 @@ pub mod tests {
|
||||||
assert_eq!(expected_hints, cached_hint_labels(editor),
|
assert_eq!(expected_hints, cached_hint_labels(editor),
|
||||||
"After multibuffer was scrolled to the end, all hints for all excerpts should be fetched");
|
"After multibuffer was scrolled to the end, all hints for all excerpts should be fetched");
|
||||||
assert_eq!(expected_hints, visible_hint_labels(editor, cx));
|
assert_eq!(expected_hints, visible_hint_labels(editor, cx));
|
||||||
assert_eq!(editor.inlay_hint_cache().version, expected_hints.len());
|
assert_eq!(editor.inlay_hint_cache_version(), expected_hints.len());
|
||||||
expected_hints.len()
|
expected_hints.len()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -2739,7 +2753,7 @@ pub mod tests {
|
||||||
assert_eq!(expected_hints, cached_hint_labels(editor),
|
assert_eq!(expected_hints, cached_hint_labels(editor),
|
||||||
"After multibuffer was scrolled to the end, further scrolls up should not bring more hints");
|
"After multibuffer was scrolled to the end, further scrolls up should not bring more hints");
|
||||||
assert_eq!(expected_hints, visible_hint_labels(editor, cx));
|
assert_eq!(expected_hints, visible_hint_labels(editor, cx));
|
||||||
assert_eq!(editor.inlay_hint_cache().version, last_scroll_update_version, "No updates should happen during scrolling already scolled buffer");
|
assert_eq!(editor.inlay_hint_cache_version(), last_scroll_update_version, "No updates should happen during scrolling already scolled buffer");
|
||||||
});
|
});
|
||||||
|
|
||||||
editor_edited.store(true, Ordering::Release);
|
editor_edited.store(true, Ordering::Release);
|
||||||
|
@ -2769,7 +2783,7 @@ all hints should be invalidated and requeried for all of its visible excerpts"
|
||||||
);
|
);
|
||||||
assert_eq!(expected_hints, visible_hint_labels(editor, cx));
|
assert_eq!(expected_hints, visible_hint_labels(editor, cx));
|
||||||
|
|
||||||
let current_cache_version = editor.inlay_hint_cache().version;
|
let current_cache_version = editor.inlay_hint_cache_version();
|
||||||
let minimum_expected_version = last_scroll_update_version + expected_hints.len();
|
let minimum_expected_version = last_scroll_update_version + expected_hints.len();
|
||||||
assert!(
|
assert!(
|
||||||
current_cache_version == minimum_expected_version || current_cache_version == minimum_expected_version + 1,
|
current_cache_version == minimum_expected_version || current_cache_version == minimum_expected_version + 1,
|
||||||
|
@ -2953,7 +2967,7 @@ all hints should be invalidated and requeried for all of its visible excerpts"
|
||||||
"All hints are disabled and should not be shown despite being present in the cache"
|
"All hints are disabled and should not be shown despite being present in the cache"
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
editor.inlay_hint_cache().version,
|
editor.inlay_hint_cache_version(),
|
||||||
2,
|
2,
|
||||||
"Cache should update once per excerpt query"
|
"Cache should update once per excerpt query"
|
||||||
);
|
);
|
||||||
|
@ -2976,7 +2990,7 @@ all hints should be invalidated and requeried for all of its visible excerpts"
|
||||||
"All hints are disabled and should not be shown despite being present in the cache"
|
"All hints are disabled and should not be shown despite being present in the cache"
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
editor.inlay_hint_cache().version,
|
editor.inlay_hint_cache_version(),
|
||||||
3,
|
3,
|
||||||
"Excerpt removal should trigger a cache update"
|
"Excerpt removal should trigger a cache update"
|
||||||
);
|
);
|
||||||
|
@ -3004,7 +3018,7 @@ all hints should be invalidated and requeried for all of its visible excerpts"
|
||||||
"Settings change should make cached hints visible"
|
"Settings change should make cached hints visible"
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
editor.inlay_hint_cache().version,
|
editor.inlay_hint_cache_version(),
|
||||||
4,
|
4,
|
||||||
"Settings change should trigger a cache update"
|
"Settings change should trigger a cache update"
|
||||||
);
|
);
|
||||||
|
@ -3114,7 +3128,7 @@ all hints should be invalidated and requeried for all of its visible excerpts"
|
||||||
let expected_hints = vec!["1".to_string()];
|
let expected_hints = vec!["1".to_string()];
|
||||||
assert_eq!(expected_hints, cached_hint_labels(editor));
|
assert_eq!(expected_hints, cached_hint_labels(editor));
|
||||||
assert_eq!(expected_hints, visible_hint_labels(editor, cx));
|
assert_eq!(expected_hints, visible_hint_labels(editor, cx));
|
||||||
assert_eq!(editor.inlay_hint_cache().version, 1);
|
assert_eq!(editor.inlay_hint_cache_version(), 1);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3171,7 +3185,7 @@ all hints should be invalidated and requeried for all of its visible excerpts"
|
||||||
);
|
);
|
||||||
assert_eq!(expected_hints, visible_hint_labels(editor, cx));
|
assert_eq!(expected_hints, visible_hint_labels(editor, cx));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
editor.inlay_hint_cache().version,
|
editor.inlay_hint_cache_version(),
|
||||||
1,
|
1,
|
||||||
"First toggle should be cache's first update"
|
"First toggle should be cache's first update"
|
||||||
);
|
);
|
||||||
|
@ -3187,7 +3201,7 @@ all hints should be invalidated and requeried for all of its visible excerpts"
|
||||||
"Should clear hints after 2nd toggle"
|
"Should clear hints after 2nd toggle"
|
||||||
);
|
);
|
||||||
assert!(visible_hint_labels(editor, cx).is_empty());
|
assert!(visible_hint_labels(editor, cx).is_empty());
|
||||||
assert_eq!(editor.inlay_hint_cache().version, 2);
|
assert_eq!(editor.inlay_hint_cache_version(), 2);
|
||||||
});
|
});
|
||||||
|
|
||||||
update_test_language_settings(cx, |settings| {
|
update_test_language_settings(cx, |settings| {
|
||||||
|
@ -3207,7 +3221,7 @@ all hints should be invalidated and requeried for all of its visible excerpts"
|
||||||
"Should query LSP hints for the 2nd time after enabling hints in settings"
|
"Should query LSP hints for the 2nd time after enabling hints in settings"
|
||||||
);
|
);
|
||||||
assert_eq!(expected_hints, visible_hint_labels(editor, cx));
|
assert_eq!(expected_hints, visible_hint_labels(editor, cx));
|
||||||
assert_eq!(editor.inlay_hint_cache().version, 3);
|
assert_eq!(editor.inlay_hint_cache_version(), 3);
|
||||||
});
|
});
|
||||||
|
|
||||||
editor.update(cx, |editor, cx| {
|
editor.update(cx, |editor, cx| {
|
||||||
|
@ -3220,7 +3234,7 @@ all hints should be invalidated and requeried for all of its visible excerpts"
|
||||||
"Should clear hints after enabling in settings and a 3rd toggle"
|
"Should clear hints after enabling in settings and a 3rd toggle"
|
||||||
);
|
);
|
||||||
assert!(visible_hint_labels(editor, cx).is_empty());
|
assert!(visible_hint_labels(editor, cx).is_empty());
|
||||||
assert_eq!(editor.inlay_hint_cache().version, 4);
|
assert_eq!(editor.inlay_hint_cache_version(), 4);
|
||||||
});
|
});
|
||||||
|
|
||||||
editor.update(cx, |editor, cx| {
|
editor.update(cx, |editor, cx| {
|
||||||
|
@ -3235,7 +3249,7 @@ all hints should be invalidated and requeried for all of its visible excerpts"
|
||||||
"Should query LSP hints for the 3rd time after enabling hints in settings and toggling them back on"
|
"Should query LSP hints for the 3rd time after enabling hints in settings and toggling them back on"
|
||||||
);
|
);
|
||||||
assert_eq!(expected_hints, visible_hint_labels(editor, cx));
|
assert_eq!(expected_hints, visible_hint_labels(editor, cx));
|
||||||
assert_eq!(editor.inlay_hint_cache().version, 5);
|
assert_eq!(editor.inlay_hint_cache_version(), 5);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3318,7 +3332,7 @@ all hints should be invalidated and requeried for all of its visible excerpts"
|
||||||
editor.update(cx, |editor, cx| {
|
editor.update(cx, |editor, cx| {
|
||||||
assert!(cached_hint_labels(editor).is_empty());
|
assert!(cached_hint_labels(editor).is_empty());
|
||||||
assert!(visible_hint_labels(editor, cx).is_empty());
|
assert!(visible_hint_labels(editor, cx).is_empty());
|
||||||
assert_eq!(editor.inlay_hint_cache().version, 0);
|
assert_eq!(editor.inlay_hint_cache_version(), 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
("/a/main.rs", editor, fake_server)
|
("/a/main.rs", editor, fake_server)
|
||||||
|
|
|
@ -178,6 +178,9 @@ pub fn update_inlay_link_and_hover_points(
|
||||||
let mut go_to_definition_updated = false;
|
let mut go_to_definition_updated = false;
|
||||||
let mut hover_updated = false;
|
let mut hover_updated = false;
|
||||||
if let Some(hovered_offset) = hovered_offset {
|
if let Some(hovered_offset) = hovered_offset {
|
||||||
|
let Some(inlay_hint_cache) = editor.inlay_hints.clone() else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
let buffer_snapshot = editor.buffer().read(cx).snapshot(cx);
|
let buffer_snapshot = editor.buffer().read(cx).snapshot(cx);
|
||||||
let previous_valid_anchor = buffer_snapshot.anchor_at(
|
let previous_valid_anchor = buffer_snapshot.anchor_at(
|
||||||
point_for_position.previous_valid.to_point(snapshot),
|
point_for_position.previous_valid.to_point(snapshot),
|
||||||
|
@ -202,82 +205,84 @@ pub fn update_inlay_link_and_hover_points(
|
||||||
})
|
})
|
||||||
.max_by_key(|hint| hint.id)
|
.max_by_key(|hint| hint.id)
|
||||||
{
|
{
|
||||||
let inlay_hint_cache = editor.inlay_hint_cache();
|
|
||||||
let excerpt_id = previous_valid_anchor.excerpt_id;
|
let excerpt_id = previous_valid_anchor.excerpt_id;
|
||||||
if let Some(cached_hint) = inlay_hint_cache.hint_by_id(excerpt_id, hovered_hint.id) {
|
inlay_hint_cache.update(cx, |inlay_hint_cache, cx| {
|
||||||
match cached_hint.resolve_state {
|
if let Some(cached_hint) = inlay_hint_cache.hint_by_id(excerpt_id, hovered_hint.id)
|
||||||
ResolveState::CanResolve(_, _) => {
|
{
|
||||||
if let Some(buffer_id) = previous_valid_anchor.buffer_id {
|
match cached_hint.resolve_state {
|
||||||
inlay_hint_cache.spawn_hint_resolve(
|
ResolveState::CanResolve(_, _) => {
|
||||||
buffer_id,
|
if let Some(buffer_id) = previous_valid_anchor.buffer_id {
|
||||||
excerpt_id,
|
inlay_hint_cache.spawn_hint_resolve(
|
||||||
hovered_hint.id,
|
buffer_id,
|
||||||
cx,
|
excerpt_id,
|
||||||
);
|
hovered_hint.id,
|
||||||
}
|
cx,
|
||||||
}
|
);
|
||||||
ResolveState::Resolved => {
|
|
||||||
let mut extra_shift_left = 0;
|
|
||||||
let mut extra_shift_right = 0;
|
|
||||||
if cached_hint.padding_left {
|
|
||||||
extra_shift_left += 1;
|
|
||||||
extra_shift_right += 1;
|
|
||||||
}
|
|
||||||
if cached_hint.padding_right {
|
|
||||||
extra_shift_right += 1;
|
|
||||||
}
|
|
||||||
match cached_hint.label {
|
|
||||||
project::InlayHintLabel::String(_) => {
|
|
||||||
if let Some(tooltip) = cached_hint.tooltip {
|
|
||||||
hover_popover::hover_at_inlay(
|
|
||||||
editor,
|
|
||||||
InlayHover {
|
|
||||||
excerpt: excerpt_id,
|
|
||||||
tooltip: match tooltip {
|
|
||||||
InlayHintTooltip::String(text) => HoverBlock {
|
|
||||||
text,
|
|
||||||
kind: HoverBlockKind::PlainText,
|
|
||||||
},
|
|
||||||
InlayHintTooltip::MarkupContent(content) => {
|
|
||||||
HoverBlock {
|
|
||||||
text: content.value,
|
|
||||||
kind: content.kind,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
range: InlayHighlight {
|
|
||||||
inlay: hovered_hint.id,
|
|
||||||
inlay_position: hovered_hint.position,
|
|
||||||
range: extra_shift_left
|
|
||||||
..hovered_hint.text.len() + extra_shift_right,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
cx,
|
|
||||||
);
|
|
||||||
hover_updated = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
project::InlayHintLabel::LabelParts(label_parts) => {
|
}
|
||||||
let hint_start =
|
ResolveState::Resolved => {
|
||||||
snapshot.anchor_to_inlay_offset(hovered_hint.position);
|
let mut extra_shift_left = 0;
|
||||||
if let Some((hovered_hint_part, part_range)) =
|
let mut extra_shift_right = 0;
|
||||||
hover_popover::find_hovered_hint_part(
|
if cached_hint.padding_left {
|
||||||
label_parts,
|
extra_shift_left += 1;
|
||||||
hint_start,
|
extra_shift_right += 1;
|
||||||
hovered_offset,
|
}
|
||||||
)
|
if cached_hint.padding_right {
|
||||||
{
|
extra_shift_right += 1;
|
||||||
let highlight_start =
|
}
|
||||||
(part_range.start - hint_start).0 + extra_shift_left;
|
match cached_hint.label {
|
||||||
let highlight_end =
|
project::InlayHintLabel::String(_) => {
|
||||||
(part_range.end - hint_start).0 + extra_shift_right;
|
if let Some(tooltip) = cached_hint.tooltip {
|
||||||
let highlight = InlayHighlight {
|
|
||||||
inlay: hovered_hint.id,
|
|
||||||
inlay_position: hovered_hint.position,
|
|
||||||
range: highlight_start..highlight_end,
|
|
||||||
};
|
|
||||||
if let Some(tooltip) = hovered_hint_part.tooltip {
|
|
||||||
hover_popover::hover_at_inlay(
|
hover_popover::hover_at_inlay(
|
||||||
|
editor,
|
||||||
|
InlayHover {
|
||||||
|
excerpt: excerpt_id,
|
||||||
|
tooltip: match tooltip {
|
||||||
|
InlayHintTooltip::String(text) => HoverBlock {
|
||||||
|
text,
|
||||||
|
kind: HoverBlockKind::PlainText,
|
||||||
|
},
|
||||||
|
InlayHintTooltip::MarkupContent(content) => {
|
||||||
|
HoverBlock {
|
||||||
|
text: content.value,
|
||||||
|
kind: content.kind,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
range: InlayHighlight {
|
||||||
|
inlay: hovered_hint.id,
|
||||||
|
inlay_position: hovered_hint.position,
|
||||||
|
range: extra_shift_left
|
||||||
|
..hovered_hint.text.len()
|
||||||
|
+ extra_shift_right,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
cx,
|
||||||
|
);
|
||||||
|
hover_updated = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
project::InlayHintLabel::LabelParts(label_parts) => {
|
||||||
|
let hint_start =
|
||||||
|
snapshot.anchor_to_inlay_offset(hovered_hint.position);
|
||||||
|
if let Some((hovered_hint_part, part_range)) =
|
||||||
|
hover_popover::find_hovered_hint_part(
|
||||||
|
label_parts,
|
||||||
|
hint_start,
|
||||||
|
hovered_offset,
|
||||||
|
)
|
||||||
|
{
|
||||||
|
let highlight_start =
|
||||||
|
(part_range.start - hint_start).0 + extra_shift_left;
|
||||||
|
let highlight_end =
|
||||||
|
(part_range.end - hint_start).0 + extra_shift_right;
|
||||||
|
let highlight = InlayHighlight {
|
||||||
|
inlay: hovered_hint.id,
|
||||||
|
inlay_position: hovered_hint.position,
|
||||||
|
range: highlight_start..highlight_end,
|
||||||
|
};
|
||||||
|
if let Some(tooltip) = hovered_hint_part.tooltip {
|
||||||
|
hover_popover::hover_at_inlay(
|
||||||
editor,
|
editor,
|
||||||
InlayHover {
|
InlayHover {
|
||||||
excerpt: excerpt_id,
|
excerpt: excerpt_id,
|
||||||
|
@ -299,31 +304,32 @@ pub fn update_inlay_link_and_hover_points(
|
||||||
},
|
},
|
||||||
cx,
|
cx,
|
||||||
);
|
);
|
||||||
hover_updated = true;
|
hover_updated = true;
|
||||||
}
|
}
|
||||||
if let Some((language_server_id, location)) =
|
if let Some((language_server_id, location)) =
|
||||||
hovered_hint_part.location
|
hovered_hint_part.location
|
||||||
{
|
{
|
||||||
go_to_definition_updated = true;
|
go_to_definition_updated = true;
|
||||||
update_go_to_definition_link(
|
update_go_to_definition_link(
|
||||||
editor,
|
editor,
|
||||||
Some(GoToDefinitionTrigger::InlayHint(
|
Some(GoToDefinitionTrigger::InlayHint(
|
||||||
highlight,
|
highlight,
|
||||||
location,
|
location,
|
||||||
language_server_id,
|
language_server_id,
|
||||||
)),
|
)),
|
||||||
cmd_held,
|
cmd_held,
|
||||||
shift_held,
|
shift_held,
|
||||||
cx,
|
cx,
|
||||||
);
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
};
|
}
|
||||||
|
ResolveState::Resolving => {}
|
||||||
}
|
}
|
||||||
ResolveState::Resolving => {}
|
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue