Return `Outline<Anchor>` from `MultiBuffer::outline`

Antonio Scandurra and Max Brunsfeld created

Co-Authored-By: Max Brunsfeld <max@zed.dev>

Change summary

crates/editor/src/multi_buffer.rs | 24 ++++++++++++++++++++----
crates/language/src/buffer.rs     |  4 ++--
crates/language/src/outline.rs    | 12 ++++++------
crates/outline/src/outline.rs     |  6 +++---
4 files changed, 31 insertions(+), 15 deletions(-)

Detailed changes

crates/editor/src/multi_buffer.rs 🔗

@@ -6,8 +6,8 @@ use clock::ReplicaId;
 use collections::{HashMap, HashSet};
 use gpui::{AppContext, Entity, ModelContext, ModelHandle, Task};
 use language::{
-    Buffer, BufferChunks, BufferSnapshot, Chunk, DiagnosticEntry, Event, File, Language, Selection,
-    ToOffset as _, ToPoint as _, TransactionId, Outline,
+    Buffer, BufferChunks, BufferSnapshot, Chunk, DiagnosticEntry, Event, File, Language, Outline,
+    OutlineItem, Selection, ToOffset as _, ToPoint as _, TransactionId,
 };
 use std::{
     cell::{Ref, RefCell},
@@ -1698,8 +1698,24 @@ impl MultiBufferSnapshot {
             })
     }
 
-    pub fn outline(&self) -> Option<Outline> {
-        self.as_singleton().and_then(move |buffer| buffer.outline())
+    pub fn outline(&self) -> Option<Outline<Anchor>> {
+        let buffer = self.as_singleton()?;
+        let outline = buffer.outline()?;
+        let excerpt_id = &self.excerpts.iter().next().unwrap().id;
+        Some(Outline::new(
+            outline
+                .items
+                .into_iter()
+                .map(|item| OutlineItem {
+                    id: item.id,
+                    depth: item.depth,
+                    range: self.anchor_in_excerpt(excerpt_id.clone(), item.range.start)
+                        ..self.anchor_in_excerpt(excerpt_id.clone(), item.range.end),
+                    text: item.text,
+                    name_range_in_text: item.name_range_in_text,
+                })
+                .collect(),
+        ))
     }
 
     fn buffer_snapshot_for_excerpt<'a>(

crates/language/src/buffer.rs 🔗

@@ -1835,7 +1835,7 @@ impl BufferSnapshot {
         }
     }
 
-    pub fn outline(&self) -> Option<Outline> {
+    pub fn outline(&self) -> Option<Outline<Anchor>> {
         let tree = self.tree.as_ref()?;
         let grammar = self
             .language
@@ -1910,7 +1910,7 @@ impl BufferSnapshot {
                 Some(OutlineItem {
                     id,
                     depth: stack.len() - 1,
-                    range,
+                    range: self.anchor_after(range.start)..self.anchor_before(range.end),
                     text,
                     name_range_in_text,
                 })

crates/language/src/outline.rs 🔗

@@ -4,22 +4,22 @@ use fuzzy::{StringMatch, StringMatchCandidate};
 use gpui::AppContext;
 
 #[derive(Debug)]
-pub struct Outline {
-    pub items: Vec<OutlineItem>,
+pub struct Outline<T> {
+    pub items: Vec<OutlineItem<T>>,
     candidates: Vec<StringMatchCandidate>,
 }
 
 #[derive(Clone, Debug)]
-pub struct OutlineItem {
+pub struct OutlineItem<T> {
     pub id: usize,
     pub depth: usize,
-    pub range: Range<usize>,
+    pub range: Range<T>,
     pub text: String,
     pub name_range_in_text: Range<usize>,
 }
 
-impl Outline {
-    pub fn new(items: Vec<OutlineItem>) -> Self {
+impl<T> Outline<T> {
+    pub fn new(items: Vec<OutlineItem<T>>) -> Self {
         Self {
             candidates: items
                 .iter()

crates/outline/src/outline.rs 🔗

@@ -1,4 +1,4 @@
-use editor::{Editor, EditorSettings};
+use editor::{Anchor, Editor, EditorSettings};
 use fuzzy::StringMatch;
 use gpui::{
     action,
@@ -34,7 +34,7 @@ pub fn init(cx: &mut MutableAppContext) {
 
 struct OutlineView {
     handle: WeakViewHandle<Self>,
-    outline: Outline,
+    outline: Outline<Anchor>,
     selected_match_index: usize,
     matches: Vec<StringMatch>,
     query_editor: ViewHandle<Editor>,
@@ -90,7 +90,7 @@ impl View for OutlineView {
 
 impl OutlineView {
     fn new(
-        outline: Outline,
+        outline: Outline<Anchor>,
         settings: watch::Receiver<Settings>,
         cx: &mut ViewContext<Self>,
     ) -> Self {