Add tracking for labelled statements, and errors on labelled jumps

This commit is contained in:
Jason Freeman
2014-07-24 12:36:10 -07:00
parent b9971f2876
commit 742637bec9
97 changed files with 318 additions and 580 deletions

View File

@@ -5,6 +5,8 @@ module ts {
[index: string]: T;
}
export interface StringSet extends Map<any> { }
export function forEach<T, U>(array: T[], callback: (element: T) => U): U {
var result: U;
if (array) {

View File

@@ -55,6 +55,10 @@ module ts {
return skipTrivia(getSourceFileOfNode(node).text, node.pos);
}
export function getSourceTextOfNodeFromSourceText(sourceText: string, node: Node): string {
return sourceText.substring(skipTrivia(sourceText, node.pos), node.end);
}
export function getSourceTextOfNode(node: Node): string {
var text = getSourceFileOfNode(node).text;
return text.substring(skipTrivia(text, node.pos), node.end);
@@ -400,18 +404,98 @@ module ts {
var labelledStatementInfo = (() => {
// TODO(jfreeman): Implement a data structure for tracking labels
var functionBoundarySentinel = <LabelledStatement>{};
var currentLabelSet: Identifier[];
var labelSetStack: Identifier[][];
var functionBoundarySentinel: StringSet = {};
var currentLabelSet: StringSet;
var labelSetStack: StringSet[];
var isIterationStack: boolean[];
function addLabel(label: Identifier): void {
if (!currentLabelSet) {
currentLabelSet = {};
}
currentLabelSet[label.text] = true;
}
function pushCurrentLabelSet(isIterationStatement: boolean): void {
if (!labelSetStack && !isIterationStack) {
labelSetStack = [];
isIterationStack = [];
}
Debug.assert(currentLabelSet !== undefined);
labelSetStack.push(currentLabelSet);
isIterationStack.push(isIterationStatement);
currentLabelSet = undefined;
}
function pushFunctionBoundary(): void {
if (!labelSetStack && !isIterationStack) {
labelSetStack = [];
isIterationStack = [];
}
Debug.assert(currentLabelSet === undefined);
labelSetStack.push(functionBoundarySentinel);
// It does not matter what we push here, since we will never ask if a function boundary
// is an iteration statement
isIterationStack.push(false);
}
function pop(): void {
// Assert that we are in a "pushed" state
Debug.assert(labelSetStack.length && isIterationStack.length && currentLabelSet === undefined);
labelSetStack.pop();
isIterationStack.pop();
}
function nodeIsNestedInLabel(label: Identifier, requireIterationStatement: boolean, stopAtFunctionBoundary: boolean): ControlBlockContext {
if (!requireIterationStatement && currentLabelSet && hasProperty(currentLabelSet, label.text)) {
return ControlBlockContext.Nested;
}
if (!labelSetStack) {
return ControlBlockContext.NotNested;
}
// We want to start searching for the label at the lowest point in the tree,
// and climb up from there. So we start at the end of the labelSetStack array.
var crossedFunctionBoundary = false;
for (var i = labelSetStack.length - 1; i >= 0; i--) {
var labelSet = labelSetStack[i];
// Not allowed to cross function boundaries, so stop if we encounter one
if (labelSet === functionBoundarySentinel) {
if (stopAtFunctionBoundary) {
break;
}
else {
crossedFunctionBoundary = true;
continue;
}
}
// If we require an iteration statement, only search in the current
// statement if it is an iteration statement
if (requireIterationStatement && isIterationStack[i] === false) {
continue;
}
if (hasProperty(labelSet, label.text)) {
return crossedFunctionBoundary ? ControlBlockContext.CrossingFunctionBoundary : ControlBlockContext.Nested;
}
}
// This is a bit of a misnomer. If the caller passed true for stopAtFunctionBoundary,
// there actually may be an enclosing label across a function boundary, but we will
// just return NotNested
return ControlBlockContext.NotNested;
}
// TODO(jfreeman): Fill in these stubs
return {
addLabel: (label: Identifier) => { },
pushCurrentLabelSet: (isIterationStatement: boolean) => { },
pushFunctionBoundary: () => { },
pop: () => { },
labelExists: (label: Identifier, requireIterationStatement: boolean): boolean => false,
addLabel: addLabel,
pushCurrentLabelSet: pushCurrentLabelSet,
pushFunctionBoundary: pushFunctionBoundary,
pop: pop,
nodeIsNestedInLabel: nodeIsNestedInLabel,
};
})();
@@ -2083,40 +2167,39 @@ module ts {
parseExpected(kind === SyntaxKind.BreakStatement ? SyntaxKind.BreakKeyword : SyntaxKind.ContinueKeyword);
if (!isSemicolon()) node.label = parseIdentifier();
parseSemicolon();
finishNode(node);
// In an ambient context, we will already give an error for having a statement.
if (!inAmbientContext && errorCountBeforeStatement === file.syntacticErrors.length) {
if (node.label) {
checkBreakOrContinueStatementWithLabel(node.label, kind);
checkBreakOrContinueStatementWithLabel(node);
}
else {
checkAnonymousBreakOrContinueStatement(kind, keywordStart, keywordLength);
checkAnonymousBreakOrContinueStatement(node);
}
}
return finishNode(node);
return node;
}
function checkAnonymousBreakOrContinueStatement(kind: SyntaxKind, errorStart: number, errorLength: number): void {
if (kind === SyntaxKind.BreakStatement) {
function checkAnonymousBreakOrContinueStatement(node: BreakOrContinueStatement): void {
if (node.kind === SyntaxKind.BreakStatement) {
if (inIterationStatement === ControlBlockContext.Nested
|| inSwitchStatement === ControlBlockContext.Nested) {
return;
}
else if (inIterationStatement === ControlBlockContext.NotNested
&& inSwitchStatement === ControlBlockContext.NotNested) {
grammarErrorAtPos(errorStart, errorLength,
Diagnostics.A_break_statement_can_only_be_used_within_an_enclosing_iteration_or_switch_statement);
grammarErrorOnNode(node, Diagnostics.A_break_statement_can_only_be_used_within_an_enclosing_iteration_or_switch_statement);
return;
}
// Fall through
}
else if (kind === SyntaxKind.ContinueStatement) {
else if (node.kind === SyntaxKind.ContinueStatement) {
if (inIterationStatement === ControlBlockContext.Nested) {
return;
}
else if (inIterationStatement === ControlBlockContext.NotNested) {
grammarErrorAtPos(errorStart, errorLength,
Diagnostics.A_continue_statement_can_only_be_used_within_an_enclosing_iteration_statement);
grammarErrorOnNode(node, Diagnostics.A_continue_statement_can_only_be_used_within_an_enclosing_iteration_statement);
return;
}
// Fall through
@@ -2127,19 +2210,31 @@ module ts {
Debug.assert(inIterationStatement === ControlBlockContext.CrossingFunctionBoundary
|| inSwitchStatement === ControlBlockContext.CrossingFunctionBoundary);
grammarErrorAtPos(errorStart, errorLength, Diagnostics.Jump_target_cannot_cross_function_boundary);
grammarErrorOnNode(node, Diagnostics.Jump_target_cannot_cross_function_boundary);
}
function checkBreakOrContinueStatementWithLabel(label: Identifier, kind: SyntaxKind): void {
if (labelledStatementInfo.labelExists(label, /*requireIterationStatement*/ kind === SyntaxKind.ContinueStatement)) {
function checkBreakOrContinueStatementWithLabel(node: BreakOrContinueStatement): void {
// For error specificity, if the label is not found, we want to distinguish whether it is because
// it crossed a function boundary or it was simply not found. To do this, we pass false for
// stopAtFunctionBoundary.
var nodeIsNestedInLabel = labelledStatementInfo.nodeIsNestedInLabel(node.label,
/*requireIterationStatement*/ node.kind === SyntaxKind.ContinueStatement,
/*stopAtFunctionBoundary*/ false);
if (nodeIsNestedInLabel === ControlBlockContext.Nested) {
return;
}
if (kind === SyntaxKind.ContinueStatement) {
grammarErrorOnNode(label, Diagnostics.A_continue_statement_can_only_jump_to_a_label_of_an_enclosing_iteration_statement);
if (nodeIsNestedInLabel === ControlBlockContext.CrossingFunctionBoundary) {
grammarErrorOnNode(node, Diagnostics.Jump_target_cannot_cross_function_boundary);
return;
}
else if (kind === SyntaxKind.BreakStatement) {
grammarErrorOnNode(label, Diagnostics.A_break_statement_can_only_jump_to_a_label_of_an_enclosing_statement);
// It is NotNested
if (node.kind === SyntaxKind.ContinueStatement) {
grammarErrorOnNode(node, Diagnostics.A_continue_statement_can_only_jump_to_a_label_of_an_enclosing_iteration_statement);
}
else if (node.kind === SyntaxKind.BreakStatement) {
grammarErrorOnNode(node, Diagnostics.A_break_statement_can_only_jump_to_a_label_of_an_enclosing_statement);
}
else {
Debug.fail("checkBreakOrContinueStatementWithLabel");
@@ -2304,8 +2399,8 @@ module ts {
node.label = parseIdentifier();
parseExpected(SyntaxKind.ColonToken);
if (labelledStatementInfo.labelExists(node.label, /*requireIterationStatement*/ false)) {
grammarErrorOnNode(node.label, Diagnostics.Duplicate_label_0);
if (labelledStatementInfo.nodeIsNestedInLabel(node.label, /*requireIterationStatement*/ false, /*stopAtFunctionBoundary*/ true)) {
grammarErrorOnNode(node.label, Diagnostics.Duplicate_label_0, getSourceTextOfNodeFromSourceText(sourceText, node.label));
}
labelledStatementInfo.addLabel(node.label);

View File

@@ -1,9 +0,0 @@
//// [breakInIterationOrSwitchStatement1.ts]
while (true) {
break;
}
//// [breakInIterationOrSwitchStatement1.js]
while (true) {
break;
}

View File

@@ -1,10 +0,0 @@
//// [breakInIterationOrSwitchStatement2.ts]
do {
break;
}
while (true);
//// [breakInIterationOrSwitchStatement2.js]
do {
break;
} while (true);

View File

@@ -1,9 +0,0 @@
//// [breakInIterationOrSwitchStatement3.ts]
for (;;) {
break;
}
//// [breakInIterationOrSwitchStatement3.js]
for (;;) {
break;
}

View File

@@ -1,6 +0,0 @@
==== tests/cases/compiler/breakInIterationOrSwitchStatement4.ts (1 errors) ====
for (var i in something) {
~~~~~~~~~
!!! Cannot find name 'something'.
break;
}

View File

@@ -1,9 +0,0 @@
//// [breakInIterationOrSwitchStatement4.ts]
for (var i in something) {
break;
}
//// [breakInIterationOrSwitchStatement4.js]
for (var i in something) {
break;
}

View File

@@ -1,4 +0,0 @@
==== tests/cases/compiler/breakNotInIterationOrSwitchStatement1.ts (1 errors) ====
break;
~~~~~
!!! A 'break' statement can only be used within an enclosing iteration or switch statement.

View File

@@ -1,8 +0,0 @@
==== tests/cases/compiler/breakNotInIterationOrSwitchStatement2.ts (1 errors) ====
while (true) {
function f() {
break;
~~~~~
!!! Jump target cannot cross function boundary.
}
}

View File

@@ -1,6 +0,0 @@
//// [breakTarget1.ts]
target:
break target;
//// [breakTarget1.js]
target: break target;

View File

@@ -1,10 +0,0 @@
//// [breakTarget2.ts]
target:
while (true) {
break target;
}
//// [breakTarget2.js]
target: while (true) {
break target;
}

View File

@@ -1,11 +0,0 @@
//// [breakTarget3.ts]
target1:
target2:
while (true) {
break target1;
}
//// [breakTarget3.js]
target1: target2: while (true) {
break target1;
}

View File

@@ -1,11 +0,0 @@
//// [breakTarget4.ts]
target1:
target2:
while (true) {
break target2;
}
//// [breakTarget4.js]
target1: target2: while (true) {
break target2;
}

View File

@@ -1,18 +0,0 @@
//// [breakTarget5.ts]
target:
while (true) {
function f() {
while (true) {
break target;
}
}
}
//// [breakTarget5.js]
target: while (true) {
function f() {
while (true) {
break target;
}
}
}

View File

@@ -1,9 +0,0 @@
//// [breakTarget6.ts]
while (true) {
break target;
}
//// [breakTarget6.js]
while (true) {
break target;
}

View File

@@ -1,9 +0,0 @@
//// [continueInIterationStatement1.ts]
while (true) {
continue;
}
//// [continueInIterationStatement1.js]
while (true) {
continue;
}

View File

@@ -1,10 +0,0 @@
//// [continueInIterationStatement2.ts]
do {
continue;
}
while (true);
//// [continueInIterationStatement2.js]
do {
continue;
} while (true);

View File

@@ -1,9 +0,0 @@
//// [continueInIterationStatement3.ts]
for (;;) {
continue;
}
//// [continueInIterationStatement3.js]
for (;;) {
continue;
}

View File

@@ -1,6 +0,0 @@
==== tests/cases/compiler/continueInIterationStatement4.ts (1 errors) ====
for (var i in something) {
~~~~~~~~~
!!! Cannot find name 'something'.
continue;
}

View File

@@ -1,9 +0,0 @@
//// [continueInIterationStatement4.ts]
for (var i in something) {
continue;
}
//// [continueInIterationStatement4.js]
for (var i in something) {
continue;
}

View File

@@ -1,9 +0,0 @@
//// [continueLabel.ts]
label1: for(var i = 0; i < 1; i++) {
continue label1;
}
//// [continueLabel.js]
label1: for (var i = 0; i < 1; i++) {
continue label1;
}

View File

@@ -1,4 +0,0 @@
==== tests/cases/compiler/continueNotInIterationStatement1.ts (1 errors) ====
continue;
~~~~~~~~
!!! A 'continue' statement can only be used within an enclosing iteration statement.

View File

@@ -1,8 +0,0 @@
==== tests/cases/compiler/continueNotInIterationStatement2.ts (1 errors) ====
while (true) {
function f() {
continue;
~~~~~~~~
!!! Jump target cannot cross function boundary.
}
}

View File

@@ -1,7 +0,0 @@
==== tests/cases/compiler/continueNotInIterationStatement3.ts (1 errors) ====
switch (0) {
default:
continue;
~~~~~~~~
!!! A 'continue' statement can only be used within an enclosing iteration statement.
}

View File

@@ -1,15 +0,0 @@
//// [continueNotInIterationStatement4.ts]
TWO:
while (true){
var x = () => {
continue TWO;
}
}
//// [continueNotInIterationStatement4.js]
TWO: while (true) {
var x = function () {
continue TWO;
};
}

View File

@@ -1,6 +0,0 @@
//// [continueTarget1.ts]
target:
continue target;
//// [continueTarget1.js]
target: continue target;

View File

@@ -1,10 +0,0 @@
//// [continueTarget2.ts]
target:
while (true) {
continue target;
}
//// [continueTarget2.js]
target: while (true) {
continue target;
}

View File

@@ -1,11 +0,0 @@
//// [continueTarget3.ts]
target1:
target2:
while (true) {
continue target1;
}
//// [continueTarget3.js]
target1: target2: while (true) {
continue target1;
}

View File

@@ -1,11 +0,0 @@
//// [continueTarget4.ts]
target1:
target2:
while (true) {
continue target2;
}
//// [continueTarget4.js]
target1: target2: while (true) {
continue target2;
}

View File

@@ -1,18 +0,0 @@
//// [continueTarget5.ts]
target:
while (true) {
function f() {
while (true) {
continue target;
}
}
}
//// [continueTarget5.js]
target: while (true) {
function f() {
while (true) {
continue target;
}
}
}

View File

@@ -1,9 +0,0 @@
//// [continueTarget6.ts]
while (true) {
continue target;
}
//// [continueTarget6.js]
while (true) {
continue target;
}

View File

@@ -1,9 +0,0 @@
//// [duplicateLabel1.ts]
target:
target:
while (true) {
}
//// [duplicateLabel1.js]
target: target: while (true) {
}

View File

@@ -1,13 +0,0 @@
//// [duplicateLabel2.ts]
target:
while (true) {
target:
while (true) {
}
}
//// [duplicateLabel2.js]
target: while (true) {
target: while (true) {
}
}

View File

@@ -1,17 +0,0 @@
//// [duplicateLabel3.ts]
target:
while (true) {
function f() {
target:
while (true) {
}
}
}
//// [duplicateLabel3.js]
target: while (true) {
function f() {
target: while (true) {
}
}
}

View File

@@ -1,14 +0,0 @@
//// [duplicateLabel4.ts]
target:
while (true) {
}
target:
while (true) {
}
//// [duplicateLabel4.js]
target: while (true) {
}
target: while (true) {
}

View File

@@ -1,20 +1,24 @@
==== tests/cases/conformance/statements/breakStatements/invalidDoWhileBreakStatements.ts (1 errors) ====
==== tests/cases/conformance/statements/breakStatements/invalidDoWhileBreakStatements.ts (6 errors) ====
// All errors
// naked break not allowed
break;
~~~~~
~~~~~~
!!! A 'break' statement can only be used within an enclosing iteration or switch statement.
// non-existent label
ONE:
do break TWO; while (true)
~~~~~~~~~~
!!! A 'break' statement can only jump to a label of an enclosing statement.
// break from inside function
TWO:
do {
var x = () => {
break TWO;
~~~~~~~~~~
!!! Jump target cannot cross function boundary.
}
}while (true)
@@ -22,12 +26,16 @@
do {
var fn = function () {
break THREE;
~~~~~~~~~~~~
!!! Jump target cannot cross function boundary.
}
}while (true)
// break forward
do {
break FIVE;
~~~~~~~~~~~
!!! A 'break' statement can only jump to a label of an enclosing statement.
FIVE:
do { } while (true)
}while (true)
@@ -38,4 +46,6 @@
do {
break NINE;
~~~~~~~~~~~
!!! A 'break' statement can only jump to a label of an enclosing statement.
}while (true)

View File

@@ -1,20 +1,24 @@
==== tests/cases/conformance/statements/continueStatements/invalidDoWhileContinueStatements.ts (1 errors) ====
==== tests/cases/conformance/statements/continueStatements/invalidDoWhileContinueStatements.ts (6 errors) ====
// All errors
// naked continue not allowed
continue;
~~~~~~~~
~~~~~~~~~
!!! A 'continue' statement can only be used within an enclosing iteration statement.
// non-existent label
ONE:
do continue TWO; while (true)
~~~~~~~~~~~~~
!!! A 'continue' statement can only jump to a label of an enclosing iteration statement.
// continue from inside function
TWO:
do {
var x = () => {
continue TWO;
~~~~~~~~~~~~~
!!! Jump target cannot cross function boundary.
}
}while (true)
@@ -22,12 +26,16 @@
do {
var fn = function () {
continue THREE;
~~~~~~~~~~~~~~~
!!! Jump target cannot cross function boundary.
}
}while (true)
// continue forward
do {
continue FIVE;
~~~~~~~~~~~~~~
!!! A 'continue' statement can only jump to a label of an enclosing iteration statement.
FIVE:
do { } while (true)
}while (true)
@@ -38,4 +46,6 @@
do {
continue NINE;
~~~~~~~~~~~~~~
!!! A 'continue' statement can only jump to a label of an enclosing iteration statement.
}while (true)

View File

@@ -1,20 +1,24 @@
==== tests/cases/conformance/statements/breakStatements/invalidForBreakStatements.ts (1 errors) ====
==== tests/cases/conformance/statements/breakStatements/invalidForBreakStatements.ts (6 errors) ====
// All errors
// naked break not allowed
break;
~~~~~
~~~~~~
!!! A 'break' statement can only be used within an enclosing iteration or switch statement.
// non-existent label
ONE:
for(;;) break TWO;
~~~~~~~~~~
!!! A 'break' statement can only jump to a label of an enclosing statement.
// break from inside function
TWO:
for(;;) {
var x = () => {
break TWO;
~~~~~~~~~~
!!! Jump target cannot cross function boundary.
}
}
@@ -22,12 +26,16 @@
for(;;) {
var fn = function () {
break THREE;
~~~~~~~~~~~~
!!! Jump target cannot cross function boundary.
}
}
// break forward
for(;;) {
break FIVE;
~~~~~~~~~~~
!!! A 'break' statement can only jump to a label of an enclosing statement.
FIVE:
for (; ;) { }
}
@@ -37,4 +45,6 @@
for(;;) {
break NINE;
~~~~~~~~~~~
!!! A 'break' statement can only jump to a label of an enclosing statement.
}

View File

@@ -1,20 +1,24 @@
==== tests/cases/conformance/statements/continueStatements/invalidForContinueStatements.ts (1 errors) ====
==== tests/cases/conformance/statements/continueStatements/invalidForContinueStatements.ts (6 errors) ====
// All errors
// naked continue not allowed
continue;
~~~~~~~~
~~~~~~~~~
!!! A 'continue' statement can only be used within an enclosing iteration statement.
// non-existent label
ONE:
for(;;) continue TWO;
~~~~~~~~~~~~~
!!! A 'continue' statement can only jump to a label of an enclosing iteration statement.
// continue from inside function
TWO:
for(;;) {
var x = () => {
continue TWO;
~~~~~~~~~~~~~
!!! Jump target cannot cross function boundary.
}
}
@@ -22,12 +26,16 @@
for(;;) {
var fn = function () {
continue THREE;
~~~~~~~~~~~~~~~
!!! Jump target cannot cross function boundary.
}
}
// continue forward
for(;;) {
continue FIVE;
~~~~~~~~~~~~~~
!!! A 'continue' statement can only jump to a label of an enclosing iteration statement.
FIVE:
for (; ;) { }
}
@@ -37,4 +45,6 @@
for(;;) {
continue NINE;
~~~~~~~~~~~~~~
!!! A 'continue' statement can only jump to a label of an enclosing iteration statement.
}

View File

@@ -1,20 +1,24 @@
==== tests/cases/conformance/statements/breakStatements/invalidForInBreakStatements.ts (1 errors) ====
==== tests/cases/conformance/statements/breakStatements/invalidForInBreakStatements.ts (6 errors) ====
// All errors
// naked break not allowed
break;
~~~~~
~~~~~~
!!! A 'break' statement can only be used within an enclosing iteration or switch statement.
// non-existent label
ONE:
for (var x in {}) break TWO;
~~~~~~~~~~
!!! A 'break' statement can only jump to a label of an enclosing statement.
// break from inside function
TWO:
for (var x in {}) {
var fn = () => {
break TWO;
~~~~~~~~~~
!!! Jump target cannot cross function boundary.
}
}
@@ -22,12 +26,16 @@
for (var x in {}) {
var fn = function () {
break THREE;
~~~~~~~~~~~~
!!! Jump target cannot cross function boundary.
}
}
// break forward
for (var x in {}) {
break FIVE;
~~~~~~~~~~~
!!! A 'break' statement can only jump to a label of an enclosing statement.
FIVE:
for (var x in {}) { }
}
@@ -38,4 +46,6 @@
for (var x in {}) {
break NINE;
~~~~~~~~~~~
!!! A 'break' statement can only jump to a label of an enclosing statement.
}

View File

@@ -1,20 +1,24 @@
==== tests/cases/conformance/statements/continueStatements/invalidForInContinueStatements.ts (1 errors) ====
==== tests/cases/conformance/statements/continueStatements/invalidForInContinueStatements.ts (6 errors) ====
// All errors
// naked continue not allowed
continue;
~~~~~~~~
~~~~~~~~~
!!! A 'continue' statement can only be used within an enclosing iteration statement.
// non-existent label
ONE:
for (var x in {}) continue TWO;
~~~~~~~~~~~~~
!!! A 'continue' statement can only jump to a label of an enclosing iteration statement.
// continue from inside function
TWO:
for (var x in {}) {
var fn = () => {
continue TWO;
~~~~~~~~~~~~~
!!! Jump target cannot cross function boundary.
}
}
@@ -22,12 +26,16 @@
for (var x in {}) {
var fn = function () {
continue THREE;
~~~~~~~~~~~~~~~
!!! Jump target cannot cross function boundary.
}
}
// continue forward
for (var x in {}) {
continue FIVE;
~~~~~~~~~~~~~~
!!! A 'continue' statement can only jump to a label of an enclosing iteration statement.
FIVE:
for (var x in {}) { }
}
@@ -38,4 +46,6 @@
for (var x in {}) {
continue NINE;
~~~~~~~~~~~~~~
!!! A 'continue' statement can only jump to a label of an enclosing iteration statement.
}

View File

@@ -4,7 +4,7 @@
switch (12) {
case 5:
continue;
~~~~~~~~
~~~~~~~~~
!!! A 'continue' statement can only be used within an enclosing iteration statement.
}

View File

@@ -1,20 +1,24 @@
==== tests/cases/conformance/statements/breakStatements/invalidWhileBreakStatements.ts (1 errors) ====
==== tests/cases/conformance/statements/breakStatements/invalidWhileBreakStatements.ts (6 errors) ====
// All errors
// naked break not allowed
break;
~~~~~
~~~~~~
!!! A 'break' statement can only be used within an enclosing iteration or switch statement.
// non-existent label
ONE:
while (true) break TWO;
~~~~~~~~~~
!!! A 'break' statement can only jump to a label of an enclosing statement.
// break from inside function
TWO:
while (true){
var x = () => {
break TWO;
~~~~~~~~~~
!!! Jump target cannot cross function boundary.
}
}
@@ -22,12 +26,16 @@
while (true) {
var fn = function () {
break THREE;
~~~~~~~~~~~~
!!! Jump target cannot cross function boundary.
}
}
// break forward
while (true) {
break FIVE;
~~~~~~~~~~~
!!! A 'break' statement can only jump to a label of an enclosing statement.
FIVE:
while (true) { }
}
@@ -38,4 +46,6 @@
while (true) {
break NINE;
~~~~~~~~~~~
!!! A 'break' statement can only jump to a label of an enclosing statement.
}

View File

@@ -1,20 +1,24 @@
==== tests/cases/conformance/statements/continueStatements/invalidWhileContinueStatements.ts (1 errors) ====
==== tests/cases/conformance/statements/continueStatements/invalidWhileContinueStatements.ts (6 errors) ====
// All errors
// naked continue not allowed
continue;
~~~~~~~~
~~~~~~~~~
!!! A 'continue' statement can only be used within an enclosing iteration statement.
// non-existent label
ONE:
while (true) continue TWO;
~~~~~~~~~~~~~
!!! A 'continue' statement can only jump to a label of an enclosing iteration statement.
// continue from inside function
TWO:
while (true){
var x = () => {
continue TWO;
~~~~~~~~~~~~~
!!! Jump target cannot cross function boundary.
}
}
@@ -22,12 +26,16 @@
while (true) {
var fn = function () {
continue THREE;
~~~~~~~~~~~~~~~
!!! Jump target cannot cross function boundary.
}
}
// continue forward
while (true) {
continue FIVE;
~~~~~~~~~~~~~~
!!! A 'continue' statement can only jump to a label of an enclosing iteration statement.
FIVE:
while (true) { }
}
@@ -38,4 +46,6 @@
while (true) {
continue NINE;
~~~~~~~~~~~~~~
!!! A 'continue' statement can only jump to a label of an enclosing iteration statement.
}

View File

@@ -2,6 +2,6 @@
public break;
~~~~~~
!!! Declaration or statement expected.
~~~~~
~~~~~~
!!! A 'break' statement can only be used within an enclosing iteration or switch statement.

View File

@@ -0,0 +1,4 @@
==== tests/cases/conformance/parser/ecmascript5/Statements/BreakStatements/parser_breakNotInIterationOrSwitchStatement1.ts (1 errors) ====
break;
~~~~~~
!!! A 'break' statement can only be used within an enclosing iteration or switch statement.

View File

@@ -0,0 +1,8 @@
==== tests/cases/conformance/parser/ecmascript5/Statements/BreakStatements/parser_breakNotInIterationOrSwitchStatement2.ts (1 errors) ====
while (true) {
function f() {
break;
~~~~~~
!!! Jump target cannot cross function boundary.
}
}

View File

@@ -0,0 +1,11 @@
==== tests/cases/conformance/parser/ecmascript5/Statements/BreakStatements/parser_breakTarget5.ts (1 errors) ====
target:
while (true) {
function f() {
while (true) {
break target;
~~~~~~~~~~~~~
!!! Jump target cannot cross function boundary.
}
}
}

View File

@@ -1,18 +0,0 @@
//// [parser_breakTarget5.ts]
target:
while (true) {
function f() {
while (true) {
break target;
}
}
}
//// [parser_breakTarget5.js]
target: while (true) {
function f() {
while (true) {
break target;
}
}
}

View File

@@ -0,0 +1,6 @@
==== tests/cases/conformance/parser/ecmascript5/Statements/BreakStatements/parser_breakTarget6.ts (1 errors) ====
while (true) {
break target;
~~~~~~~~~~~~~
!!! A 'break' statement can only jump to a label of an enclosing statement.
}

View File

@@ -1,9 +0,0 @@
//// [parser_breakTarget6.ts]
while (true) {
break target;
}
//// [parser_breakTarget6.js]
while (true) {
break target;
}

View File

@@ -0,0 +1,4 @@
==== tests/cases/conformance/parser/ecmascript5/Statements/ContinueStatements/parser_continueNotInIterationStatement1.ts (1 errors) ====
continue;
~~~~~~~~~
!!! A 'continue' statement can only be used within an enclosing iteration statement.

View File

@@ -0,0 +1,8 @@
==== tests/cases/conformance/parser/ecmascript5/Statements/ContinueStatements/parser_continueNotInIterationStatement2.ts (1 errors) ====
while (true) {
function f() {
continue;
~~~~~~~~~
!!! Jump target cannot cross function boundary.
}
}

View File

@@ -0,0 +1,7 @@
==== tests/cases/conformance/parser/ecmascript5/Statements/ContinueStatements/parser_continueNotInIterationStatement3.ts (1 errors) ====
switch (0) {
default:
continue;
~~~~~~~~~
!!! A 'continue' statement can only be used within an enclosing iteration statement.
}

View File

@@ -0,0 +1,10 @@
==== tests/cases/conformance/parser/ecmascript5/Statements/ContinueStatements/parser_continueNotInIterationStatement4.ts (1 errors) ====
TWO:
while (true){
var x = () => {
continue TWO;
~~~~~~~~~~~~~
!!! Jump target cannot cross function boundary.
}
}

View File

@@ -1,15 +0,0 @@
//// [parser_continueNotInIterationStatement4.ts]
TWO:
while (true){
var x = () => {
continue TWO;
}
}
//// [parser_continueNotInIterationStatement4.js]
TWO: while (true) {
var x = function () {
continue TWO;
};
}

View File

@@ -0,0 +1,5 @@
==== tests/cases/conformance/parser/ecmascript5/Statements/ContinueStatements/parser_continueTarget1.ts (1 errors) ====
target:
continue target;
~~~~~~~~~~~~~~~~
!!! A 'continue' statement can only jump to a label of an enclosing iteration statement.

View File

@@ -1,6 +0,0 @@
//// [parser_continueTarget1.ts]
target:
continue target;
//// [parser_continueTarget1.js]
target: continue target;

View File

@@ -0,0 +1,11 @@
==== tests/cases/conformance/parser/ecmascript5/Statements/ContinueStatements/parser_continueTarget5.ts (1 errors) ====
target:
while (true) {
function f() {
while (true) {
continue target;
~~~~~~~~~~~~~~~~
!!! Jump target cannot cross function boundary.
}
}
}

View File

@@ -1,18 +0,0 @@
//// [parser_continueTarget5.ts]
target:
while (true) {
function f() {
while (true) {
continue target;
}
}
}
//// [parser_continueTarget5.js]
target: while (true) {
function f() {
while (true) {
continue target;
}
}
}

View File

@@ -0,0 +1,6 @@
==== tests/cases/conformance/parser/ecmascript5/Statements/ContinueStatements/parser_continueTarget6.ts (1 errors) ====
while (true) {
continue target;
~~~~~~~~~~~~~~~~
!!! A 'continue' statement can only jump to a label of an enclosing iteration statement.
}

View File

@@ -1,9 +0,0 @@
//// [parser_continueTarget6.ts]
while (true) {
continue target;
}
//// [parser_continueTarget6.js]
while (true) {
continue target;
}

View File

@@ -0,0 +1,7 @@
==== tests/cases/conformance/parser/ecmascript5/Statements/LabeledStatements/parser_duplicateLabel1.ts (1 errors) ====
target:
target:
~~~~~~
!!! Duplicate label 'target'
while (true) {
}

View File

@@ -1,9 +0,0 @@
//// [parser_duplicateLabel1.ts]
target:
target:
while (true) {
}
//// [parser_duplicateLabel1.js]
target: target: while (true) {
}

View File

@@ -0,0 +1,9 @@
==== tests/cases/conformance/parser/ecmascript5/Statements/LabeledStatements/parser_duplicateLabel2.ts (1 errors) ====
target:
while (true) {
target:
~~~~~~
!!! Duplicate label 'target'
while (true) {
}
}

View File

@@ -1,13 +0,0 @@
//// [parser_duplicateLabel2.ts]
target:
while (true) {
target:
while (true) {
}
}
//// [parser_duplicateLabel2.js]
target: while (true) {
target: while (true) {
}
}

View File

@@ -1,3 +0,0 @@
while (true) {
break;
}

View File

@@ -1,4 +0,0 @@
do {
break;
}
while (true);

View File

@@ -1,3 +0,0 @@
for (;;) {
break;
}

View File

@@ -1,3 +0,0 @@
for (var i in something) {
break;
}

View File

@@ -1,2 +0,0 @@
target:
break target;

View File

@@ -1,4 +0,0 @@
target:
while (true) {
break target;
}

View File

@@ -1,5 +0,0 @@
target1:
target2:
while (true) {
break target1;
}

View File

@@ -1,5 +0,0 @@
target1:
target2:
while (true) {
break target2;
}

View File

@@ -1,8 +0,0 @@
target:
while (true) {
function f() {
while (true) {
break target;
}
}
}

View File

@@ -1,3 +0,0 @@
while (true) {
break target;
}

View File

@@ -1,3 +0,0 @@
while (true) {
continue;
}

View File

@@ -1,4 +0,0 @@
do {
continue;
}
while (true);

View File

@@ -1,3 +0,0 @@
for (;;) {
continue;
}

View File

@@ -1,3 +0,0 @@
for (var i in something) {
continue;
}

View File

@@ -1,3 +0,0 @@
label1: for(var i = 0; i < 1; i++) {
continue label1;
}

View File

@@ -1,6 +0,0 @@
TWO:
while (true){
var x = () => {
continue TWO;
}
}

View File

@@ -1,2 +0,0 @@
target:
continue target;

View File

@@ -1,4 +0,0 @@
target:
while (true) {
continue target;
}

View File

@@ -1,5 +0,0 @@
target1:
target2:
while (true) {
continue target1;
}

View File

@@ -1,5 +0,0 @@
target1:
target2:
while (true) {
continue target2;
}

View File

@@ -1,8 +0,0 @@
target:
while (true) {
function f() {
while (true) {
continue target;
}
}
}

View File

@@ -1,3 +0,0 @@
while (true) {
continue target;
}

View File

@@ -1,4 +0,0 @@
target:
target:
while (true) {
}

View File

@@ -1,6 +0,0 @@
target:
while (true) {
target:
while (true) {
}
}

View File

@@ -1,8 +0,0 @@
target:
while (true) {
function f() {
target:
while (true) {
}
}
}

View File

@@ -1,7 +0,0 @@
target:
while (true) {
}
target:
while (true) {
}