Further changes to parser for OmittedExpressions, and make checker resilient to them

This commit is contained in:
Jason Freeman 2014-09-18 13:11:46 -07:00
parent 9973b9c075
commit 1bfd7159e8
2 changed files with 39 additions and 5 deletions

View File

@ -4129,11 +4129,18 @@ module ts {
return unknownSignature;
}
function signatureHasCorrectArity(node: CallExpression, signature: Signature) {
function signatureHasCorrectArity(node: CallExpression, signature: Signature): boolean {
var args = node.arguments || emptyArray;
return args.length >= signature.minArgumentCount &&
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.
if (!isCorrect && forEach(node.arguments, arg => arg.kind === SyntaxKind.OmittedExpression)) {
return true;
}
return isCorrect;
}
// The candidate list orders groups in reverse, but within a group signatures are kept in declaration order
@ -4208,6 +4215,9 @@ module ts {
var mapper = createInferenceMapper(context);
// First infer from arguments that are not context sensitive
for (var i = 0; i < args.length; i++) {
if (args[i].kind === SyntaxKind.OmittedExpression) {
continue;
}
if (!excludeArgument || excludeArgument[i] === undefined) {
var parameterType = getTypeAtPosition(signature, i);
inferTypes(context, checkExpressionWithContextualType(args[i], parameterType, mapper), parameterType);
@ -4216,6 +4226,9 @@ module ts {
// Next, infer from those context sensitive arguments that are no longer excluded
if (excludeArgument) {
for (var i = 0; i < args.length; i++) {
if (args[i].kind === SyntaxKind.OmittedExpression) {
continue;
}
if (excludeArgument[i] === false) {
var parameterType = getTypeAtPosition(signature, i);
inferTypes(context, checkExpressionWithContextualType(args[i], parameterType, mapper), parameterType);
@ -4244,6 +4257,10 @@ module ts {
if (node.arguments) {
for (var i = 0; i < node.arguments.length; i++) {
var arg = node.arguments[i];
if (arg.kind === SyntaxKind.OmittedExpression) {
continue;
}
var paramType = getTypeAtPosition(signature, i);
// String literals get string literal types unless we're reporting errors
var argType = arg.kind === SyntaxKind.StringLiteral && !reportErrors ?

View File

@ -2307,7 +2307,7 @@ module ts {
// needs evidence of a trailing comma in order to give good results for signature help.
// That is why we do not allow a trailing comma, but we "preserve" a trailing comma.
callExpr.arguments = parseDelimitedList(ParsingContext.ArgumentExpressions,
parseAssignmentExpression, /*allowTrailingComma*/ false, /*preserveTrailingComma*/ true);
parseArgumentExpression, /*allowTrailingComma*/ false, /*preserveTrailingComma*/ true);
parseExpected(SyntaxKind.CloseParenToken);
expr = finishNode(callExpr);
continue;
@ -2376,8 +2376,25 @@ module ts {
return finishNode(node);
}
function parseAssignmentExpressionOrOmittedExpression(omittedExpressionDiagnostic: DiagnosticMessage): Expression {
if (token === SyntaxKind.CommaToken) {
if (omittedExpressionDiagnostic) {
var errorStart = scanner.getTokenPos();
var errorLength = scanner.getTextPos() - errorStart;
grammarErrorAtPos(errorStart, errorLength, omittedExpressionDiagnostic);
}
return createNode(SyntaxKind.OmittedExpression);
}
return parseAssignmentExpression();
}
function parseArrayLiteralElement(): Expression {
return token === SyntaxKind.CommaToken ? createNode(SyntaxKind.OmittedExpression) : parseAssignmentExpression();
return parseAssignmentExpressionOrOmittedExpression(/*omittedExpressionDiagnostic*/ undefined);
}
function parseArgumentExpression(): Expression {
return parseAssignmentExpressionOrOmittedExpression(Diagnostics.Argument_expression_expected);
}
function parseArrayLiteral(): ArrayLiteral {
@ -2523,7 +2540,7 @@ module ts {
// needs evidence of a trailing comma in order to give good results for signature help.
// That is why we do not allow a trailing comma, but we "preserve" a trailing comma.
node.arguments = parseDelimitedList(ParsingContext.ArgumentExpressions,
parseAssignmentExpression, /*allowTrailingComma*/ false, /*preserveTrailingComma*/ true);
parseArgumentExpression, /*allowTrailingComma*/ false, /*preserveTrailingComma*/ true);
parseExpected(SyntaxKind.CloseParenToken);
}
return finishNode(node);