fix(53011): Illegal declaration file can be emitted (duplicate parameter names) when spreading tuples into parameter positions (#53028)

This commit is contained in:
Oleksandr T
2023-03-09 19:47:49 +02:00
committed by GitHub
parent d681520a14
commit 2ab9e7edd9
5 changed files with 160 additions and 3 deletions

View File

@@ -12644,11 +12644,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
function expandSignatureParametersWithTupleMembers(restType: TupleTypeReference, restIndex: number) {
const elementTypes = getTypeArguments(restType);
const associatedNames = restType.target.labeledElementDeclarations;
const associatedNames = getUniqAssociatedNamesFromTupleType(restType);
const restParams = map(elementTypes, (t, i) => {
// Lookup the label from the individual tuple passed in before falling back to the signature `rest` parameter name
const tupleLabelName = !!associatedNames && getTupleElementLabel(associatedNames[i]);
const name = tupleLabelName || getParameterNameAtPosition(sig, restIndex + i, restType);
const name = associatedNames && associatedNames[i] ? associatedNames[i] :
getParameterNameAtPosition(sig, restIndex + i, restType);
const flags = restType.target.elementFlags[i];
const checkFlags = flags & ElementFlags.Variable ? CheckFlags.RestParameter :
flags & ElementFlags.Optional ? CheckFlags.OptionalParameter : 0;
@@ -12658,6 +12658,22 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
});
return concatenate(sig.parameters.slice(0, restIndex), restParams);
}
function getUniqAssociatedNamesFromTupleType(type: TupleTypeReference) {
const associatedNamesMap = new Map<__String, number>();
return map(type.target.labeledElementDeclarations, labeledElement => {
const name = getTupleElementLabel(labeledElement);
const prevCounter = associatedNamesMap.get(name);
if (prevCounter === undefined) {
associatedNamesMap.set(name, 1);
return name;
}
else {
associatedNamesMap.set(name, prevCounter + 1);
return `${name}_${prevCounter}` as __String;
}
});
}
}
function getDefaultConstructSignatures(classType: InterfaceType): Signature[] {

View File

@@ -0,0 +1,40 @@
//// [spreadParameterTupleType.ts]
function f1() {
type A = [s: string];
type C = [...A, ...A];
return function fn(...args: C) { }
}
function f2() {
type A = [a: string];
type B = [b: string];
type C = [c: string];
type D = [...A, ...A, ...B, ...A, ...B, ...B, ...A, ...C];
return function fn(...args: D) { }
}
//// [spreadParameterTupleType.js]
function f1() {
return function fn() {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
};
}
function f2() {
return function fn() {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
};
}
//// [spreadParameterTupleType.d.ts]
declare function f1(): (s: string, s_1: string) => void;
declare function f2(): (a: string, a_1: string, b: string, a_2: string, b_1: string, b_2: string, a_3: string, c: string) => void;

View File

@@ -0,0 +1,47 @@
=== tests/cases/compiler/spreadParameterTupleType.ts ===
function f1() {
>f1 : Symbol(f1, Decl(spreadParameterTupleType.ts, 0, 0))
type A = [s: string];
>A : Symbol(A, Decl(spreadParameterTupleType.ts, 0, 15))
type C = [...A, ...A];
>C : Symbol(C, Decl(spreadParameterTupleType.ts, 1, 25))
>A : Symbol(A, Decl(spreadParameterTupleType.ts, 0, 15))
>A : Symbol(A, Decl(spreadParameterTupleType.ts, 0, 15))
return function fn(...args: C) { }
>fn : Symbol(fn, Decl(spreadParameterTupleType.ts, 4, 10))
>args : Symbol(args, Decl(spreadParameterTupleType.ts, 4, 23))
>C : Symbol(C, Decl(spreadParameterTupleType.ts, 1, 25))
}
function f2() {
>f2 : Symbol(f2, Decl(spreadParameterTupleType.ts, 5, 1))
type A = [a: string];
>A : Symbol(A, Decl(spreadParameterTupleType.ts, 7, 15))
type B = [b: string];
>B : Symbol(B, Decl(spreadParameterTupleType.ts, 8, 25))
type C = [c: string];
>C : Symbol(C, Decl(spreadParameterTupleType.ts, 9, 25))
type D = [...A, ...A, ...B, ...A, ...B, ...B, ...A, ...C];
>D : Symbol(D, Decl(spreadParameterTupleType.ts, 10, 25))
>A : Symbol(A, Decl(spreadParameterTupleType.ts, 7, 15))
>A : Symbol(A, Decl(spreadParameterTupleType.ts, 7, 15))
>B : Symbol(B, Decl(spreadParameterTupleType.ts, 8, 25))
>A : Symbol(A, Decl(spreadParameterTupleType.ts, 7, 15))
>B : Symbol(B, Decl(spreadParameterTupleType.ts, 8, 25))
>B : Symbol(B, Decl(spreadParameterTupleType.ts, 8, 25))
>A : Symbol(A, Decl(spreadParameterTupleType.ts, 7, 15))
>C : Symbol(C, Decl(spreadParameterTupleType.ts, 9, 25))
return function fn(...args: D) { }
>fn : Symbol(fn, Decl(spreadParameterTupleType.ts, 13, 10))
>args : Symbol(args, Decl(spreadParameterTupleType.ts, 13, 23))
>D : Symbol(D, Decl(spreadParameterTupleType.ts, 10, 25))
}

View File

@@ -0,0 +1,37 @@
=== tests/cases/compiler/spreadParameterTupleType.ts ===
function f1() {
>f1 : () => (s: string, s_1: string) => void
type A = [s: string];
>A : [s: string]
type C = [...A, ...A];
>C : [s: string, s: string]
return function fn(...args: C) { }
>function fn(...args: C) { } : (s: string, s_1: string) => void
>fn : (s: string, s_1: string) => void
>args : [s: string, s: string]
}
function f2() {
>f2 : () => (a: string, a_1: string, b: string, a_2: string, b_1: string, b_2: string, a_3: string, c: string) => void
type A = [a: string];
>A : [a: string]
type B = [b: string];
>B : [b: string]
type C = [c: string];
>C : [c: string]
type D = [...A, ...A, ...B, ...A, ...B, ...B, ...A, ...C];
>D : [a: string, a: string, b: string, a: string, b: string, b: string, a: string, c: string]
return function fn(...args: D) { }
>function fn(...args: D) { } : (a: string, a_1: string, b: string, a_2: string, b_1: string, b_2: string, a_3: string, c: string) => void
>fn : (a: string, a_1: string, b: string, a_2: string, b_1: string, b_2: string, a_3: string, c: string) => void
>args : [a: string, a: string, b: string, a: string, b: string, b: string, a: string, c: string]
}

View File

@@ -0,0 +1,17 @@
// @declaration: true
function f1() {
type A = [s: string];
type C = [...A, ...A];
return function fn(...args: C) { }
}
function f2() {
type A = [a: string];
type B = [b: string];
type C = [c: string];
type D = [...A, ...A, ...B, ...A, ...B, ...B, ...A, ...C];
return function fn(...args: D) { }
}