From 4cc27227001d7d9895bf930f750eb57955ac4214 Mon Sep 17 00:00:00 2001 From: Jason Freeman Date: Fri, 16 Jan 2015 19:15:24 -0800 Subject: [PATCH] Disallow this in computed properties in classes --- src/compiler/checker.ts | 3 +++ .../diagnosticInformationMap.generated.ts | 1 + src/compiler/diagnosticMessages.json | 4 ++++ src/compiler/utilities.ts | 8 +++++++ src/services/services.ts | 2 ++ .../reference/computedPropertyNames18.js | 13 +++++++++++ .../reference/computedPropertyNames18.types | 14 +++++++++++ .../computedPropertyNames19.errors.txt | 11 +++++++++ .../reference/computedPropertyNames19.js | 14 +++++++++++ .../reference/computedPropertyNames20.js | 9 ++++++++ .../reference/computedPropertyNames20.types | 10 ++++++++ .../computedPropertyNames21.errors.txt | 12 ++++++++++ .../reference/computedPropertyNames21.js | 19 +++++++++++++++ .../reference/computedPropertyNames22.js | 23 +++++++++++++++++++ .../reference/computedPropertyNames22.types | 21 +++++++++++++++++ .../computedPropertyNames23.errors.txt | 14 +++++++++++ .../reference/computedPropertyNames23.js | 21 +++++++++++++++++ .../computedPropertyNames18.ts | 6 +++++ .../computedPropertyNames19.ts | 6 +++++ .../computedPropertyNames20.ts | 4 ++++ .../computedPropertyNames21.ts | 7 ++++++ .../computedPropertyNames22.ts | 9 ++++++++ .../computedPropertyNames23.ts | 9 ++++++++ 23 files changed, 240 insertions(+) create mode 100644 tests/baselines/reference/computedPropertyNames18.js create mode 100644 tests/baselines/reference/computedPropertyNames18.types create mode 100644 tests/baselines/reference/computedPropertyNames19.errors.txt create mode 100644 tests/baselines/reference/computedPropertyNames19.js create mode 100644 tests/baselines/reference/computedPropertyNames20.js create mode 100644 tests/baselines/reference/computedPropertyNames20.types create mode 100644 tests/baselines/reference/computedPropertyNames21.errors.txt create mode 100644 tests/baselines/reference/computedPropertyNames21.js create mode 100644 tests/baselines/reference/computedPropertyNames22.js create mode 100644 tests/baselines/reference/computedPropertyNames22.types create mode 100644 tests/baselines/reference/computedPropertyNames23.errors.txt create mode 100644 tests/baselines/reference/computedPropertyNames23.js create mode 100644 tests/cases/conformance/es6/computedProperties/computedPropertyNames18.ts create mode 100644 tests/cases/conformance/es6/computedProperties/computedPropertyNames19.ts create mode 100644 tests/cases/conformance/es6/computedProperties/computedPropertyNames20.ts create mode 100644 tests/cases/conformance/es6/computedProperties/computedPropertyNames21.ts create mode 100644 tests/cases/conformance/es6/computedProperties/computedPropertyNames22.ts create mode 100644 tests/cases/conformance/es6/computedProperties/computedPropertyNames23.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 3232fe1749a..8c5b49014ad 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4853,6 +4853,9 @@ module ts { // do not return here so in case if lexical this is captured - it will be reflected in flags on NodeLinks } break; + case SyntaxKind.ComputedPropertyName: + error(node, Diagnostics.this_cannot_be_referenced_in_a_computed_property_name); + break; } if (needToCaptureLexicalThis) { diff --git a/src/compiler/diagnosticInformationMap.generated.ts b/src/compiler/diagnosticInformationMap.generated.ts index 6354633fe60..fb9811b396b 100644 --- a/src/compiler/diagnosticInformationMap.generated.ts +++ b/src/compiler/diagnosticInformationMap.generated.ts @@ -300,6 +300,7 @@ module ts { A_rest_element_must_be_last_in_an_array_destructuring_pattern: { code: 2462, category: DiagnosticCategory.Error, key: "A rest element must be last in an array destructuring pattern" }, A_binding_pattern_parameter_cannot_be_optional_in_an_implementation_signature: { code: 2463, category: DiagnosticCategory.Error, key: "A binding pattern parameter cannot be optional in an implementation signature." }, A_computed_property_name_must_be_of_type_string_number_or_any: { code: 2464, category: DiagnosticCategory.Error, key: "A computed property name must be of type 'string', 'number', or 'any'." }, + this_cannot_be_referenced_in_a_computed_property_name: { code: 2465, category: DiagnosticCategory.Error, key: "'this' cannot be referenced in a computed property name." }, Import_declaration_0_is_using_private_name_1: { code: 4000, category: DiagnosticCategory.Error, key: "Import declaration '{0}' is using private name '{1}'." }, Type_parameter_0_of_exported_class_has_or_is_using_private_name_1: { code: 4002, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of exported class has or is using private name '{1}'." }, Type_parameter_0_of_exported_interface_has_or_is_using_private_name_1: { code: 4004, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of exported interface has or is using private name '{1}'." }, diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 8268af730ec..940b66c4efc 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1294,6 +1294,10 @@ "category": "Error", "code": 2464 }, + "'this' cannot be referenced in a computed property name.": { + "category": "Error", + "code": 2465 + }, "Import declaration '{0}' is using private name '{1}'.": { "category": "Error", diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index f1fab4137e2..6f3460244b3 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -399,6 +399,14 @@ module ts { return undefined; } switch (node.kind) { + case SyntaxKind.ComputedPropertyName: + // If the grandparent node is an object literal (as opposed to a class), + // then the computed property is not a 'this' container. + // A computed property name in a class needs to be a this container + // so that we can error on it. + if (node.parent.parent.kind !== SyntaxKind.ClassDeclaration) { + continue; + } case SyntaxKind.ArrowFunction: if (!includeArrowFunctions) { continue; diff --git a/src/services/services.ts b/src/services/services.ts index 84e5e7fefa5..8c6ebecf469 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -4191,6 +4191,8 @@ module ts { case SyntaxKind.FunctionDeclaration: case SyntaxKind.FunctionExpression: break; + // Computed properties in classes are not handled here because references to this are illegal, + // so there is no point finding references to them. default: return undefined; } diff --git a/tests/baselines/reference/computedPropertyNames18.js b/tests/baselines/reference/computedPropertyNames18.js new file mode 100644 index 00000000000..af2d68b3095 --- /dev/null +++ b/tests/baselines/reference/computedPropertyNames18.js @@ -0,0 +1,13 @@ +//// [computedPropertyNames18.ts] +function foo() { + var obj = { + [this.bar]: 0 + } +} + +//// [computedPropertyNames18.js] +function foo() { + var obj = { + [this.bar]: 0 + }; +} diff --git a/tests/baselines/reference/computedPropertyNames18.types b/tests/baselines/reference/computedPropertyNames18.types new file mode 100644 index 00000000000..0976e5fc3ca --- /dev/null +++ b/tests/baselines/reference/computedPropertyNames18.types @@ -0,0 +1,14 @@ +=== tests/cases/conformance/es6/computedProperties/computedPropertyNames18.ts === +function foo() { +>foo : () => void + + var obj = { +>obj : {} +>{ [this.bar]: 0 } : {} + + [this.bar]: 0 +>this.bar : any +>this : any +>bar : any + } +} diff --git a/tests/baselines/reference/computedPropertyNames19.errors.txt b/tests/baselines/reference/computedPropertyNames19.errors.txt new file mode 100644 index 00000000000..2037008992f --- /dev/null +++ b/tests/baselines/reference/computedPropertyNames19.errors.txt @@ -0,0 +1,11 @@ +tests/cases/conformance/es6/computedProperties/computedPropertyNames19.ts(3,10): error TS2331: 'this' cannot be referenced in a module body. + + +==== tests/cases/conformance/es6/computedProperties/computedPropertyNames19.ts (1 errors) ==== + module M { + var obj = { + [this.bar]: 0 + ~~~~ +!!! error TS2331: 'this' cannot be referenced in a module body. + } + } \ No newline at end of file diff --git a/tests/baselines/reference/computedPropertyNames19.js b/tests/baselines/reference/computedPropertyNames19.js new file mode 100644 index 00000000000..3fd2f99eea6 --- /dev/null +++ b/tests/baselines/reference/computedPropertyNames19.js @@ -0,0 +1,14 @@ +//// [computedPropertyNames19.ts] +module M { + var obj = { + [this.bar]: 0 + } +} + +//// [computedPropertyNames19.js] +var M; +(function (M) { + var obj = { + [this.bar]: 0 + }; +})(M || (M = {})); diff --git a/tests/baselines/reference/computedPropertyNames20.js b/tests/baselines/reference/computedPropertyNames20.js new file mode 100644 index 00000000000..2a1edf06142 --- /dev/null +++ b/tests/baselines/reference/computedPropertyNames20.js @@ -0,0 +1,9 @@ +//// [computedPropertyNames20.ts] +var obj = { + [this.bar]: 0 +} + +//// [computedPropertyNames20.js] +var obj = { + [this.bar]: 0 +}; diff --git a/tests/baselines/reference/computedPropertyNames20.types b/tests/baselines/reference/computedPropertyNames20.types new file mode 100644 index 00000000000..abd1b203e87 --- /dev/null +++ b/tests/baselines/reference/computedPropertyNames20.types @@ -0,0 +1,10 @@ +=== tests/cases/conformance/es6/computedProperties/computedPropertyNames20.ts === +var obj = { +>obj : {} +>{ [this.bar]: 0} : {} + + [this.bar]: 0 +>this.bar : any +>this : any +>bar : any +} diff --git a/tests/baselines/reference/computedPropertyNames21.errors.txt b/tests/baselines/reference/computedPropertyNames21.errors.txt new file mode 100644 index 00000000000..a44c8d60ee8 --- /dev/null +++ b/tests/baselines/reference/computedPropertyNames21.errors.txt @@ -0,0 +1,12 @@ +tests/cases/conformance/es6/computedProperties/computedPropertyNames21.ts(5,6): error TS2465: 'this' cannot be referenced in a computed property name. + + +==== tests/cases/conformance/es6/computedProperties/computedPropertyNames21.ts (1 errors) ==== + class C { + bar() { + return 0; + } + [this.bar()]() { } + ~~~~ +!!! error TS2465: 'this' cannot be referenced in a computed property name. + } \ No newline at end of file diff --git a/tests/baselines/reference/computedPropertyNames21.js b/tests/baselines/reference/computedPropertyNames21.js new file mode 100644 index 00000000000..250d9142aa5 --- /dev/null +++ b/tests/baselines/reference/computedPropertyNames21.js @@ -0,0 +1,19 @@ +//// [computedPropertyNames21.ts] +class C { + bar() { + return 0; + } + [this.bar()]() { } +} + +//// [computedPropertyNames21.js] +var C = (function () { + function C() { + } + C.prototype.bar = function () { + return 0; + }; + C.prototype[this.bar()] = function () { + }; + return C; +})(); diff --git a/tests/baselines/reference/computedPropertyNames22.js b/tests/baselines/reference/computedPropertyNames22.js new file mode 100644 index 00000000000..b42946536d0 --- /dev/null +++ b/tests/baselines/reference/computedPropertyNames22.js @@ -0,0 +1,23 @@ +//// [computedPropertyNames22.ts] +class C { + bar() { + var obj = { + [this.bar()]() { } + }; + return 0; + } +} + +//// [computedPropertyNames22.js] +var C = (function () { + function C() { + } + C.prototype.bar = function () { + var obj = { + [this.bar()]() { + } + }; + return 0; + }; + return C; +})(); diff --git a/tests/baselines/reference/computedPropertyNames22.types b/tests/baselines/reference/computedPropertyNames22.types new file mode 100644 index 00000000000..52dff9a4f41 --- /dev/null +++ b/tests/baselines/reference/computedPropertyNames22.types @@ -0,0 +1,21 @@ +=== tests/cases/conformance/es6/computedProperties/computedPropertyNames22.ts === +class C { +>C : C + + bar() { +>bar : () => number + + var obj = { +>obj : {} +>{ [this.bar()]() { } } : {} + + [this.bar()]() { } +>this.bar() : any +>this.bar : any +>this : any +>bar : any + + }; + return 0; + } +} diff --git a/tests/baselines/reference/computedPropertyNames23.errors.txt b/tests/baselines/reference/computedPropertyNames23.errors.txt new file mode 100644 index 00000000000..0846ba4d6c6 --- /dev/null +++ b/tests/baselines/reference/computedPropertyNames23.errors.txt @@ -0,0 +1,14 @@ +tests/cases/conformance/es6/computedProperties/computedPropertyNames23.ts(6,12): error TS2465: 'this' cannot be referenced in a computed property name. + + +==== tests/cases/conformance/es6/computedProperties/computedPropertyNames23.ts (1 errors) ==== + class C { + bar() { + return 0; + } + [ + { [this.bar()]: 1 }[0] + ~~~~ +!!! error TS2465: 'this' cannot be referenced in a computed property name. + ]() { } + } \ No newline at end of file diff --git a/tests/baselines/reference/computedPropertyNames23.js b/tests/baselines/reference/computedPropertyNames23.js new file mode 100644 index 00000000000..9d71ef34c1e --- /dev/null +++ b/tests/baselines/reference/computedPropertyNames23.js @@ -0,0 +1,21 @@ +//// [computedPropertyNames23.ts] +class C { + bar() { + return 0; + } + [ + { [this.bar()]: 1 }[0] + ]() { } +} + +//// [computedPropertyNames23.js] +var C = (function () { + function C() { + } + C.prototype.bar = function () { + return 0; + }; + C.prototype[{ [this.bar()]: 1 }[0]] = function () { + }; + return C; +})(); diff --git a/tests/cases/conformance/es6/computedProperties/computedPropertyNames18.ts b/tests/cases/conformance/es6/computedProperties/computedPropertyNames18.ts new file mode 100644 index 00000000000..cd7a43f233f --- /dev/null +++ b/tests/cases/conformance/es6/computedProperties/computedPropertyNames18.ts @@ -0,0 +1,6 @@ +// @target: es6 +function foo() { + var obj = { + [this.bar]: 0 + } +} \ No newline at end of file diff --git a/tests/cases/conformance/es6/computedProperties/computedPropertyNames19.ts b/tests/cases/conformance/es6/computedProperties/computedPropertyNames19.ts new file mode 100644 index 00000000000..3dbf97d7f7a --- /dev/null +++ b/tests/cases/conformance/es6/computedProperties/computedPropertyNames19.ts @@ -0,0 +1,6 @@ +// @target: es6 +module M { + var obj = { + [this.bar]: 0 + } +} \ No newline at end of file diff --git a/tests/cases/conformance/es6/computedProperties/computedPropertyNames20.ts b/tests/cases/conformance/es6/computedProperties/computedPropertyNames20.ts new file mode 100644 index 00000000000..d31f63d2e87 --- /dev/null +++ b/tests/cases/conformance/es6/computedProperties/computedPropertyNames20.ts @@ -0,0 +1,4 @@ +// @target: es6 +var obj = { + [this.bar]: 0 +} \ No newline at end of file diff --git a/tests/cases/conformance/es6/computedProperties/computedPropertyNames21.ts b/tests/cases/conformance/es6/computedProperties/computedPropertyNames21.ts new file mode 100644 index 00000000000..654f1b29985 --- /dev/null +++ b/tests/cases/conformance/es6/computedProperties/computedPropertyNames21.ts @@ -0,0 +1,7 @@ +// @target: es6 +class C { + bar() { + return 0; + } + [this.bar()]() { } +} \ No newline at end of file diff --git a/tests/cases/conformance/es6/computedProperties/computedPropertyNames22.ts b/tests/cases/conformance/es6/computedProperties/computedPropertyNames22.ts new file mode 100644 index 00000000000..c999e0d642c --- /dev/null +++ b/tests/cases/conformance/es6/computedProperties/computedPropertyNames22.ts @@ -0,0 +1,9 @@ +// @target: es6 +class C { + bar() { + var obj = { + [this.bar()]() { } + }; + return 0; + } +} \ No newline at end of file diff --git a/tests/cases/conformance/es6/computedProperties/computedPropertyNames23.ts b/tests/cases/conformance/es6/computedProperties/computedPropertyNames23.ts new file mode 100644 index 00000000000..9c7c5bb6539 --- /dev/null +++ b/tests/cases/conformance/es6/computedProperties/computedPropertyNames23.ts @@ -0,0 +1,9 @@ +// @target: es6 +class C { + bar() { + return 0; + } + [ + { [this.bar()]: 1 }[0] + ]() { } +} \ No newline at end of file