Simplify grammar check pass.

This commit is contained in:
Cyrus Najmabadi 2014-11-20 14:10:08 -08:00
parent ed22f1ca3e
commit 32864f47ca
3 changed files with 153 additions and 174 deletions

View file

@ -3526,14 +3526,12 @@ module ts {
function checkGrammar(sourceText: string, languageVersion: ScriptTarget, file: SourceFileInternal) { function checkGrammar(sourceText: string, languageVersion: ScriptTarget, file: SourceFileInternal) {
var grammarDiagnostics = file.grammarDiagnostics; var grammarDiagnostics = file.grammarDiagnostics;
// Create a scanner so we can find the start of tokens to report errors on.
var scanner = createScanner(languageVersion, /*skipTrivia*/ true, sourceText); var scanner = createScanner(languageVersion, /*skipTrivia*/ true, sourceText);
// We're automatically in an ambient context if this is a .d.ts file. // We're automatically in an ambient context if this is a .d.ts file.
var inAmbientContext = fileExtensionIs(file.filename, ".d.ts"); var inAmbientContext = fileExtensionIs(file.filename, ".d.ts");
if (inAmbientContext && checkTopLevelElementsForRequiredDeclareModifier(file)) {
return;
}
var inFunctionBlock = false; var inFunctionBlock = false;
var parent: Node; var parent: Node;
visitNode(file); visitNode(file);
@ -3573,11 +3571,8 @@ module ts {
return; return;
} }
var diagnosticCount = grammarDiagnostics.length;
checkNode(node, nodeKind);
// if we got any errors, just stop performing any more checks on this node or higher. // if we got any errors, just stop performing any more checks on this node or higher.
if (diagnosticCount !== grammarDiagnostics.length) { if (checkNode(node, nodeKind)) {
return; return;
} }
@ -3585,7 +3580,7 @@ module ts {
forEachChild(node, visitNode); forEachChild(node, visitNode);
} }
function checkNode(node: Node, nodeKind: SyntaxKind): any { function checkNode(node: Node, nodeKind: SyntaxKind): boolean {
// Now do node specific checks. // Now do node specific checks.
switch (nodeKind) { switch (nodeKind) {
case SyntaxKind.ArrowFunction: case SyntaxKind.ArrowFunction:
@ -3593,50 +3588,50 @@ module ts {
case SyntaxKind.ConstructorType: case SyntaxKind.ConstructorType:
case SyntaxKind.ConstructSignature: case SyntaxKind.ConstructSignature:
case SyntaxKind.FunctionType: case SyntaxKind.FunctionType:
return checkParsedSignature(<FunctionLikeDeclaration>node); return checkAnyParsedSignature(<FunctionLikeDeclaration>node);
case SyntaxKind.BreakStatement: case SyntaxKind.BreakStatement:
case SyntaxKind.ContinueStatement: case SyntaxKind.ContinueStatement:
return checkBreakOrContinueStatement(<BreakOrContinueStatement>node); return checkBreakOrContinueStatement(<BreakOrContinueStatement>node);
case SyntaxKind.LabeledStatement:
return checkLabeledStatement(<LabeledStatement>node);
case SyntaxKind.CallExpression: case SyntaxKind.CallExpression:
case SyntaxKind.NewExpression: case SyntaxKind.NewExpression:
return checkCallOrNewExpression(<NewExpression>node); return checkCallOrNewExpression(<NewExpression>node);
case SyntaxKind.EnumDeclaration: return checkEnumInitializer(<EnumDeclaration>node); case SyntaxKind.EnumDeclaration: return checkEnumDeclaration(<EnumDeclaration>node);
case SyntaxKind.Parameter: return checkParameter(<ParameterDeclaration>node); case SyntaxKind.Parameter: return checkParameter(<ParameterDeclaration>node);
case SyntaxKind.BinaryExpression: return visitBinaryExpression(<BinaryExpression>node); case SyntaxKind.BinaryExpression: return checkBinaryExpression(<BinaryExpression>node);
case SyntaxKind.CatchBlock: return visitCatchBlock(<CatchBlock>node); case SyntaxKind.CatchBlock: return checkCatchBlock(<CatchBlock>node);
case SyntaxKind.ClassDeclaration: return visitClassDeclaration(<ClassDeclaration>node); case SyntaxKind.ClassDeclaration: return checkClassDeclaration(<ClassDeclaration>node);
case SyntaxKind.Constructor: return visitConstructor(<ConstructorDeclaration>node); case SyntaxKind.Constructor: return checkConstructor(<ConstructorDeclaration>node);
case SyntaxKind.ExportAssignment: return visitExportAssignment(<ExportAssignment>node); case SyntaxKind.ExportAssignment: return checkExportAssignment(<ExportAssignment>node);
case SyntaxKind.ForInStatement: return visitForInStatement(<ForInStatement>node); case SyntaxKind.ForInStatement: return checkForInStatement(<ForInStatement>node);
case SyntaxKind.ForStatement: return visitForStatement(<ForStatement>node); case SyntaxKind.ForStatement: return checkForStatement(<ForStatement>node);
case SyntaxKind.FunctionDeclaration: return visitFunctionDeclaration(<FunctionLikeDeclaration>node); case SyntaxKind.FunctionDeclaration: return checkFunctionDeclaration(<FunctionLikeDeclaration>node);
case SyntaxKind.FunctionExpression: return visitFunctionExpression(<FunctionExpression>node); case SyntaxKind.FunctionExpression: return checkFunctionExpression(<FunctionExpression>node);
case SyntaxKind.GetAccessor: return visitGetAccessor(<MethodDeclaration>node); case SyntaxKind.GetAccessor: return checkGetAccessor(<MethodDeclaration>node);
case SyntaxKind.IndexedAccess: return visitIndexedAccess(<IndexedAccess>node); case SyntaxKind.IndexedAccess: return checkIndexedAccess(<IndexedAccess>node);
case SyntaxKind.IndexSignature: return visitIndexSignature(<SignatureDeclaration>node); case SyntaxKind.IndexSignature: return checkIndexSignature(<SignatureDeclaration>node);
case SyntaxKind.InterfaceDeclaration: return visitInterfaceDeclaration(<InterfaceDeclaration>node); case SyntaxKind.InterfaceDeclaration: return checkInterfaceDeclaration(<InterfaceDeclaration>node);
case SyntaxKind.Method: return visitMethod(<MethodDeclaration>node); case SyntaxKind.LabeledStatement: return checkLabeledStatement(<LabeledStatement>node);
case SyntaxKind.ModuleDeclaration: return visitModuleDeclaration(<ModuleDeclaration>node); case SyntaxKind.Method: return checkMethod(<MethodDeclaration>node);
case SyntaxKind.ObjectLiteral: return visitObjectLiteral(<ObjectLiteral>node); case SyntaxKind.ModuleDeclaration: return checkModuleDeclaration(<ModuleDeclaration>node);
case SyntaxKind.NumericLiteral: return visitNumericLiteral(<LiteralExpression>node); case SyntaxKind.ObjectLiteral: return checkObjectLiteral(<ObjectLiteral>node);
case SyntaxKind.PostfixOperator: return visitPostfixOperator(<UnaryExpression>node); case SyntaxKind.NumericLiteral: return checkNumericLiteral(<LiteralExpression>node);
case SyntaxKind.PrefixOperator: return visitPrefixOperator(<UnaryExpression>node); case SyntaxKind.PostfixOperator: return checkPostfixOperator(<UnaryExpression>node);
case SyntaxKind.Property: return visitProperty(<PropertyDeclaration>node); case SyntaxKind.PrefixOperator: return checkPrefixOperator(<UnaryExpression>node);
case SyntaxKind.PropertyAssignment: return visitPropertyAssignment(<PropertyDeclaration>node); case SyntaxKind.Property: return checkProperty(<PropertyDeclaration>node);
case SyntaxKind.ReturnStatement: return visitReturnStatement(<ReturnStatement>node); case SyntaxKind.PropertyAssignment: return checkPropertyAssignment(<PropertyDeclaration>node);
case SyntaxKind.SetAccessor: return visitSetAccessor(<MethodDeclaration>node); case SyntaxKind.ReturnStatement: return checkReturnStatement(<ReturnStatement>node);
case SyntaxKind.ShorthandPropertyAssignment: return visitShorthandPropertyAssignment(<ShortHandPropertyDeclaration>node); case SyntaxKind.SetAccessor: return checkSetAccessor(<MethodDeclaration>node);
case SyntaxKind.SwitchStatement: return visitSwitchStatement(<SwitchStatement>node); case SyntaxKind.SourceFile: return checkSourceFile(<SourceFile>node);
case SyntaxKind.TaggedTemplateExpression: return visitTaggedTemplateExpression(<TaggedTemplateExpression>node); case SyntaxKind.ShorthandPropertyAssignment: return checkShorthandPropertyAssignment(<ShortHandPropertyDeclaration>node);
case SyntaxKind.TupleType: return visitTupleType(<TupleTypeNode>node); case SyntaxKind.SwitchStatement: return checkSwitchStatement(<SwitchStatement>node);
case SyntaxKind.TypeParameter: return visitTypeParameter(<TypeParameterDeclaration>node); case SyntaxKind.TaggedTemplateExpression: return checkTaggedTemplateExpression(<TaggedTemplateExpression>node);
case SyntaxKind.TypeReference: return visitTypeReference(<TypeReferenceNode>node); case SyntaxKind.TupleType: return checkTupleType(<TupleTypeNode>node);
case SyntaxKind.VariableDeclaration: return visitVariableDeclaration(<VariableDeclaration>node); case SyntaxKind.TypeParameter: return checkTypeParameter(<TypeParameterDeclaration>node);
case SyntaxKind.VariableStatement: return visitVariableStatement(<VariableStatement>node); case SyntaxKind.TypeReference: return checkTypeReference(<TypeReferenceNode>node);
case SyntaxKind.WithStatement: return visitWithStatement(<WithStatement>node); case SyntaxKind.VariableDeclaration: return checkVariableDeclaration(<VariableDeclaration>node);
case SyntaxKind.VariableStatement: return checkVariableStatement(<VariableStatement>node);
case SyntaxKind.WithStatement: return checkWithStatement(<WithStatement>node);
} }
} }
@ -3669,39 +3664,6 @@ module ts {
return grammarErrorOnNode(node, Diagnostics.Invalid_use_of_0_in_strict_mode, name); return grammarErrorOnNode(node, Diagnostics.Invalid_use_of_0_in_strict_mode, name);
} }
function checkTopLevelElementsForRequiredDeclareModifier(file: SourceFile): boolean {
for (var i = 0, n = file.statements.length; i < n; i++) {
var decl = file.statements[i];
if (isDeclaration(decl) || decl.kind === SyntaxKind.VariableStatement) {
if (checkTopLevelElementForRequiredDeclareModifier(decl)) {
return true;
}
}
}
}
function checkTopLevelElementForRequiredDeclareModifier(node: Node): boolean {
// A declare modifier is required for any top level .d.ts declaration except export=, interfaces and imports:
// categories:
//
// DeclarationElement:
// ExportAssignment
// export_opt InterfaceDeclaration
// export_opt ImportDeclaration
// export_opt ExternalImportDeclaration
// export_opt AmbientDeclaration
//
if (node.kind === SyntaxKind.InterfaceDeclaration ||
node.kind === SyntaxKind.ImportDeclaration ||
node.kind === SyntaxKind.ExportAssignment ||
(node.flags & NodeFlags.Ambient)) {
return false;
}
return grammarErrorOnFirstToken(node, Diagnostics.A_declare_modifier_is_required_for_a_top_level_declaration_in_a_d_ts_file);
}
function checkForStatementInAmbientContext(node: Node, kind: SyntaxKind): boolean { function checkForStatementInAmbientContext(node: Node, kind: SyntaxKind): boolean {
switch (kind) { switch (kind) {
case SyntaxKind.Block: case SyntaxKind.Block:
@ -3725,18 +3687,18 @@ module ts {
} }
} }
function checkParsedSignature(node: ParsedSignature): boolean { function checkAnyParsedSignature(node: ParsedSignature): boolean {
return checkTypeParameterList(node.typeParameters) || return checkTypeParameterList(node.typeParameters) ||
checkParameterList(node.parameters); checkParameterList(node.parameters);
} }
function visitBinaryExpression(node: BinaryExpression) { function checkBinaryExpression(node: BinaryExpression) {
if (node.flags & NodeFlags.ParsedInStrictMode) { if (node.flags & NodeFlags.ParsedInStrictMode) {
if (isLeftHandSideExpression(node.left) && isAssignmentOperator(node.operator)) { if (isLeftHandSideExpression(node.left) && isAssignmentOperator(node.operator)) {
if (isEvalOrArgumentsIdentifier(node.left)) { if (isEvalOrArgumentsIdentifier(node.left)) {
// ECMA 262 (Annex C) The identifier eval or arguments may not appear as the LeftHandSideExpression of an // ECMA 262 (Annex C) The identifier eval or arguments may not appear as the LeftHandSideExpression of an
// Assignment operator(11.13) or of a PostfixExpression(11.3) // Assignment operator(11.13) or of a PostfixExpression(11.3)
reportInvalidUseInStrictMode(<Identifier>node.left); return reportInvalidUseInStrictMode(<Identifier>node.left);
} }
} }
} }
@ -3825,7 +3787,7 @@ module ts {
} }
function checkCallOrNewExpression(node: CallExpression) { function checkCallOrNewExpression(node: CallExpression) {
checkTypeArguments(node.typeArguments) || return checkTypeArguments(node.typeArguments) ||
checkArguments(node.arguments); checkArguments(node.arguments);
} }
@ -3878,20 +3840,20 @@ module ts {
} }
} }
function visitCatchBlock(node: CatchBlock) { function checkCatchBlock(node: CatchBlock) {
if (node.type) { if (node.type) {
var colonStart = skipTrivia(sourceText, node.variable.end); var colonStart = skipTrivia(sourceText, node.variable.end);
grammarErrorAtPos(colonStart, ":".length, Diagnostics.Catch_clause_parameter_cannot_have_a_type_annotation); return grammarErrorAtPos(colonStart, ":".length, Diagnostics.Catch_clause_parameter_cannot_have_a_type_annotation);
} }
if (node.flags & NodeFlags.ParsedInStrictMode && isEvalOrArgumentsIdentifier(node.variable)) { if (node.flags & NodeFlags.ParsedInStrictMode && isEvalOrArgumentsIdentifier(node.variable)) {
// It is a SyntaxError if a TryStatement with a Catch occurs within strict code and the Identifier of the // It is a SyntaxError if a TryStatement with a Catch occurs within strict code and the Identifier of the
// Catch production is eval or arguments // Catch production is eval or arguments
reportInvalidUseInStrictMode(node.variable); return reportInvalidUseInStrictMode(node.variable);
} }
} }
function visitClassDeclaration(node: ClassDeclaration) { function checkClassDeclaration(node: ClassDeclaration) {
checkForDisallowedTrailingComma(node.implementedTypes) || return checkForDisallowedTrailingComma(node.implementedTypes) ||
checkForAtLeastOneHeritageClause(node.implementedTypes, "implements"); checkForAtLeastOneHeritageClause(node.implementedTypes, "implements");
} }
@ -3901,8 +3863,8 @@ module ts {
} }
} }
function visitConstructor(node: ConstructorDeclaration) { function checkConstructor(node: ConstructorDeclaration) {
checkParsedSignature(node) || return checkAnyParsedSignature(node) ||
checkConstructorTypeParameters(node) || checkConstructorTypeParameters(node) ||
checkConstructorTypeAnnotation(node) || checkConstructorTypeAnnotation(node) ||
checkForBodyInAmbientContext(node.body, /*isConstructor:*/ true); checkForBodyInAmbientContext(node.body, /*isConstructor:*/ true);
@ -3920,7 +3882,7 @@ module ts {
} }
} }
function checkEnumInitializer(enumDecl: EnumDeclaration): boolean { function checkEnumDeclaration(enumDecl: EnumDeclaration): boolean {
var enumIsConst = (enumDecl.flags & NodeFlags.Const) !== 0; var enumIsConst = (enumDecl.flags & NodeFlags.Const) !== 0;
var hasError = false; var hasError = false;
@ -3943,6 +3905,7 @@ module ts {
} }
} }
} }
return hasError; return hasError;
} }
@ -3969,19 +3932,19 @@ module ts {
return false; return false;
} }
function visitExportAssignment(node: ExportAssignment) { function checkExportAssignment(node: ExportAssignment) {
if (node.flags & NodeFlags.Modifier) { if (node.flags & NodeFlags.Modifier) {
grammarErrorOnFirstToken(node, Diagnostics.An_export_assignment_cannot_have_modifiers); return grammarErrorOnFirstToken(node, Diagnostics.An_export_assignment_cannot_have_modifiers);
} }
} }
function visitForInStatement(node: ForInStatement) { function checkForInStatement(node: ForInStatement) {
checkVariableDeclarations(node.declarations) || return checkVariableDeclarations(node.declarations) ||
checkForMoreThanOneDeclaration(node.declarations); checkForMoreThanOneDeclaration(node.declarations);
} }
function visitForStatement(node: ForStatement) { function checkForStatement(node: ForStatement) {
checkVariableDeclarations(node.declarations); return checkVariableDeclarations(node.declarations);
} }
function checkForMoreThanOneDeclaration(declarations: NodeArray<VariableDeclaration>) { function checkForMoreThanOneDeclaration(declarations: NodeArray<VariableDeclaration>) {
@ -3990,14 +3953,14 @@ module ts {
} }
} }
function visitFunctionDeclaration(node: FunctionLikeDeclaration) { function checkFunctionDeclaration(node: FunctionLikeDeclaration) {
checkParsedSignature(node) || return checkAnyParsedSignature(node) ||
checkFunctionName(node.name) || checkFunctionName(node.name) ||
checkForBodyInAmbientContext(node.body, /*isConstructor:*/ false); checkForBodyInAmbientContext(node.body, /*isConstructor:*/ false);
} }
function visitFunctionExpression(node: FunctionExpression) { function checkFunctionExpression(node: FunctionExpression) {
checkParsedSignature(node) || return checkAnyParsedSignature(node) ||
checkFunctionName(node.name); checkFunctionName(node.name);
} }
@ -4009,24 +3972,24 @@ module ts {
} }
} }
function visitGetAccessor(node: MethodDeclaration) { function checkGetAccessor(node: MethodDeclaration) {
checkParsedSignature(node) || return checkAnyParsedSignature(node) ||
checkAccessor(node); checkAccessor(node);
} }
function visitIndexedAccess(node: IndexedAccess): void { function checkIndexedAccess(node: IndexedAccess) {
if (node.index.kind === SyntaxKind.Missing && if (node.index.kind === SyntaxKind.Missing &&
node.parent.kind === SyntaxKind.NewExpression && node.parent.kind === SyntaxKind.NewExpression &&
(<NewExpression>node.parent).func === node) { (<NewExpression>node.parent).func === node) {
var start = skipTrivia(sourceText, node.parent.pos); var start = skipTrivia(sourceText, node.parent.pos);
var end = node.end; var end = node.end;
grammarErrorAtPos(start, end - start, Diagnostics.new_T_cannot_be_used_to_create_an_array_Use_new_Array_T_instead); return grammarErrorAtPos(start, end - start, Diagnostics.new_T_cannot_be_used_to_create_an_array_Use_new_Array_T_instead);
} }
} }
function visitIndexSignature(node: SignatureDeclaration): void { function checkIndexSignature(node: SignatureDeclaration): boolean {
checkIndexSignatureParameters(node) || return checkIndexSignatureParameters(node) ||
checkForIndexSignatureModifiers(node); checkForIndexSignatureModifiers(node);
} }
@ -4069,13 +4032,13 @@ module ts {
} }
} }
function visitInterfaceDeclaration(node: InterfaceDeclaration) { function checkInterfaceDeclaration(node: InterfaceDeclaration) {
checkForDisallowedTrailingComma(node.baseTypes) || return checkForDisallowedTrailingComma(node.baseTypes) ||
checkForAtLeastOneHeritageClause(node.baseTypes, "extends"); checkForAtLeastOneHeritageClause(node.baseTypes, "extends");
} }
function visitMethod(node: MethodDeclaration) { function checkMethod(node: MethodDeclaration) {
checkParsedSignature(node) || return checkAnyParsedSignature(node) ||
checkForBodyInAmbientContext(node.body, /*isConstructor:*/ false) || checkForBodyInAmbientContext(node.body, /*isConstructor:*/ false) ||
(node.parent.kind === SyntaxKind.ClassDeclaration && checkForInvalidQuestionMark(node, Diagnostics.A_class_member_cannot_be_declared_optional)); (node.parent.kind === SyntaxKind.ClassDeclaration && checkForInvalidQuestionMark(node, Diagnostics.A_class_member_cannot_be_declared_optional));
} }
@ -4089,8 +4052,8 @@ module ts {
} }
} }
function visitModuleDeclaration(node: ModuleDeclaration): void { function checkModuleDeclaration(node: ModuleDeclaration): boolean {
checkModuleDeclarationName(node) || return checkModuleDeclarationName(node) ||
checkModuleDeclarationStatements(node); checkModuleDeclarationStatements(node);
} }
@ -4117,7 +4080,7 @@ module ts {
} }
} }
function visitObjectLiteral(node: ObjectLiteral): void { function checkObjectLiteral(node: ObjectLiteral): boolean {
var seen: Map<SymbolFlags> = {}; var seen: Map<SymbolFlags> = {};
var Property = 1; var Property = 1;
var GetAccessor = 2; var GetAccessor = 2;
@ -4175,23 +4138,23 @@ module ts {
seen[name.text] = currentKind | existingKind; seen[name.text] = currentKind | existingKind;
} }
else { else {
grammarErrorOnNode(name, Diagnostics.An_object_literal_cannot_have_multiple_get_Slashset_accessors_with_the_same_name); return grammarErrorOnNode(name, Diagnostics.An_object_literal_cannot_have_multiple_get_Slashset_accessors_with_the_same_name);
} }
} }
else { else {
grammarErrorOnNode(name, Diagnostics.An_object_literal_cannot_have_property_and_accessor_with_the_same_name); return grammarErrorOnNode(name, Diagnostics.An_object_literal_cannot_have_property_and_accessor_with_the_same_name);
} }
} }
} }
} }
function visitNumericLiteral(node: LiteralExpression): void { function checkNumericLiteral(node: LiteralExpression): boolean {
if (node.flags & NodeFlags.OctalLiteral) { if (node.flags & NodeFlags.OctalLiteral) {
if (node.flags & NodeFlags.ParsedInStrictMode) { if (node.flags & NodeFlags.ParsedInStrictMode) {
grammarErrorOnNode(node, Diagnostics.Octal_literals_are_not_allowed_in_strict_mode); return grammarErrorOnNode(node, Diagnostics.Octal_literals_are_not_allowed_in_strict_mode);
} }
else if (languageVersion >= ScriptTarget.ES5) { else if (languageVersion >= ScriptTarget.ES5) {
grammarErrorOnNode(node, Diagnostics.Octal_literals_are_not_available_when_targeting_ECMAScript_5_and_higher); return grammarErrorOnNode(node, Diagnostics.Octal_literals_are_not_available_when_targeting_ECMAScript_5_and_higher);
} }
} }
} }
@ -4386,33 +4349,33 @@ module ts {
} }
} }
function visitPostfixOperator(node: UnaryExpression) { function checkPostfixOperator(node: UnaryExpression) {
// The identifier eval or arguments may not appear as the LeftHandSideExpression of an // The identifier eval or arguments may not appear as the LeftHandSideExpression of an
// Assignment operator(11.13) or of a PostfixExpression(11.3) or as the UnaryExpression // Assignment operator(11.13) or of a PostfixExpression(11.3) or as the UnaryExpression
// operated upon by a Prefix Increment(11.4.4) or a Prefix Decrement(11.4.5) operator. // operated upon by a Prefix Increment(11.4.4) or a Prefix Decrement(11.4.5) operator.
if (node.flags & NodeFlags.ParsedInStrictMode && isEvalOrArgumentsIdentifier(node.operand)) { if (node.flags & NodeFlags.ParsedInStrictMode && isEvalOrArgumentsIdentifier(node.operand)) {
reportInvalidUseInStrictMode(<Identifier>node.operand); return reportInvalidUseInStrictMode(<Identifier>node.operand);
} }
} }
function visitPrefixOperator(node: UnaryExpression) { function checkPrefixOperator(node: UnaryExpression) {
if (node.flags & NodeFlags.ParsedInStrictMode) { if (node.flags & NodeFlags.ParsedInStrictMode) {
// The identifier eval or arguments may not appear as the LeftHandSideExpression of an // The identifier eval or arguments may not appear as the LeftHandSideExpression of an
// Assignment operator(11.13) or of a PostfixExpression(11.3) or as the UnaryExpression // Assignment operator(11.13) or of a PostfixExpression(11.3) or as the UnaryExpression
// operated upon by a Prefix Increment(11.4.4) or a Prefix Decrement(11.4.5) operator // operated upon by a Prefix Increment(11.4.4) or a Prefix Decrement(11.4.5) operator
if ((node.operator === SyntaxKind.PlusPlusToken || node.operator === SyntaxKind.MinusMinusToken) && isEvalOrArgumentsIdentifier(node.operand)) { if ((node.operator === SyntaxKind.PlusPlusToken || node.operator === SyntaxKind.MinusMinusToken) && isEvalOrArgumentsIdentifier(node.operand)) {
reportInvalidUseInStrictMode(<Identifier>node.operand); return reportInvalidUseInStrictMode(<Identifier>node.operand);
} }
else if (node.operator === SyntaxKind.DeleteKeyword && node.operand.kind === SyntaxKind.Identifier) { else if (node.operator === SyntaxKind.DeleteKeyword && node.operand.kind === SyntaxKind.Identifier) {
// When a delete operator occurs within strict mode code, a SyntaxError is thrown if its // When a delete operator occurs within strict mode code, a SyntaxError is thrown if its
// UnaryExpression is a direct reference to a variable, function argument, or function name // UnaryExpression is a direct reference to a variable, function argument, or function name
grammarErrorOnNode(node.operand, Diagnostics.delete_cannot_be_called_on_an_identifier_in_strict_mode); return grammarErrorOnNode(node.operand, Diagnostics.delete_cannot_be_called_on_an_identifier_in_strict_mode);
} }
} }
} }
function visitProperty(node: PropertyDeclaration) { function checkProperty(node: PropertyDeclaration) {
(node.parent.kind === SyntaxKind.ClassDeclaration && checkForInvalidQuestionMark(node, Diagnostics.A_class_member_cannot_be_declared_optional)) || return (node.parent.kind === SyntaxKind.ClassDeclaration && checkForInvalidQuestionMark(node, Diagnostics.A_class_member_cannot_be_declared_optional)) ||
checkForInitializerInAmbientContext(node); checkForInitializerInAmbientContext(node);
} }
@ -4422,8 +4385,8 @@ module ts {
} }
} }
function visitPropertyAssignment(node: PropertyDeclaration) { function checkPropertyAssignment(node: PropertyDeclaration) {
checkForInvalidQuestionMark(node, Diagnostics.An_object_member_cannot_be_declared_optional); return checkForInvalidQuestionMark(node, Diagnostics.An_object_member_cannot_be_declared_optional);
} }
function checkForInvalidQuestionMark(node: Declaration, message: DiagnosticMessage) { function checkForInvalidQuestionMark(node: Declaration, message: DiagnosticMessage) {
@ -4433,14 +4396,14 @@ module ts {
} }
} }
function visitReturnStatement(node: ReturnStatement) { function checkReturnStatement(node: ReturnStatement) {
if (!inFunctionBlock) { if (!inFunctionBlock) {
grammarErrorOnFirstToken(node, Diagnostics.A_return_statement_can_only_be_used_within_a_function_body); return grammarErrorOnFirstToken(node, Diagnostics.A_return_statement_can_only_be_used_within_a_function_body);
} }
} }
function visitSetAccessor(node: MethodDeclaration) { function checkSetAccessor(node: MethodDeclaration) {
checkParsedSignature(node) || return checkAnyParsedSignature(node) ||
checkAccessor(node); checkAccessor(node);
} }
@ -4486,11 +4449,48 @@ module ts {
} }
} }
function visitShorthandPropertyAssignment(node: ShortHandPropertyDeclaration): void { function checkSourceFile(node: SourceFile): boolean {
checkForInvalidQuestionMark(node, Diagnostics.An_object_member_cannot_be_declared_optional); return inAmbientContext && checkTopLevelElementsForRequiredDeclareModifier(file);
} }
function visitSwitchStatement(node: SwitchStatement) { function checkTopLevelElementsForRequiredDeclareModifier(file: SourceFile): boolean {
for (var i = 0, n = file.statements.length; i < n; i++) {
var decl = file.statements[i];
if (isDeclaration(decl) || decl.kind === SyntaxKind.VariableStatement) {
if (checkTopLevelElementForRequiredDeclareModifier(decl)) {
return true;
}
}
}
}
function checkTopLevelElementForRequiredDeclareModifier(node: Node): boolean {
// A declare modifier is required for any top level .d.ts declaration except export=, interfaces and imports:
// categories:
//
// DeclarationElement:
// ExportAssignment
// export_opt InterfaceDeclaration
// export_opt ImportDeclaration
// export_opt ExternalImportDeclaration
// export_opt AmbientDeclaration
//
if (node.kind === SyntaxKind.InterfaceDeclaration ||
node.kind === SyntaxKind.ImportDeclaration ||
node.kind === SyntaxKind.ExportAssignment ||
(node.flags & NodeFlags.Ambient)) {
return false;
}
return grammarErrorOnFirstToken(node, Diagnostics.A_declare_modifier_is_required_for_a_top_level_declaration_in_a_d_ts_file);
}
function checkShorthandPropertyAssignment(node: ShortHandPropertyDeclaration): boolean {
return checkForInvalidQuestionMark(node, Diagnostics.An_object_member_cannot_be_declared_optional);
}
function checkSwitchStatement(node: SwitchStatement) {
var firstDefaultClause: CaseOrDefaultClause; var firstDefaultClause: CaseOrDefaultClause;
// Error on duplicate 'default' clauses. // Error on duplicate 'default' clauses.
@ -4503,20 +4503,20 @@ module ts {
else { else {
var start = skipTrivia(file.text, clause.pos); var start = skipTrivia(file.text, clause.pos);
var end = clause.statements.length > 0 ? clause.statements[0].pos : clause.end; var end = clause.statements.length > 0 ? clause.statements[0].pos : clause.end;
grammarErrorAtPos(start, end - start, Diagnostics.A_default_clause_cannot_appear_more_than_once_in_a_switch_statement); return grammarErrorAtPos(start, end - start, Diagnostics.A_default_clause_cannot_appear_more_than_once_in_a_switch_statement);
} }
} }
} }
} }
function visitTaggedTemplateExpression(node: TaggedTemplateExpression) { function checkTaggedTemplateExpression(node: TaggedTemplateExpression) {
if (languageVersion < ScriptTarget.ES6) { if (languageVersion < ScriptTarget.ES6) {
grammarErrorOnFirstToken(node.template, Diagnostics.Tagged_templates_are_only_available_when_targeting_ECMAScript_6_and_higher); return grammarErrorOnFirstToken(node.template, Diagnostics.Tagged_templates_are_only_available_when_targeting_ECMAScript_6_and_higher);
} }
} }
function visitTupleType(node: TupleTypeNode) { function checkTupleType(node: TupleTypeNode) {
checkForDisallowedTrailingComma(node.elementTypes) || return checkForDisallowedTrailingComma(node.elementTypes) ||
checkForAtLeastOneType(node); checkForAtLeastOneType(node);
} }
@ -4526,28 +4526,28 @@ module ts {
} }
} }
function visitTypeParameter(node: TypeParameterDeclaration) { function checkTypeParameter(node: TypeParameterDeclaration) {
if (node.expression) { if (node.expression) {
grammarErrorOnFirstToken(node.expression, Diagnostics.Type_expected); return grammarErrorOnFirstToken(node.expression, Diagnostics.Type_expected);
} }
} }
function visitTypeReference(node: TypeReferenceNode) { function checkTypeReference(node: TypeReferenceNode) {
checkTypeArguments(node.typeArguments); return checkTypeArguments(node.typeArguments);
} }
function visitVariableDeclaration(node: VariableDeclaration) { function checkVariableDeclaration(node: VariableDeclaration) {
if (inAmbientContext && node.initializer) { if (inAmbientContext && node.initializer) {
var equalsPos = node.type ? skipTrivia(sourceText, node.type.end) : skipTrivia(sourceText, node.name.end); var equalsPos = node.type ? skipTrivia(sourceText, node.type.end) : skipTrivia(sourceText, node.name.end);
grammarErrorAtPos(equalsPos, "=".length, Diagnostics.Initializers_are_not_allowed_in_ambient_contexts); return grammarErrorAtPos(equalsPos, "=".length, Diagnostics.Initializers_are_not_allowed_in_ambient_contexts);
} }
if (!inAmbientContext && !node.initializer && node.flags & NodeFlags.Const) { if (!inAmbientContext && !node.initializer && node.flags & NodeFlags.Const) {
grammarErrorOnNode(node, Diagnostics.const_declarations_must_be_initialized); return grammarErrorOnNode(node, Diagnostics.const_declarations_must_be_initialized);
} }
if (node.flags & NodeFlags.ParsedInStrictMode && isEvalOrArgumentsIdentifier(node.name)) { if (node.flags & NodeFlags.ParsedInStrictMode && isEvalOrArgumentsIdentifier(node.name)) {
// It is a SyntaxError if a VariableDeclaration or VariableDeclarationNoIn occurs within strict code // It is a SyntaxError if a VariableDeclaration or VariableDeclarationNoIn occurs within strict code
// and its Identifier is eval or arguments // and its Identifier is eval or arguments
reportInvalidUseInStrictMode(node.name); return reportInvalidUseInStrictMode(node.name);
} }
} }
@ -4573,8 +4573,8 @@ module ts {
} }
} }
function visitVariableStatement(node: VariableStatement) { function checkVariableStatement(node: VariableStatement) {
checkVariableDeclarations(node.declarations) || return checkVariableDeclarations(node.declarations) ||
checkForDisallowedLetOrConstStatement(node); checkForDisallowedLetOrConstStatement(node);
} }
@ -4605,11 +4605,11 @@ module ts {
return true; return true;
} }
function visitWithStatement(node: WithStatement): void { function checkWithStatement(node: WithStatement): boolean {
if (node.flags & NodeFlags.ParsedInStrictMode) { if (node.flags & NodeFlags.ParsedInStrictMode) {
// Strict mode code may not include a WithStatement. The occurrence of a WithStatement in such // Strict mode code may not include a WithStatement. The occurrence of a WithStatement in such
// a context is an // a context is an
grammarErrorOnFirstToken(node, Diagnostics.with_statements_are_not_allowed_in_strict_mode); return grammarErrorOnFirstToken(node, Diagnostics.with_statements_are_not_allowed_in_strict_mode);
} }
} }
} }

