Skip to content

Commit fd6fbdf

Browse files
authored
Show more items in the navbar (#33040)
* show more items in navbar * fixed missing node kind for property assignments * updated navBarNestedCommonJsExports test * updated navigationBarMerging_grandchildren test * updated navigationBarItemsFunctions test * updated navigationBarAnonymousClassAndFunctionExpressions test * updated navigationBarFunctionIndirectlyInVariableDeclaration test * updated navigationBarInitializerSpans test * updated navigationBarItemsPropertiesDefinedInConstructors test * updated tests * change nav icon for properties with function-like initializers * add test case for binding element with function-like initializer * add navigationBarNestedObjectLiterals test * add navigationBarFunctionLikePropertyAssignments test * made some silly names less silly (?) * added SpreadAssignments and ShorthandPropertyAssignments * new wording for primary menu items
1 parent f9cc374 commit fd6fbdf

16 files changed

+662
-64
lines changed

src/services/navigationBar.ts

Lines changed: 38 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ namespace ts.NavigationBar {
5656
curCancellationToken = cancellationToken;
5757
curSourceFile = sourceFile;
5858
try {
59-
return map(topLevelItems(rootNavigationBarNode(sourceFile)), convertToTopLevelItem);
59+
return map(primaryNavBarMenuItems(rootNavigationBarNode(sourceFile)), convertToPrimaryNavBarMenuItem);
6060
}
6161
finally {
6262
reset();
@@ -111,8 +111,8 @@ namespace ts.NavigationBar {
111111
return root;
112112
}
113113

114-
function addLeafNode(node: Node): void {
115-
pushChild(parent, emptyNavigationBarNode(node));
114+
function addLeafNode(node: Node, name?: DeclarationName): void {
115+
pushChild(parent, emptyNavigationBarNode(node, name));
116116
}
117117

118118
function emptyNavigationBarNode(node: Node, name?: DeclarationName): NavigationBarNode {
@@ -243,23 +243,26 @@ namespace ts.NavigationBar {
243243
}
244244
break;
245245

246+
case SyntaxKind.ShorthandPropertyAssignment:
247+
addNodeWithRecursiveChild(node, (<ShorthandPropertyAssignment>node).name);
248+
break;
249+
case SyntaxKind.SpreadAssignment:
250+
const { expression } = <SpreadAssignment>node;
251+
// Use the expression as the name of the SpreadAssignment, otherwise show as <unknown>.
252+
isIdentifier(expression) ? addLeafNode(node, expression) : addLeafNode(node);
253+
break;
246254
case SyntaxKind.BindingElement:
255+
case SyntaxKind.PropertyAssignment:
247256
case SyntaxKind.VariableDeclaration:
248-
const { name, initializer } = <VariableDeclaration | BindingElement>node;
257+
const { name, initializer } = <VariableDeclaration | PropertyAssignment | BindingElement>node;
249258
if (isBindingPattern(name)) {
250259
addChildrenRecursively(name);
251260
}
252261
else if (initializer && isFunctionOrClassExpression(initializer)) {
253-
if (initializer.name) {
254-
// Don't add a node for the VariableDeclaration, just for the initializer.
255-
addChildrenRecursively(initializer);
256-
}
257-
else {
258-
// Add a node for the VariableDeclaration, but not for the initializer.
259-
startNode(node);
260-
forEachChild(initializer, addChildrenRecursively);
261-
endNode();
262-
}
262+
// Add a node for the VariableDeclaration, but not for the initializer.
263+
startNode(node);
264+
forEachChild(initializer, addChildrenRecursively);
265+
endNode();
263266
}
264267
else {
265268
addNodeWithRecursiveChild(node, initializer);
@@ -699,12 +702,15 @@ namespace ts.NavigationBar {
699702
}
700703
}
701704

702-
/** Flattens the NavNode tree to a list, keeping only the top-level items. */
703-
function topLevelItems(root: NavigationBarNode): NavigationBarNode[] {
704-
const topLevel: NavigationBarNode[] = [];
705+
/** Flattens the NavNode tree to a list of items to appear in the primary navbar menu. */
706+
function primaryNavBarMenuItems(root: NavigationBarNode): NavigationBarNode[] {
707+
// The primary (middle) navbar menu displays the general code navigation hierarchy, similar to the navtree.
708+
// The secondary (right) navbar menu displays the child items of whichever primary item is selected.
709+
// Some less interesting items without their own child navigation items (e.g. a local variable declaration) only show up in the secondary menu.
710+
const primaryNavBarMenuItems: NavigationBarNode[] = [];
705711
function recur(item: NavigationBarNode) {
706-
if (isTopLevel(item)) {
707-
topLevel.push(item);
712+
if (shouldAppearInPrimaryNavBarMenu(item)) {
713+
primaryNavBarMenuItems.push(item);
708714
if (item.children) {
709715
for (const child of item.children) {
710716
recur(child);
@@ -713,9 +719,16 @@ namespace ts.NavigationBar {
713719
}
714720
}
715721
recur(root);
716-
return topLevel;
722+
return primaryNavBarMenuItems;
717723

718-
function isTopLevel(item: NavigationBarNode): boolean {
724+
/** Determines if a node should appear in the primary navbar menu. */
725+
function shouldAppearInPrimaryNavBarMenu(item: NavigationBarNode): boolean {
726+
// Items with children should always appear in the primary navbar menu.
727+
if (item.children) {
728+
return true;
729+
}
730+
731+
// Some nodes are otherwise important enough to always include in the primary navigation menu.
719732
switch (navigationBarNodeKind(item)) {
720733
case SyntaxKind.ClassDeclaration:
721734
case SyntaxKind.ClassExpression:
@@ -728,13 +741,6 @@ namespace ts.NavigationBar {
728741
case SyntaxKind.JSDocCallbackTag:
729742
return true;
730743

731-
case SyntaxKind.Constructor:
732-
case SyntaxKind.MethodDeclaration:
733-
case SyntaxKind.GetAccessor:
734-
case SyntaxKind.SetAccessor:
735-
case SyntaxKind.VariableDeclaration:
736-
return hasSomeImportantChild(item);
737-
738744
case SyntaxKind.ArrowFunction:
739745
case SyntaxKind.FunctionDeclaration:
740746
case SyntaxKind.FunctionExpression:
@@ -755,15 +761,9 @@ namespace ts.NavigationBar {
755761
case SyntaxKind.Constructor:
756762
return true;
757763
default:
758-
return hasSomeImportantChild(item);
764+
return false;
759765
}
760766
}
761-
function hasSomeImportantChild(item: NavigationBarNode): boolean {
762-
return some(item.children, child => {
763-
const childKind = navigationBarNodeKind(child);
764-
return childKind !== SyntaxKind.VariableDeclaration && childKind !== SyntaxKind.BindingElement;
765-
});
766-
}
767767
}
768768
}
769769

@@ -778,19 +778,19 @@ namespace ts.NavigationBar {
778778
};
779779
}
780780

781-
function convertToTopLevelItem(n: NavigationBarNode): NavigationBarItem {
781+
function convertToPrimaryNavBarMenuItem(n: NavigationBarNode): NavigationBarItem {
782782
return {
783783
text: getItemName(n.node, n.name),
784784
kind: getNodeKind(n.node),
785785
kindModifiers: getModifiers(n.node),
786786
spans: getSpans(n),
787-
childItems: map(n.children, convertToChildItem) || emptyChildItemArray,
787+
childItems: map(n.children, convertToSecondaryNavBarMenuItem) || emptyChildItemArray,
788788
indent: n.indent,
789789
bolded: false,
790790
grayed: false
791791
};
792792

793-
function convertToChildItem(n: NavigationBarNode): NavigationBarItem {
793+
function convertToSecondaryNavBarMenuItem(n: NavigationBarNode): NavigationBarItem {
794794
return {
795795
text: getItemName(n.node, n.name),
796796
kind: getNodeKind(n.node),

src/services/utilities.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,8 +353,13 @@ namespace ts {
353353
case SyntaxKind.MethodDeclaration:
354354
case SyntaxKind.MethodSignature:
355355
return ScriptElementKind.memberFunctionElement;
356+
case SyntaxKind.PropertyAssignment:
357+
const {initializer} = node as PropertyAssignment;
358+
return isFunctionLike(initializer) ? ScriptElementKind.memberFunctionElement : ScriptElementKind.memberVariableElement;
356359
case SyntaxKind.PropertyDeclaration:
357360
case SyntaxKind.PropertySignature:
361+
case SyntaxKind.ShorthandPropertyAssignment:
362+
case SyntaxKind.SpreadAssignment:
358363
return ScriptElementKind.memberVariableElement;
359364
case SyntaxKind.IndexSignature: return ScriptElementKind.indexSignatureElement;
360365
case SyntaxKind.ConstructSignature: return ScriptElementKind.constructSignatureElement;

tests/cases/fourslash/navbarNestedCommonJsExports.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,23 @@ verify.navigationBar([
2929
kind: "script",
3030
childItems: [
3131
{ text: "a", kind: "const" },
32+
]
33+
},
34+
{
35+
text: "a",
36+
kind: "const",
37+
childItems: [
38+
{ text: "b", kind: "const"},
3239
],
40+
indent: 1,
3341
},
42+
{
43+
text: "b",
44+
kind: "const",
45+
childItems: [
46+
{ text: "c", kind: "const" },
47+
],
48+
indent: 2,
49+
}
3450
]);
3551

tests/cases/fourslash/navigationBarAnonymousClassAndFunctionExpressions.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ verify.navigationTree({
6262
"childItems": [
6363
{
6464
"text": "foo",
65-
"kind": "function"
65+
"kind": "method"
6666
}
6767
]
6868
}
@@ -185,7 +185,7 @@ verify.navigationBar([
185185
"childItems": [
186186
{
187187
"text": "foo",
188-
"kind": "function"
188+
"kind": "method"
189189
}
190190
],
191191
"indent": 2
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/// <reference path='fourslash.ts'/>
2+
////'use strict'
3+
////const a = {
4+
//// ...b,
5+
//// c,
6+
//// d: 0
7+
////};
8+
9+
verify.navigationTree({
10+
text: "<global>",
11+
kind: "script",
12+
childItems: [
13+
{
14+
text: "a",
15+
kind: "const",
16+
childItems: [
17+
{
18+
text: "b",
19+
kind: "property",
20+
},
21+
{
22+
text: "c",
23+
kind: "property"
24+
},
25+
{
26+
text: "d",
27+
kind: "property"
28+
}
29+
]
30+
}
31+
]
32+
});
33+
34+
verify.navigationBar([
35+
{
36+
text: "<global>",
37+
kind: "script",
38+
childItems: [
39+
{
40+
text: "a",
41+
kind: "const"
42+
}
43+
]
44+
},
45+
{
46+
text: "a",
47+
kind: "const",
48+
childItems: [
49+
{
50+
text: "b",
51+
kind: "property",
52+
},
53+
{
54+
text: "c",
55+
kind: "property"
56+
},
57+
{
58+
text: "d",
59+
kind: "property"
60+
}
61+
],
62+
indent: 1
63+
}
64+
]);

tests/cases/fourslash/navigationBarFunctionIndirectlyInVariableDeclaration.ts

Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
11
/// <reference path="fourslash.ts"/>
22

33
////var a = {
4-
//// propA: function() {}
4+
//// propA: function() {
5+
//// var c;
6+
//// }
57
////};
68
////var b;
79
////b = {
8-
//// propB: function() {}
10+
//// propB: function() {
11+
//// // function must not have an empty body to appear top level
12+
//// var d;
13+
//// }
914
////};
1015

1116
verify.navigationTree({
@@ -18,7 +23,13 @@ verify.navigationTree({
1823
"childItems": [
1924
{
2025
"text": "propA",
21-
"kind": "function"
26+
"kind": "method",
27+
"childItems": [
28+
{
29+
"text": "c",
30+
"kind": "var"
31+
}
32+
]
2233
}
2334
]
2435
},
@@ -28,7 +39,13 @@ verify.navigationTree({
2839
},
2940
{
3041
"text": "propB",
31-
"kind": "function"
42+
"kind": "method",
43+
"childItems": [
44+
{
45+
"text": "d",
46+
"kind": "var"
47+
}
48+
]
3249
}
3350
]
3451
});
@@ -48,7 +65,7 @@ verify.navigationBar([
4865
},
4966
{
5067
"text": "propB",
51-
"kind": "function"
68+
"kind": "method"
5269
}
5370
]
5471
},
@@ -58,14 +75,31 @@ verify.navigationBar([
5875
"childItems": [
5976
{
6077
"text": "propA",
61-
"kind": "function"
78+
"kind": "method"
6279
}
6380
],
6481
"indent": 1
6582
},
83+
{
84+
"text": "propA",
85+
"kind": "method",
86+
"childItems": [
87+
{
88+
"text": "c",
89+
"kind": "var"
90+
}
91+
],
92+
"indent": 2
93+
},
6694
{
6795
"text": "propB",
68-
"kind": "function",
96+
"kind": "method",
97+
"childItems": [
98+
{
99+
"text": "d",
100+
"kind": "var"
101+
}
102+
],
69103
"indent": 1
70104
}
71105
]);

0 commit comments

Comments
 (0)