Merge pull request #2046 from zed-industries/line-breaks-in-outline-items

Max Brunsfeld created

Prevent outline items from accidentally spanning multiple lines

Change summary

crates/language/src/buffer.rs           | 10 +++++++---
crates/language/src/buffer_tests.rs     | 26 ++++++++++++++++++++++++++
crates/zed/src/languages/go/outline.scm |  3 +--
3 files changed, 34 insertions(+), 5 deletions(-)

Detailed changes

crates/language/src/buffer.rs 🔗

@@ -2168,8 +2168,6 @@ impl BufferSnapshot {
                 continue;
             }
 
-            // TODO - move later, after processing captures
-
             let mut text = String::new();
             let mut name_ranges = Vec::new();
             let mut highlight_ranges = Vec::new();
@@ -2183,7 +2181,13 @@ impl BufferSnapshot {
                     continue;
                 }
 
-                let range = capture.node.start_byte()..capture.node.end_byte();
+                let mut range = capture.node.start_byte()..capture.node.end_byte();
+                let start = capture.node.start_position();
+                if capture.node.end_position().row > start.row {
+                    range.end =
+                        range.start + self.line_len(start.row as u32) as usize - start.column;
+                }
+
                 if !text.is_empty() {
                     text.push(' ');
                 }

crates/language/src/buffer_tests.rs 🔗

@@ -455,6 +455,32 @@ async fn test_outline(cx: &mut gpui::TestAppContext) {
     }
 }
 
+#[gpui::test]
+async fn test_outline_nodes_with_newlines(cx: &mut gpui::TestAppContext) {
+    let text = r#"
+        impl A for B<
+            C
+        > {
+        };
+    "#
+    .unindent();
+
+    let buffer =
+        cx.add_model(|cx| Buffer::new(0, text, cx).with_language(Arc::new(rust_lang()), cx));
+    let outline = buffer
+        .read_with(cx, |buffer, _| buffer.snapshot().outline(None))
+        .unwrap();
+
+    assert_eq!(
+        outline
+            .items
+            .iter()
+            .map(|item| (item.text.as_str(), item.depth))
+            .collect::<Vec<_>>(),
+        &[("impl A for B<", 0)]
+    );
+}
+
 #[gpui::test]
 async fn test_symbols_containing(cx: &mut gpui::TestAppContext) {
     let text = r#"