From 4069e0a0d00a1bed4654a9c252a895e8ae4b8bf2 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Fri, 3 Oct 2014 15:53:35 -0700 Subject: [PATCH] Finished up "overload collapsing" for navigate-to. Current semantics: - If an overload lacks an implementation, go to the first implementation. - If an overload has any implementation, go to the first one. - If there are any declarations between an implementation and any overload, this will split the series of overloads (note that this is invalid code). --- src/services/services.ts | 36 +++++++++---------- ....ts => navigationItemsOverloadsBroken1.ts} | 4 +-- .../navigationItemsOverloadsBroken2.ts | 23 ++++++++++++ 3 files changed, 43 insertions(+), 20 deletions(-) rename tests/cases/fourslash/{navigationItemsOverloadsBroken.ts => navigationItemsOverloadsBroken1.ts} (88%) create mode 100644 tests/cases/fourslash/navigationItemsOverloadsBroken2.ts 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