From 236e24b4683100012bb724a6b32d7b4d032cbc03 Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Wed, 6 Aug 2014 13:39:09 -0700 Subject: [PATCH] do not reorder signatures from derived and base types --- src/compiler/checker.ts | 27 +++++++++-- ...nheritedOverloadedSpecializedSignatures.js | 47 +++++++++++++++++++ ...nheritedOverloadedSpecializedSignatures.ts | 36 ++++++++++++++ 3 files changed, 106 insertions(+), 4 deletions(-) create mode 100644 tests/baselines/reference/inheritedOverloadedSpecializedSignatures.js create mode 100644 tests/cases/compiler/inheritedOverloadedSpecializedSignatures.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 465db55542..c48a417f9b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3793,21 +3793,40 @@ module ts { } // The candidate list orders groups in reverse, but within a group signatures are kept in declaration order + // A nit here is that we reorder only signatures that belong to the same symbol, + // so order how inherited signatures are processed is still preserved. + // interface A { (x: string): void } + // interface B { (x: 'foo'): string } + // var b: B; + // b('foo') // <- here overloads should be processed as [(x:'foo'): string, (x: string): void] function collectCandidates(node: CallExpression, signatures: Signature[]): Signature[]{ var result: Signature[] = []; var lastParent: Node; + var lastSymbol: Symbol; + var cutoffPos: number = 0; var pos: number; for (var i = 0; i < signatures.length; i++) { var signature = signatures[i]; if (isCandidateSignature(node, signature)) { - var parent = signature.declaration ? signature.declaration.parent : undefined; - if (lastParent && parent === lastParent) { - pos++; + var symbol = signature.declaration && getSymbolOfNode(signature.declaration); + var parent = signature.declaration && signature.declaration.parent; + if (!lastSymbol || symbol === lastSymbol) { + if (lastParent && parent === lastParent) { + pos++; + } + else { + lastParent = parent; + pos = cutoffPos; + } } else { + // current declaration belongs to a different symbol + // set cutoffPos so reorderings in the future won't change result set from 0 to cutoffPos + pos = cutoffPos = result.length; lastParent = parent; - pos = 0; } + lastSymbol = symbol; + for (var j = result.length; j > pos; j--) { result[j] = result[j - 1]; } diff --git a/tests/baselines/reference/inheritedOverloadedSpecializedSignatures.js b/tests/baselines/reference/inheritedOverloadedSpecializedSignatures.js new file mode 100644 index 0000000000..54089541fd --- /dev/null +++ b/tests/baselines/reference/inheritedOverloadedSpecializedSignatures.js @@ -0,0 +1,47 @@ +//// [inheritedOverloadedSpecializedSignatures.ts] +interface A { + (key:string):void; +} + +interface B extends A { + (key:'foo'):string; +} + +var b:B; +// Should not error +b('foo').charAt(0); + +interface A { + (x: 'A1'): string; + (x: string): void; +} + +interface B extends A { + (x: 'B1'): number; +} + +interface A { + (x: 'A2'): boolean; +} + +interface B { + (x: 'B2'): string[]; +} + +var b: B; +// non of these lines should error +var x1: string[] = b('B2'); +var x2: number = b('B1'); +var x3: boolean = b('A2'); +var x4: string = b('A1'); +var x5: void = b('A0'); + +//// [inheritedOverloadedSpecializedSignatures.js] +var b; +b('foo').charAt(0); +var b; +var x1 = b('B2'); +var x2 = b('B1'); +var x3 = b('A2'); +var x4 = b('A1'); +var x5 = b('A0'); diff --git a/tests/cases/compiler/inheritedOverloadedSpecializedSignatures.ts b/tests/cases/compiler/inheritedOverloadedSpecializedSignatures.ts new file mode 100644 index 0000000000..c513cecb2c --- /dev/null +++ b/tests/cases/compiler/inheritedOverloadedSpecializedSignatures.ts @@ -0,0 +1,36 @@ +interface A { + (key:string):void; +} + +interface B extends A { + (key:'foo'):string; +} + +var b:B; +// Should not error +b('foo').charAt(0); + +interface A { + (x: 'A1'): string; + (x: string): void; +} + +interface B extends A { + (x: 'B1'): number; +} + +interface A { + (x: 'A2'): boolean; +} + +interface B { + (x: 'B2'): string[]; +} + +var b: B; +// non of these lines should error +var x1: string[] = b('B2'); +var x2: number = b('B1'); +var x3: boolean = b('A2'); +var x4: string = b('A1'); +var x5: void = b('A0'); \ No newline at end of file