Compare commits
14 commits
main
...
editor_tea
Author | SHA1 | Date | |
---|---|---|---|
![]() |
575e193ea3 | ||
![]() |
a9e3d8c9a4 | ||
![]() |
b11d1e2db8 | ||
![]() |
e6448d7f71 | ||
![]() |
8996ef9d20 | ||
![]() |
c0f6075302 | ||
![]() |
f93b23cfc4 | ||
![]() |
9e60c836e0 | ||
![]() |
1a5897e264 | ||
![]() |
1724d5dde2 | ||
![]() |
ebe8e7d4a0 | ||
![]() |
722a508c2e | ||
![]() |
840309a6b7 | ||
![]() |
c961a1cd2b |
7 changed files with 1555 additions and 1189 deletions
|
@ -5796,7 +5796,7 @@ async fn test_collaborating_with_renames(
|
|||
prepare_rename.await.unwrap();
|
||||
editor_b.update(cx_b, |editor, cx| {
|
||||
use editor::ToOffset;
|
||||
let rename = editor.pending_rename().unwrap();
|
||||
let rename = editor.pending_rename(cx).unwrap();
|
||||
let buffer = editor.buffer().read(cx).snapshot(cx);
|
||||
assert_eq!(
|
||||
rename.range.start.to_offset(&buffer)..rename.range.end.to_offset(&buffer),
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -2,8 +2,9 @@ use super::*;
|
|||
use crate::{
|
||||
scroll::scroll_amount::ScrollAmount,
|
||||
test::{
|
||||
assert_text_with_selections, build_editor, editor_lsp_test_context::EditorLspTestContext,
|
||||
editor_test_context::EditorTestContext, select_ranges,
|
||||
assert_text_with_selections, build_editor, build_editor_with_project,
|
||||
editor_lsp_test_context::EditorLspTestContext, editor_test_context::EditorTestContext,
|
||||
select_ranges,
|
||||
},
|
||||
JoinLines,
|
||||
};
|
||||
|
@ -4895,7 +4896,9 @@ async fn test_document_format_during_save(cx: &mut gpui::TestAppContext) {
|
|||
let fake_server = fake_servers.next().await.unwrap();
|
||||
|
||||
let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
|
||||
let editor = cx.add_window(|cx| build_editor(buffer, cx)).root(cx);
|
||||
let editor = cx
|
||||
.add_window(|cx| build_editor_with_project(project.clone(), buffer, cx))
|
||||
.root(cx);
|
||||
editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
|
||||
assert!(cx.read(|cx| editor.is_dirty(cx)));
|
||||
|
||||
|
@ -5007,7 +5010,9 @@ async fn test_range_format_during_save(cx: &mut gpui::TestAppContext) {
|
|||
let fake_server = fake_servers.next().await.unwrap();
|
||||
|
||||
let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
|
||||
let editor = cx.add_window(|cx| build_editor(buffer, cx)).root(cx);
|
||||
let editor = cx
|
||||
.add_window(|cx| build_editor_with_project(project.clone(), buffer, cx))
|
||||
.root(cx);
|
||||
editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
|
||||
assert!(cx.read(|cx| editor.is_dirty(cx)));
|
||||
|
||||
|
@ -5128,11 +5133,13 @@ async fn test_document_format_manual_trigger(cx: &mut gpui::TestAppContext) {
|
|||
let fake_server = fake_servers.next().await.unwrap();
|
||||
|
||||
let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
|
||||
let editor = cx.add_window(|cx| build_editor(buffer, cx)).root(cx);
|
||||
let editor = cx
|
||||
.add_window(|cx| build_editor_with_project(project, buffer, cx))
|
||||
.root(cx);
|
||||
editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
|
||||
|
||||
let format = editor.update(cx, |editor, cx| {
|
||||
editor.perform_format(project.clone(), FormatTrigger::Manual, cx)
|
||||
editor.perform_format(FormatTrigger::Manual, cx)
|
||||
});
|
||||
fake_server
|
||||
.handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
|
||||
|
@ -5149,7 +5156,7 @@ async fn test_document_format_manual_trigger(cx: &mut gpui::TestAppContext) {
|
|||
.next()
|
||||
.await;
|
||||
cx.foreground().start_waiting();
|
||||
format.await.unwrap();
|
||||
format.unwrap().await.unwrap();
|
||||
assert_eq!(
|
||||
editor.read_with(cx, |editor, cx| editor.text(cx)),
|
||||
"one, two\nthree\n"
|
||||
|
@ -5166,11 +5173,11 @@ async fn test_document_format_manual_trigger(cx: &mut gpui::TestAppContext) {
|
|||
unreachable!()
|
||||
});
|
||||
let format = editor.update(cx, |editor, cx| {
|
||||
editor.perform_format(project, FormatTrigger::Manual, cx)
|
||||
editor.perform_format(FormatTrigger::Manual, cx)
|
||||
});
|
||||
cx.foreground().advance_clock(super::FORMAT_TIMEOUT);
|
||||
cx.foreground().start_waiting();
|
||||
format.await.unwrap();
|
||||
format.unwrap().await.unwrap();
|
||||
assert_eq!(
|
||||
editor.read_with(cx, |editor, cx| editor.text(cx)),
|
||||
"one\ntwo\nthree\n"
|
||||
|
@ -8010,13 +8017,15 @@ async fn test_document_format_with_prettier(cx: &mut gpui::TestAppContext) {
|
|||
|
||||
let buffer_text = "one\ntwo\nthree\n";
|
||||
let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
|
||||
let editor = cx.add_window(|cx| build_editor(buffer, cx)).root(cx);
|
||||
let editor = cx
|
||||
.add_window(|cx| build_editor_with_project(project.clone(), buffer, cx))
|
||||
.root(cx);
|
||||
editor.update(cx, |editor, cx| editor.set_text(buffer_text, cx));
|
||||
|
||||
let format = editor.update(cx, |editor, cx| {
|
||||
editor.perform_format(project.clone(), FormatTrigger::Manual, cx)
|
||||
editor.perform_format(FormatTrigger::Manual, cx)
|
||||
});
|
||||
format.await.unwrap();
|
||||
format.unwrap().await.unwrap();
|
||||
assert_eq!(
|
||||
editor.read_with(cx, |editor, cx| editor.text(cx)),
|
||||
buffer_text.to_string() + prettier_format_suffix,
|
||||
|
@ -8027,9 +8036,9 @@ async fn test_document_format_with_prettier(cx: &mut gpui::TestAppContext) {
|
|||
settings.defaults.formatter = Some(language_settings::Formatter::Auto)
|
||||
});
|
||||
let format = editor.update(cx, |editor, cx| {
|
||||
editor.perform_format(project.clone(), FormatTrigger::Manual, cx)
|
||||
editor.perform_format(FormatTrigger::Manual, cx)
|
||||
});
|
||||
format.await.unwrap();
|
||||
format.unwrap().await.unwrap();
|
||||
assert_eq!(
|
||||
editor.read_with(cx, |editor, cx| editor.text(cx)),
|
||||
buffer_text.to_string() + prettier_format_suffix + "\n" + prettier_format_suffix,
|
||||
|
|
|
@ -80,7 +80,7 @@ pub fn find_hovered_hint_part(
|
|||
|
||||
pub fn hover_at_inlay(editor: &mut Editor, inlay_hover: InlayHover, cx: &mut ViewContext<Editor>) {
|
||||
if settings::get::<EditorSettings>(cx).hover_popover_enabled {
|
||||
if editor.pending_rename.is_some() {
|
||||
if editor.has_pending_rename(cx) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -166,7 +166,7 @@ fn show_hover(
|
|||
ignore_timeout: bool,
|
||||
cx: &mut ViewContext<Editor>,
|
||||
) {
|
||||
if editor.pending_rename.is_some() {
|
||||
if editor.has_pending_rename(cx) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -11,10 +11,10 @@ use crate::{
|
|||
use anyhow::Context;
|
||||
use clock::Global;
|
||||
use futures::future;
|
||||
use gpui::{ModelContext, ModelHandle, Task, ViewContext};
|
||||
use gpui::{Entity, ModelContext, ModelHandle, Task, ViewContext};
|
||||
use language::{language_settings::InlayHintKind, Buffer, BufferSnapshot};
|
||||
use parking_lot::RwLock;
|
||||
use project::{InlayHint, ResolveState};
|
||||
use project::{InlayHint, Project, ResolveState};
|
||||
|
||||
use collections::{hash_map, HashMap, HashSet};
|
||||
use language::language_settings::InlayHintSettings;
|
||||
|
@ -24,9 +24,11 @@ use text::{ToOffset, ToPoint};
|
|||
use util::post_inc;
|
||||
|
||||
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>>,
|
||||
version: usize,
|
||||
pub(super) version: usize,
|
||||
pub(super) enabled: bool,
|
||||
update_tasks: HashMap<ExcerptId, TasksForRanges>,
|
||||
lsp_request_limiter: Arc<Semaphore>,
|
||||
|
@ -236,9 +238,13 @@ impl TasksForRanges {
|
|||
}
|
||||
}
|
||||
|
||||
impl Entity for InlayHintCache {
|
||||
type Event = ();
|
||||
}
|
||||
impl InlayHintCache {
|
||||
pub fn new(inlay_hint_settings: InlayHintSettings) -> Self {
|
||||
pub fn new(project: ModelHandle<Project>, inlay_hint_settings: InlayHintSettings) -> Self {
|
||||
Self {
|
||||
project,
|
||||
allowed_hint_kinds: inlay_hint_settings.enabled_inlay_hint_kinds(),
|
||||
enabled: inlay_hint_settings.enabled,
|
||||
hints: HashMap::default(),
|
||||
|
@ -304,6 +310,7 @@ impl InlayHintCache {
|
|||
reason: &'static str,
|
||||
excerpts_to_query: HashMap<ExcerptId, (ModelHandle<Buffer>, Global, Range<usize>)>,
|
||||
invalidate: InvalidationStrategy,
|
||||
cache: ModelHandle<Self>,
|
||||
cx: &mut ViewContext<Editor>,
|
||||
) -> Option<InlaySplice> {
|
||||
if !self.enabled {
|
||||
|
@ -336,6 +343,7 @@ impl InlayHintCache {
|
|||
excerpts_to_query,
|
||||
invalidate,
|
||||
cache_version,
|
||||
cache,
|
||||
cx,
|
||||
)
|
||||
})
|
||||
|
@ -538,7 +546,7 @@ impl InlayHintCache {
|
|||
.read(cx)
|
||||
.buffer(buffer_id)
|
||||
.and_then(|buffer| {
|
||||
let project = editor.project.as_ref()?;
|
||||
let project = self.project;
|
||||
Some(project.update(cx, |project, cx| {
|
||||
project.resolve_inlay_hint(
|
||||
hint_to_resolve,
|
||||
|
@ -582,6 +590,7 @@ fn spawn_new_update_tasks(
|
|||
excerpts_to_query: HashMap<ExcerptId, (ModelHandle<Buffer>, Global, Range<usize>)>,
|
||||
invalidate: InvalidationStrategy,
|
||||
update_cache_version: usize,
|
||||
cache: ModelHandle<InlayHintCache>,
|
||||
cx: &mut ViewContext<'_, '_, Editor>,
|
||||
) {
|
||||
let visible_hints = Arc::new(editor.visible_inlay_hints(cx));
|
||||
|
@ -601,7 +610,8 @@ fn spawn_new_update_tasks(
|
|||
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 {
|
||||
let cached_excerpt_hints = cached_excerpt_hints.read();
|
||||
let cached_buffer_version = &cached_excerpt_hints.buffer_version;
|
||||
|
@ -636,35 +646,39 @@ fn spawn_new_update_tasks(
|
|||
reason,
|
||||
};
|
||||
|
||||
let new_update_task = |query_ranges| {
|
||||
new_update_task(
|
||||
query,
|
||||
query_ranges,
|
||||
multi_buffer_snapshot,
|
||||
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,
|
||||
let cache_handle = cache.clone();
|
||||
cache.update(cx, |cache, _| {
|
||||
let new_update_task = |query_ranges| {
|
||||
new_update_task(
|
||||
query,
|
||||
query_ranges,
|
||||
invalidate,
|
||||
new_update_task,
|
||||
);
|
||||
multi_buffer_snapshot,
|
||||
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>>,
|
||||
cached_excerpt_hints: Option<Arc<RwLock<CachedExcerptHints>>>,
|
||||
lsp_request_limiter: Arc<Semaphore>,
|
||||
cache: ModelHandle<InlayHintCache>,
|
||||
cx: &mut ViewContext<'_, '_, Editor>,
|
||||
) -> Task<()> {
|
||||
cx.spawn(|editor, mut cx| async move {
|
||||
|
@ -775,6 +790,7 @@ fn new_update_task(
|
|||
invalidate,
|
||||
range,
|
||||
Arc::clone(&lsp_request_limiter),
|
||||
cache,
|
||||
closure_cx.clone(),
|
||||
)
|
||||
};
|
||||
|
@ -795,13 +811,9 @@ fn new_update_task(
|
|||
|
||||
let mut query_range_failed = |range: &Range<language::Anchor>, e: anyhow::Error| {
|
||||
log::error!("inlay hint update task for range {range:?} failed: {e:#}");
|
||||
editor
|
||||
.update(&mut cx, |editor, _| {
|
||||
if let Some(task_ranges) = editor
|
||||
.inlay_hint_cache
|
||||
.update_tasks
|
||||
.get_mut(&query.excerpt_id)
|
||||
{
|
||||
cache
|
||||
.update(&mut cx, |cache, _| {
|
||||
if let Some(task_ranges) = cache.update_tasks.get_mut(&query.excerpt_id) {
|
||||
task_ranges.invalidate_range(&buffer_snapshot, &range);
|
||||
}
|
||||
})
|
||||
|
@ -846,6 +858,7 @@ async fn fetch_and_update_hints(
|
|||
invalidate: bool,
|
||||
fetch_range: Range<language::Anchor>,
|
||||
lsp_request_limiter: Arc<Semaphore>,
|
||||
cache: ModelHandle<InlayHintCache>,
|
||||
mut cx: gpui::AsyncAppContext,
|
||||
) -> anyhow::Result<()> {
|
||||
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 {
|
||||
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
|
||||
.inlay_hint_cache
|
||||
.update_tasks
|
||||
.get_mut(&query.excerpt_id)
|
||||
{
|
||||
task_ranges.invalidate_range(&buffer_snapshot, &fetch_range);
|
||||
}
|
||||
cache.update(cx, |cache, _| {
|
||||
if let Some(task_ranges) = cache
|
||||
.update_tasks
|
||||
.get_mut(&query.excerpt_id)
|
||||
{
|
||||
task_ranges.invalidate_range(&buffer_snapshot, &fetch_range);
|
||||
}
|
||||
});
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
@ -895,7 +909,7 @@ async fn fetch_and_update_hints(
|
|||
.read(cx)
|
||||
.buffer(query.buffer_id)
|
||||
.and_then(|buffer| {
|
||||
let project = editor.project.as_ref()?;
|
||||
let project = cache.read(cx).project;
|
||||
Some(project.update(cx, |project, cx| {
|
||||
project.inlay_hints(buffer, fetch_range.clone(), cx)
|
||||
}))
|
||||
|
@ -957,6 +971,7 @@ async fn fetch_and_update_hints(
|
|||
invalidate,
|
||||
buffer_snapshot,
|
||||
multi_buffer_snapshot,
|
||||
cache,
|
||||
cx,
|
||||
);
|
||||
})
|
||||
|
@ -1071,13 +1086,11 @@ fn apply_hint_update(
|
|||
invalidate: bool,
|
||||
buffer_snapshot: BufferSnapshot,
|
||||
multi_buffer_snapshot: MultiBufferSnapshot,
|
||||
cache: ModelHandle<InlayHintsCache>,
|
||||
cx: &mut ViewContext<'_, '_, Editor>,
|
||||
) {
|
||||
let cached_excerpt_hints = editor
|
||||
.inlay_hint_cache
|
||||
.hints
|
||||
.entry(new_update.excerpt_id)
|
||||
.or_insert_with(|| {
|
||||
cache.update(cx, |cache, cx| {
|
||||
let cached_excerpt_hints = cache.hints.entry(new_update.excerpt_id).or_insert_with(|| {
|
||||
Arc::new(RwLock::new(CachedExcerptHints {
|
||||
version: query.cache_version,
|
||||
buffer_version: buffer_snapshot.version().clone(),
|
||||
|
@ -1086,112 +1099,111 @@ fn apply_hint_update(
|
|||
hints_by_id: HashMap::default(),
|
||||
}))
|
||||
});
|
||||
let mut cached_excerpt_hints = cached_excerpt_hints.write();
|
||||
match query.cache_version.cmp(&cached_excerpt_hints.version) {
|
||||
cmp::Ordering::Less => return,
|
||||
cmp::Ordering::Greater | cmp::Ordering::Equal => {
|
||||
cached_excerpt_hints.version = query.cache_version;
|
||||
let mut cached_excerpt_hints = cached_excerpt_hints.write();
|
||||
match query.cache_version.cmp(&cached_excerpt_hints.version) {
|
||||
cmp::Ordering::Less => return,
|
||||
cmp::Ordering::Greater | cmp::Ordering::Equal => {
|
||||
cached_excerpt_hints.version = query.cache_version;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut cached_inlays_changed = !new_update.remove_from_cache.is_empty();
|
||||
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
|
||||
let mut cached_inlays_changed = !new_update.remove_from_cache.is_empty();
|
||||
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),
|
||||
.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
|
||||
.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 {
|
||||
let new_inlay_id = post_inc(&mut editor.next_inlay_id);
|
||||
if editor
|
||||
.inlay_hint_cache
|
||||
.allowed_hint_kinds
|
||||
.contains(&new_hint.kind)
|
||||
{
|
||||
let new_hint_position =
|
||||
multi_buffer_snapshot.anchor_in_excerpt(query.excerpt_id, new_hint.position);
|
||||
splice
|
||||
.to_insert
|
||||
.push(Inlay::hint(new_inlay_id, new_hint_position, &new_hint));
|
||||
}
|
||||
let new_id = InlayId::Hint(new_inlay_id);
|
||||
cached_excerpt_hints.hints_by_id.insert(new_id, new_hint);
|
||||
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());
|
||||
if let Some(insert_position) = insert_position {
|
||||
let new_inlay_id = post_inc(&mut editor.next_inlay_id);
|
||||
if cache.allowed_hint_kinds.contains(&new_hint.kind) {
|
||||
let new_hint_position = multi_buffer_snapshot
|
||||
.anchor_in_excerpt(query.excerpt_id, new_hint.position);
|
||||
splice
|
||||
.to_insert
|
||||
.push(Inlay::hint(new_inlay_id, new_hint_position, &new_hint));
|
||||
}
|
||||
let new_id = InlayId::Hint(new_inlay_id);
|
||||
cached_excerpt_hints.hints_by_id.insert(new_id, new_hint);
|
||||
cached_excerpt_hints
|
||||
.ordered_hints
|
||||
.insert(insert_position, new_id);
|
||||
cached_inlays_changed = true;
|
||||
}
|
||||
}
|
||||
cached_inlays_changed |= !outdated_excerpt_caches.is_empty();
|
||||
editor
|
||||
.inlay_hint_cache
|
||||
.hints
|
||||
.retain(|excerpt_id, _| !outdated_excerpt_caches.contains(excerpt_id));
|
||||
}
|
||||
cached_excerpt_hints.buffer_version = buffer_snapshot.version().clone();
|
||||
drop(cached_excerpt_hints);
|
||||
});
|
||||
|
||||
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 {
|
||||
editor.inlay_hint_cache.version += 1;
|
||||
}
|
||||
if displayed_inlays_changed {
|
||||
editor.splice_inlay_hints(to_remove, to_insert, cx)
|
||||
}
|
||||
cache.update(cx, |cache, _| {
|
||||
if invalidate {
|
||||
let mut outdated_excerpt_caches = HashSet::default();
|
||||
for (excerpt_id, excerpt_hints) in &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();
|
||||
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)]
|
||||
|
@ -1287,7 +1299,8 @@ pub mod tests {
|
|||
"Cache should use editor settings to get the allowed hint kinds"
|
||||
);
|
||||
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"
|
||||
);
|
||||
});
|
||||
|
@ -1312,7 +1325,8 @@ pub mod tests {
|
|||
"Cache should use editor settings to get the allowed hint kinds"
|
||||
);
|
||||
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"
|
||||
);
|
||||
});
|
||||
|
@ -1392,7 +1406,7 @@ pub mod tests {
|
|||
);
|
||||
assert_eq!(expected_hints, visible_hint_labels(editor, cx));
|
||||
assert_eq!(
|
||||
editor.inlay_hint_cache().version,
|
||||
editor.inlay_hint_cache_version(),
|
||||
edits_made,
|
||||
"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!(
|
||||
editor.inlay_hint_cache().version,
|
||||
editor.inlay_hint_cache_version(),
|
||||
edits_made,
|
||||
"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!(
|
||||
editor.inlay_hint_cache().version,
|
||||
editor.inlay_hint_cache_version(),
|
||||
edits_made,
|
||||
"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!(
|
||||
editor.inlay_hint_cache().version,
|
||||
editor.inlay_hint_cache_version(),
|
||||
1,
|
||||
"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"
|
||||
);
|
||||
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| {
|
||||
|
@ -1640,7 +1654,7 @@ pub mod tests {
|
|||
);
|
||||
assert_eq!(expected_hints, visible_hint_labels(editor, cx));
|
||||
assert_eq!(
|
||||
editor.inlay_hint_cache().version,
|
||||
editor.inlay_hint_cache_version(),
|
||||
2,
|
||||
"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"
|
||||
);
|
||||
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| {
|
||||
|
@ -1669,7 +1683,7 @@ pub mod tests {
|
|||
"Rust editor should not be affected by Markdown editor changes"
|
||||
);
|
||||
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| {
|
||||
let expected_hints = vec!["1".to_string()];
|
||||
|
@ -1679,7 +1693,7 @@ pub mod tests {
|
|||
"Markdown editor should also change independently"
|
||||
);
|
||||
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)
|
||||
);
|
||||
assert_eq!(
|
||||
editor.inlay_hint_cache().version,
|
||||
editor.inlay_hint_cache_version(),
|
||||
edits_made,
|
||||
"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!(visible_hint_labels(editor, cx).is_empty());
|
||||
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"
|
||||
);
|
||||
});
|
||||
|
@ -2007,7 +2021,7 @@ pub mod tests {
|
|||
vec!["parameter hint".to_string()],
|
||||
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!(
|
||||
editor.inlay_hint_cache().version, 1,
|
||||
editor.inlay_hint_cache_version(), 1,
|
||||
"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!(
|
||||
editor.inlay_hint_cache().version,
|
||||
editor.inlay_hint_cache_version(),
|
||||
2,
|
||||
"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!(
|
||||
editor.inlay_hint_cache().version, requests_count,
|
||||
editor.inlay_hint_cache_version(), requests_count,
|
||||
"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!(
|
||||
editor.inlay_hint_cache().version,
|
||||
editor.inlay_hint_cache_version(),
|
||||
lsp_requests,
|
||||
"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),
|
||||
"Should have hints from the new LSP response after the edit");
|
||||
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"
|
||||
);
|
||||
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| {
|
||||
|
@ -2680,7 +2694,7 @@ pub mod tests {
|
|||
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");
|
||||
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");
|
||||
});
|
||||
|
||||
|
@ -2711,7 +2725,7 @@ pub mod tests {
|
|||
assert_eq!(expected_hints, cached_hint_labels(editor),
|
||||
"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!(editor.inlay_hint_cache().version, expected_hints.len());
|
||||
assert_eq!(editor.inlay_hint_cache_version(), expected_hints.len());
|
||||
expected_hints.len()
|
||||
});
|
||||
|
||||
|
@ -2739,7 +2753,7 @@ pub mod tests {
|
|||
assert_eq!(expected_hints, cached_hint_labels(editor),
|
||||
"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!(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);
|
||||
|
@ -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));
|
||||
|
||||
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();
|
||||
assert!(
|
||||
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"
|
||||
);
|
||||
assert_eq!(
|
||||
editor.inlay_hint_cache().version,
|
||||
editor.inlay_hint_cache_version(),
|
||||
2,
|
||||
"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"
|
||||
);
|
||||
assert_eq!(
|
||||
editor.inlay_hint_cache().version,
|
||||
editor.inlay_hint_cache_version(),
|
||||
3,
|
||||
"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"
|
||||
);
|
||||
assert_eq!(
|
||||
editor.inlay_hint_cache().version,
|
||||
editor.inlay_hint_cache_version(),
|
||||
4,
|
||||
"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()];
|
||||
assert_eq!(expected_hints, cached_hint_labels(editor));
|
||||
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!(
|
||||
editor.inlay_hint_cache().version,
|
||||
editor.inlay_hint_cache_version(),
|
||||
1,
|
||||
"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"
|
||||
);
|
||||
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| {
|
||||
|
@ -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"
|
||||
);
|
||||
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| {
|
||||
|
@ -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"
|
||||
);
|
||||
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| {
|
||||
|
@ -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"
|
||||
);
|
||||
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| {
|
||||
assert!(cached_hint_labels(editor).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)
|
||||
|
|
|
@ -3,7 +3,7 @@ use crate::{
|
|||
movement::surrounding_word, persistence::DB, scroll::ScrollAnchor, Anchor, Autoscroll, Editor,
|
||||
Event, ExcerptId, ExcerptRange, MultiBuffer, MultiBufferSnapshot, NavigationData, ToPoint as _,
|
||||
};
|
||||
use anyhow::{Context, Result};
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use collections::HashSet;
|
||||
use futures::future::try_join_all;
|
||||
use gpui::{
|
||||
|
@ -652,7 +652,9 @@ impl Item for Editor {
|
|||
cx: &mut ViewContext<Self>,
|
||||
) -> Task<Result<()>> {
|
||||
self.report_editor_event("save", None, cx);
|
||||
let format = self.perform_format(project.clone(), FormatTrigger::Save, cx);
|
||||
let Some(format) = self.perform_format(FormatTrigger::Save, cx) else {
|
||||
return Task::ready(Err(anyhow!("Editor does not have a formatter attached")));
|
||||
};
|
||||
let buffers = self.buffer().clone().read(cx).all_buffers();
|
||||
cx.spawn(|_, mut cx| async move {
|
||||
format.await?;
|
||||
|
|
|
@ -178,6 +178,9 @@ pub fn update_inlay_link_and_hover_points(
|
|||
let mut go_to_definition_updated = false;
|
||||
let mut hover_updated = false;
|
||||
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 previous_valid_anchor = buffer_snapshot.anchor_at(
|
||||
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)
|
||||
{
|
||||
let inlay_hint_cache = editor.inlay_hint_cache();
|
||||
let excerpt_id = previous_valid_anchor.excerpt_id;
|
||||
if let Some(cached_hint) = inlay_hint_cache.hint_by_id(excerpt_id, hovered_hint.id) {
|
||||
match cached_hint.resolve_state {
|
||||
ResolveState::CanResolve(_, _) => {
|
||||
if let Some(buffer_id) = previous_valid_anchor.buffer_id {
|
||||
inlay_hint_cache.spawn_hint_resolve(
|
||||
buffer_id,
|
||||
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;
|
||||
}
|
||||
inlay_hint_cache.update(cx, |inlay_hint_cache, cx| {
|
||||
if let Some(cached_hint) = inlay_hint_cache.hint_by_id(excerpt_id, hovered_hint.id)
|
||||
{
|
||||
match cached_hint.resolve_state {
|
||||
ResolveState::CanResolve(_, _) => {
|
||||
if let Some(buffer_id) = previous_valid_anchor.buffer_id {
|
||||
inlay_hint_cache.spawn_hint_resolve(
|
||||
buffer_id,
|
||||
excerpt_id,
|
||||
hovered_hint.id,
|
||||
cx,
|
||||
);
|
||||
}
|
||||
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 {
|
||||
}
|
||||
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 =
|
||||
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,
|
||||
InlayHover {
|
||||
excerpt: excerpt_id,
|
||||
|
@ -299,31 +304,32 @@ pub fn update_inlay_link_and_hover_points(
|
|||
},
|
||||
cx,
|
||||
);
|
||||
hover_updated = true;
|
||||
}
|
||||
if let Some((language_server_id, location)) =
|
||||
hovered_hint_part.location
|
||||
{
|
||||
go_to_definition_updated = true;
|
||||
update_go_to_definition_link(
|
||||
editor,
|
||||
Some(GoToDefinitionTrigger::InlayHint(
|
||||
highlight,
|
||||
location,
|
||||
language_server_id,
|
||||
)),
|
||||
cmd_held,
|
||||
shift_held,
|
||||
cx,
|
||||
);
|
||||
hover_updated = true;
|
||||
}
|
||||
if let Some((language_server_id, location)) =
|
||||
hovered_hint_part.location
|
||||
{
|
||||
go_to_definition_updated = true;
|
||||
update_go_to_definition_link(
|
||||
editor,
|
||||
Some(GoToDefinitionTrigger::InlayHint(
|
||||
highlight,
|
||||
location,
|
||||
language_server_id,
|
||||
)),
|
||||
cmd_held,
|
||||
shift_held,
|
||||
cx,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
ResolveState::Resolving => {}
|
||||
}
|
||||
ResolveState::Resolving => {}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -353,7 +359,7 @@ pub fn show_link_definition(
|
|||
hide_link_definition(editor, cx);
|
||||
}
|
||||
|
||||
if editor.pending_rename.is_some() {
|
||||
if editor.has_pending_rename(cx) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue