languages: Add JS/TS generator functions to outline (#34388)

Functions like `function* iterateElements() {}` would not show up in the
editor's navigation outline. With this change, they do.

| **Before** | **After**
|-|-|
|<img width="453" height="280" alt="Screenshot 2025-07-13 at 4 58 22 PM"
src="https://github.com/user-attachments/assets/822f0774-bda2-4855-a6dd-80ba82fffaf3"
/>|<img width="564" height="373" alt="Screenshot 2025-07-13 at 4 58
55 PM"
src="https://github.com/user-attachments/assets/f4f6b84f-cd26-49b7-923b-724860eb18ad"
/>|

Note that I decided to use Zed's agent assistance features to do this PR
as a sort of test run. I don't normally code with an AI assistant, but
figured it might be good in this case since I'm unfamiliar with the
codebase. I must say I was fairly impressed. All the changes in this PR
were done by Claude Sonnet 4, though I have done a manual review to
ensure the changes look sane and tested the changes by running the
re-built `zed` binary with a toy project.

Closes #21631

Release Notes:

- Fixed JS/TS outlines to show generator functions.
This commit is contained in:
Brian Donovan 2025-07-14 05:26:17 -07:00 committed by GitHub
parent 2edf85f054
commit 6f9e052edb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 83 additions and 0 deletions

View file

@ -14,6 +14,15 @@
"(" @context
")" @context)) @item
(generator_function_declaration
"async"? @context
"function" @context
"*" @context
name: (_) @name
parameters: (formal_parameters
"(" @context
")" @context)) @item
(interface_declaration
"interface" @context
name: (_) @name) @item

View file

@ -18,6 +18,15 @@
"(" @context
")" @context)) @item
(generator_function_declaration
"async"? @context
"function" @context
"*" @context
name: (_) @name
parameters: (formal_parameters
"(" @context
")" @context)) @item
(interface_declaration
"interface" @context
name: (_) @name) @item

View file

@ -1075,6 +1075,62 @@ mod tests {
);
}
#[gpui::test]
async fn test_generator_function_outline(cx: &mut TestAppContext) {
let language = crate::language("javascript", tree_sitter_typescript::LANGUAGE_TSX.into());
let text = r#"
function normalFunction() {
console.log("normal");
}
function* simpleGenerator() {
yield 1;
yield 2;
}
async function* asyncGenerator() {
yield await Promise.resolve(1);
}
function* generatorWithParams(start, end) {
for (let i = start; i <= end; i++) {
yield i;
}
}
class TestClass {
*methodGenerator() {
yield "method";
}
async *asyncMethodGenerator() {
yield "async method";
}
}
"#
.unindent();
let buffer = cx.new(|cx| language::Buffer::local(text, cx).with_language(language, 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<_>>(),
&[
("function normalFunction()", 0),
("function* simpleGenerator()", 0),
("async function* asyncGenerator()", 0),
("function* generatorWithParams( )", 0),
("class TestClass", 0),
("*methodGenerator()", 1),
("async *asyncMethodGenerator()", 1),
]
);
}
#[gpui::test]
async fn test_package_json_discovery(executor: BackgroundExecutor, cx: &mut TestAppContext) {
cx.update(|cx| {

View file

@ -18,6 +18,15 @@
"(" @context
")" @context)) @item
(generator_function_declaration
"async"? @context
"function" @context
"*" @context
name: (_) @name
parameters: (formal_parameters
"(" @context
")" @context)) @item
(interface_declaration
"interface" @context
name: (_) @name) @item