diff --git a/src/services/services.ts b/src/services/services.ts index b2f7eb4bdbaaf..578e0166defee 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -904,6 +904,7 @@ namespace ts { function visit(node: Node): void { switch (node.kind) { case SyntaxKind.FunctionDeclaration: + case SyntaxKind.FunctionExpression: case SyntaxKind.MethodDeclaration: case SyntaxKind.MethodSignature: const functionDeclaration = node; @@ -930,6 +931,7 @@ namespace ts { break; case SyntaxKind.ClassDeclaration: + case SyntaxKind.ClassExpression: case SyntaxKind.InterfaceDeclaration: case SyntaxKind.TypeAliasDeclaration: case SyntaxKind.EnumDeclaration: @@ -944,22 +946,9 @@ namespace ts { case SyntaxKind.SetAccessor: case SyntaxKind.TypeLiteral: addDeclaration(node); - // fall through - case SyntaxKind.Constructor: - case SyntaxKind.VariableStatement: - case SyntaxKind.VariableDeclarationList: - case SyntaxKind.ObjectBindingPattern: - case SyntaxKind.ArrayBindingPattern: - case SyntaxKind.ModuleBlock: forEachChild(node, visit); break; - case SyntaxKind.Block: - if (isFunctionBlock(node)) { - forEachChild(node, visit); - } - break; - case SyntaxKind.Parameter: // Only consider parameter properties if (!(node.flags & NodeFlags.ParameterPropertyModifier)) { @@ -967,11 +956,15 @@ namespace ts { } // fall through case SyntaxKind.VariableDeclaration: - case SyntaxKind.BindingElement: - if (isBindingPattern((node).name)) { - forEachChild((node).name, visit); + case SyntaxKind.BindingElement: { + const decl = node; + if (isBindingPattern(decl.name)) { + forEachChild(decl.name, visit); break; } + if (decl.initializer) + visit(decl.initializer); + } case SyntaxKind.EnumMember: case SyntaxKind.PropertyDeclaration: case SyntaxKind.PropertySignature: @@ -1008,6 +1001,9 @@ namespace ts { } } break; + + default: + forEachChild(node, visit); } } } @@ -2770,7 +2766,9 @@ namespace ts { /* @internal */ export function getNodeKind(node: Node): string { switch (node.kind) { case SyntaxKind.ModuleDeclaration: return ScriptElementKind.moduleElement; - case SyntaxKind.ClassDeclaration: return ScriptElementKind.classElement; + case SyntaxKind.ClassDeclaration: + case SyntaxKind.ClassExpression: + return ScriptElementKind.classElement; case SyntaxKind.InterfaceDeclaration: return ScriptElementKind.interfaceElement; case SyntaxKind.TypeAliasDeclaration: return ScriptElementKind.typeElement; case SyntaxKind.EnumDeclaration: return ScriptElementKind.enumElement; @@ -2780,7 +2778,9 @@ namespace ts { : isLet(node) ? ScriptElementKind.letElement : ScriptElementKind.variableElement; - case SyntaxKind.FunctionDeclaration: return ScriptElementKind.functionElement; + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.FunctionExpression: + return ScriptElementKind.functionElement; case SyntaxKind.GetAccessor: return ScriptElementKind.memberGetAccessorElement; case SyntaxKind.SetAccessor: return ScriptElementKind.memberSetAccessorElement; case SyntaxKind.MethodDeclaration: diff --git a/tests/cases/fourslash/declarationExpressions.ts b/tests/cases/fourslash/declarationExpressions.ts new file mode 100644 index 0000000000000..7f2a64d8ecfb6 --- /dev/null +++ b/tests/cases/fourslash/declarationExpressions.ts @@ -0,0 +1,30 @@ +/// + +////class A {} +////const B = class C { +//// public x; +////}; +////function D() {} +////const E = function F() {} +////console.log(function() {}, class {}); // Expression with no name should have no effect. +////console.log(function inner() {}); +////String(function fun() { class cls { public prop; } })); + +function navExact(name: string, kind: string) { + verify.navigationItemsListContains(name, kind, name, "exact"); +} + +navExact("A", "class"); +navExact("B", "const"); +navExact("C", "class"); +navExact("x", "property"); + +navExact("D", "function"); +navExact("E", "const"); +navExact("F", "function") + +navExact("inner", "function"); + +navExact("fun", "function"); +navExact("cls", "class"); +navExact("prop", "property");