Move ambient statement checks to the grammar checker.

This commit is contained in:
Cyrus Najmabadi
2014-11-19 13:26:15 -08:00
parent abbd89aa2b
commit 8b832a5713
10 changed files with 133 additions and 80 deletions

View File

@@ -3810,20 +3810,9 @@ module ts {
}
function parseSourceElementOrModuleElement(modifierContext: ModifierContext): Statement {
if (isDeclarationStart()) {
return parseDeclaration(modifierContext);
}
var statementStart = scanner.getTokenPos();
var statementFirstTokenLength = scanner.getTextPos() - statementStart;
var errorCountBeforeStatement = file._parserDiagnostics.length;
var statement = parseStatement();
if (inAmbientContext && file._parserDiagnostics.length === errorCountBeforeStatement) {
grammarErrorAtPos(statementStart, statementFirstTokenLength, Diagnostics.Statements_are_not_allowed_in_ambient_contexts);
}
return statement;
return isDeclarationStart()
? parseDeclaration(modifierContext)
: parseStatement();
}
function processReferenceComments(): ReferenceComments {
@@ -3970,6 +3959,7 @@ module ts {
function checkGrammar(sourceText: string, languageVersion: ScriptTarget, file: SourceFileInternal) {
var syntacticDiagnostics = file._syntacticDiagnostics;
var scanner = createScanner(languageVersion, /*skipTrivia*/ true, sourceText);
// We're automatically in an ambient context if this is a .d.ts file.
var inAmbientContext = fileExtensionIs(file.filename, ".d.ts");
@@ -3977,31 +3967,44 @@ module ts {
visitNode(file);
function visitNode(node: Node): void {
// Store and restore our recursive state here.
var savedParent = parent;
node.parent = parent;
parent = node;
// First recurse and perform all grammar checks on the children of this node.
var savedInAmbientContext = inAmbientContext
if (node.flags & NodeFlags.Ambient) {
inAmbientContext = true;
}
var diagnosticCount = syntacticDiagnostics.length;
forEachChild(node, visitNode);
// If any children had an grammar error, then skip reporting errors for this node or
// anything higher.
if (diagnosticCount === syntacticDiagnostics.length) {
checkNode(node);
}
checkNode(node);
inAmbientContext = savedInAmbientContext;
parent = savedParent;
}
function checkNode(node: Node) {
// No grammar errors on any of our children. Check this node for grammar errors.
// First, check if you have a statement in a place where it is not allowed. We want
// to do this before recursing, because we'd prefer to report these errors at the top
// level instead of at some nested level.
if (checkForStatementInAmbientContext(node)) {
return;
}
// Now recurse and perform all grammar checks on the children of this node.
var diagnosticCount = syntacticDiagnostics.length;
forEachChild(node, visitNode);
// if we got any errors, just stop performing any more checks on this node or higher.
if (diagnosticCount !== syntacticDiagnostics.length) {
return;
}
// Now do node specific checks.
dispatch(node);
}
function dispatch(node: Node) {
switch (node.kind) {
case SyntaxKind.ArrowFunction: return visitArrowFunction(<FunctionExpression>node);
case SyntaxKind.BinaryExpression: return visitBinaryExpression(<BinaryExpression>node);
@@ -4038,6 +4041,15 @@ module ts {
}
}
function grammarErrorOnFirstToken(node: Node, message: DiagnosticMessage, arg0?: any, arg1?: any, arg2?: any): boolean {
var start = skipTrivia(sourceText, node.pos);
scanner.setTextPos(start);
scanner.scan();
var end = scanner.getTextPos();
file._syntacticDiagnostics.push(createFileDiagnostic(file, start, end - start, message, arg0, arg1, arg2));
return true;
}
function grammarErrorOnNode(node: Node, message: DiagnosticMessage, arg0?: any, arg1?: any, arg2?: any): boolean {
var span = getErrorSpanForNode(node);
var start = span.end > span.pos ? skipTrivia(file.text, span.pos) : span.pos;
@@ -4058,6 +4070,31 @@ module ts {
return grammarErrorOnNode(node, Diagnostics.Invalid_use_of_0_in_strict_mode, name);
}
function checkForStatementInAmbientContext(node: Node): boolean {
if (inAmbientContext) {
switch (node.kind) {
case SyntaxKind.Block:
case SyntaxKind.EmptyStatement:
case SyntaxKind.IfStatement:
case SyntaxKind.DoStatement:
case SyntaxKind.WhileStatement:
case SyntaxKind.ForStatement:
case SyntaxKind.ForInStatement:
case SyntaxKind.ContinueStatement:
case SyntaxKind.BreakStatement:
case SyntaxKind.ReturnStatement:
case SyntaxKind.WithStatement:
case SyntaxKind.SwitchStatement:
case SyntaxKind.ThrowStatement:
case SyntaxKind.TryStatement:
case SyntaxKind.DebuggerStatement:
case SyntaxKind.LabeledStatement:
case SyntaxKind.ExpressionStatement:
return grammarErrorOnFirstToken(node, Diagnostics.Statements_are_not_allowed_in_ambient_contexts);
}
}
}
function visitArrowFunction(node: FunctionExpression) {
checkTypeParameterList(node.typeParameters) ||
checkParameterList(node.parameters);

View File

@@ -1,10 +1,10 @@
tests/cases/compiler/accessorsInAmbientContext.ts(4,13): error TS1086: An accessor cannot be declared in an ambient context.
tests/cases/compiler/accessorsInAmbientContext.ts(4,19): error TS1036: Statements are not allowed in ambient contexts.
tests/cases/compiler/accessorsInAmbientContext.ts(5,13): error TS1086: An accessor cannot be declared in an ambient context.
tests/cases/compiler/accessorsInAmbientContext.ts(7,20): error TS1086: An accessor cannot be declared in an ambient context.
tests/cases/compiler/accessorsInAmbientContext.ts(7,26): error TS1036: Statements are not allowed in ambient contexts.
tests/cases/compiler/accessorsInAmbientContext.ts(8,20): error TS1086: An accessor cannot be declared in an ambient context.
tests/cases/compiler/accessorsInAmbientContext.ts(13,9): error TS1086: An accessor cannot be declared in an ambient context.
tests/cases/compiler/accessorsInAmbientContext.ts(13,15): error TS1036: Statements are not allowed in ambient contexts.
tests/cases/compiler/accessorsInAmbientContext.ts(14,9): error TS1086: An accessor cannot be declared in an ambient context.
tests/cases/compiler/accessorsInAmbientContext.ts(16,16): error TS1086: An accessor cannot be declared in an ambient context.
tests/cases/compiler/accessorsInAmbientContext.ts(16,22): error TS1036: Statements are not allowed in ambient contexts.
tests/cases/compiler/accessorsInAmbientContext.ts(17,16): error TS1086: An accessor cannot be declared in an ambient context.
@@ -13,15 +13,15 @@ tests/cases/compiler/accessorsInAmbientContext.ts(17,16): error TS1086: An acces
declare module M {
class C {
get X() { return 1; }
~
!!! error TS1086: An accessor cannot be declared in an ambient context.
~~~~~~
!!! error TS1036: Statements are not allowed in ambient contexts.
set X(v) { }
~
!!! error TS1086: An accessor cannot be declared in an ambient context.
static get Y() { return 1; }
~
!!! error TS1086: An accessor cannot be declared in an ambient context.
~~~~~~
!!! error TS1036: Statements are not allowed in ambient contexts.
static set Y(v) { }
~
!!! error TS1086: An accessor cannot be declared in an ambient context.
@@ -30,15 +30,15 @@ tests/cases/compiler/accessorsInAmbientContext.ts(17,16): error TS1086: An acces
declare class C {
get X() { return 1; }
~
!!! error TS1086: An accessor cannot be declared in an ambient context.
~~~~~~
!!! error TS1036: Statements are not allowed in ambient contexts.
set X(v) { }
~
!!! error TS1086: An accessor cannot be declared in an ambient context.
static get Y() { return 1; }
~
!!! error TS1086: An accessor cannot be declared in an ambient context.
~~~~~~
!!! error TS1036: Statements are not allowed in ambient contexts.
static set Y(v) { }
~
!!! error TS1086: An accessor cannot be declared in an ambient context.

View File

@@ -1,5 +1,5 @@
tests/cases/compiler/ambientGetters.ts(3,9): error TS1086: An accessor cannot be declared in an ambient context.
tests/cases/compiler/ambientGetters.ts(7,9): error TS1086: An accessor cannot be declared in an ambient context.
tests/cases/compiler/ambientGetters.ts(7,20): error TS1036: Statements are not allowed in ambient contexts.
==== tests/cases/compiler/ambientGetters.ts (2 errors) ====
@@ -12,6 +12,6 @@ tests/cases/compiler/ambientGetters.ts(7,9): error TS1086: An accessor cannot be
declare class B {
get length() { return 0; }
~~~~~~
!!! error TS1086: An accessor cannot be declared in an ambient context.
~~~~~~
!!! error TS1036: Statements are not allowed in ambient contexts.
}

View File

@@ -0,0 +1,14 @@
tests/cases/compiler/ambientStatement1.ts(2,6): error TS1036: Statements are not allowed in ambient contexts.
tests/cases/compiler/ambientStatement1.ts(4,20): error TS1039: Initializers are not allowed in ambient contexts.
==== tests/cases/compiler/ambientStatement1.ts (2 errors) ====
declare module M1 {
while(true);
~~~~~
!!! error TS1036: Statements are not allowed in ambient contexts.
export var v1 = () => false;
~
!!! error TS1039: Initializers are not allowed in ambient contexts.
}

View File

@@ -30,9 +30,7 @@ tests/cases/compiler/giant.ts(254,21): error TS1037: A function implementation c
tests/cases/compiler/giant.ts(255,31): error TS1037: A function implementation cannot be declared in an ambient context.
tests/cases/compiler/giant.ts(257,22): error TS1037: A function implementation cannot be declared in an ambient context.
tests/cases/compiler/giant.ts(262,22): error TS1037: A function implementation cannot be declared in an ambient context.
tests/cases/compiler/giant.ts(262,25): error TS1036: Statements are not allowed in ambient contexts.
tests/cases/compiler/giant.ts(267,30): error TS1037: A function implementation cannot be declared in an ambient context.
tests/cases/compiler/giant.ts(267,33): error TS1036: Statements are not allowed in ambient contexts.
tests/cases/compiler/giant.ts(283,5): error TS1005: '{' expected.
tests/cases/compiler/giant.ts(285,5): error TS1005: '{' expected.
tests/cases/compiler/giant.ts(287,5): error TS1005: '{' expected.
@@ -65,9 +63,7 @@ tests/cases/compiler/giant.ts(512,21): error TS1037: A function implementation c
tests/cases/compiler/giant.ts(513,31): error TS1037: A function implementation cannot be declared in an ambient context.
tests/cases/compiler/giant.ts(515,22): error TS1037: A function implementation cannot be declared in an ambient context.
tests/cases/compiler/giant.ts(520,22): error TS1037: A function implementation cannot be declared in an ambient context.
tests/cases/compiler/giant.ts(520,25): error TS1036: Statements are not allowed in ambient contexts.
tests/cases/compiler/giant.ts(525,30): error TS1037: A function implementation cannot be declared in an ambient context.
tests/cases/compiler/giant.ts(525,33): error TS1036: Statements are not allowed in ambient contexts.
tests/cases/compiler/giant.ts(532,31): error TS1037: A function implementation cannot be declared in an ambient context.
tests/cases/compiler/giant.ts(534,20): error TS1111: A constructor implementation cannot be declared in an ambient context.
tests/cases/compiler/giant.ts(537,17): error TS1037: A function implementation cannot be declared in an ambient context.
@@ -80,29 +76,22 @@ tests/cases/compiler/giant.ts(548,17): error TS1037: A function implementation c
tests/cases/compiler/giant.ts(549,27): error TS1037: A function implementation cannot be declared in an ambient context.
tests/cases/compiler/giant.ts(551,18): error TS1037: A function implementation cannot be declared in an ambient context.
tests/cases/compiler/giant.ts(556,18): error TS1037: A function implementation cannot be declared in an ambient context.
tests/cases/compiler/giant.ts(556,21): error TS1036: Statements are not allowed in ambient contexts.
tests/cases/compiler/giant.ts(558,24): error TS1111: A constructor implementation cannot be declared in an ambient context.
tests/cases/compiler/giant.ts(561,21): error TS1037: A function implementation cannot be declared in an ambient context.
tests/cases/compiler/giant.ts(563,21): error TS1037: A function implementation cannot be declared in an ambient context.
tests/cases/compiler/giant.ts(606,22): error TS1037: A function implementation cannot be declared in an ambient context.
tests/cases/compiler/giant.ts(606,25): error TS1036: Statements are not allowed in ambient contexts.
tests/cases/compiler/giant.ts(611,30): error TS1037: A function implementation cannot be declared in an ambient context.
tests/cases/compiler/giant.ts(611,33): error TS1036: Statements are not allowed in ambient contexts.
tests/cases/compiler/giant.ts(615,16): error TS1038: A 'declare' modifier cannot be used in an already ambient context.
tests/cases/compiler/giant.ts(616,16): error TS1038: A 'declare' modifier cannot be used in an already ambient context.
tests/cases/compiler/giant.ts(616,39): error TS1037: A function implementation cannot be declared in an ambient context.
tests/cases/compiler/giant.ts(616,42): error TS1036: Statements are not allowed in ambient contexts.
tests/cases/compiler/giant.ts(617,16): error TS1038: A 'declare' modifier cannot be used in an already ambient context.
tests/cases/compiler/giant.ts(618,16): error TS1038: A 'declare' modifier cannot be used in an already ambient context.
tests/cases/compiler/giant.ts(621,26): error TS1037: A function implementation cannot be declared in an ambient context.
tests/cases/compiler/giant.ts(621,29): error TS1036: Statements are not allowed in ambient contexts.
tests/cases/compiler/giant.ts(623,24): error TS1111: A constructor implementation cannot be declared in an ambient context.
tests/cases/compiler/giant.ts(626,21): error TS1037: A function implementation cannot be declared in an ambient context.
tests/cases/compiler/giant.ts(628,21): error TS1037: A function implementation cannot be declared in an ambient context.
tests/cases/compiler/giant.ts(672,22): error TS1037: A function implementation cannot be declared in an ambient context.
tests/cases/compiler/giant.ts(672,25): error TS1036: Statements are not allowed in ambient contexts.
tests/cases/compiler/giant.ts(676,30): error TS1037: A function implementation cannot be declared in an ambient context.
tests/cases/compiler/giant.ts(676,33): error TS1036: Statements are not allowed in ambient contexts.
tests/cases/compiler/giant.ts(23,12): error TS2300: Duplicate identifier 'pgF'.
tests/cases/compiler/giant.ts(24,16): error TS2300: Duplicate identifier 'pgF'.
tests/cases/compiler/giant.ts(24,16): error TS2378: A 'get' accessor must return a value or consist of a single 'throw' statement.
@@ -239,7 +228,7 @@ tests/cases/compiler/giant.ts(602,9): error TS2386: Overload signatures must all
tests/cases/compiler/giant.ts(668,9): error TS2386: Overload signatures must all be optional or required.
==== tests/cases/compiler/giant.ts (239 errors) ====
==== tests/cases/compiler/giant.ts (228 errors) ====
/*
Prefixes
@@ -686,8 +675,6 @@ tests/cases/compiler/giant.ts(668,9): error TS2386: Overload signatures must all
function F() { };
~
!!! error TS1037: A function implementation cannot be declared in an ambient context.
~
!!! error TS1036: Statements are not allowed in ambient contexts.
class C { }
interface I { }
module M { }
@@ -695,8 +682,6 @@ tests/cases/compiler/giant.ts(668,9): error TS2386: Overload signatures must all
export function eF() { };
~
!!! error TS1037: A function implementation cannot be declared in an ambient context.
~
!!! error TS1036: Statements are not allowed in ambient contexts.
export class eC { }
export interface eI { }
export module eM { }
@@ -1134,8 +1119,6 @@ tests/cases/compiler/giant.ts(668,9): error TS2386: Overload signatures must all
function F() { };
~
!!! error TS1037: A function implementation cannot be declared in an ambient context.
~
!!! error TS1036: Statements are not allowed in ambient contexts.
class C { }
interface I { }
module M { }
@@ -1143,8 +1126,6 @@ tests/cases/compiler/giant.ts(668,9): error TS2386: Overload signatures must all
export function eF() { };
~
!!! error TS1037: A function implementation cannot be declared in an ambient context.
~
!!! error TS1036: Statements are not allowed in ambient contexts.
export class eC { }
export interface eI { }
export module eM { }
@@ -1224,8 +1205,6 @@ tests/cases/compiler/giant.ts(668,9): error TS2386: Overload signatures must all
function F() { };
~
!!! error TS1037: A function implementation cannot be declared in an ambient context.
~
!!! error TS1036: Statements are not allowed in ambient contexts.
class C {
constructor () { }
~
@@ -1286,8 +1265,6 @@ tests/cases/compiler/giant.ts(668,9): error TS2386: Overload signatures must all
function F() { };
~
!!! error TS1037: A function implementation cannot be declared in an ambient context.
~
!!! error TS1036: Statements are not allowed in ambient contexts.
class C { }
interface I { }
module M { }
@@ -1295,8 +1272,6 @@ tests/cases/compiler/giant.ts(668,9): error TS2386: Overload signatures must all
export function eF() { };
~
!!! error TS1037: A function implementation cannot be declared in an ambient context.
~
!!! error TS1036: Statements are not allowed in ambient contexts.
export class eC { }
export interface eI { }
export module eM { }
@@ -1308,8 +1283,6 @@ tests/cases/compiler/giant.ts(668,9): error TS2386: Overload signatures must all
!!! error TS1038: A 'declare' modifier cannot be used in an already ambient context.
~
!!! error TS1037: A function implementation cannot be declared in an ambient context.
~
!!! error TS1036: Statements are not allowed in ambient contexts.
export declare class eaC { }
~~~~~~~
!!! error TS1038: A 'declare' modifier cannot be used in an already ambient context.
@@ -1321,8 +1294,6 @@ tests/cases/compiler/giant.ts(668,9): error TS2386: Overload signatures must all
export function eF() { };
~
!!! error TS1037: A function implementation cannot be declared in an ambient context.
~
!!! error TS1036: Statements are not allowed in ambient contexts.
export class eC {
constructor () { }
~
@@ -1384,16 +1355,12 @@ tests/cases/compiler/giant.ts(668,9): error TS2386: Overload signatures must all
function F() { };
~
!!! error TS1037: A function implementation cannot be declared in an ambient context.
~
!!! error TS1036: Statements are not allowed in ambient contexts.
class C { }
module M { }
export var eV;
export function eF() { };
~
!!! error TS1037: A function implementation cannot be declared in an ambient context.
~
!!! error TS1036: Statements are not allowed in ambient contexts.
export class eC { }
export interface eI { }
export module eM { }

View File

@@ -1,10 +1,9 @@
tests/cases/conformance/externalModules/initializersInDeclarations.ts(5,7): error TS1039: Initializers are not allowed in ambient contexts.
tests/cases/conformance/externalModules/initializersInDeclarations.ts(6,14): error TS1039: Initializers are not allowed in ambient contexts.
tests/cases/conformance/externalModules/initializersInDeclarations.ts(7,16): error TS1037: A function implementation cannot be declared in an ambient context.
tests/cases/conformance/externalModules/initializersInDeclarations.ts(16,2): error TS1036: Statements are not allowed in ambient contexts.
==== tests/cases/conformance/externalModules/initializersInDeclarations.ts (4 errors) ====
==== tests/cases/conformance/externalModules/initializersInDeclarations.ts (3 errors) ====
// Errors: Initializers & statements in declaration file
@@ -27,8 +26,6 @@ tests/cases/conformance/externalModules/initializersInDeclarations.ts(16,2): err
declare module M1 {
while(true);
~~~~~
!!! error TS1036: Statements are not allowed in ambient contexts.
export var v1 = () => false;
}

View File

@@ -1,9 +1,9 @@
tests/cases/conformance/parser/ecmascript5/Accessors/parserAccessors5.ts(2,7): error TS1086: An accessor cannot be declared in an ambient context.
tests/cases/conformance/parser/ecmascript5/Accessors/parserAccessors5.ts(2,15): error TS1036: Statements are not allowed in ambient contexts.
==== tests/cases/conformance/parser/ecmascript5/Accessors/parserAccessors5.ts (1 errors) ====
declare class C {
get foo() { return 0; }
~~~
!!! error TS1086: An accessor cannot be declared in an ambient context.
~~~~~~
!!! error TS1036: Statements are not allowed in ambient contexts.
}

View File

@@ -0,0 +1,21 @@
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) ====
var x = 10;
switch (x) {
case 1:
case 2:
default: // No issues.
break;
default: // Error; second 'default' clause.
~~~~~~~~
!!! error TS1113: A 'default' clause cannot appear more than once in a 'switch' statement.
default: // Error; third 'default' clause.
~~~~~~~~
!!! error TS1113: A 'default' clause cannot appear more than once in a 'switch' statement.
case 3:
x *= x;
}

View File

@@ -0,0 +1,5 @@
declare module M1 {
while(true);
export var v1 = () => false;
}

View File

@@ -0,0 +1,12 @@
var x = 10;
switch (x) {
case 1:
case 2:
default: // No issues.
break;
default: // Error; second 'default' clause.
default: // Error; third 'default' clause.
case 3:
x *= x;
}