Move parameter grammar checks to the grammar pass.

This commit is contained in:
Cyrus Najmabadi 2014-11-18 17:42:32 -08:00
parent 6fdc5dc148
commit 08f0672b03
7 changed files with 161 additions and 94 deletions

View file

@ -1676,7 +1676,6 @@ module ts {
}
var typeParameters = parseTypeParameters();
var parameters = parseParameterList(SyntaxKind.OpenParenToken, SyntaxKind.CloseParenToken);
checkParameterList(parameters);
var type: TypeNode;
@ -1702,45 +1701,6 @@ module ts {
return parseBracketedList(ParsingContext.Parameters, parseParameter, startDelimiter, endDelimiter);
}
function checkParameterList(parameters: NodeArray<ParameterDeclaration>): void {
var seenOptionalParameter = false;
var parameterCount = parameters.length;
for (var i = 0; i < parameterCount; i++) {
var parameter = parameters[i];
if (parameter.flags & NodeFlags.Rest) {
if (i !== (parameterCount - 1)) {
grammarErrorOnNode(parameter.name, Diagnostics.A_rest_parameter_must_be_last_in_a_parameter_list);
return;
}
if (parameter.flags & NodeFlags.QuestionMark) {
grammarErrorOnNode(parameter.name, Diagnostics.A_rest_parameter_cannot_be_optional);
return;
}
if (parameter.initializer) {
grammarErrorOnNode(parameter.name, Diagnostics.A_rest_parameter_cannot_have_an_initializer);
return;
}
}
else if (parameter.flags & NodeFlags.QuestionMark || parameter.initializer) {
seenOptionalParameter = true;
if (parameter.flags & NodeFlags.QuestionMark && parameter.initializer) {
grammarErrorOnNode(parameter.name, Diagnostics.Parameter_cannot_have_question_mark_and_initializer);
return;
}
}
else {
if (seenOptionalParameter) {
grammarErrorOnNode(parameter.name, Diagnostics.A_required_parameter_cannot_follow_an_optional_parameter);
return;
}
}
}
}
function parseSignatureMember(kind: SyntaxKind, returnToken: SyntaxKind): SignatureDeclaration {
var node = <SignatureDeclaration>createNode(kind);
var sig = parseSignature(kind, returnToken, /* returnTokenRequired */ false);
@ -4372,9 +4332,21 @@ module ts {
// No grammar errors on any of our children. Check this node for grammar errors.
switch (node.kind) {
case SyntaxKind.Parameter:
return performParameterChecks(<ParameterDeclaration>node);
case SyntaxKind.ArrowFunction: return performArrowFunctionChecks(<FunctionExpression>node);
case SyntaxKind.CallSignature: return performCallSignatureChecks(<SignatureDeclaration>node);
case SyntaxKind.Constructor: return performConstructorChecks(<ConstructorDeclaration>node);
case SyntaxKind.ConstructorType: return performConstructorTypeChecks(<SignatureDeclaration>node);
case SyntaxKind.ConstructSignature: return performConstructSignatureChecks(<SignatureDeclaration>node);
case SyntaxKind.FunctionDeclaration: return performFunctionDeclarationChecks(<FunctionLikeDeclaration>node);
case SyntaxKind.FunctionExpression: return performFunctionExpressionChecks(<FunctionExpression>node);
case SyntaxKind.FunctionType: return performFunctionTypeChecks(<SignatureDeclaration>node);
case SyntaxKind.GetAccessor: return performGetAccessorChecks(<MethodDeclaration>node);
case SyntaxKind.Method: return performMethodChecks(<MethodDeclaration>node);
case SyntaxKind.Parameter: return performParameterChecks(<ParameterDeclaration>node);
case SyntaxKind.SetAccessor: return performSetAccessorChecks(<MethodDeclaration>node);
}
return false;
}
function grammarErrorOnNode(node: Node, message: DiagnosticMessage, arg0?: any, arg1?: any, arg2?: any): void {
@ -4391,6 +4363,86 @@ module ts {
grammarErrorOnNode(node, Diagnostics.Invalid_use_of_0_in_strict_mode, name);
}
function performArrowFunctionChecks(node: FunctionExpression) {
if (performParameterListChecks(node.parameters)) {
return true;
}
return false;
}
function performCallSignatureChecks(node: ConstructorDeclaration) {
if (performParameterListChecks(node.parameters)) {
return true;
}
return false;
}
function performConstructorChecks(node: ConstructorDeclaration) {
if (performParameterListChecks(node.parameters)) {
return true;
}
return false;
}
function performConstructorTypeChecks(node: SignatureDeclaration) {
if (performParameterListChecks(node.parameters)) {
return true;
}
return false;
}
function performConstructSignatureChecks(node: FunctionLikeDeclaration) {
if (performParameterListChecks(node.parameters)) {
return true;
}
return false;
}
function performFunctionDeclarationChecks(node: FunctionLikeDeclaration) {
if (performParameterListChecks(node.parameters)) {
return true;
}
return false;
}
function performFunctionExpressionChecks(node: FunctionExpression) {
if (performParameterListChecks(node.parameters)) {
return true;
}
return false;
}
function performFunctionTypeChecks(node: SignatureDeclaration) {
if (performParameterListChecks(node.parameters)) {
return true;
}
return false;
}
function performGetAccessorChecks(node: MethodDeclaration) {
if (performParameterListChecks(node.parameters)) {
return true;
}
return false;
}
function performMethodChecks(node: MethodDeclaration) {
if (performParameterListChecks(node.parameters)) {
return true;
}
return false;
}
function performParameterChecks(node: ParameterDeclaration): boolean {
// It is a SyntaxError if the Identifier "eval" or the Identifier "arguments" occurs as the
// Identifier in a PropertySetParameterList of a PropertyAssignment that is contained in strict code
@ -4404,6 +4456,53 @@ module ts {
return false;
}
function performParameterListChecks(parameters: NodeArray<ParameterDeclaration>): void {
var seenOptionalParameter = false;
var parameterCount = parameters.length;
for (var i = 0; i < parameterCount; i++) {
var parameter = parameters[i];
if (parameter.flags & NodeFlags.Rest) {
if (i !== (parameterCount - 1)) {
grammarErrorOnNode(parameter.name, Diagnostics.A_rest_parameter_must_be_last_in_a_parameter_list);
return;
}
if (parameter.flags & NodeFlags.QuestionMark) {
grammarErrorOnNode(parameter.name, Diagnostics.A_rest_parameter_cannot_be_optional);
return;
}
if (parameter.initializer) {
grammarErrorOnNode(parameter.name, Diagnostics.A_rest_parameter_cannot_have_an_initializer);
return;
}
}
else if (parameter.flags & NodeFlags.QuestionMark || parameter.initializer) {
seenOptionalParameter = true;
if (parameter.flags & NodeFlags.QuestionMark && parameter.initializer) {
grammarErrorOnNode(parameter.name, Diagnostics.Parameter_cannot_have_question_mark_and_initializer);
return;
}
}
else {
if (seenOptionalParameter) {
grammarErrorOnNode(parameter.name, Diagnostics.A_required_parameter_cannot_follow_an_optional_parameter);
return;
}
}
}
}
function performSetAccessorChecks(node: MethodDeclaration) {
if (performParameterListChecks(node.parameters)) {
return true;
}
return false;
}
}

View file

@ -1,16 +1,16 @@
tests/cases/compiler/amdModuleName2.ts(2,1): error TS2458: An AMD module cannot have multiple name assignments.
==== tests/cases/compiler/amdModuleName2.ts (1 errors) ====
///<amd-module name='FirstModuleName'/>
///<amd-module name='SecondModuleName'/>
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2458: An AMD module cannot have multiple name assignments.
class Foo {
x: number;
constructor() {
this.x = 5;
}
}
export = Foo;
tests/cases/compiler/amdModuleName2.ts(2,1): error TS2458: An AMD module cannot have multiple name assignments.
==== tests/cases/compiler/amdModuleName2.ts (1 errors) ====
///<amd-module name='FirstModuleName'/>
///<amd-module name='SecondModuleName'/>
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2458: An AMD module cannot have multiple name assignments.
class Foo {
x: number;
constructor() {
this.x = 5;
}
}
export = Foo;

View file

@ -1,15 +1,8 @@
tests/cases/compiler/fatarrowfunctionsOptionalArgs.ts(60,10): error TS1015: Parameter cannot have question mark and initializer.
tests/cases/compiler/fatarrowfunctionsOptionalArgs.ts(70,11): error TS1015: Parameter cannot have question mark and initializer.
tests/cases/compiler/fatarrowfunctionsOptionalArgs.ts(80,17): error TS1015: Parameter cannot have question mark and initializer.
tests/cases/compiler/fatarrowfunctionsOptionalArgs.ts(88,23): error TS1005: ';' expected.
tests/cases/compiler/fatarrowfunctionsOptionalArgs.ts(88,38): error TS1005: ';' expected.
tests/cases/compiler/fatarrowfunctionsOptionalArgs.ts(106,3): error TS1015: Parameter cannot have question mark and initializer.
tests/cases/compiler/fatarrowfunctionsOptionalArgs.ts(106,35): error TS1015: Parameter cannot have question mark and initializer.
tests/cases/compiler/fatarrowfunctionsOptionalArgs.ts(126,6): error TS1015: Parameter cannot have question mark and initializer.
tests/cases/compiler/fatarrowfunctionsOptionalArgs.ts(128,9): error TS1015: Parameter cannot have question mark and initializer.
==== tests/cases/compiler/fatarrowfunctionsOptionalArgs.ts (9 errors) ====
==== tests/cases/compiler/fatarrowfunctionsOptionalArgs.ts (2 errors) ====
// valid
// no params
@ -70,8 +63,6 @@ tests/cases/compiler/fatarrowfunctionsOptionalArgs.ts(128,9): error TS1015: Para
false ? (arg: number) => 45 : null;
false ? (arg?: number) => 46 : null;
false ? (arg?: number = 0) => 47 : null;
~~~
!!! error TS1015: Parameter cannot have question mark and initializer.
false ? (...arg: number[]) => 48 : null;
// in ternary exression within paren
@ -82,8 +73,6 @@ tests/cases/compiler/fatarrowfunctionsOptionalArgs.ts(128,9): error TS1015: Para
false ? ((arg: number) => 55) : null;
false ? ((arg?: number) => 56) : null;
false ? ((arg?: number = 0) => 57) : null;
~~~
!!! error TS1015: Parameter cannot have question mark and initializer.
false ? ((...arg: number[]) => 58) : null;
// ternary exression's else clause
@ -94,8 +83,6 @@ tests/cases/compiler/fatarrowfunctionsOptionalArgs.ts(128,9): error TS1015: Para
false ? null : (arg: number) => 65;
false ? null : (arg?: number) => 66;
false ? null : (arg?: number = 0) => 67;
~~~
!!! error TS1015: Parameter cannot have question mark and initializer.
false ? null : (...arg: number[]) => 68;
@ -126,10 +113,6 @@ tests/cases/compiler/fatarrowfunctionsOptionalArgs.ts(128,9): error TS1015: Para
((arg:number) => 0) + '' + ((arg:number) => 104);
((arg:number = 1) => 0) + '' + ((arg:number = 2) => 105);
((arg?:number = 1) => 0) + '' + ((arg?:number = 2) => 106);
~~~
!!! error TS1015: Parameter cannot have question mark and initializer.
~~~
!!! error TS1015: Parameter cannot have question mark and initializer.
((...arg:number[]) => 0) + '' + ((...arg:number[]) => 107);
((arg1, arg2?) => 0) + '' + ((arg1,arg2?) => 108);
((arg1, ...arg2:number[]) => 0) + '' + ((arg1, ...arg2:number[]) => 108);
@ -150,12 +133,8 @@ tests/cases/compiler/fatarrowfunctionsOptionalArgs.ts(128,9): error TS1015: Para
(a: number = 0) => 116,
(a = 0) => 117,
(a?: number = 0) => 118,
~
!!! error TS1015: Parameter cannot have question mark and initializer.
(...a: number[]) => 119,
(a, b? = 0, ...c: number[]) => 120,
~
!!! error TS1015: Parameter cannot have question mark and initializer.
(a) => (b) => (c) => 121,
false? (a) => 0 : (b) => 122
);

View file

@ -1,11 +1,10 @@
tests/cases/compiler/fatarrowfunctionsOptionalArgsErrors1.ts(1,9): error TS1016: A required parameter cannot follow an optional parameter.
tests/cases/compiler/fatarrowfunctionsOptionalArgsErrors1.ts(2,5): error TS1047: A rest parameter cannot be optional.
tests/cases/compiler/fatarrowfunctionsOptionalArgsErrors1.ts(4,5): error TS1048: A rest parameter cannot have an initializer.
tests/cases/compiler/fatarrowfunctionsOptionalArgsErrors1.ts(5,5): error TS1003: Identifier expected.
tests/cases/compiler/fatarrowfunctionsOptionalArgsErrors1.ts(8,12): error TS1016: A required parameter cannot follow an optional parameter.
tests/cases/compiler/fatarrowfunctionsOptionalArgsErrors1.ts(7,12): error TS1016: A required parameter cannot follow an optional parameter.
==== tests/cases/compiler/fatarrowfunctionsOptionalArgsErrors1.ts (5 errors) ====
==== tests/cases/compiler/fatarrowfunctionsOptionalArgsErrors1.ts (4 errors) ====
(arg1?, arg2) => 101;
~~~~
!!! error TS1016: A required parameter cannot follow an optional parameter.
@ -16,9 +15,6 @@ tests/cases/compiler/fatarrowfunctionsOptionalArgsErrors1.ts(8,12): error TS1016
(...arg:number [] = []) => 104;
~~~
!!! error TS1048: A rest parameter cannot have an initializer.
(...) => 105;
~
!!! error TS1003: Identifier expected.
// Non optional parameter following an optional one
(arg1 = 1, arg2) => 1;

View file

@ -1,6 +1,5 @@
tests/cases/conformance/parser/ecmascript5/parserRealSource11.ts(4,1): error TS6053: File 'tests/cases/conformance/parser/ecmascript5/typescript.ts' not found.
tests/cases/conformance/parser/ecmascript5/parserRealSource11.ts(193,40): error TS1150: 'new T[]' cannot be used to create an array. Use 'new Array<T>()' instead.
tests/cases/conformance/parser/ecmascript5/parserRealSource11.ts(867,29): error TS1015: Parameter cannot have question mark and initializer.
tests/cases/conformance/parser/ecmascript5/parserRealSource11.ts(1009,45): error TS1150: 'new T[]' cannot be used to create an array. Use 'new Array<T>()' instead.
tests/cases/conformance/parser/ecmascript5/parserRealSource11.ts(1024,47): error TS1150: 'new T[]' cannot be used to create an array. Use 'new Array<T>()' instead.
tests/cases/conformance/parser/ecmascript5/parserRealSource11.ts(13,22): error TS2304: Cannot find name 'Type'.
@ -515,7 +514,7 @@ tests/cases/conformance/parser/ecmascript5/parserRealSource11.ts(2356,30): error
tests/cases/conformance/parser/ecmascript5/parserRealSource11.ts(2356,48): error TS2304: Cannot find name 'TokenID'.
==== tests/cases/conformance/parser/ecmascript5/parserRealSource11.ts (515 errors) ====
==== tests/cases/conformance/parser/ecmascript5/parserRealSource11.ts (514 errors) ====
// Copyright (c) Microsoft. All rights reserved. Licensed under the Apache License, Version 2.0.
// See LICENSE.txt in the project root for complete license information.
@ -1815,8 +1814,6 @@ tests/cases/conformance/parser/ecmascript5/parserRealSource11.ts(2356,48): error
}
public getAliasName(aliasAST?: AST = this.alias) : string {
~~~~~~~~
!!! error TS1015: Parameter cannot have question mark and initializer.
if (aliasAST.nodeType == NodeType.Name) {
~~~~~~~~
!!! error TS2304: Cannot find name 'NodeType'.

View file

@ -3,7 +3,6 @@ tests/cases/conformance/parser/ecmascript5/RealWorld/parserharness.ts(17,1): err
tests/cases/conformance/parser/ecmascript5/RealWorld/parserharness.ts(18,1): error TS6053: File 'tests/cases/conformance/parser/ecmascript5/services/typescriptServices.ts' not found.
tests/cases/conformance/parser/ecmascript5/RealWorld/parserharness.ts(19,1): error TS6053: File 'tests/cases/conformance/parser/ecmascript5/RealWorld/diff.ts' not found.
tests/cases/conformance/parser/ecmascript5/RealWorld/parserharness.ts(1430,9): error TS1128: Declaration or statement expected.
tests/cases/conformance/parser/ecmascript5/RealWorld/parserharness.ts(2047,13): error TS1015: Parameter cannot have question mark and initializer.
tests/cases/conformance/parser/ecmascript5/RealWorld/parserharness.ts(21,21): error TS2305: Module 'Harness' has no exported member 'Assert'.
tests/cases/conformance/parser/ecmascript5/RealWorld/parserharness.ts(25,17): error TS2304: Cannot find name 'IIO'.
tests/cases/conformance/parser/ecmascript5/RealWorld/parserharness.ts(41,12): error TS2304: Cannot find name 'ActiveXObject'.
@ -111,7 +110,7 @@ tests/cases/conformance/parser/ecmascript5/RealWorld/parserharness.ts(1787,68):
tests/cases/conformance/parser/ecmascript5/RealWorld/parserharness.ts(2030,32): error TS2304: Cannot find name 'Diff'.
==== tests/cases/conformance/parser/ecmascript5/RealWorld/parserharness.ts (111 errors) ====
==== tests/cases/conformance/parser/ecmascript5/RealWorld/parserharness.ts (110 errors) ====
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
@ -2379,8 +2378,6 @@ tests/cases/conformance/parser/ecmascript5/RealWorld/parserharness.ts(2030,32):
relativeFilename: string,
generateContent: () => string,
runImmediately? = false,
~~~~~~~~~~~~~~
!!! error TS1015: Parameter cannot have question mark and initializer.
opts?: BaselineOptions) {
var actual = <string>undefined;

View file

@ -2,7 +2,6 @@
(...arg?) => 102;
(...arg) => 103;
(...arg:number [] = []) => 104;
(...) => 105;
// Non optional parameter following an optional one
(arg1 = 1, arg2) => 1;