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).
This commit is contained in:
Daniel Rosenwasser 2014-10-03 15:53:35 -07:00
parent 782275924f
commit 4069e0a0d0
3 changed files with 43 additions and 20 deletions

View File

@ -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 = <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 && !(<FunctionDeclaration>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(<Declaration>node);
}
// fall through
case SyntaxKind.Constructor:
case SyntaxKind.VariableStatement:
case SyntaxKind.ModuleBlock:
case SyntaxKind.FunctionBlock:
@ -560,9 +563,6 @@ module ts {
namedDeclarations.push(<Declaration>node);
break;
}
// do not go any deeper
return undefined;
});
this.namedDeclarations = namedDeclarations;

View File

@ -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");
verify.navigationItemsListCount(4, "overload", "prefix");

View File

@ -0,0 +1,23 @@
/// <reference path="fourslash.ts"/>
////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");