Issue 19220 function parameter arity (#24031)
* Added reference test case and diagnostics message * Adjusted arity checks to account for non-contiguous overloads * Code cleanup, baseline not yet commited * Accepted test baselines and minor implementation changes * Cleaned up baseline tracking the now renamed arity check test * Add range response when range contains only 2 values * Added recent baseline * Refined arity error messages when available overloads can be grouped * Rolled back code formatting * WIP cleanup needed in a few edge cases * Finished adding new more descriptive error messages * Code cleanup * Added simplified version of bugfix for #19220 * Rebased onto master * Removed whitespace after type assertion * Code review simplifications * Use correct diagnostic name * Code review changes and simplification of diagnostic message * Revert formatting changes
This commit is contained in:
parent
5f4a03c408
commit
66e9aaac18
|
@ -19052,24 +19052,40 @@ namespace ts {
|
|||
else if (args) {
|
||||
let min = Number.POSITIVE_INFINITY;
|
||||
let max = Number.NEGATIVE_INFINITY;
|
||||
let belowArgCount = Number.NEGATIVE_INFINITY;
|
||||
let aboveArgCount = Number.POSITIVE_INFINITY;
|
||||
|
||||
let argCount = args.length;
|
||||
for (const sig of signatures) {
|
||||
min = Math.min(min, getMinArgumentCount(sig));
|
||||
max = Math.max(max, getParameterCount(sig));
|
||||
const minCount = getMinArgumentCount(sig);
|
||||
const maxCount = getParameterCount(sig);
|
||||
if (minCount < argCount && minCount > belowArgCount) belowArgCount = minCount;
|
||||
if (argCount < maxCount && maxCount < aboveArgCount) aboveArgCount = maxCount;
|
||||
min = Math.min(min, minCount);
|
||||
max = Math.max(max, maxCount);
|
||||
}
|
||||
|
||||
const hasRestParameter = some(signatures, hasEffectiveRestParameter);
|
||||
const hasSpreadArgument = getSpreadArgumentIndex(args) > -1;
|
||||
const paramCount = hasRestParameter ? min :
|
||||
const paramRange = hasRestParameter ? min :
|
||||
min < max ? min + "-" + max :
|
||||
min;
|
||||
let argCount = args.length;
|
||||
const hasSpreadArgument = getSpreadArgumentIndex(args) > -1;
|
||||
if (argCount <= max && hasSpreadArgument) {
|
||||
argCount--;
|
||||
}
|
||||
const error = hasRestParameter && hasSpreadArgument ? Diagnostics.Expected_at_least_0_arguments_but_got_1_or_more :
|
||||
hasRestParameter ? Diagnostics.Expected_at_least_0_arguments_but_got_1 :
|
||||
hasSpreadArgument ? Diagnostics.Expected_0_arguments_but_got_1_or_more :
|
||||
Diagnostics.Expected_0_arguments_but_got_1;
|
||||
diagnostics.add(createDiagnosticForNode(node, error, paramCount, argCount));
|
||||
|
||||
if (hasRestParameter || hasSpreadArgument) {
|
||||
const error = hasRestParameter && hasSpreadArgument ? Diagnostics.Expected_at_least_0_arguments_but_got_1_or_more :
|
||||
hasRestParameter ? Diagnostics.Expected_at_least_0_arguments_but_got_1 :
|
||||
Diagnostics.Expected_0_arguments_but_got_1_or_more;
|
||||
diagnostics.add(createDiagnosticForNode(node, error, paramRange, argCount));
|
||||
}
|
||||
else if (min < argCount && argCount < max) {
|
||||
diagnostics.add(createDiagnosticForNode(node, Diagnostics.No_overload_expects_0_arguments_but_overloads_do_exist_that_expect_either_1_or_2_arguments, argCount, belowArgCount, aboveArgCount));
|
||||
}
|
||||
else {
|
||||
diagnostics.add(createDiagnosticForNode(node, Diagnostics.Expected_0_arguments_but_got_1, paramRange, argCount));
|
||||
}
|
||||
}
|
||||
else if (fallbackError) {
|
||||
diagnostics.add(createDiagnosticForNode(node, fallbackError));
|
||||
|
|
|
@ -2056,6 +2056,10 @@
|
|||
"category": "Error",
|
||||
"code": 2574
|
||||
},
|
||||
"No overload expects {0} arguments, but overloads do exist that expect either {1} or {2} arguments.": {
|
||||
"category": "Error",
|
||||
"code": 2575
|
||||
},
|
||||
"JSX element attributes type '{0}' may not be a union type.": {
|
||||
"category": "Error",
|
||||
"code": 2600
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
tests/cases/compiler/functionParameterArityMismatch.ts(3,1): error TS2554: Expected 1-3 arguments, but got 0.
|
||||
tests/cases/compiler/functionParameterArityMismatch.ts(4,1): error TS2575: No overload expects 2 arguments, but overloads do exist that expect either 1 or 3 arguments.
|
||||
tests/cases/compiler/functionParameterArityMismatch.ts(5,1): error TS2554: Expected 1-3 arguments, but got 4.
|
||||
tests/cases/compiler/functionParameterArityMismatch.ts(11,1): error TS2575: No overload expects 1 arguments, but overloads do exist that expect either 0 or 2 arguments.
|
||||
tests/cases/compiler/functionParameterArityMismatch.ts(12,1): error TS2575: No overload expects 3 arguments, but overloads do exist that expect either 2 or 4 arguments.
|
||||
tests/cases/compiler/functionParameterArityMismatch.ts(13,1): error TS2575: No overload expects 5 arguments, but overloads do exist that expect either 4 or 6 arguments.
|
||||
tests/cases/compiler/functionParameterArityMismatch.ts(14,1): error TS2554: Expected 0-6 arguments, but got 7.
|
||||
|
||||
|
||||
==== tests/cases/compiler/functionParameterArityMismatch.ts (7 errors) ====
|
||||
declare function f1(a: number);
|
||||
declare function f1(a: number, b: number, c: number);
|
||||
f1();
|
||||
~~~~
|
||||
!!! error TS2554: Expected 1-3 arguments, but got 0.
|
||||
f1(1, 2);
|
||||
~~~~~~~~
|
||||
!!! error TS2575: No overload expects 2 arguments, but overloads do exist that expect either 1 or 3 arguments.
|
||||
f1(1, 2, 3, 4);
|
||||
~~~~~~~~~~~~~~
|
||||
!!! error TS2554: Expected 1-3 arguments, but got 4.
|
||||
|
||||
declare function f2();
|
||||
declare function f2(a: number, b: number);
|
||||
declare function f2(a: number, b: number, c: number, d: number);
|
||||
declare function f2(a: number, b: number, c: number, d: number, e: number, f: number);
|
||||
f2(1);
|
||||
~~~~~
|
||||
!!! error TS2575: No overload expects 1 arguments, but overloads do exist that expect either 0 or 2 arguments.
|
||||
f2(1, 2, 3);
|
||||
~~~~~~~~~~~
|
||||
!!! error TS2575: No overload expects 3 arguments, but overloads do exist that expect either 2 or 4 arguments.
|
||||
f2(1, 2, 3, 4, 5);
|
||||
~~~~~~~~~~~~~~~~~
|
||||
!!! error TS2575: No overload expects 5 arguments, but overloads do exist that expect either 4 or 6 arguments.
|
||||
f2(1, 2, 3, 4, 5, 6, 7);
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
!!! error TS2554: Expected 0-6 arguments, but got 7.
|
||||
|
25
tests/baselines/reference/functionParameterArityMismatch.js
Normal file
25
tests/baselines/reference/functionParameterArityMismatch.js
Normal file
|
@ -0,0 +1,25 @@
|
|||
//// [functionParameterArityMismatch.ts]
|
||||
declare function f1(a: number);
|
||||
declare function f1(a: number, b: number, c: number);
|
||||
f1();
|
||||
f1(1, 2);
|
||||
f1(1, 2, 3, 4);
|
||||
|
||||
declare function f2();
|
||||
declare function f2(a: number, b: number);
|
||||
declare function f2(a: number, b: number, c: number, d: number);
|
||||
declare function f2(a: number, b: number, c: number, d: number, e: number, f: number);
|
||||
f2(1);
|
||||
f2(1, 2, 3);
|
||||
f2(1, 2, 3, 4, 5);
|
||||
f2(1, 2, 3, 4, 5, 6, 7);
|
||||
|
||||
|
||||
//// [functionParameterArityMismatch.js]
|
||||
f1();
|
||||
f1(1, 2);
|
||||
f1(1, 2, 3, 4);
|
||||
f2(1);
|
||||
f2(1, 2, 3);
|
||||
f2(1, 2, 3, 4, 5);
|
||||
f2(1, 2, 3, 4, 5, 6, 7);
|
|
@ -0,0 +1,56 @@
|
|||
=== tests/cases/compiler/functionParameterArityMismatch.ts ===
|
||||
declare function f1(a: number);
|
||||
>f1 : Symbol(f1, Decl(functionParameterArityMismatch.ts, 0, 0), Decl(functionParameterArityMismatch.ts, 0, 31))
|
||||
>a : Symbol(a, Decl(functionParameterArityMismatch.ts, 0, 20))
|
||||
|
||||
declare function f1(a: number, b: number, c: number);
|
||||
>f1 : Symbol(f1, Decl(functionParameterArityMismatch.ts, 0, 0), Decl(functionParameterArityMismatch.ts, 0, 31))
|
||||
>a : Symbol(a, Decl(functionParameterArityMismatch.ts, 1, 20))
|
||||
>b : Symbol(b, Decl(functionParameterArityMismatch.ts, 1, 30))
|
||||
>c : Symbol(c, Decl(functionParameterArityMismatch.ts, 1, 41))
|
||||
|
||||
f1();
|
||||
>f1 : Symbol(f1, Decl(functionParameterArityMismatch.ts, 0, 0), Decl(functionParameterArityMismatch.ts, 0, 31))
|
||||
|
||||
f1(1, 2);
|
||||
>f1 : Symbol(f1, Decl(functionParameterArityMismatch.ts, 0, 0), Decl(functionParameterArityMismatch.ts, 0, 31))
|
||||
|
||||
f1(1, 2, 3, 4);
|
||||
>f1 : Symbol(f1, Decl(functionParameterArityMismatch.ts, 0, 0), Decl(functionParameterArityMismatch.ts, 0, 31))
|
||||
|
||||
declare function f2();
|
||||
>f2 : Symbol(f2, Decl(functionParameterArityMismatch.ts, 4, 15), Decl(functionParameterArityMismatch.ts, 6, 22), Decl(functionParameterArityMismatch.ts, 7, 42), Decl(functionParameterArityMismatch.ts, 8, 64))
|
||||
|
||||
declare function f2(a: number, b: number);
|
||||
>f2 : Symbol(f2, Decl(functionParameterArityMismatch.ts, 4, 15), Decl(functionParameterArityMismatch.ts, 6, 22), Decl(functionParameterArityMismatch.ts, 7, 42), Decl(functionParameterArityMismatch.ts, 8, 64))
|
||||
>a : Symbol(a, Decl(functionParameterArityMismatch.ts, 7, 20))
|
||||
>b : Symbol(b, Decl(functionParameterArityMismatch.ts, 7, 30))
|
||||
|
||||
declare function f2(a: number, b: number, c: number, d: number);
|
||||
>f2 : Symbol(f2, Decl(functionParameterArityMismatch.ts, 4, 15), Decl(functionParameterArityMismatch.ts, 6, 22), Decl(functionParameterArityMismatch.ts, 7, 42), Decl(functionParameterArityMismatch.ts, 8, 64))
|
||||
>a : Symbol(a, Decl(functionParameterArityMismatch.ts, 8, 20))
|
||||
>b : Symbol(b, Decl(functionParameterArityMismatch.ts, 8, 30))
|
||||
>c : Symbol(c, Decl(functionParameterArityMismatch.ts, 8, 41))
|
||||
>d : Symbol(d, Decl(functionParameterArityMismatch.ts, 8, 52))
|
||||
|
||||
declare function f2(a: number, b: number, c: number, d: number, e: number, f: number);
|
||||
>f2 : Symbol(f2, Decl(functionParameterArityMismatch.ts, 4, 15), Decl(functionParameterArityMismatch.ts, 6, 22), Decl(functionParameterArityMismatch.ts, 7, 42), Decl(functionParameterArityMismatch.ts, 8, 64))
|
||||
>a : Symbol(a, Decl(functionParameterArityMismatch.ts, 9, 20))
|
||||
>b : Symbol(b, Decl(functionParameterArityMismatch.ts, 9, 30))
|
||||
>c : Symbol(c, Decl(functionParameterArityMismatch.ts, 9, 41))
|
||||
>d : Symbol(d, Decl(functionParameterArityMismatch.ts, 9, 52))
|
||||
>e : Symbol(e, Decl(functionParameterArityMismatch.ts, 9, 63))
|
||||
>f : Symbol(f, Decl(functionParameterArityMismatch.ts, 9, 74))
|
||||
|
||||
f2(1);
|
||||
>f2 : Symbol(f2, Decl(functionParameterArityMismatch.ts, 4, 15), Decl(functionParameterArityMismatch.ts, 6, 22), Decl(functionParameterArityMismatch.ts, 7, 42), Decl(functionParameterArityMismatch.ts, 8, 64))
|
||||
|
||||
f2(1, 2, 3);
|
||||
>f2 : Symbol(f2, Decl(functionParameterArityMismatch.ts, 4, 15), Decl(functionParameterArityMismatch.ts, 6, 22), Decl(functionParameterArityMismatch.ts, 7, 42), Decl(functionParameterArityMismatch.ts, 8, 64))
|
||||
|
||||
f2(1, 2, 3, 4, 5);
|
||||
>f2 : Symbol(f2, Decl(functionParameterArityMismatch.ts, 4, 15), Decl(functionParameterArityMismatch.ts, 6, 22), Decl(functionParameterArityMismatch.ts, 7, 42), Decl(functionParameterArityMismatch.ts, 8, 64))
|
||||
|
||||
f2(1, 2, 3, 4, 5, 6, 7);
|
||||
>f2 : Symbol(f2, Decl(functionParameterArityMismatch.ts, 4, 15), Decl(functionParameterArityMismatch.ts, 6, 22), Decl(functionParameterArityMismatch.ts, 7, 42), Decl(functionParameterArityMismatch.ts, 8, 64))
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
=== tests/cases/compiler/functionParameterArityMismatch.ts ===
|
||||
declare function f1(a: number);
|
||||
>f1 : { (a: number): any; (a: number, b: number, c: number): any; }
|
||||
>a : number
|
||||
|
||||
declare function f1(a: number, b: number, c: number);
|
||||
>f1 : { (a: number): any; (a: number, b: number, c: number): any; }
|
||||
>a : number
|
||||
>b : number
|
||||
>c : number
|
||||
|
||||
f1();
|
||||
>f1() : any
|
||||
>f1 : { (a: number): any; (a: number, b: number, c: number): any; }
|
||||
|
||||
f1(1, 2);
|
||||
>f1(1, 2) : any
|
||||
>f1 : { (a: number): any; (a: number, b: number, c: number): any; }
|
||||
>1 : 1
|
||||
>2 : 2
|
||||
|
||||
f1(1, 2, 3, 4);
|
||||
>f1(1, 2, 3, 4) : any
|
||||
>f1 : { (a: number): any; (a: number, b: number, c: number): any; }
|
||||
>1 : 1
|
||||
>2 : 2
|
||||
>3 : 3
|
||||
>4 : 4
|
||||
|
||||
declare function f2();
|
||||
>f2 : { (): any; (a: number, b: number): any; (a: number, b: number, c: number, d: number): any; (a: number, b: number, c: number, d: number, e: number, f: number): any; }
|
||||
|
||||
declare function f2(a: number, b: number);
|
||||
>f2 : { (): any; (a: number, b: number): any; (a: number, b: number, c: number, d: number): any; (a: number, b: number, c: number, d: number, e: number, f: number): any; }
|
||||
>a : number
|
||||
>b : number
|
||||
|
||||
declare function f2(a: number, b: number, c: number, d: number);
|
||||
>f2 : { (): any; (a: number, b: number): any; (a: number, b: number, c: number, d: number): any; (a: number, b: number, c: number, d: number, e: number, f: number): any; }
|
||||
>a : number
|
||||
>b : number
|
||||
>c : number
|
||||
>d : number
|
||||
|
||||
declare function f2(a: number, b: number, c: number, d: number, e: number, f: number);
|
||||
>f2 : { (): any; (a: number, b: number): any; (a: number, b: number, c: number, d: number): any; (a: number, b: number, c: number, d: number, e: number, f: number): any; }
|
||||
>a : number
|
||||
>b : number
|
||||
>c : number
|
||||
>d : number
|
||||
>e : number
|
||||
>f : number
|
||||
|
||||
f2(1);
|
||||
>f2(1) : any
|
||||
>f2 : { (): any; (a: number, b: number): any; (a: number, b: number, c: number, d: number): any; (a: number, b: number, c: number, d: number, e: number, f: number): any; }
|
||||
>1 : 1
|
||||
|
||||
f2(1, 2, 3);
|
||||
>f2(1, 2, 3) : any
|
||||
>f2 : { (): any; (a: number, b: number): any; (a: number, b: number, c: number, d: number): any; (a: number, b: number, c: number, d: number, e: number, f: number): any; }
|
||||
>1 : 1
|
||||
>2 : 2
|
||||
>3 : 3
|
||||
|
||||
f2(1, 2, 3, 4, 5);
|
||||
>f2(1, 2, 3, 4, 5) : any
|
||||
>f2 : { (): any; (a: number, b: number): any; (a: number, b: number, c: number, d: number): any; (a: number, b: number, c: number, d: number, e: number, f: number): any; }
|
||||
>1 : 1
|
||||
>2 : 2
|
||||
>3 : 3
|
||||
>4 : 4
|
||||
>5 : 5
|
||||
|
||||
f2(1, 2, 3, 4, 5, 6, 7);
|
||||
>f2(1, 2, 3, 4, 5, 6, 7) : any
|
||||
>f2 : { (): any; (a: number, b: number): any; (a: number, b: number, c: number, d: number): any; (a: number, b: number, c: number, d: number, e: number, f: number): any; }
|
||||
>1 : 1
|
||||
>2 : 2
|
||||
>3 : 3
|
||||
>4 : 4
|
||||
>5 : 5
|
||||
>6 : 6
|
||||
>7 : 7
|
||||
|
14
tests/cases/compiler/functionParameterArityMismatch.ts
Normal file
14
tests/cases/compiler/functionParameterArityMismatch.ts
Normal file
|
@ -0,0 +1,14 @@
|
|||
declare function f1(a: number);
|
||||
declare function f1(a: number, b: number, c: number);
|
||||
f1();
|
||||
f1(1, 2);
|
||||
f1(1, 2, 3, 4);
|
||||
|
||||
declare function f2();
|
||||
declare function f2(a: number, b: number);
|
||||
declare function f2(a: number, b: number, c: number, d: number);
|
||||
declare function f2(a: number, b: number, c: number, d: number, e: number, f: number);
|
||||
f2(1);
|
||||
f2(1, 2, 3);
|
||||
f2(1, 2, 3, 4, 5);
|
||||
f2(1, 2, 3, 4, 5, 6, 7);
|
Loading…
Reference in a new issue