@@ -18215,7 +18215,6 @@ namespace ts {
18215
18215
18216
18216
function hasCorrectArity(node: CallLikeExpression, args: ReadonlyArray<Expression>, signature: Signature, signatureHelpTrailingComma = false) {
18217
18217
let argCount: number; // Apparent number of arguments we will have in this call
18218
- let typeArguments: NodeArray<TypeNode> | undefined; // Type arguments (undefined if none)
18219
18218
let callIsIncomplete = false; // In incomplete call we want to be lenient when we have too few arguments
18220
18219
let spreadArgIndex = -1;
18221
18220
@@ -18228,7 +18227,6 @@ namespace ts {
18228
18227
// Even if the call is incomplete, we'll have a missing expression as our last argument,
18229
18228
// so we can say the count is just the arg list length
18230
18229
argCount = args.length;
18231
- typeArguments = node.typeArguments;
18232
18230
18233
18231
if (node.template.kind === SyntaxKind.TemplateExpression) {
18234
18232
// If a tagged template expression lacks a tail literal, the call is incomplete.
@@ -18246,7 +18244,6 @@ namespace ts {
18246
18244
}
18247
18245
}
18248
18246
else if (node.kind === SyntaxKind.Decorator) {
18249
- typeArguments = undefined;
18250
18247
argCount = getEffectiveArgumentCount(node, /*args*/ undefined!, signature);
18251
18248
}
18252
18249
else {
@@ -18261,14 +18258,9 @@ namespace ts {
18261
18258
// If we are missing the close parenthesis, the call is incomplete.
18262
18259
callIsIncomplete = node.arguments.end === node.end;
18263
18260
18264
- typeArguments = node.typeArguments;
18265
18261
spreadArgIndex = getSpreadArgumentIndex(args);
18266
18262
}
18267
18263
18268
- if (!hasCorrectTypeArgumentArity(signature, typeArguments)) {
18269
- return false;
18270
- }
18271
-
18272
18264
// If a spread argument is present, check that it corresponds to a rest parameter or at least that it's in the valid range.
18273
18265
if (spreadArgIndex >= 0) {
18274
18266
return spreadArgIndex >= getMinArgumentCount(signature) && (hasEffectiveRestParameter(signature) || spreadArgIndex < getParameterCount(signature));
@@ -18918,6 +18910,43 @@ namespace ts {
18918
18910
}
18919
18911
}
18920
18912
18913
+ function getArgumentArityError(node: Node, signatures: ReadonlyArray<Signature>, args: ReadonlyArray<Expression>) {
18914
+ let min = Number.POSITIVE_INFINITY;
18915
+ let max = Number.NEGATIVE_INFINITY;
18916
+ let belowArgCount = Number.NEGATIVE_INFINITY;
18917
+ let aboveArgCount = Number.POSITIVE_INFINITY;
18918
+
18919
+ let argCount = args.length;
18920
+ for (const sig of signatures) {
18921
+ const minCount = getMinArgumentCount(sig);
18922
+ const maxCount = getParameterCount(sig);
18923
+ if (minCount < argCount && minCount > belowArgCount) belowArgCount = minCount;
18924
+ if (argCount < maxCount && maxCount < aboveArgCount) aboveArgCount = maxCount;
18925
+ min = Math.min(min, minCount);
18926
+ max = Math.max(max, maxCount);
18927
+ }
18928
+
18929
+ const hasRestParameter = some(signatures, hasEffectiveRestParameter);
18930
+ const paramRange = hasRestParameter ? min :
18931
+ min < max ? min + "-" + max :
18932
+ min;
18933
+ const hasSpreadArgument = getSpreadArgumentIndex(args) > -1;
18934
+ if (argCount <= max && hasSpreadArgument) {
18935
+ argCount--;
18936
+ }
18937
+
18938
+ if (hasRestParameter || hasSpreadArgument) {
18939
+ const error = hasRestParameter && hasSpreadArgument ? Diagnostics.Expected_at_least_0_arguments_but_got_1_or_more :
18940
+ hasRestParameter ? Diagnostics.Expected_at_least_0_arguments_but_got_1 :
18941
+ Diagnostics.Expected_0_arguments_but_got_1_or_more;
18942
+ return createDiagnosticForNode(node, error, paramRange, argCount);
18943
+ }
18944
+ if (min < argCount && argCount < max) {
18945
+ return createDiagnosticForNode(node, Diagnostics.No_overload_expects_0_arguments_but_overloads_do_exist_that_expect_either_1_or_2_arguments, argCount, belowArgCount, aboveArgCount);
18946
+ }
18947
+ return createDiagnosticForNode(node, Diagnostics.Expected_0_arguments_but_got_1, paramRange, argCount);
18948
+ }
18949
+
18921
18950
function getTypeArgumentArityError(node: Node, signatures: ReadonlyArray<Signature>, typeArguments: NodeArray<TypeNode>) {
18922
18951
let min = Infinity;
18923
18952
let max = -Infinity;
@@ -19008,6 +19037,7 @@ namespace ts {
19008
19037
// foo<number>(0);
19009
19038
//
19010
19039
let candidateForArgumentError: Signature | undefined;
19040
+ let candidateForArgumentArityError: Signature | undefined;
19011
19041
let candidateForTypeArgumentError: Signature | undefined;
19012
19042
let result: Signature | undefined;
19013
19043
@@ -19052,49 +19082,17 @@ namespace ts {
19052
19082
// an error, we don't need to exclude any arguments, although it would cause no harm to do so.
19053
19083
checkApplicableSignature(node, args!, candidateForArgumentError, assignableRelation, /*excludeArgument*/ undefined, /*reportErrors*/ true);
19054
19084
}
19085
+ else if (candidateForArgumentArityError) {
19086
+ diagnostics.add(getArgumentArityError(node, [candidateForArgumentArityError], args!));
19087
+ }
19055
19088
else if (candidateForTypeArgumentError) {
19056
19089
checkTypeArguments(candidateForTypeArgumentError, (node as CallExpression | TaggedTemplateExpression).typeArguments!, /*reportErrors*/ true, fallbackError);
19057
19090
}
19058
19091
else if (typeArguments && every(signatures, sig => length(sig.typeParameters) !== typeArguments!.length)) {
19059
19092
diagnostics.add(getTypeArgumentArityError(node, signatures, typeArguments));
19060
19093
}
19061
19094
else if (args) {
19062
- let min = Number.POSITIVE_INFINITY;
19063
- let max = Number.NEGATIVE_INFINITY;
19064
- let belowArgCount = Number.NEGATIVE_INFINITY;
19065
- let aboveArgCount = Number.POSITIVE_INFINITY;
19066
-
19067
- let argCount = args.length;
19068
- for (const sig of signatures) {
19069
- const minCount = getMinArgumentCount(sig);
19070
- const maxCount = getParameterCount(sig);
19071
- if (minCount < argCount && minCount > belowArgCount) belowArgCount = minCount;
19072
- if (argCount < maxCount && maxCount < aboveArgCount) aboveArgCount = maxCount;
19073
- min = Math.min(min, minCount);
19074
- max = Math.max(max, maxCount);
19075
- }
19076
-
19077
- const hasRestParameter = some(signatures, hasEffectiveRestParameter);
19078
- const paramRange = hasRestParameter ? min :
19079
- min < max ? min + "-" + max :
19080
- min;
19081
- const hasSpreadArgument = getSpreadArgumentIndex(args) > -1;
19082
- if (argCount <= max && hasSpreadArgument) {
19083
- argCount--;
19084
- }
19085
-
19086
- if (hasRestParameter || hasSpreadArgument) {
19087
- const error = hasRestParameter && hasSpreadArgument ? Diagnostics.Expected_at_least_0_arguments_but_got_1_or_more :
19088
- hasRestParameter ? Diagnostics.Expected_at_least_0_arguments_but_got_1 :
19089
- Diagnostics.Expected_0_arguments_but_got_1_or_more;
19090
- diagnostics.add(createDiagnosticForNode(node, error, paramRange, argCount));
19091
- }
19092
- else if (min < argCount && argCount < max) {
19093
- diagnostics.add(createDiagnosticForNode(node, Diagnostics.No_overload_expects_0_arguments_but_overloads_do_exist_that_expect_either_1_or_2_arguments, argCount, belowArgCount, aboveArgCount));
19094
- }
19095
- else {
19096
- diagnostics.add(createDiagnosticForNode(node, Diagnostics.Expected_0_arguments_but_got_1, paramRange, argCount));
19097
- }
19095
+ diagnostics.add(getArgumentArityError(node, signatures, args));
19098
19096
}
19099
19097
else if (fallbackError) {
19100
19098
diagnostics.add(createDiagnosticForNode(node, fallbackError));
@@ -19104,11 +19102,12 @@ namespace ts {
19104
19102
19105
19103
function chooseOverload(candidates: Signature[], relation: Map<RelationComparisonResult>, signatureHelpTrailingComma = false) {
19106
19104
candidateForArgumentError = undefined;
19105
+ candidateForArgumentArityError = undefined;
19107
19106
candidateForTypeArgumentError = undefined;
19108
19107
19109
19108
if (isSingleNonGenericCandidate) {
19110
19109
const candidate = candidates[0];
19111
- if (!hasCorrectArity(node, args!, candidate, signatureHelpTrailingComma)) {
19110
+ if (typeArguments || !hasCorrectArity(node, args!, candidate, signatureHelpTrailingComma)) {
19112
19111
return undefined;
19113
19112
}
19114
19113
if (!checkApplicableSignature(node, args!, candidate, relation, excludeArgument, /*reportErrors*/ false)) {
@@ -19120,7 +19119,7 @@ namespace ts {
19120
19119
19121
19120
for (let candidateIndex = 0; candidateIndex < candidates.length; candidateIndex++) {
19122
19121
const originalCandidate = candidates[candidateIndex];
19123
- if (!hasCorrectArity(node, args!, originalCandidate, signatureHelpTrailingComma)) {
19122
+ if (!hasCorrectTypeArgumentArity(originalCandidate, typeArguments) || ! hasCorrectArity(node, args!, originalCandidate, signatureHelpTrailingComma)) {
19124
19123
continue;
19125
19124
}
19126
19125
@@ -19148,6 +19147,12 @@ namespace ts {
19148
19147
}
19149
19148
const isJavascript = isInJavaScriptFile(candidate.declaration);
19150
19149
candidate = getSignatureInstantiation(candidate, typeArgumentTypes, isJavascript);
19150
+ // If the original signature has a rest type parameter, instantiation may produce a
19151
+ // signature with different arity and we need to perform another arity check.
19152
+ if (getRestTypeParameter(originalCandidate) && !hasCorrectArity(node, args!, candidate, signatureHelpTrailingComma)) {
19153
+ candidateForArgumentArityError = candidate;
19154
+ break;
19155
+ }
19151
19156
}
19152
19157
if (!checkApplicableSignature(node, args!, candidate, relation, excludeArgument, /*reportErrors*/ false)) {
19153
19158
candidateForArgumentError = candidate;
0 commit comments