1use crate::diagnostic_set::DiagnosticEntry;
2pub use crate::{
3 diagnostic_set::DiagnosticSet,
4 highlight_map::{HighlightId, HighlightMap},
5 proto, BracketPair, Grammar, Language, LanguageConfig, LanguageRegistry, LanguageServerConfig,
6 PLAIN_TEXT,
7};
8use anyhow::{anyhow, Result};
9use clock::ReplicaId;
10use futures::FutureExt as _;
11use gpui::{fonts::HighlightStyle, AppContext, Entity, ModelContext, MutableAppContext, Task};
12use lazy_static::lazy_static;
13use lsp::LanguageServer;
14use parking_lot::Mutex;
15use postage::{prelude::Stream, sink::Sink, watch};
16use similar::{ChangeTag, TextDiff};
17use smol::future::yield_now;
18use std::{
19 any::Any,
20 cell::RefCell,
21 cmp,
22 collections::{BTreeMap, HashMap, HashSet},
23 ffi::OsString,
24 future::Future,
25 iter::{Iterator, Peekable},
26 ops::{Deref, DerefMut, Range},
27 path::{Path, PathBuf},
28 str,
29 sync::Arc,
30 time::{Duration, Instant, SystemTime, UNIX_EPOCH},
31 vec,
32};
33use sum_tree::TreeMap;
34use text::operation_queue::OperationQueue;
35pub use text::{Buffer as TextBuffer, Operation as _, *};
36use theme::SyntaxTheme;
37use tree_sitter::{InputEdit, Parser, QueryCursor, Tree};
38use util::{post_inc, TryFutureExt as _};
39
40#[cfg(any(test, feature = "test-support"))]
41pub use tree_sitter_rust;
42
43pub use lsp::DiagnosticSeverity;
44
45thread_local! {
46 static PARSER: RefCell<Parser> = RefCell::new(Parser::new());
47}
48
49lazy_static! {
50 static ref QUERY_CURSORS: Mutex<Vec<QueryCursor>> = Default::default();
51}
52
53// TODO - Make this configurable
54const INDENT_SIZE: u32 = 4;
55
56pub struct Buffer {
57 text: TextBuffer,
58 file: Option<Box<dyn File>>,
59 saved_version: clock::Global,
60 saved_mtime: SystemTime,
61 language: Option<Arc<Language>>,
62 autoindent_requests: Vec<Arc<AutoindentRequest>>,
63 pending_autoindent: Option<Task<()>>,
64 sync_parse_timeout: Duration,
65 syntax_tree: Mutex<Option<SyntaxTree>>,
66 parsing_in_background: bool,
67 parse_count: usize,
68 remote_selections: TreeMap<ReplicaId, Arc<[Selection<Anchor>]>>,
69 diagnostics: DiagnosticSet,
70 diagnostics_update_count: usize,
71 language_server: Option<LanguageServerState>,
72 deferred_ops: OperationQueue<Operation>,
73 #[cfg(test)]
74 pub(crate) operations: Vec<Operation>,
75}
76
77pub struct BufferSnapshot {
78 text: text::BufferSnapshot,
79 tree: Option<Tree>,
80 diagnostics: DiagnosticSet,
81 remote_selections: TreeMap<ReplicaId, Arc<[Selection<Anchor>]>>,
82 diagnostics_update_count: usize,
83 is_parsing: bool,
84 language: Option<Arc<Language>>,
85 parse_count: usize,
86}
87
88#[derive(Clone, Debug, PartialEq, Eq)]
89pub struct Diagnostic {
90 pub severity: DiagnosticSeverity,
91 pub message: String,
92 pub group_id: usize,
93 pub is_primary: bool,
94}
95
96struct LanguageServerState {
97 server: Arc<LanguageServer>,
98 latest_snapshot: watch::Sender<Option<LanguageServerSnapshot>>,
99 pending_snapshots: BTreeMap<usize, LanguageServerSnapshot>,
100 next_version: usize,
101 _maintain_server: Task<Option<()>>,
102}
103
104#[derive(Clone)]
105struct LanguageServerSnapshot {
106 buffer_snapshot: text::BufferSnapshot,
107 version: usize,
108 path: Arc<Path>,
109}
110
111#[derive(Clone, Debug)]
112pub enum Operation {
113 Buffer(text::Operation),
114 UpdateDiagnostics {
115 diagnostics: Arc<[DiagnosticEntry<Anchor>]>,
116 lamport_timestamp: clock::Lamport,
117 },
118 UpdateSelections {
119 replica_id: ReplicaId,
120 selections: Arc<[Selection<Anchor>]>,
121 lamport_timestamp: clock::Lamport,
122 },
123 RemoveSelections {
124 replica_id: ReplicaId,
125 lamport_timestamp: clock::Lamport,
126 },
127}
128
129#[derive(Clone, Debug, Eq, PartialEq)]
130pub enum Event {
131 Edited,
132 Dirtied,
133 Saved,
134 FileHandleChanged,
135 Reloaded,
136 Reparsed,
137 DiagnosticsUpdated,
138 Closed,
139}
140
141pub trait File {
142 fn worktree_id(&self) -> usize;
143
144 fn entry_id(&self) -> Option<usize>;
145
146 fn mtime(&self) -> SystemTime;
147
148 /// Returns the path of this file relative to the worktree's root directory.
149 fn path(&self) -> &Arc<Path>;
150
151 /// Returns the absolute path of this file.
152 fn abs_path(&self) -> Option<PathBuf>;
153
154 /// Returns the path of this file relative to the worktree's parent directory (this means it
155 /// includes the name of the worktree's root folder).
156 fn full_path(&self) -> PathBuf;
157
158 /// Returns the last component of this handle's absolute path. If this handle refers to the root
159 /// of its worktree, then this method will return the name of the worktree itself.
160 fn file_name(&self) -> Option<OsString>;
161
162 fn is_deleted(&self) -> bool;
163
164 fn save(
165 &self,
166 buffer_id: u64,
167 text: Rope,
168 version: clock::Global,
169 cx: &mut MutableAppContext,
170 ) -> Task<Result<(clock::Global, SystemTime)>>;
171
172 fn load_local(&self, cx: &AppContext) -> Option<Task<Result<String>>>;
173
174 fn buffer_updated(&self, buffer_id: u64, operation: Operation, cx: &mut MutableAppContext);
175
176 fn buffer_removed(&self, buffer_id: u64, cx: &mut MutableAppContext);
177
178 fn boxed_clone(&self) -> Box<dyn File>;
179
180 fn as_any(&self) -> &dyn Any;
181}
182
183struct QueryCursorHandle(Option<QueryCursor>);
184
185#[derive(Clone)]
186struct SyntaxTree {
187 tree: Tree,
188 version: clock::Global,
189}
190
191#[derive(Clone)]
192struct AutoindentRequest {
193 before_edit: BufferSnapshot,
194 edited: Vec<Anchor>,
195 inserted: Option<Vec<Range<Anchor>>>,
196}
197
198#[derive(Debug)]
199struct IndentSuggestion {
200 basis_row: u32,
201 indent: bool,
202}
203
204struct TextProvider<'a>(&'a Rope);
205
206struct BufferChunkHighlights<'a> {
207 captures: tree_sitter::QueryCaptures<'a, 'a, TextProvider<'a>>,
208 next_capture: Option<(tree_sitter::QueryMatch<'a, 'a>, usize)>,
209 stack: Vec<(usize, HighlightId)>,
210 highlight_map: HighlightMap,
211 theme: &'a SyntaxTheme,
212 _query_cursor: QueryCursorHandle,
213}
214
215pub struct BufferChunks<'a> {
216 range: Range<usize>,
217 chunks: rope::Chunks<'a>,
218 diagnostic_endpoints: Peekable<vec::IntoIter<DiagnosticEndpoint>>,
219 error_depth: usize,
220 warning_depth: usize,
221 information_depth: usize,
222 hint_depth: usize,
223 highlights: Option<BufferChunkHighlights<'a>>,
224}
225
226#[derive(Clone, Copy, Debug, Default)]
227pub struct Chunk<'a> {
228 pub text: &'a str,
229 pub highlight_style: Option<HighlightStyle>,
230 pub diagnostic: Option<DiagnosticSeverity>,
231}
232
233pub(crate) struct Diff {
234 base_version: clock::Global,
235 new_text: Arc<str>,
236 changes: Vec<(ChangeTag, usize)>,
237}
238
239#[derive(Clone, Copy)]
240struct DiagnosticEndpoint {
241 offset: usize,
242 is_start: bool,
243 severity: DiagnosticSeverity,
244}
245
246impl Buffer {
247 pub fn new<T: Into<Arc<str>>>(
248 replica_id: ReplicaId,
249 base_text: T,
250 cx: &mut ModelContext<Self>,
251 ) -> Self {
252 Self::build(
253 TextBuffer::new(
254 replica_id,
255 cx.model_id() as u64,
256 History::new(base_text.into()),
257 ),
258 None,
259 )
260 }
261
262 pub fn from_file<T: Into<Arc<str>>>(
263 replica_id: ReplicaId,
264 base_text: T,
265 file: Box<dyn File>,
266 cx: &mut ModelContext<Self>,
267 ) -> Self {
268 Self::build(
269 TextBuffer::new(
270 replica_id,
271 cx.model_id() as u64,
272 History::new(base_text.into()),
273 ),
274 Some(file),
275 )
276 }
277
278 pub fn from_proto(
279 replica_id: ReplicaId,
280 message: proto::Buffer,
281 file: Option<Box<dyn File>>,
282 cx: &mut ModelContext<Self>,
283 ) -> Result<Self> {
284 let mut buffer =
285 text::Buffer::new(replica_id, message.id, History::new(message.content.into()));
286 let ops = message
287 .history
288 .into_iter()
289 .map(|op| text::Operation::Edit(proto::deserialize_edit_operation(op)));
290 buffer.apply_ops(ops)?;
291 let mut this = Self::build(buffer, file);
292 for selection_set in message.selections {
293 this.remote_selections.insert(
294 selection_set.replica_id as ReplicaId,
295 proto::deserialize_selections(selection_set.selections),
296 );
297 }
298 this.apply_diagnostic_update(
299 Arc::from(proto::deserialize_diagnostics(message.diagnostics)),
300 cx,
301 );
302
303 Ok(this)
304 }
305
306 pub fn to_proto(&self) -> proto::Buffer {
307 proto::Buffer {
308 id: self.remote_id(),
309 content: self.text.base_text().to_string(),
310 history: self
311 .text
312 .history()
313 .map(proto::serialize_edit_operation)
314 .collect(),
315 selections: self
316 .remote_selections
317 .iter()
318 .map(|(replica_id, selections)| proto::SelectionSet {
319 replica_id: *replica_id as u32,
320 selections: proto::serialize_selections(selections),
321 })
322 .collect(),
323 diagnostics: proto::serialize_diagnostics(self.diagnostics.iter()),
324 }
325 }
326
327 pub fn with_language(
328 mut self,
329 language: Option<Arc<Language>>,
330 language_server: Option<Arc<LanguageServer>>,
331 cx: &mut ModelContext<Self>,
332 ) -> Self {
333 self.set_language(language, language_server, cx);
334 self
335 }
336
337 fn build(buffer: TextBuffer, file: Option<Box<dyn File>>) -> Self {
338 let saved_mtime;
339 if let Some(file) = file.as_ref() {
340 saved_mtime = file.mtime();
341 } else {
342 saved_mtime = UNIX_EPOCH;
343 }
344
345 Self {
346 saved_mtime,
347 saved_version: buffer.version(),
348 text: buffer,
349 file,
350 syntax_tree: Mutex::new(None),
351 parsing_in_background: false,
352 parse_count: 0,
353 sync_parse_timeout: Duration::from_millis(1),
354 autoindent_requests: Default::default(),
355 pending_autoindent: Default::default(),
356 language: None,
357 remote_selections: Default::default(),
358 diagnostics: Default::default(),
359 diagnostics_update_count: 0,
360 language_server: None,
361 deferred_ops: OperationQueue::new(),
362 #[cfg(test)]
363 operations: Default::default(),
364 }
365 }
366
367 pub fn snapshot(&self) -> BufferSnapshot {
368 BufferSnapshot {
369 text: self.text.snapshot(),
370 tree: self.syntax_tree(),
371 remote_selections: self.remote_selections.clone(),
372 diagnostics: self.diagnostics.clone(),
373 diagnostics_update_count: self.diagnostics_update_count,
374 is_parsing: self.parsing_in_background,
375 language: self.language.clone(),
376 parse_count: self.parse_count,
377 }
378 }
379
380 pub fn file(&self) -> Option<&dyn File> {
381 self.file.as_deref()
382 }
383
384 pub fn save(
385 &mut self,
386 cx: &mut ModelContext<Self>,
387 ) -> Result<Task<Result<(clock::Global, SystemTime)>>> {
388 let file = self
389 .file
390 .as_ref()
391 .ok_or_else(|| anyhow!("buffer has no file"))?;
392 let text = self.as_rope().clone();
393 let version = self.version();
394 let save = file.save(self.remote_id(), text, version, cx.as_mut());
395 Ok(cx.spawn(|this, mut cx| async move {
396 let (version, mtime) = save.await?;
397 this.update(&mut cx, |this, cx| {
398 this.did_save(version.clone(), mtime, None, cx);
399 });
400 Ok((version, mtime))
401 }))
402 }
403
404 pub fn set_language(
405 &mut self,
406 language: Option<Arc<Language>>,
407 language_server: Option<Arc<lsp::LanguageServer>>,
408 cx: &mut ModelContext<Self>,
409 ) {
410 self.language = language;
411 self.language_server = if let Some(server) = language_server {
412 let (latest_snapshot_tx, mut latest_snapshot_rx) = watch::channel();
413 Some(LanguageServerState {
414 latest_snapshot: latest_snapshot_tx,
415 pending_snapshots: Default::default(),
416 next_version: 0,
417 server: server.clone(),
418 _maintain_server: cx.background().spawn(
419 async move {
420 let mut prev_snapshot: Option<LanguageServerSnapshot> = None;
421 while let Some(snapshot) = latest_snapshot_rx.recv().await {
422 if let Some(snapshot) = snapshot {
423 let uri = lsp::Url::from_file_path(&snapshot.path).unwrap();
424 if let Some(prev_snapshot) = prev_snapshot {
425 let changes = lsp::DidChangeTextDocumentParams {
426 text_document: lsp::VersionedTextDocumentIdentifier::new(
427 uri,
428 snapshot.version as i32,
429 ),
430 content_changes: snapshot
431 .buffer_snapshot
432 .edits_since::<(PointUtf16, usize)>(
433 prev_snapshot.buffer_snapshot.version(),
434 )
435 .map(|edit| {
436 let edit_start = edit.new.start.0;
437 let edit_end = edit_start
438 + (edit.old.end.0 - edit.old.start.0);
439 let new_text = snapshot
440 .buffer_snapshot
441 .text_for_range(
442 edit.new.start.1..edit.new.end.1,
443 )
444 .collect();
445 lsp::TextDocumentContentChangeEvent {
446 range: Some(lsp::Range::new(
447 lsp::Position::new(
448 edit_start.row,
449 edit_start.column,
450 ),
451 lsp::Position::new(
452 edit_end.row,
453 edit_end.column,
454 ),
455 )),
456 range_length: None,
457 text: new_text,
458 }
459 })
460 .collect(),
461 };
462 server
463 .notify::<lsp::notification::DidChangeTextDocument>(changes)
464 .await?;
465 } else {
466 server
467 .notify::<lsp::notification::DidOpenTextDocument>(
468 lsp::DidOpenTextDocumentParams {
469 text_document: lsp::TextDocumentItem::new(
470 uri,
471 Default::default(),
472 snapshot.version as i32,
473 snapshot.buffer_snapshot.text().to_string(),
474 ),
475 },
476 )
477 .await?;
478 }
479
480 prev_snapshot = Some(snapshot);
481 }
482 }
483 Ok(())
484 }
485 .log_err(),
486 ),
487 })
488 } else {
489 None
490 };
491
492 self.reparse(cx);
493 self.update_language_server();
494 }
495
496 pub fn did_save(
497 &mut self,
498 version: clock::Global,
499 mtime: SystemTime,
500 new_file: Option<Box<dyn File>>,
501 cx: &mut ModelContext<Self>,
502 ) {
503 self.saved_mtime = mtime;
504 self.saved_version = version;
505 if let Some(new_file) = new_file {
506 self.file = Some(new_file);
507 }
508 if let Some(state) = &self.language_server {
509 cx.background()
510 .spawn(
511 state
512 .server
513 .notify::<lsp::notification::DidSaveTextDocument>(
514 lsp::DidSaveTextDocumentParams {
515 text_document: lsp::TextDocumentIdentifier {
516 uri: lsp::Url::from_file_path(
517 self.file.as_ref().unwrap().abs_path().unwrap(),
518 )
519 .unwrap(),
520 },
521 text: None,
522 },
523 ),
524 )
525 .detach()
526 }
527 cx.emit(Event::Saved);
528 }
529
530 pub fn file_updated(
531 &mut self,
532 new_file: Box<dyn File>,
533 cx: &mut ModelContext<Self>,
534 ) -> Option<Task<()>> {
535 let old_file = self.file.as_ref()?;
536 let mut file_changed = false;
537 let mut task = None;
538
539 if new_file.path() != old_file.path() {
540 file_changed = true;
541 }
542
543 if new_file.is_deleted() {
544 if !old_file.is_deleted() {
545 file_changed = true;
546 if !self.is_dirty() {
547 cx.emit(Event::Dirtied);
548 }
549 }
550 } else {
551 let new_mtime = new_file.mtime();
552 if new_mtime != old_file.mtime() {
553 file_changed = true;
554
555 if !self.is_dirty() {
556 task = Some(cx.spawn(|this, mut cx| {
557 async move {
558 let new_text = this.read_with(&cx, |this, cx| {
559 this.file.as_ref().and_then(|file| file.load_local(cx))
560 });
561 if let Some(new_text) = new_text {
562 let new_text = new_text.await?;
563 let diff = this
564 .read_with(&cx, |this, cx| this.diff(new_text.into(), cx))
565 .await;
566 this.update(&mut cx, |this, cx| {
567 if this.apply_diff(diff, cx) {
568 this.saved_version = this.version();
569 this.saved_mtime = new_mtime;
570 cx.emit(Event::Reloaded);
571 }
572 });
573 }
574 Ok(())
575 }
576 .log_err()
577 .map(drop)
578 }));
579 }
580 }
581 }
582
583 if file_changed {
584 cx.emit(Event::FileHandleChanged);
585 }
586 self.file = Some(new_file);
587 task
588 }
589
590 pub fn close(&mut self, cx: &mut ModelContext<Self>) {
591 cx.emit(Event::Closed);
592 }
593
594 pub fn language(&self) -> Option<&Arc<Language>> {
595 self.language.as_ref()
596 }
597
598 pub fn parse_count(&self) -> usize {
599 self.parse_count
600 }
601
602 pub fn diagnostics_update_count(&self) -> usize {
603 self.diagnostics_update_count
604 }
605
606 pub(crate) fn syntax_tree(&self) -> Option<Tree> {
607 if let Some(syntax_tree) = self.syntax_tree.lock().as_mut() {
608 self.interpolate_tree(syntax_tree);
609 Some(syntax_tree.tree.clone())
610 } else {
611 None
612 }
613 }
614
615 #[cfg(any(test, feature = "test-support"))]
616 pub fn is_parsing(&self) -> bool {
617 self.parsing_in_background
618 }
619
620 #[cfg(test)]
621 pub fn set_sync_parse_timeout(&mut self, timeout: Duration) {
622 self.sync_parse_timeout = timeout;
623 }
624
625 fn reparse(&mut self, cx: &mut ModelContext<Self>) -> bool {
626 if self.parsing_in_background {
627 return false;
628 }
629
630 if let Some(grammar) = self.grammar().cloned() {
631 let old_tree = self.syntax_tree();
632 let text = self.as_rope().clone();
633 let parsed_version = self.version();
634 let parse_task = cx.background().spawn({
635 let grammar = grammar.clone();
636 async move { Self::parse_text(&text, old_tree, &grammar) }
637 });
638
639 match cx
640 .background()
641 .block_with_timeout(self.sync_parse_timeout, parse_task)
642 {
643 Ok(new_tree) => {
644 self.did_finish_parsing(new_tree, parsed_version, cx);
645 return true;
646 }
647 Err(parse_task) => {
648 self.parsing_in_background = true;
649 cx.spawn(move |this, mut cx| async move {
650 let new_tree = parse_task.await;
651 this.update(&mut cx, move |this, cx| {
652 let grammar_changed = this
653 .grammar()
654 .map_or(true, |curr_grammar| !Arc::ptr_eq(&grammar, curr_grammar));
655 let parse_again = this.version.gt(&parsed_version) || grammar_changed;
656 this.parsing_in_background = false;
657 this.did_finish_parsing(new_tree, parsed_version, cx);
658
659 if parse_again && this.reparse(cx) {
660 return;
661 }
662 });
663 })
664 .detach();
665 }
666 }
667 }
668 false
669 }
670
671 fn parse_text(text: &Rope, old_tree: Option<Tree>, grammar: &Grammar) -> Tree {
672 PARSER.with(|parser| {
673 let mut parser = parser.borrow_mut();
674 parser
675 .set_language(grammar.ts_language)
676 .expect("incompatible grammar");
677 let mut chunks = text.chunks_in_range(0..text.len());
678 let tree = parser
679 .parse_with(
680 &mut move |offset, _| {
681 chunks.seek(offset);
682 chunks.next().unwrap_or("").as_bytes()
683 },
684 old_tree.as_ref(),
685 )
686 .unwrap();
687 tree
688 })
689 }
690
691 fn interpolate_tree(&self, tree: &mut SyntaxTree) {
692 for edit in self.edits_since::<(usize, Point)>(&tree.version) {
693 let (bytes, lines) = edit.flatten();
694 tree.tree.edit(&InputEdit {
695 start_byte: bytes.new.start,
696 old_end_byte: bytes.new.start + bytes.old.len(),
697 new_end_byte: bytes.new.end,
698 start_position: lines.new.start.to_ts_point(),
699 old_end_position: (lines.new.start + (lines.old.end - lines.old.start))
700 .to_ts_point(),
701 new_end_position: lines.new.end.to_ts_point(),
702 });
703 }
704 tree.version = self.version();
705 }
706
707 fn did_finish_parsing(
708 &mut self,
709 tree: Tree,
710 version: clock::Global,
711 cx: &mut ModelContext<Self>,
712 ) {
713 self.parse_count += 1;
714 *self.syntax_tree.lock() = Some(SyntaxTree { tree, version });
715 self.request_autoindent(cx);
716 cx.emit(Event::Reparsed);
717 cx.notify();
718 }
719
720 pub fn update_diagnostics(
721 &mut self,
722 version: Option<i32>,
723 mut diagnostics: Vec<lsp::Diagnostic>,
724 cx: &mut ModelContext<Self>,
725 ) -> Result<Operation> {
726 diagnostics.sort_unstable_by_key(|d| (d.range.start, d.range.end));
727
728 let version = version.map(|version| version as usize);
729 let content = if let Some(version) = version {
730 let language_server = self.language_server.as_mut().unwrap();
731 let snapshot = language_server
732 .pending_snapshots
733 .get(&version)
734 .ok_or_else(|| anyhow!("missing snapshot"))?;
735 &snapshot.buffer_snapshot
736 } else {
737 self.deref()
738 };
739 let abs_path = self.file.as_ref().and_then(|f| f.abs_path());
740
741 let empty_set = HashSet::new();
742 let disk_based_sources = self
743 .language
744 .as_ref()
745 .and_then(|language| language.disk_based_diagnostic_sources())
746 .unwrap_or(&empty_set);
747
748 let mut edits_since_save = content
749 .edits_since::<PointUtf16>(&self.saved_version)
750 .peekable();
751 let mut last_edit_old_end = PointUtf16::zero();
752 let mut last_edit_new_end = PointUtf16::zero();
753 let mut group_ids_by_diagnostic_range = HashMap::new();
754 let mut diagnostics_by_group_id = HashMap::new();
755 let mut next_group_id = 0;
756 'outer: for diagnostic in &diagnostics {
757 let mut start = diagnostic.range.start.to_point_utf16();
758 let mut end = diagnostic.range.end.to_point_utf16();
759 let source = diagnostic.source.as_ref();
760 let code = diagnostic.code.as_ref();
761 let group_id = diagnostic_ranges(&diagnostic, abs_path.as_deref())
762 .find_map(|range| group_ids_by_diagnostic_range.get(&(source, code, range)))
763 .copied()
764 .unwrap_or_else(|| {
765 let group_id = post_inc(&mut next_group_id);
766 for range in diagnostic_ranges(&diagnostic, abs_path.as_deref()) {
767 group_ids_by_diagnostic_range.insert((source, code, range), group_id);
768 }
769 group_id
770 });
771
772 if diagnostic
773 .source
774 .as_ref()
775 .map_or(false, |source| disk_based_sources.contains(source))
776 {
777 while let Some(edit) = edits_since_save.peek() {
778 if edit.old.end <= start {
779 last_edit_old_end = edit.old.end;
780 last_edit_new_end = edit.new.end;
781 edits_since_save.next();
782 } else if edit.old.start <= end && edit.old.end >= start {
783 continue 'outer;
784 } else {
785 break;
786 }
787 }
788
789 start = last_edit_new_end + (start - last_edit_old_end);
790 end = last_edit_new_end + (end - last_edit_old_end);
791 }
792
793 let mut range = content.clip_point_utf16(start, Bias::Left)
794 ..content.clip_point_utf16(end, Bias::Right);
795 if range.start == range.end {
796 range.end.column += 1;
797 range.end = content.clip_point_utf16(range.end, Bias::Right);
798 if range.start == range.end && range.end.column > 0 {
799 range.start.column -= 1;
800 range.start = content.clip_point_utf16(range.start, Bias::Left);
801 }
802 }
803
804 diagnostics_by_group_id
805 .entry(group_id)
806 .or_insert(Vec::new())
807 .push(DiagnosticEntry {
808 range,
809 diagnostic: Diagnostic {
810 severity: diagnostic.severity.unwrap_or(DiagnosticSeverity::ERROR),
811 message: diagnostic.message.clone(),
812 group_id,
813 is_primary: false,
814 },
815 });
816 }
817
818 drop(edits_since_save);
819 let new_diagnostics = DiagnosticSet::new(
820 diagnostics_by_group_id
821 .into_values()
822 .flat_map(|mut diagnostics| {
823 let primary = diagnostics
824 .iter_mut()
825 .min_by_key(|entry| entry.diagnostic.severity)
826 .unwrap();
827 primary.diagnostic.is_primary = true;
828 diagnostics
829 }),
830 content,
831 );
832 self.diagnostics = new_diagnostics;
833
834 if let Some(version) = version {
835 let language_server = self.language_server.as_mut().unwrap();
836 let versions_to_delete = language_server
837 .pending_snapshots
838 .range(..version)
839 .map(|(v, _)| *v)
840 .collect::<Vec<_>>();
841 for version in versions_to_delete {
842 language_server.pending_snapshots.remove(&version);
843 }
844 }
845
846 self.diagnostics_update_count += 1;
847 cx.notify();
848 cx.emit(Event::DiagnosticsUpdated);
849 Ok(Operation::UpdateDiagnostics {
850 diagnostics: Arc::from(self.diagnostics.iter().cloned().collect::<Vec<_>>()),
851 lamport_timestamp: self.text.lamport_clock.tick(),
852 })
853 }
854
855 fn request_autoindent(&mut self, cx: &mut ModelContext<Self>) {
856 if let Some(indent_columns) = self.compute_autoindents() {
857 let indent_columns = cx.background().spawn(indent_columns);
858 match cx
859 .background()
860 .block_with_timeout(Duration::from_micros(500), indent_columns)
861 {
862 Ok(indent_columns) => self.apply_autoindents(indent_columns, cx),
863 Err(indent_columns) => {
864 self.pending_autoindent = Some(cx.spawn(|this, mut cx| async move {
865 let indent_columns = indent_columns.await;
866 this.update(&mut cx, |this, cx| {
867 this.apply_autoindents(indent_columns, cx);
868 });
869 }));
870 }
871 }
872 }
873 }
874
875 fn compute_autoindents(&self) -> Option<impl Future<Output = BTreeMap<u32, u32>>> {
876 let max_rows_between_yields = 100;
877 let snapshot = self.snapshot();
878 if snapshot.language.is_none()
879 || snapshot.tree.is_none()
880 || self.autoindent_requests.is_empty()
881 {
882 return None;
883 }
884
885 let autoindent_requests = self.autoindent_requests.clone();
886 Some(async move {
887 let mut indent_columns = BTreeMap::new();
888 for request in autoindent_requests {
889 let old_to_new_rows = request
890 .edited
891 .iter()
892 .map(|anchor| anchor.summary::<Point>(&request.before_edit).row)
893 .zip(
894 request
895 .edited
896 .iter()
897 .map(|anchor| anchor.summary::<Point>(&snapshot).row),
898 )
899 .collect::<BTreeMap<u32, u32>>();
900
901 let mut old_suggestions = HashMap::<u32, u32>::default();
902 let old_edited_ranges =
903 contiguous_ranges(old_to_new_rows.keys().copied(), max_rows_between_yields);
904 for old_edited_range in old_edited_ranges {
905 let suggestions = request
906 .before_edit
907 .suggest_autoindents(old_edited_range.clone())
908 .into_iter()
909 .flatten();
910 for (old_row, suggestion) in old_edited_range.zip(suggestions) {
911 let indentation_basis = old_to_new_rows
912 .get(&suggestion.basis_row)
913 .and_then(|from_row| old_suggestions.get(from_row).copied())
914 .unwrap_or_else(|| {
915 request
916 .before_edit
917 .indent_column_for_line(suggestion.basis_row)
918 });
919 let delta = if suggestion.indent { INDENT_SIZE } else { 0 };
920 old_suggestions.insert(
921 *old_to_new_rows.get(&old_row).unwrap(),
922 indentation_basis + delta,
923 );
924 }
925 yield_now().await;
926 }
927
928 // At this point, old_suggestions contains the suggested indentation for all edited lines with respect to the state of the
929 // buffer before the edit, but keyed by the row for these lines after the edits were applied.
930 let new_edited_row_ranges =
931 contiguous_ranges(old_to_new_rows.values().copied(), max_rows_between_yields);
932 for new_edited_row_range in new_edited_row_ranges {
933 let suggestions = snapshot
934 .suggest_autoindents(new_edited_row_range.clone())
935 .into_iter()
936 .flatten();
937 for (new_row, suggestion) in new_edited_row_range.zip(suggestions) {
938 let delta = if suggestion.indent { INDENT_SIZE } else { 0 };
939 let new_indentation = indent_columns
940 .get(&suggestion.basis_row)
941 .copied()
942 .unwrap_or_else(|| {
943 snapshot.indent_column_for_line(suggestion.basis_row)
944 })
945 + delta;
946 if old_suggestions
947 .get(&new_row)
948 .map_or(true, |old_indentation| new_indentation != *old_indentation)
949 {
950 indent_columns.insert(new_row, new_indentation);
951 }
952 }
953 yield_now().await;
954 }
955
956 if let Some(inserted) = request.inserted.as_ref() {
957 let inserted_row_ranges = contiguous_ranges(
958 inserted
959 .iter()
960 .map(|range| range.to_point(&snapshot))
961 .flat_map(|range| range.start.row..range.end.row + 1),
962 max_rows_between_yields,
963 );
964 for inserted_row_range in inserted_row_ranges {
965 let suggestions = snapshot
966 .suggest_autoindents(inserted_row_range.clone())
967 .into_iter()
968 .flatten();
969 for (row, suggestion) in inserted_row_range.zip(suggestions) {
970 let delta = if suggestion.indent { INDENT_SIZE } else { 0 };
971 let new_indentation = indent_columns
972 .get(&suggestion.basis_row)
973 .copied()
974 .unwrap_or_else(|| {
975 snapshot.indent_column_for_line(suggestion.basis_row)
976 })
977 + delta;
978 indent_columns.insert(row, new_indentation);
979 }
980 yield_now().await;
981 }
982 }
983 }
984 indent_columns
985 })
986 }
987
988 fn apply_autoindents(
989 &mut self,
990 indent_columns: BTreeMap<u32, u32>,
991 cx: &mut ModelContext<Self>,
992 ) {
993 self.start_transaction();
994 for (row, indent_column) in &indent_columns {
995 self.set_indent_column_for_line(*row, *indent_column, cx);
996 }
997 self.end_transaction(cx);
998 }
999
1000 fn set_indent_column_for_line(&mut self, row: u32, column: u32, cx: &mut ModelContext<Self>) {
1001 let current_column = self.indent_column_for_line(row);
1002 if column > current_column {
1003 let offset = Point::new(row, 0).to_offset(&*self);
1004 self.edit(
1005 [offset..offset],
1006 " ".repeat((column - current_column) as usize),
1007 cx,
1008 );
1009 } else if column < current_column {
1010 self.edit(
1011 [Point::new(row, 0)..Point::new(row, current_column - column)],
1012 "",
1013 cx,
1014 );
1015 }
1016 }
1017
1018 pub(crate) fn diff(&self, new_text: Arc<str>, cx: &AppContext) -> Task<Diff> {
1019 // TODO: it would be nice to not allocate here.
1020 let old_text = self.text();
1021 let base_version = self.version();
1022 cx.background().spawn(async move {
1023 let changes = TextDiff::from_lines(old_text.as_str(), new_text.as_ref())
1024 .iter_all_changes()
1025 .map(|c| (c.tag(), c.value().len()))
1026 .collect::<Vec<_>>();
1027 Diff {
1028 base_version,
1029 new_text,
1030 changes,
1031 }
1032 })
1033 }
1034
1035 pub(crate) fn apply_diff(&mut self, diff: Diff, cx: &mut ModelContext<Self>) -> bool {
1036 if self.version == diff.base_version {
1037 self.start_transaction();
1038 let mut offset = 0;
1039 for (tag, len) in diff.changes {
1040 let range = offset..(offset + len);
1041 match tag {
1042 ChangeTag::Equal => offset += len,
1043 ChangeTag::Delete => self.edit(Some(range), "", cx),
1044 ChangeTag::Insert => {
1045 self.edit(Some(offset..offset), &diff.new_text[range], cx);
1046 offset += len;
1047 }
1048 }
1049 }
1050 self.end_transaction(cx);
1051 true
1052 } else {
1053 false
1054 }
1055 }
1056
1057 pub fn is_dirty(&self) -> bool {
1058 !self.saved_version.ge(&self.version)
1059 || self.file.as_ref().map_or(false, |file| file.is_deleted())
1060 }
1061
1062 pub fn has_conflict(&self) -> bool {
1063 !self.saved_version.ge(&self.version)
1064 && self
1065 .file
1066 .as_ref()
1067 .map_or(false, |file| file.mtime() > self.saved_mtime)
1068 }
1069
1070 pub fn subscribe(&mut self) -> Subscription {
1071 self.text.subscribe()
1072 }
1073
1074 pub fn start_transaction(&mut self) -> Option<TransactionId> {
1075 self.start_transaction_at(Instant::now())
1076 }
1077
1078 pub fn start_transaction_at(&mut self, now: Instant) -> Option<TransactionId> {
1079 self.text.start_transaction_at(now)
1080 }
1081
1082 pub fn end_transaction(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
1083 self.end_transaction_at(Instant::now(), cx)
1084 }
1085
1086 pub fn end_transaction_at(
1087 &mut self,
1088 now: Instant,
1089 cx: &mut ModelContext<Self>,
1090 ) -> Option<TransactionId> {
1091 if let Some((transaction_id, start_version)) = self.text.end_transaction_at(now) {
1092 let was_dirty = start_version != self.saved_version;
1093 self.did_edit(&start_version, was_dirty, cx);
1094 Some(transaction_id)
1095 } else {
1096 None
1097 }
1098 }
1099
1100 pub fn set_active_selections(
1101 &mut self,
1102 selections: Arc<[Selection<Anchor>]>,
1103 cx: &mut ModelContext<Self>,
1104 ) {
1105 let lamport_timestamp = self.text.lamport_clock.tick();
1106 self.remote_selections
1107 .insert(self.text.replica_id(), selections.clone());
1108 self.send_operation(
1109 Operation::UpdateSelections {
1110 replica_id: self.text.replica_id(),
1111 selections,
1112 lamport_timestamp,
1113 },
1114 cx,
1115 );
1116 }
1117
1118 pub fn remove_active_selections(&mut self, cx: &mut ModelContext<Self>) {
1119 let lamport_timestamp = self.text.lamport_clock.tick();
1120 self.send_operation(
1121 Operation::RemoveSelections {
1122 replica_id: self.text.replica_id(),
1123 lamport_timestamp,
1124 },
1125 cx,
1126 );
1127 }
1128
1129 fn update_language_server(&mut self) {
1130 let language_server = if let Some(language_server) = self.language_server.as_mut() {
1131 language_server
1132 } else {
1133 return;
1134 };
1135 let abs_path = self
1136 .file
1137 .as_ref()
1138 .map_or(Path::new("/").to_path_buf(), |file| {
1139 file.abs_path().unwrap()
1140 });
1141
1142 let version = post_inc(&mut language_server.next_version);
1143 let snapshot = LanguageServerSnapshot {
1144 buffer_snapshot: self.text.snapshot(),
1145 version,
1146 path: Arc::from(abs_path),
1147 };
1148 language_server
1149 .pending_snapshots
1150 .insert(version, snapshot.clone());
1151 let _ = language_server
1152 .latest_snapshot
1153 .blocking_send(Some(snapshot));
1154 }
1155
1156 pub fn edit<I, S, T>(&mut self, ranges_iter: I, new_text: T, cx: &mut ModelContext<Self>)
1157 where
1158 I: IntoIterator<Item = Range<S>>,
1159 S: ToOffset,
1160 T: Into<String>,
1161 {
1162 self.edit_internal(ranges_iter, new_text, false, cx)
1163 }
1164
1165 pub fn edit_with_autoindent<I, S, T>(
1166 &mut self,
1167 ranges_iter: I,
1168 new_text: T,
1169 cx: &mut ModelContext<Self>,
1170 ) where
1171 I: IntoIterator<Item = Range<S>>,
1172 S: ToOffset,
1173 T: Into<String>,
1174 {
1175 self.edit_internal(ranges_iter, new_text, true, cx)
1176 }
1177
1178 pub fn edit_internal<I, S, T>(
1179 &mut self,
1180 ranges_iter: I,
1181 new_text: T,
1182 autoindent: bool,
1183 cx: &mut ModelContext<Self>,
1184 ) where
1185 I: IntoIterator<Item = Range<S>>,
1186 S: ToOffset,
1187 T: Into<String>,
1188 {
1189 let new_text = new_text.into();
1190
1191 // Skip invalid ranges and coalesce contiguous ones.
1192 let mut ranges: Vec<Range<usize>> = Vec::new();
1193 for range in ranges_iter {
1194 let range = range.start.to_offset(self)..range.end.to_offset(self);
1195 if !new_text.is_empty() || !range.is_empty() {
1196 if let Some(prev_range) = ranges.last_mut() {
1197 if prev_range.end >= range.start {
1198 prev_range.end = cmp::max(prev_range.end, range.end);
1199 } else {
1200 ranges.push(range);
1201 }
1202 } else {
1203 ranges.push(range);
1204 }
1205 }
1206 }
1207 if ranges.is_empty() {
1208 return;
1209 }
1210
1211 self.start_transaction();
1212 self.pending_autoindent.take();
1213 let autoindent_request = if autoindent && self.language.is_some() {
1214 let before_edit = self.snapshot();
1215 let edited = ranges
1216 .iter()
1217 .filter_map(|range| {
1218 let start = range.start.to_point(self);
1219 if new_text.starts_with('\n') && start.column == self.line_len(start.row) {
1220 None
1221 } else {
1222 Some(self.anchor_before(range.start))
1223 }
1224 })
1225 .collect();
1226 Some((before_edit, edited))
1227 } else {
1228 None
1229 };
1230
1231 let first_newline_ix = new_text.find('\n');
1232 let new_text_len = new_text.len();
1233
1234 let edit = self.text.edit(ranges.iter().cloned(), new_text);
1235
1236 if let Some((before_edit, edited)) = autoindent_request {
1237 let mut inserted = None;
1238 if let Some(first_newline_ix) = first_newline_ix {
1239 let mut delta = 0isize;
1240 inserted = Some(
1241 ranges
1242 .iter()
1243 .map(|range| {
1244 let start =
1245 (delta + range.start as isize) as usize + first_newline_ix + 1;
1246 let end = (delta + range.start as isize) as usize + new_text_len;
1247 delta +=
1248 (range.end as isize - range.start as isize) + new_text_len as isize;
1249 self.anchor_before(start)..self.anchor_after(end)
1250 })
1251 .collect(),
1252 );
1253 }
1254
1255 self.autoindent_requests.push(Arc::new(AutoindentRequest {
1256 before_edit,
1257 edited,
1258 inserted,
1259 }));
1260 }
1261
1262 self.end_transaction(cx);
1263 self.send_operation(Operation::Buffer(text::Operation::Edit(edit)), cx);
1264 }
1265
1266 fn did_edit(
1267 &mut self,
1268 old_version: &clock::Global,
1269 was_dirty: bool,
1270 cx: &mut ModelContext<Self>,
1271 ) {
1272 if self.edits_since::<usize>(old_version).next().is_none() {
1273 return;
1274 }
1275
1276 self.reparse(cx);
1277 self.update_language_server();
1278
1279 cx.emit(Event::Edited);
1280 if !was_dirty {
1281 cx.emit(Event::Dirtied);
1282 }
1283 cx.notify();
1284 }
1285
1286 fn grammar(&self) -> Option<&Arc<Grammar>> {
1287 self.language.as_ref().and_then(|l| l.grammar.as_ref())
1288 }
1289
1290 pub fn apply_ops<I: IntoIterator<Item = Operation>>(
1291 &mut self,
1292 ops: I,
1293 cx: &mut ModelContext<Self>,
1294 ) -> Result<()> {
1295 self.pending_autoindent.take();
1296 let was_dirty = self.is_dirty();
1297 let old_version = self.version.clone();
1298 let mut deferred_ops = Vec::new();
1299 let buffer_ops = ops
1300 .into_iter()
1301 .filter_map(|op| match op {
1302 Operation::Buffer(op) => Some(op),
1303 _ => {
1304 if self.can_apply_op(&op) {
1305 self.apply_op(op, cx);
1306 } else {
1307 deferred_ops.push(op);
1308 }
1309 None
1310 }
1311 })
1312 .collect::<Vec<_>>();
1313 self.text.apply_ops(buffer_ops)?;
1314 self.flush_deferred_ops(cx);
1315 self.did_edit(&old_version, was_dirty, cx);
1316 // Notify independently of whether the buffer was edited as the operations could include a
1317 // selection update.
1318 cx.notify();
1319 Ok(())
1320 }
1321
1322 fn flush_deferred_ops(&mut self, cx: &mut ModelContext<Self>) {
1323 let mut deferred_ops = Vec::new();
1324 for op in self.deferred_ops.drain().iter().cloned() {
1325 if self.can_apply_op(&op) {
1326 self.apply_op(op, cx);
1327 } else {
1328 deferred_ops.push(op);
1329 }
1330 }
1331 self.deferred_ops.insert(deferred_ops);
1332 }
1333
1334 fn can_apply_op(&self, operation: &Operation) -> bool {
1335 match operation {
1336 Operation::Buffer(_) => {
1337 unreachable!("buffer operations should never be applied at this layer")
1338 }
1339 Operation::UpdateDiagnostics { diagnostics, .. } => {
1340 diagnostics.iter().all(|diagnostic| {
1341 self.text.can_resolve(&diagnostic.range.start)
1342 && self.text.can_resolve(&diagnostic.range.end)
1343 })
1344 }
1345 Operation::UpdateSelections { selections, .. } => selections
1346 .iter()
1347 .all(|s| self.can_resolve(&s.start) && self.can_resolve(&s.end)),
1348 Operation::RemoveSelections { .. } => true,
1349 }
1350 }
1351
1352 fn apply_op(&mut self, operation: Operation, cx: &mut ModelContext<Self>) {
1353 match operation {
1354 Operation::Buffer(_) => {
1355 unreachable!("buffer operations should never be applied at this layer")
1356 }
1357 Operation::UpdateDiagnostics { diagnostics, .. } => {
1358 self.apply_diagnostic_update(diagnostics, cx);
1359 }
1360 Operation::UpdateSelections {
1361 replica_id,
1362 selections,
1363 lamport_timestamp,
1364 } => {
1365 self.remote_selections.insert(replica_id, selections);
1366 self.text.lamport_clock.observe(lamport_timestamp);
1367 }
1368 Operation::RemoveSelections {
1369 replica_id,
1370 lamport_timestamp,
1371 } => {
1372 self.remote_selections.remove(&replica_id);
1373 self.text.lamport_clock.observe(lamport_timestamp);
1374 }
1375 }
1376 }
1377
1378 fn apply_diagnostic_update(
1379 &mut self,
1380 diagnostics: Arc<[DiagnosticEntry<Anchor>]>,
1381 cx: &mut ModelContext<Self>,
1382 ) {
1383 self.diagnostics = DiagnosticSet::from_sorted_entries(diagnostics.iter().cloned(), self);
1384 self.diagnostics_update_count += 1;
1385 cx.notify();
1386 }
1387
1388 #[cfg(not(test))]
1389 pub fn send_operation(&mut self, operation: Operation, cx: &mut ModelContext<Self>) {
1390 if let Some(file) = &self.file {
1391 file.buffer_updated(self.remote_id(), operation, cx.as_mut());
1392 }
1393 }
1394
1395 #[cfg(test)]
1396 pub fn send_operation(&mut self, operation: Operation, _: &mut ModelContext<Self>) {
1397 self.operations.push(operation);
1398 }
1399
1400 pub fn remove_peer(&mut self, replica_id: ReplicaId, cx: &mut ModelContext<Self>) {
1401 self.remote_selections.remove(&replica_id);
1402 cx.notify();
1403 }
1404
1405 pub fn undo(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
1406 let was_dirty = self.is_dirty();
1407 let old_version = self.version.clone();
1408
1409 if let Some((transaction_id, operation)) = self.text.undo() {
1410 self.send_operation(Operation::Buffer(operation), cx);
1411 self.did_edit(&old_version, was_dirty, cx);
1412 Some(transaction_id)
1413 } else {
1414 None
1415 }
1416 }
1417
1418 pub fn redo(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
1419 let was_dirty = self.is_dirty();
1420 let old_version = self.version.clone();
1421
1422 if let Some((transaction_id, operation)) = self.text.redo() {
1423 self.send_operation(Operation::Buffer(operation), cx);
1424 self.did_edit(&old_version, was_dirty, cx);
1425 Some(transaction_id)
1426 } else {
1427 None
1428 }
1429 }
1430}
1431
1432#[cfg(any(test, feature = "test-support"))]
1433impl Buffer {
1434 pub fn randomly_edit<T>(
1435 &mut self,
1436 rng: &mut T,
1437 old_range_count: usize,
1438 cx: &mut ModelContext<Self>,
1439 ) where
1440 T: rand::Rng,
1441 {
1442 self.start_transaction();
1443 self.text.randomly_edit(rng, old_range_count);
1444 self.end_transaction(cx);
1445 }
1446}
1447
1448impl Entity for Buffer {
1449 type Event = Event;
1450
1451 fn release(&mut self, cx: &mut gpui::MutableAppContext) {
1452 if let Some(file) = self.file.as_ref() {
1453 file.buffer_removed(self.remote_id(), cx);
1454 }
1455 }
1456}
1457
1458impl Deref for Buffer {
1459 type Target = TextBuffer;
1460
1461 fn deref(&self) -> &Self::Target {
1462 &self.text
1463 }
1464}
1465
1466impl BufferSnapshot {
1467 fn suggest_autoindents<'a>(
1468 &'a self,
1469 row_range: Range<u32>,
1470 ) -> Option<impl Iterator<Item = IndentSuggestion> + 'a> {
1471 let mut query_cursor = QueryCursorHandle::new();
1472 if let Some((grammar, tree)) = self.grammar().zip(self.tree.as_ref()) {
1473 let prev_non_blank_row = self.prev_non_blank_row(row_range.start);
1474
1475 // Get the "indentation ranges" that intersect this row range.
1476 let indent_capture_ix = grammar.indents_query.capture_index_for_name("indent");
1477 let end_capture_ix = grammar.indents_query.capture_index_for_name("end");
1478 query_cursor.set_point_range(
1479 Point::new(prev_non_blank_row.unwrap_or(row_range.start), 0).to_ts_point()
1480 ..Point::new(row_range.end, 0).to_ts_point(),
1481 );
1482 let mut indentation_ranges = Vec::<(Range<Point>, &'static str)>::new();
1483 for mat in query_cursor.matches(
1484 &grammar.indents_query,
1485 tree.root_node(),
1486 TextProvider(self.as_rope()),
1487 ) {
1488 let mut node_kind = "";
1489 let mut start: Option<Point> = None;
1490 let mut end: Option<Point> = None;
1491 for capture in mat.captures {
1492 if Some(capture.index) == indent_capture_ix {
1493 node_kind = capture.node.kind();
1494 start.get_or_insert(Point::from_ts_point(capture.node.start_position()));
1495 end.get_or_insert(Point::from_ts_point(capture.node.end_position()));
1496 } else if Some(capture.index) == end_capture_ix {
1497 end = Some(Point::from_ts_point(capture.node.start_position().into()));
1498 }
1499 }
1500
1501 if let Some((start, end)) = start.zip(end) {
1502 if start.row == end.row {
1503 continue;
1504 }
1505
1506 let range = start..end;
1507 match indentation_ranges.binary_search_by_key(&range.start, |r| r.0.start) {
1508 Err(ix) => indentation_ranges.insert(ix, (range, node_kind)),
1509 Ok(ix) => {
1510 let prev_range = &mut indentation_ranges[ix];
1511 prev_range.0.end = prev_range.0.end.max(range.end);
1512 }
1513 }
1514 }
1515 }
1516
1517 let mut prev_row = prev_non_blank_row.unwrap_or(0);
1518 Some(row_range.map(move |row| {
1519 let row_start = Point::new(row, self.indent_column_for_line(row));
1520
1521 let mut indent_from_prev_row = false;
1522 let mut outdent_to_row = u32::MAX;
1523 for (range, _node_kind) in &indentation_ranges {
1524 if range.start.row >= row {
1525 break;
1526 }
1527
1528 if range.start.row == prev_row && range.end > row_start {
1529 indent_from_prev_row = true;
1530 }
1531 if range.end.row >= prev_row && range.end <= row_start {
1532 outdent_to_row = outdent_to_row.min(range.start.row);
1533 }
1534 }
1535
1536 let suggestion = if outdent_to_row == prev_row {
1537 IndentSuggestion {
1538 basis_row: prev_row,
1539 indent: false,
1540 }
1541 } else if indent_from_prev_row {
1542 IndentSuggestion {
1543 basis_row: prev_row,
1544 indent: true,
1545 }
1546 } else if outdent_to_row < prev_row {
1547 IndentSuggestion {
1548 basis_row: outdent_to_row,
1549 indent: false,
1550 }
1551 } else {
1552 IndentSuggestion {
1553 basis_row: prev_row,
1554 indent: false,
1555 }
1556 };
1557
1558 prev_row = row;
1559 suggestion
1560 }))
1561 } else {
1562 None
1563 }
1564 }
1565
1566 fn prev_non_blank_row(&self, mut row: u32) -> Option<u32> {
1567 while row > 0 {
1568 row -= 1;
1569 if !self.is_line_blank(row) {
1570 return Some(row);
1571 }
1572 }
1573 None
1574 }
1575
1576 pub fn chunks<'a, T: ToOffset>(
1577 &'a self,
1578 range: Range<T>,
1579 theme: Option<&'a SyntaxTheme>,
1580 ) -> BufferChunks<'a> {
1581 let range = range.start.to_offset(self)..range.end.to_offset(self);
1582
1583 let mut highlights = None;
1584 let mut diagnostic_endpoints = Vec::<DiagnosticEndpoint>::new();
1585 if let Some(theme) = theme {
1586 for entry in self
1587 .diagnostics
1588 .range::<_, usize>(range.clone(), self, true)
1589 {
1590 diagnostic_endpoints.push(DiagnosticEndpoint {
1591 offset: entry.range.start,
1592 is_start: true,
1593 severity: entry.diagnostic.severity,
1594 });
1595 diagnostic_endpoints.push(DiagnosticEndpoint {
1596 offset: entry.range.end,
1597 is_start: false,
1598 severity: entry.diagnostic.severity,
1599 });
1600 }
1601 diagnostic_endpoints
1602 .sort_unstable_by_key(|endpoint| (endpoint.offset, !endpoint.is_start));
1603
1604 if let Some((grammar, tree)) = self.grammar().zip(self.tree.as_ref()) {
1605 let mut query_cursor = QueryCursorHandle::new();
1606
1607 // TODO - add a Tree-sitter API to remove the need for this.
1608 let cursor = unsafe {
1609 std::mem::transmute::<_, &'static mut QueryCursor>(query_cursor.deref_mut())
1610 };
1611 let captures = cursor.set_byte_range(range.clone()).captures(
1612 &grammar.highlights_query,
1613 tree.root_node(),
1614 TextProvider(self.text.as_rope()),
1615 );
1616 highlights = Some(BufferChunkHighlights {
1617 captures,
1618 next_capture: None,
1619 stack: Default::default(),
1620 highlight_map: grammar.highlight_map(),
1621 _query_cursor: query_cursor,
1622 theme,
1623 })
1624 }
1625 }
1626
1627 let diagnostic_endpoints = diagnostic_endpoints.into_iter().peekable();
1628 let chunks = self.text.as_rope().chunks_in_range(range.clone());
1629
1630 BufferChunks {
1631 range,
1632 chunks,
1633 diagnostic_endpoints,
1634 error_depth: 0,
1635 warning_depth: 0,
1636 information_depth: 0,
1637 hint_depth: 0,
1638 highlights,
1639 }
1640 }
1641
1642 pub fn language(&self) -> Option<&Arc<Language>> {
1643 self.language.as_ref()
1644 }
1645
1646 fn grammar(&self) -> Option<&Arc<Grammar>> {
1647 self.language
1648 .as_ref()
1649 .and_then(|language| language.grammar.as_ref())
1650 }
1651
1652 pub fn range_for_syntax_ancestor<T: ToOffset>(&self, range: Range<T>) -> Option<Range<usize>> {
1653 if let Some(tree) = self.tree.as_ref() {
1654 let root = tree.root_node();
1655 let range = range.start.to_offset(self)..range.end.to_offset(self);
1656 let mut node = root.descendant_for_byte_range(range.start, range.end);
1657 while node.map_or(false, |n| n.byte_range() == range) {
1658 node = node.unwrap().parent();
1659 }
1660 node.map(|n| n.byte_range())
1661 } else {
1662 None
1663 }
1664 }
1665
1666 pub fn enclosing_bracket_ranges<T: ToOffset>(
1667 &self,
1668 range: Range<T>,
1669 ) -> Option<(Range<usize>, Range<usize>)> {
1670 let (grammar, tree) = self.grammar().zip(self.tree.as_ref())?;
1671 let open_capture_ix = grammar.brackets_query.capture_index_for_name("open")?;
1672 let close_capture_ix = grammar.brackets_query.capture_index_for_name("close")?;
1673
1674 // Find bracket pairs that *inclusively* contain the given range.
1675 let range = range.start.to_offset(self).saturating_sub(1)..range.end.to_offset(self) + 1;
1676 let mut cursor = QueryCursorHandle::new();
1677 let matches = cursor.set_byte_range(range).matches(
1678 &grammar.brackets_query,
1679 tree.root_node(),
1680 TextProvider(self.as_rope()),
1681 );
1682
1683 // Get the ranges of the innermost pair of brackets.
1684 matches
1685 .filter_map(|mat| {
1686 let open = mat.nodes_for_capture_index(open_capture_ix).next()?;
1687 let close = mat.nodes_for_capture_index(close_capture_ix).next()?;
1688 Some((open.byte_range(), close.byte_range()))
1689 })
1690 .min_by_key(|(open_range, close_range)| close_range.end - open_range.start)
1691 }
1692
1693 pub fn remote_selections_in_range<'a>(
1694 &'a self,
1695 range: Range<Anchor>,
1696 ) -> impl 'a + Iterator<Item = (ReplicaId, impl 'a + Iterator<Item = &'a Selection<Anchor>>)>
1697 {
1698 self.remote_selections
1699 .iter()
1700 .filter(|(replica_id, _)| **replica_id != self.text.replica_id())
1701 .map(move |(replica_id, selections)| {
1702 let start_ix = match selections
1703 .binary_search_by(|probe| probe.end.cmp(&range.start, self).unwrap())
1704 {
1705 Ok(ix) | Err(ix) => ix,
1706 };
1707 let end_ix = match selections
1708 .binary_search_by(|probe| probe.start.cmp(&range.end, self).unwrap())
1709 {
1710 Ok(ix) | Err(ix) => ix,
1711 };
1712
1713 (*replica_id, selections[start_ix..end_ix].iter())
1714 })
1715 }
1716
1717 pub fn diagnostics_in_range<'a, T, O>(
1718 &'a self,
1719 search_range: Range<T>,
1720 ) -> impl 'a + Iterator<Item = DiagnosticEntry<O>>
1721 where
1722 T: 'a + ToOffset,
1723 O: 'a + FromAnchor,
1724 {
1725 self.diagnostics.range(search_range, self, true)
1726 }
1727
1728 pub fn diagnostic_group<'a, O>(
1729 &'a self,
1730 group_id: usize,
1731 ) -> impl 'a + Iterator<Item = DiagnosticEntry<O>>
1732 where
1733 O: 'a + FromAnchor,
1734 {
1735 self.diagnostics.group(group_id, self)
1736 }
1737
1738 pub fn diagnostics_update_count(&self) -> usize {
1739 self.diagnostics_update_count
1740 }
1741
1742 pub fn parse_count(&self) -> usize {
1743 self.parse_count
1744 }
1745}
1746
1747impl Clone for BufferSnapshot {
1748 fn clone(&self) -> Self {
1749 Self {
1750 text: self.text.clone(),
1751 tree: self.tree.clone(),
1752 remote_selections: self.remote_selections.clone(),
1753 diagnostics: self.diagnostics.clone(),
1754 diagnostics_update_count: self.diagnostics_update_count,
1755 is_parsing: self.is_parsing,
1756 language: self.language.clone(),
1757 parse_count: self.parse_count,
1758 }
1759 }
1760}
1761
1762impl Deref for BufferSnapshot {
1763 type Target = text::BufferSnapshot;
1764
1765 fn deref(&self) -> &Self::Target {
1766 &self.text
1767 }
1768}
1769
1770impl<'a> tree_sitter::TextProvider<'a> for TextProvider<'a> {
1771 type I = ByteChunks<'a>;
1772
1773 fn text(&mut self, node: tree_sitter::Node) -> Self::I {
1774 ByteChunks(self.0.chunks_in_range(node.byte_range()))
1775 }
1776}
1777
1778struct ByteChunks<'a>(rope::Chunks<'a>);
1779
1780impl<'a> Iterator for ByteChunks<'a> {
1781 type Item = &'a [u8];
1782
1783 fn next(&mut self) -> Option<Self::Item> {
1784 self.0.next().map(str::as_bytes)
1785 }
1786}
1787
1788unsafe impl<'a> Send for BufferChunks<'a> {}
1789
1790impl<'a> BufferChunks<'a> {
1791 pub fn seek(&mut self, offset: usize) {
1792 self.range.start = offset;
1793 self.chunks.seek(self.range.start);
1794 if let Some(highlights) = self.highlights.as_mut() {
1795 highlights
1796 .stack
1797 .retain(|(end_offset, _)| *end_offset > offset);
1798 if let Some((mat, capture_ix)) = &highlights.next_capture {
1799 let capture = mat.captures[*capture_ix as usize];
1800 if offset >= capture.node.start_byte() {
1801 let next_capture_end = capture.node.end_byte();
1802 if offset < next_capture_end {
1803 highlights.stack.push((
1804 next_capture_end,
1805 highlights.highlight_map.get(capture.index),
1806 ));
1807 }
1808 highlights.next_capture.take();
1809 }
1810 }
1811 highlights.captures.set_byte_range(self.range.clone());
1812 }
1813 }
1814
1815 pub fn offset(&self) -> usize {
1816 self.range.start
1817 }
1818
1819 fn update_diagnostic_depths(&mut self, endpoint: DiagnosticEndpoint) {
1820 let depth = match endpoint.severity {
1821 DiagnosticSeverity::ERROR => &mut self.error_depth,
1822 DiagnosticSeverity::WARNING => &mut self.warning_depth,
1823 DiagnosticSeverity::INFORMATION => &mut self.information_depth,
1824 DiagnosticSeverity::HINT => &mut self.hint_depth,
1825 _ => return,
1826 };
1827 if endpoint.is_start {
1828 *depth += 1;
1829 } else {
1830 *depth -= 1;
1831 }
1832 }
1833
1834 fn current_diagnostic_severity(&mut self) -> Option<DiagnosticSeverity> {
1835 if self.error_depth > 0 {
1836 Some(DiagnosticSeverity::ERROR)
1837 } else if self.warning_depth > 0 {
1838 Some(DiagnosticSeverity::WARNING)
1839 } else if self.information_depth > 0 {
1840 Some(DiagnosticSeverity::INFORMATION)
1841 } else if self.hint_depth > 0 {
1842 Some(DiagnosticSeverity::HINT)
1843 } else {
1844 None
1845 }
1846 }
1847}
1848
1849impl<'a> Iterator for BufferChunks<'a> {
1850 type Item = Chunk<'a>;
1851
1852 fn next(&mut self) -> Option<Self::Item> {
1853 let mut next_capture_start = usize::MAX;
1854 let mut next_diagnostic_endpoint = usize::MAX;
1855
1856 if let Some(highlights) = self.highlights.as_mut() {
1857 while let Some((parent_capture_end, _)) = highlights.stack.last() {
1858 if *parent_capture_end <= self.range.start {
1859 highlights.stack.pop();
1860 } else {
1861 break;
1862 }
1863 }
1864
1865 if highlights.next_capture.is_none() {
1866 highlights.next_capture = highlights.captures.next();
1867 }
1868
1869 while let Some((mat, capture_ix)) = highlights.next_capture.as_ref() {
1870 let capture = mat.captures[*capture_ix as usize];
1871 if self.range.start < capture.node.start_byte() {
1872 next_capture_start = capture.node.start_byte();
1873 break;
1874 } else {
1875 let highlight_id = highlights.highlight_map.get(capture.index);
1876 highlights
1877 .stack
1878 .push((capture.node.end_byte(), highlight_id));
1879 highlights.next_capture = highlights.captures.next();
1880 }
1881 }
1882 }
1883
1884 while let Some(endpoint) = self.diagnostic_endpoints.peek().copied() {
1885 if endpoint.offset <= self.range.start {
1886 self.update_diagnostic_depths(endpoint);
1887 self.diagnostic_endpoints.next();
1888 } else {
1889 next_diagnostic_endpoint = endpoint.offset;
1890 break;
1891 }
1892 }
1893
1894 if let Some(chunk) = self.chunks.peek() {
1895 let chunk_start = self.range.start;
1896 let mut chunk_end = (self.chunks.offset() + chunk.len())
1897 .min(next_capture_start)
1898 .min(next_diagnostic_endpoint);
1899 let mut highlight_style = None;
1900 if let Some(highlights) = self.highlights.as_ref() {
1901 if let Some((parent_capture_end, parent_highlight_id)) = highlights.stack.last() {
1902 chunk_end = chunk_end.min(*parent_capture_end);
1903 highlight_style = parent_highlight_id.style(highlights.theme);
1904 }
1905 }
1906
1907 let slice =
1908 &chunk[chunk_start - self.chunks.offset()..chunk_end - self.chunks.offset()];
1909 self.range.start = chunk_end;
1910 if self.range.start == self.chunks.offset() + chunk.len() {
1911 self.chunks.next().unwrap();
1912 }
1913
1914 Some(Chunk {
1915 text: slice,
1916 highlight_style,
1917 diagnostic: self.current_diagnostic_severity(),
1918 })
1919 } else {
1920 None
1921 }
1922 }
1923}
1924
1925impl QueryCursorHandle {
1926 fn new() -> Self {
1927 QueryCursorHandle(Some(
1928 QUERY_CURSORS
1929 .lock()
1930 .pop()
1931 .unwrap_or_else(|| QueryCursor::new()),
1932 ))
1933 }
1934}
1935
1936impl Deref for QueryCursorHandle {
1937 type Target = QueryCursor;
1938
1939 fn deref(&self) -> &Self::Target {
1940 self.0.as_ref().unwrap()
1941 }
1942}
1943
1944impl DerefMut for QueryCursorHandle {
1945 fn deref_mut(&mut self) -> &mut Self::Target {
1946 self.0.as_mut().unwrap()
1947 }
1948}
1949
1950impl Drop for QueryCursorHandle {
1951 fn drop(&mut self) {
1952 let mut cursor = self.0.take().unwrap();
1953 cursor.set_byte_range(0..usize::MAX);
1954 cursor.set_point_range(Point::zero().to_ts_point()..Point::MAX.to_ts_point());
1955 QUERY_CURSORS.lock().push(cursor)
1956 }
1957}
1958
1959trait ToTreeSitterPoint {
1960 fn to_ts_point(self) -> tree_sitter::Point;
1961 fn from_ts_point(point: tree_sitter::Point) -> Self;
1962}
1963
1964impl ToTreeSitterPoint for Point {
1965 fn to_ts_point(self) -> tree_sitter::Point {
1966 tree_sitter::Point::new(self.row as usize, self.column as usize)
1967 }
1968
1969 fn from_ts_point(point: tree_sitter::Point) -> Self {
1970 Point::new(point.row as u32, point.column as u32)
1971 }
1972}
1973
1974trait ToPointUtf16 {
1975 fn to_point_utf16(self) -> PointUtf16;
1976}
1977
1978impl ToPointUtf16 for lsp::Position {
1979 fn to_point_utf16(self) -> PointUtf16 {
1980 PointUtf16::new(self.line, self.character)
1981 }
1982}
1983
1984impl operation_queue::Operation for Operation {
1985 fn lamport_timestamp(&self) -> clock::Lamport {
1986 match self {
1987 Operation::Buffer(_) => {
1988 unreachable!("buffer operations should never be deferred at this layer")
1989 }
1990 Operation::UpdateDiagnostics {
1991 lamport_timestamp, ..
1992 }
1993 | Operation::UpdateSelections {
1994 lamport_timestamp, ..
1995 }
1996 | Operation::RemoveSelections {
1997 lamport_timestamp, ..
1998 } => *lamport_timestamp,
1999 }
2000 }
2001}
2002
2003fn diagnostic_ranges<'a>(
2004 diagnostic: &'a lsp::Diagnostic,
2005 abs_path: Option<&'a Path>,
2006) -> impl 'a + Iterator<Item = Range<PointUtf16>> {
2007 diagnostic
2008 .related_information
2009 .iter()
2010 .flatten()
2011 .filter_map(move |info| {
2012 if info.location.uri.to_file_path().ok()? == abs_path? {
2013 let info_start = PointUtf16::new(
2014 info.location.range.start.line,
2015 info.location.range.start.character,
2016 );
2017 let info_end = PointUtf16::new(
2018 info.location.range.end.line,
2019 info.location.range.end.character,
2020 );
2021 Some(info_start..info_end)
2022 } else {
2023 None
2024 }
2025 })
2026 .chain(Some(
2027 diagnostic.range.start.to_point_utf16()..diagnostic.range.end.to_point_utf16(),
2028 ))
2029}
2030
2031pub fn contiguous_ranges(
2032 values: impl Iterator<Item = u32>,
2033 max_len: usize,
2034) -> impl Iterator<Item = Range<u32>> {
2035 let mut values = values.into_iter();
2036 let mut current_range: Option<Range<u32>> = None;
2037 std::iter::from_fn(move || loop {
2038 if let Some(value) = values.next() {
2039 if let Some(range) = &mut current_range {
2040 if value == range.end && range.len() < max_len {
2041 range.end += 1;
2042 continue;
2043 }
2044 }
2045
2046 let prev_range = current_range.clone();
2047 current_range = Some(value..(value + 1));
2048 if prev_range.is_some() {
2049 return prev_range;
2050 }
2051 } else {
2052 return current_range.take();
2053 }
2054 })
2055}