diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 39dd49176b6..cccd74e3907 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -10916,9 +10916,32 @@ module ts { } } } + + var checkLetConstNames = languageVersion >= ScriptTarget.ES6 && (isLet(node) || isConst(node)); + + // 1. LexicalDeclaration : LetOrConst BindingList ; + // It is a Syntax Error if the BoundNames of BindingList contains "let". + // 2. ForDeclaration: ForDeclaration : LetOrConst ForBinding + // It is a Syntax Error if the BoundNames of ForDeclaration contains "let". + // It is a SyntaxError if a VariableDeclaration or VariableDeclarationNoIn occurs within strict code // and its Identifier is eval or arguments - return checkGrammarEvalOrArgumentsInStrictMode(node, node.name); + return (checkLetConstNames && checkGrammarNameInLetOrConstDeclarations(node.name)) || + checkGrammarEvalOrArgumentsInStrictMode(node, node.name); + } + + function checkGrammarNameInLetOrConstDeclarations(name: Identifier | BindingPattern): boolean { + if (name.kind === SyntaxKind.Identifier) { + if ((name).text === "let") { + return grammarErrorOnNode(name, Diagnostics.let_is_not_allowed_to_be_used_as_a_name_in_let_or_const_declarations); + } + } + else { + var elements = (name).elements; + for (var i = 0; i < elements.length; ++i) { + checkGrammarNameInLetOrConstDeclarations(elements[i].name); + } + } } function checkGrammarVariableDeclarationList(declarationList: VariableDeclarationList): boolean { diff --git a/src/compiler/diagnosticInformationMap.generated.ts b/src/compiler/diagnosticInformationMap.generated.ts index a0e323dca1c..6c79578e41c 100644 --- a/src/compiler/diagnosticInformationMap.generated.ts +++ b/src/compiler/diagnosticInformationMap.generated.ts @@ -380,6 +380,7 @@ module ts { const_enum_member_initializer_was_evaluated_to_a_non_finite_value: { code: 4086, category: DiagnosticCategory.Error, key: "'const' enum member initializer was evaluated to a non-finite value." }, const_enum_member_initializer_was_evaluated_to_disallowed_value_NaN: { code: 4087, category: DiagnosticCategory.Error, key: "'const' enum member initializer was evaluated to disallowed value 'NaN'." }, Property_0_does_not_exist_on_const_enum_1: { code: 4088, category: DiagnosticCategory.Error, key: "Property '{0}' does not exist on 'const' enum '{1}'." }, + let_is_not_allowed_to_be_used_as_a_name_in_let_or_const_declarations: { code: 4089, category: DiagnosticCategory.Error, key: "'let' is not allowed to be used as a name in 'let' or 'const' declarations." }, The_current_host_does_not_support_the_0_option: { code: 5001, category: DiagnosticCategory.Error, key: "The current host does not support the '{0}' option." }, Cannot_find_the_common_subdirectory_path_for_the_input_files: { code: 5009, category: DiagnosticCategory.Error, key: "Cannot find the common subdirectory path for the input files." }, Cannot_read_file_0_Colon_1: { code: 5012, category: DiagnosticCategory.Error, key: "Cannot read file '{0}': {1}" }, diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 69db958075f..8a5d8d80427 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1513,6 +1513,10 @@ "category": "Error", "code": 4088 }, + "'let' is not allowed to be used as a name in 'let' or 'const' declarations.": { + "category": "Error", + "code": 4089 + }, "The current host does not support the '{0}' option.": { "category": "Error", "code": 5001 diff --git a/tests/baselines/reference/letInLetOrConstDeclarations.errors.txt b/tests/baselines/reference/letInLetOrConstDeclarations.errors.txt new file mode 100644 index 00000000000..93dc307fc85 --- /dev/null +++ b/tests/baselines/reference/letInLetOrConstDeclarations.errors.txt @@ -0,0 +1,23 @@ +tests/cases/compiler/letInLetOrConstDeclarations.ts(2,9): error TS4089: 'let' is not allowed to be used as a name in 'let' or 'const' declarations. +tests/cases/compiler/letInLetOrConstDeclarations.ts(3,14): error TS4089: 'let' is not allowed to be used as a name in 'let' or 'const' declarations. +tests/cases/compiler/letInLetOrConstDeclarations.ts(6,11): error TS4089: 'let' is not allowed to be used as a name in 'let' or 'const' declarations. + + +==== tests/cases/compiler/letInLetOrConstDeclarations.ts (3 errors) ==== + { + let let = 1; // should error + ~~~ +!!! error TS4089: 'let' is not allowed to be used as a name in 'let' or 'const' declarations. + for (let let in []) { } // should error + ~~~ +!!! error TS4089: 'let' is not allowed to be used as a name in 'let' or 'const' declarations. + } + { + const let = 1; // should error + ~~~ +!!! error TS4089: 'let' is not allowed to be used as a name in 'let' or 'const' declarations. + } + { + function let() { // should be ok + } + } \ No newline at end of file diff --git a/tests/baselines/reference/letInLetOrConstDeclarations.js b/tests/baselines/reference/letInLetOrConstDeclarations.js new file mode 100644 index 00000000000..ee23abc4e4f --- /dev/null +++ b/tests/baselines/reference/letInLetOrConstDeclarations.js @@ -0,0 +1,25 @@ +//// [letInLetOrConstDeclarations.ts] +{ + let let = 1; // should error + for (let let in []) { } // should error +} +{ + const let = 1; // should error +} +{ + function let() { // should be ok + } +} + +//// [letInLetOrConstDeclarations.js] +{ + let let = 1; // should error + for (let let in []) { } // should error +} +{ + const let = 1; // should error +} +{ + function let() { + } +} diff --git a/tests/cases/compiler/letInLetOrConstDeclarations.ts b/tests/cases/compiler/letInLetOrConstDeclarations.ts new file mode 100644 index 00000000000..c622759a459 --- /dev/null +++ b/tests/cases/compiler/letInLetOrConstDeclarations.ts @@ -0,0 +1,12 @@ +// @target: es6 +{ + let let = 1; // should error + for (let let in []) { } // should error +} +{ + const let = 1; // should error +} +{ + function let() { // should be ok + } +} \ No newline at end of file