View file

@ -1,14 +1,8 @@
tests/cases/compiler/switchStatementsWithMultipleDefaults.ts(9,5): error TS1113: A 'default' clause cannot appear more than once in a 'switch' statement. tests/cases/compiler/switchStatementsWithMultipleDefaults.ts(9,5): error TS1113: A 'default' clause cannot appear more than once in a 'switch' statement.
tests/cases/compiler/switchStatementsWithMultipleDefaults.ts(10,5): error TS1113: A 'default' clause cannot appear more than once in a 'switch' statement.
tests/cases/compiler/switchStatementsWithMultipleDefaults.ts(21,13): error TS1113: A 'default' clause cannot appear more than once in a 'switch' statement. tests/cases/compiler/switchStatementsWithMultipleDefaults.ts(21,13): error TS1113: A 'default' clause cannot appear more than once in a 'switch' statement.
tests/cases/compiler/switchStatementsWithMultipleDefaults.ts(25,13): error TS1113: A 'default' clause cannot appear more than once in a 'switch' statement.
tests/cases/compiler/switchStatementsWithMultipleDefaults.ts(26,13): error TS1113: A 'default' clause cannot appear more than once in a 'switch' statement.
tests/cases/compiler/switchStatementsWithMultipleDefaults.ts(28,13): error TS1113: A 'default' clause cannot appear more than once in a 'switch' statement.
tests/cases/compiler/switchStatementsWithMultipleDefaults.ts(29,13): error TS1113: A 'default' clause cannot appear more than once in a 'switch' statement.
tests/cases/compiler/switchStatementsWithMultipleDefaults.ts(29,22): error TS1113: A 'default' clause cannot appear more than once in a 'switch' statement.
==== tests/cases/compiler/switchStatementsWithMultipleDefaults.ts (8 errors) ==== ==== tests/cases/compiler/switchStatementsWithMultipleDefaults.ts (2 errors) ====
var x = 10; var x = 10;
@ -21,8 +15,6 @@ tests/cases/compiler/switchStatementsWithMultipleDefaults.ts(29,22): error TS111
~~~~~~~~ ~~~~~~~~
!!! error TS1113: A 'default' clause cannot appear more than once in a 'switch' statement. !!! error TS1113: A 'default' clause cannot appear more than once in a 'switch' statement.
default: // Error; third 'default' clause. default: // Error; third 'default' clause.
~~~~~~~~
!!! error TS1113: A 'default' clause cannot appear more than once in a 'switch' statement.
case 3: case 3:
x *= x; x *= x;
} }
@ -40,19 +32,9 @@ tests/cases/compiler/switchStatementsWithMultipleDefaults.ts(29,22): error TS111
case 10000: case 10000:
x /= x; x /= x;
default: // Error, third 'default' clause default: // Error, third 'default' clause
~~~~~~~~
!!! error TS1113: A 'default' clause cannot appear more than once in a 'switch' statement.
def\u0061ult: // Error, fourth 'default' clause. def\u0061ult: // Error, fourth 'default' clause.
~~~~~~~~~~~~~
!!! error TS1113: A 'default' clause cannot appear more than once in a 'switch' statement.
// Errors on fifth-seventh // Errors on fifth-seventh
default: return; default: return;
~~~~~~~~
!!! error TS1113: A 'default' clause cannot appear more than once in a 'switch' statement.
default: default: default: default:
~~~~~~~~
!!! error TS1113: A 'default' clause cannot appear more than once in a 'switch' statement.
~~~~~~~~
!!! error TS1113: A 'default' clause cannot appear more than once in a 'switch' statement.
} }
} }

