fix(45345): throw an error on overridden member that is defined in multiple interfaces (#45352)

This commit is contained in:
Oleksandr T 2021-08-10 21:50:22 +03:00 committed by GitHub
parent 68eb1a551f
commit ad894f74b3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 293 additions and 2 deletions

View file

@ -37687,8 +37687,8 @@ namespace ts {
error(member, Diagnostics.This_member_cannot_have_an_override_modifier_because_it_is_not_declared_in_the_base_class_0_Did_you_mean_1, baseClassName, symbolToString(suggestion)) :
error(member, Diagnostics.This_member_cannot_have_an_override_modifier_because_it_is_not_declared_in_the_base_class_0, baseClassName);
}
else if (prop && baseProp?.valueDeclaration && compilerOptions.noImplicitOverride && !nodeInAmbientContext) {
const baseHasAbstract = hasAbstractModifier(baseProp.valueDeclaration);
else if (prop && baseProp?.declarations && compilerOptions.noImplicitOverride && !nodeInAmbientContext) {
const baseHasAbstract = some(baseProp.declarations, hasAbstractModifier);
if (hasOverride) {
return;
}

View file

@ -0,0 +1,41 @@
tests/cases/conformance/override/override20.ts(25,5): error TS4114: This member must have an 'override' modifier because it overrides a member in the base class 'I1 & I2'.
tests/cases/conformance/override/override20.ts(28,5): error TS4114: This member must have an 'override' modifier because it overrides a member in the base class 'I1 & I2'.
==== tests/cases/conformance/override/override20.ts (2 errors) ====
const Foo: C1 & C2 =
class {
m1() { }
m2() { }
}
interface I1 {
m1(): void;
}
interface I2 {
m1(): void;
m2(): void;
}
interface C1 {
new(...args: any[]): I1;
}
interface C2 {
new(...args: any[]): I2;
}
export class Bar extends Foo {
m1() {
~~
!!! error TS4114: This member must have an 'override' modifier because it overrides a member in the base class 'I1 & I2'.
super.m1();
}
m2() {
~~
!!! error TS4114: This member must have an 'override' modifier because it overrides a member in the base class 'I1 & I2'.
super.m2();
}
}

View file

@ -0,0 +1,47 @@
//// [override20.ts]
const Foo: C1 & C2 =
class {
m1() { }
m2() { }
}
interface I1 {
m1(): void;
}
interface I2 {
m1(): void;
m2(): void;
}
interface C1 {
new(...args: any[]): I1;
}
interface C2 {
new(...args: any[]): I2;
}
export class Bar extends Foo {
m1() {
super.m1();
}
m2() {
super.m2();
}
}
//// [override20.js]
const Foo = class {
m1() { }
m2() { }
};
export class Bar extends Foo {
m1() {
super.m1();
}
m2() {
super.m2();
}
}

View file

@ -0,0 +1,67 @@
=== tests/cases/conformance/override/override20.ts ===
const Foo: C1 & C2 =
>Foo : Symbol(Foo, Decl(override20.ts, 0, 5))
>C1 : Symbol(C1, Decl(override20.ts, 13, 1))
>C2 : Symbol(C2, Decl(override20.ts, 17, 1))
class {
m1() { }
>m1 : Symbol(Foo.m1, Decl(override20.ts, 1, 11))
m2() { }
>m2 : Symbol(Foo.m2, Decl(override20.ts, 2, 16))
}
interface I1 {
>I1 : Symbol(I1, Decl(override20.ts, 4, 5))
m1(): void;
>m1 : Symbol(I1.m1, Decl(override20.ts, 6, 14))
}
interface I2 {
>I2 : Symbol(I2, Decl(override20.ts, 8, 1))
m1(): void;
>m1 : Symbol(I2.m1, Decl(override20.ts, 10, 14))
m2(): void;
>m2 : Symbol(I2.m2, Decl(override20.ts, 11, 15))
}
interface C1 {
>C1 : Symbol(C1, Decl(override20.ts, 13, 1))
new(...args: any[]): I1;
>args : Symbol(args, Decl(override20.ts, 16, 8))
>I1 : Symbol(I1, Decl(override20.ts, 4, 5))
}
interface C2 {
>C2 : Symbol(C2, Decl(override20.ts, 17, 1))
new(...args: any[]): I2;
>args : Symbol(args, Decl(override20.ts, 20, 8))
>I2 : Symbol(I2, Decl(override20.ts, 8, 1))
}
export class Bar extends Foo {
>Bar : Symbol(Bar, Decl(override20.ts, 21, 1))
>Foo : Symbol(Foo, Decl(override20.ts, 0, 5))
m1() {
>m1 : Symbol(Bar.m1, Decl(override20.ts, 23, 30))
super.m1();
>super.m1 : Symbol(m1, Decl(override20.ts, 6, 14), Decl(override20.ts, 10, 14))
>m1 : Symbol(m1, Decl(override20.ts, 6, 14), Decl(override20.ts, 10, 14))
}
m2() {
>m2 : Symbol(Bar.m2, Decl(override20.ts, 26, 5))
super.m2();
>super.m2 : Symbol(I2.m2, Decl(override20.ts, 11, 15))
>m2 : Symbol(I2.m2, Decl(override20.ts, 11, 15))
}
}

View file

@ -0,0 +1,61 @@
=== tests/cases/conformance/override/override20.ts ===
const Foo: C1 & C2 =
>Foo : C1 & C2
class {
>class { m1() { } m2() { } } : typeof Foo
m1() { }
>m1 : () => void
m2() { }
>m2 : () => void
}
interface I1 {
m1(): void;
>m1 : () => void
}
interface I2 {
m1(): void;
>m1 : () => void
m2(): void;
>m2 : () => void
}
interface C1 {
new(...args: any[]): I1;
>args : any[]
}
interface C2 {
new(...args: any[]): I2;
>args : any[]
}
export class Bar extends Foo {
>Bar : Bar
>Foo : I1 & I2
m1() {
>m1 : () => void
super.m1();
>super.m1() : void
>super.m1 : (() => void) & (() => void)
>super : I1 & I2
>m1 : (() => void) & (() => void)
}
m2() {
>m2 : () => void
super.m2();
>super.m2() : void
>super.m2 : () => void
>super : I1 & I2
>m2 : () => void
}
}

View file

@ -0,0 +1,34 @@
// @target: esnext
// @noImplicitOverride: true
const Foo: C1 & C2 =
class {
m1() { }
m2() { }
}
interface I1 {
m1(): void;
}
interface I2 {
m1(): void;
m2(): void;
}
interface C1 {
new(...args: any[]): I1;
}
interface C2 {
new(...args: any[]): I2;
}
export class Bar extends Foo {
m1() {
super.m1();
}
m2() {
super.m2();
}
}

View file

@ -0,0 +1,41 @@
/// <reference path='fourslash.ts' />
// @noImplicitOverride: true
////const Foo: C1 & C2 =
//// class {
//// m1() { }
//// m2() { }
//// }
////
////interface I1 {
//// m1(): void;
////}
////
////interface I2 {
//// m1(): void;
//// m2(): void;
////}
////
////interface C1 {
//// new(...args: any[]): I1;
////}
////
////interface C2 {
//// new(...args: any[]): I2;
////}
////
////class Bar extends Foo {
//// [|m1()|] {
//// super.m1();
//// }
//// m2() {
//// super.m2();
//// }
////}
verify.codeFix({
description: "Add 'override' modifier",
newRangeContent: "override m1()",
index: 0
})