Wire up 'writing' parameter through protected derived class detection (#43455)

Fixes #43443
This commit is contained in:
Ryan Cavanaugh 2021-04-19 09:20:21 -07:00 committed by GitHub
parent e4e96c3399
commit b1ab2b98be
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 436 additions and 3 deletions

View File

@ -19676,8 +19676,8 @@ namespace ts {
// Return true if the given class derives from each of the declaring classes of the protected
// constituents of the given property.
function isClassDerivedFromDeclaringClasses(checkClass: Type, prop: Symbol) {
return forEachProperty(prop, p => getDeclarationModifierFlagsFromSymbol(p) & ModifierFlags.Protected ?
function isClassDerivedFromDeclaringClasses(checkClass: Type, prop: Symbol, writing: boolean) {
return forEachProperty(prop, p => getDeclarationModifierFlagsFromSymbol(p, writing) & ModifierFlags.Protected ?
!hasBaseType(checkClass, getDeclaringClass(p)) : false) ? undefined : checkClass;
}
@ -26907,7 +26907,7 @@ namespace ts {
// of the property as base classes
let enclosingClass = forEachEnclosingClass(node, enclosingDeclaration => {
const enclosingClass = <InterfaceType>getDeclaredTypeOfSymbol(getSymbolOfNode(enclosingDeclaration)!);
return isClassDerivedFromDeclaringClasses(enclosingClass, prop) ? enclosingClass : undefined;
return isClassDerivedFromDeclaringClasses(enclosingClass, prop, writing) ? enclosingClass : undefined;
});
// A protected property is accessible if the property is within the declaring class or classes derived from it
if (!enclosingClass) {

View File

@ -0,0 +1,45 @@
tests/cases/compiler/publicGetterProtectedSetterFromThisParameter.ts(33,7): error TS2446: Property 'q' is protected and only accessible through an instance of class 'A'. This is an instance of class 'B'.
tests/cases/compiler/publicGetterProtectedSetterFromThisParameter.ts(34,7): error TS2446: Property 'u' is protected and only accessible through an instance of class 'A'. This is an instance of class 'B'.
==== tests/cases/compiler/publicGetterProtectedSetterFromThisParameter.ts (2 errors) ====
class A {
get x() { return 0; }
protected set x(v: number) { }
public get y() { return 0; }
protected set y(v: number) { }
}
class B {
get q() { return 0; }
protected set q(v: number) { }
protected get u() { return 0; }
protected set u(v: number) { }
foo(this: A, a: A, b: B) {
// Should have no errors in this block
this.x = 0;
this.y = 0;
a.x = 0;
a.y = 0;
b.q = 0;
b.u = 0;
}
}
function bar(this: A, a: A, b: B) {
this.x = 0;
this.y = 0;
a.x = 0;
a.y = 0;
// These should error
b.q = 0;
~
!!! error TS2446: Property 'q' is protected and only accessible through an instance of class 'A'. This is an instance of class 'B'.
b.u = 0;
~
!!! error TS2446: Property 'u' is protected and only accessible through an instance of class 'A'. This is an instance of class 'B'.
}

View File

@ -0,0 +1,91 @@
//// [publicGetterProtectedSetterFromThisParameter.ts]
class A {
get x() { return 0; }
protected set x(v: number) { }
public get y() { return 0; }
protected set y(v: number) { }
}
class B {
get q() { return 0; }
protected set q(v: number) { }
protected get u() { return 0; }
protected set u(v: number) { }
foo(this: A, a: A, b: B) {
// Should have no errors in this block
this.x = 0;
this.y = 0;
a.x = 0;
a.y = 0;
b.q = 0;
b.u = 0;
}
}
function bar(this: A, a: A, b: B) {
this.x = 0;
this.y = 0;
a.x = 0;
a.y = 0;
// These should error
b.q = 0;
b.u = 0;
}
//// [publicGetterProtectedSetterFromThisParameter.js]
var A = /** @class */ (function () {
function A() {
}
Object.defineProperty(A.prototype, "x", {
get: function () { return 0; },
set: function (v) { },
enumerable: false,
configurable: true
});
Object.defineProperty(A.prototype, "y", {
get: function () { return 0; },
set: function (v) { },
enumerable: false,
configurable: true
});
return A;
}());
var B = /** @class */ (function () {
function B() {
}
Object.defineProperty(B.prototype, "q", {
get: function () { return 0; },
set: function (v) { },
enumerable: false,
configurable: true
});
Object.defineProperty(B.prototype, "u", {
get: function () { return 0; },
set: function (v) { },
enumerable: false,
configurable: true
});
B.prototype.foo = function (a, b) {
// Should have no errors in this block
this.x = 0;
this.y = 0;
a.x = 0;
a.y = 0;
b.q = 0;
b.u = 0;
};
return B;
}());
function bar(a, b) {
this.x = 0;
this.y = 0;
a.x = 0;
a.y = 0;
// These should error
b.q = 0;
b.u = 0;
}

View File

@ -0,0 +1,119 @@
=== tests/cases/compiler/publicGetterProtectedSetterFromThisParameter.ts ===
class A {
>A : Symbol(A, Decl(publicGetterProtectedSetterFromThisParameter.ts, 0, 0))
get x() { return 0; }
>x : Symbol(A.x, Decl(publicGetterProtectedSetterFromThisParameter.ts, 0, 9), Decl(publicGetterProtectedSetterFromThisParameter.ts, 1, 23))
protected set x(v: number) { }
>x : Symbol(A.x, Decl(publicGetterProtectedSetterFromThisParameter.ts, 0, 9), Decl(publicGetterProtectedSetterFromThisParameter.ts, 1, 23))
>v : Symbol(v, Decl(publicGetterProtectedSetterFromThisParameter.ts, 2, 18))
public get y() { return 0; }
>y : Symbol(A.y, Decl(publicGetterProtectedSetterFromThisParameter.ts, 2, 32), Decl(publicGetterProtectedSetterFromThisParameter.ts, 4, 30))
protected set y(v: number) { }
>y : Symbol(A.y, Decl(publicGetterProtectedSetterFromThisParameter.ts, 2, 32), Decl(publicGetterProtectedSetterFromThisParameter.ts, 4, 30))
>v : Symbol(v, Decl(publicGetterProtectedSetterFromThisParameter.ts, 5, 18))
}
class B {
>B : Symbol(B, Decl(publicGetterProtectedSetterFromThisParameter.ts, 6, 1))
get q() { return 0; }
>q : Symbol(B.q, Decl(publicGetterProtectedSetterFromThisParameter.ts, 8, 9), Decl(publicGetterProtectedSetterFromThisParameter.ts, 9, 23))
protected set q(v: number) { }
>q : Symbol(B.q, Decl(publicGetterProtectedSetterFromThisParameter.ts, 8, 9), Decl(publicGetterProtectedSetterFromThisParameter.ts, 9, 23))
>v : Symbol(v, Decl(publicGetterProtectedSetterFromThisParameter.ts, 10, 18))
protected get u() { return 0; }
>u : Symbol(B.u, Decl(publicGetterProtectedSetterFromThisParameter.ts, 10, 32), Decl(publicGetterProtectedSetterFromThisParameter.ts, 12, 33))
protected set u(v: number) { }
>u : Symbol(B.u, Decl(publicGetterProtectedSetterFromThisParameter.ts, 10, 32), Decl(publicGetterProtectedSetterFromThisParameter.ts, 12, 33))
>v : Symbol(v, Decl(publicGetterProtectedSetterFromThisParameter.ts, 13, 18))
foo(this: A, a: A, b: B) {
>foo : Symbol(B.foo, Decl(publicGetterProtectedSetterFromThisParameter.ts, 13, 32))
>this : Symbol(this, Decl(publicGetterProtectedSetterFromThisParameter.ts, 15, 6))
>A : Symbol(A, Decl(publicGetterProtectedSetterFromThisParameter.ts, 0, 0))
>a : Symbol(a, Decl(publicGetterProtectedSetterFromThisParameter.ts, 15, 14))
>A : Symbol(A, Decl(publicGetterProtectedSetterFromThisParameter.ts, 0, 0))
>b : Symbol(b, Decl(publicGetterProtectedSetterFromThisParameter.ts, 15, 20))
>B : Symbol(B, Decl(publicGetterProtectedSetterFromThisParameter.ts, 6, 1))
// Should have no errors in this block
this.x = 0;
>this.x : Symbol(A.x, Decl(publicGetterProtectedSetterFromThisParameter.ts, 0, 9), Decl(publicGetterProtectedSetterFromThisParameter.ts, 1, 23))
>this : Symbol(this, Decl(publicGetterProtectedSetterFromThisParameter.ts, 15, 6))
>x : Symbol(A.x, Decl(publicGetterProtectedSetterFromThisParameter.ts, 0, 9), Decl(publicGetterProtectedSetterFromThisParameter.ts, 1, 23))
this.y = 0;
>this.y : Symbol(A.y, Decl(publicGetterProtectedSetterFromThisParameter.ts, 2, 32), Decl(publicGetterProtectedSetterFromThisParameter.ts, 4, 30))
>this : Symbol(this, Decl(publicGetterProtectedSetterFromThisParameter.ts, 15, 6))
>y : Symbol(A.y, Decl(publicGetterProtectedSetterFromThisParameter.ts, 2, 32), Decl(publicGetterProtectedSetterFromThisParameter.ts, 4, 30))
a.x = 0;
>a.x : Symbol(A.x, Decl(publicGetterProtectedSetterFromThisParameter.ts, 0, 9), Decl(publicGetterProtectedSetterFromThisParameter.ts, 1, 23))
>a : Symbol(a, Decl(publicGetterProtectedSetterFromThisParameter.ts, 15, 14))
>x : Symbol(A.x, Decl(publicGetterProtectedSetterFromThisParameter.ts, 0, 9), Decl(publicGetterProtectedSetterFromThisParameter.ts, 1, 23))
a.y = 0;
>a.y : Symbol(A.y, Decl(publicGetterProtectedSetterFromThisParameter.ts, 2, 32), Decl(publicGetterProtectedSetterFromThisParameter.ts, 4, 30))
>a : Symbol(a, Decl(publicGetterProtectedSetterFromThisParameter.ts, 15, 14))
>y : Symbol(A.y, Decl(publicGetterProtectedSetterFromThisParameter.ts, 2, 32), Decl(publicGetterProtectedSetterFromThisParameter.ts, 4, 30))
b.q = 0;
>b.q : Symbol(B.q, Decl(publicGetterProtectedSetterFromThisParameter.ts, 8, 9), Decl(publicGetterProtectedSetterFromThisParameter.ts, 9, 23))
>b : Symbol(b, Decl(publicGetterProtectedSetterFromThisParameter.ts, 15, 20))
>q : Symbol(B.q, Decl(publicGetterProtectedSetterFromThisParameter.ts, 8, 9), Decl(publicGetterProtectedSetterFromThisParameter.ts, 9, 23))
b.u = 0;
>b.u : Symbol(B.u, Decl(publicGetterProtectedSetterFromThisParameter.ts, 10, 32), Decl(publicGetterProtectedSetterFromThisParameter.ts, 12, 33))
>b : Symbol(b, Decl(publicGetterProtectedSetterFromThisParameter.ts, 15, 20))
>u : Symbol(B.u, Decl(publicGetterProtectedSetterFromThisParameter.ts, 10, 32), Decl(publicGetterProtectedSetterFromThisParameter.ts, 12, 33))
}
}
function bar(this: A, a: A, b: B) {
>bar : Symbol(bar, Decl(publicGetterProtectedSetterFromThisParameter.ts, 24, 1))
>this : Symbol(this, Decl(publicGetterProtectedSetterFromThisParameter.ts, 26, 13))
>A : Symbol(A, Decl(publicGetterProtectedSetterFromThisParameter.ts, 0, 0))
>a : Symbol(a, Decl(publicGetterProtectedSetterFromThisParameter.ts, 26, 21))
>A : Symbol(A, Decl(publicGetterProtectedSetterFromThisParameter.ts, 0, 0))
>b : Symbol(b, Decl(publicGetterProtectedSetterFromThisParameter.ts, 26, 27))
>B : Symbol(B, Decl(publicGetterProtectedSetterFromThisParameter.ts, 6, 1))
this.x = 0;
>this.x : Symbol(A.x, Decl(publicGetterProtectedSetterFromThisParameter.ts, 0, 9), Decl(publicGetterProtectedSetterFromThisParameter.ts, 1, 23))
>this : Symbol(this, Decl(publicGetterProtectedSetterFromThisParameter.ts, 26, 13))
>x : Symbol(A.x, Decl(publicGetterProtectedSetterFromThisParameter.ts, 0, 9), Decl(publicGetterProtectedSetterFromThisParameter.ts, 1, 23))
this.y = 0;
>this.y : Symbol(A.y, Decl(publicGetterProtectedSetterFromThisParameter.ts, 2, 32), Decl(publicGetterProtectedSetterFromThisParameter.ts, 4, 30))
>this : Symbol(this, Decl(publicGetterProtectedSetterFromThisParameter.ts, 26, 13))
>y : Symbol(A.y, Decl(publicGetterProtectedSetterFromThisParameter.ts, 2, 32), Decl(publicGetterProtectedSetterFromThisParameter.ts, 4, 30))
a.x = 0;
>a.x : Symbol(A.x, Decl(publicGetterProtectedSetterFromThisParameter.ts, 0, 9), Decl(publicGetterProtectedSetterFromThisParameter.ts, 1, 23))
>a : Symbol(a, Decl(publicGetterProtectedSetterFromThisParameter.ts, 26, 21))
>x : Symbol(A.x, Decl(publicGetterProtectedSetterFromThisParameter.ts, 0, 9), Decl(publicGetterProtectedSetterFromThisParameter.ts, 1, 23))
a.y = 0;
>a.y : Symbol(A.y, Decl(publicGetterProtectedSetterFromThisParameter.ts, 2, 32), Decl(publicGetterProtectedSetterFromThisParameter.ts, 4, 30))
>a : Symbol(a, Decl(publicGetterProtectedSetterFromThisParameter.ts, 26, 21))
>y : Symbol(A.y, Decl(publicGetterProtectedSetterFromThisParameter.ts, 2, 32), Decl(publicGetterProtectedSetterFromThisParameter.ts, 4, 30))
// These should error
b.q = 0;
>b.q : Symbol(B.q, Decl(publicGetterProtectedSetterFromThisParameter.ts, 8, 9), Decl(publicGetterProtectedSetterFromThisParameter.ts, 9, 23))
>b : Symbol(b, Decl(publicGetterProtectedSetterFromThisParameter.ts, 26, 27))
>q : Symbol(B.q, Decl(publicGetterProtectedSetterFromThisParameter.ts, 8, 9), Decl(publicGetterProtectedSetterFromThisParameter.ts, 9, 23))
b.u = 0;
>b.u : Symbol(B.u, Decl(publicGetterProtectedSetterFromThisParameter.ts, 10, 32), Decl(publicGetterProtectedSetterFromThisParameter.ts, 12, 33))
>b : Symbol(b, Decl(publicGetterProtectedSetterFromThisParameter.ts, 26, 27))
>u : Symbol(B.u, Decl(publicGetterProtectedSetterFromThisParameter.ts, 10, 32), Decl(publicGetterProtectedSetterFromThisParameter.ts, 12, 33))
}

View File

@ -0,0 +1,141 @@
=== tests/cases/compiler/publicGetterProtectedSetterFromThisParameter.ts ===
class A {
>A : A
get x() { return 0; }
>x : number
>0 : 0
protected set x(v: number) { }
>x : number
>v : number
public get y() { return 0; }
>y : number
>0 : 0
protected set y(v: number) { }
>y : number
>v : number
}
class B {
>B : B
get q() { return 0; }
>q : number
>0 : 0
protected set q(v: number) { }
>q : number
>v : number
protected get u() { return 0; }
>u : number
>0 : 0
protected set u(v: number) { }
>u : number
>v : number
foo(this: A, a: A, b: B) {
>foo : (this: A, a: A, b: B) => void
>this : A
>a : A
>b : B
// Should have no errors in this block
this.x = 0;
>this.x = 0 : 0
>this.x : number
>this : A
>x : number
>0 : 0
this.y = 0;
>this.y = 0 : 0
>this.y : number
>this : A
>y : number
>0 : 0
a.x = 0;
>a.x = 0 : 0
>a.x : number
>a : A
>x : number
>0 : 0
a.y = 0;
>a.y = 0 : 0
>a.y : number
>a : A
>y : number
>0 : 0
b.q = 0;
>b.q = 0 : 0
>b.q : number
>b : B
>q : number
>0 : 0
b.u = 0;
>b.u = 0 : 0
>b.u : number
>b : B
>u : number
>0 : 0
}
}
function bar(this: A, a: A, b: B) {
>bar : (this: A, a: A, b: B) => void
>this : A
>a : A
>b : B
this.x = 0;
>this.x = 0 : 0
>this.x : number
>this : A
>x : number
>0 : 0
this.y = 0;
>this.y = 0 : 0
>this.y : number
>this : A
>y : number
>0 : 0
a.x = 0;
>a.x = 0 : 0
>a.x : number
>a : A
>x : number
>0 : 0
a.y = 0;
>a.y = 0 : 0
>a.y : number
>a : A
>y : number
>0 : 0
// These should error
b.q = 0;
>b.q = 0 : 0
>b.q : number
>b : B
>q : number
>0 : 0
b.u = 0;
>b.u = 0 : 0
>b.u : number
>b : B
>u : number
>0 : 0
}

View File

@ -0,0 +1,37 @@
// @target: ES5
class A {
get x() { return 0; }
protected set x(v: number) { }
public get y() { return 0; }
protected set y(v: number) { }
}
class B {
get q() { return 0; }
protected set q(v: number) { }
protected get u() { return 0; }
protected set u(v: number) { }
foo(this: A, a: A, b: B) {
// Should have no errors in this block
this.x = 0;
this.y = 0;
a.x = 0;
a.y = 0;
b.q = 0;
b.u = 0;
}
}
function bar(this: A, a: A, b: B) {
this.x = 0;
this.y = 0;
a.x = 0;
a.y = 0;
// These should error
b.q = 0;
b.u = 0;
}