From b435e1ceaf676d4d4dcc9aa7cbf2ba79b5ff745f Mon Sep 17 00:00:00 2001 From: Andrew Branch Date: Mon, 26 Apr 2021 10:57:12 -0700 Subject: [PATCH 1/6] Allow `override` as parameter property --- src/compiler/checker.ts | 3 - .../overrideParameterProperty.errors.txt | 31 ++++++++ .../reference/overrideParameterProperty.js | 77 +++++++++++++++++++ .../overrideParameterProperty.symbols | 59 ++++++++++++++ .../reference/overrideParameterProperty.types | 62 +++++++++++++++ .../override/overrideParameterProperty.ts | 26 +++++++ 6 files changed, 255 insertions(+), 3 deletions(-) create mode 100644 tests/baselines/reference/overrideParameterProperty.errors.txt create mode 100644 tests/baselines/reference/overrideParameterProperty.js create mode 100644 tests/baselines/reference/overrideParameterProperty.symbols create mode 100644 tests/baselines/reference/overrideParameterProperty.types create mode 100644 tests/cases/conformance/override/overrideParameterProperty.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f4ee7960f1074..eeedbc27caafe 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -40621,9 +40621,6 @@ namespace ts { else if (flags & ModifierFlags.Async) { return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "override", "async"); } - if (node.kind === SyntaxKind.Parameter) { - return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_a_parameter, "override"); - } flags |= ModifierFlags.Override; lastOverride = modifier; break; diff --git a/tests/baselines/reference/overrideParameterProperty.errors.txt b/tests/baselines/reference/overrideParameterProperty.errors.txt new file mode 100644 index 0000000000000..98d953d4706b3 --- /dev/null +++ b/tests/baselines/reference/overrideParameterProperty.errors.txt @@ -0,0 +1,31 @@ +tests/cases/conformance/override/overrideParameterProperty.ts(20,24): error TS1029: 'public' modifier must precede 'override' modifier. + + +==== tests/cases/conformance/override/overrideParameterProperty.ts (1 errors) ==== + class Base { + p1!: string; + } + + class C1 extends Base { + constructor(public override p1: "hello") { + super(); + this.p1; + } + } + + class C2 extends Base { + constructor(override p1: "hello") { + super(); + this.p1; + } + } + + class C3 extends Base { + constructor(override public p1: "hello") { + ~~~~~~ +!!! error TS1029: 'public' modifier must precede 'override' modifier. + super(); + this.p1; + } + } + \ No newline at end of file diff --git a/tests/baselines/reference/overrideParameterProperty.js b/tests/baselines/reference/overrideParameterProperty.js new file mode 100644 index 0000000000000..dc5e735c93441 --- /dev/null +++ b/tests/baselines/reference/overrideParameterProperty.js @@ -0,0 +1,77 @@ +//// [overrideParameterProperty.ts] +class Base { + p1!: string; +} + +class C1 extends Base { + constructor(public override p1: "hello") { + super(); + this.p1; + } +} + +class C2 extends Base { + constructor(override p1: "hello") { + super(); + this.p1; + } +} + +class C3 extends Base { + constructor(override public p1: "hello") { + super(); + this.p1; + } +} + + +//// [overrideParameterProperty.js] +var __extends = (this && this.__extends) || (function () { + var extendStatics = function (d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + return function (d, b) { + if (typeof b !== "function" && b !== null) + throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +var Base = /** @class */ (function () { + function Base() { + } + return Base; +}()); +var C1 = /** @class */ (function (_super) { + __extends(C1, _super); + function C1(p1) { + var _this = _super.call(this) || this; + _this.p1 = p1; + _this.p1; + return _this; + } + return C1; +}(Base)); +var C2 = /** @class */ (function (_super) { + __extends(C2, _super); + function C2(p1) { + var _this = _super.call(this) || this; + _this.p1; + return _this; + } + return C2; +}(Base)); +var C3 = /** @class */ (function (_super) { + __extends(C3, _super); + function C3(p1) { + var _this = _super.call(this) || this; + _this.p1 = p1; + _this.p1; + return _this; + } + return C3; +}(Base)); diff --git a/tests/baselines/reference/overrideParameterProperty.symbols b/tests/baselines/reference/overrideParameterProperty.symbols new file mode 100644 index 0000000000000..f504c911efc25 --- /dev/null +++ b/tests/baselines/reference/overrideParameterProperty.symbols @@ -0,0 +1,59 @@ +=== tests/cases/conformance/override/overrideParameterProperty.ts === +class Base { +>Base : Symbol(Base, Decl(overrideParameterProperty.ts, 0, 0)) + + p1!: string; +>p1 : Symbol(Base.p1, Decl(overrideParameterProperty.ts, 0, 12)) +} + +class C1 extends Base { +>C1 : Symbol(C1, Decl(overrideParameterProperty.ts, 2, 1)) +>Base : Symbol(Base, Decl(overrideParameterProperty.ts, 0, 0)) + + constructor(public override p1: "hello") { +>p1 : Symbol(C1.p1, Decl(overrideParameterProperty.ts, 5, 14)) + + super(); +>super : Symbol(Base, Decl(overrideParameterProperty.ts, 0, 0)) + + this.p1; +>this.p1 : Symbol(C1.p1, Decl(overrideParameterProperty.ts, 5, 14)) +>this : Symbol(C1, Decl(overrideParameterProperty.ts, 2, 1)) +>p1 : Symbol(C1.p1, Decl(overrideParameterProperty.ts, 5, 14)) + } +} + +class C2 extends Base { +>C2 : Symbol(C2, Decl(overrideParameterProperty.ts, 9, 1)) +>Base : Symbol(Base, Decl(overrideParameterProperty.ts, 0, 0)) + + constructor(override p1: "hello") { +>p1 : Symbol(p1, Decl(overrideParameterProperty.ts, 12, 14)) + + super(); +>super : Symbol(Base, Decl(overrideParameterProperty.ts, 0, 0)) + + this.p1; +>this.p1 : Symbol(Base.p1, Decl(overrideParameterProperty.ts, 0, 12)) +>this : Symbol(C2, Decl(overrideParameterProperty.ts, 9, 1)) +>p1 : Symbol(Base.p1, Decl(overrideParameterProperty.ts, 0, 12)) + } +} + +class C3 extends Base { +>C3 : Symbol(C3, Decl(overrideParameterProperty.ts, 16, 1)) +>Base : Symbol(Base, Decl(overrideParameterProperty.ts, 0, 0)) + + constructor(override public p1: "hello") { +>p1 : Symbol(C3.p1, Decl(overrideParameterProperty.ts, 19, 14)) + + super(); +>super : Symbol(Base, Decl(overrideParameterProperty.ts, 0, 0)) + + this.p1; +>this.p1 : Symbol(C3.p1, Decl(overrideParameterProperty.ts, 19, 14)) +>this : Symbol(C3, Decl(overrideParameterProperty.ts, 16, 1)) +>p1 : Symbol(C3.p1, Decl(overrideParameterProperty.ts, 19, 14)) + } +} + diff --git a/tests/baselines/reference/overrideParameterProperty.types b/tests/baselines/reference/overrideParameterProperty.types new file mode 100644 index 0000000000000..bfbae816e6bb2 --- /dev/null +++ b/tests/baselines/reference/overrideParameterProperty.types @@ -0,0 +1,62 @@ +=== tests/cases/conformance/override/overrideParameterProperty.ts === +class Base { +>Base : Base + + p1!: string; +>p1 : string +} + +class C1 extends Base { +>C1 : C1 +>Base : Base + + constructor(public override p1: "hello") { +>p1 : "hello" + + super(); +>super() : void +>super : typeof Base + + this.p1; +>this.p1 : "hello" +>this : this +>p1 : "hello" + } +} + +class C2 extends Base { +>C2 : C2 +>Base : Base + + constructor(override p1: "hello") { +>p1 : "hello" + + super(); +>super() : void +>super : typeof Base + + this.p1; +>this.p1 : string +>this : this +>p1 : string + } +} + +class C3 extends Base { +>C3 : C3 +>Base : Base + + constructor(override public p1: "hello") { +>p1 : "hello" + + super(); +>super() : void +>super : typeof Base + + this.p1; +>this.p1 : "hello" +>this : this +>p1 : "hello" + } +} + diff --git a/tests/cases/conformance/override/overrideParameterProperty.ts b/tests/cases/conformance/override/overrideParameterProperty.ts new file mode 100644 index 0000000000000..4f53a69cb5750 --- /dev/null +++ b/tests/cases/conformance/override/overrideParameterProperty.ts @@ -0,0 +1,26 @@ +// @noImplicitOverride: true + +class Base { + p1!: string; +} + +class C1 extends Base { + constructor(public override p1: "hello") { + super(); + this.p1; + } +} + +class C2 extends Base { + constructor(override p1: "hello") { + super(); + this.p1; + } +} + +class C3 extends Base { + constructor(override public p1: "hello") { + super(); + this.p1; + } +} From 97ee23a1d32a578737f31a6b538333d6cd19e112 Mon Sep 17 00:00:00 2001 From: Andrew Branch Date: Mon, 26 Apr 2021 11:46:12 -0700 Subject: [PATCH 2/6] Update other baseline --- tests/baselines/reference/override11.errors.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/baselines/reference/override11.errors.txt b/tests/baselines/reference/override11.errors.txt index 0af9f32dd0a65..2a0d38fa187b5 100644 --- a/tests/baselines/reference/override11.errors.txt +++ b/tests/baselines/reference/override11.errors.txt @@ -1,4 +1,4 @@ -tests/cases/conformance/override/override11.ts(6,18): error TS1090: 'override' modifier cannot appear on a parameter. +tests/cases/conformance/override/override11.ts(6,27): error TS1029: 'public' modifier must precede 'override' modifier. ==== tests/cases/conformance/override/override11.ts (1 errors) ==== @@ -8,8 +8,8 @@ tests/cases/conformance/override/override11.ts(6,18): error TS1090: 'override' m class Sub extends Base { constructor (override public foo: number) { - ~~~~~~~~ -!!! error TS1090: 'override' modifier cannot appear on a parameter. + ~~~~~~ +!!! error TS1029: 'public' modifier must precede 'override' modifier. super(); } } From 38700c90e5ed452c7a9a49f255bf7d13197c3a87 Mon Sep 17 00:00:00 2001 From: Andrew Branch Date: Mon, 26 Apr 2021 15:51:33 -0700 Subject: [PATCH 3/6] Add test for override on normal parameter --- src/compiler/checker.ts | 3 ++- src/compiler/types.ts | 2 +- tests/cases/conformance/override/overrideParameterProperty.ts | 3 +++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index eeedbc27caafe..e3cbaa157a1dd 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -40609,6 +40609,7 @@ namespace ts { } break; case SyntaxKind.OverrideKeyword: + // If node.kind === SyntaxKind.Parameter, checkParameter report an error if it's not a parameter property. if (flags & ModifierFlags.Override) { return grammarErrorOnNode(modifier, Diagnostics._0_modifier_already_seen, "override"); } @@ -40693,7 +40694,7 @@ namespace ts { return grammarErrorOnNode(modifier, Diagnostics._0_modifier_already_seen, "readonly"); } else if (node.kind !== SyntaxKind.PropertyDeclaration && node.kind !== SyntaxKind.PropertySignature && node.kind !== SyntaxKind.IndexSignature && node.kind !== SyntaxKind.Parameter) { - // If node.kind === SyntaxKind.Parameter, checkParameter report an error if it's not a parameter property. + // If node.kind === SyntaxKind.Parameter, checkParameter reports an error if it's not a parameter property. return grammarErrorOnNode(modifier, Diagnostics.readonly_modifier_can_only_appear_on_a_property_declaration_or_index_signature); } flags |= ModifierFlags.Readonly; diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 780050afed5b5..e488333bbad00 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -806,7 +806,7 @@ namespace ts { AccessibilityModifier = Public | Private | Protected, // Accessibility modifiers and 'readonly' can be attached to a parameter in a constructor to make it a property. - ParameterPropertyModifier = AccessibilityModifier | Readonly, + ParameterPropertyModifier = AccessibilityModifier | Readonly | Override, NonPublicAccessibilityModifier = Private | Protected, TypeScriptModifier = Ambient | Public | Private | Protected | Readonly | Abstract | Const | Override, diff --git a/tests/cases/conformance/override/overrideParameterProperty.ts b/tests/cases/conformance/override/overrideParameterProperty.ts index 4f53a69cb5750..20e5708b97fa8 100644 --- a/tests/cases/conformance/override/overrideParameterProperty.ts +++ b/tests/cases/conformance/override/overrideParameterProperty.ts @@ -2,6 +2,7 @@ class Base { p1!: string; + [key: string]: string; } class C1 extends Base { @@ -23,4 +24,6 @@ class C3 extends Base { super(); this.p1; } + + m(override p1: "hello") {} } From 0b4e464e6f6e87e39abb5c45625ccdf9c591d479 Mon Sep 17 00:00:00 2001 From: Andrew Branch Date: Mon, 26 Apr 2021 15:52:23 -0700 Subject: [PATCH 4/6] Copy typo fix --- src/compiler/checker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index e3cbaa157a1dd..7eae4e8bb062a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -40609,7 +40609,7 @@ namespace ts { } break; case SyntaxKind.OverrideKeyword: - // If node.kind === SyntaxKind.Parameter, checkParameter report an error if it's not a parameter property. + // If node.kind === SyntaxKind.Parameter, checkParameter reports an error if it's not a parameter property. if (flags & ModifierFlags.Override) { return grammarErrorOnNode(modifier, Diagnostics._0_modifier_already_seen, "override"); } From c5ee12566aadaf244675c0dcf4c4c56727e1a152 Mon Sep 17 00:00:00 2001 From: Andrew Branch Date: Mon, 26 Apr 2021 15:55:36 -0700 Subject: [PATCH 5/6] Update baselines --- .../reference/overrideParameterProperty.errors.txt | 7 ++++++- tests/baselines/reference/overrideParameterProperty.js | 4 ++++ .../reference/overrideParameterProperty.symbols | 10 +++++++--- .../reference/overrideParameterProperty.types | 8 ++++++-- .../conformance/override/overrideParameterProperty.ts | 1 - 5 files changed, 23 insertions(+), 7 deletions(-) diff --git a/tests/baselines/reference/overrideParameterProperty.errors.txt b/tests/baselines/reference/overrideParameterProperty.errors.txt index 98d953d4706b3..10929ce6e3cae 100644 --- a/tests/baselines/reference/overrideParameterProperty.errors.txt +++ b/tests/baselines/reference/overrideParameterProperty.errors.txt @@ -1,7 +1,8 @@ tests/cases/conformance/override/overrideParameterProperty.ts(20,24): error TS1029: 'public' modifier must precede 'override' modifier. +tests/cases/conformance/override/overrideParameterProperty.ts(25,5): error TS2369: A parameter property is only allowed in a constructor implementation. -==== tests/cases/conformance/override/overrideParameterProperty.ts (1 errors) ==== +==== tests/cases/conformance/override/overrideParameterProperty.ts (2 errors) ==== class Base { p1!: string; } @@ -27,5 +28,9 @@ tests/cases/conformance/override/overrideParameterProperty.ts(20,24): error TS10 super(); this.p1; } + + m(override p1: "hello") {} + ~~~~~~~~~~~~~~~~~~~~ +!!! error TS2369: A parameter property is only allowed in a constructor implementation. } \ No newline at end of file diff --git a/tests/baselines/reference/overrideParameterProperty.js b/tests/baselines/reference/overrideParameterProperty.js index dc5e735c93441..ad063d8e5ef8f 100644 --- a/tests/baselines/reference/overrideParameterProperty.js +++ b/tests/baselines/reference/overrideParameterProperty.js @@ -22,6 +22,8 @@ class C3 extends Base { super(); this.p1; } + + m(override p1: "hello") {} } @@ -60,6 +62,7 @@ var C2 = /** @class */ (function (_super) { __extends(C2, _super); function C2(p1) { var _this = _super.call(this) || this; + _this.p1 = p1; _this.p1; return _this; } @@ -73,5 +76,6 @@ var C3 = /** @class */ (function (_super) { _this.p1; return _this; } + C3.prototype.m = function (p1) { }; return C3; }(Base)); diff --git a/tests/baselines/reference/overrideParameterProperty.symbols b/tests/baselines/reference/overrideParameterProperty.symbols index f504c911efc25..88eefef58290e 100644 --- a/tests/baselines/reference/overrideParameterProperty.symbols +++ b/tests/baselines/reference/overrideParameterProperty.symbols @@ -28,15 +28,15 @@ class C2 extends Base { >Base : Symbol(Base, Decl(overrideParameterProperty.ts, 0, 0)) constructor(override p1: "hello") { ->p1 : Symbol(p1, Decl(overrideParameterProperty.ts, 12, 14)) +>p1 : Symbol(C2.p1, Decl(overrideParameterProperty.ts, 12, 14)) super(); >super : Symbol(Base, Decl(overrideParameterProperty.ts, 0, 0)) this.p1; ->this.p1 : Symbol(Base.p1, Decl(overrideParameterProperty.ts, 0, 12)) +>this.p1 : Symbol(C2.p1, Decl(overrideParameterProperty.ts, 12, 14)) >this : Symbol(C2, Decl(overrideParameterProperty.ts, 9, 1)) ->p1 : Symbol(Base.p1, Decl(overrideParameterProperty.ts, 0, 12)) +>p1 : Symbol(C2.p1, Decl(overrideParameterProperty.ts, 12, 14)) } } @@ -55,5 +55,9 @@ class C3 extends Base { >this : Symbol(C3, Decl(overrideParameterProperty.ts, 16, 1)) >p1 : Symbol(C3.p1, Decl(overrideParameterProperty.ts, 19, 14)) } + + m(override p1: "hello") {} +>m : Symbol(C3.m, Decl(overrideParameterProperty.ts, 22, 3)) +>p1 : Symbol(p1, Decl(overrideParameterProperty.ts, 24, 4)) } diff --git a/tests/baselines/reference/overrideParameterProperty.types b/tests/baselines/reference/overrideParameterProperty.types index bfbae816e6bb2..33aca1cfbca47 100644 --- a/tests/baselines/reference/overrideParameterProperty.types +++ b/tests/baselines/reference/overrideParameterProperty.types @@ -36,9 +36,9 @@ class C2 extends Base { >super : typeof Base this.p1; ->this.p1 : string +>this.p1 : "hello" >this : this ->p1 : string +>p1 : "hello" } } @@ -58,5 +58,9 @@ class C3 extends Base { >this : this >p1 : "hello" } + + m(override p1: "hello") {} +>m : (p1: "hello") => void +>p1 : "hello" } diff --git a/tests/cases/conformance/override/overrideParameterProperty.ts b/tests/cases/conformance/override/overrideParameterProperty.ts index 20e5708b97fa8..67e25674010a2 100644 --- a/tests/cases/conformance/override/overrideParameterProperty.ts +++ b/tests/cases/conformance/override/overrideParameterProperty.ts @@ -2,7 +2,6 @@ class Base { p1!: string; - [key: string]: string; } class C1 extends Base { From e058849114b48f7bd236b527c7b534cd7c751a1c Mon Sep 17 00:00:00 2001 From: Andrew Branch Date: Mon, 26 Apr 2021 16:14:23 -0700 Subject: [PATCH 6/6] Update API baseline --- src/harness/fourslashInterfaceImpl.ts | 2 +- tests/baselines/reference/api/tsserverlibrary.d.ts | 2 +- tests/baselines/reference/api/typescript.d.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/harness/fourslashInterfaceImpl.ts b/src/harness/fourslashInterfaceImpl.ts index 55462526ae6f6..736581022dcbf 100644 --- a/src/harness/fourslashInterfaceImpl.ts +++ b/src/harness/fourslashInterfaceImpl.ts @@ -1175,7 +1175,7 @@ namespace FourSlashInterface { export const classElementInJsKeywords = getInJsKeywords(classElementKeywords); export const constructorParameterKeywords: readonly ExpectedCompletionEntryObject[] = - ["private", "protected", "public", "readonly"].map((name): ExpectedCompletionEntryObject => ({ + ["private", "protected", "public", "readonly", "override"].map((name): ExpectedCompletionEntryObject => ({ name, kind: "keyword", sortText: SortText.GlobalsOrKeywords diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index ea64a21ef4294..e94b1da823f34 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -540,7 +540,7 @@ declare namespace ts { Override = 16384, HasComputedFlags = 536870912, AccessibilityModifier = 28, - ParameterPropertyModifier = 92, + ParameterPropertyModifier = 16476, NonPublicAccessibilityModifier = 24, TypeScriptModifier = 18654, ExportDefault = 513, diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 859a76db3394b..7b8a24ba088b4 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -540,7 +540,7 @@ declare namespace ts { Override = 16384, HasComputedFlags = 536870912, AccessibilityModifier = 28, - ParameterPropertyModifier = 92, + ParameterPropertyModifier = 16476, NonPublicAccessibilityModifier = 24, TypeScriptModifier = 18654, ExportDefault = 513,