Skip to content

Commit 1bfd715

Browse files
committed
Further changes to parser for OmittedExpressions, and make checker resilient to them
1 parent 9973b9c commit 1bfd715

File tree

2 files changed

+39
-5
lines changed

2 files changed

+39
-5
lines changed

src/compiler/checker.ts

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4129,11 +4129,18 @@ module ts {
41294129
return unknownSignature;
41304130
}
41314131

4132-
function signatureHasCorrectArity(node: CallExpression, signature: Signature) {
4132+
function signatureHasCorrectArity(node: CallExpression, signature: Signature): boolean {
41334133
var args = node.arguments || emptyArray;
4134-
return args.length >= signature.minArgumentCount &&
4134+
var isCorrect = args.length >= signature.minArgumentCount &&
41354135
(signature.hasRestParameter || args.length <= signature.parameters.length) &&
41364136
(!node.typeArguments || signature.typeParameters && node.typeArguments.length === signature.typeParameters.length);
4137+
4138+
// For error recovery, since we have parsed OmittedExpressions for any extra commas
4139+
// in the argument list, if we see any OmittedExpressions, just return true.
4140+
if (!isCorrect && forEach(node.arguments, arg => arg.kind === SyntaxKind.OmittedExpression)) {
4141+
return true;
4142+
}
4143+
return isCorrect;
41374144
}
41384145

41394146
// The candidate list orders groups in reverse, but within a group signatures are kept in declaration order
@@ -4208,6 +4215,9 @@ module ts {
42084215
var mapper = createInferenceMapper(context);
42094216
// First infer from arguments that are not context sensitive
42104217
for (var i = 0; i < args.length; i++) {
4218+
if (args[i].kind === SyntaxKind.OmittedExpression) {
4219+
continue;
4220+
}
42114221
if (!excludeArgument || excludeArgument[i] === undefined) {
42124222
var parameterType = getTypeAtPosition(signature, i);
42134223
inferTypes(context, checkExpressionWithContextualType(args[i], parameterType, mapper), parameterType);
@@ -4216,6 +4226,9 @@ module ts {
42164226
// Next, infer from those context sensitive arguments that are no longer excluded
42174227
if (excludeArgument) {
42184228
for (var i = 0; i < args.length; i++) {
4229+
if (args[i].kind === SyntaxKind.OmittedExpression) {
4230+
continue;
4231+
}
42194232
if (excludeArgument[i] === false) {
42204233
var parameterType = getTypeAtPosition(signature, i);
42214234
inferTypes(context, checkExpressionWithContextualType(args[i], parameterType, mapper), parameterType);
@@ -4244,6 +4257,10 @@ module ts {
42444257
if (node.arguments) {
42454258
for (var i = 0; i < node.arguments.length; i++) {
42464259
var arg = node.arguments[i];
4260+
if (arg.kind === SyntaxKind.OmittedExpression) {
4261+
continue;
4262+
}
4263+
42474264
var paramType = getTypeAtPosition(signature, i);
42484265
// String literals get string literal types unless we're reporting errors
42494266
var argType = arg.kind === SyntaxKind.StringLiteral && !reportErrors ?

src/compiler/parser.ts

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2307,7 +2307,7 @@ module ts {
23072307
// needs evidence of a trailing comma in order to give good results for signature help.
23082308
// That is why we do not allow a trailing comma, but we "preserve" a trailing comma.
23092309
callExpr.arguments = parseDelimitedList(ParsingContext.ArgumentExpressions,
2310-
parseAssignmentExpression, /*allowTrailingComma*/ false, /*preserveTrailingComma*/ true);
2310+
parseArgumentExpression, /*allowTrailingComma*/ false, /*preserveTrailingComma*/ true);
23112311
parseExpected(SyntaxKind.CloseParenToken);
23122312
expr = finishNode(callExpr);
23132313
continue;
@@ -2376,8 +2376,25 @@ module ts {
23762376
return finishNode(node);
23772377
}
23782378

2379+
function parseAssignmentExpressionOrOmittedExpression(omittedExpressionDiagnostic: DiagnosticMessage): Expression {
2380+
if (token === SyntaxKind.CommaToken) {
2381+
if (omittedExpressionDiagnostic) {
2382+
var errorStart = scanner.getTokenPos();
2383+
var errorLength = scanner.getTextPos() - errorStart;
2384+
grammarErrorAtPos(errorStart, errorLength, omittedExpressionDiagnostic);
2385+
}
2386+
return createNode(SyntaxKind.OmittedExpression);
2387+
}
2388+
2389+
return parseAssignmentExpression();
2390+
}
2391+
23792392
function parseArrayLiteralElement(): Expression {
2380-
return token === SyntaxKind.CommaToken ? createNode(SyntaxKind.OmittedExpression) : parseAssignmentExpression();
2393+
return parseAssignmentExpressionOrOmittedExpression(/*omittedExpressionDiagnostic*/ undefined);
2394+
}
2395+
2396+
function parseArgumentExpression(): Expression {
2397+
return parseAssignmentExpressionOrOmittedExpression(Diagnostics.Argument_expression_expected);
23812398
}
23822399

23832400
function parseArrayLiteral(): ArrayLiteral {
@@ -2523,7 +2540,7 @@ module ts {
25232540
// needs evidence of a trailing comma in order to give good results for signature help.
25242541
// That is why we do not allow a trailing comma, but we "preserve" a trailing comma.
25252542
node.arguments = parseDelimitedList(ParsingContext.ArgumentExpressions,
2526-
parseAssignmentExpression, /*allowTrailingComma*/ false, /*preserveTrailingComma*/ true);
2543+
parseArgumentExpression, /*allowTrailingComma*/ false, /*preserveTrailingComma*/ true);
25272544
parseExpected(SyntaxKind.CloseParenToken);
25282545
}
25292546
return finishNode(node);

0 commit comments

Comments
 (0)