diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 5a1f6f440fe7e..5ee0f6c3f0af3 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -35325,6 +35325,10 @@ namespace ts { // Grammar checking if (!checkGrammarMethod(node)) checkGrammarComputedPropertyName(node.name); + if (isMethodDeclaration(node) && node.asteriskToken && isIdentifier(node.name) && idText(node.name) === "constructor") { + error(node.name, Diagnostics.Class_constructor_may_not_be_a_generator); + } + // Grammar checking for modifiers is done inside the function checkGrammarFunctionLikeDeclaration checkFunctionOrMethodDeclaration(node); @@ -35477,6 +35481,9 @@ namespace ts { } function checkAccessorDeclaration(node: AccessorDeclaration) { + if (isIdentifier(node.name) && idText(node.name) === "constructor") { + error(node.name, Diagnostics.Class_constructor_may_not_be_an_accessor); + } addLazyDiagnostic(checkAccessorDeclarationDiagnostics); checkSourceElement(node.body); setNodeLinksForPrivateIdentifierScope(node); diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 207b23d70135a..16aa9a573046f 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1012,6 +1012,10 @@ "category": "Error", "code": 1340 }, + "Class constructor may not be an accessor.": { + "category": "Error", + "code": 1341 + }, "Type arguments cannot be used here.": { "category": "Error", "code": 1342 @@ -1084,6 +1088,10 @@ "category": "Error", "code": 1359 }, + "Class constructor may not be a generator.": { + "category": "Error", + "code": 1360 + }, "'{0}' cannot be used as a value because it was imported using 'import type'.": { "category": "Error", "code": 1361 diff --git a/src/compiler/program.ts b/src/compiler/program.ts index c7f886ea3119f..823fbf12a2e87 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -967,6 +967,8 @@ namespace ts { Diagnostics.extends_clause_already_seen.code, Diagnostics.let_declarations_can_only_be_declared_inside_a_block.code, Diagnostics.let_is_not_allowed_to_be_used_as_a_name_in_let_or_const_declarations.code, + Diagnostics.Class_constructor_may_not_be_a_generator.code, + Diagnostics.Class_constructor_may_not_be_an_accessor.code, ]); /** diff --git a/tests/baselines/reference/constructorNameInAccessor.errors.txt b/tests/baselines/reference/constructorNameInAccessor.errors.txt new file mode 100644 index 0000000000000..7033dec4e5bed --- /dev/null +++ b/tests/baselines/reference/constructorNameInAccessor.errors.txt @@ -0,0 +1,14 @@ +tests/cases/conformance/salsa/constructorNameInAccessor.ts(2,9): error TS1341: Class constructor may not be an accessor. +tests/cases/conformance/salsa/constructorNameInAccessor.ts(3,9): error TS1341: Class constructor may not be an accessor. + + +==== tests/cases/conformance/salsa/constructorNameInAccessor.ts (2 errors) ==== + class C1 { + get constructor() { return } + ~~~~~~~~~~~ +!!! error TS1341: Class constructor may not be an accessor. + set constructor(value) {} + ~~~~~~~~~~~ +!!! error TS1341: Class constructor may not be an accessor. + } + \ No newline at end of file diff --git a/tests/baselines/reference/constructorNameInAccessor.js b/tests/baselines/reference/constructorNameInAccessor.js new file mode 100644 index 0000000000000..041d812b01620 --- /dev/null +++ b/tests/baselines/reference/constructorNameInAccessor.js @@ -0,0 +1,12 @@ +//// [constructorNameInAccessor.ts] +class C1 { + get constructor() { return } + set constructor(value) {} +} + + +//// [constructorNameInAccessor.js] +class C1 { + get constructor() { return; } + set constructor(value) { } +} diff --git a/tests/baselines/reference/constructorNameInAccessor.symbols b/tests/baselines/reference/constructorNameInAccessor.symbols new file mode 100644 index 0000000000000..cea664a716f80 --- /dev/null +++ b/tests/baselines/reference/constructorNameInAccessor.symbols @@ -0,0 +1,12 @@ +=== tests/cases/conformance/salsa/constructorNameInAccessor.ts === +class C1 { +>C1 : Symbol(C1, Decl(constructorNameInAccessor.ts, 0, 0)) + + get constructor() { return } +>constructor : Symbol(C1.constructor, Decl(constructorNameInAccessor.ts, 0, 10), Decl(constructorNameInAccessor.ts, 1, 32)) + + set constructor(value) {} +>constructor : Symbol(C1.constructor, Decl(constructorNameInAccessor.ts, 0, 10), Decl(constructorNameInAccessor.ts, 1, 32)) +>value : Symbol(value, Decl(constructorNameInAccessor.ts, 2, 20)) +} + diff --git a/tests/baselines/reference/constructorNameInAccessor.types b/tests/baselines/reference/constructorNameInAccessor.types new file mode 100644 index 0000000000000..b81c47ec3e2d8 --- /dev/null +++ b/tests/baselines/reference/constructorNameInAccessor.types @@ -0,0 +1,12 @@ +=== tests/cases/conformance/salsa/constructorNameInAccessor.ts === +class C1 { +>C1 : C1 + + get constructor() { return } +>constructor : void + + set constructor(value) {} +>constructor : void +>value : void +} + diff --git a/tests/baselines/reference/constructorNameInGenerator.errors.txt b/tests/baselines/reference/constructorNameInGenerator.errors.txt new file mode 100644 index 0000000000000..061560615fb0c --- /dev/null +++ b/tests/baselines/reference/constructorNameInGenerator.errors.txt @@ -0,0 +1,10 @@ +tests/cases/conformance/salsa/constructorNameInGenerator.ts(2,6): error TS1360: Class constructor may not be a generator. + + +==== tests/cases/conformance/salsa/constructorNameInGenerator.ts (1 errors) ==== + class C2 { + *constructor() {} + ~~~~~~~~~~~ +!!! error TS1360: Class constructor may not be a generator. + } + \ No newline at end of file diff --git a/tests/baselines/reference/constructorNameInGenerator.js b/tests/baselines/reference/constructorNameInGenerator.js new file mode 100644 index 0000000000000..fb7b318a1923d --- /dev/null +++ b/tests/baselines/reference/constructorNameInGenerator.js @@ -0,0 +1,10 @@ +//// [constructorNameInGenerator.ts] +class C2 { + *constructor() {} +} + + +//// [constructorNameInGenerator.js] +class C2 { + *constructor() { } +} diff --git a/tests/baselines/reference/constructorNameInGenerator.symbols b/tests/baselines/reference/constructorNameInGenerator.symbols new file mode 100644 index 0000000000000..ea64a07a65188 --- /dev/null +++ b/tests/baselines/reference/constructorNameInGenerator.symbols @@ -0,0 +1,8 @@ +=== tests/cases/conformance/salsa/constructorNameInGenerator.ts === +class C2 { +>C2 : Symbol(C2, Decl(constructorNameInGenerator.ts, 0, 0)) + + *constructor() {} +>constructor : Symbol(C2.constructor, Decl(constructorNameInGenerator.ts, 0, 10)) +} + diff --git a/tests/baselines/reference/constructorNameInGenerator.types b/tests/baselines/reference/constructorNameInGenerator.types new file mode 100644 index 0000000000000..ba5f4f243da43 --- /dev/null +++ b/tests/baselines/reference/constructorNameInGenerator.types @@ -0,0 +1,8 @@ +=== tests/cases/conformance/salsa/constructorNameInGenerator.ts === +class C2 { +>C2 : C2 + + *constructor() {} +>constructor : () => Generator +} + diff --git a/tests/cases/conformance/salsa/constructorNameInAccessor.ts b/tests/cases/conformance/salsa/constructorNameInAccessor.ts new file mode 100644 index 0000000000000..878c4b8dc788a --- /dev/null +++ b/tests/cases/conformance/salsa/constructorNameInAccessor.ts @@ -0,0 +1,5 @@ +// @target: esnext +class C1 { + get constructor() { return } + set constructor(value) {} +} diff --git a/tests/cases/conformance/salsa/constructorNameInGenerator.ts b/tests/cases/conformance/salsa/constructorNameInGenerator.ts new file mode 100644 index 0000000000000..7040fb40baaf6 --- /dev/null +++ b/tests/cases/conformance/salsa/constructorNameInGenerator.ts @@ -0,0 +1,4 @@ +// @target: esnext +class C2 { + *constructor() {} +}