1use std::{
2 cmp, mem,
3 sync::atomic::{AtomicUsize, Ordering::SeqCst},
4};
5
6use buffer::{Anchor, Bias, Edit, Point, Rope, TextSummary};
7use gpui::{fonts::HighlightStyle, AppContext, ModelHandle};
8use language::Buffer;
9use parking_lot::Mutex;
10use sum_tree::SumTree;
11
12#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Ord, PartialOrd)]
13pub struct InjectionId(usize);
14
15pub struct InjectionMap {
16 buffer: ModelHandle<Buffer>,
17 transforms: Mutex<SumTree<Transform>>,
18 injections: SumTree<Injection>,
19 injection_contents: SumTree<InjectionContent>,
20 version: AtomicUsize,
21 last_sync: Mutex<SyncState>,
22}
23
24pub struct InjectionSnapshot {
25 transforms: SumTree<Transform>,
26 injection_contents: SumTree<InjectionContent>,
27 buffer_snapshot: language::Snapshot,
28 pub version: usize,
29}
30
31pub struct InjectionMapWriter<'a>(&'a mut InjectionMap);
32
33#[derive(Clone)]
34struct SyncState {
35 version: clock::Global,
36 parse_count: usize,
37 diagnostics_update_count: usize,
38}
39
40#[derive(Clone, Debug)]
41struct Injection {
42 id: InjectionId,
43 position: Anchor,
44 is_block: bool,
45}
46
47#[derive(Clone, Debug)]
48struct InjectionSummary {
49 min_id: InjectionId,
50 max_id: InjectionId,
51 min_position: Anchor,
52 max_position: Anchor,
53}
54
55#[derive(Clone, Debug)]
56struct InjectionContent {
57 injection_id: InjectionId,
58 runs: Vec<(usize, HighlightStyle)>,
59 text: Rope,
60}
61
62#[derive(Clone, Debug, Default, PartialEq)]
63struct Transform {
64 summary: TransformSummary,
65 injection_id: Option<InjectionId>,
66}
67
68#[derive(Clone, Debug, Default, Eq, PartialEq)]
69struct TransformSummary {
70 output: TextSummary,
71 input: TextSummary,
72}
73
74#[derive(Copy, Clone)]
75struct InjectionOffset(usize);
76
77impl sum_tree::Summary for InjectionId {
78 type Context = ();
79
80 fn add_summary(&mut self, summary: &Self, cx: &Self::Context) {
81 *self = *summary
82 }
83}
84
85impl InjectionMap {
86 pub fn read(&self, cx: &AppContext) -> (InjectionSnapshot, Vec<Edit<InjectionOffset>>) {
87 let edits = self.sync(cx);
88 // self.check_invariants(cx);
89 let snapshot = InjectionSnapshot {
90 transforms: self.transforms.lock().clone(),
91 injection_contents: self.injection_contents.clone(),
92 buffer_snapshot: self.buffer.read(cx).snapshot(),
93 version: self.version.load(SeqCst),
94 };
95 (snapshot, edits)
96 }
97
98 pub fn write(
99 &mut self,
100 cx: &AppContext,
101 ) -> (
102 InjectionMapWriter,
103 InjectionSnapshot,
104 Vec<Edit<InjectionOffset>>,
105 ) {
106 let (snapshot, edits) = self.read(cx);
107 (InjectionMapWriter(self), snapshot, edits)
108 }
109
110 fn sync(&self, cx: &AppContext) -> Vec<Edit<InjectionOffset>> {
111 let buffer = self.buffer.read(cx);
112 let last_sync = mem::replace(
113 &mut *self.last_sync.lock(),
114 SyncState {
115 version: buffer.version(),
116 parse_count: buffer.parse_count(),
117 diagnostics_update_count: buffer.diagnostics_update_count(),
118 },
119 );
120 let edits = buffer
121 .edits_since(&last_sync.version)
122 .map(Into::into)
123 .collect::<Vec<_>>();
124 if edits.is_empty() {
125 if last_sync.parse_count != buffer.parse_count()
126 || last_sync.diagnostics_update_count != buffer.diagnostics_update_count()
127 {
128 self.version.fetch_add(1, SeqCst);
129 }
130 Vec::new()
131 } else {
132 self.apply_edits(edits, cx)
133 }
134 }
135
136 fn apply_edits(
137 &self,
138 buffer_edits: Vec<buffer::Edit<usize>>,
139 cx: &AppContext,
140 ) -> Vec<Edit<InjectionOffset>> {
141 let buffer = self.buffer.read(cx).snapshot();
142 let mut buffer_edits_iter = buffer_edits.iter().cloned().peekable();
143
144 let mut new_transforms = SumTree::<Transform>::new();
145 let mut transforms = self.transforms.lock();
146 let mut cursor = transforms.cursor::<usize>();
147
148 while let Some(mut edit) = buffer_edits_iter.next() {
149 new_transforms.push_tree(cursor.slice(&edit.old.start, Bias::Left, &()), &());
150 edit.new.start -= edit.old.start - cursor.start();
151 edit.old.start = *cursor.start();
152
153 cursor.seek(&edit.old.end, Bias::Right, &());
154 cursor.next(&());
155
156 let mut delta = edit.new.len() as isize - edit.old.len() as isize;
157 loop {
158 edit.old.end = *cursor.start();
159
160 if let Some(next_edit) = buffer_edits_iter.peek() {
161 if next_edit.old.start > edit.old.end {
162 break;
163 }
164
165 let next_edit = buffer_edits_iter.next().unwrap();
166 delta += next_edit.new.len() as isize - next_edit.old.len() as isize;
167
168 if next_edit.old.end >= edit.old.end {
169 edit.old.end = next_edit.old.end;
170 cursor.seek(&edit.old.end, Bias::Right, &());
171 cursor.next(&());
172 }
173 } else {
174 break;
175 }
176 }
177
178 edit.new.end = ((edit.new.start + edit.old.len()) as isize + delta) as usize;
179
180 let anchor = buffer.anchor_before(edit.new.start);
181 let mut injections_cursor = self.injections.cursor::<Anchor>();
182 // folds_cursor.seek(&Fold(anchor..Anchor::max()), Bias::Left, &buffer);
183 }
184
185 todo!()
186 }
187}
188
189impl sum_tree::Item for Injection {
190 type Summary = InjectionSummary;
191
192 fn summary(&self) -> Self::Summary {
193 InjectionSummary {
194 min_id: self.id,
195 max_id: self.id,
196 min_position: self.position.clone(),
197 max_position: self.position.clone(),
198 }
199 }
200}
201
202impl sum_tree::Summary for InjectionSummary {
203 type Context = buffer::Snapshot;
204
205 fn add_summary(&mut self, summary: &Self, _: &buffer::Snapshot) {
206 self.max_position = summary.max_position.clone();
207 self.min_id = cmp::min(self.min_id, summary.min_id);
208 self.max_id = cmp::max(self.max_id, summary.max_id);
209 }
210}
211
212impl Default for InjectionSummary {
213 fn default() -> Self {
214 Self {
215 min_id: InjectionId(0),
216 max_id: InjectionId(usize::MAX),
217 min_position: Anchor::max(),
218 max_position: Anchor::min(),
219 }
220 }
221}
222
223impl sum_tree::Item for InjectionContent {
224 type Summary = InjectionId;
225
226 fn summary(&self) -> Self::Summary {
227 self.injection_id
228 }
229}
230
231impl sum_tree::Item for Transform {
232 type Summary = TransformSummary;
233
234 fn summary(&self) -> Self::Summary {
235 self.summary.clone()
236 }
237}
238
239impl sum_tree::Summary for TransformSummary {
240 type Context = ();
241
242 fn add_summary(&mut self, other: &Self, _: &()) {
243 self.input += &other.input;
244 self.output += &other.output;
245 }
246}
247
248impl<'a> sum_tree::Dimension<'a, TransformSummary> for usize {
249 fn add_summary(&mut self, summary: &'a TransformSummary, _: &()) {
250 *self += summary.input.bytes
251 }
252}