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}