From 4ac676f718514c47a3f236013dd9742c38cf7c0b Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Mon, 21 Jul 2014 14:58:57 -0700 Subject: [PATCH] Added checking for switch statements with multiple default clauses. --- src/compiler/core.ts | 12 ++++-- .../diagnosticInformationMap.generated.ts | 1 + src/compiler/diagnosticMessages.json | 5 ++- src/compiler/parser.ts | 11 +++++- ...hStatementsWithMultipleDefaults.errors.txt | 37 +++++++++++++++++++ .../switchStatementsWithMultipleDefaults.ts | 27 ++++++++++++++ 6 files changed, 87 insertions(+), 6 deletions(-) create mode 100644 tests/baselines/reference/switchStatementsWithMultipleDefaults.errors.txt create mode 100644 tests/cases/compiler/switchStatementsWithMultipleDefaults.ts diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 6b1b22487e..27a9f163d5 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -19,7 +19,9 @@ module ts { if (array) { var len = array.length; for (var i = 0; i < len; i++) { - if (array[i] === value) return true; + if (array[i] === value) { + return true; + } } } return false; @@ -29,7 +31,9 @@ module ts { if (array) { var len = array.length; for (var i = 0; i < len; i++) { - if (array[i] === value) return i; + if (array[i] === value) { + return i; + } } } return -1; @@ -41,7 +45,9 @@ module ts { result = []; for (var i = 0, len = array.length; i < len; i++) { var item = array[i]; - if (f(item)) result.push(item); + if (f(item)) { + result.push(item); + } } } return result; diff --git a/src/compiler/diagnosticInformationMap.generated.ts b/src/compiler/diagnosticInformationMap.generated.ts index 2c967b40b6..8b47bd15e2 100644 --- a/src/compiler/diagnosticInformationMap.generated.ts +++ b/src/compiler/diagnosticInformationMap.generated.ts @@ -98,6 +98,7 @@ module ts { Type_expected: { code: -9999999, category: DiagnosticCategory.Error, key: "Type expected." }, A_constructor_implementation_cannot_be_declared_in_an_ambient_context: { code: 1111, category: DiagnosticCategory.Error, key: "A constructor implementation cannot be declared in an ambient context." }, A_class_member_cannot_be_declared_optional: { code: 1112, category: DiagnosticCategory.Error, key: "A class member cannot be declared optional." }, + A_default_clause_cannot_appear_more_than_once_in_a_switch_statement: { code: 1113, category: DiagnosticCategory.Error, key: "A 'default' clause cannot appear more than once in a 'switch' statement." }, Duplicate_identifier_0: { code: 2000, category: DiagnosticCategory.Error, key: "Duplicate identifier '{0}'." }, new_T_cannot_be_used_to_create_an_array_Use_new_Array_T_instead: { code: 2068, category: DiagnosticCategory.Error, key: "'new T[]' cannot be used to create an array. Use 'new Array()' instead." }, Multiple_constructor_implementations_are_not_allowed: { code: 2070, category: DiagnosticCategory.Error, key: "Multiple constructor implementations are not allowed." }, diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 55d0ffa226..3114b18136 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -384,7 +384,10 @@ "category": "Error", "code": 1112 }, - + "A 'default' clause cannot appear more than once in a 'switch' statement.": { + "category": "Error", + "code": 1113 + }, "Duplicate identifier '{0}'.": { "category": "Error", diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index fcfb2120b7..ec2b37f291 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -766,7 +766,7 @@ module ts { return false; } - // Parses a list of elements + // Parses a semicolon-delimited list of elements function parseList(kind: ParsingContext, parseElement: () => T): NodeArray { var saveParsingContext = parsingContext; parsingContext |= 1 << kind; @@ -789,7 +789,7 @@ module ts { return result; } - // Parses a comma delimited list of elements + // Parses a comma-delimited list of elements function parseDelimitedList(kind: ParsingContext, parseElement: () => T, trailingCommaBehavior: TrailingCommaBehavior): NodeArray { var saveParsingContext = parsingContext; parsingContext |= 1 << kind; @@ -2063,6 +2063,13 @@ module ts { parseExpected(SyntaxKind.OpenBraceToken); node.clauses = parseList(ParsingContext.SwitchClauses, parseCaseOrDefaultClause); parseExpected(SyntaxKind.CloseBraceToken); + + // Error on duplicate 'default' clauses. + var defaultClauses = filter(node.clauses, clause => clause.kind === SyntaxKind.DefaultClause); + for (var i = 1, len = defaultClauses.length; i < len; i++) { + grammarErrorOnNode(defaultClauses[i], Diagnostics.A_default_clause_cannot_appear_more_than_once_in_a_switch_statement); + } + return finishNode(node); } diff --git a/tests/baselines/reference/switchStatementsWithMultipleDefaults.errors.txt b/tests/baselines/reference/switchStatementsWithMultipleDefaults.errors.txt new file mode 100644 index 0000000000..fef743e13e --- /dev/null +++ b/tests/baselines/reference/switchStatementsWithMultipleDefaults.errors.txt @@ -0,0 +1,37 @@ +==== tests/cases/compiler/switchStatementsWithMultipleDefaults.ts (4 errors) ==== + + var x = 10; + + switch (x) { + case 1: + case 2: + default: // No issues. + break; + default: // Error; second 'default' clause. + ~~~~~~~~ +!!! A 'default' clause cannot appear more than once in a 'switch' statement. + default: // Error; third 'default' clause. + ~~~~~~~~ +!!! A 'default' clause cannot appear more than once in a 'switch' statement. + case 3: + x *= x; + } + + switch (x) { + default: // No issues. + break; + case 100: + switch (x * x) { + default: // No issues. + default: // Error; second 'default' clause. + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + break; + ~~~~~~~~~~~~~~~~~~~~~~ +!!! A 'default' clause cannot appear more than once in a 'switch' statement. + case 10000: + x /= x; + default: + ~~~~~~~~ +!!! A 'default' clause cannot appear more than once in a 'switch' statement. + } + } \ No newline at end of file diff --git a/tests/cases/compiler/switchStatementsWithMultipleDefaults.ts b/tests/cases/compiler/switchStatementsWithMultipleDefaults.ts new file mode 100644 index 0000000000..8e0f9121b4 --- /dev/null +++ b/tests/cases/compiler/switchStatementsWithMultipleDefaults.ts @@ -0,0 +1,27 @@ + +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; +} + +switch (x) { + default: // No issues. + break; + case 100: + switch (x * x) { + default: // No issues. + default: // Error; second 'default' clause. + break; + case 10000: + x /= x; + default: + } +} \ No newline at end of file