Skip to content

Commit 7222963

Browse files
Tweak how we populate NavBarItems.
Now we will always place child items of a node in the right bar, even if we're also placing it on the 'top level nodes' list on the left. This makes things clearer for users by making it clear that any time you have a node selected on the left, you can always find its children on the right. And, it still preserves the behavior we want where the left list acts as a high level 'table of contents' for the file.
1 parent 432fff1 commit 7222963

File tree

5 files changed

+57
-34
lines changed

5 files changed

+57
-34
lines changed

src/compiler/parser.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3639,7 +3639,7 @@ module ts {
36393639
}
36403640
return finishNode(node);
36413641
}
3642-
3642+
36433643
function parseAndCheckEnumDeclaration(pos: number, flags: NodeFlags): EnumDeclaration {
36443644
function isIntegerLiteral(expression: Expression): boolean {
36453645
function isInteger(literalExpression: LiteralExpression): boolean {

src/services/navigationBar.ts

Lines changed: 53 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ module ts.NavigationBar {
2222
// to say it only has a single layer of depth
2323
do {
2424
current = current.parent;
25-
} while (current.kind === SyntaxKind.ModuleDeclaration);
25+
}
26+
while (current.kind === SyntaxKind.ModuleDeclaration);
2627

2728
// fall through
2829
case SyntaxKind.ClassDeclaration:
@@ -37,22 +38,27 @@ module ts.NavigationBar {
3738

3839
return indent;
3940
}
40-
41+
4142
function getChildNodes(nodes: Node[]): Node[] {
4243
var childNodes: Node[] = [];
4344

4445
for (var i = 0, n = nodes.length; i < n; i++) {
4546
var node = nodes[i];
4647

47-
if (node.kind === SyntaxKind.FunctionDeclaration) {
48+
if (node.kind === SyntaxKind.ClassDeclaration ||
49+
node.kind === SyntaxKind.EnumDeclaration ||
50+
node.kind === SyntaxKind.InterfaceDeclaration ||
51+
node.kind === SyntaxKind.ModuleDeclaration ||
52+
node.kind === SyntaxKind.FunctionDeclaration) {
53+
4854
childNodes.push(node);
4955
}
5056
else if (node.kind === SyntaxKind.VariableStatement) {
5157
childNodes.push.apply(childNodes, (<VariableStatement>node).declarations);
5258
}
5359
}
5460

55-
return childNodes;
61+
return sortNodes(childNodes);
5662
}
5763

5864
function getTopLevelNodes(node: SourceFile): Node[] {
@@ -63,8 +69,27 @@ module ts.NavigationBar {
6369

6470
return topLevelNodes;
6571
}
66-
72+
73+
function sortNodes(nodes: Node[]): Node[] {
74+
return nodes.slice(0).sort((n1: Declaration, n2: Declaration) => {
75+
if (n1.name && n2.name) {
76+
return n1.name.text.localeCompare(n2.name.text);
77+
}
78+
else if (n1.name) {
79+
return 1;
80+
}
81+
else if (n2.name) {
82+
-1;
83+
}
84+
else {
85+
return n1.kind - n2.kind;
86+
}
87+
});
88+
}
89+
6790
function addTopLevelNodes(nodes: Node[], topLevelNodes: Node[]): void {
91+
nodes = sortNodes(nodes);
92+
6893
for (var i = 0, n = nodes.length; i < n; i++) {
6994
var node = nodes[i];
7095
switch (node.kind) {
@@ -97,9 +122,10 @@ module ts.NavigationBar {
97122
return functionDeclaration.kind === SyntaxKind.FunctionDeclaration &&
98123
functionDeclaration.body &&
99124
functionDeclaration.body.kind === SyntaxKind.FunctionBlock &&
100-
forEach((<Block>functionDeclaration.body).statements, s => s.kind === SyntaxKind.FunctionDeclaration);
125+
forEach((<Block>functionDeclaration.body).statements,
126+
s => s.kind === SyntaxKind.FunctionDeclaration && !isEmpty((<FunctionDeclaration>s).name.text));
101127
}
102-
128+
103129
function getItemsWorker(nodes: Node[], createItem: (n: Node) => ts.NavigationBarItem): ts.NavigationBarItem[] {
104130
var items: ts.NavigationBarItem[] = [];
105131

@@ -161,31 +187,26 @@ module ts.NavigationBar {
161187
function createChildItem(node: Node): ts.NavigationBarItem {
162188
switch (node.kind) {
163189
case SyntaxKind.Parameter:
164-
var parameter = <ParameterDeclaration>node;
165190
if ((node.flags & NodeFlags.Modifier) === 0) {
166191
return undefined;
167192
}
168193

169-
return createItem(node, getTextOfNode(parameter.name), ts.ScriptElementKind.memberVariableElement);
194+
return createItem(node, getTextOfNode((<ParameterDeclaration>node).name), ts.ScriptElementKind.memberVariableElement);
170195

171196
case SyntaxKind.Method:
172-
var method = <MethodDeclaration>node;
173-
return createItem(node, getTextOfNode(method.name), ts.ScriptElementKind.memberFunctionElement);
197+
return createItem(node, getTextOfNode((<MethodDeclaration>node).name), ts.ScriptElementKind.memberFunctionElement);
174198

175199
case SyntaxKind.GetAccessor:
176-
var getAccessor = <AccessorDeclaration>node;
177-
return createItem(node, getTextOfNode(getAccessor.name), ts.ScriptElementKind.memberGetAccessorElement);
200+
return createItem(node, getTextOfNode((<AccessorDeclaration>node).name), ts.ScriptElementKind.memberGetAccessorElement);
178201

179202
case SyntaxKind.SetAccessor:
180-
var setAccessor = <AccessorDeclaration>node;
181-
return createItem(node, getTextOfNode(setAccessor.name), ts.ScriptElementKind.memberSetAccessorElement);
203+
return createItem(node, getTextOfNode((<AccessorDeclaration>node).name), ts.ScriptElementKind.memberSetAccessorElement);
182204

183205
case SyntaxKind.IndexSignature:
184206
return createItem(node, "[]", ts.ScriptElementKind.indexSignatureElement);
185207

186208
case SyntaxKind.EnumMember:
187-
var enumMember = <EnumMember>node;
188-
return createItem(node, getTextOfNode(enumMember.name), ts.ScriptElementKind.memberVariableElement);
209+
return createItem(node, getTextOfNode((<EnumMember>node).name), ts.ScriptElementKind.memberVariableElement);
189210

190211
case SyntaxKind.CallSignature:
191212
return createItem(node, "()", ts.ScriptElementKind.callSignatureElement);
@@ -194,19 +215,13 @@ module ts.NavigationBar {
194215
return createItem(node, "new()", ts.ScriptElementKind.constructSignatureElement);
195216

196217
case SyntaxKind.Property:
197-
var property = <PropertyDeclaration>node;
198-
return createItem(node, getTextOfNode(property.name), ts.ScriptElementKind.memberVariableElement);
218+
return createItem(node, getTextOfNode((<PropertyDeclaration>node).name), ts.ScriptElementKind.memberVariableElement);
199219

200220
case SyntaxKind.FunctionDeclaration:
201-
var functionDeclaration = <FunctionDeclaration>node;
202-
if (!isTopLevelFunctionDeclaration(functionDeclaration)) {
203-
return createItem(node, getTextOfNode(functionDeclaration.name), ts.ScriptElementKind.functionElement);
204-
}
205-
break;
221+
return createItem(node, getTextOfNode((<FunctionDeclaration>node).name), ts.ScriptElementKind.functionElement);
206222

207223
case SyntaxKind.VariableDeclaration:
208-
var variableDeclaration = <VariableDeclaration>node;
209-
return createItem(node, getTextOfNode(variableDeclaration.name), ts.ScriptElementKind.variableElement);
224+
return createItem(node, getTextOfNode((<VariableDeclaration>node).name), ts.ScriptElementKind.variableElement);
210225

211226
case SyntaxKind.Constructor:
212227
return createItem(node, "constructor", ts.ScriptElementKind.constructorImplementationElement);
@@ -219,7 +234,15 @@ module ts.NavigationBar {
219234
}
220235
}
221236

237+
function isEmpty(text: string) {
238+
return !text || text.trim() === "";
239+
}
240+
222241
function getNavigationBarItem(text: string, kind: string, kindModifiers: string, spans: TypeScript.TextSpan[], childItems: ts.NavigationBarItem[] = [], indent: number = 0): ts.NavigationBarItem {
242+
if (isEmpty(text)) {
243+
return undefined;
244+
}
245+
223246
return {
224247
text: text,
225248
kind: kind,
@@ -290,7 +313,7 @@ module ts.NavigationBar {
290313

291314
function createFunctionItem(node: FunctionDeclaration) {
292315
if (node.name && node.body && node.body.kind === SyntaxKind.FunctionBlock) {
293-
var childItems = getItemsWorker((<Block>node.body).statements, createChildItem);
316+
var childItems = getItemsWorker(getChildNodes((<Block>node.body).statements), createChildItem);
294317

295318
return getNavigationBarItem(node.name.text,
296319
ts.ScriptElementKind.functionElement,
@@ -335,7 +358,7 @@ module ts.NavigationBar {
335358
? constructor.parameters.concat(node.members)
336359
: node.members;
337360

338-
var childItems = getItemsWorker(nodes, createChildItem);
361+
var childItems = getItemsWorker(sortNodes(nodes), createChildItem);
339362
}
340363

341364
return getNavigationBarItem(
@@ -348,7 +371,7 @@ module ts.NavigationBar {
348371
}
349372

350373
function createEnumItem(node: EnumDeclaration): ts.NavigationBarItem {
351-
var childItems = getItemsWorker(node.members, createChildItem);
374+
var childItems = getItemsWorker(sortNodes(node.members), createChildItem);
352375
return getNavigationBarItem(
353376
node.name.text,
354377
ts.ScriptElementKind.enumElement,
@@ -359,7 +382,7 @@ module ts.NavigationBar {
359382
}
360383

361384
function createIterfaceItem(node: InterfaceDeclaration): ts.NavigationBarItem {
362-
var childItems = getItemsWorker(node.members, createChildItem);
385+
var childItems = getItemsWorker(sortNodes(node.members), createChildItem);
363386
return getNavigationBarItem(
364387
node.name.text,
365388
ts.ScriptElementKind.interfaceElement,

tests/cases/fourslash/scriptLexicalStructureFunctions.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,4 @@ test.markers().forEach((marker) => {
2020
verify.getScriptLexicalStructureListContains(marker.data.itemName, marker.data.kind, marker.fileName, marker.data.parentName);
2121
});
2222

23-
verify.getScriptLexicalStructureListCount(5); // 4 functions + global
23+
verify.getScriptLexicalStructureListCount(9); // 4 functions + global. Note: there are 9 because of the functions show up at the top level and as child items.

tests/cases/fourslash/scriptLexicalStructureFunctionsBroken.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,4 @@ test.markers().forEach((marker) => {
99
verify.getScriptLexicalStructureListContains(marker.data.itemName, marker.data.kind, marker.fileName, marker.data.parentName);
1010
});
1111

12-
verify.getScriptLexicalStructureListCount(1); // 1 function - no global since the inner function thinks it has a declaration.
12+
verify.getScriptLexicalStructureListCount(3); // <global>, 'f' in the top level list, and 'f' as a child of '<global>'

tests/cases/fourslash/scriptLexicalStructureFunctionsBroken2.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,4 @@ test.markers().forEach((marker) => {
1010
verify.getScriptLexicalStructureListContains(marker.data.itemName, marker.data.kind, marker.fileName, marker.data.parentName);
1111
});
1212

13-
verify.getScriptLexicalStructureListCount(1); // 1 function with no global - the broken declaration adds nothing for us at the global scope.
13+
verify.getScriptLexicalStructureListCount(3); // <global> and 'f' as a child of 'global' and as as top level function.

0 commit comments

Comments
 (0)