inlay_map.rs

  1#![allow(unused)]
  2// TODO kb
  3
  4use std::{
  5    ops::{Add, AddAssign, Range, Sub},
  6    sync::atomic::{self, AtomicUsize},
  7};
  8
  9use crate::MultiBufferSnapshot;
 10
 11use super::{
 12    suggestion_map::{
 13        SuggestionBufferRows, SuggestionChunks, SuggestionEdit, SuggestionOffset, SuggestionPoint,
 14        SuggestionSnapshot,
 15    },
 16    TextHighlights,
 17};
 18use collections::HashMap;
 19use gpui::fonts::HighlightStyle;
 20use language::{Chunk, Edit, Point, Rope, TextSummary};
 21use parking_lot::Mutex;
 22use project::InlayHint;
 23use rand::Rng;
 24use sum_tree::{Bias, SumTree};
 25
 26#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
 27pub struct InlayHintId(usize);
 28
 29pub struct InlayMap {
 30    snapshot: Mutex<InlaySnapshot>,
 31    next_hint_id: AtomicUsize,
 32    inlay_hints: HashMap<InlayHintId, InlayHintToRender>,
 33}
 34
 35#[derive(Clone)]
 36pub struct InlaySnapshot {
 37    // TODO kb merge these two together?
 38    pub suggestion_snapshot: SuggestionSnapshot,
 39    transforms: SumTree<Transform>,
 40    pub version: usize,
 41}
 42
 43#[derive(Clone)]
 44struct Transform {
 45    input: TextSummary,
 46    output: TextSummary,
 47}
 48
 49impl sum_tree::Item for Transform {
 50    type Summary = TextSummary;
 51
 52    fn summary(&self) -> Self::Summary {
 53        self.output.clone()
 54    }
 55}
 56
 57pub type InlayEdit = Edit<InlayOffset>;
 58
 59#[derive(Copy, Clone, Debug, Default, Eq, Ord, PartialOrd, PartialEq)]
 60pub struct InlayOffset(pub usize);
 61
 62impl Add for InlayOffset {
 63    type Output = Self;
 64
 65    fn add(self, rhs: Self) -> Self::Output {
 66        Self(self.0 + rhs.0)
 67    }
 68}
 69
 70impl Sub for InlayOffset {
 71    type Output = Self;
 72
 73    fn sub(self, rhs: Self) -> Self::Output {
 74        Self(self.0 - rhs.0)
 75    }
 76}
 77
 78impl AddAssign for InlayOffset {
 79    fn add_assign(&mut self, rhs: Self) {
 80        self.0 += rhs.0;
 81    }
 82}
 83
 84#[derive(Copy, Clone, Debug, Default, Eq, Ord, PartialOrd, PartialEq)]
 85pub struct InlayPoint(pub Point);
 86
 87#[derive(Clone)]
 88pub struct InlayBufferRows<'a> {
 89    suggestion_rows: SuggestionBufferRows<'a>,
 90}
 91
 92pub struct InlayChunks<'a> {
 93    suggestion_chunks: SuggestionChunks<'a>,
 94}
 95
 96#[derive(Debug, Clone)]
 97pub struct InlayHintToRender {
 98    pub(super) position: InlayPoint,
 99    pub(super) text: Rope,
100}
101
102impl<'a> Iterator for InlayChunks<'a> {
103    type Item = Chunk<'a>;
104
105    fn next(&mut self) -> Option<Self::Item> {
106        self.suggestion_chunks.next()
107    }
108}
109
110impl<'a> Iterator for InlayBufferRows<'a> {
111    type Item = Option<u32>;
112
113    fn next(&mut self) -> Option<Self::Item> {
114        self.suggestion_rows.next()
115    }
116}
117
118impl InlayPoint {
119    pub fn new(row: u32, column: u32) -> Self {
120        Self(Point::new(row, column))
121    }
122
123    pub fn row(self) -> u32 {
124        self.0.row
125    }
126
127    pub fn column(self) -> u32 {
128        self.0.column
129    }
130}
131
132impl InlayMap {
133    pub fn new(suggestion_snapshot: SuggestionSnapshot) -> (Self, InlaySnapshot) {
134        let snapshot = InlaySnapshot {
135            suggestion_snapshot: suggestion_snapshot.clone(),
136            version: 0,
137            transforms: SumTree::new(),
138        };
139
140        (
141            Self {
142                snapshot: Mutex::new(snapshot.clone()),
143                next_hint_id: AtomicUsize::new(0),
144                inlay_hints: HashMap::default(),
145            },
146            snapshot,
147        )
148    }
149
150    pub fn sync(
151        &self,
152        suggestion_snapshot: SuggestionSnapshot,
153        suggestion_edits: Vec<SuggestionEdit>,
154    ) -> (InlaySnapshot, Vec<InlayEdit>) {
155        let mut snapshot = self.snapshot.lock();
156
157        if snapshot.suggestion_snapshot.version != suggestion_snapshot.version {
158            snapshot.version += 1;
159        }
160
161        let mut inlay_edits = Vec::new();
162
163        for suggestion_edit in suggestion_edits {
164            let old = suggestion_edit.old;
165            let new = suggestion_edit.new;
166            // TODO kb copied from suggestion_map
167            inlay_edits.push(InlayEdit {
168                old: InlayOffset(old.start.0)..InlayOffset(old.end.0),
169                new: InlayOffset(old.start.0)..InlayOffset(new.end.0),
170            })
171        }
172
173        snapshot.suggestion_snapshot = suggestion_snapshot;
174
175        (snapshot.clone(), inlay_edits)
176    }
177
178    // TODO kb replace set_inlay_hints with this
179    pub fn splice(
180        &mut self,
181        to_remove: Vec<InlayHintId>,
182        to_insert: Vec<InlayHintToRender>,
183    ) -> Vec<InlayHintId> {
184        // Order removals and insertions by position.
185        // let anchors;
186
187        // Remove and insert inlays in a single traversal across the tree.
188        todo!("TODO kb")
189    }
190
191    pub fn set_inlay_hints(&mut self, new_hints: Vec<InlayHintToRender>) {
192        // TODO kb reuse ids for hints that did not change and similar things
193        self.inlay_hints = new_hints
194            .into_iter()
195            .map(|hint| {
196                (
197                    InlayHintId(self.next_hint_id.fetch_add(1, atomic::Ordering::SeqCst)),
198                    hint,
199                )
200            })
201            .collect();
202    }
203}
204
205impl InlaySnapshot {
206    pub fn buffer_snapshot(&self) -> &MultiBufferSnapshot {
207        // TODO kb copied from suggestion_map
208        self.suggestion_snapshot.buffer_snapshot()
209    }
210
211    pub fn to_point(&self, offset: InlayOffset) -> InlayPoint {
212        // TODO kb copied from suggestion_map
213        self.to_inlay_point(
214            self.suggestion_snapshot
215                .to_point(super::suggestion_map::SuggestionOffset(offset.0)),
216        )
217    }
218
219    pub fn max_point(&self) -> InlayPoint {
220        // TODO kb copied from suggestion_map
221        self.to_inlay_point(self.suggestion_snapshot.max_point())
222    }
223
224    pub fn to_offset(&self, point: InlayPoint) -> InlayOffset {
225        // TODO kb copied from suggestion_map
226        InlayOffset(
227            self.suggestion_snapshot
228                .to_offset(self.to_suggestion_point(point, Bias::Left))
229                .0,
230        )
231    }
232
233    pub fn chars_at(&self, start: InlayPoint) -> impl '_ + Iterator<Item = char> {
234        self.suggestion_snapshot
235            .chars_at(self.to_suggestion_point(start, Bias::Left))
236    }
237
238    // TODO kb what to do with bias?
239    pub fn to_suggestion_point(&self, point: InlayPoint, _: Bias) -> SuggestionPoint {
240        SuggestionPoint(point.0)
241    }
242
243    pub fn to_inlay_point(&self, point: SuggestionPoint) -> InlayPoint {
244        InlayPoint(point.0)
245    }
246
247    pub fn clip_point(&self, point: InlayPoint, bias: Bias) -> InlayPoint {
248        // TODO kb copied from suggestion_map
249        self.to_inlay_point(
250            self.suggestion_snapshot
251                .clip_point(self.to_suggestion_point(point, bias), bias),
252        )
253    }
254
255    pub fn text_summary_for_range(&self, range: Range<InlayPoint>) -> TextSummary {
256        // TODO kb copied from suggestion_map
257        self.suggestion_snapshot.text_summary_for_range(
258            self.to_suggestion_point(range.start, Bias::Left)
259                ..self.to_suggestion_point(range.end, Bias::Left),
260        )
261    }
262
263    pub fn buffer_rows<'a>(&'a self, row: u32) -> InlayBufferRows<'a> {
264        InlayBufferRows {
265            suggestion_rows: self.suggestion_snapshot.buffer_rows(row),
266        }
267    }
268
269    pub fn line_len(&self, row: u32) -> u32 {
270        // TODO kb copied from suggestion_map
271        self.suggestion_snapshot.line_len(row)
272    }
273
274    pub fn chunks<'a>(
275        &'a self,
276        range: Range<InlayOffset>,
277        language_aware: bool,
278        text_highlights: Option<&'a TextHighlights>,
279        suggestion_highlight: Option<HighlightStyle>,
280    ) -> InlayChunks<'a> {
281        // TODO kb copied from suggestion_map
282        InlayChunks {
283            suggestion_chunks: self.suggestion_snapshot.chunks(
284                SuggestionOffset(range.start.0)..SuggestionOffset(range.end.0),
285                language_aware,
286                text_highlights,
287                suggestion_highlight,
288            ),
289        }
290    }
291
292    #[cfg(test)]
293    pub fn text(&self) -> String {
294        // TODO kb copied from suggestion_map
295        self.suggestion_snapshot.text()
296    }
297}