diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index 4a756ab3b1ecc..87bcbb14fbe88 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -1992,7 +1992,7 @@ namespace FourSlash { } } - public printNavigationBar() { + public printNavigationBar(showChildItems = false) { const items = this.languageService.getNavigationBarItems(this.activeFile.fileName); const length = items && items.length; @@ -3190,8 +3190,8 @@ namespace FourSlashInterface { this.state.printNavigationItems(searchValue); } - public printNavigationBar() { - this.state.printNavigationBar(); + public printNavigationBar(showChildItems = false) { + this.state.printNavigationBar(showChildItems); } public printReferences() { diff --git a/src/services/navigationBar.ts b/src/services/navigationBar.ts index 57726a45cb023..23343ec25485a 100644 --- a/src/services/navigationBar.ts +++ b/src/services/navigationBar.ts @@ -26,9 +26,12 @@ namespace ts.NavigationBar { while (current.kind === SyntaxKind.ModuleDeclaration); // fall through + case SyntaxKind.ClassExpression: case SyntaxKind.ClassDeclaration: case SyntaxKind.EnumDeclaration: case SyntaxKind.InterfaceDeclaration: + case SyntaxKind.ArrowFunction: + case SyntaxKind.FunctionExpression: case SyntaxKind.FunctionDeclaration: indent++; } @@ -85,15 +88,25 @@ namespace ts.NavigationBar { case SyntaxKind.BindingElement: case SyntaxKind.VariableDeclaration: - if (isBindingPattern((node).name)) { - visit((node).name); + const decl = node; + if (isBindingPattern(decl.name)) { + visit(decl.name); break; } + // Don't include the const 'x' in `const x = function() {}`, just use the function. + if (decl.initializer && isFunctionOrClassExpression(decl.initializer)) { + visit(decl.initializer); + break; + } + // Fall through + case SyntaxKind.ClassExpression: case SyntaxKind.ClassDeclaration: case SyntaxKind.EnumDeclaration: case SyntaxKind.InterfaceDeclaration: case SyntaxKind.ModuleDeclaration: + case SyntaxKind.ArrowFunction: + case SyntaxKind.FunctionExpression: case SyntaxKind.FunctionDeclaration: case SyntaxKind.ImportEqualsDeclaration: case SyntaxKind.ImportSpecifier: @@ -101,6 +114,9 @@ namespace ts.NavigationBar { case SyntaxKind.TypeAliasDeclaration: childNodes.push(node); break; + + default: + forEachChild(node, visit); } } @@ -133,14 +149,21 @@ namespace ts.NavigationBar { } function sortNodes(nodes: Node[]): Node[] { - return nodes.slice(0).sort((n1: Declaration, n2: Declaration) => { - if (n1.name && n2.name) { - return localeCompareFix(getPropertyNameForPropertyNameNode(n1.name), getPropertyNameForPropertyNameNode(n2.name)); + const sortedCopy = nodes.slice(0); + sortNodesInPlace(sortedCopy); + return sortedCopy; + } + + function sortNodesInPlace(nodes: Node[]): void { + nodes.sort((n1, n2) => { + const name1 = tryGetName(n1), name2 = tryGetName(n2); + if (name1 && name2) { + return localeCompareFix(name1, name2); } - else if (n1.name) { + else if (name1) { return 1; } - else if (n2.name) { + else if (name2) { return -1; } else { @@ -159,87 +182,95 @@ namespace ts.NavigationBar { } } - function addTopLevelNodes(nodes: Node[], topLevelNodes: Node[]): void { - nodes = sortNodes(nodes); + // Add nodes in a single "level" of top-level nodes (e.g. methods in a class.) + // Nodes in a single "level" are sorted together. + // Returns whether any nodes were added. + function addTopLevelNodes(nodes: Node | Node[], topLevelNodes: Node[]) { + const decls = getNextLevelOfDeclarations(nodes); + // Sort each level of declarations together + sortNodesInPlace(decls); + for (const decl of decls) { + addTopLevelNode(decl, topLevelNodes); + } + } - for (const node of nodes) { + // Gets all declarations contained within `nodes` and their sub-expressions, + // but not declarations within declarations. + function getNextLevelOfDeclarations(nodes: Node | Node[]): Node[] { + const result: Node[] = []; + function recur(node: Node): void { switch (node.kind) { + case SyntaxKind.ClassExpression: case SyntaxKind.ClassDeclaration: - topLevelNodes.push(node); - for (const member of (node).members) { - if (member.kind === SyntaxKind.MethodDeclaration || member.kind === SyntaxKind.Constructor) { - type FunctionLikeMember = MethodDeclaration | ConstructorDeclaration; - if ((member).body) { - // We do not include methods that does not have child functions in it, because of duplications. - if (hasNamedFunctionDeclarations(((member).body).statements)) { - topLevelNodes.push(member); - } - addTopLevelNodes(((member).body).statements, topLevelNodes); - } - } - } - break; case SyntaxKind.EnumDeclaration: case SyntaxKind.InterfaceDeclaration: case SyntaxKind.TypeAliasDeclaration: - topLevelNodes.push(node); - break; - case SyntaxKind.ModuleDeclaration: - let moduleDeclaration = node; - topLevelNodes.push(node); - addTopLevelNodes((getInnermostModule(moduleDeclaration).body).statements, topLevelNodes); - break; - + case SyntaxKind.ArrowFunction: + case SyntaxKind.FunctionExpression: case SyntaxKind.FunctionDeclaration: - let functionDeclaration = node; - if (isTopLevelFunctionDeclaration(functionDeclaration)) { - topLevelNodes.push(node); - addTopLevelNodes((functionDeclaration.body).statements, topLevelNodes); - } + result.push(node); + // Its children are handled by addTopLevelNode later. break; + default: + forEachChild(node, recur); } } - } - - function hasNamedFunctionDeclarations(nodes: NodeArray): boolean { - for (const s of nodes) { - if (s.kind === SyntaxKind.FunctionDeclaration && !isEmpty((s).name.text)) { - return true; + if (nodes instanceof Array) { + for (const node of nodes) { + recur(node); } } - return false; + else { + recur(nodes); + } + return result; } - function isTopLevelFunctionDeclaration(functionDeclaration: FunctionLikeDeclaration): boolean { - if (functionDeclaration.kind === SyntaxKind.FunctionDeclaration) { - // A function declaration is 'top level' if it contains any function declarations - // within it. - if (functionDeclaration.body && functionDeclaration.body.kind === SyntaxKind.Block) { - // Proper function declarations can only have identifier names - if (hasNamedFunctionDeclarations((functionDeclaration.body).statements)) { - return true; + function addTopLevelNode(node: Node, topLevelNodes: Node[]) { + switch (node.kind) { + case SyntaxKind.ClassExpression: + case SyntaxKind.ClassDeclaration: + topLevelNodes.push(node); + for (const member of (node).members) { + if (member.kind === SyntaxKind.MethodDeclaration || member.kind === SyntaxKind.Constructor) { + type FunctionLikeMember = MethodDeclaration | ConstructorDeclaration; + const decl = member; + if (decl.body) { + // Add node, but it will not become an item unless it has children later. + topLevelNodes.push(member); + addTopLevelNodes(decl.body.statements, topLevelNodes); + } + } } + break; - // Or if it is not parented by another function. I.e all functions at module scope are 'top level'. - if (!isFunctionBlock(functionDeclaration.parent)) { - return true; - } + case SyntaxKind.EnumDeclaration: + case SyntaxKind.InterfaceDeclaration: + case SyntaxKind.TypeAliasDeclaration: + topLevelNodes.push(node); + break; - // Or if it is nested inside class methods and constructors. - else { - // We have made sure that a grand parent node exists with 'isFunctionBlock()' above. - const grandParentKind = functionDeclaration.parent.parent.kind; - if (grandParentKind === SyntaxKind.MethodDeclaration || - grandParentKind === SyntaxKind.Constructor) { + case SyntaxKind.ModuleDeclaration: + let moduleDeclaration = node; + topLevelNodes.push(node); + addTopLevelNodes((getInnermostModule(moduleDeclaration).body).statements, topLevelNodes); + break; - return true; - } + case SyntaxKind.ArrowFunction: + case SyntaxKind.FunctionExpression: + case SyntaxKind.FunctionDeclaration: + const decl = node; + if (decl.body) { + topLevelNodes.push(node); + addTopLevelNodes(decl.body, topLevelNodes); } - } - } + break; - return false; + default: + // There should be a case in addTopLevelNode for each case in getNextLevelOfDeclarations. + throw new Error("Unreachable"); + } } function getItemsWorker(nodes: Node[], createItem: (n: Node) => ts.NavigationBarItem): ts.NavigationBarItem[] { @@ -251,6 +282,12 @@ namespace ts.NavigationBar { const item = createItem(child); if (item !== undefined) { if (item.text.length > 0) { + if (isFunctionOrClassExpression(child)) { + // Never merge + items.push(item); + continue; + } + const key = item.text + "-" + item.kind + "-" + item.indent; const itemWithSameName = keyToItem[key]; @@ -345,10 +382,13 @@ namespace ts.NavigationBar { return createItem(node, getTextOfNode((node).name), ts.ScriptElementKind.memberVariableElement); case SyntaxKind.ClassDeclaration: - return createItem(node, getTextOfNode((node).name), ts.ScriptElementKind.classElement); + case SyntaxKind.ClassExpression: + return createItem(node, getFunctionOrClassName(node), ts.ScriptElementKind.classElement); + case SyntaxKind.ArrowFunction: + case SyntaxKind.FunctionExpression: case SyntaxKind.FunctionDeclaration: - return createItem(node, getTextOfNode((node).name), ts.ScriptElementKind.functionElement); + return createItem(node, getFunctionOrClassName(node), ts.ScriptElementKind.functionElement); case SyntaxKind.VariableDeclaration: case SyntaxKind.BindingElement: @@ -425,6 +465,7 @@ namespace ts.NavigationBar { case SyntaxKind.SourceFile: return createSourceFileItem(node); + case SyntaxKind.ClassExpression: case SyntaxKind.ClassDeclaration: return createClassItem(node); @@ -441,6 +482,8 @@ namespace ts.NavigationBar { case SyntaxKind.ModuleDeclaration: return createModuleItem(node); + case SyntaxKind.ArrowFunction: + case SyntaxKind.FunctionExpression: case SyntaxKind.FunctionDeclaration: return createFunctionItem(node); @@ -464,18 +507,25 @@ namespace ts.NavigationBar { } function createFunctionItem(node: FunctionDeclaration): ts.NavigationBarItem { - if (node.body && node.body.kind === SyntaxKind.Block) { - const childItems = getItemsWorker(sortNodes((node.body).statements), createChildItem); - - return getNavigationBarItem(!node.name ? "default" : node.name.text, - ts.ScriptElementKind.functionElement, - getNodeModifiers(node), - [getNodeSpan(node)], - childItems, - getIndent(node)); + const children = node.body ? getChildNodes([node.body]) : []; + const isTopLevel = node.parent.kind === SyntaxKind.ModuleBlock || node.parent.kind === SyntaxKind.SourceFile || + // Functions with declaration children (not including local variables) are worthy + children.some(child => child.kind !== SyntaxKind.VariableDeclaration && child.kind !== SyntaxKind.BindingElement) || + // Functions inside class methods are worthy + node.parent.parent.kind === SyntaxKind.MethodDeclaration || node.parent.parent.kind === SyntaxKind.Constructor; + if (!isTopLevel) { + return undefined; } - return undefined; + const childItems = getItemsWorker(children, createChildItem); + + return getNavigationBarItem( + getFunctionOrClassName(node), + ts.ScriptElementKind.functionElement, + getNodeModifiers(node), + [getNodeSpan(node)], + childItems, + getIndent(node)); } function createTypeAliasItem(node: TypeAliasDeclaration): ts.NavigationBarItem { @@ -488,28 +538,29 @@ namespace ts.NavigationBar { } function createMemberFunctionLikeItem(node: MethodDeclaration | ConstructorDeclaration): ts.NavigationBarItem { - if (node.body && node.body.kind === SyntaxKind.Block) { - const childItems = getItemsWorker(sortNodes((node.body).statements), createChildItem); - let scriptElementKind: string; - let memberFunctionName: string; - if (node.kind === SyntaxKind.MethodDeclaration) { - memberFunctionName = getPropertyNameForPropertyNameNode(node.name); - scriptElementKind = ts.ScriptElementKind.memberFunctionElement; - } - else { - memberFunctionName = "constructor"; - scriptElementKind = ts.ScriptElementKind.constructorImplementationElement; - } + const childItems = getItemsWorker(sortNodes(node.body.statements), createChildItem); + // Don't include member functions as top-level if they don't contain other items. + if (!childItems.length) { + return undefined; + } - return getNavigationBarItem(memberFunctionName, - scriptElementKind, - getNodeModifiers(node), - [getNodeSpan(node)], - childItems, - getIndent(node)); + let scriptElementKind: string; + let memberFunctionName: string; + if (node.kind === SyntaxKind.MethodDeclaration) { + memberFunctionName = getPropertyNameForPropertyNameNode(node.name); + scriptElementKind = ts.ScriptElementKind.memberFunctionElement; + } + else { + memberFunctionName = "constructor"; + scriptElementKind = ts.ScriptElementKind.constructorImplementationElement; } - return undefined; + return getNavigationBarItem(memberFunctionName, + scriptElementKind, + getNodeModifiers(node), + [getNodeSpan(node)], + childItems, + getIndent(node)); } function createSourceFileItem(node: SourceFile): ts.NavigationBarItem { @@ -545,10 +596,8 @@ namespace ts.NavigationBar { childItems = getItemsWorker(sortNodes(nodes), createChildItem); } - const nodeName = !node.name ? "default" : node.name.text; - return getNavigationBarItem( - nodeName, + getFunctionOrClassName(node), ts.ScriptElementKind.classElement, getNodeModifiers(node), [getNodeSpan(node)], @@ -630,8 +679,6 @@ namespace ts.NavigationBar { } export function getJsNavigationBarItems(sourceFile: SourceFile, compilerOptions: CompilerOptions): NavigationBarItem[] { - const anonFnText = ""; - const anonClassText = ""; let indent = 0; const rootName = isExternalModule(sourceFile) ? @@ -661,8 +708,7 @@ namespace ts.NavigationBar { topItem = lastTop; indent--; - // If the last item added was an anonymous function expression, and it had no children, discard it. - if (newItem && newItem.text === anonFnText && newItem.childItems.length === 0) { + if (newItem && isAnonymousFunction(newItem) && newItem.childItems.length === 0) { topItem.childItems.pop(); } } @@ -772,30 +818,7 @@ namespace ts.NavigationBar { } const fnExpr = node as FunctionExpression | ArrowFunction | ClassExpression; - let fnName: string; - if (fnExpr.name && getFullWidth(fnExpr.name) > 0) { - // The expression has an identifier, so use that as the name - fnName = declarationNameToString(fnExpr.name); - } - else { - // See if it is a var initializer. If so, use the var name. - if (fnExpr.parent.kind === SyntaxKind.VariableDeclaration) { - fnName = declarationNameToString((fnExpr.parent as VariableDeclaration).name); - } - // See if it is of the form " = function(){...}". If so, use the text from the left-hand side. - else if (fnExpr.parent.kind === SyntaxKind.BinaryExpression && - (fnExpr.parent as BinaryExpression).operatorToken.kind === SyntaxKind.EqualsToken) { - fnName = (fnExpr.parent as BinaryExpression).left.getText(); - } - // See if it is a property assignment, and if so use the property name - else if (fnExpr.parent.kind === SyntaxKind.PropertyAssignment && - (fnExpr.parent as PropertyAssignment).name) { - fnName = (fnExpr.parent as PropertyAssignment).name.getText(); - } - else { - fnName = node.kind === SyntaxKind.ClassExpression ? anonClassText : anonFnText; - } - } + const fnName = getFunctionOrClassName(fnExpr); const scriptKind = node.kind === SyntaxKind.ClassExpression ? ScriptElementKind.classElement : ScriptElementKind.functionElement; return getNavBarItem(fnName, scriptKind, [getNodeSpan(node)]); } @@ -827,4 +850,57 @@ namespace ts.NavigationBar { return sourceFileItem.childItems; } + + const anonymousFunctionText = ""; + const anonymousClassText = ""; + + function tryGetName(node: Node): string { + const decl = node; + if (decl.name) { + return getPropertyNameForPropertyNameNode(decl.name); + } + switch (node.kind) { + case SyntaxKind.FunctionExpression: + case SyntaxKind.ArrowFunction: + case SyntaxKind.ClassExpression: + return getFunctionOrClassName(node); + default: + return undefined; + } + } + + /** Get the name for a (possibly anonymous) class/function expression. */ + function getFunctionOrClassName(node: FunctionExpression | FunctionDeclaration | ArrowFunction | ClassLikeDeclaration): string { + if (node.name && getFullWidth(node.name) > 0) { + return declarationNameToString(node.name); + } + // See if it is a var initializer. If so, use the var name. + else if (node.parent.kind === SyntaxKind.VariableDeclaration) { + return declarationNameToString((node.parent as VariableDeclaration).name); + } + // See if it is of the form " = function(){...}". If so, use the text from the left-hand side. + else if (node.parent.kind === SyntaxKind.BinaryExpression && + (node.parent as BinaryExpression).operatorToken.kind === SyntaxKind.EqualsToken) { + return (node.parent as BinaryExpression).left.getText(); + } + // See if it is a property assignment, and if so use the property name + else if (node.parent.kind === SyntaxKind.PropertyAssignment && (node.parent as PropertyAssignment).name) { + return (node.parent as PropertyAssignment).name.getText(); + } + // Default exports are named "default" + else if (node.flags & NodeFlags.Default) { + return "default"; + } + else { + return isClassLike(node) ? anonymousClassText : anonymousFunctionText; + } + } + + function isAnonymousFunction(item: NavigationBarItem): boolean { + return item.text === anonymousFunctionText; + } + + function isFunctionOrClassExpression(node: Node): boolean { + return node.kind === SyntaxKind.FunctionExpression || node.kind === SyntaxKind.ArrowFunction || node.kind === SyntaxKind.ClassExpression; + } } diff --git a/tests/cases/fourslash/fourslash.ts b/tests/cases/fourslash/fourslash.ts index 8a0d2d36364c2..b86d1b493d2fb 100644 --- a/tests/cases/fourslash/fourslash.ts +++ b/tests/cases/fourslash/fourslash.ts @@ -235,7 +235,7 @@ declare namespace FourSlashInterface { printBreakpointAtCurrentLocation(): void; printNameOrDottedNameSpans(pos: number): void; printErrorList(): void; - printNavigationBar(): void; + printNavigationBar(showChildItems?: boolean): void; printNavigationItems(searchValue?: string): void; printScriptLexicalStructureItems(): void; printReferences(): void; diff --git a/tests/cases/fourslash/navbar_exportDefault.ts b/tests/cases/fourslash/navbar_exportDefault.ts index dc99cff7d649c..e547c9129a69d 100644 --- a/tests/cases/fourslash/navbar_exportDefault.ts +++ b/tests/cases/fourslash/navbar_exportDefault.ts @@ -16,7 +16,14 @@ goTo.file("a.ts"); verify.navigationBar([ { "text": "\"a\"", - "kind": "module" + "kind": "module", + "childItems": [ + { + "text": "default", + "kind": "class", + "kindModifiers": "export" + } + ] }, { "text": "default", @@ -52,6 +59,13 @@ verify.navigationBar([ { "text": "\"c\"", "kind": "module", + "childItems": [ + { + "text": "default", + "kind": "function", + "kindModifiers": "export" + } + ] }, { "text": "default", diff --git a/tests/cases/fourslash/navigationBarAnonymousDeclarationExpressions.ts b/tests/cases/fourslash/navigationBarAnonymousDeclarationExpressions.ts new file mode 100644 index 0000000000000..8fe12ec94a284 --- /dev/null +++ b/tests/cases/fourslash/navigationBarAnonymousDeclarationExpressions.ts @@ -0,0 +1,148 @@ +/// + +////global.cls = class { }; +////(function() { +//// const x = () => { +//// // Presence of inner function causes x to be a top-level function. +//// function xx() {} +//// }; +//// const y = { +//// // This is not a top-level function (contains nothing, but shows up in childItems of its parent.) +//// foo: function() {} +//// }; +//// (function nest() { +//// function moreNest() {} +//// })(); +////})(); +////(function() { // Different anonymous functions are not merged +//// // These will only show up as childItems. +//// function z() {} +//// console.log(function() {}) +////}) +////(function classes() { +//// // Classes show up in top-level regardless of whether they have names or inner declarations. +//// const cls2 = class { }; +//// console.log(class cls3 {}); +//// (class { }); +////}) + +verify.navigationBar([ + { + "text": "", + "kind": "module", + "childItems": [ + { + "text": "", + "kind": "function" + }, + { + "text": "", + "kind": "function" + }, + { + "text": "classes", + "kind": "function" + }, + { + "text": "global.cls", + "kind": "class" + } + ] + }, + { + "text": "", + "kind": "function", + "childItems": [ + { + "text": "nest", + "kind": "function" + }, + { + "text": "x", + "kind": "function" + }, + { + "text": "y", + "kind": "const" + } + ], + "indent": 1 + }, + { + "text": "nest", + "kind": "function", + "childItems": [ + { + "text": "moreNest", + "kind": "function" + } + ], + "indent": 2 + }, + { + "text": "x", + "kind": "function", + "childItems": [ + { + "text": "xx", + "kind": "function" + } + ], + "indent": 2 + }, + { + "text": "", + "kind": "function", + "childItems": [ + { + "text": "", + "kind": "function" + }, + { + "text": "z", + "kind": "function" + } + ], + "indent": 1 + }, + { + "text": "classes", + "kind": "function", + "childItems": [ + { + "text": "", + "kind": "class" + }, + { + "text": "cls2", + "kind": "class" + }, + { + "text": "cls3", + "kind": "class" + } + ], + "indent": 1 + }, + { + "text": "", + "kind": "class", + "indent": 2 + }, + { + "text": "cls2", + "kind": "class", + "indent": 2 + }, + { + "text": "cls3", + "kind": "class", + "indent": 2 + }, + { + "text": "global.cls", + "kind": "class", + "indent": 1 + } +] +); diff --git a/tests/cases/fourslash/navigationBarDeclarationExpressions.ts b/tests/cases/fourslash/navigationBarDeclarationExpressions.ts new file mode 100644 index 0000000000000..4d037e42fa78e --- /dev/null +++ b/tests/cases/fourslash/navigationBarDeclarationExpressions.ts @@ -0,0 +1,76 @@ +/// + +////console.log(console.log(class Y {}, class X {}), console.log(class B {}, class A {})); +////console.log(class Cls { meth() {} }); + +verify.navigationBar( [ + { + "text": "", + "kind": "module", + "childItems": [ + { + "text": "A", + "kind": "class" + }, + { + "text": "B", + "kind": "class" + }, + { + "text": "Cls", + "kind": "class" + }, + { + "text": "X", + "kind": "class" + }, + { + "text": "Y", + "kind": "class" + } + ] + }, + { + "text": "A", + "kind": "class", + "indent": 1 + }, + { + "text": "B", + "kind": "class", + "indent": 1 + }, + { + "text": "Cls", + "kind": "class", + "childItems": [ + { + "text": "meth", + "kind": "method" + } + ], + "indent": 1 + }, + { + "text": "X", + "kind": "class", + "indent": 1 + }, + { + "text": "Y", + "kind": "class", + "indent": 1 + } +]); + +/* +verify.navigationBarCount(6); +verify.navigationBarIndex("A", 0); +verify.navigationBarIndex("B", 1); +verify.navigationBarIndex("Cls", 2); +verify.navigationBarIndex("X", 3); +verify.navigationBarIndex("Y", 4); + +verify.navigationBarContains("Cls", "class"); +verify.navigationBarChildItem("Cls", "meth", "method"); +*/ \ No newline at end of file diff --git a/tests/cases/fourslash/navigationBarItemsFunctions.ts b/tests/cases/fourslash/navigationBarItemsFunctions.ts index 91546462a2572..f5aa3fb681dd5 100644 --- a/tests/cases/fourslash/navigationBarItemsFunctions.ts +++ b/tests/cases/fourslash/navigationBarItemsFunctions.ts @@ -32,6 +32,12 @@ verify.navigationBar([ { "text": "baz", "kind": "function", + "childItems": [ + { + "text": "v", + "kind": "var" + } + ], "indent": 1 }, { @@ -41,6 +47,10 @@ verify.navigationBar([ { "text": "bar", "kind": "function" + }, + { + "text": "x", + "kind": "var" } ], "indent": 1 @@ -52,6 +62,10 @@ verify.navigationBar([ { "text": "biz", "kind": "function" + }, + { + "text": "y", + "kind": "var" } ], "indent": 2 diff --git a/tests/cases/fourslash/navigationBarItemsFunctionsBroken.ts b/tests/cases/fourslash/navigationBarItemsFunctionsBroken.ts index 96dcbb944ae07..2f17a5006ff5f 100644 --- a/tests/cases/fourslash/navigationBarItemsFunctionsBroken.ts +++ b/tests/cases/fourslash/navigationBarItemsFunctionsBroken.ts @@ -18,6 +18,12 @@ verify.navigationBar([ { "text": "f", "kind": "function", + "childItems": [ + { + "text": "", + "kind": "function" + } + ], "indent": 1 } ]); diff --git a/tests/cases/fourslash/navigationBarItemsFunctionsBroken2.ts b/tests/cases/fourslash/navigationBarItemsFunctionsBroken2.ts index 127bde8c9e71d..f907bdad06719 100644 --- a/tests/cases/fourslash/navigationBarItemsFunctionsBroken2.ts +++ b/tests/cases/fourslash/navigationBarItemsFunctionsBroken2.ts @@ -10,6 +10,10 @@ verify.navigationBar([ "text": "", "kind": "module", "childItems": [ + { + "text": "", + "kind": "function" + }, { "text": "f", "kind": "function" @@ -19,6 +23,12 @@ verify.navigationBar([ { "text": "f", "kind": "function", + "childItems": [ + { + "text": "", + "kind": "function" + } + ], "indent": 1 } ]); diff --git a/tests/cases/fourslash/navigationBarItemsItems2.ts b/tests/cases/fourslash/navigationBarItemsItems2.ts index 762531d8778b5..6ab0827e8f959 100644 --- a/tests/cases/fourslash/navigationBarItemsItems2.ts +++ b/tests/cases/fourslash/navigationBarItemsItems2.ts @@ -12,6 +12,11 @@ verify.navigationBar([ "text": "\"navigationBarItemsItems2\"", "kind": "module", "childItems": [ + { + "text": "", + "kind": "class", + "kindModifiers": "export" + }, { "text": "A", "kind": "module" @@ -19,7 +24,7 @@ verify.navigationBar([ ] }, { - "text": "default", + "text": "", "kind": "class", "kindModifiers": "export", "indent": 1 diff --git a/tests/cases/fourslash/navigationBarItemsItemsContainsNoAnonymousFunctions.ts b/tests/cases/fourslash/navigationBarItemsItemsContainsNoAnonymousFunctions.ts deleted file mode 100644 index 276e19624c92a..0000000000000 --- a/tests/cases/fourslash/navigationBarItemsItemsContainsNoAnonymousFunctions.ts +++ /dev/null @@ -1,80 +0,0 @@ -/// -// @Filename: scriptLexicalStructureItemsContainsNoAnonymouseFunctions_0.ts -/////*file1*/ -////(function() { -//// // this should not be included -//// var x = 0; -//// -//// // this should not be included either -//// function foo() { -//// -//// } -////})(); -//// -// @Filename: scriptLexicalStructureItemsContainsNoAnonymouseFunctions_1.ts -/////*file2*/ -////var x = function() { -//// // this should not be included -//// var x = 0; -//// -//// // this should not be included either -//// function foo() { -////}; -//// -// @Filename: scriptLexicalStructureItemsContainsNoAnonymouseFunctions_2.ts -////// Named functions should still show up -/////*file3*/ -////function foo() { -////} -////function bar() { -////} - -goTo.marker("file1"); -verify.navigationBar([ - { - "text": "", - "kind": "module" - } -]); - -goTo.marker("file2"); -verify.navigationBar([ - { - "text": "", - "kind": "module", - "childItems": [ - { - "text": "x", - "kind": "var" - } - ] - } -]); - -goTo.marker("file3"); -verify.navigationBar([ - { - "text": "", - "kind": "module", - "childItems": [ - { - "text": "bar", - "kind": "function" - }, - { - "text": "foo", - "kind": "function" - } - ] - }, - { - "text": "bar", - "kind": "function", - "indent": 1 - }, - { - "text": "foo", - "kind": "function", - "indent": 1 - } -]); diff --git a/tests/cases/fourslash/navigationBarItemsMissingName1.ts b/tests/cases/fourslash/navigationBarItemsMissingName1.ts index af0e89683bcfe..84ee46e9cfad3 100644 --- a/tests/cases/fourslash/navigationBarItemsMissingName1.ts +++ b/tests/cases/fourslash/navigationBarItemsMissingName1.ts @@ -3,26 +3,31 @@ //// foo() {} ////} -verify.navigationBar([ - { - "text": "\"navigationBarItemsMissingName1\"", - "kind": "module", - "childItems": [ - { - "text": "C", - "kind": "class" - } - ] - }, - { +verify.navigationBar( [ + { + "text": "\"navigationBarItemsMissingName1\"", + "kind": "module", + "childItems": [ + { + "text": "", + "kind": "function", + "kindModifiers": "export" + }, + { "text": "C", - "kind": "class", - "childItems": [ - { - "text": "foo", - "kind": "method" - } - ], - "indent": 1 - } + "kind": "class" + } + ] + }, + { + "text": "C", + "kind": "class", + "childItems": [ + { + "text": "foo", + "kind": "method" + } + ], + "indent": 1 + } ]); diff --git a/tests/cases/fourslash/navigationBarItemsMissingName2.ts b/tests/cases/fourslash/navigationBarItemsMissingName2.ts index 2eda3b07855c7..c39185f9dd2d9 100644 --- a/tests/cases/fourslash/navigationBarItemsMissingName2.ts +++ b/tests/cases/fourslash/navigationBarItemsMissingName2.ts @@ -7,19 +7,25 @@ // Anonymous classes are still included. verify.navigationBar([ - { - "text": "", - "kind": "module" - }, - { - "text": "default", - "kind": "class", - "childItems": [ - { - "text": "foo", - "kind": "method" - } - ], - "indent": 1 - } + { + "text": "", + "kind": "module", + "childItems": [ + { + "text": "", + "kind": "class" + } + ] + }, + { + "text": "", + "kind": "class", + "childItems": [ + { + "text": "foo", + "kind": "method" + } + ], + "indent": 1 + } ]);