Fix arity checking for partial overload resolution

This commit is contained in:
Jason Freeman 2014-09-26 13:51:13 -07:00
parent f2880ce5b7
commit ab3326f7b7
4 changed files with 56 additions and 23 deletions

View File

@ -4331,25 +4331,32 @@ module ts {
}
function signatureHasCorrectArity(node: CallExpression, signature: Signature): boolean {
var args = node.arguments || emptyArray;
var isCorrect = args.length >= signature.minArgumentCount &&
(signature.hasRestParameter || args.length <= signature.parameters.length) &&
(!node.typeArguments || signature.typeParameters && node.typeArguments.length === signature.typeParameters.length);
// For error recovery, since we have parsed OmittedExpressions for any extra commas
// in the argument list, if we see any OmittedExpressions, just return true.
// The reason this is ok is because omitted expressions here are syntactically
// illegal, and will cause a parse error.
// Note: It may be worth keeping the upper bound check on arity, but removing
// the lower bound check if there are omitted expressions.
if (!isCorrect) {
// Technically this type assertion is not safe because args could be initialized to emptyArray
// above.
if ((<NodeArray<Node>>args).hasTrailingComma || forEach(args, arg => arg.kind === SyntaxKind.OmittedExpression)) {
return true;
}
if (!node.arguments) {
// This only happens when we have something of the form:
// new C
//
return signature.minArgumentCount === 0;
}
return isCorrect;
// For IDE scenarios, since we may have an incomplete call, we make two modifications
// to arity checking.
// 1. A trailing comma is tantamount to adding another argument
// 2. If the call is incomplete (no closing paren) allow fewer arguments than expected
var args = node.arguments;
var numberOfArgs = args.hasTrailingComma ? args.length + 1 : args.length;
var hasTooManyArguments = !signature.hasRestParameter && numberOfArgs > signature.parameters.length;
var hasRightNumberOfTypeArguments = !node.typeArguments ||
(signature.typeParameters && node.typeArguments.length === signature.typeParameters.length);
if (hasTooManyArguments || !hasRightNumberOfTypeArguments) {
return false;
}
// If we are missing the close paren, the call is incomplete, and we should skip
// the lower bound check.
var callIsIncomplete = args.end === node.end;
var hasEnoughArguments = numberOfArgs >= signature.minArgumentCount;
return callIsIncomplete || hasEnoughArguments;
}
// If type has a single call signature and no other members, return that signature. Otherwise, return undefined.

View File

@ -1,18 +1,24 @@
tests/cases/compiler/trailingSeparatorInFunctionCall.ts(4,7): error TS1009: Trailing comma not allowed.
tests/cases/compiler/trailingSeparatorInFunctionCall.ts(9,8): error TS1009: Trailing comma not allowed.
tests/cases/compiler/trailingSeparatorInFunctionCall.ts(4,1): error TS2346: Supplied parameters do not match any signature of call target.
tests/cases/compiler/trailingSeparatorInFunctionCall.ts(9,1): error TS2346: Supplied parameters do not match any signature of call target.
==== tests/cases/compiler/trailingSeparatorInFunctionCall.ts (2 errors) ====
==== tests/cases/compiler/trailingSeparatorInFunctionCall.ts (4 errors) ====
function f(x, y) {
}
f(1, 2, );
~
!!! error TS1009: Trailing comma not allowed.
~~~~~~~~~
!!! error TS2346: Supplied parameters do not match any signature of call target.
function f2<T>(x: T, y: T) {
}
f2(1, 2, );
~
!!! error TS1009: Trailing comma not allowed.
!!! error TS1009: Trailing comma not allowed.
~~~~~~~~~~
!!! error TS2346: Supplied parameters do not match any signature of call target.

View File

@ -13,6 +13,6 @@ verify.currentParameterSpanIs("x: string");
edit.insert("'',");
verify.signatureHelpCountIs(2);
// verify.currentSignatureHelpIs("fn(x: string, y: number): any");
// verify.currentParameterHelpArgumentNameIs("y");
// verify.currentParameterSpanIs("y: number");
verify.currentSignatureHelpIs("fn(x: string, y: number): any");
verify.currentParameterHelpArgumentNameIs("y");
verify.currentParameterSpanIs("y: number");

View File

@ -0,0 +1,20 @@
/// <reference path='fourslash.ts'/>
////declare function f(s: string);
////declare function f(n: number);
////declare function f(s: string, b: boolean);
////declare function f(n: number, b: boolean);
////
////f(1/**/
goTo.marker();
verify.signatureHelpCountIs(4);
verify.currentSignatureHelpIs("f(n: number): any");
verify.currentParameterHelpArgumentNameIs("n");
verify.currentParameterSpanIs("n: number");
edit.insert(", ");
verify.signatureHelpCountIs(4);
verify.currentSignatureHelpIs("f(n: number, b: boolean): any");
verify.currentParameterHelpArgumentNameIs("b");
verify.currentParameterSpanIs("b: boolean");