View file

@ -1,8 +1,7 @@
tests/cases/compiler/switchStatementsWithMultipleDefaults1.ts(8,9): error TS1113: A 'default' clause cannot appear more than once in a 'switch' statement. tests/cases/compiler/switchStatementsWithMultipleDefaults1.ts(8,9): error TS1113: A 'default' clause cannot appear more than once in a 'switch' statement.
tests/cases/compiler/switchStatementsWithMultipleDefaults1.ts(9,9): error TS1113: A 'default' clause cannot appear more than once in a 'switch' statement.
==== tests/cases/compiler/switchStatementsWithMultipleDefaults1.ts (2 errors) ==== ==== tests/cases/compiler/switchStatementsWithMultipleDefaults1.ts (1 errors) ====
var x = 10; var x = 10;
switch (x) { switch (x) {
@ -14,8 +13,6 @@ tests/cases/compiler/switchStatementsWithMultipleDefaults1.ts(9,9): error TS1113
~~~~~~~~ ~~~~~~~~
!!! error TS1113: A 'default' clause cannot appear more than once in a 'switch' statement. !!! error TS1113: A 'default' clause cannot appear more than once in a 'switch' statement.
default: // Error; third 'default' clause. default: // Error; third 'default' clause.
~~~~~~~~
!!! error TS1113: A 'default' clause cannot appear more than once in a 'switch' statement.
case 3: case 3:
x *= x; x *= x;
} }