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:
Nathan Shively-Sanders 2016-07-25 12:38:07 -07:00 committed by GitHub
commit ac2c41c081
7 changed files with 146 additions and 47 deletions

View File

@ -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));
}

View File

@ -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);

View File

@ -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;

View File

@ -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.
}

View 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;
}());

View File

@ -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);

View File

@ -0,0 +1,10 @@
class Base {
protected constructor() { }
}
class Derived extends Base {
static make() { new Base() } // ok
}
class Unrelated {
static fake() { new Base() } // error
}