Draft the hint render data flow

This commit is contained in:
Kirill Bulatov 2023-06-06 15:16:46 +03:00
parent 2ead3de7de
commit 4c3c0eb796
6 changed files with 103 additions and 24 deletions

View file

@ -30,6 +30,8 @@ pub use block_map::{
BlockDisposition, BlockId, BlockProperties, BlockStyle, RenderBlock, TransformBlock,
};
use self::editor_addition_map::InlayHintToRender;
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum FoldStatus {
Folded,
@ -286,6 +288,25 @@ impl DisplayMap {
.update(cx, |map, cx| map.set_wrap_width(width, cx))
}
pub fn set_inlay_hints(&self, new_hints: &[project::InlayHint], cx: &mut ModelContext<Self>) {
let multi_buffer = self.buffer.read(cx);
self.editor_addition_map.set_inlay_hints(
new_hints
.into_iter()
.filter_map(|hint| {
let buffer = multi_buffer.buffer(hint.buffer_id)?.read(cx);
let snapshot = buffer.snapshot();
Some(InlayHintToRender {
position: editor_addition_map::EditorAdditionPoint(
text::ToPoint::to_point(&hint.position, &snapshot),
),
text: hint.text().trim_end().into(),
})
})
.collect(),
)
}
fn tab_size(buffer: &ModelHandle<MultiBuffer>, cx: &mut ModelContext<Self>) -> NonZeroU32 {
let language = buffer
.read(cx)

View file

@ -10,17 +10,20 @@ use super::{
TextHighlights,
};
use gpui::fonts::HighlightStyle;
use language::{Chunk, Edit, Point, TextSummary};
use language::{Chunk, Edit, Point, Rope, TextSummary};
use parking_lot::Mutex;
use project::InlayHint;
use rand::Rng;
use sum_tree::Bias;
pub struct EditorAdditionMap;
pub struct EditorAdditionMap(Mutex<EditorAdditionSnapshot>);
#[derive(Clone)]
pub struct EditorAdditionSnapshot {
// TODO kb merge these two together
pub suggestion_snapshot: SuggestionSnapshot,
pub version: usize,
hints: Vec<InlayHintToRender>,
}
pub type EditorAdditionEdit = Edit<EditorAdditionOffset>;
@ -63,6 +66,12 @@ pub struct EditorAdditionChunks<'a> {
_z: &'a std::marker::PhantomData<()>,
}
#[derive(Clone)]
pub struct InlayHintToRender {
pub(super) position: EditorAdditionPoint,
pub(super) text: Rope,
}
impl<'a> Iterator for EditorAdditionChunks<'a> {
type Item = Chunk<'a>;
@ -95,7 +104,12 @@ impl EditorAdditionPoint {
impl EditorAdditionMap {
pub fn new(suggestion_snapshot: SuggestionSnapshot) -> (Self, EditorAdditionSnapshot) {
todo!("TODO kb")
let snapshot = EditorAdditionSnapshot {
suggestion_snapshot: suggestion_snapshot.clone(),
version: 0,
hints: Vec::new(),
};
(Self(Mutex::new(snapshot.clone())), snapshot)
}
pub fn sync(
@ -103,14 +117,24 @@ impl EditorAdditionMap {
suggestion_snapshot: SuggestionSnapshot,
suggestion_edits: Vec<SuggestionEdit>,
) -> (EditorAdditionSnapshot, Vec<EditorAdditionEdit>) {
todo!("TODO kb")
let mut snapshot = self.0.lock();
if snapshot.suggestion_snapshot.version != suggestion_snapshot.version {
snapshot.version += 1;
}
let editor_addition_edits = Vec::new();
{
todo!("TODO kb")
}
snapshot.suggestion_snapshot = suggestion_snapshot;
(snapshot.clone(), editor_addition_edits)
}
pub fn randomly_mutate(
&self,
rng: &mut impl Rng,
) -> (EditorAdditionSnapshot, Vec<EditorAdditionEdit>) {
todo!("TODO kb")
pub fn set_inlay_hints(&self, new_hints: Vec<InlayHintToRender>) {
self.0.lock().hints = new_hints;
}
}

View file

@ -761,11 +761,13 @@ mod tests {
let (suggestion_map, _) = SuggestionMap::new(fold_snapshot);
let (suggestion_snapshot, _) = suggestion_map.randomly_mutate(&mut rng);
log::info!("SuggestionMap text: {:?}", suggestion_snapshot.text());
let (editor_addition_map, _) = EditorAdditionMap::new(suggestion_snapshot.clone());
let (suggestion_snapshot, _) = editor_addition_map.randomly_mutate(&mut rng);
log::info!("EditorAdditionMap text: {:?}", suggestion_snapshot.text());
let (_, editor_addition_snapshot) = EditorAdditionMap::new(suggestion_snapshot.clone());
log::info!(
"EditorAdditionMap text: {:?}",
editor_addition_snapshot.text()
);
let (tab_map, _) = TabMap::new(suggestion_snapshot.clone(), tab_size);
let (tab_map, _) = TabMap::new(editor_addition_snapshot.clone(), tab_size);
let tabs_snapshot = tab_map.set_max_expansion_column(32);
let text = text::Rope::from(tabs_snapshot.text().as_str());
@ -803,7 +805,7 @@ mod tests {
);
let mut actual_summary = tabs_snapshot.text_summary_for_range(start..end);
if tab_size.get() > 1 && suggestion_snapshot.text().contains('\t') {
if tab_size.get() > 1 && editor_addition_snapshot.text().contains('\t') {
actual_summary.longest_row = expected_summary.longest_row;
actual_summary.longest_row_chars = expected_summary.longest_row_chars;
}

View file

@ -1169,11 +1169,19 @@ impl InlayHintState {
Self::first_timestamp_newer(timestamp, &current_timestamp)
}
fn update_if_newer(&self, new_hints: Vec<InlayHint>, new_timestamp: HashMap<usize, Global>) {
fn update_if_newer(
&self,
new_hints: Vec<InlayHint>,
new_timestamp: HashMap<usize, Global>,
) -> bool {
let mut guard = self.0.write();
if Self::first_timestamp_newer(&new_timestamp, &guard.0) {
guard.0 = new_timestamp;
guard.1 = new_hints;
true
} else {
false
}
}
@ -2688,7 +2696,7 @@ impl Editor {
let inlay_hints_storage = Arc::clone(&self.inlay_hints);
if inlay_hints_storage.is_newer(&new_timestamp) {
cx.spawn(|_, _| async move {
cx.spawn(|editor, mut cx| async move {
let mut new_hints = Vec::new();
for task_result in futures::future::join_all(hint_fetch_tasks).await {
match task_result {
@ -2696,7 +2704,18 @@ impl Editor {
Err(e) => error!("Failed to update hints for buffer: {e:#}"),
}
}
inlay_hints_storage.update_if_newer(new_hints, new_timestamp);
// TODO kb another odd clone, can be avoid all this? hide hints behind a handle?
if inlay_hints_storage.update_if_newer(new_hints.clone(), new_timestamp) {
editor
.update(&mut cx, |editor, cx| {
editor.display_map.update(cx, |display_map, cx| {
display_map.set_inlay_hints(&new_hints, cx)
});
})
.log_err()
.unwrap_or(())
}
})
.detach();
}

View file

@ -1834,6 +1834,7 @@ impl LspCommand for InlayHints {
.unwrap_or_default()
.into_iter()
.map(|lsp_hint| InlayHint {
buffer_id: buffer.id() as u64,
position: origin_buffer.anchor_after(
origin_buffer
.clip_point_utf16(point_from_lsp(lsp_hint.position), Bias::Left),
@ -2006,6 +2007,7 @@ impl LspCommand for InlayHints {
let mut hints = Vec::new();
for message_hint in message.hints {
let hint = InlayHint {
buffer_id: buffer.id() as u64,
position: message_hint
.position
.and_then(language::proto::deserialize_anchor)

View file

@ -29,6 +29,7 @@ use gpui::{
AnyModelHandle, AppContext, AsyncAppContext, BorrowAppContext, Entity, ModelContext,
ModelHandle, Task, WeakModelHandle,
};
use itertools::Itertools;
use language::{
language_settings::{language_settings, FormatOnSave, Formatter},
point_to_lsp,
@ -320,46 +321,56 @@ pub struct DiagnosticSummary {
pub warning_count: usize,
}
#[derive(Debug, Clone)]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Location {
pub buffer: ModelHandle<Buffer>,
pub range: Range<language::Anchor>,
}
#[derive(Debug, Clone)]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct InlayHint {
pub buffer_id: u64,
pub position: Anchor,
pub label: InlayHintLabel,
pub kind: Option<String>,
pub tooltip: Option<InlayHintTooltip>,
}
#[derive(Debug, Clone)]
impl InlayHint {
pub fn text(&self) -> String {
match &self.label {
InlayHintLabel::String(s) => s.to_owned(),
InlayHintLabel::LabelParts(parts) => parts.iter().map(|part| &part.value).join(""),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum InlayHintLabel {
String(String),
LabelParts(Vec<InlayHintLabelPart>),
}
#[derive(Debug, Clone)]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct InlayHintLabelPart {
pub value: String,
pub tooltip: Option<InlayHintLabelPartTooltip>,
pub location: Option<Location>,
}
#[derive(Debug, Clone)]
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum InlayHintTooltip {
String(String),
MarkupContent(MarkupContent),
}
#[derive(Debug, Clone)]
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum InlayHintLabelPartTooltip {
String(String),
MarkupContent(MarkupContent),
}
#[derive(Debug, Clone)]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct MarkupContent {
pub kind: String,
pub value: String,