Skip to content

Commit a497918

Browse files
committed
Additional test cases and better nameing for object patterns and elisions
1 parent dcb41db commit a497918

8 files changed

+7030
-40
lines changed

src/compiler/checker.ts

Lines changed: 60 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -13620,7 +13620,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1362013620
function getUniqAssociatedNamesFromTupleType(type: TupleTypeReference, restSymbol: Symbol) {
1362113621
const associatedNamesMap = new Map<__String, number>();
1362213622
return map(type.target.labeledElementDeclarations, (labeledElement, i) => {
13623-
const name = getTupleElementLabel(labeledElement, i, restSymbol);
13623+
const name = getTupleElementLabel(labeledElement, i, type.target.elementFlags[i], restSymbol);
1362413624
const prevCounter = associatedNamesMap.get(name);
1362513625
if (prevCounter === undefined) {
1362613626
associatedNamesMap.set(name, 1);
@@ -37268,35 +37268,71 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3726837268

3726937269
/**
3727037270
* Gets a tuple element label by recursively walking `ArrayBindingPattern` nodes in a `BindingName`.
37271+
* @param node The source node from which to derive a label
37272+
* @param index The index into the tuple
37273+
* @param elementFlags The {@see ElementFlags} of the tuple element
3727137274
*/
37272-
function getTupleElementLabelFromBindingName(node: BindingName, index: number): __String | undefined {
37273-
if (isArrayBindingPattern(node)) {
37274-
const elements = node.elements;
37275-
const lastElement = tryCast(lastOrUndefined(elements), isBindingElement);
37276-
const elementCount = elements.length - (lastElement?.dotDotDotToken ? 1 : 0);
37277-
if (index < elementCount) {
37278-
const element = elements[index];
37279-
if (isBindingElement(element) && isIdentifier(element.name)) {
37280-
return element.name.escapedText;
37275+
function getTupleElementLabelFromBindingElement(node: BindingElement | ParameterDeclaration, index: number, elementFlags: ElementFlags): __String {
37276+
switch (node.name.kind) {
37277+
case SyntaxKind.Identifier: {
37278+
const name = node.name.escapedText;
37279+
if (node.dotDotDotToken) {
37280+
// given
37281+
// (...[x, y, ...z]: [number, number, ...number[]]) => ...
37282+
// this produces
37283+
// (x: number, y: number, ...z: number[]) => ...
37284+
// which preserves rest elements of 'z'
37285+
37286+
// given
37287+
// (...[x, y, ...z]: [number, number, ...[...number[], number]]) => ...
37288+
// this produces
37289+
// (x: number, y: number, ...z: number[], z_1: number) => ...
37290+
// which preserves rest elements of z but gives distinct numbers to fixed elements of 'z'
37291+
return elementFlags & ElementFlags.Variable ? name : `${name}_${index}` as __String;
37292+
}
37293+
else {
37294+
// given
37295+
// (...[x]: [number]) => ...
37296+
// this produces
37297+
// (x: number) => ...
37298+
// which preserves fixed elements of 'x'
37299+
37300+
// given
37301+
// (...[x]: ...number[]) => ...
37302+
// this produces
37303+
// (x_0: number) => ...
37304+
// which which numbers fixed elements of 'x' whose tuple element type is variable
37305+
return elementFlags & ElementFlags.Fixed ? name : `${name}_n` as __String;
3728137306
}
3728237307
}
37283-
else if (lastElement?.dotDotDotToken) {
37284-
const restIndex = index - elementCount;
37285-
return getTupleElementLabelFromBindingName(lastElement.name, restIndex);
37308+
case SyntaxKind.ArrayBindingPattern: {
37309+
if (node.dotDotDotToken) {
37310+
const elements = node.name.elements;
37311+
const lastElement = tryCast(lastOrUndefined(elements), isBindingElement);
37312+
const elementCount = elements.length - (lastElement?.dotDotDotToken ? 1 : 0);
37313+
if (index < elementCount) {
37314+
const element = elements[index];
37315+
if (isBindingElement(element)) {
37316+
return getTupleElementLabelFromBindingElement(element, index, elementFlags);
37317+
}
37318+
}
37319+
else if (lastElement?.dotDotDotToken) {
37320+
return getTupleElementLabelFromBindingElement(lastElement, index - elementCount, elementFlags);
37321+
}
37322+
}
37323+
break;
3728637324
}
3728737325
}
37288-
else if (isIdentifier(node)) {
37289-
return `${node.escapedText}_${index}` as __String;
37290-
}
37326+
return `arg_${index}` as __String;
3729137327
}
3729237328

3729337329
function getTupleElementLabel(d: ParameterDeclaration | NamedTupleMember): __String;
37294-
function getTupleElementLabel(d: ParameterDeclaration | NamedTupleMember | undefined, index: number, restSymbol?: Symbol): __String;
37295-
function getTupleElementLabel(d: ParameterDeclaration | NamedTupleMember | undefined, index = 0, restSymbol?: Symbol) {
37330+
function getTupleElementLabel(d: ParameterDeclaration | NamedTupleMember | undefined, index: number, elementFlags: ElementFlags, restSymbol?: Symbol): __String;
37331+
function getTupleElementLabel(d: ParameterDeclaration | NamedTupleMember | undefined, index = 0, elementFlags = ElementFlags.Fixed, restSymbol?: Symbol) {
3729637332
if (!d) {
3729737333
const restParameter = tryCast(restSymbol?.valueDeclaration, isParameter);
37298-
const label = restParameter && getTupleElementLabelFromBindingName(restParameter.name, index);
37299-
return label ?? `${restSymbol?.escapedName ?? "arg"}_${index}` as __String;
37334+
return restParameter ? getTupleElementLabelFromBindingElement(restParameter, index, elementFlags) :
37335+
`${restSymbol?.escapedName ?? "arg"}_${index}` as __String;
3730037336
}
3730137337
Debug.assert(isIdentifier(d.name)); // Parameter declarations could be binding patterns, but we only allow identifier names
3730237338
return d.name.escapedText;
@@ -37310,9 +37346,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3731037346
const restParameter = signature.parameters[paramCount] || unknownSymbol;
3731137347
const restType = overrideRestType || getTypeOfSymbol(restParameter);
3731237348
if (isTupleType(restType)) {
37313-
const associatedNames = ((restType as TypeReference).target as TupleType).labeledElementDeclarations;
37349+
const tupleType = ((restType as TypeReference).target as TupleType);
3731437350
const index = pos - paramCount;
37315-
return getTupleElementLabel(associatedNames?.[index], index, restParameter);
37351+
const associatedName = tupleType.labeledElementDeclarations?.[index];
37352+
const elementFlags = tupleType.elementFlags[index];
37353+
return getTupleElementLabel(associatedName, index, elementFlags, restParameter);
3731637354
}
3731737355
return restParameter.escapedName;
3731837356
}

tests/baselines/reference/iterableArrayPattern14.types

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,8 @@ class FooIterator {
5959
}
6060

6161
function fun(...[a, ...b]) { }
62-
>fun : (a: any, ...b_0: any[]) => void
63-
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
62+
>fun : (a: any, ...b: any[]) => void
63+
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6464
>a : any
6565
> : ^^^
6666
>b : any[]
@@ -69,8 +69,8 @@ function fun(...[a, ...b]) { }
6969
fun(new FooIterator);
7070
>fun(new FooIterator) : void
7171
> : ^^^^
72-
>fun : (a: any, ...b_0: any[]) => void
73-
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
72+
>fun : (a: any, ...b: any[]) => void
73+
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
7474
>new FooIterator : FooIterator
7575
> : ^^^^^^^^^^^
7676
>FooIterator : typeof FooIterator

tests/baselines/reference/iterableArrayPattern25.types

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
=== iterableArrayPattern25.ts ===
44
function takeFirstTwoEntries(...[[k1, v1], [k2, v2]]) { }
5-
>takeFirstTwoEntries : (__0_0: [any, any], __0_1: [any, any]) => void
5+
>takeFirstTwoEntries : (arg_0: [any, any], arg_1: [any, any]) => void
66
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
77
>k1 : any
88
> : ^^^
@@ -16,7 +16,7 @@ function takeFirstTwoEntries(...[[k1, v1], [k2, v2]]) { }
1616
takeFirstTwoEntries(new Map([["", 0], ["hello", 1]]));
1717
>takeFirstTwoEntries(new Map([["", 0], ["hello", 1]])) : void
1818
> : ^^^^
19-
>takeFirstTwoEntries : (__0_0: [any, any], __0_1: [any, any]) => void
19+
>takeFirstTwoEntries : (arg_0: [any, any], arg_1: [any, any]) => void
2020
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2121
>new Map([["", 0], ["hello", 1]]) : Map<string, number>
2222
> : ^^^^^^^^^^^^^^^^^^^

tests/baselines/reference/restParameterWithBindingPattern3.types

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ function b(...[...foo = []]: string[]) { }
2222
> : ^^^^^^^^^^^
2323

2424
function c(...{0: a, length, 3: d}: [boolean, string, number]) { }
25-
>c : (__0_0: boolean, __0_1: string, __0_2: number) => void
25+
>c : (arg_0: boolean, arg_1: string, arg_2: number) => void
2626
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2727
>a : boolean
2828
> : ^^^^^^^
@@ -32,7 +32,7 @@ function c(...{0: a, length, 3: d}: [boolean, string, number]) { }
3232
> : ^^^^^^^^^
3333

3434
function d(...[a, , , d]: [boolean, string, number]) { }
35-
>d : (a: boolean, __0_1: string, __0_2: number) => void
35+
>d : (a: boolean, arg_1: string, arg_2: number) => void
3636
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3737
>a : boolean
3838
> : ^^^^^^^
@@ -44,7 +44,7 @@ function d(...[a, , , d]: [boolean, string, number]) { }
4444
> : ^^^^^^^^^
4545

4646
function e(...{0: a = 1, 1: b = true, ...rest: rest}: [boolean, string, number]) { }
47-
>e : (__0_0: boolean, __0_1: string, __0_2: number) => void
47+
>e : (arg_0: boolean, arg_1: string, arg_2: number) => void
4848
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4949
>a : boolean
5050
> : ^^^^^^^

0 commit comments

Comments
 (0)