mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-11 01:34:55 -06:00
Merge pull request #9904 from Microsoft/protected-constructors-accessible-in-subclass-static-methods
Protected constructors accessible in subclass static methods
This commit is contained in:
commit
ac2c41c081
@ -11544,8 +11544,20 @@ namespace ts {
|
||||
const declaringClassDeclaration = <ClassLikeDeclaration>getClassLikeDeclarationOfSymbol(declaration.parent.symbol);
|
||||
const declaringClass = <InterfaceType>getDeclaredTypeOfSymbol(declaration.parent.symbol);
|
||||
|
||||
// A private or protected constructor can only be instantiated within it's own class
|
||||
// A private or protected constructor can only be instantiated within its own class (or a subclass, for protected)
|
||||
if (!isNodeWithinClass(node, declaringClassDeclaration)) {
|
||||
const containingClass = getContainingClass(node);
|
||||
if (containingClass) {
|
||||
const containingType = getTypeOfNode(containingClass);
|
||||
const baseTypes = getBaseTypes(<InterfaceType>containingType);
|
||||
if (baseTypes.length) {
|
||||
const baseType = baseTypes[0];
|
||||
if (flags & NodeFlags.Protected &&
|
||||
baseType.symbol === declaration.parent.symbol) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (flags & NodeFlags.Private) {
|
||||
error(node, Diagnostics.Constructor_of_class_0_is_private_and_only_accessible_within_the_class_declaration, typeToString(declaringClass));
|
||||
}
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility2.ts(26,28): error TS2674: Constructor of class 'BaseB' is protected and only accessible within the class declaration.
|
||||
tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility2.ts(29,24): error TS2675: Cannot extend a class 'BaseC'. Class constructor is marked as private.
|
||||
tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility2.ts(32,28): error TS2673: Constructor of class 'BaseC' is private and only accessible within the class declaration.
|
||||
tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility2.ts(36,10): error TS2674: Constructor of class 'BaseB' is protected and only accessible within the class declaration.
|
||||
tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility2.ts(37,10): error TS2673: Constructor of class 'BaseC' is private and only accessible within the class declaration.
|
||||
tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility2.ts(32,24): error TS2675: Cannot extend a class 'BaseC'. Class constructor is marked as private.
|
||||
tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility2.ts(35,28): error TS2673: Constructor of class 'BaseC' is private and only accessible within the class declaration.
|
||||
tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility2.ts(36,35): error TS2673: Constructor of class 'BaseC' is private and only accessible within the class declaration.
|
||||
tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility2.ts(40,10): error TS2674: Constructor of class 'BaseB' is protected and only accessible within the class declaration.
|
||||
tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility2.ts(41,10): error TS2673: Constructor of class 'BaseC' is private and only accessible within the class declaration.
|
||||
|
||||
|
||||
==== tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility2.ts (5 errors) ====
|
||||
@ -14,35 +14,39 @@ tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessib
|
||||
|
||||
class BaseB {
|
||||
protected constructor(public x: number) { }
|
||||
createInstance() { new BaseB(1); }
|
||||
createInstance() { new BaseB(2); }
|
||||
}
|
||||
|
||||
class BaseC {
|
||||
private constructor(public x: number) { }
|
||||
createInstance() { new BaseC(1); }
|
||||
private constructor(public x: number) { }
|
||||
createInstance() { new BaseC(3); }
|
||||
static staticInstance() { new BaseC(4); }
|
||||
}
|
||||
|
||||
class DerivedA extends BaseA {
|
||||
constructor(public x: number) { super(x); }
|
||||
createInstance() { new DerivedA(1); }
|
||||
createBaseInstance() { new BaseA(1); }
|
||||
createInstance() { new DerivedA(5); }
|
||||
createBaseInstance() { new BaseA(6); }
|
||||
static staticBaseInstance() { new BaseA(7); }
|
||||
}
|
||||
|
||||
class DerivedB extends BaseB {
|
||||
constructor(public x: number) { super(x); }
|
||||
createInstance() { new DerivedB(1); }
|
||||
createBaseInstance() { new BaseB(1); } // error
|
||||
~~~~~~~~~~~~
|
||||
!!! error TS2674: Constructor of class 'BaseB' is protected and only accessible within the class declaration.
|
||||
createInstance() { new DerivedB(7); }
|
||||
createBaseInstance() { new BaseB(8); } // ok
|
||||
static staticBaseInstance() { new BaseB(9); } // ok
|
||||
}
|
||||
|
||||
class DerivedC extends BaseC { // error
|
||||
~~~~~
|
||||
!!! error TS2675: Cannot extend a class 'BaseC'. Class constructor is marked as private.
|
||||
constructor(public x: number) { super(x); }
|
||||
createInstance() { new DerivedC(1); }
|
||||
createBaseInstance() { new BaseC(1); } // error
|
||||
~~~~~~~~~~~~
|
||||
createInstance() { new DerivedC(9); }
|
||||
createBaseInstance() { new BaseC(10); } // error
|
||||
~~~~~~~~~~~~~
|
||||
!!! error TS2673: Constructor of class 'BaseC' is private and only accessible within the class declaration.
|
||||
static staticBaseInstance() { new BaseC(11); } // error
|
||||
~~~~~~~~~~~~~
|
||||
!!! error TS2673: Constructor of class 'BaseC' is private and only accessible within the class declaration.
|
||||
}
|
||||
|
||||
@ -56,4 +60,5 @@ tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessib
|
||||
|
||||
var da = new DerivedA(1);
|
||||
var db = new DerivedB(1);
|
||||
var dc = new DerivedC(1);
|
||||
var dc = new DerivedC(1);
|
||||
|
||||
@ -7,30 +7,34 @@ class BaseA {
|
||||
|
||||
class BaseB {
|
||||
protected constructor(public x: number) { }
|
||||
createInstance() { new BaseB(1); }
|
||||
createInstance() { new BaseB(2); }
|
||||
}
|
||||
|
||||
class BaseC {
|
||||
private constructor(public x: number) { }
|
||||
createInstance() { new BaseC(1); }
|
||||
private constructor(public x: number) { }
|
||||
createInstance() { new BaseC(3); }
|
||||
static staticInstance() { new BaseC(4); }
|
||||
}
|
||||
|
||||
class DerivedA extends BaseA {
|
||||
constructor(public x: number) { super(x); }
|
||||
createInstance() { new DerivedA(1); }
|
||||
createBaseInstance() { new BaseA(1); }
|
||||
createInstance() { new DerivedA(5); }
|
||||
createBaseInstance() { new BaseA(6); }
|
||||
static staticBaseInstance() { new BaseA(7); }
|
||||
}
|
||||
|
||||
class DerivedB extends BaseB {
|
||||
constructor(public x: number) { super(x); }
|
||||
createInstance() { new DerivedB(1); }
|
||||
createBaseInstance() { new BaseB(1); } // error
|
||||
createInstance() { new DerivedB(7); }
|
||||
createBaseInstance() { new BaseB(8); } // ok
|
||||
static staticBaseInstance() { new BaseB(9); } // ok
|
||||
}
|
||||
|
||||
class DerivedC extends BaseC { // error
|
||||
constructor(public x: number) { super(x); }
|
||||
createInstance() { new DerivedC(1); }
|
||||
createBaseInstance() { new BaseC(1); } // error
|
||||
createInstance() { new DerivedC(9); }
|
||||
createBaseInstance() { new BaseC(10); } // error
|
||||
static staticBaseInstance() { new BaseC(11); } // error
|
||||
}
|
||||
|
||||
var ba = new BaseA(1);
|
||||
@ -39,7 +43,8 @@ var bc = new BaseC(1); // error
|
||||
|
||||
var da = new DerivedA(1);
|
||||
var db = new DerivedB(1);
|
||||
var dc = new DerivedC(1);
|
||||
var dc = new DerivedC(1);
|
||||
|
||||
|
||||
//// [classConstructorAccessibility2.js]
|
||||
var __extends = (this && this.__extends) || function (d, b) {
|
||||
@ -58,14 +63,15 @@ var BaseB = (function () {
|
||||
function BaseB(x) {
|
||||
this.x = x;
|
||||
}
|
||||
BaseB.prototype.createInstance = function () { new BaseB(1); };
|
||||
BaseB.prototype.createInstance = function () { new BaseB(2); };
|
||||
return BaseB;
|
||||
}());
|
||||
var BaseC = (function () {
|
||||
function BaseC(x) {
|
||||
this.x = x;
|
||||
}
|
||||
BaseC.prototype.createInstance = function () { new BaseC(1); };
|
||||
BaseC.prototype.createInstance = function () { new BaseC(3); };
|
||||
BaseC.staticInstance = function () { new BaseC(4); };
|
||||
return BaseC;
|
||||
}());
|
||||
var DerivedA = (function (_super) {
|
||||
@ -74,8 +80,9 @@ var DerivedA = (function (_super) {
|
||||
_super.call(this, x);
|
||||
this.x = x;
|
||||
}
|
||||
DerivedA.prototype.createInstance = function () { new DerivedA(1); };
|
||||
DerivedA.prototype.createBaseInstance = function () { new BaseA(1); };
|
||||
DerivedA.prototype.createInstance = function () { new DerivedA(5); };
|
||||
DerivedA.prototype.createBaseInstance = function () { new BaseA(6); };
|
||||
DerivedA.staticBaseInstance = function () { new BaseA(7); };
|
||||
return DerivedA;
|
||||
}(BaseA));
|
||||
var DerivedB = (function (_super) {
|
||||
@ -84,8 +91,9 @@ var DerivedB = (function (_super) {
|
||||
_super.call(this, x);
|
||||
this.x = x;
|
||||
}
|
||||
DerivedB.prototype.createInstance = function () { new DerivedB(1); };
|
||||
DerivedB.prototype.createBaseInstance = function () { new BaseB(1); }; // error
|
||||
DerivedB.prototype.createInstance = function () { new DerivedB(7); };
|
||||
DerivedB.prototype.createBaseInstance = function () { new BaseB(8); }; // ok
|
||||
DerivedB.staticBaseInstance = function () { new BaseB(9); }; // ok
|
||||
return DerivedB;
|
||||
}(BaseB));
|
||||
var DerivedC = (function (_super) {
|
||||
@ -94,8 +102,9 @@ var DerivedC = (function (_super) {
|
||||
_super.call(this, x);
|
||||
this.x = x;
|
||||
}
|
||||
DerivedC.prototype.createInstance = function () { new DerivedC(1); };
|
||||
DerivedC.prototype.createBaseInstance = function () { new BaseC(1); }; // error
|
||||
DerivedC.prototype.createInstance = function () { new DerivedC(9); };
|
||||
DerivedC.prototype.createBaseInstance = function () { new BaseC(10); }; // error
|
||||
DerivedC.staticBaseInstance = function () { new BaseC(11); }; // error
|
||||
return DerivedC;
|
||||
}(BaseC));
|
||||
var ba = new BaseA(1);
|
||||
@ -121,24 +130,28 @@ declare class BaseC {
|
||||
x: number;
|
||||
private constructor(x);
|
||||
createInstance(): void;
|
||||
static staticInstance(): void;
|
||||
}
|
||||
declare class DerivedA extends BaseA {
|
||||
x: number;
|
||||
constructor(x: number);
|
||||
createInstance(): void;
|
||||
createBaseInstance(): void;
|
||||
static staticBaseInstance(): void;
|
||||
}
|
||||
declare class DerivedB extends BaseB {
|
||||
x: number;
|
||||
constructor(x: number);
|
||||
createInstance(): void;
|
||||
createBaseInstance(): void;
|
||||
static staticBaseInstance(): void;
|
||||
}
|
||||
declare class DerivedC extends BaseC {
|
||||
x: number;
|
||||
constructor(x: number);
|
||||
createInstance(): void;
|
||||
createBaseInstance(): void;
|
||||
static staticBaseInstance(): void;
|
||||
}
|
||||
declare var ba: BaseA;
|
||||
declare var bb: any;
|
||||
|
||||
@ -0,0 +1,17 @@
|
||||
tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility5.ts(9,21): error TS2674: Constructor of class 'Base' is protected and only accessible within the class declaration.
|
||||
|
||||
|
||||
==== tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility5.ts (1 errors) ====
|
||||
class Base {
|
||||
protected constructor() { }
|
||||
}
|
||||
class Derived extends Base {
|
||||
static make() { new Base() } // ok
|
||||
}
|
||||
|
||||
class Unrelated {
|
||||
static fake() { new Base() } // error
|
||||
~~~~~~~~~~
|
||||
!!! error TS2674: Constructor of class 'Base' is protected and only accessible within the class declaration.
|
||||
}
|
||||
|
||||
38
tests/baselines/reference/classConstructorAccessibility5.js
Normal file
38
tests/baselines/reference/classConstructorAccessibility5.js
Normal file
@ -0,0 +1,38 @@
|
||||
//// [classConstructorAccessibility5.ts]
|
||||
class Base {
|
||||
protected constructor() { }
|
||||
}
|
||||
class Derived extends Base {
|
||||
static make() { new Base() } // ok
|
||||
}
|
||||
|
||||
class Unrelated {
|
||||
static fake() { new Base() } // error
|
||||
}
|
||||
|
||||
|
||||
//// [classConstructorAccessibility5.js]
|
||||
var __extends = (this && this.__extends) || function (d, b) {
|
||||
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
|
||||
function __() { this.constructor = d; }
|
||||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||||
};
|
||||
var Base = (function () {
|
||||
function Base() {
|
||||
}
|
||||
return Base;
|
||||
}());
|
||||
var Derived = (function (_super) {
|
||||
__extends(Derived, _super);
|
||||
function Derived() {
|
||||
_super.apply(this, arguments);
|
||||
}
|
||||
Derived.make = function () { new Base(); }; // ok
|
||||
return Derived;
|
||||
}(Base));
|
||||
var Unrelated = (function () {
|
||||
function Unrelated() {
|
||||
}
|
||||
Unrelated.fake = function () { new Base(); }; // error
|
||||
return Unrelated;
|
||||
}());
|
||||
@ -7,30 +7,34 @@ class BaseA {
|
||||
|
||||
class BaseB {
|
||||
protected constructor(public x: number) { }
|
||||
createInstance() { new BaseB(1); }
|
||||
createInstance() { new BaseB(2); }
|
||||
}
|
||||
|
||||
class BaseC {
|
||||
private constructor(public x: number) { }
|
||||
createInstance() { new BaseC(1); }
|
||||
private constructor(public x: number) { }
|
||||
createInstance() { new BaseC(3); }
|
||||
static staticInstance() { new BaseC(4); }
|
||||
}
|
||||
|
||||
class DerivedA extends BaseA {
|
||||
constructor(public x: number) { super(x); }
|
||||
createInstance() { new DerivedA(1); }
|
||||
createBaseInstance() { new BaseA(1); }
|
||||
createInstance() { new DerivedA(5); }
|
||||
createBaseInstance() { new BaseA(6); }
|
||||
static staticBaseInstance() { new BaseA(7); }
|
||||
}
|
||||
|
||||
class DerivedB extends BaseB {
|
||||
constructor(public x: number) { super(x); }
|
||||
createInstance() { new DerivedB(1); }
|
||||
createBaseInstance() { new BaseB(1); } // error
|
||||
createInstance() { new DerivedB(7); }
|
||||
createBaseInstance() { new BaseB(8); } // ok
|
||||
static staticBaseInstance() { new BaseB(9); } // ok
|
||||
}
|
||||
|
||||
class DerivedC extends BaseC { // error
|
||||
constructor(public x: number) { super(x); }
|
||||
createInstance() { new DerivedC(1); }
|
||||
createBaseInstance() { new BaseC(1); } // error
|
||||
createInstance() { new DerivedC(9); }
|
||||
createBaseInstance() { new BaseC(10); } // error
|
||||
static staticBaseInstance() { new BaseC(11); } // error
|
||||
}
|
||||
|
||||
var ba = new BaseA(1);
|
||||
@ -39,4 +43,4 @@ var bc = new BaseC(1); // error
|
||||
|
||||
var da = new DerivedA(1);
|
||||
var db = new DerivedB(1);
|
||||
var dc = new DerivedC(1);
|
||||
var dc = new DerivedC(1);
|
||||
|
||||
@ -0,0 +1,10 @@
|
||||
class Base {
|
||||
protected constructor() { }
|
||||
}
|
||||
class Derived extends Base {
|
||||
static make() { new Base() } // ok
|
||||
}
|
||||
|
||||
class Unrelated {
|
||||
static fake() { new Base() } // error
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user