Copy outline improvements from typescript over to tsx as well (#41862)
Closes #4483 Release Notes: - Interprets outline of tsx files with the same grammar as typescript, including improvements from #39797
This commit is contained in:
@@ -34,18 +34,64 @@
|
||||
(export_statement
|
||||
(lexical_declaration
|
||||
["let" "const"] @context
|
||||
; Multiple names may be exported - @item is on the declarator to keep
|
||||
; ranges distinct.
|
||||
(variable_declarator
|
||||
name: (_) @name) @item))
|
||||
name: (identifier) @name) @item))
|
||||
|
||||
; Exported array destructuring
|
||||
(export_statement
|
||||
(lexical_declaration
|
||||
["let" "const"] @context
|
||||
(variable_declarator
|
||||
name: (array_pattern
|
||||
[
|
||||
(identifier) @name @item
|
||||
(assignment_pattern left: (identifier) @name @item)
|
||||
(rest_pattern (identifier) @name @item)
|
||||
]))))
|
||||
|
||||
; Exported object destructuring
|
||||
(export_statement
|
||||
(lexical_declaration
|
||||
["let" "const"] @context
|
||||
(variable_declarator
|
||||
name: (object_pattern
|
||||
[(shorthand_property_identifier_pattern) @name @item
|
||||
(pair_pattern
|
||||
value: (identifier) @name @item)
|
||||
(pair_pattern
|
||||
value: (assignment_pattern left: (identifier) @name @item))
|
||||
(rest_pattern (identifier) @name @item)]))))
|
||||
|
||||
(program
|
||||
(lexical_declaration
|
||||
["let" "const"] @context
|
||||
; Multiple names may be defined - @item is on the declarator to keep
|
||||
; ranges distinct.
|
||||
(variable_declarator
|
||||
name: (_) @name) @item))
|
||||
name: (identifier) @name) @item))
|
||||
|
||||
; Top-level array destructuring
|
||||
(program
|
||||
(lexical_declaration
|
||||
["let" "const"] @context
|
||||
(variable_declarator
|
||||
name: (array_pattern
|
||||
[
|
||||
(identifier) @name @item
|
||||
(assignment_pattern left: (identifier) @name @item)
|
||||
(rest_pattern (identifier) @name @item)
|
||||
]))))
|
||||
|
||||
; Top-level object destructuring
|
||||
(program
|
||||
(lexical_declaration
|
||||
["let" "const"] @context
|
||||
(variable_declarator
|
||||
name: (object_pattern
|
||||
[(shorthand_property_identifier_pattern) @name @item
|
||||
(pair_pattern
|
||||
value: (identifier) @name @item)
|
||||
(pair_pattern
|
||||
value: (assignment_pattern left: (identifier) @name @item))
|
||||
(rest_pattern (identifier) @name @item)]))))
|
||||
|
||||
(class_declaration
|
||||
"class" @context
|
||||
@@ -56,21 +102,38 @@
|
||||
"class" @context
|
||||
name: (_) @name) @item
|
||||
|
||||
(method_definition
|
||||
[
|
||||
"get"
|
||||
"set"
|
||||
"async"
|
||||
"*"
|
||||
"readonly"
|
||||
"static"
|
||||
(override_modifier)
|
||||
(accessibility_modifier)
|
||||
]* @context
|
||||
name: (_) @name
|
||||
parameters: (formal_parameters
|
||||
"(" @context
|
||||
")" @context)) @item
|
||||
; Method definitions in classes (not in object literals)
|
||||
(class_body
|
||||
(method_definition
|
||||
[
|
||||
"get"
|
||||
"set"
|
||||
"async"
|
||||
"*"
|
||||
"readonly"
|
||||
"static"
|
||||
(override_modifier)
|
||||
(accessibility_modifier)
|
||||
]* @context
|
||||
name: (_) @name
|
||||
parameters: (formal_parameters
|
||||
"(" @context
|
||||
")" @context)) @item)
|
||||
|
||||
; Object literal methods
|
||||
(variable_declarator
|
||||
value: (object
|
||||
(method_definition
|
||||
[
|
||||
"get"
|
||||
"set"
|
||||
"async"
|
||||
"*"
|
||||
]* @context
|
||||
name: (_) @name
|
||||
parameters: (formal_parameters
|
||||
"(" @context
|
||||
")" @context)) @item))
|
||||
|
||||
(public_field_definition
|
||||
[
|
||||
@@ -124,4 +187,44 @@
|
||||
)
|
||||
) @item
|
||||
|
||||
; Object properties
|
||||
(pair
|
||||
key: [
|
||||
(property_identifier) @name
|
||||
(string (string_fragment) @name)
|
||||
(number) @name
|
||||
(computed_property_name) @name
|
||||
]) @item
|
||||
|
||||
|
||||
; Nested variables in function bodies
|
||||
(statement_block
|
||||
(lexical_declaration
|
||||
["let" "const"] @context
|
||||
(variable_declarator
|
||||
name: (identifier) @name) @item))
|
||||
|
||||
; Nested array destructuring in functions
|
||||
(statement_block
|
||||
(lexical_declaration
|
||||
["let" "const"] @context
|
||||
(variable_declarator
|
||||
name: (array_pattern
|
||||
[
|
||||
(identifier) @name @item
|
||||
(assignment_pattern left: (identifier) @name @item)
|
||||
(rest_pattern (identifier) @name @item)
|
||||
]))))
|
||||
|
||||
; Nested object destructuring in functions
|
||||
(statement_block
|
||||
(lexical_declaration
|
||||
["let" "const"] @context
|
||||
(variable_declarator
|
||||
name: (object_pattern
|
||||
[(shorthand_property_identifier_pattern) @name @item
|
||||
(pair_pattern value: (identifier) @name @item)
|
||||
(pair_pattern value: (assignment_pattern left: (identifier) @name @item))
|
||||
(rest_pattern (identifier) @name @item)]))))
|
||||
|
||||
(comment) @annotation
|
||||
|
||||
+155
-143
@@ -1103,12 +1103,14 @@ mod tests {
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_outline(cx: &mut TestAppContext) {
|
||||
let language = crate::language(
|
||||
"typescript",
|
||||
tree_sitter_typescript::LANGUAGE_TYPESCRIPT.into(),
|
||||
);
|
||||
|
||||
let text = r#"
|
||||
for language in [
|
||||
crate::language(
|
||||
"typescript",
|
||||
tree_sitter_typescript::LANGUAGE_TYPESCRIPT.into(),
|
||||
),
|
||||
crate::language("tsx", tree_sitter_typescript::LANGUAGE_TSX.into()),
|
||||
] {
|
||||
let text = r#"
|
||||
function a() {
|
||||
// local variables are included
|
||||
let a1 = 1;
|
||||
@@ -1121,35 +1123,38 @@ mod tests {
|
||||
// exported variables are included
|
||||
export const d = e;
|
||||
"#
|
||||
.unindent();
|
||||
.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));
|
||||
assert_eq!(
|
||||
outline
|
||||
.items
|
||||
.iter()
|
||||
.map(|item| (item.text.as_str(), item.depth))
|
||||
.collect::<Vec<_>>(),
|
||||
&[
|
||||
("function a()", 0),
|
||||
("let a1", 1),
|
||||
("async function a2()", 1),
|
||||
("let b", 0),
|
||||
("function getB()", 0),
|
||||
("const d", 0),
|
||||
]
|
||||
);
|
||||
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));
|
||||
assert_eq!(
|
||||
outline
|
||||
.items
|
||||
.iter()
|
||||
.map(|item| (item.text.as_str(), item.depth))
|
||||
.collect::<Vec<_>>(),
|
||||
&[
|
||||
("function a()", 0),
|
||||
("let a1", 1),
|
||||
("async function a2()", 1),
|
||||
("let b", 0),
|
||||
("function getB()", 0),
|
||||
("const d", 0),
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_outline_with_destructuring(cx: &mut TestAppContext) {
|
||||
let language = crate::language(
|
||||
"typescript",
|
||||
tree_sitter_typescript::LANGUAGE_TYPESCRIPT.into(),
|
||||
);
|
||||
|
||||
let text = r#"
|
||||
for language in [
|
||||
crate::language(
|
||||
"typescript",
|
||||
tree_sitter_typescript::LANGUAGE_TYPESCRIPT.into(),
|
||||
),
|
||||
crate::language("tsx", tree_sitter_typescript::LANGUAGE_TSX.into()),
|
||||
] {
|
||||
let text = r#"
|
||||
// Top-level destructuring
|
||||
const { a1, a2 } = a;
|
||||
const [b1, b2] = b;
|
||||
@@ -1177,55 +1182,58 @@ mod tests {
|
||||
}
|
||||
}
|
||||
"#
|
||||
.unindent();
|
||||
.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));
|
||||
assert_eq!(
|
||||
outline
|
||||
.items
|
||||
.iter()
|
||||
.map(|item| (item.text.as_str(), item.depth))
|
||||
.collect::<Vec<_>>(),
|
||||
&[
|
||||
("const a1", 0),
|
||||
("const a2", 0),
|
||||
("const b1", 0),
|
||||
("const b2", 0),
|
||||
("const c1", 0),
|
||||
("const c2", 0),
|
||||
("const rest1", 0),
|
||||
("const d1", 0),
|
||||
("const e1", 0),
|
||||
("const h1", 0),
|
||||
("const rest2", 0),
|
||||
("function processData()", 0),
|
||||
("const c1", 1),
|
||||
("const c2", 1),
|
||||
("const d1", 1),
|
||||
("const d2", 1),
|
||||
("const d3", 1),
|
||||
("const g1", 1),
|
||||
("const x", 1),
|
||||
("const y", 1),
|
||||
("class DataHandler", 0),
|
||||
("method()", 1),
|
||||
("const a1", 2),
|
||||
("const a2", 2),
|
||||
("const b1", 2),
|
||||
("const b2", 2),
|
||||
]
|
||||
);
|
||||
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));
|
||||
assert_eq!(
|
||||
outline
|
||||
.items
|
||||
.iter()
|
||||
.map(|item| (item.text.as_str(), item.depth))
|
||||
.collect::<Vec<_>>(),
|
||||
&[
|
||||
("const a1", 0),
|
||||
("const a2", 0),
|
||||
("const b1", 0),
|
||||
("const b2", 0),
|
||||
("const c1", 0),
|
||||
("const c2", 0),
|
||||
("const rest1", 0),
|
||||
("const d1", 0),
|
||||
("const e1", 0),
|
||||
("const h1", 0),
|
||||
("const rest2", 0),
|
||||
("function processData()", 0),
|
||||
("const c1", 1),
|
||||
("const c2", 1),
|
||||
("const d1", 1),
|
||||
("const d2", 1),
|
||||
("const d3", 1),
|
||||
("const g1", 1),
|
||||
("const x", 1),
|
||||
("const y", 1),
|
||||
("class DataHandler", 0),
|
||||
("method()", 1),
|
||||
("const a1", 2),
|
||||
("const a2", 2),
|
||||
("const b1", 2),
|
||||
("const b2", 2),
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_outline_with_object_properties(cx: &mut TestAppContext) {
|
||||
let language = crate::language(
|
||||
"typescript",
|
||||
tree_sitter_typescript::LANGUAGE_TYPESCRIPT.into(),
|
||||
);
|
||||
|
||||
let text = r#"
|
||||
for language in [
|
||||
crate::language(
|
||||
"typescript",
|
||||
tree_sitter_typescript::LANGUAGE_TYPESCRIPT.into(),
|
||||
),
|
||||
crate::language("tsx", tree_sitter_typescript::LANGUAGE_TSX.into()),
|
||||
] {
|
||||
let text = r#"
|
||||
// Object with function properties
|
||||
const o = { m() {}, async n() {}, g: function* () {}, h: () => {}, k: function () {} };
|
||||
|
||||
@@ -1246,47 +1254,50 @@ mod tests {
|
||||
return local;
|
||||
}
|
||||
"#
|
||||
.unindent();
|
||||
.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));
|
||||
assert_eq!(
|
||||
outline
|
||||
.items
|
||||
.iter()
|
||||
.map(|item| (item.text.as_str(), item.depth))
|
||||
.collect::<Vec<_>>(),
|
||||
&[
|
||||
("const o", 0),
|
||||
("m()", 1),
|
||||
("async n()", 1),
|
||||
("g", 1),
|
||||
("h", 1),
|
||||
("k", 1),
|
||||
("const p", 0),
|
||||
("p1", 1),
|
||||
("p2", 1),
|
||||
("p3", 1),
|
||||
("const q", 0),
|
||||
("r", 1),
|
||||
("s", 2),
|
||||
("t", 1),
|
||||
("function getData()", 0),
|
||||
("const local", 1),
|
||||
("x", 2),
|
||||
("y", 2),
|
||||
]
|
||||
);
|
||||
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));
|
||||
assert_eq!(
|
||||
outline
|
||||
.items
|
||||
.iter()
|
||||
.map(|item| (item.text.as_str(), item.depth))
|
||||
.collect::<Vec<_>>(),
|
||||
&[
|
||||
("const o", 0),
|
||||
("m()", 1),
|
||||
("async n()", 1),
|
||||
("g", 1),
|
||||
("h", 1),
|
||||
("k", 1),
|
||||
("const p", 0),
|
||||
("p1", 1),
|
||||
("p2", 1),
|
||||
("p3", 1),
|
||||
("const q", 0),
|
||||
("r", 1),
|
||||
("s", 2),
|
||||
("t", 1),
|
||||
("function getData()", 0),
|
||||
("const local", 1),
|
||||
("x", 2),
|
||||
("y", 2),
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_outline_with_computed_property_names(cx: &mut TestAppContext) {
|
||||
let language = crate::language(
|
||||
"typescript",
|
||||
tree_sitter_typescript::LANGUAGE_TYPESCRIPT.into(),
|
||||
);
|
||||
|
||||
let text = r#"
|
||||
for language in [
|
||||
crate::language(
|
||||
"typescript",
|
||||
tree_sitter_typescript::LANGUAGE_TYPESCRIPT.into(),
|
||||
),
|
||||
crate::language("tsx", tree_sitter_typescript::LANGUAGE_TSX.into()),
|
||||
] {
|
||||
let text = r#"
|
||||
// Symbols as object keys
|
||||
const sym = Symbol("test");
|
||||
const obj1 = {
|
||||
@@ -1323,40 +1334,41 @@ mod tests {
|
||||
}
|
||||
};
|
||||
"#
|
||||
.unindent();
|
||||
.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));
|
||||
assert_eq!(
|
||||
outline
|
||||
.items
|
||||
.iter()
|
||||
.map(|item| (item.text.as_str(), item.depth))
|
||||
.collect::<Vec<_>>(),
|
||||
&[
|
||||
("const sym", 0),
|
||||
("const obj1", 0),
|
||||
("[sym]", 1),
|
||||
("[Symbol(\"inline\")]", 1),
|
||||
("normalKey", 1),
|
||||
("enum Color", 0),
|
||||
("const obj2", 0),
|
||||
("[Color.Red]", 1),
|
||||
("[Color.Blue]", 1),
|
||||
("regularProp", 1),
|
||||
("const key", 0),
|
||||
("const obj3", 0),
|
||||
("[key]", 1),
|
||||
("[\"string\" + \"concat\"]", 1),
|
||||
("[1 + 1]", 1),
|
||||
("static", 1),
|
||||
("const obj4", 0),
|
||||
("[sym]", 1),
|
||||
("nested", 2),
|
||||
("regular", 1),
|
||||
("[key]", 2),
|
||||
]
|
||||
);
|
||||
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));
|
||||
assert_eq!(
|
||||
outline
|
||||
.items
|
||||
.iter()
|
||||
.map(|item| (item.text.as_str(), item.depth))
|
||||
.collect::<Vec<_>>(),
|
||||
&[
|
||||
("const sym", 0),
|
||||
("const obj1", 0),
|
||||
("[sym]", 1),
|
||||
("[Symbol(\"inline\")]", 1),
|
||||
("normalKey", 1),
|
||||
("enum Color", 0),
|
||||
("const obj2", 0),
|
||||
("[Color.Red]", 1),
|
||||
("[Color.Blue]", 1),
|
||||
("regularProp", 1),
|
||||
("const key", 0),
|
||||
("const obj3", 0),
|
||||
("[key]", 1),
|
||||
("[\"string\" + \"concat\"]", 1),
|
||||
("[1 + 1]", 1),
|
||||
("static", 1),
|
||||
("const obj4", 0),
|
||||
("[sym]", 1),
|
||||
("nested", 2),
|
||||
("regular", 1),
|
||||
("[key]", 2),
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
|
||||
Reference in New Issue
Block a user