diff --git a/src/services/services.ts b/src/services/services.ts index a35c12139562b..11a84a42635e2 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -504,27 +504,47 @@ module ts { if (!this.namedDeclarations) { var sourceFile = this; var namedDeclarations: Declaration[] = []; - var isExternalModule = ts.isExternalModule(sourceFile); - forEachChild(sourceFile, function visit(node: Node): boolean { + forEachChild(sourceFile, function visit(node: Node): void { switch (node.kind) { + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.Method: + var functionDeclaration = node; + + if (functionDeclaration.name && functionDeclaration.name.kind !== SyntaxKind.Missing) { + var lastDeclaration = namedDeclarations.length > 0 ? + namedDeclarations[namedDeclarations.length - 1] : + undefined; + + // Check whether this declaration belongs to an "overload group". + if (lastDeclaration && functionDeclaration.symbol === lastDeclaration.symbol) { + // Overwrite the last declaration if it was an overload + // and this one is an implementation. + if (functionDeclaration.body && !(lastDeclaration).body) { + namedDeclarations[namedDeclarations.length - 1] = functionDeclaration; + } + } + else { + namedDeclarations.push(node); + } + + forEachChild(node, visit); + } + break; + case SyntaxKind.ClassDeclaration: case SyntaxKind.InterfaceDeclaration: case SyntaxKind.EnumDeclaration: case SyntaxKind.ModuleDeclaration: case SyntaxKind.ImportDeclaration: - case SyntaxKind.Method: - case SyntaxKind.FunctionDeclaration: - case SyntaxKind.Constructor: case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: case SyntaxKind.TypeLiteral: if ((node).name) { namedDeclarations.push(node); } - forEachChild(node, visit); - break; - + // fall through + case SyntaxKind.Constructor: case SyntaxKind.VariableStatement: case SyntaxKind.ModuleBlock: case SyntaxKind.FunctionBlock: @@ -532,19 +552,17 @@ module ts { break; case SyntaxKind.Parameter: + // Only consider properties defined as constructor parameters if (!(node.flags & NodeFlags.AccessibilityModifier)) { - // Only consider properties defined as constructor parameters break; } + // fall through case SyntaxKind.VariableDeclaration: case SyntaxKind.EnumMember: case SyntaxKind.Property: namedDeclarations.push(node); break; } - - // do not go any deeper - return undefined; }); this.namedDeclarations = namedDeclarations; diff --git a/tests/cases/fourslash/navigationItemsOverloads1.ts b/tests/cases/fourslash/navigationItemsOverloads1.ts new file mode 100644 index 0000000000000..5f1981fe917d3 --- /dev/null +++ b/tests/cases/fourslash/navigationItemsOverloads1.ts @@ -0,0 +1,30 @@ +/// + +////function overload(a: string): boolean; +////function overload(b: boolean): boolean; +////function overload(b: number): boolean; +////function overload(f: typeof overload): boolean; +////function overload(x: any, b = (function overload() { return false })): boolean { +//// throw overload; +////} +//// +////interface I { +//// interfaceMethodSignature(a: string): boolean; +//// interfaceMethodSignature(b: boolean): boolean; +//// interfaceMethodSignature(b: number): boolean; +//// interfaceMethodSignature(f: I): boolean; +////} +//// +////class C { +//// methodOverload(a: string): boolean; +//// methodOverload(b: boolean): boolean; +//// methodOverload(b: number): boolean; +//// methodOverload(f: I): boolean; +//// methodOverload(x: any, b = (function overload() { return false })): boolean { +//// throw C; +//// } +////} + +verify.navigationItemsListCount(1, "overload", "exact"); +verify.navigationItemsListCount(1, "interfaceMethodSignature", "exact"); +verify.navigationItemsListCount(1, "methodOverload", "exact"); diff --git a/tests/cases/fourslash/navigationItemsOverloads2.ts b/tests/cases/fourslash/navigationItemsOverloads2.ts new file mode 100644 index 0000000000000..c5824b639bcb3 --- /dev/null +++ b/tests/cases/fourslash/navigationItemsOverloads2.ts @@ -0,0 +1,12 @@ +/// + +////interface I { +//// interfaceMethodSignature(a: string): boolean; +//// interfaceMethodSignature(b: number): boolean; +//// interfaceMethodSignature(f: I): boolean; +////} +////interface I { +//// interfaceMethodSignature(b: boolean): boolean; +////} + +verify.navigationItemsListCount(2, "interfaceMethodSignature", "exact"); diff --git a/tests/cases/fourslash/navigationItemsOverloadsBroken1.ts b/tests/cases/fourslash/navigationItemsOverloadsBroken1.ts new file mode 100644 index 0000000000000..7b8ebc9181fc7 --- /dev/null +++ b/tests/cases/fourslash/navigationItemsOverloadsBroken1.ts @@ -0,0 +1,29 @@ +/// + +////function overload1(a: string): boolean; +////function overload1(b: boolean): boolean; +////function overload1(b: number): boolean; +//// +////var heyImNotInterruptingAnythingAmI = '?'; +//// +////function overload1(f: typeof overload): boolean; +////function overload1(x: any, b = (function overload() { return false })): boolean { +//// throw overload; +////} + +////function overload2(a: string): boolean; +////function overload2(b: boolean): boolean; +////function overload2(b: number): boolean; +//// +////function iJustRuinEverything(x: any, b = (function overload() { return false })): boolean { +//// throw overload; +////} +//// +////function overload2(f: typeof overload): boolean; +////function overload2(x: any, b = (function overload() { return false })): boolean { +//// throw overload; +////} + +verify.navigationItemsListCount(2, "overload1", "exact"); +verify.navigationItemsListCount(2, "overload2", "exact"); +verify.navigationItemsListCount(4, "overload", "prefix"); \ No newline at end of file diff --git a/tests/cases/fourslash/navigationItemsOverloadsBroken2.ts b/tests/cases/fourslash/navigationItemsOverloadsBroken2.ts new file mode 100644 index 0000000000000..c1f6ccae2f5f1 --- /dev/null +++ b/tests/cases/fourslash/navigationItemsOverloadsBroken2.ts @@ -0,0 +1,23 @@ +/// + +////function overload1(a: string): boolean; +////function overload1(b: boolean): boolean; +////function overload1(x: any, b = (function overload() { return false })): boolean { +//// throw overload1; +////} +////function overload1(b: number): boolean; +////function overload1(f: typeof overload): boolean; + +////function overload2(a: string): boolean; +////function overload2(b: boolean): boolean; +////function overload2(x: any, b = (function overload() { return false })): boolean { +//// function overload2(): boolean; +//// function overload2(x: any): boolean; +//// throw overload2; +////} +////function overload2(b: number): boolean; +////function overload2(f: typeof overload): boolean; + +verify.navigationItemsListCount(1, "overload1", "exact"); +verify.navigationItemsListCount(3, "overload2", "exact"); +verify.navigationItemsListCount(4, "overload", "prefix"); \ No newline at end of file