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
This commit is contained in:
Jesse Trinity
2019-09-11 15:54:27 -07:00
committed by GitHub
parent f9cc374d21
commit fd6fbdf7fe
16 changed files with 664 additions and 66 deletions

View File

@@ -56,7 +56,7 @@ namespace ts.NavigationBar {
curCancellationToken = cancellationToken;
curSourceFile = sourceFile;
try {
return map(topLevelItems(rootNavigationBarNode(sourceFile)), convertToTopLevelItem);
return map(primaryNavBarMenuItems(rootNavigationBarNode(sourceFile)), convertToPrimaryNavBarMenuItem);
}
finally {
reset();
@@ -111,8 +111,8 @@ namespace ts.NavigationBar {
return root;
}
function addLeafNode(node: Node): void {
pushChild(parent, emptyNavigationBarNode(node));
function addLeafNode(node: Node, name?: DeclarationName): void {
pushChild(parent, emptyNavigationBarNode(node, name));
}
function emptyNavigationBarNode(node: Node, name?: DeclarationName): NavigationBarNode {
@@ -243,23 +243,26 @@ namespace ts.NavigationBar {
}
break;
case SyntaxKind.ShorthandPropertyAssignment:
addNodeWithRecursiveChild(node, (<ShorthandPropertyAssignment>node).name);
break;
case SyntaxKind.SpreadAssignment:
const { expression } = <SpreadAssignment>node;
// Use the expression as the name of the SpreadAssignment, otherwise show as <unknown>.
isIdentifier(expression) ? addLeafNode(node, expression) : addLeafNode(node);
break;
case SyntaxKind.BindingElement:
case SyntaxKind.PropertyAssignment:
case SyntaxKind.VariableDeclaration:
const { name, initializer } = <VariableDeclaration | BindingElement>node;
const { name, initializer } = <VariableDeclaration | PropertyAssignment | BindingElement>node;
if (isBindingPattern(name)) {
addChildrenRecursively(name);
}
else if (initializer && isFunctionOrClassExpression(initializer)) {
if (initializer.name) {
// Don't add a node for the VariableDeclaration, just for the initializer.
addChildrenRecursively(initializer);
}
else {
// Add a node for the VariableDeclaration, but not for the initializer.
startNode(node);
forEachChild(initializer, addChildrenRecursively);
endNode();
}
// Add a node for the VariableDeclaration, but not for the initializer.
startNode(node);
forEachChild(initializer, addChildrenRecursively);
endNode();
}
else {
addNodeWithRecursiveChild(node, initializer);
@@ -699,12 +702,15 @@ namespace ts.NavigationBar {
}
}
/** Flattens the NavNode tree to a list, keeping only the top-level items. */
function topLevelItems(root: NavigationBarNode): NavigationBarNode[] {
const topLevel: NavigationBarNode[] = [];
/** Flattens the NavNode tree to a list of items to appear in the primary navbar menu. */
function primaryNavBarMenuItems(root: NavigationBarNode): NavigationBarNode[] {
// The primary (middle) navbar menu displays the general code navigation hierarchy, similar to the navtree.
// The secondary (right) navbar menu displays the child items of whichever primary item is selected.
// Some less interesting items without their own child navigation items (e.g. a local variable declaration) only show up in the secondary menu.
const primaryNavBarMenuItems: NavigationBarNode[] = [];
function recur(item: NavigationBarNode) {
if (isTopLevel(item)) {
topLevel.push(item);
if (shouldAppearInPrimaryNavBarMenu(item)) {
primaryNavBarMenuItems.push(item);
if (item.children) {
for (const child of item.children) {
recur(child);
@@ -713,9 +719,16 @@ namespace ts.NavigationBar {
}
}
recur(root);
return topLevel;
return primaryNavBarMenuItems;
function isTopLevel(item: NavigationBarNode): boolean {
/** Determines if a node should appear in the primary navbar menu. */
function shouldAppearInPrimaryNavBarMenu(item: NavigationBarNode): boolean {
// Items with children should always appear in the primary navbar menu.
if (item.children) {
return true;
}
// Some nodes are otherwise important enough to always include in the primary navigation menu.
switch (navigationBarNodeKind(item)) {
case SyntaxKind.ClassDeclaration:
case SyntaxKind.ClassExpression:
@@ -728,13 +741,6 @@ namespace ts.NavigationBar {
case SyntaxKind.JSDocCallbackTag:
return true;
case SyntaxKind.Constructor:
case SyntaxKind.MethodDeclaration:
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
case SyntaxKind.VariableDeclaration:
return hasSomeImportantChild(item);
case SyntaxKind.ArrowFunction:
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.FunctionExpression:
@@ -755,15 +761,9 @@ namespace ts.NavigationBar {
case SyntaxKind.Constructor:
return true;
default:
return hasSomeImportantChild(item);
return false;
}
}
function hasSomeImportantChild(item: NavigationBarNode): boolean {
return some(item.children, child => {
const childKind = navigationBarNodeKind(child);
return childKind !== SyntaxKind.VariableDeclaration && childKind !== SyntaxKind.BindingElement;
});
}
}
}
@@ -778,19 +778,19 @@ namespace ts.NavigationBar {
};
}
function convertToTopLevelItem(n: NavigationBarNode): NavigationBarItem {
function convertToPrimaryNavBarMenuItem(n: NavigationBarNode): NavigationBarItem {
return {
text: getItemName(n.node, n.name),
kind: getNodeKind(n.node),
kindModifiers: getModifiers(n.node),
spans: getSpans(n),
childItems: map(n.children, convertToChildItem) || emptyChildItemArray,
childItems: map(n.children, convertToSecondaryNavBarMenuItem) || emptyChildItemArray,
indent: n.indent,
bolded: false,
grayed: false
};
function convertToChildItem(n: NavigationBarNode): NavigationBarItem {
function convertToSecondaryNavBarMenuItem(n: NavigationBarNode): NavigationBarItem {
return {
text: getItemName(n.node, n.name),
kind: getNodeKind(n.node),

View File

@@ -353,8 +353,13 @@ namespace ts {
case SyntaxKind.MethodDeclaration:
case SyntaxKind.MethodSignature:
return ScriptElementKind.memberFunctionElement;
case SyntaxKind.PropertyAssignment:
const {initializer} = node as PropertyAssignment;
return isFunctionLike(initializer) ? ScriptElementKind.memberFunctionElement : ScriptElementKind.memberVariableElement;
case SyntaxKind.PropertyDeclaration:
case SyntaxKind.PropertySignature:
case SyntaxKind.ShorthandPropertyAssignment:
case SyntaxKind.SpreadAssignment:
return ScriptElementKind.memberVariableElement;
case SyntaxKind.IndexSignature: return ScriptElementKind.indexSignatureElement;
case SyntaxKind.ConstructSignature: return ScriptElementKind.constructSignatureElement;

View File

@@ -29,7 +29,23 @@ verify.navigationBar([
kind: "script",
childItems: [
{ text: "a", kind: "const" },
],
]
},
{
text: "a",
kind: "const",
childItems: [
{ text: "b", kind: "const"},
],
indent: 1,
},
{
text: "b",
kind: "const",
childItems: [
{ text: "c", kind: "const" },
],
indent: 2,
}
]);

View File

@@ -62,7 +62,7 @@ verify.navigationTree({
"childItems": [
{
"text": "foo",
"kind": "function"
"kind": "method"
}
]
}
@@ -185,7 +185,7 @@ verify.navigationBar([
"childItems": [
{
"text": "foo",
"kind": "function"
"kind": "method"
}
],
"indent": 2

View File

@@ -0,0 +1,64 @@
/// <reference path='fourslash.ts'/>
////'use strict'
////const a = {
//// ...b,
//// c,
//// d: 0
////};
verify.navigationTree({
text: "<global>",
kind: "script",
childItems: [
{
text: "a",
kind: "const",
childItems: [
{
text: "b",
kind: "property",
},
{
text: "c",
kind: "property"
},
{
text: "d",
kind: "property"
}
]
}
]
});
verify.navigationBar([
{
text: "<global>",
kind: "script",
childItems: [
{
text: "a",
kind: "const"
}
]
},
{
text: "a",
kind: "const",
childItems: [
{
text: "b",
kind: "property",
},
{
text: "c",
kind: "property"
},
{
text: "d",
kind: "property"
}
],
indent: 1
}
]);

View File

@@ -1,11 +1,16 @@
/// <reference path="fourslash.ts"/>
////var a = {
//// propA: function() {}
//// propA: function() {
//// var c;
//// }
////};
////var b;
////b = {
//// propB: function() {}
//// propB: function() {
//// // function must not have an empty body to appear top level
//// var d;
//// }
////};
verify.navigationTree({
@@ -18,7 +23,13 @@ verify.navigationTree({
"childItems": [
{
"text": "propA",
"kind": "function"
"kind": "method",
"childItems": [
{
"text": "c",
"kind": "var"
}
]
}
]
},
@@ -28,7 +39,13 @@ verify.navigationTree({
},
{
"text": "propB",
"kind": "function"
"kind": "method",
"childItems": [
{
"text": "d",
"kind": "var"
}
]
}
]
});
@@ -48,7 +65,7 @@ verify.navigationBar([
},
{
"text": "propB",
"kind": "function"
"kind": "method"
}
]
},
@@ -58,14 +75,31 @@ verify.navigationBar([
"childItems": [
{
"text": "propA",
"kind": "function"
"kind": "method"
}
],
"indent": 1
},
{
"text": "propA",
"kind": "method",
"childItems": [
{
"text": "c",
"kind": "var"
}
],
"indent": 2
},
{
"text": "propB",
"kind": "function",
"kind": "method",
"childItems": [
{
"text": "d",
"kind": "var"
}
],
"indent": 1
}
]);

View File

@@ -0,0 +1,91 @@
/// <reference path="fourslash.ts"/>
////var functions = {
//// a: 0,
//// b: function () { },
//// c: function x() { },
//// d: () => { },
//// e: y(),
//// f() { }
////};
verify.navigationTree({
text: "<global>",
kind: "script",
childItems: [
{
text: "functions",
kind: "var",
childItems: [
{
text: "a",
kind: "property"
},
{
text: "b",
kind: "method"
},
{
text: "c",
kind: "method"
},
{
text: "d",
kind: "method"
},
{
text: "e",
kind: "property"
},
{
text: "f",
kind: "method"
}
]
}
]
});
verify.navigationBar([
{
"text": "<global>",
"kind": "script",
"childItems": [
{
"text": "functions",
"kind": "var"
}
]
},
{
"text": "functions",
"kind": "var",
"childItems": [
{
"text": "a",
"kind": "property"
},
{
"text": "b",
"kind": "method"
},
{
"text": "c",
"kind": "method"
},
{
"text": "d",
"kind": "method"
},
{
"text": "e",
"kind": "property"
},
{
"text": "f",
"kind": "method"
}
],
"indent": 1
}
]);

View File

@@ -44,11 +44,11 @@ verify.navigationTree({
"childItems": [
{
"text": "get",
"kind": "function"
"kind": "method"
},
{
"text": "set",
"kind": "function"
"kind": "method"
}
]
},
@@ -57,11 +57,11 @@ verify.navigationTree({
"childItems": [
{
"text": "get",
"kind": "function"
"kind": "method"
},
{
"text": "set",
"kind": "function"
"kind": "method"
}
]
}
@@ -108,5 +108,33 @@ verify.navigationBar([
}
],
"indent": 1
}
},
{
"text": "staticProp",
"childItems": [
{
"text": "get",
"kind": "method"
},
{
"text": "set",
"kind": "method"
}
],
"indent": 2
},
{
"text": "name",
"childItems": [
{
"text": "get",
"kind": "method"
},
{
"text": "set",
"kind": "method"
}
],
"indent": 2
}
]);

View File

@@ -138,6 +138,28 @@ verify.navigationBar([
}
]
},
{
"text": "G",
"kind": "method",
"childItems": [
{
"text": "A",
"kind": "method"
}
],
"indent": 1
},
{
"text": "A",
"kind": "method",
"childItems": [
{
"text": "a",
"kind": "function"
}
],
"indent": 2
},
{
"text": "A",
"kind": "class",
@@ -152,5 +174,16 @@ verify.navigationBar([
}
],
"indent": 1
}
},
{
"text": "A",
"kind": "method",
"childItems": [
{
"text": "a",
"kind": "function"
}
],
"indent": 2
},
]);

View File

@@ -208,6 +208,16 @@ verify.navigationBar([
],
"indent": 2
},
{
"text": "x",
"childItems": [
{
"text": "get",
"kind": "method"
}
],
"indent": 3
},
{
"text": "D",
"kind": "class",

View File

@@ -1,10 +1,25 @@
/// <reference path="fourslash.ts" />
////const [|[|x|] = () => 0|];
////const f = [|function [|f|]() {}|];
////// get the name for the navbar from the variable name rather than the function name
////const [|[|x|] = () => { var [|a|]; }|];
////const [|[|f|] = function f() { var [|b|]; }|];
////const [|[|y|] = { [|[|z|]: function z() { var [|c|]; }|] }|];
const [s0, s0Name, s1, s1Name] = test.spans();
const sGlobal = { start: 0, length: 45 };
const [
s0,
s0Name,
s0Child,
s1,
s1Name,
s1Child,
s2,
s2Name,
s2Child,
s2ChildName,
s2GrandChildName
] = test.spans();
const sGlobal = { start: 0, length: 188 };
verify.navigationTree({
text: "<global>",
@@ -13,16 +28,54 @@ verify.navigationTree({
childItems: [
{
text: "f",
kind: "function",
kind: "const",
spans: [s1],
nameSpan: s1Name,
childItems: [
{
text: "b",
kind: "var",
spans: [s1Child],
nameSpan: s1Child,
},
],
},
{
text: "x",
kind: "const",
spans: [s0],
nameSpan: s0Name,
childItems: [
{
text: "a",
kind: "var",
spans: [s0Child],
nameSpan: s0Child,
},
],
},
{
text: "y",
kind: "const",
spans: [s2],
nameSpan: s2Name,
childItems:[
{
text: "z",
kind: "method",
spans: [s2Child],
nameSpan: s2ChildName,
childItems: [
{
text: "c",
kind: "var",
spans: [s2GrandChildName],
nameSpan: s2GrandChildName,
},
],
},
],
}
]
}, { checkSpans: true });
@@ -34,7 +87,7 @@ verify.navigationBar([
childItems: [
{
text: "f",
kind: "function",
kind: "const",
spans: [s1],
},
{
@@ -42,12 +95,63 @@ verify.navigationBar([
kind: "const",
spans: [s0],
},
{
text: "y",
kind: "const",
spans: [s2],
}
],
},
{
text: "f",
kind: "function",
kind: "const",
spans: [s1],
childItems: [
{
text: "b",
kind: "var",
spans: [s1Child],
},
],
indent: 1,
},
{
text: "x",
kind: "const",
spans: [s0],
childItems: [
{
text: "a",
kind: "var",
spans: [s0Child],
},
],
indent: 1,
},
{
text: "y",
kind: "const",
spans: [s2],
childItems: [
{
text: "z",
kind: "method",
spans: [s2Child],
},
],
indent: 1,
},
{
text: "z",
kind: "method",
spans: [s2Child],
childItems: [
{
text: "c",
kind: "var",
spans: [s2GrandChildName],
},
],
indent: 2,
},
], { checkSpans: true });

View File

@@ -5,6 +5,7 @@
////let foo1, {a, b}
////const bar1, [c, d]
////var {e, x: [f, g]} = {a:1, x:[]};
////var { h: i = function j() {} } = obj;
verify.navigationTree({
"text": "<global>",
@@ -53,6 +54,10 @@ verify.navigationTree({
{
"text": "g",
"kind": "var"
},
{
"text": "i",
"kind": "var"
}
]
});
@@ -105,6 +110,10 @@ verify.navigationBar([
{
"text": "g",
"kind": "var"
},
{
"text": "i",
"kind": "var"
}
]
}

View File

@@ -7,6 +7,9 @@
//// function biz() {
//// var z = 10;
//// }
//// function qux() {
//// // A function with an empty body should not be top level
//// }
//// }
////}
////
@@ -46,6 +49,10 @@ verify.navigationTree({
}
]
},
{
"text": "qux",
"kind": "function"
},
{
"text": "y",
"kind": "var"
@@ -110,11 +117,27 @@ verify.navigationBar([
"text": "biz",
"kind": "function"
},
{
"text": "qux",
"kind": "function"
},
{
"text": "y",
"kind": "var"
}
],
"indent": 2
}
},
{
"text": "biz",
"kind": "function",
"childItems": [
{
"text": "z",
"kind": "var"
}
],
"indent": 3
},
]);

View File

@@ -78,5 +78,17 @@ verify.navigationBar([
}
],
"indent": 1
},
{
"text": "constructor",
"kind": "constructor",
"childItems": [
{
"text": "local",
"kind": "var"
}
],
"indent": 2
}
]);

View File

@@ -1,5 +1,6 @@
/// <reference path="fourslash.ts"/>
////// Should not merge grandchildren with property assignments
////const o = {
//// a: {
//// m() {},
@@ -17,8 +18,20 @@ verify.navigationTree({
text: "o",
kind: "const",
childItems: [
{ text: "m", kind: "method" },
{ text: "m", kind: "method" },
{
text: "a",
kind: "property",
childItems: [
{ text: "m", kind: "method" }
]
},
{
text: "b",
kind: "property",
childItems: [
{ text: "m", kind: "method" }
]
},
],
},
]
@@ -36,9 +49,26 @@ verify.navigationBar([
text: "o",
kind: "const",
childItems: [
{ text: "m", kind: "method" },
{ text: "m", kind: "method" },
{ text: "a", kind: "property" },
{ text: "b", kind: "property" },
],
indent: 1,
},
{
text: "a",
kind: "property",
childItems: [
{ text: "m", kind: "method" },
],
indent: 2,
},
{
text: "b",
kind: "property",
childItems: [
{ text: "m", kind: "method" },
],
indent: 2,
},
]);

View File

@@ -0,0 +1,139 @@
/// <reference path="fourslash.ts"/>
////var a = {
//// b: 0,
//// c: {},
//// d: {
//// e: 1,
//// },
//// f: {
//// g: 2,
//// h: {
//// i: 3,
//// },
//// },
////}
verify.navigationTree({
"text": "<global>",
"kind": "script",
"childItems": [
{
"text": "a",
"kind": "var",
"childItems": [
{
"text": "b",
"kind": "property"
},
{
"text": "c",
"kind": "property"
},
{
"text": "d",
"kind": "property",
"childItems": [
{
"text": "e",
"kind": "property"
}
]
},
{
"text": "f",
"kind": "property",
"childItems": [
{
"text": "g",
"kind": "property"
},
{
"text": "h",
"kind": "property",
"childItems": [
{
"text": "i",
"kind": "property"
}
]
}
]
}
]
}
]
});
verify.navigationBar([
{
"text": "<global>",
"kind": "script",
"childItems": [
{
"text": "a",
"kind": "var"
}
]
},
{
"text": "a",
"kind": "var",
"childItems": [
{
"text": "b",
"kind": "property"
},
{
"text": "c",
"kind": "property"
},
{
"text": "d",
"kind": "property"
},
{
"text": "f",
"kind": "property"
}
],
"indent": 1
},
{
"text": "d",
"kind": "property",
"childItems": [
{
"text": "e",
"kind": "property"
}
],
"indent": 2
},
{
"text": "f",
"kind": "property",
"childItems": [
{
"text": "g",
"kind": "property"
},
{
"text": "h",
"kind": "property"
}
],
"indent": 2
},
{
"text": "h",
"kind": "property",
"childItems": [
{
"text": "i",
"kind": "property"
}
],
"indent": 3
}
]);