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