diff --git a/src/services/services.ts b/src/services/services.ts index a7a3b43afd1..11a84a42635 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -504,28 +504,31 @@ module ts { if (!this.namedDeclarations) { var sourceFile = this; var namedDeclarations: Declaration[] = []; - - // This keeps track of the last encountered function/method/method signature - // so that we may ignore all but the first overload. - var overloadDeclaration: FunctionDeclaration; - 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; - // We can assume that overloadDeclaration will never be "trampled" - // between consecutive overloads because we never dive into parameter initializers. - if (functionDeclaration.name) { - if (overloadDeclaration && - functionDeclaration.name.text === overloadDeclaration.name.text && - node.parent === overloadDeclaration.parent) { - break; + 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); } - namedDeclarations.push(functionDeclaration); - overloadDeclaration = functionDeclaration; + forEachChild(node, visit); } break; @@ -534,7 +537,6 @@ module ts { case SyntaxKind.EnumDeclaration: case SyntaxKind.ModuleDeclaration: case SyntaxKind.ImportDeclaration: - case SyntaxKind.Constructor: case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: case SyntaxKind.TypeLiteral: @@ -542,6 +544,7 @@ module ts { namedDeclarations.push(node); } // fall through + case SyntaxKind.Constructor: case SyntaxKind.VariableStatement: case SyntaxKind.ModuleBlock: case SyntaxKind.FunctionBlock: @@ -560,9 +563,6 @@ module ts { namedDeclarations.push(node); break; } - - // do not go any deeper - return undefined; }); this.namedDeclarations = namedDeclarations; diff --git a/tests/cases/fourslash/navigationItemsOverloadsBroken.ts b/tests/cases/fourslash/navigationItemsOverloadsBroken1.ts similarity index 88% rename from tests/cases/fourslash/navigationItemsOverloadsBroken.ts rename to tests/cases/fourslash/navigationItemsOverloadsBroken1.ts index f9501948272..7b8ebc9181f 100644 --- a/tests/cases/fourslash/navigationItemsOverloadsBroken.ts +++ b/tests/cases/fourslash/navigationItemsOverloadsBroken1.ts @@ -24,6 +24,6 @@ //// throw overload; ////} -verify.navigationItemsListCount(1, "overload1", "exact"); +verify.navigationItemsListCount(2, "overload1", "exact"); verify.navigationItemsListCount(2, "overload2", "exact"); -verify.navigationItemsListCount(3, "overload", "prefix"); \ No newline at end of file +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 00000000000..c1f6ccae2f5 --- /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