From 56839604da355d1121f55a7fd40e026e5ce2a771 Mon Sep 17 00:00:00 2001 From: Yui T Date: Thu, 12 Mar 2015 08:40:09 -0700 Subject: [PATCH] Disallow refering to static property in computed property name --- src/compiler/checker.ts | 23 ++++++++++++++++ .../diagnosticInformationMap.generated.ts | 1 + src/compiler/diagnosticMessages.json | 4 +++ ...PropertyNamesWithStaticProperty.errors.txt | 22 ++++++++++++++++ ...computedPropertyNamesWithStaticProperty.js | 26 +++++++++++++++++++ ...computedPropertyNamesWithStaticProperty.ts | 11 ++++++++ 6 files changed, 87 insertions(+) create mode 100644 tests/baselines/reference/computedPropertyNamesWithStaticProperty.errors.txt create mode 100644 tests/baselines/reference/computedPropertyNamesWithStaticProperty.js create mode 100644 tests/cases/conformance/es6/computedProperties/computedPropertyNamesWithStaticProperty.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 135cecca730..28b3b74b271 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5696,6 +5696,29 @@ module ts { if (!links.resolvedType) { links.resolvedType = checkExpression(node.expression); + // Disallow using static property in computedPropertyName because classDeclaration is binded lexically in ES6 + // and its static property assignment will be emitted after classDeclaration. + // Therefore, using static property inside computedPropertyName will cause use-before-definition + // Example: + // * TypeScript + // class C { + // static p = 10; + // [C.p]() {} + // } + // * JavaScript + // class C { + // [C.p]() {} // Use before definition error + // } + // C.p = 10; + if (languageVersion >= ScriptTarget.ES6 && links.resolvedSymbol) { + var declarations = links.resolvedSymbol.declarations; + forEach(declarations, (declaration) => { + if (declaration.flags & NodeFlags.Static) { + error(node, Diagnostics.A_computed_property_name_cannot_reference_a_static_property); + } + }); + } + // This will allow types number, string, symbol or any. It will also allow enums, the unknown // type, and any union of these types (like string | number). if (!allConstituentTypesHaveKind(links.resolvedType, TypeFlags.Any | TypeFlags.NumberLike | TypeFlags.StringLike | TypeFlags.ESSymbol)) { diff --git a/src/compiler/diagnosticInformationMap.generated.ts b/src/compiler/diagnosticInformationMap.generated.ts index 24ed8ce4e99..a8b41e2159d 100644 --- a/src/compiler/diagnosticInformationMap.generated.ts +++ b/src/compiler/diagnosticInformationMap.generated.ts @@ -157,6 +157,7 @@ module ts { Catch_clause_variable_cannot_have_an_initializer: { code: 1197, category: DiagnosticCategory.Error, key: "Catch clause variable cannot have an initializer." }, An_extended_Unicode_escape_value_must_be_between_0x0_and_0x10FFFF_inclusive: { code: 1198, category: DiagnosticCategory.Error, key: "An extended Unicode escape value must be between 0x0 and 0x10FFFF inclusive." }, Unterminated_Unicode_escape_sequence: { code: 1199, category: DiagnosticCategory.Error, key: "Unterminated Unicode escape sequence." }, + A_computed_property_name_cannot_reference_a_static_property: { code: 1200, category: DiagnosticCategory.Error, key: "A computed property name cannot reference a static property" }, Duplicate_identifier_0: { code: 2300, category: DiagnosticCategory.Error, key: "Duplicate identifier '{0}'." }, Initializer_of_instance_member_variable_0_cannot_reference_identifier_1_declared_in_the_constructor: { code: 2301, category: DiagnosticCategory.Error, key: "Initializer of instance member variable '{0}' cannot reference identifier '{1}' declared in the constructor." }, Static_members_cannot_reference_class_type_parameters: { code: 2302, category: DiagnosticCategory.Error, key: "Static members cannot reference class type parameters." }, diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 40f7d55f9f0..489c929821d 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -619,6 +619,10 @@ "category": "Error", "code": 1199 }, + "A computed property name cannot reference a static property": { + "category": "Error", + "code": 1200 + }, "Duplicate identifier '{0}'.": { "category": "Error", "code": 2300 diff --git a/tests/baselines/reference/computedPropertyNamesWithStaticProperty.errors.txt b/tests/baselines/reference/computedPropertyNamesWithStaticProperty.errors.txt new file mode 100644 index 00000000000..f078365f600 --- /dev/null +++ b/tests/baselines/reference/computedPropertyNamesWithStaticProperty.errors.txt @@ -0,0 +1,22 @@ +tests/cases/conformance/es6/computedProperties/computedPropertyNamesWithStaticProperty.ts(3,9): error TS1200: A computed property name cannot reference a static property +tests/cases/conformance/es6/computedProperties/computedPropertyNamesWithStaticProperty.ts(6,9): error TS1200: A computed property name cannot reference a static property +tests/cases/conformance/es6/computedProperties/computedPropertyNamesWithStaticProperty.ts(9,5): error TS1200: A computed property name cannot reference a static property + + +==== tests/cases/conformance/es6/computedProperties/computedPropertyNamesWithStaticProperty.ts (3 errors) ==== + class C { + static staticProp = 10; + get [C.staticProp]() { + ~~~~~~~~~~~~~~ +!!! error TS1200: A computed property name cannot reference a static property + return "hello"; + } + set [C.staticProp](x: string) { + ~~~~~~~~~~~~~~ +!!! error TS1200: A computed property name cannot reference a static property + var y = x; + } + [C.staticProp]() { } + ~~~~~~~~~~~~~~ +!!! error TS1200: A computed property name cannot reference a static property + } \ No newline at end of file diff --git a/tests/baselines/reference/computedPropertyNamesWithStaticProperty.js b/tests/baselines/reference/computedPropertyNamesWithStaticProperty.js new file mode 100644 index 00000000000..f7506d7904d --- /dev/null +++ b/tests/baselines/reference/computedPropertyNamesWithStaticProperty.js @@ -0,0 +1,26 @@ +//// [computedPropertyNamesWithStaticProperty.ts] +class C { + static staticProp = 10; + get [C.staticProp]() { + return "hello"; + } + set [C.staticProp](x: string) { + var y = x; + } + [C.staticProp]() { } +} + +//// [computedPropertyNamesWithStaticProperty.js] +class C { + constructor() { + } + get [C.staticProp]() { + return "hello"; + } + set [C.staticProp](x) { + var y = x; + } + [C.staticProp]() { + } +} +C.staticProp = 10; diff --git a/tests/cases/conformance/es6/computedProperties/computedPropertyNamesWithStaticProperty.ts b/tests/cases/conformance/es6/computedProperties/computedPropertyNamesWithStaticProperty.ts new file mode 100644 index 00000000000..4cd9047581f --- /dev/null +++ b/tests/cases/conformance/es6/computedProperties/computedPropertyNamesWithStaticProperty.ts @@ -0,0 +1,11 @@ +// @target: es6 +class C { + static staticProp = 10; + get [C.staticProp]() { + return "hello"; + } + set [C.staticProp](x: string) { + var y = x; + } + [C.staticProp]() { } +} \ No newline at end of file