Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Emit grammar error on quoted constructors and class fields named “constructor” #31119

Merged
merged 7 commits into from May 1, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/compiler/checker.ts
Expand Up @@ -31468,6 +31468,9 @@ namespace ts {
return grammarErrorAtPos(node, node.end - 1, ";".length, Diagnostics._0_expected, "{");
}
}
else if (isClassLike(node.parent) && isStringLiteral(node.name) && node.name.text === "constructor" && (!compilerOptions.target || compilerOptions.target < ScriptTarget.ES5)) {
return grammarErrorOnNode(node.name, Diagnostics.Quoted_constructors_have_previously_been_interpreted_as_methods_which_is_incorrect_In_TypeScript_3_6_they_will_be_correctly_parsed_as_constructors_In_the_meantime_consider_using_constructor_to_write_a_constructor_or_constructor_to_write_a_method);
}
if (checkGrammarForGenerator(node)) {
return true;
}
Expand Down Expand Up @@ -31786,6 +31789,9 @@ namespace ts {

function checkGrammarProperty(node: PropertyDeclaration | PropertySignature) {
if (isClassLike(node.parent)) {
if (isStringLiteral(node.name) && node.name.text === "constructor") {
return grammarErrorOnNode(node.name, Diagnostics.Classes_may_not_have_a_field_named_constructor);
}
if (checkGrammarForInvalidDynamicName(node.name, Diagnostics.A_computed_property_name_in_a_class_property_declaration_must_refer_to_an_expression_whose_type_is_a_literal_type_or_a_unique_symbol_type)) {
return true;
}
Expand Down
10 changes: 9 additions & 1 deletion src/compiler/diagnosticMessages.json
Expand Up @@ -2959,7 +2959,7 @@
"category": "Error",
"code": 4104
},

"The current host does not support the '{0}' option.": {
"category": "Error",
"code": 5001
Expand Down Expand Up @@ -4954,5 +4954,13 @@
"No value exists in scope for the shorthand property '{0}'. Either declare one or provide an initializer." :{
"category": "Error",
"code": 18004
},
"Quoted constructors have previously been interpreted as methods, which is incorrect. In TypeScript 3.6, they will be correctly parsed as constructors. In the meantime, consider using 'constructor()' to write a constructor, or '[\"constructor\"]()' to write a method.": {
"category": "Error",
"code": 18005
},
"Classes may not have a field named 'constructor'.": {
"category": "Error",
"code": 18006
}
}
5 changes: 4 additions & 1 deletion tests/baselines/reference/convertKeywordsYes.errors.txt
@@ -1,3 +1,4 @@
tests/cases/compiler/convertKeywordsYes.ts(175,12): error TS18006: Classes may not have a field named 'constructor'.
tests/cases/compiler/convertKeywordsYes.ts(292,11): error TS1213: Identifier expected. 'implements' is a reserved word in strict mode. Class definitions are automatically in strict mode.
tests/cases/compiler/convertKeywordsYes.ts(293,11): error TS1213: Identifier expected. 'interface' is a reserved word in strict mode. Class definitions are automatically in strict mode.
tests/cases/compiler/convertKeywordsYes.ts(294,11): error TS1213: Identifier expected. 'let' is a reserved word in strict mode. Class definitions are automatically in strict mode.
Expand All @@ -9,7 +10,7 @@ tests/cases/compiler/convertKeywordsYes.ts(301,11): error TS1213: Identifier exp
tests/cases/compiler/convertKeywordsYes.ts(303,11): error TS1213: Identifier expected. 'yield' is a reserved word in strict mode. Class definitions are automatically in strict mode.


==== tests/cases/compiler/convertKeywordsYes.ts (9 errors) ====
==== tests/cases/compiler/convertKeywordsYes.ts (10 errors) ====
// reserved ES5 future in strict mode

var constructor = 0;
Expand Down Expand Up @@ -185,6 +186,8 @@ tests/cases/compiler/convertKeywordsYes.ts(303,11): error TS1213: Identifier exp

class bigClass {
public "constructor" = 0;
~~~~~~~~~~~~~
!!! error TS18006: Classes may not have a field named 'constructor'.
public any = 0;
public boolean = 0;
public implements = 0;
Expand Down
14 changes: 14 additions & 0 deletions tests/baselines/reference/propertyNamedConstructor.errors.txt
@@ -0,0 +1,14 @@
tests/cases/conformance/classes/propertyMemberDeclarations/propertyNamedConstructor.ts(2,3): error TS18006: Classes may not have a field named 'constructor'.


==== tests/cases/conformance/classes/propertyMemberDeclarations/propertyNamedConstructor.ts (1 errors) ====
class X1 {
"constructor" = 3; // Error
~~~~~~~~~~~~~
!!! error TS18006: Classes may not have a field named 'constructor'.
}

class X2 {
["constructor"] = 3;
}

23 changes: 23 additions & 0 deletions tests/baselines/reference/propertyNamedConstructor.js
@@ -0,0 +1,23 @@
//// [propertyNamedConstructor.ts]
class X1 {
"constructor" = 3; // Error
}

class X2 {
["constructor"] = 3;
}


//// [propertyNamedConstructor.js]
var X1 = /** @class */ (function () {
function X1() {
this["constructor"] = 3; // Error
}
return X1;
}());
var X2 = /** @class */ (function () {
function X2() {
this["constructor"] = 3;
}
return X2;
}());
16 changes: 16 additions & 0 deletions tests/baselines/reference/propertyNamedConstructor.symbols
@@ -0,0 +1,16 @@
=== tests/cases/conformance/classes/propertyMemberDeclarations/propertyNamedConstructor.ts ===
class X1 {
>X1 : Symbol(X1, Decl(propertyNamedConstructor.ts, 0, 0))

"constructor" = 3; // Error
>"constructor" : Symbol(X1["constructor"], Decl(propertyNamedConstructor.ts, 0, 10))
}

class X2 {
>X2 : Symbol(X2, Decl(propertyNamedConstructor.ts, 2, 1))

["constructor"] = 3;
>["constructor"] : Symbol(X2["constructor"], Decl(propertyNamedConstructor.ts, 4, 10))
>"constructor" : Symbol(X2["constructor"], Decl(propertyNamedConstructor.ts, 4, 10))
}

18 changes: 18 additions & 0 deletions tests/baselines/reference/propertyNamedConstructor.types
@@ -0,0 +1,18 @@
=== tests/cases/conformance/classes/propertyMemberDeclarations/propertyNamedConstructor.ts ===
class X1 {
>X1 : X1

"constructor" = 3; // Error
>"constructor" : number
>3 : 3
}

class X2 {
>X2 : X2

["constructor"] = 3;
>["constructor"] : number
>"constructor" : "constructor"
>3 : 3
}

30 changes: 30 additions & 0 deletions tests/baselines/reference/quotedConstructors.errors.txt
@@ -0,0 +1,30 @@
tests/cases/conformance/classes/constructorDeclarations/quotedConstructors.ts(2,5): error TS18005: Quoted constructors have previously been interpreted as methods, which is incorrect. In TypeScript 3.6, they will be correctly parsed as constructors. In the meantime, consider using 'constructor()' to write a constructor, or '["constructor"]()' to write a method.
tests/cases/conformance/classes/constructorDeclarations/quotedConstructors.ts(6,5): error TS18005: Quoted constructors have previously been interpreted as methods, which is incorrect. In TypeScript 3.6, they will be correctly parsed as constructors. In the meantime, consider using 'constructor()' to write a constructor, or '["constructor"]()' to write a method.
tests/cases/conformance/classes/constructorDeclarations/quotedConstructors.ts(14,5): error TS18005: Quoted constructors have previously been interpreted as methods, which is incorrect. In TypeScript 3.6, they will be correctly parsed as constructors. In the meantime, consider using 'constructor()' to write a constructor, or '["constructor"]()' to write a method.


==== tests/cases/conformance/classes/constructorDeclarations/quotedConstructors.ts (3 errors) ====
class C {
"constructor"() {} // Error in 3.5
~~~~~~~~~~~~~
!!! error TS18005: Quoted constructors have previously been interpreted as methods, which is incorrect. In TypeScript 3.6, they will be correctly parsed as constructors. In the meantime, consider using 'constructor()' to write a constructor, or '["constructor"]()' to write a method.
}

class D {
'constructor'() {} // Error in 3.5
~~~~~~~~~~~~~
!!! error TS18005: Quoted constructors have previously been interpreted as methods, which is incorrect. In TypeScript 3.6, they will be correctly parsed as constructors. In the meantime, consider using 'constructor()' to write a constructor, or '["constructor"]()' to write a method.
}

class E {
['constructor']() {}
}

new class {
"constructor"() {} // Error in 3.5
~~~~~~~~~~~~~
!!! error TS18005: Quoted constructors have previously been interpreted as methods, which is incorrect. In TypeScript 3.6, they will be correctly parsed as constructors. In the meantime, consider using 'constructor()' to write a constructor, or '["constructor"]()' to write a method.
};

var o = { "constructor"() {} };

46 changes: 46 additions & 0 deletions tests/baselines/reference/quotedConstructors.js
@@ -0,0 +1,46 @@
//// [quotedConstructors.ts]
class C {
"constructor"() {} // Error in 3.5
}

class D {
'constructor'() {} // Error in 3.5
}

class E {
['constructor']() {}
}

new class {
"constructor"() {} // Error in 3.5
};

var o = { "constructor"() {} };


//// [quotedConstructors.js]
var C = /** @class */ (function () {
function C() {
}
C.prototype["constructor"] = function () { }; // Error in 3.5
return C;
}());
var D = /** @class */ (function () {
function D() {
}
D.prototype['constructor'] = function () { }; // Error in 3.5
return D;
}());
var E = /** @class */ (function () {
function E() {
}
E.prototype['constructor'] = function () { };
return E;
}());
new /** @class */ (function () {
function class_1() {
}
class_1.prototype["constructor"] = function () { }; // Error in 3.5
return class_1;
}());
var o = { "constructor": function () { } };
33 changes: 33 additions & 0 deletions tests/baselines/reference/quotedConstructors.symbols
@@ -0,0 +1,33 @@
=== tests/cases/conformance/classes/constructorDeclarations/quotedConstructors.ts ===
class C {
>C : Symbol(C, Decl(quotedConstructors.ts, 0, 0))

"constructor"() {} // Error in 3.5
>"constructor" : Symbol(C["constructor"], Decl(quotedConstructors.ts, 0, 9))
}

class D {
>D : Symbol(D, Decl(quotedConstructors.ts, 2, 1))

'constructor'() {} // Error in 3.5
>'constructor' : Symbol(D['constructor'], Decl(quotedConstructors.ts, 4, 9))
}

class E {
>E : Symbol(E, Decl(quotedConstructors.ts, 6, 1))

['constructor']() {}
>['constructor'] : Symbol(E['constructor'], Decl(quotedConstructors.ts, 8, 9))
>'constructor' : Symbol(E['constructor'], Decl(quotedConstructors.ts, 8, 9))
}

new class {
"constructor"() {} // Error in 3.5
>"constructor" : Symbol((Anonymous class)["constructor"], Decl(quotedConstructors.ts, 12, 11))

};

var o = { "constructor"() {} };
>o : Symbol(o, Decl(quotedConstructors.ts, 16, 3))
>"constructor" : Symbol("constructor", Decl(quotedConstructors.ts, 16, 9))

37 changes: 37 additions & 0 deletions tests/baselines/reference/quotedConstructors.types
@@ -0,0 +1,37 @@
=== tests/cases/conformance/classes/constructorDeclarations/quotedConstructors.ts ===
class C {
>C : C

"constructor"() {} // Error in 3.5
>"constructor" : () => void
}

class D {
>D : D

'constructor'() {} // Error in 3.5
>'constructor' : () => void
}

class E {
>E : E

['constructor']() {}
>['constructor'] : () => void
>'constructor' : "constructor"
}

new class {
>new class { "constructor"() {} // Error in 3.5} : (Anonymous class)
>class { "constructor"() {} // Error in 3.5} : typeof (Anonymous class)

"constructor"() {} // Error in 3.5
>"constructor" : () => void

};

var o = { "constructor"() {} };
>o : { "constructor"(): void; }
>{ "constructor"() {} } : { "constructor"(): void; }
>"constructor" : () => void

@@ -0,0 +1,17 @@
class C {
"constructor"() {} // Error in 3.5
}

class D {
'constructor'() {} // Error in 3.5
}

class E {
['constructor']() {}
}

new class {
"constructor"() {} // Error in 3.5
};

var o = { "constructor"() {} };
@@ -0,0 +1,7 @@
class X1 {
"constructor" = 3; // Error
}

class X2 {
["constructor"] = 3;
}