From f76e01fbd98f3c847d5ee84e949c88b45893ee5c Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Thu, 12 Sep 2019 15:04:36 -0700 Subject: [PATCH 1/6] Disallow property/accessor overrides Unless the base property or accessor is abstract --- src/compiler/checker.ts | 23 ++++-- src/compiler/diagnosticMessages.json | 9 +++ src/compiler/utilities.ts | 1 - .../accessorsOverrideProperty.errors.txt | 24 ++++++ .../reference/accessorsOverrideProperty.js | 39 ++++++++++ .../accessorsOverrideProperty.symbols | 42 +++++++++++ .../reference/accessorsOverrideProperty.types | 47 ++++++++++++ .../accessorsOverrideProperty2.errors.txt | 18 +++++ .../reference/accessorsOverrideProperty2.js | 26 +++++++ .../accessorsOverrideProperty2.symbols | 36 +++++++++ .../accessorsOverrideProperty2.types | 42 +++++++++++ .../accessorsOverrideProperty3.errors.txt | 15 ++++ .../reference/accessorsOverrideProperty3.js | 20 +++++ .../accessorsOverrideProperty3.symbols | 29 ++++++++ .../accessorsOverrideProperty3.types | 31 ++++++++ .../accessorsOverrideProperty4.errors.txt | 15 ++++ .../reference/accessorsOverrideProperty4.js | 20 +++++ .../accessorsOverrideProperty4.symbols | 29 ++++++++ .../accessorsOverrideProperty4.types | 31 ++++++++ ...emberAccessorOverridingProperty.errors.txt | 5 +- ...emberPropertyOverridingAccessor.errors.txt | 5 +- .../propertyOverridesAccessors.errors.txt | 24 ++++++ .../reference/propertyOverridesAccessors.js | 40 ++++++++++ .../propertyOverridesAccessors.symbols | 42 +++++++++++ .../propertyOverridesAccessors.types | 47 ++++++++++++ .../propertyOverridesAccessors2.errors.txt | 18 +++++ .../reference/propertyOverridesAccessors2.js | 27 +++++++ .../propertyOverridesAccessors2.symbols | 36 +++++++++ .../propertyOverridesAccessors2.types | 42 +++++++++++ .../propertyOverridesAccessors3.errors.txt | 30 ++++++++ .../reference/propertyOverridesAccessors3.js | 50 +++++++++++++ .../propertyOverridesAccessors3.symbols | 65 +++++++++++++++++ .../propertyOverridesAccessors3.types | 73 +++++++++++++++++++ .../propertyOverridesAccessors4.errors.txt | 14 ++++ .../reference/propertyOverridesAccessors4.js | 33 +++++++++ .../propertyOverridesAccessors4.symbols | 19 +++++ .../propertyOverridesAccessors4.types | 20 +++++ .../accessorsOverrideProperty.ts | 15 ++++ .../accessorsOverrideProperty2.ts | 12 +++ .../accessorsOverrideProperty3.ts | 9 +++ .../accessorsOverrideProperty4.ts | 9 +++ .../propertyOverridesAccessors.ts | 15 ++++ .../propertyOverridesAccessors2.ts | 12 +++ .../propertyOverridesAccessors3.ts | 24 ++++++ .../propertyOverridesAccessors4.ts | 7 ++ 45 files changed, 1182 insertions(+), 8 deletions(-) create mode 100644 tests/baselines/reference/accessorsOverrideProperty.errors.txt create mode 100644 tests/baselines/reference/accessorsOverrideProperty.js create mode 100644 tests/baselines/reference/accessorsOverrideProperty.symbols create mode 100644 tests/baselines/reference/accessorsOverrideProperty.types create mode 100644 tests/baselines/reference/accessorsOverrideProperty2.errors.txt create mode 100644 tests/baselines/reference/accessorsOverrideProperty2.js create mode 100644 tests/baselines/reference/accessorsOverrideProperty2.symbols create mode 100644 tests/baselines/reference/accessorsOverrideProperty2.types create mode 100644 tests/baselines/reference/accessorsOverrideProperty3.errors.txt create mode 100644 tests/baselines/reference/accessorsOverrideProperty3.js create mode 100644 tests/baselines/reference/accessorsOverrideProperty3.symbols create mode 100644 tests/baselines/reference/accessorsOverrideProperty3.types create mode 100644 tests/baselines/reference/accessorsOverrideProperty4.errors.txt create mode 100644 tests/baselines/reference/accessorsOverrideProperty4.js create mode 100644 tests/baselines/reference/accessorsOverrideProperty4.symbols create mode 100644 tests/baselines/reference/accessorsOverrideProperty4.types create mode 100644 tests/baselines/reference/propertyOverridesAccessors.errors.txt create mode 100644 tests/baselines/reference/propertyOverridesAccessors.js create mode 100644 tests/baselines/reference/propertyOverridesAccessors.symbols create mode 100644 tests/baselines/reference/propertyOverridesAccessors.types create mode 100644 tests/baselines/reference/propertyOverridesAccessors2.errors.txt create mode 100644 tests/baselines/reference/propertyOverridesAccessors2.js create mode 100644 tests/baselines/reference/propertyOverridesAccessors2.symbols create mode 100644 tests/baselines/reference/propertyOverridesAccessors2.types create mode 100644 tests/baselines/reference/propertyOverridesAccessors3.errors.txt create mode 100644 tests/baselines/reference/propertyOverridesAccessors3.js create mode 100644 tests/baselines/reference/propertyOverridesAccessors3.symbols create mode 100644 tests/baselines/reference/propertyOverridesAccessors3.types create mode 100644 tests/baselines/reference/propertyOverridesAccessors4.errors.txt create mode 100644 tests/baselines/reference/propertyOverridesAccessors4.js create mode 100644 tests/baselines/reference/propertyOverridesAccessors4.symbols create mode 100644 tests/baselines/reference/propertyOverridesAccessors4.types create mode 100644 tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty.ts create mode 100644 tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty2.ts create mode 100644 tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty3.ts create mode 100644 tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty4.ts create mode 100644 tests/cases/conformance/classes/propertyMemberDeclarations/propertyOverridesAccessors.ts create mode 100644 tests/cases/conformance/classes/propertyMemberDeclarations/propertyOverridesAccessors2.ts create mode 100644 tests/cases/conformance/classes/propertyMemberDeclarations/propertyOverridesAccessors3.ts create mode 100644 tests/cases/conformance/classes/propertyMemberDeclarations/propertyOverridesAccessors4.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f8c8817888591..b6d7723c6cab1 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -29513,14 +29513,27 @@ namespace ts { // either base or derived property is private - not override, skip it continue; } - - if (isPrototypeProperty(base) || base.flags & SymbolFlags.PropertyOrAccessor && derived.flags & SymbolFlags.PropertyOrAccessor) { - // method is overridden with method or property/accessor is overridden with property/accessor - correct case + if (isPrototypeProperty(base)) { + // method is overridden with method - correct case continue; } - let errorMessage: DiagnosticMessage; - if (isPrototypeProperty(base)) { + const basePropertyFlags = base.flags & SymbolFlags.PropertyOrAccessor; + const derivedPropertyFlags = derived.flags & SymbolFlags.PropertyOrAccessor; + if (basePropertyFlags && derivedPropertyFlags) { + // property/accessor is overridden with property/accessor + if (!(baseDeclarationFlags & ModifierFlags.Abstract) && basePropertyFlags !== SymbolFlags.Property && derivedPropertyFlags === SymbolFlags.Property) { + errorMessage = Diagnostics.Class_0_defines_instance_member_accessor_1_but_extended_class_2_defines_it_as_instance_member_property; + } + else if (!(baseDeclarationFlags & ModifierFlags.Abstract) && basePropertyFlags === SymbolFlags.Property && derivedPropertyFlags !== SymbolFlags.Property) { + errorMessage = Diagnostics.Class_0_defines_instance_member_property_1_but_extended_class_2_defines_it_as_instance_member_accessor; + } + else { + // correct case + continue; + } + } + else if (isPrototypeProperty(base)) { if (derived.flags & SymbolFlags.Accessor) { errorMessage = Diagnostics.Class_0_defines_instance_member_function_1_but_extended_class_2_defines_it_as_instance_member_accessor; } diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 86686cb9f6c1b..24e1df77649c2 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -2204,6 +2204,15 @@ "category": "Error", "code": 2609 }, + "Class '{0}' defines instance member accessor '{1}', but extended class '{2}' defines it as instance member property.": { + "category": "Error", + "code": 2610 + }, + "Class '{0}' defines instance member property '{1}', but extended class '{2}' defines it as instance member accessor.": { + "category": "Error", + "code": 2611 + }, + "Cannot augment module '{0}' with value exports because it resolves to a non-module entity.": { "category": "Error", "code": 2649 diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index b338d3ba657cd..ed7bdff0fc97e 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -3972,7 +3972,6 @@ namespace ts { } export function getModifierFlagsNoCache(node: Node): ModifierFlags { - let flags = ModifierFlags.None; if (node.modifiers) { for (const modifier of node.modifiers) { diff --git a/tests/baselines/reference/accessorsOverrideProperty.errors.txt b/tests/baselines/reference/accessorsOverrideProperty.errors.txt new file mode 100644 index 0000000000000..cda030610b543 --- /dev/null +++ b/tests/baselines/reference/accessorsOverrideProperty.errors.txt @@ -0,0 +1,24 @@ +tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty.ts(5,9): error TS2611: Class 'A' defines instance member property 'p', but extended class 'B' defines it as instance member accessor. +tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty.ts(12,9): error TS2611: Class 'C' defines instance member property 'p', but extended class 'D' defines it as instance member accessor. + + +==== tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty.ts (2 errors) ==== + class A { + p = 'yep' + } + class B extends A { + get p() { return 'oh no' } // error + ~ +!!! error TS2611: Class 'A' defines instance member property 'p', but extended class 'B' defines it as instance member accessor. + } + class C { + p = 101 + } + class D extends C { + _secret = 11 + get p() { return this._secret } // error + ~ +!!! error TS2611: Class 'C' defines instance member property 'p', but extended class 'D' defines it as instance member accessor. + set p(value) { this._secret = value } // error + } + \ No newline at end of file diff --git a/tests/baselines/reference/accessorsOverrideProperty.js b/tests/baselines/reference/accessorsOverrideProperty.js new file mode 100644 index 0000000000000..3a19b0f7fff33 --- /dev/null +++ b/tests/baselines/reference/accessorsOverrideProperty.js @@ -0,0 +1,39 @@ +//// [accessorsOverrideProperty.ts] +class A { + p = 'yep' +} +class B extends A { + get p() { return 'oh no' } // error +} +class C { + p = 101 +} +class D extends C { + _secret = 11 + get p() { return this._secret } // error + set p(value) { this._secret = value } // error +} + + +//// [accessorsOverrideProperty.js] +class A { + constructor() { + this.p = 'yep'; + } +} +class B extends A { + get p() { return 'oh no'; } // error +} +class C { + constructor() { + this.p = 101; + } +} +class D extends C { + constructor() { + super(...arguments); + this._secret = 11; + } + get p() { return this._secret; } // error + set p(value) { this._secret = value; } // error +} diff --git a/tests/baselines/reference/accessorsOverrideProperty.symbols b/tests/baselines/reference/accessorsOverrideProperty.symbols new file mode 100644 index 0000000000000..702417679a316 --- /dev/null +++ b/tests/baselines/reference/accessorsOverrideProperty.symbols @@ -0,0 +1,42 @@ +=== tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty.ts === +class A { +>A : Symbol(A, Decl(accessorsOverrideProperty.ts, 0, 0)) + + p = 'yep' +>p : Symbol(A.p, Decl(accessorsOverrideProperty.ts, 0, 9)) +} +class B extends A { +>B : Symbol(B, Decl(accessorsOverrideProperty.ts, 2, 1)) +>A : Symbol(A, Decl(accessorsOverrideProperty.ts, 0, 0)) + + get p() { return 'oh no' } // error +>p : Symbol(B.p, Decl(accessorsOverrideProperty.ts, 3, 19)) +} +class C { +>C : Symbol(C, Decl(accessorsOverrideProperty.ts, 5, 1)) + + p = 101 +>p : Symbol(C.p, Decl(accessorsOverrideProperty.ts, 6, 9)) +} +class D extends C { +>D : Symbol(D, Decl(accessorsOverrideProperty.ts, 8, 1)) +>C : Symbol(C, Decl(accessorsOverrideProperty.ts, 5, 1)) + + _secret = 11 +>_secret : Symbol(D._secret, Decl(accessorsOverrideProperty.ts, 9, 19)) + + get p() { return this._secret } // error +>p : Symbol(D.p, Decl(accessorsOverrideProperty.ts, 10, 17), Decl(accessorsOverrideProperty.ts, 11, 35)) +>this._secret : Symbol(D._secret, Decl(accessorsOverrideProperty.ts, 9, 19)) +>this : Symbol(D, Decl(accessorsOverrideProperty.ts, 8, 1)) +>_secret : Symbol(D._secret, Decl(accessorsOverrideProperty.ts, 9, 19)) + + set p(value) { this._secret = value } // error +>p : Symbol(D.p, Decl(accessorsOverrideProperty.ts, 10, 17), Decl(accessorsOverrideProperty.ts, 11, 35)) +>value : Symbol(value, Decl(accessorsOverrideProperty.ts, 12, 10)) +>this._secret : Symbol(D._secret, Decl(accessorsOverrideProperty.ts, 9, 19)) +>this : Symbol(D, Decl(accessorsOverrideProperty.ts, 8, 1)) +>_secret : Symbol(D._secret, Decl(accessorsOverrideProperty.ts, 9, 19)) +>value : Symbol(value, Decl(accessorsOverrideProperty.ts, 12, 10)) +} + diff --git a/tests/baselines/reference/accessorsOverrideProperty.types b/tests/baselines/reference/accessorsOverrideProperty.types new file mode 100644 index 0000000000000..4e3021e70243f --- /dev/null +++ b/tests/baselines/reference/accessorsOverrideProperty.types @@ -0,0 +1,47 @@ +=== tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty.ts === +class A { +>A : A + + p = 'yep' +>p : string +>'yep' : "yep" +} +class B extends A { +>B : B +>A : A + + get p() { return 'oh no' } // error +>p : string +>'oh no' : "oh no" +} +class C { +>C : C + + p = 101 +>p : number +>101 : 101 +} +class D extends C { +>D : D +>C : C + + _secret = 11 +>_secret : number +>11 : 11 + + get p() { return this._secret } // error +>p : number +>this._secret : number +>this : this +>_secret : number + + set p(value) { this._secret = value } // error +>p : number +>value : number +>this._secret = value : number +>this._secret : number +>this : this +>_secret : number +>value : number +} + diff --git a/tests/baselines/reference/accessorsOverrideProperty2.errors.txt b/tests/baselines/reference/accessorsOverrideProperty2.errors.txt new file mode 100644 index 0000000000000..ee26b16f7c906 --- /dev/null +++ b/tests/baselines/reference/accessorsOverrideProperty2.errors.txt @@ -0,0 +1,18 @@ +tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty2.ts(6,7): error TS2611: Class 'Base' defines instance member property 'x', but extended class 'Derived' defines it as instance member accessor. + + +==== tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty2.ts (1 errors) ==== + class Base { + x = 1; + } + + class Derived extends Base { + get x() { return 2; } // should be an error + ~ +!!! error TS2611: Class 'Base' defines instance member property 'x', but extended class 'Derived' defines it as instance member accessor. + set x(value) { console.log(`x was set to ${value}`); } + } + + const obj = new Derived(); // nothing printed + console.log(obj.x); // 1 + \ No newline at end of file diff --git a/tests/baselines/reference/accessorsOverrideProperty2.js b/tests/baselines/reference/accessorsOverrideProperty2.js new file mode 100644 index 0000000000000..dcdb2308253a4 --- /dev/null +++ b/tests/baselines/reference/accessorsOverrideProperty2.js @@ -0,0 +1,26 @@ +//// [accessorsOverrideProperty2.ts] +class Base { + x = 1; +} + +class Derived extends Base { + get x() { return 2; } // should be an error + set x(value) { console.log(`x was set to ${value}`); } +} + +const obj = new Derived(); // nothing printed +console.log(obj.x); // 1 + + +//// [accessorsOverrideProperty2.js] +class Base { + constructor() { + this.x = 1; + } +} +class Derived extends Base { + get x() { return 2; } // should be an error + set x(value) { console.log(`x was set to ${value}`); } +} +const obj = new Derived(); // nothing printed +console.log(obj.x); // 1 diff --git a/tests/baselines/reference/accessorsOverrideProperty2.symbols b/tests/baselines/reference/accessorsOverrideProperty2.symbols new file mode 100644 index 0000000000000..eab967402566b --- /dev/null +++ b/tests/baselines/reference/accessorsOverrideProperty2.symbols @@ -0,0 +1,36 @@ +=== tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty2.ts === +class Base { +>Base : Symbol(Base, Decl(accessorsOverrideProperty2.ts, 0, 0)) + + x = 1; +>x : Symbol(Base.x, Decl(accessorsOverrideProperty2.ts, 0, 12)) +} + +class Derived extends Base { +>Derived : Symbol(Derived, Decl(accessorsOverrideProperty2.ts, 2, 1)) +>Base : Symbol(Base, Decl(accessorsOverrideProperty2.ts, 0, 0)) + + get x() { return 2; } // should be an error +>x : Symbol(Derived.x, Decl(accessorsOverrideProperty2.ts, 4, 28), Decl(accessorsOverrideProperty2.ts, 5, 23)) + + set x(value) { console.log(`x was set to ${value}`); } +>x : Symbol(Derived.x, Decl(accessorsOverrideProperty2.ts, 4, 28), Decl(accessorsOverrideProperty2.ts, 5, 23)) +>value : Symbol(value, Decl(accessorsOverrideProperty2.ts, 6, 8)) +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>value : Symbol(value, Decl(accessorsOverrideProperty2.ts, 6, 8)) +} + +const obj = new Derived(); // nothing printed +>obj : Symbol(obj, Decl(accessorsOverrideProperty2.ts, 9, 5)) +>Derived : Symbol(Derived, Decl(accessorsOverrideProperty2.ts, 2, 1)) + +console.log(obj.x); // 1 +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>obj.x : Symbol(Derived.x, Decl(accessorsOverrideProperty2.ts, 4, 28), Decl(accessorsOverrideProperty2.ts, 5, 23)) +>obj : Symbol(obj, Decl(accessorsOverrideProperty2.ts, 9, 5)) +>x : Symbol(Derived.x, Decl(accessorsOverrideProperty2.ts, 4, 28), Decl(accessorsOverrideProperty2.ts, 5, 23)) + diff --git a/tests/baselines/reference/accessorsOverrideProperty2.types b/tests/baselines/reference/accessorsOverrideProperty2.types new file mode 100644 index 0000000000000..f094ab56040e0 --- /dev/null +++ b/tests/baselines/reference/accessorsOverrideProperty2.types @@ -0,0 +1,42 @@ +=== tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty2.ts === +class Base { +>Base : Base + + x = 1; +>x : number +>1 : 1 +} + +class Derived extends Base { +>Derived : Derived +>Base : Base + + get x() { return 2; } // should be an error +>x : number +>2 : 2 + + set x(value) { console.log(`x was set to ${value}`); } +>x : number +>value : number +>console.log(`x was set to ${value}`) : void +>console.log : (message?: any, ...optionalParams: any[]) => void +>console : Console +>log : (message?: any, ...optionalParams: any[]) => void +>`x was set to ${value}` : string +>value : number +} + +const obj = new Derived(); // nothing printed +>obj : Derived +>new Derived() : Derived +>Derived : typeof Derived + +console.log(obj.x); // 1 +>console.log(obj.x) : void +>console.log : (message?: any, ...optionalParams: any[]) => void +>console : Console +>log : (message?: any, ...optionalParams: any[]) => void +>obj.x : number +>obj : Derived +>x : number + diff --git a/tests/baselines/reference/accessorsOverrideProperty3.errors.txt b/tests/baselines/reference/accessorsOverrideProperty3.errors.txt new file mode 100644 index 0000000000000..129af97f9b573 --- /dev/null +++ b/tests/baselines/reference/accessorsOverrideProperty3.errors.txt @@ -0,0 +1,15 @@ +tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty3.ts(6,9): error TS2611: Class 'Animal' defines instance member property 'sound', but extended class 'Lion' defines it as instance member accessor. + + +==== tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty3.ts (1 errors) ==== + declare class Animal { + sound: string + } + class Lion extends Animal { + _sound = 'grrr' + get sound() { return this._sound } // error here + ~~~~~ +!!! error TS2611: Class 'Animal' defines instance member property 'sound', but extended class 'Lion' defines it as instance member accessor. + set sound(val) { this._sound = val } + } + \ No newline at end of file diff --git a/tests/baselines/reference/accessorsOverrideProperty3.js b/tests/baselines/reference/accessorsOverrideProperty3.js new file mode 100644 index 0000000000000..1f1b69ed6eece --- /dev/null +++ b/tests/baselines/reference/accessorsOverrideProperty3.js @@ -0,0 +1,20 @@ +//// [accessorsOverrideProperty3.ts] +declare class Animal { + sound: string +} +class Lion extends Animal { + _sound = 'grrr' + get sound() { return this._sound } // error here + set sound(val) { this._sound = val } +} + + +//// [accessorsOverrideProperty3.js] +class Lion extends Animal { + constructor() { + super(...arguments); + this._sound = 'grrr'; + } + get sound() { return this._sound; } // error here + set sound(val) { this._sound = val; } +} diff --git a/tests/baselines/reference/accessorsOverrideProperty3.symbols b/tests/baselines/reference/accessorsOverrideProperty3.symbols new file mode 100644 index 0000000000000..f34923d36aad3 --- /dev/null +++ b/tests/baselines/reference/accessorsOverrideProperty3.symbols @@ -0,0 +1,29 @@ +=== tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty3.ts === +declare class Animal { +>Animal : Symbol(Animal, Decl(accessorsOverrideProperty3.ts, 0, 0)) + + sound: string +>sound : Symbol(Animal.sound, Decl(accessorsOverrideProperty3.ts, 0, 22)) +} +class Lion extends Animal { +>Lion : Symbol(Lion, Decl(accessorsOverrideProperty3.ts, 2, 1)) +>Animal : Symbol(Animal, Decl(accessorsOverrideProperty3.ts, 0, 0)) + + _sound = 'grrr' +>_sound : Symbol(Lion._sound, Decl(accessorsOverrideProperty3.ts, 3, 27)) + + get sound() { return this._sound } // error here +>sound : Symbol(Lion.sound, Decl(accessorsOverrideProperty3.ts, 4, 19), Decl(accessorsOverrideProperty3.ts, 5, 38)) +>this._sound : Symbol(Lion._sound, Decl(accessorsOverrideProperty3.ts, 3, 27)) +>this : Symbol(Lion, Decl(accessorsOverrideProperty3.ts, 2, 1)) +>_sound : Symbol(Lion._sound, Decl(accessorsOverrideProperty3.ts, 3, 27)) + + set sound(val) { this._sound = val } +>sound : Symbol(Lion.sound, Decl(accessorsOverrideProperty3.ts, 4, 19), Decl(accessorsOverrideProperty3.ts, 5, 38)) +>val : Symbol(val, Decl(accessorsOverrideProperty3.ts, 6, 14)) +>this._sound : Symbol(Lion._sound, Decl(accessorsOverrideProperty3.ts, 3, 27)) +>this : Symbol(Lion, Decl(accessorsOverrideProperty3.ts, 2, 1)) +>_sound : Symbol(Lion._sound, Decl(accessorsOverrideProperty3.ts, 3, 27)) +>val : Symbol(val, Decl(accessorsOverrideProperty3.ts, 6, 14)) +} + diff --git a/tests/baselines/reference/accessorsOverrideProperty3.types b/tests/baselines/reference/accessorsOverrideProperty3.types new file mode 100644 index 0000000000000..6fa0efd42f5a6 --- /dev/null +++ b/tests/baselines/reference/accessorsOverrideProperty3.types @@ -0,0 +1,31 @@ +=== tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty3.ts === +declare class Animal { +>Animal : Animal + + sound: string +>sound : string +} +class Lion extends Animal { +>Lion : Lion +>Animal : Animal + + _sound = 'grrr' +>_sound : string +>'grrr' : "grrr" + + get sound() { return this._sound } // error here +>sound : string +>this._sound : string +>this : this +>_sound : string + + set sound(val) { this._sound = val } +>sound : string +>val : string +>this._sound = val : string +>this._sound : string +>this : this +>_sound : string +>val : string +} + diff --git a/tests/baselines/reference/accessorsOverrideProperty4.errors.txt b/tests/baselines/reference/accessorsOverrideProperty4.errors.txt new file mode 100644 index 0000000000000..ca69ba6074425 --- /dev/null +++ b/tests/baselines/reference/accessorsOverrideProperty4.errors.txt @@ -0,0 +1,15 @@ +tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty4.ts(6,9): error TS2611: Class 'Animal' defines instance member property 'sound', but extended class 'Lion' defines it as instance member accessor. + + +==== tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty4.ts (1 errors) ==== + declare class Animal { + sound: string; + } + class Lion extends Animal { + _sound = 'roar' + get sound(): string { return this._sound } + ~~~~~ +!!! error TS2611: Class 'Animal' defines instance member property 'sound', but extended class 'Lion' defines it as instance member accessor. + set sound(val: string) { this._sound = val } + } + \ No newline at end of file diff --git a/tests/baselines/reference/accessorsOverrideProperty4.js b/tests/baselines/reference/accessorsOverrideProperty4.js new file mode 100644 index 0000000000000..43c07e0c3657c --- /dev/null +++ b/tests/baselines/reference/accessorsOverrideProperty4.js @@ -0,0 +1,20 @@ +//// [accessorsOverrideProperty4.ts] +declare class Animal { + sound: string; +} +class Lion extends Animal { + _sound = 'roar' + get sound(): string { return this._sound } + set sound(val: string) { this._sound = val } +} + + +//// [accessorsOverrideProperty4.js] +class Lion extends Animal { + constructor() { + super(...arguments); + this._sound = 'roar'; + } + get sound() { return this._sound; } + set sound(val) { this._sound = val; } +} diff --git a/tests/baselines/reference/accessorsOverrideProperty4.symbols b/tests/baselines/reference/accessorsOverrideProperty4.symbols new file mode 100644 index 0000000000000..d51646d1ce558 --- /dev/null +++ b/tests/baselines/reference/accessorsOverrideProperty4.symbols @@ -0,0 +1,29 @@ +=== tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty4.ts === +declare class Animal { +>Animal : Symbol(Animal, Decl(accessorsOverrideProperty4.ts, 0, 0)) + + sound: string; +>sound : Symbol(Animal.sound, Decl(accessorsOverrideProperty4.ts, 0, 22)) +} +class Lion extends Animal { +>Lion : Symbol(Lion, Decl(accessorsOverrideProperty4.ts, 2, 1)) +>Animal : Symbol(Animal, Decl(accessorsOverrideProperty4.ts, 0, 0)) + + _sound = 'roar' +>_sound : Symbol(Lion._sound, Decl(accessorsOverrideProperty4.ts, 3, 27)) + + get sound(): string { return this._sound } +>sound : Symbol(Lion.sound, Decl(accessorsOverrideProperty4.ts, 4, 19), Decl(accessorsOverrideProperty4.ts, 5, 46)) +>this._sound : Symbol(Lion._sound, Decl(accessorsOverrideProperty4.ts, 3, 27)) +>this : Symbol(Lion, Decl(accessorsOverrideProperty4.ts, 2, 1)) +>_sound : Symbol(Lion._sound, Decl(accessorsOverrideProperty4.ts, 3, 27)) + + set sound(val: string) { this._sound = val } +>sound : Symbol(Lion.sound, Decl(accessorsOverrideProperty4.ts, 4, 19), Decl(accessorsOverrideProperty4.ts, 5, 46)) +>val : Symbol(val, Decl(accessorsOverrideProperty4.ts, 6, 14)) +>this._sound : Symbol(Lion._sound, Decl(accessorsOverrideProperty4.ts, 3, 27)) +>this : Symbol(Lion, Decl(accessorsOverrideProperty4.ts, 2, 1)) +>_sound : Symbol(Lion._sound, Decl(accessorsOverrideProperty4.ts, 3, 27)) +>val : Symbol(val, Decl(accessorsOverrideProperty4.ts, 6, 14)) +} + diff --git a/tests/baselines/reference/accessorsOverrideProperty4.types b/tests/baselines/reference/accessorsOverrideProperty4.types new file mode 100644 index 0000000000000..e553e5f37f05d --- /dev/null +++ b/tests/baselines/reference/accessorsOverrideProperty4.types @@ -0,0 +1,31 @@ +=== tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty4.ts === +declare class Animal { +>Animal : Animal + + sound: string; +>sound : string +} +class Lion extends Animal { +>Lion : Lion +>Animal : Animal + + _sound = 'roar' +>_sound : string +>'roar' : "roar" + + get sound(): string { return this._sound } +>sound : string +>this._sound : string +>this : this +>_sound : string + + set sound(val: string) { this._sound = val } +>sound : string +>val : string +>this._sound = val : string +>this._sound : string +>this : this +>_sound : string +>val : string +} + diff --git a/tests/baselines/reference/inheritanceMemberAccessorOverridingProperty.errors.txt b/tests/baselines/reference/inheritanceMemberAccessorOverridingProperty.errors.txt index 98b9d349d64fe..fd71a37a6875d 100644 --- a/tests/baselines/reference/inheritanceMemberAccessorOverridingProperty.errors.txt +++ b/tests/baselines/reference/inheritanceMemberAccessorOverridingProperty.errors.txt @@ -1,8 +1,9 @@ tests/cases/compiler/inheritanceMemberAccessorOverridingProperty.ts(6,9): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher. +tests/cases/compiler/inheritanceMemberAccessorOverridingProperty.ts(6,9): error TS2611: Class 'a' defines instance member property 'x', but extended class 'b' defines it as instance member accessor. tests/cases/compiler/inheritanceMemberAccessorOverridingProperty.ts(9,9): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher. -==== tests/cases/compiler/inheritanceMemberAccessorOverridingProperty.ts (2 errors) ==== +==== tests/cases/compiler/inheritanceMemberAccessorOverridingProperty.ts (3 errors) ==== class a { x: string; } @@ -11,6 +12,8 @@ tests/cases/compiler/inheritanceMemberAccessorOverridingProperty.ts(9,9): error get x() { ~ !!! error TS1056: Accessors are only available when targeting ECMAScript 5 and higher. + ~ +!!! error TS2611: Class 'a' defines instance member property 'x', but extended class 'b' defines it as instance member accessor. return "20"; } set x(aValue: string) { diff --git a/tests/baselines/reference/inheritanceMemberPropertyOverridingAccessor.errors.txt b/tests/baselines/reference/inheritanceMemberPropertyOverridingAccessor.errors.txt index ec8ec05a8aeb5..4b468181f96a3 100644 --- a/tests/baselines/reference/inheritanceMemberPropertyOverridingAccessor.errors.txt +++ b/tests/baselines/reference/inheritanceMemberPropertyOverridingAccessor.errors.txt @@ -1,8 +1,9 @@ tests/cases/compiler/inheritanceMemberPropertyOverridingAccessor.ts(3,9): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher. tests/cases/compiler/inheritanceMemberPropertyOverridingAccessor.ts(6,9): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher. +tests/cases/compiler/inheritanceMemberPropertyOverridingAccessor.ts(12,5): error TS2610: Class 'a' defines instance member accessor 'x', but extended class 'b' defines it as instance member property. -==== tests/cases/compiler/inheritanceMemberPropertyOverridingAccessor.ts (2 errors) ==== +==== tests/cases/compiler/inheritanceMemberPropertyOverridingAccessor.ts (3 errors) ==== class a { private __x: () => string; get x() { @@ -19,4 +20,6 @@ tests/cases/compiler/inheritanceMemberPropertyOverridingAccessor.ts(6,9): error class b extends a { x: () => string; + ~ +!!! error TS2610: Class 'a' defines instance member accessor 'x', but extended class 'b' defines it as instance member property. } \ No newline at end of file diff --git a/tests/baselines/reference/propertyOverridesAccessors.errors.txt b/tests/baselines/reference/propertyOverridesAccessors.errors.txt new file mode 100644 index 0000000000000..dcacf16696d48 --- /dev/null +++ b/tests/baselines/reference/propertyOverridesAccessors.errors.txt @@ -0,0 +1,24 @@ +tests/cases/conformance/classes/propertyMemberDeclarations/propertyOverridesAccessors.ts(5,5): error TS2610: Class 'A' defines instance member accessor 'p', but extended class 'B' defines it as instance member property. +tests/cases/conformance/classes/propertyMemberDeclarations/propertyOverridesAccessors.ts(13,5): error TS2610: Class 'C' defines instance member accessor 'p', but extended class 'D' defines it as instance member property. + + +==== tests/cases/conformance/classes/propertyMemberDeclarations/propertyOverridesAccessors.ts (2 errors) ==== + class A { + get p() { return 'oh no' } + } + class B extends A { + p = 'yep' // error + ~ +!!! error TS2610: Class 'A' defines instance member accessor 'p', but extended class 'B' defines it as instance member property. + } + class C { + _secret = 11 + get p() { return this._secret } + set p(value) { this._secret = value } + } + class D extends C { + p = 101 // error + ~ +!!! error TS2610: Class 'C' defines instance member accessor 'p', but extended class 'D' defines it as instance member property. + } + \ No newline at end of file diff --git a/tests/baselines/reference/propertyOverridesAccessors.js b/tests/baselines/reference/propertyOverridesAccessors.js new file mode 100644 index 0000000000000..bc69da6705a36 --- /dev/null +++ b/tests/baselines/reference/propertyOverridesAccessors.js @@ -0,0 +1,40 @@ +//// [propertyOverridesAccessors.ts] +class A { + get p() { return 'oh no' } +} +class B extends A { + p = 'yep' // error +} +class C { + _secret = 11 + get p() { return this._secret } + set p(value) { this._secret = value } +} +class D extends C { + p = 101 // error +} + + +//// [propertyOverridesAccessors.js] +class A { + get p() { return 'oh no'; } +} +class B extends A { + constructor() { + super(...arguments); + this.p = 'yep'; // error + } +} +class C { + constructor() { + this._secret = 11; + } + get p() { return this._secret; } + set p(value) { this._secret = value; } +} +class D extends C { + constructor() { + super(...arguments); + this.p = 101; // error + } +} diff --git a/tests/baselines/reference/propertyOverridesAccessors.symbols b/tests/baselines/reference/propertyOverridesAccessors.symbols new file mode 100644 index 0000000000000..e365fedad0a2e --- /dev/null +++ b/tests/baselines/reference/propertyOverridesAccessors.symbols @@ -0,0 +1,42 @@ +=== tests/cases/conformance/classes/propertyMemberDeclarations/propertyOverridesAccessors.ts === +class A { +>A : Symbol(A, Decl(propertyOverridesAccessors.ts, 0, 0)) + + get p() { return 'oh no' } +>p : Symbol(A.p, Decl(propertyOverridesAccessors.ts, 0, 9)) +} +class B extends A { +>B : Symbol(B, Decl(propertyOverridesAccessors.ts, 2, 1)) +>A : Symbol(A, Decl(propertyOverridesAccessors.ts, 0, 0)) + + p = 'yep' // error +>p : Symbol(B.p, Decl(propertyOverridesAccessors.ts, 3, 19)) +} +class C { +>C : Symbol(C, Decl(propertyOverridesAccessors.ts, 5, 1)) + + _secret = 11 +>_secret : Symbol(C._secret, Decl(propertyOverridesAccessors.ts, 6, 9)) + + get p() { return this._secret } +>p : Symbol(C.p, Decl(propertyOverridesAccessors.ts, 7, 16), Decl(propertyOverridesAccessors.ts, 8, 35)) +>this._secret : Symbol(C._secret, Decl(propertyOverridesAccessors.ts, 6, 9)) +>this : Symbol(C, Decl(propertyOverridesAccessors.ts, 5, 1)) +>_secret : Symbol(C._secret, Decl(propertyOverridesAccessors.ts, 6, 9)) + + set p(value) { this._secret = value } +>p : Symbol(C.p, Decl(propertyOverridesAccessors.ts, 7, 16), Decl(propertyOverridesAccessors.ts, 8, 35)) +>value : Symbol(value, Decl(propertyOverridesAccessors.ts, 9, 10)) +>this._secret : Symbol(C._secret, Decl(propertyOverridesAccessors.ts, 6, 9)) +>this : Symbol(C, Decl(propertyOverridesAccessors.ts, 5, 1)) +>_secret : Symbol(C._secret, Decl(propertyOverridesAccessors.ts, 6, 9)) +>value : Symbol(value, Decl(propertyOverridesAccessors.ts, 9, 10)) +} +class D extends C { +>D : Symbol(D, Decl(propertyOverridesAccessors.ts, 10, 1)) +>C : Symbol(C, Decl(propertyOverridesAccessors.ts, 5, 1)) + + p = 101 // error +>p : Symbol(D.p, Decl(propertyOverridesAccessors.ts, 11, 19)) +} + diff --git a/tests/baselines/reference/propertyOverridesAccessors.types b/tests/baselines/reference/propertyOverridesAccessors.types new file mode 100644 index 0000000000000..9ffec6e8fe68d --- /dev/null +++ b/tests/baselines/reference/propertyOverridesAccessors.types @@ -0,0 +1,47 @@ +=== tests/cases/conformance/classes/propertyMemberDeclarations/propertyOverridesAccessors.ts === +class A { +>A : A + + get p() { return 'oh no' } +>p : string +>'oh no' : "oh no" +} +class B extends A { +>B : B +>A : A + + p = 'yep' // error +>p : string +>'yep' : "yep" +} +class C { +>C : C + + _secret = 11 +>_secret : number +>11 : 11 + + get p() { return this._secret } +>p : number +>this._secret : number +>this : this +>_secret : number + + set p(value) { this._secret = value } +>p : number +>value : number +>this._secret = value : number +>this._secret : number +>this : this +>_secret : number +>value : number +} +class D extends C { +>D : D +>C : C + + p = 101 // error +>p : number +>101 : 101 +} + diff --git a/tests/baselines/reference/propertyOverridesAccessors2.errors.txt b/tests/baselines/reference/propertyOverridesAccessors2.errors.txt new file mode 100644 index 0000000000000..0c91d3b9f7f7a --- /dev/null +++ b/tests/baselines/reference/propertyOverridesAccessors2.errors.txt @@ -0,0 +1,18 @@ +tests/cases/conformance/classes/propertyMemberDeclarations/propertyOverridesAccessors2.ts(7,3): error TS2610: Class 'Base' defines instance member accessor 'x', but extended class 'Derived' defines it as instance member property. + + +==== tests/cases/conformance/classes/propertyMemberDeclarations/propertyOverridesAccessors2.ts (1 errors) ==== + class Base { + get x() { return 2; } + set x(value) { console.log(`x was set to ${value}`); } + } + + class Derived extends Base { + x = 1; + ~ +!!! error TS2610: Class 'Base' defines instance member accessor 'x', but extended class 'Derived' defines it as instance member property. + } + + const obj = new Derived(); // prints 'x was set to 1' + console.log(obj.x); // 2 + \ No newline at end of file diff --git a/tests/baselines/reference/propertyOverridesAccessors2.js b/tests/baselines/reference/propertyOverridesAccessors2.js new file mode 100644 index 0000000000000..bf5825771ff06 --- /dev/null +++ b/tests/baselines/reference/propertyOverridesAccessors2.js @@ -0,0 +1,27 @@ +//// [propertyOverridesAccessors2.ts] +class Base { + get x() { return 2; } + set x(value) { console.log(`x was set to ${value}`); } +} + +class Derived extends Base { + x = 1; +} + +const obj = new Derived(); // prints 'x was set to 1' +console.log(obj.x); // 2 + + +//// [propertyOverridesAccessors2.js] +class Base { + get x() { return 2; } + set x(value) { console.log(`x was set to ${value}`); } +} +class Derived extends Base { + constructor() { + super(...arguments); + this.x = 1; + } +} +const obj = new Derived(); // prints 'x was set to 1' +console.log(obj.x); // 2 diff --git a/tests/baselines/reference/propertyOverridesAccessors2.symbols b/tests/baselines/reference/propertyOverridesAccessors2.symbols new file mode 100644 index 0000000000000..fd26e67e69bf0 --- /dev/null +++ b/tests/baselines/reference/propertyOverridesAccessors2.symbols @@ -0,0 +1,36 @@ +=== tests/cases/conformance/classes/propertyMemberDeclarations/propertyOverridesAccessors2.ts === +class Base { +>Base : Symbol(Base, Decl(propertyOverridesAccessors2.ts, 0, 0)) + + get x() { return 2; } +>x : Symbol(Base.x, Decl(propertyOverridesAccessors2.ts, 0, 12), Decl(propertyOverridesAccessors2.ts, 1, 23)) + + set x(value) { console.log(`x was set to ${value}`); } +>x : Symbol(Base.x, Decl(propertyOverridesAccessors2.ts, 0, 12), Decl(propertyOverridesAccessors2.ts, 1, 23)) +>value : Symbol(value, Decl(propertyOverridesAccessors2.ts, 2, 8)) +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>value : Symbol(value, Decl(propertyOverridesAccessors2.ts, 2, 8)) +} + +class Derived extends Base { +>Derived : Symbol(Derived, Decl(propertyOverridesAccessors2.ts, 3, 1)) +>Base : Symbol(Base, Decl(propertyOverridesAccessors2.ts, 0, 0)) + + x = 1; +>x : Symbol(Derived.x, Decl(propertyOverridesAccessors2.ts, 5, 28)) +} + +const obj = new Derived(); // prints 'x was set to 1' +>obj : Symbol(obj, Decl(propertyOverridesAccessors2.ts, 9, 5)) +>Derived : Symbol(Derived, Decl(propertyOverridesAccessors2.ts, 3, 1)) + +console.log(obj.x); // 2 +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>obj.x : Symbol(Derived.x, Decl(propertyOverridesAccessors2.ts, 5, 28)) +>obj : Symbol(obj, Decl(propertyOverridesAccessors2.ts, 9, 5)) +>x : Symbol(Derived.x, Decl(propertyOverridesAccessors2.ts, 5, 28)) + diff --git a/tests/baselines/reference/propertyOverridesAccessors2.types b/tests/baselines/reference/propertyOverridesAccessors2.types new file mode 100644 index 0000000000000..5db511e968184 --- /dev/null +++ b/tests/baselines/reference/propertyOverridesAccessors2.types @@ -0,0 +1,42 @@ +=== tests/cases/conformance/classes/propertyMemberDeclarations/propertyOverridesAccessors2.ts === +class Base { +>Base : Base + + get x() { return 2; } +>x : number +>2 : 2 + + set x(value) { console.log(`x was set to ${value}`); } +>x : number +>value : number +>console.log(`x was set to ${value}`) : void +>console.log : (message?: any, ...optionalParams: any[]) => void +>console : Console +>log : (message?: any, ...optionalParams: any[]) => void +>`x was set to ${value}` : string +>value : number +} + +class Derived extends Base { +>Derived : Derived +>Base : Base + + x = 1; +>x : number +>1 : 1 +} + +const obj = new Derived(); // prints 'x was set to 1' +>obj : Derived +>new Derived() : Derived +>Derived : typeof Derived + +console.log(obj.x); // 2 +>console.log(obj.x) : void +>console.log : (message?: any, ...optionalParams: any[]) => void +>console : Console +>log : (message?: any, ...optionalParams: any[]) => void +>obj.x : number +>obj : Derived +>x : number + diff --git a/tests/baselines/reference/propertyOverridesAccessors3.errors.txt b/tests/baselines/reference/propertyOverridesAccessors3.errors.txt new file mode 100644 index 0000000000000..523a0f6db3d08 --- /dev/null +++ b/tests/baselines/reference/propertyOverridesAccessors3.errors.txt @@ -0,0 +1,30 @@ +tests/cases/conformance/classes/propertyMemberDeclarations/propertyOverridesAccessors3.ts(19,5): error TS2610: Class 'Animal' defines instance member accessor 'sound', but extended class 'Lion' defines it as instance member property. + + +==== tests/cases/conformance/classes/propertyMemberDeclarations/propertyOverridesAccessors3.ts (1 errors) ==== + class Animal { + _sound = 'rustling noise in the bushes' + + get sound() { return this._sound } + set sound(val) { + this._sound = val; + /* some important code here, perhaps tracking known sounds, etc */ + } + + makeSound() { + console.log(this._sound) + } + } + + const a = new Animal + a.makeSound() // 'rustling noise in the bushes' + + class Lion extends Animal { + sound = 'RAWR!' // error here + ~~~~~ +!!! error TS2610: Class 'Animal' defines instance member accessor 'sound', but extended class 'Lion' defines it as instance member property. + } + + const lion = new Lion + lion.makeSound() // with [[Define]]: Expected "RAWR!" but got "rustling noise in the bushes" + \ No newline at end of file diff --git a/tests/baselines/reference/propertyOverridesAccessors3.js b/tests/baselines/reference/propertyOverridesAccessors3.js new file mode 100644 index 0000000000000..3df81827bc97f --- /dev/null +++ b/tests/baselines/reference/propertyOverridesAccessors3.js @@ -0,0 +1,50 @@ +//// [propertyOverridesAccessors3.ts] +class Animal { + _sound = 'rustling noise in the bushes' + + get sound() { return this._sound } + set sound(val) { + this._sound = val; + /* some important code here, perhaps tracking known sounds, etc */ + } + + makeSound() { + console.log(this._sound) + } +} + +const a = new Animal +a.makeSound() // 'rustling noise in the bushes' + +class Lion extends Animal { + sound = 'RAWR!' // error here +} + +const lion = new Lion +lion.makeSound() // with [[Define]]: Expected "RAWR!" but got "rustling noise in the bushes" + + +//// [propertyOverridesAccessors3.js] +class Animal { + constructor() { + this._sound = 'rustling noise in the bushes'; + } + get sound() { return this._sound; } + set sound(val) { + this._sound = val; + /* some important code here, perhaps tracking known sounds, etc */ + } + makeSound() { + console.log(this._sound); + } +} +const a = new Animal; +a.makeSound(); // 'rustling noise in the bushes' +class Lion extends Animal { + constructor() { + super(...arguments); + this.sound = 'RAWR!'; // error here + } +} +const lion = new Lion; +lion.makeSound(); // with [[Define]]: Expected "RAWR!" but got "rustling noise in the bushes" diff --git a/tests/baselines/reference/propertyOverridesAccessors3.symbols b/tests/baselines/reference/propertyOverridesAccessors3.symbols new file mode 100644 index 0000000000000..801b6ca3c9810 --- /dev/null +++ b/tests/baselines/reference/propertyOverridesAccessors3.symbols @@ -0,0 +1,65 @@ +=== tests/cases/conformance/classes/propertyMemberDeclarations/propertyOverridesAccessors3.ts === +class Animal { +>Animal : Symbol(Animal, Decl(propertyOverridesAccessors3.ts, 0, 0)) + + _sound = 'rustling noise in the bushes' +>_sound : Symbol(Animal._sound, Decl(propertyOverridesAccessors3.ts, 0, 14)) + + get sound() { return this._sound } +>sound : Symbol(Animal.sound, Decl(propertyOverridesAccessors3.ts, 1, 43), Decl(propertyOverridesAccessors3.ts, 3, 38)) +>this._sound : Symbol(Animal._sound, Decl(propertyOverridesAccessors3.ts, 0, 14)) +>this : Symbol(Animal, Decl(propertyOverridesAccessors3.ts, 0, 0)) +>_sound : Symbol(Animal._sound, Decl(propertyOverridesAccessors3.ts, 0, 14)) + + set sound(val) { +>sound : Symbol(Animal.sound, Decl(propertyOverridesAccessors3.ts, 1, 43), Decl(propertyOverridesAccessors3.ts, 3, 38)) +>val : Symbol(val, Decl(propertyOverridesAccessors3.ts, 4, 14)) + + this._sound = val; +>this._sound : Symbol(Animal._sound, Decl(propertyOverridesAccessors3.ts, 0, 14)) +>this : Symbol(Animal, Decl(propertyOverridesAccessors3.ts, 0, 0)) +>_sound : Symbol(Animal._sound, Decl(propertyOverridesAccessors3.ts, 0, 14)) +>val : Symbol(val, Decl(propertyOverridesAccessors3.ts, 4, 14)) + + /* some important code here, perhaps tracking known sounds, etc */ + } + + makeSound() { +>makeSound : Symbol(Animal.makeSound, Decl(propertyOverridesAccessors3.ts, 7, 5)) + + console.log(this._sound) +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>this._sound : Symbol(Animal._sound, Decl(propertyOverridesAccessors3.ts, 0, 14)) +>this : Symbol(Animal, Decl(propertyOverridesAccessors3.ts, 0, 0)) +>_sound : Symbol(Animal._sound, Decl(propertyOverridesAccessors3.ts, 0, 14)) + } +} + +const a = new Animal +>a : Symbol(a, Decl(propertyOverridesAccessors3.ts, 14, 5)) +>Animal : Symbol(Animal, Decl(propertyOverridesAccessors3.ts, 0, 0)) + +a.makeSound() // 'rustling noise in the bushes' +>a.makeSound : Symbol(Animal.makeSound, Decl(propertyOverridesAccessors3.ts, 7, 5)) +>a : Symbol(a, Decl(propertyOverridesAccessors3.ts, 14, 5)) +>makeSound : Symbol(Animal.makeSound, Decl(propertyOverridesAccessors3.ts, 7, 5)) + +class Lion extends Animal { +>Lion : Symbol(Lion, Decl(propertyOverridesAccessors3.ts, 15, 13)) +>Animal : Symbol(Animal, Decl(propertyOverridesAccessors3.ts, 0, 0)) + + sound = 'RAWR!' // error here +>sound : Symbol(Lion.sound, Decl(propertyOverridesAccessors3.ts, 17, 27)) +} + +const lion = new Lion +>lion : Symbol(lion, Decl(propertyOverridesAccessors3.ts, 21, 5)) +>Lion : Symbol(Lion, Decl(propertyOverridesAccessors3.ts, 15, 13)) + +lion.makeSound() // with [[Define]]: Expected "RAWR!" but got "rustling noise in the bushes" +>lion.makeSound : Symbol(Animal.makeSound, Decl(propertyOverridesAccessors3.ts, 7, 5)) +>lion : Symbol(lion, Decl(propertyOverridesAccessors3.ts, 21, 5)) +>makeSound : Symbol(Animal.makeSound, Decl(propertyOverridesAccessors3.ts, 7, 5)) + diff --git a/tests/baselines/reference/propertyOverridesAccessors3.types b/tests/baselines/reference/propertyOverridesAccessors3.types new file mode 100644 index 0000000000000..b7ea64087c7a8 --- /dev/null +++ b/tests/baselines/reference/propertyOverridesAccessors3.types @@ -0,0 +1,73 @@ +=== tests/cases/conformance/classes/propertyMemberDeclarations/propertyOverridesAccessors3.ts === +class Animal { +>Animal : Animal + + _sound = 'rustling noise in the bushes' +>_sound : string +>'rustling noise in the bushes' : "rustling noise in the bushes" + + get sound() { return this._sound } +>sound : string +>this._sound : string +>this : this +>_sound : string + + set sound(val) { +>sound : string +>val : string + + this._sound = val; +>this._sound = val : string +>this._sound : string +>this : this +>_sound : string +>val : string + + /* some important code here, perhaps tracking known sounds, etc */ + } + + makeSound() { +>makeSound : () => void + + console.log(this._sound) +>console.log(this._sound) : void +>console.log : (message?: any, ...optionalParams: any[]) => void +>console : Console +>log : (message?: any, ...optionalParams: any[]) => void +>this._sound : string +>this : this +>_sound : string + } +} + +const a = new Animal +>a : Animal +>new Animal : Animal +>Animal : typeof Animal + +a.makeSound() // 'rustling noise in the bushes' +>a.makeSound() : void +>a.makeSound : () => void +>a : Animal +>makeSound : () => void + +class Lion extends Animal { +>Lion : Lion +>Animal : Animal + + sound = 'RAWR!' // error here +>sound : string +>'RAWR!' : "RAWR!" +} + +const lion = new Lion +>lion : Lion +>new Lion : Lion +>Lion : typeof Lion + +lion.makeSound() // with [[Define]]: Expected "RAWR!" but got "rustling noise in the bushes" +>lion.makeSound() : void +>lion.makeSound : () => void +>lion : Lion +>makeSound : () => void + diff --git a/tests/baselines/reference/propertyOverridesAccessors4.errors.txt b/tests/baselines/reference/propertyOverridesAccessors4.errors.txt new file mode 100644 index 0000000000000..c437e05b28280 --- /dev/null +++ b/tests/baselines/reference/propertyOverridesAccessors4.errors.txt @@ -0,0 +1,14 @@ +tests/cases/conformance/classes/propertyMemberDeclarations/propertyOverridesAccessors4.ts(6,5): error TS2610: Class 'Animal' defines instance member accessor 'sound', but extended class 'Lion' defines it as instance member property. + + +==== tests/cases/conformance/classes/propertyMemberDeclarations/propertyOverridesAccessors4.ts (1 errors) ==== + declare class Animal { + get sound(): string + set sound(val: string) + } + class Lion extends Animal { + sound = 'RAWR!' // error here + ~~~~~ +!!! error TS2610: Class 'Animal' defines instance member accessor 'sound', but extended class 'Lion' defines it as instance member property. + } + \ No newline at end of file diff --git a/tests/baselines/reference/propertyOverridesAccessors4.js b/tests/baselines/reference/propertyOverridesAccessors4.js new file mode 100644 index 0000000000000..0b0330de05668 --- /dev/null +++ b/tests/baselines/reference/propertyOverridesAccessors4.js @@ -0,0 +1,33 @@ +//// [propertyOverridesAccessors4.ts] +declare class Animal { + get sound(): string + set sound(val: string) +} +class Lion extends Animal { + sound = 'RAWR!' // error here +} + + +//// [propertyOverridesAccessors4.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 (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +var Lion = /** @class */ (function (_super) { + __extends(Lion, _super); + function Lion() { + var _this = _super !== null && _super.apply(this, arguments) || this; + _this.sound = 'RAWR!'; // error here + return _this; + } + return Lion; +}(Animal)); diff --git a/tests/baselines/reference/propertyOverridesAccessors4.symbols b/tests/baselines/reference/propertyOverridesAccessors4.symbols new file mode 100644 index 0000000000000..d7097e1d528cd --- /dev/null +++ b/tests/baselines/reference/propertyOverridesAccessors4.symbols @@ -0,0 +1,19 @@ +=== tests/cases/conformance/classes/propertyMemberDeclarations/propertyOverridesAccessors4.ts === +declare class Animal { +>Animal : Symbol(Animal, Decl(propertyOverridesAccessors4.ts, 0, 0)) + + get sound(): string +>sound : Symbol(Animal.sound, Decl(propertyOverridesAccessors4.ts, 0, 22), Decl(propertyOverridesAccessors4.ts, 1, 23)) + + set sound(val: string) +>sound : Symbol(Animal.sound, Decl(propertyOverridesAccessors4.ts, 0, 22), Decl(propertyOverridesAccessors4.ts, 1, 23)) +>val : Symbol(val, Decl(propertyOverridesAccessors4.ts, 2, 14)) +} +class Lion extends Animal { +>Lion : Symbol(Lion, Decl(propertyOverridesAccessors4.ts, 3, 1)) +>Animal : Symbol(Animal, Decl(propertyOverridesAccessors4.ts, 0, 0)) + + sound = 'RAWR!' // error here +>sound : Symbol(Lion.sound, Decl(propertyOverridesAccessors4.ts, 4, 27)) +} + diff --git a/tests/baselines/reference/propertyOverridesAccessors4.types b/tests/baselines/reference/propertyOverridesAccessors4.types new file mode 100644 index 0000000000000..5701f76127bd6 --- /dev/null +++ b/tests/baselines/reference/propertyOverridesAccessors4.types @@ -0,0 +1,20 @@ +=== tests/cases/conformance/classes/propertyMemberDeclarations/propertyOverridesAccessors4.ts === +declare class Animal { +>Animal : Animal + + get sound(): string +>sound : string + + set sound(val: string) +>sound : string +>val : string +} +class Lion extends Animal { +>Lion : Lion +>Animal : Animal + + sound = 'RAWR!' // error here +>sound : string +>'RAWR!' : "RAWR!" +} + diff --git a/tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty.ts b/tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty.ts new file mode 100644 index 0000000000000..9365ea6bf9467 --- /dev/null +++ b/tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty.ts @@ -0,0 +1,15 @@ +// @target: esnext +class A { + p = 'yep' +} +class B extends A { + get p() { return 'oh no' } // error +} +class C { + p = 101 +} +class D extends C { + _secret = 11 + get p() { return this._secret } // error + set p(value) { this._secret = value } // error +} diff --git a/tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty2.ts b/tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty2.ts new file mode 100644 index 0000000000000..18a51bb1c11ab --- /dev/null +++ b/tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty2.ts @@ -0,0 +1,12 @@ +// @target: esnext +class Base { + x = 1; +} + +class Derived extends Base { + get x() { return 2; } // should be an error + set x(value) { console.log(`x was set to ${value}`); } +} + +const obj = new Derived(); // nothing printed +console.log(obj.x); // 1 diff --git a/tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty3.ts b/tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty3.ts new file mode 100644 index 0000000000000..204286d2463d6 --- /dev/null +++ b/tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty3.ts @@ -0,0 +1,9 @@ +// @target: esnext +declare class Animal { + sound: string +} +class Lion extends Animal { + _sound = 'grrr' + get sound() { return this._sound } // error here + set sound(val) { this._sound = val } +} diff --git a/tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty4.ts b/tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty4.ts new file mode 100644 index 0000000000000..4712b9c6f8d38 --- /dev/null +++ b/tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty4.ts @@ -0,0 +1,9 @@ +// @target: esnext +declare class Animal { + sound: string; +} +class Lion extends Animal { + _sound = 'roar' + get sound(): string { return this._sound } + set sound(val: string) { this._sound = val } +} diff --git a/tests/cases/conformance/classes/propertyMemberDeclarations/propertyOverridesAccessors.ts b/tests/cases/conformance/classes/propertyMemberDeclarations/propertyOverridesAccessors.ts new file mode 100644 index 0000000000000..b9dc49c574005 --- /dev/null +++ b/tests/cases/conformance/classes/propertyMemberDeclarations/propertyOverridesAccessors.ts @@ -0,0 +1,15 @@ +// @target: esnext +class A { + get p() { return 'oh no' } +} +class B extends A { + p = 'yep' // error +} +class C { + _secret = 11 + get p() { return this._secret } + set p(value) { this._secret = value } +} +class D extends C { + p = 101 // error +} diff --git a/tests/cases/conformance/classes/propertyMemberDeclarations/propertyOverridesAccessors2.ts b/tests/cases/conformance/classes/propertyMemberDeclarations/propertyOverridesAccessors2.ts new file mode 100644 index 0000000000000..760658238a5ec --- /dev/null +++ b/tests/cases/conformance/classes/propertyMemberDeclarations/propertyOverridesAccessors2.ts @@ -0,0 +1,12 @@ +// @target: esnext +class Base { + get x() { return 2; } + set x(value) { console.log(`x was set to ${value}`); } +} + +class Derived extends Base { + x = 1; +} + +const obj = new Derived(); // prints 'x was set to 1' +console.log(obj.x); // 2 diff --git a/tests/cases/conformance/classes/propertyMemberDeclarations/propertyOverridesAccessors3.ts b/tests/cases/conformance/classes/propertyMemberDeclarations/propertyOverridesAccessors3.ts new file mode 100644 index 0000000000000..5d61108fc99b7 --- /dev/null +++ b/tests/cases/conformance/classes/propertyMemberDeclarations/propertyOverridesAccessors3.ts @@ -0,0 +1,24 @@ +// @target: esnext +class Animal { + _sound = 'rustling noise in the bushes' + + get sound() { return this._sound } + set sound(val) { + this._sound = val; + /* some important code here, perhaps tracking known sounds, etc */ + } + + makeSound() { + console.log(this._sound) + } +} + +const a = new Animal +a.makeSound() // 'rustling noise in the bushes' + +class Lion extends Animal { + sound = 'RAWR!' // error here +} + +const lion = new Lion +lion.makeSound() // with [[Define]]: Expected "RAWR!" but got "rustling noise in the bushes" diff --git a/tests/cases/conformance/classes/propertyMemberDeclarations/propertyOverridesAccessors4.ts b/tests/cases/conformance/classes/propertyMemberDeclarations/propertyOverridesAccessors4.ts new file mode 100644 index 0000000000000..e34b08a9bbd77 --- /dev/null +++ b/tests/cases/conformance/classes/propertyMemberDeclarations/propertyOverridesAccessors4.ts @@ -0,0 +1,7 @@ +declare class Animal { + get sound(): string + set sound(val: string) +} +class Lion extends Animal { + sound = 'RAWR!' // error here +} From c4f334a7be6f813fe8510685f5af64dddb0281f0 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Fri, 13 Sep 2019 15:49:16 -0700 Subject: [PATCH 2/6] Updates from design review + fix ancient bug 1. Don't error when overriding properties from interfaces. 2. Fix error when overriding methods with other things. This had no tests so I assume that the code was always dead and never worked. --- src/compiler/checker.ts | 19 ++++--- .../accessorsOverrideMethod.errors.txt | 13 +++++ .../reference/accessorsOverrideMethod.js | 16 ++++++ .../reference/accessorsOverrideMethod.symbols | 15 ++++++ .../reference/accessorsOverrideMethod.types | 17 +++++++ .../checkJsFiles_noErrorLocation.errors.txt | 25 ++++++++++ ...eMemberAccessorOverridingMethod.errors.txt | 20 ++++++++ ...eMemberPropertyOverridingMethod.errors.txt | 15 ++++++ .../reference/overrideInterfaceProperty.js | 31 ++++++++++++ .../overrideInterfaceProperty.symbols | 49 +++++++++++++++++++ .../reference/overrideInterfaceProperty.types | 36 ++++++++++++++ .../propertyOverridesMethod.errors.txt | 13 +++++ .../reference/propertyOverridesMethod.js | 19 +++++++ .../reference/propertyOverridesMethod.symbols | 15 ++++++ .../reference/propertyOverridesMethod.types | 17 +++++++ .../propertyOverridingPrototype.errors.txt | 16 ++++++ .../accessorsOverrideMethod.ts | 7 +++ .../overrideInterfaceProperty.ts | 18 +++++++ .../propertyOverridesMethod.ts | 7 +++ 19 files changed, 361 insertions(+), 7 deletions(-) create mode 100644 tests/baselines/reference/accessorsOverrideMethod.errors.txt create mode 100644 tests/baselines/reference/accessorsOverrideMethod.js create mode 100644 tests/baselines/reference/accessorsOverrideMethod.symbols create mode 100644 tests/baselines/reference/accessorsOverrideMethod.types create mode 100644 tests/baselines/reference/checkJsFiles_noErrorLocation.errors.txt create mode 100644 tests/baselines/reference/inheritanceMemberAccessorOverridingMethod.errors.txt create mode 100644 tests/baselines/reference/inheritanceMemberPropertyOverridingMethod.errors.txt create mode 100644 tests/baselines/reference/overrideInterfaceProperty.js create mode 100644 tests/baselines/reference/overrideInterfaceProperty.symbols create mode 100644 tests/baselines/reference/overrideInterfaceProperty.types create mode 100644 tests/baselines/reference/propertyOverridesMethod.errors.txt create mode 100644 tests/baselines/reference/propertyOverridesMethod.js create mode 100644 tests/baselines/reference/propertyOverridesMethod.symbols create mode 100644 tests/baselines/reference/propertyOverridesMethod.types create mode 100644 tests/baselines/reference/propertyOverridingPrototype.errors.txt create mode 100644 tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideMethod.ts create mode 100644 tests/cases/conformance/classes/propertyMemberDeclarations/overrideInterfaceProperty.ts create mode 100644 tests/cases/conformance/classes/propertyMemberDeclarations/propertyOverridesMethod.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index b6d7723c6cab1..e38b631df4f9c 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -29513,19 +29513,20 @@ namespace ts { // either base or derived property is private - not override, skip it continue; } - if (isPrototypeProperty(base)) { - // method is overridden with method - correct case - continue; - } let errorMessage: DiagnosticMessage; const basePropertyFlags = base.flags & SymbolFlags.PropertyOrAccessor; const derivedPropertyFlags = derived.flags & SymbolFlags.PropertyOrAccessor; if (basePropertyFlags && derivedPropertyFlags) { // property/accessor is overridden with property/accessor - if (!(baseDeclarationFlags & ModifierFlags.Abstract) && basePropertyFlags !== SymbolFlags.Property && derivedPropertyFlags === SymbolFlags.Property) { + if (baseDeclarationFlags & ModifierFlags.Abstract + || getObjectFlags(getTargetType(baseType)) & ObjectFlags.Interface) { + // when the base property is abstract or from an interface, base/derived flags don't need to match + continue; + } + if (basePropertyFlags !== SymbolFlags.Property && derivedPropertyFlags === SymbolFlags.Property) { errorMessage = Diagnostics.Class_0_defines_instance_member_accessor_1_but_extended_class_2_defines_it_as_instance_member_property; } - else if (!(baseDeclarationFlags & ModifierFlags.Abstract) && basePropertyFlags === SymbolFlags.Property && derivedPropertyFlags !== SymbolFlags.Property) { + else if (basePropertyFlags === SymbolFlags.Property && derivedPropertyFlags !== SymbolFlags.Property) { errorMessage = Diagnostics.Class_0_defines_instance_member_property_1_but_extended_class_2_defines_it_as_instance_member_accessor; } else { @@ -29534,7 +29535,11 @@ namespace ts { } } else if (isPrototypeProperty(base)) { - if (derived.flags & SymbolFlags.Accessor) { + if (isPrototypeProperty(derived)) { + // method is overridden with method -- correct case + continue; + } + else if (derived.flags & SymbolFlags.Accessor) { errorMessage = Diagnostics.Class_0_defines_instance_member_function_1_but_extended_class_2_defines_it_as_instance_member_accessor; } else { diff --git a/tests/baselines/reference/accessorsOverrideMethod.errors.txt b/tests/baselines/reference/accessorsOverrideMethod.errors.txt new file mode 100644 index 0000000000000..2ff047d49be36 --- /dev/null +++ b/tests/baselines/reference/accessorsOverrideMethod.errors.txt @@ -0,0 +1,13 @@ +tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideMethod.ts(5,9): error TS2423: Class 'A' defines instance member function 'm', but extended class 'B' defines it as instance member accessor. + + +==== tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideMethod.ts (1 errors) ==== + class A { + m() { } + } + class B extends A { + get m() { return () => 1 } + ~ +!!! error TS2423: Class 'A' defines instance member function 'm', but extended class 'B' defines it as instance member accessor. + } + \ No newline at end of file diff --git a/tests/baselines/reference/accessorsOverrideMethod.js b/tests/baselines/reference/accessorsOverrideMethod.js new file mode 100644 index 0000000000000..0b7d62391909b --- /dev/null +++ b/tests/baselines/reference/accessorsOverrideMethod.js @@ -0,0 +1,16 @@ +//// [accessorsOverrideMethod.ts] +class A { + m() { } +} +class B extends A { + get m() { return () => 1 } +} + + +//// [accessorsOverrideMethod.js] +class A { + m() { } +} +class B extends A { + get m() { return () => 1; } +} diff --git a/tests/baselines/reference/accessorsOverrideMethod.symbols b/tests/baselines/reference/accessorsOverrideMethod.symbols new file mode 100644 index 0000000000000..d447c137acff4 --- /dev/null +++ b/tests/baselines/reference/accessorsOverrideMethod.symbols @@ -0,0 +1,15 @@ +=== tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideMethod.ts === +class A { +>A : Symbol(A, Decl(accessorsOverrideMethod.ts, 0, 0)) + + m() { } +>m : Symbol(A.m, Decl(accessorsOverrideMethod.ts, 0, 9)) +} +class B extends A { +>B : Symbol(B, Decl(accessorsOverrideMethod.ts, 2, 1)) +>A : Symbol(A, Decl(accessorsOverrideMethod.ts, 0, 0)) + + get m() { return () => 1 } +>m : Symbol(B.m, Decl(accessorsOverrideMethod.ts, 3, 19)) +} + diff --git a/tests/baselines/reference/accessorsOverrideMethod.types b/tests/baselines/reference/accessorsOverrideMethod.types new file mode 100644 index 0000000000000..a8781ae41a99b --- /dev/null +++ b/tests/baselines/reference/accessorsOverrideMethod.types @@ -0,0 +1,17 @@ +=== tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideMethod.ts === +class A { +>A : A + + m() { } +>m : () => void +} +class B extends A { +>B : B +>A : A + + get m() { return () => 1 } +>m : () => number +>() => 1 : () => number +>1 : 1 +} + diff --git a/tests/baselines/reference/checkJsFiles_noErrorLocation.errors.txt b/tests/baselines/reference/checkJsFiles_noErrorLocation.errors.txt new file mode 100644 index 0000000000000..d9104608284a9 --- /dev/null +++ b/tests/baselines/reference/checkJsFiles_noErrorLocation.errors.txt @@ -0,0 +1,25 @@ +tests/cases/compiler/a.js(14,10): error TS2424: Class 'A' defines instance member function 'foo', but extended class 'B' defines it as instance member property. + + +==== tests/cases/compiler/a.js (1 errors) ==== + // @ts-check + class A { + constructor() { + + } + foo() { + return 4; + } + } + + class B extends A { + constructor() { + super(); + this.foo = () => 3; + ~~~ +!!! error TS2424: Class 'A' defines instance member function 'foo', but extended class 'B' defines it as instance member property. + } + } + + const i = new B(); + i.foo(); \ No newline at end of file diff --git a/tests/baselines/reference/inheritanceMemberAccessorOverridingMethod.errors.txt b/tests/baselines/reference/inheritanceMemberAccessorOverridingMethod.errors.txt new file mode 100644 index 0000000000000..52ae20032e628 --- /dev/null +++ b/tests/baselines/reference/inheritanceMemberAccessorOverridingMethod.errors.txt @@ -0,0 +1,20 @@ +tests/cases/compiler/inheritanceMemberAccessorOverridingMethod.ts(8,9): error TS2423: Class 'a' defines instance member function 'x', but extended class 'b' defines it as instance member accessor. + + +==== tests/cases/compiler/inheritanceMemberAccessorOverridingMethod.ts (1 errors) ==== + class a { + x() { + return "20"; + } + } + + class b extends a { + get x() { + ~ +!!! error TS2423: Class 'a' defines instance member function 'x', but extended class 'b' defines it as instance member accessor. + return () => "20"; + } + set x(aValue) { + + } + } \ No newline at end of file diff --git a/tests/baselines/reference/inheritanceMemberPropertyOverridingMethod.errors.txt b/tests/baselines/reference/inheritanceMemberPropertyOverridingMethod.errors.txt new file mode 100644 index 0000000000000..2b56866b22b33 --- /dev/null +++ b/tests/baselines/reference/inheritanceMemberPropertyOverridingMethod.errors.txt @@ -0,0 +1,15 @@ +tests/cases/compiler/inheritanceMemberPropertyOverridingMethod.ts(8,5): error TS2424: Class 'a' defines instance member function 'x', but extended class 'b' defines it as instance member property. + + +==== tests/cases/compiler/inheritanceMemberPropertyOverridingMethod.ts (1 errors) ==== + class a { + x() { + return "20"; + } + } + + class b extends a { + x: () => string; + ~ +!!! error TS2424: Class 'a' defines instance member function 'x', but extended class 'b' defines it as instance member property. + } \ No newline at end of file diff --git a/tests/baselines/reference/overrideInterfaceProperty.js b/tests/baselines/reference/overrideInterfaceProperty.js new file mode 100644 index 0000000000000..0c1029b0c1129 --- /dev/null +++ b/tests/baselines/reference/overrideInterfaceProperty.js @@ -0,0 +1,31 @@ +//// [overrideInterfaceProperty.ts] +interface Mup { + readonly size: number; +} +interface MupConstructor { + new(): Mup; + new(entries?: readonly (readonly [K, V])[] | null): Mup; + readonly prototype: Mup; +} +declare var Mup: MupConstructor; + +class Sizz extends Mup { + // ok, because Mup is an interface + get size() { return 0 } +} +class Kasizz extends Mup { + size = -1 +} + + +//// [overrideInterfaceProperty.js] +class Sizz extends Mup { + // ok, because Mup is an interface + get size() { return 0; } +} +class Kasizz extends Mup { + constructor() { + super(...arguments); + this.size = -1; + } +} diff --git a/tests/baselines/reference/overrideInterfaceProperty.symbols b/tests/baselines/reference/overrideInterfaceProperty.symbols new file mode 100644 index 0000000000000..37f0f99a1070a --- /dev/null +++ b/tests/baselines/reference/overrideInterfaceProperty.symbols @@ -0,0 +1,49 @@ +=== tests/cases/conformance/classes/propertyMemberDeclarations/overrideInterfaceProperty.ts === +interface Mup { +>Mup : Symbol(Mup, Decl(overrideInterfaceProperty.ts, 0, 0), Decl(overrideInterfaceProperty.ts, 8, 11)) +>K : Symbol(K, Decl(overrideInterfaceProperty.ts, 0, 14)) +>V : Symbol(V, Decl(overrideInterfaceProperty.ts, 0, 16)) + + readonly size: number; +>size : Symbol(Mup.size, Decl(overrideInterfaceProperty.ts, 0, 21)) +} +interface MupConstructor { +>MupConstructor : Symbol(MupConstructor, Decl(overrideInterfaceProperty.ts, 2, 1)) + + new(): Mup; +>Mup : Symbol(Mup, Decl(overrideInterfaceProperty.ts, 0, 0), Decl(overrideInterfaceProperty.ts, 8, 11)) + + new(entries?: readonly (readonly [K, V])[] | null): Mup; +>K : Symbol(K, Decl(overrideInterfaceProperty.ts, 5, 8)) +>V : Symbol(V, Decl(overrideInterfaceProperty.ts, 5, 10)) +>entries : Symbol(entries, Decl(overrideInterfaceProperty.ts, 5, 14)) +>K : Symbol(K, Decl(overrideInterfaceProperty.ts, 5, 8)) +>V : Symbol(V, Decl(overrideInterfaceProperty.ts, 5, 10)) +>Mup : Symbol(Mup, Decl(overrideInterfaceProperty.ts, 0, 0), Decl(overrideInterfaceProperty.ts, 8, 11)) +>K : Symbol(K, Decl(overrideInterfaceProperty.ts, 5, 8)) +>V : Symbol(V, Decl(overrideInterfaceProperty.ts, 5, 10)) + + readonly prototype: Mup; +>prototype : Symbol(MupConstructor.prototype, Decl(overrideInterfaceProperty.ts, 5, 72)) +>Mup : Symbol(Mup, Decl(overrideInterfaceProperty.ts, 0, 0), Decl(overrideInterfaceProperty.ts, 8, 11)) +} +declare var Mup: MupConstructor; +>Mup : Symbol(Mup, Decl(overrideInterfaceProperty.ts, 0, 0), Decl(overrideInterfaceProperty.ts, 8, 11)) +>MupConstructor : Symbol(MupConstructor, Decl(overrideInterfaceProperty.ts, 2, 1)) + +class Sizz extends Mup { +>Sizz : Symbol(Sizz, Decl(overrideInterfaceProperty.ts, 8, 32)) +>Mup : Symbol(Mup, Decl(overrideInterfaceProperty.ts, 0, 0), Decl(overrideInterfaceProperty.ts, 8, 11)) + + // ok, because Mup is an interface + get size() { return 0 } +>size : Symbol(Sizz.size, Decl(overrideInterfaceProperty.ts, 10, 24)) +} +class Kasizz extends Mup { +>Kasizz : Symbol(Kasizz, Decl(overrideInterfaceProperty.ts, 13, 1)) +>Mup : Symbol(Mup, Decl(overrideInterfaceProperty.ts, 0, 0), Decl(overrideInterfaceProperty.ts, 8, 11)) + + size = -1 +>size : Symbol(Kasizz.size, Decl(overrideInterfaceProperty.ts, 14, 26)) +} + diff --git a/tests/baselines/reference/overrideInterfaceProperty.types b/tests/baselines/reference/overrideInterfaceProperty.types new file mode 100644 index 0000000000000..69bf70e7358d5 --- /dev/null +++ b/tests/baselines/reference/overrideInterfaceProperty.types @@ -0,0 +1,36 @@ +=== tests/cases/conformance/classes/propertyMemberDeclarations/overrideInterfaceProperty.ts === +interface Mup { + readonly size: number; +>size : number +} +interface MupConstructor { + new(): Mup; + new(entries?: readonly (readonly [K, V])[] | null): Mup; +>entries : readonly (readonly [K, V])[] +>null : null + + readonly prototype: Mup; +>prototype : Mup +} +declare var Mup: MupConstructor; +>Mup : MupConstructor + +class Sizz extends Mup { +>Sizz : Sizz +>Mup : Mup + + // ok, because Mup is an interface + get size() { return 0 } +>size : number +>0 : 0 +} +class Kasizz extends Mup { +>Kasizz : Kasizz +>Mup : Mup + + size = -1 +>size : number +>-1 : -1 +>1 : 1 +} + diff --git a/tests/baselines/reference/propertyOverridesMethod.errors.txt b/tests/baselines/reference/propertyOverridesMethod.errors.txt new file mode 100644 index 0000000000000..aaee2d48cf658 --- /dev/null +++ b/tests/baselines/reference/propertyOverridesMethod.errors.txt @@ -0,0 +1,13 @@ +tests/cases/conformance/classes/propertyMemberDeclarations/propertyOverridesMethod.ts(5,5): error TS2424: Class 'A' defines instance member function 'm', but extended class 'B' defines it as instance member property. + + +==== tests/cases/conformance/classes/propertyMemberDeclarations/propertyOverridesMethod.ts (1 errors) ==== + class A { + m() { } + } + class B extends A { + m = () => 1 + ~ +!!! error TS2424: Class 'A' defines instance member function 'm', but extended class 'B' defines it as instance member property. + } + \ No newline at end of file diff --git a/tests/baselines/reference/propertyOverridesMethod.js b/tests/baselines/reference/propertyOverridesMethod.js new file mode 100644 index 0000000000000..f51fb16653527 --- /dev/null +++ b/tests/baselines/reference/propertyOverridesMethod.js @@ -0,0 +1,19 @@ +//// [propertyOverridesMethod.ts] +class A { + m() { } +} +class B extends A { + m = () => 1 +} + + +//// [propertyOverridesMethod.js] +class A { + m() { } +} +class B extends A { + constructor() { + super(...arguments); + this.m = () => 1; + } +} diff --git a/tests/baselines/reference/propertyOverridesMethod.symbols b/tests/baselines/reference/propertyOverridesMethod.symbols new file mode 100644 index 0000000000000..960aab6cb5612 --- /dev/null +++ b/tests/baselines/reference/propertyOverridesMethod.symbols @@ -0,0 +1,15 @@ +=== tests/cases/conformance/classes/propertyMemberDeclarations/propertyOverridesMethod.ts === +class A { +>A : Symbol(A, Decl(propertyOverridesMethod.ts, 0, 0)) + + m() { } +>m : Symbol(A.m, Decl(propertyOverridesMethod.ts, 0, 9)) +} +class B extends A { +>B : Symbol(B, Decl(propertyOverridesMethod.ts, 2, 1)) +>A : Symbol(A, Decl(propertyOverridesMethod.ts, 0, 0)) + + m = () => 1 +>m : Symbol(B.m, Decl(propertyOverridesMethod.ts, 3, 19)) +} + diff --git a/tests/baselines/reference/propertyOverridesMethod.types b/tests/baselines/reference/propertyOverridesMethod.types new file mode 100644 index 0000000000000..13fcda01a853d --- /dev/null +++ b/tests/baselines/reference/propertyOverridesMethod.types @@ -0,0 +1,17 @@ +=== tests/cases/conformance/classes/propertyMemberDeclarations/propertyOverridesMethod.ts === +class A { +>A : A + + m() { } +>m : () => void +} +class B extends A { +>B : B +>A : A + + m = () => 1 +>m : () => number +>() => 1 : () => number +>1 : 1 +} + diff --git a/tests/baselines/reference/propertyOverridingPrototype.errors.txt b/tests/baselines/reference/propertyOverridingPrototype.errors.txt new file mode 100644 index 0000000000000..a585f7999f603 --- /dev/null +++ b/tests/baselines/reference/propertyOverridingPrototype.errors.txt @@ -0,0 +1,16 @@ +tests/cases/compiler/propertyOverridingPrototype.ts(7,5): error TS2424: Class 'Base' defines instance member function 'foo', but extended class 'Derived' defines it as instance member property. + + +==== tests/cases/compiler/propertyOverridingPrototype.ts (1 errors) ==== + class Base { + foo() { + } + } + + class Derived extends Base { + foo: () => { }; + ~~~ +!!! error TS2424: Class 'Base' defines instance member function 'foo', but extended class 'Derived' defines it as instance member property. + } + + \ No newline at end of file diff --git a/tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideMethod.ts b/tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideMethod.ts new file mode 100644 index 0000000000000..c06dd5d91a970 --- /dev/null +++ b/tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideMethod.ts @@ -0,0 +1,7 @@ +// @target: esnext +class A { + m() { } +} +class B extends A { + get m() { return () => 1 } +} diff --git a/tests/cases/conformance/classes/propertyMemberDeclarations/overrideInterfaceProperty.ts b/tests/cases/conformance/classes/propertyMemberDeclarations/overrideInterfaceProperty.ts new file mode 100644 index 0000000000000..8b70357515cd2 --- /dev/null +++ b/tests/cases/conformance/classes/propertyMemberDeclarations/overrideInterfaceProperty.ts @@ -0,0 +1,18 @@ +// @target: esnext +interface Mup { + readonly size: number; +} +interface MupConstructor { + new(): Mup; + new(entries?: readonly (readonly [K, V])[] | null): Mup; + readonly prototype: Mup; +} +declare var Mup: MupConstructor; + +class Sizz extends Mup { + // ok, because Mup is an interface + get size() { return 0 } +} +class Kasizz extends Mup { + size = -1 +} diff --git a/tests/cases/conformance/classes/propertyMemberDeclarations/propertyOverridesMethod.ts b/tests/cases/conformance/classes/propertyMemberDeclarations/propertyOverridesMethod.ts new file mode 100644 index 0000000000000..9700f838663ec --- /dev/null +++ b/tests/cases/conformance/classes/propertyMemberDeclarations/propertyOverridesMethod.ts @@ -0,0 +1,7 @@ +// @target: esnext +class A { + m() { } +} +class B extends A { + m = () => 1 +} From 58e17462045651933fce591f1579f519b2750f4c Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Thu, 19 Sep 2019 07:40:34 -0700 Subject: [PATCH 3/6] Ignore this-property assignments --- src/compiler/checker.ts | 4 ++- .../thisPropertyOverridesAccessors.symbols | 28 ++++++++++++++++ .../thisPropertyOverridesAccessors.types | 32 +++++++++++++++++++ .../thisPropertyOverridesAccessors.ts | 17 ++++++++++ 4 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/thisPropertyOverridesAccessors.symbols create mode 100644 tests/baselines/reference/thisPropertyOverridesAccessors.types create mode 100644 tests/cases/conformance/classes/propertyMemberDeclarations/thisPropertyOverridesAccessors.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index e38b631df4f9c..a2f69261c3c84 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -29519,8 +29519,10 @@ namespace ts { if (basePropertyFlags && derivedPropertyFlags) { // property/accessor is overridden with property/accessor if (baseDeclarationFlags & ModifierFlags.Abstract - || getObjectFlags(getTargetType(baseType)) & ObjectFlags.Interface) { + || getObjectFlags(getTargetType(baseType)) & ObjectFlags.Interface + || derived.valueDeclaration && isBinaryExpression(derived.valueDeclaration)) { // when the base property is abstract or from an interface, base/derived flags don't need to match + // same when the derived property is from an assignment continue; } if (basePropertyFlags !== SymbolFlags.Property && derivedPropertyFlags === SymbolFlags.Property) { diff --git a/tests/baselines/reference/thisPropertyOverridesAccessors.symbols b/tests/baselines/reference/thisPropertyOverridesAccessors.symbols new file mode 100644 index 0000000000000..40cec9f184709 --- /dev/null +++ b/tests/baselines/reference/thisPropertyOverridesAccessors.symbols @@ -0,0 +1,28 @@ +=== tests/cases/conformance/classes/propertyMemberDeclarations/foo.ts === +class Foo { +>Foo : Symbol(Foo, Decl(foo.ts, 0, 0)) + + get p() { return 1 } +>p : Symbol(Foo.p, Decl(foo.ts, 0, 11), Decl(foo.ts, 1, 24)) + + set p(value) { } +>p : Symbol(Foo.p, Decl(foo.ts, 0, 11), Decl(foo.ts, 1, 24)) +>value : Symbol(value, Decl(foo.ts, 2, 10)) +} + +=== tests/cases/conformance/classes/propertyMemberDeclarations/bar.js === +class Bar extends Foo { +>Bar : Symbol(Bar, Decl(bar.js, 0, 0)) +>Foo : Symbol(Foo, Decl(foo.ts, 0, 0)) + + constructor() { + super() +>super : Symbol(Foo, Decl(foo.ts, 0, 0)) + + this.p = 2 +>this.p : Symbol(Bar.p, Decl(bar.js, 2, 15)) +>this : Symbol(Bar, Decl(bar.js, 0, 0)) +>p : Symbol(Bar.p, Decl(bar.js, 2, 15)) + } +} + diff --git a/tests/baselines/reference/thisPropertyOverridesAccessors.types b/tests/baselines/reference/thisPropertyOverridesAccessors.types new file mode 100644 index 0000000000000..c242351dbd2b2 --- /dev/null +++ b/tests/baselines/reference/thisPropertyOverridesAccessors.types @@ -0,0 +1,32 @@ +=== tests/cases/conformance/classes/propertyMemberDeclarations/foo.ts === +class Foo { +>Foo : Foo + + get p() { return 1 } +>p : number +>1 : 1 + + set p(value) { } +>p : number +>value : number +} + +=== tests/cases/conformance/classes/propertyMemberDeclarations/bar.js === +class Bar extends Foo { +>Bar : Bar +>Foo : Foo + + constructor() { + super() +>super() : void +>super : typeof Foo + + this.p = 2 +>this.p = 2 : 2 +>this.p : number +>this : this +>p : number +>2 : 2 + } +} + diff --git a/tests/cases/conformance/classes/propertyMemberDeclarations/thisPropertyOverridesAccessors.ts b/tests/cases/conformance/classes/propertyMemberDeclarations/thisPropertyOverridesAccessors.ts new file mode 100644 index 0000000000000..779d326fa6f3b --- /dev/null +++ b/tests/cases/conformance/classes/propertyMemberDeclarations/thisPropertyOverridesAccessors.ts @@ -0,0 +1,17 @@ +// @target: esnext +// @allowjs: true +// @noemit: true +// @checkjs: true +// @Filename: foo.ts +class Foo { + get p() { return 1 } + set p(value) { } +} + +// @Filename: bar.js +class Bar extends Foo { + constructor() { + super() + this.p = 2 + } +} From 832d51f62981c23fcf66d6ac67cf44dfb86e5d81 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Thu, 19 Sep 2019 10:28:06 -0700 Subject: [PATCH 4/6] Fix base-in-interface check --- src/compiler/checker.ts | 3 ++- .../reference/accessorsOverrideProperty5.js | 19 ++++++++++++++ .../accessorsOverrideProperty5.symbols | 26 +++++++++++++++++++ .../accessorsOverrideProperty5.types | 22 ++++++++++++++++ .../accessorsOverrideProperty5.ts | 10 +++++++ 5 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/accessorsOverrideProperty5.js create mode 100644 tests/baselines/reference/accessorsOverrideProperty5.symbols create mode 100644 tests/baselines/reference/accessorsOverrideProperty5.types create mode 100644 tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty5.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a2f69261c3c84..11291fb869369 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -29518,8 +29518,9 @@ namespace ts { const derivedPropertyFlags = derived.flags & SymbolFlags.PropertyOrAccessor; if (basePropertyFlags && derivedPropertyFlags) { // property/accessor is overridden with property/accessor + const baseParent = getParentOfSymbol(base); if (baseDeclarationFlags & ModifierFlags.Abstract - || getObjectFlags(getTargetType(baseType)) & ObjectFlags.Interface + || baseParent && baseParent.flags & SymbolFlags.Interface || derived.valueDeclaration && isBinaryExpression(derived.valueDeclaration)) { // when the base property is abstract or from an interface, base/derived flags don't need to match // same when the derived property is from an assignment diff --git a/tests/baselines/reference/accessorsOverrideProperty5.js b/tests/baselines/reference/accessorsOverrideProperty5.js new file mode 100644 index 0000000000000..fb7cee0630b67 --- /dev/null +++ b/tests/baselines/reference/accessorsOverrideProperty5.js @@ -0,0 +1,19 @@ +//// [accessorsOverrideProperty5.ts] +interface I { + p: number +} +interface B extends I { } +class B { } +class C extends B { + get p() { return 1 } + set p(value) { } +} + + +//// [accessorsOverrideProperty5.js] +class B { +} +class C extends B { + get p() { return 1; } + set p(value) { } +} diff --git a/tests/baselines/reference/accessorsOverrideProperty5.symbols b/tests/baselines/reference/accessorsOverrideProperty5.symbols new file mode 100644 index 0000000000000..b048d8bbc928d --- /dev/null +++ b/tests/baselines/reference/accessorsOverrideProperty5.symbols @@ -0,0 +1,26 @@ +=== tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty5.ts === +interface I { +>I : Symbol(I, Decl(accessorsOverrideProperty5.ts, 0, 0)) + + p: number +>p : Symbol(I.p, Decl(accessorsOverrideProperty5.ts, 0, 13)) +} +interface B extends I { } +>B : Symbol(B, Decl(accessorsOverrideProperty5.ts, 2, 1), Decl(accessorsOverrideProperty5.ts, 3, 25)) +>I : Symbol(I, Decl(accessorsOverrideProperty5.ts, 0, 0)) + +class B { } +>B : Symbol(B, Decl(accessorsOverrideProperty5.ts, 2, 1), Decl(accessorsOverrideProperty5.ts, 3, 25)) + +class C extends B { +>C : Symbol(C, Decl(accessorsOverrideProperty5.ts, 4, 11)) +>B : Symbol(B, Decl(accessorsOverrideProperty5.ts, 2, 1), Decl(accessorsOverrideProperty5.ts, 3, 25)) + + get p() { return 1 } +>p : Symbol(C.p, Decl(accessorsOverrideProperty5.ts, 5, 19), Decl(accessorsOverrideProperty5.ts, 6, 24)) + + set p(value) { } +>p : Symbol(C.p, Decl(accessorsOverrideProperty5.ts, 5, 19), Decl(accessorsOverrideProperty5.ts, 6, 24)) +>value : Symbol(value, Decl(accessorsOverrideProperty5.ts, 7, 10)) +} + diff --git a/tests/baselines/reference/accessorsOverrideProperty5.types b/tests/baselines/reference/accessorsOverrideProperty5.types new file mode 100644 index 0000000000000..2032d3fa6ae50 --- /dev/null +++ b/tests/baselines/reference/accessorsOverrideProperty5.types @@ -0,0 +1,22 @@ +=== tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty5.ts === +interface I { + p: number +>p : number +} +interface B extends I { } +class B { } +>B : B + +class C extends B { +>C : C +>B : B + + get p() { return 1 } +>p : number +>1 : 1 + + set p(value) { } +>p : number +>value : number +} + diff --git a/tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty5.ts b/tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty5.ts new file mode 100644 index 0000000000000..3bf85e9ddd2c1 --- /dev/null +++ b/tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty5.ts @@ -0,0 +1,10 @@ +// @target: esnext +interface I { + p: number +} +interface B extends I { } +class B { } +class C extends B { + get p() { return 1 } + set p(value) { } +} From 6ec445f9d512e63b8f3d76de7eb73235b1bdec40 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Thu, 19 Sep 2019 12:46:20 -0700 Subject: [PATCH 5/6] Fix check --- src/compiler/checker.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 11291fb869369..03365d106e638 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -29518,9 +29518,8 @@ namespace ts { const derivedPropertyFlags = derived.flags & SymbolFlags.PropertyOrAccessor; if (basePropertyFlags && derivedPropertyFlags) { // property/accessor is overridden with property/accessor - const baseParent = getParentOfSymbol(base); if (baseDeclarationFlags & ModifierFlags.Abstract - || baseParent && baseParent.flags & SymbolFlags.Interface + || base.valueDeclaration && base.valueDeclaration.parent.kind === SyntaxKind.InterfaceDeclaration || derived.valueDeclaration && isBinaryExpression(derived.valueDeclaration)) { // when the base property is abstract or from an interface, base/derived flags don't need to match // same when the derived property is from an assignment From c283574123686bba0e860fe2818b29050b244d74 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Thu, 19 Sep 2019 14:04:25 -0700 Subject: [PATCH 6/6] Fix new errors in services --- src/services/services.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/services/services.ts b/src/services/services.ts index 644629ce2af4f..ebf63d246a6e2 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -339,7 +339,6 @@ namespace ts { } class TokenObject extends TokenOrIdentifierObject implements Token { - public symbol!: Symbol; public kind: TKind; constructor(kind: TKind, pos: number, end: number) { @@ -349,9 +348,8 @@ namespace ts { } class IdentifierObject extends TokenOrIdentifierObject implements Identifier { - public kind!: SyntaxKind.Identifier; + public kind: SyntaxKind.Identifier = SyntaxKind.Identifier; public escapedText!: __String; - public symbol!: Symbol; public autoGenerateFlags!: GeneratedIdentifierFlags; _primaryExpressionBrand: any; _memberExpressionBrand: any; @@ -541,7 +539,7 @@ namespace ts { } class SourceFileObject extends NodeObject implements SourceFile { - public kind!: SyntaxKind.SourceFile; + public kind: SyntaxKind.SourceFile = SyntaxKind.SourceFile; public _declarationBrand: any; public fileName!: string; public path!: Path;