diff --git a/crates/grammars/src/go/outline.scm b/crates/grammars/src/go/outline.scm index da42904fab9..29b9bd7554a 100644 --- a/crates/grammars/src/go/outline.scm +++ b/crates/grammars/src/go/outline.scm @@ -23,7 +23,7 @@ receiver: (parameter_list "(" @context (parameter_declaration - name: (_) @context + name: (_)? @context type: (_) @context) ")" @context) name: (field_identifier) @name diff --git a/crates/languages/src/go.rs b/crates/languages/src/go.rs index 13a4fcc9bdf..87efea16c85 100644 --- a/crates/languages/src/go.rs +++ b/crates/languages/src/go.rs @@ -945,6 +945,7 @@ mod tests { use gpui::{AppContext, Hsla, TestAppContext}; use task::TaskContext; use theme::SyntaxTheme; + use unindent::Unindent as _; fn go_language() -> Arc { let language = language("go", tree_sitter_go::LANGUAGE.into()); @@ -2017,6 +2018,89 @@ mod tests { ); } + #[gpui::test] + fn test_go_outline_includes_methods_with_receiver_forms(cx: &mut TestAppContext) { + let language = go_language(); + + let source = r#" + package main + + type v2 struct{} + + func (v2) BrokenMethod() { + println("start") + } + + func (_ v2) UnderscoreReceiverMethod() { + println("start") + } + + func (v v2) NamedReceiverMethod() { + println("start") + } + + func (v *v2) PointerReceiverMethod() { + println("start") + } + + func WorkingFunction() { + println("start") + } + "# + .unindent(); + + let buffer = + cx.new(|cx| crate::Buffer::local(source.clone(), cx).with_language(language, cx)); + let snapshot = buffer.read_with(cx, |buffer, _| buffer.snapshot()); + let outline = snapshot.outline(None); + + assert_eq!( + outline + .items + .iter() + .map(|item| item.text.as_str()) + .collect::>(), + &[ + "type v2", + "func (v2) BrokenMethod", + "func (_ v2) UnderscoreReceiverMethod", + "func (v v2) NamedReceiverMethod", + "func (v *v2) PointerReceiverMethod", + "func WorkingFunction", + ] + ); + + for (method_name, expected_symbol) in [ + ("BrokenMethod", "func (v2) BrokenMethod"), + ( + "UnderscoreReceiverMethod", + "func (_ v2) UnderscoreReceiverMethod", + ), + ("NamedReceiverMethod", "func (v v2) NamedReceiverMethod"), + ( + "PointerReceiverMethod", + "func (v *v2) PointerReceiverMethod", + ), + ("WorkingFunction", "func WorkingFunction"), + ] { + let method_position = source + .find(&format!("{method_name}()")) + .expect("method should exist in source"); + let body_position = source[method_position..] + .find("println") + .map(|body_offset| method_position + body_offset) + .expect("method should contain a body"); + let symbols = snapshot.symbols_containing(body_position, None); + assert_eq!( + symbols + .last() + .map(|item| item.text.as_str()) + .expect("method should have an outline symbol"), + expected_symbol + ); + } + } + #[test] fn test_extract_subtest_name() { // Interpreted string literal