Merge pull request #6885 from AbubakerB/constructorAccessibility

Constructor Visibility
This commit is contained in:
Mohamed Hegazy 2016-02-16 16:50:19 -08:00
commit bde20c4ec7
38 changed files with 1184 additions and 135 deletions

View File

@ -1720,6 +1720,16 @@ namespace ts {
return result;
}
function visibilityToString(flags: NodeFlags) {
if (flags === NodeFlags.Private) {
return "private";
}
if (flags === NodeFlags.Protected) {
return "protected";
}
return "public";
}
function getTypeAliasForTypeLiteral(type: Type): Symbol {
if (type.symbol && type.symbol.flags & SymbolFlags.TypeLiteral) {
let node = type.symbol.declarations[0].parent;
@ -5907,16 +5917,20 @@ namespace ts {
const sourceSignatures = getSignaturesOfType(source, kind);
const targetSignatures = getSignaturesOfType(target, kind);
if (kind === SignatureKind.Construct && sourceSignatures.length && targetSignatures.length &&
isAbstractConstructorType(source) && !isAbstractConstructorType(target)) {
// An abstract constructor type is not assignable to a non-abstract constructor type
if (kind === SignatureKind.Construct && sourceSignatures.length && targetSignatures.length) {
if (isAbstractConstructorType(source) && !isAbstractConstructorType(target)) {
// An abstract constructor type is not assignable to a non-abstract constructor type
// as it would otherwise be possible to new an abstract class. Note that the assignability
// check we perform for an extends clause excludes construct signatures from the target,
// so this check never proceeds.
if (reportErrors) {
reportError(Diagnostics.Cannot_assign_an_abstract_constructor_type_to_a_non_abstract_constructor_type);
// check we perform for an extends clause excludes construct signatures from the target,
// so this check never proceeds.
if (reportErrors) {
reportError(Diagnostics.Cannot_assign_an_abstract_constructor_type_to_a_non_abstract_constructor_type);
}
return Ternary.False;
}
if (!constructorVisibilitiesAreCompatible(sourceSignatures[0], targetSignatures[0], reportErrors)) {
return Ternary.False;
}
return Ternary.False;
}
let result = Ternary.True;
@ -6059,6 +6073,36 @@ namespace ts {
}
return Ternary.True;
}
function constructorVisibilitiesAreCompatible(sourceSignature: Signature, targetSignature: Signature, reportErrors: boolean) {
if (!sourceSignature.declaration || !targetSignature.declaration) {
return true;
}
const sourceAccessibility = sourceSignature.declaration.flags & (NodeFlags.Private | NodeFlags.Protected);
const targetAccessibility = targetSignature.declaration.flags & (NodeFlags.Private | NodeFlags.Protected);
// A public, protected and private signature is assignable to a private signature.
if (targetAccessibility === NodeFlags.Private) {
return true;
}
// A public and protected signature is assignable to a protected signature.
if (targetAccessibility === NodeFlags.Protected && sourceAccessibility !== NodeFlags.Private) {
return true;
}
// Only a public signature is assignable to public signature.
if (targetAccessibility !== NodeFlags.Protected && !sourceAccessibility) {
return true;
}
if (reportErrors) {
reportError(Diagnostics.Cannot_assign_a_0_constructor_type_to_a_1_constructor_type, visibilityToString(sourceAccessibility), visibilityToString(targetAccessibility));
}
return false;
}
}
// Return true if the given type is the constructor type for an abstract class
@ -10166,6 +10210,9 @@ namespace ts {
// that the user will not add any.
const constructSignatures = getSignaturesOfType(expressionType, SignatureKind.Construct);
if (constructSignatures.length) {
if (!isConstructorAccessible(node, constructSignatures[0])) {
return resolveErrorCall(node);
}
return resolveCall(node, constructSignatures, candidatesOutArray);
}
@ -10186,6 +10233,36 @@ namespace ts {
return resolveErrorCall(node);
}
function isConstructorAccessible(node: NewExpression, signature: Signature) {
if (!signature || !signature.declaration) {
return true;
}
const declaration = signature.declaration;
const flags = declaration.flags;
// Public constructor is accessible.
if (!(flags & (NodeFlags.Private | NodeFlags.Protected))) {
return true;
}
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
if (!isNodeWithinClass(node, declaringClassDeclaration)) {
if (flags & NodeFlags.Private) {
error(node, Diagnostics.Constructor_of_class_0_is_private_and_only_accessible_within_the_class_declaration, typeToString(declaringClass));
}
if (flags & NodeFlags.Protected) {
error(node, Diagnostics.Constructor_of_class_0_is_protected_and_only_accessible_within_the_class_declaration, typeToString(declaringClass));
}
return false;
}
return true;
}
function resolveTaggedTemplateExpression(node: TaggedTemplateExpression, candidatesOutArray: Signature[]): Signature {
const tagType = checkExpression(node.tag);
const apparentType = getApparentType(tagType);
@ -12123,7 +12200,7 @@ namespace ts {
error(o.name, Diagnostics.Overload_signatures_must_all_be_ambient_or_non_ambient);
}
else if (deviation & (NodeFlags.Private | NodeFlags.Protected)) {
error(o.name, Diagnostics.Overload_signatures_must_all_be_public_private_or_protected);
error(o.name || o, Diagnostics.Overload_signatures_must_all_be_public_private_or_protected);
}
else if (deviation & NodeFlags.Abstract) {
error(o.name, Diagnostics.Overload_signatures_must_all_be_abstract_or_not_abstract);
@ -13992,6 +14069,7 @@ namespace ts {
if (baseTypes.length && produceDiagnostics) {
const baseType = baseTypes[0];
const staticBaseType = getBaseConstructorTypeOfClass(type);
checkBaseTypeAccessibility(staticBaseType, baseTypeNode);
checkSourceElement(baseTypeNode.expression);
if (baseTypeNode.typeArguments) {
forEach(baseTypeNode.typeArguments, checkSourceElement);
@ -14047,6 +14125,19 @@ namespace ts {
}
}
function checkBaseTypeAccessibility(type: ObjectType, node: ExpressionWithTypeArguments) {
const signatures = getSignaturesOfType(type, SignatureKind.Construct);
if (signatures.length) {
const declaration = signatures[0].declaration;
if (declaration && declaration.flags & NodeFlags.Private) {
const typeClassDeclaration = <ClassLikeDeclaration>getClassLikeDeclarationOfSymbol(type.symbol);
if (!isNodeWithinClass(node, typeClassDeclaration)) {
error(node, Diagnostics.Cannot_extend_a_class_0_Class_constructor_is_marked_as_private, (<Identifier>node.expression).text);
}
}
}
}
function getTargetSymbol(s: Symbol) {
// if symbol is instantiated its flags are not copied from the 'target'
// so we'll need to get back original 'target' symbol to work with correct set of flags
@ -15370,6 +15461,18 @@ namespace ts {
return node.parent && node.parent.kind === SyntaxKind.ExpressionWithTypeArguments;
}
function isNodeWithinClass(node: Node, classDeclaration: ClassLikeDeclaration) {
while (true) {
node = getContainingClass(node);
if (!node) {
return false;
}
if (node === classDeclaration) {
return true;
}
}
}
function getLeftSideOfImportEqualsOrExportAssignment(nodeOnRightSide: EntityName): ImportEqualsDeclaration | ExportAssignment {
while (nodeOnRightSide.parent.kind === SyntaxKind.QualifiedName) {
nodeOnRightSide = <QualifiedName>nodeOnRightSide.parent;
@ -16253,16 +16356,12 @@ namespace ts {
case SyntaxKind.PublicKeyword:
case SyntaxKind.ProtectedKeyword:
case SyntaxKind.PrivateKeyword:
let text: string;
if (modifier.kind === SyntaxKind.PublicKeyword) {
text = "public";
}
else if (modifier.kind === SyntaxKind.ProtectedKeyword) {
text = "protected";
let text = visibilityToString(modifierToFlag(modifier.kind));
if (modifier.kind === SyntaxKind.ProtectedKeyword) {
lastProtected = modifier;
}
else {
text = "private";
else if (modifier.kind === SyntaxKind.PrivateKeyword) {
lastPrivate = modifier;
}
@ -16413,12 +16512,6 @@ namespace ts {
if (flags & NodeFlags.Abstract) {
return grammarErrorOnNode(lastStatic, Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "abstract");
}
else if (flags & NodeFlags.Protected) {
return grammarErrorOnNode(lastProtected, Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "protected");
}
else if (flags & NodeFlags.Private) {
return grammarErrorOnNode(lastPrivate, Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "private");
}
else if (flags & NodeFlags.Async) {
return grammarErrorOnNode(lastAsync, Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "async");
}

View File

@ -1313,7 +1313,7 @@ namespace ts {
if (node.kind === SyntaxKind.FunctionDeclaration) {
emitModuleElementDeclarationFlags(node);
}
else if (node.kind === SyntaxKind.MethodDeclaration) {
else if (node.kind === SyntaxKind.MethodDeclaration || node.kind === SyntaxKind.Constructor) {
emitClassMemberDeclarationFlags(node.flags);
}
if (node.kind === SyntaxKind.FunctionDeclaration) {

View File

@ -1827,6 +1827,22 @@
"category": "Error",
"code": 2671
},
"Cannot assign a '{0}' constructor type to a '{1}' constructor type.": {
"category": "Error",
"code": 2672
},
"Constructor of class '{0}' is private and only accessible within the class declaration.": {
"category": "Error",
"code": 2673
},
"Constructor of class '{0}' is protected and only accessible within the class declaration.": {
"category": "Error",
"code": 2674
},
"Cannot extend a class '{0}'. Class constructor is marked as private.": {
"category": "Error",
"code": 2675
},
"Import declaration '{0}' is using private name '{1}'.": {
"category": "Error",
"code": 4000
@ -2785,4 +2801,4 @@
"category": "Error",
"code": 17009
}
}
}

View File

@ -1,9 +0,0 @@
tests/cases/conformance/parser/ecmascript5/Protected/Protected3.ts(2,3): error TS1089: 'protected' modifier cannot appear on a constructor declaration.
==== tests/cases/conformance/parser/ecmascript5/Protected/Protected3.ts (1 errors) ====
class C {
protected constructor() { }
~~~~~~~~~
!!! error TS1089: 'protected' modifier cannot appear on a constructor declaration.
}

View File

@ -0,0 +1,6 @@
=== tests/cases/conformance/parser/ecmascript5/Protected/Protected3.ts ===
class C {
>C : Symbol(C, Decl(Protected3.ts, 0, 0))
protected constructor() { }
}

View File

@ -0,0 +1,6 @@
=== tests/cases/conformance/parser/ecmascript5/Protected/Protected3.ts ===
class C {
>C : C
protected constructor() { }
}

View File

@ -1,29 +1,30 @@
tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts(6,5): error TS1089: 'private' modifier cannot appear on a constructor declaration.
tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts(10,5): error TS1089: 'protected' modifier cannot appear on a constructor declaration.
tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts(23,9): error TS1089: 'private' modifier cannot appear on a constructor declaration.
tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts(27,9): error TS1089: 'protected' modifier cannot appear on a constructor declaration.
tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts(15,9): error TS2673: Constructor of class 'D' is private and only accessible within the class declaration.
tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts(16,9): error TS2674: Constructor of class 'E' is protected and only accessible within the class declaration.
tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts(32,13): error TS2673: Constructor of class 'D<T>' is private and only accessible within the class declaration.
tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts(33,13): error TS2674: Constructor of class 'E<T>' is protected and only accessible within the class declaration.
==== tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts (4 errors) ====
class C {
public constructor(public x: number) { }
}
class D {
private constructor(public x: number) { } // error
~~~~~~~
!!! error TS1089: 'private' modifier cannot appear on a constructor declaration.
private constructor(public x: number) { }
}
class E {
protected constructor(public x: number) { } // error
~~~~~~~~~
!!! error TS1089: 'protected' modifier cannot appear on a constructor declaration.
protected constructor(public x: number) { }
}
var c = new C(1);
var d = new D(1);
var e = new E(1);
var d = new D(1); // error
~~~~~~~~
!!! error TS2673: Constructor of class 'D' is private and only accessible within the class declaration.
var e = new E(1); // error
~~~~~~~~
!!! error TS2674: Constructor of class 'E' is protected and only accessible within the class declaration.
module Generic {
class C<T> {
@ -31,19 +32,19 @@ tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessib
}
class D<T> {
private constructor(public x: T) { } // error
~~~~~~~
!!! error TS1089: 'private' modifier cannot appear on a constructor declaration.
private constructor(public x: T) { }
}
class E<T> {
protected constructor(public x: T) { } // error
~~~~~~~~~
!!! error TS1089: 'protected' modifier cannot appear on a constructor declaration.
protected constructor(public x: T) { }
}
var c = new C(1);
var d = new D(1);
var e = new E(1);
var d = new D(1); // error
~~~~~~~~
!!! error TS2673: Constructor of class 'D<T>' is private and only accessible within the class declaration.
var e = new E(1); // error
~~~~~~~~
!!! error TS2674: Constructor of class 'E<T>' is protected and only accessible within the class declaration.
}

View File

@ -1,19 +1,20 @@
//// [classConstructorAccessibility.ts]
class C {
public constructor(public x: number) { }
}
class D {
private constructor(public x: number) { } // error
private constructor(public x: number) { }
}
class E {
protected constructor(public x: number) { } // error
protected constructor(public x: number) { }
}
var c = new C(1);
var d = new D(1);
var e = new E(1);
var d = new D(1); // error
var e = new E(1); // error
module Generic {
class C<T> {
@ -21,16 +22,16 @@ module Generic {
}
class D<T> {
private constructor(public x: T) { } // error
private constructor(public x: T) { }
}
class E<T> {
protected constructor(public x: T) { } // error
protected constructor(public x: T) { }
}
var c = new C(1);
var d = new D(1);
var e = new E(1);
var d = new D(1); // error
var e = new E(1); // error
}
@ -44,18 +45,18 @@ var C = (function () {
var D = (function () {
function D(x) {
this.x = x;
} // error
}
return D;
}());
var E = (function () {
function E(x) {
this.x = x;
} // error
}
return E;
}());
var c = new C(1);
var d = new D(1);
var e = new E(1);
var d = new D(1); // error
var e = new E(1); // error
var Generic;
(function (Generic) {
var C = (function () {
@ -67,16 +68,36 @@ var Generic;
var D = (function () {
function D(x) {
this.x = x;
} // error
}
return D;
}());
var E = (function () {
function E(x) {
this.x = x;
} // error
}
return E;
}());
var c = new C(1);
var d = new D(1);
var e = new E(1);
var d = new D(1); // error
var e = new E(1); // error
})(Generic || (Generic = {}));
//// [classConstructorAccessibility.d.ts]
declare class C {
x: number;
constructor(x: number);
}
declare class D {
x: number;
private constructor(x);
}
declare class E {
x: number;
protected constructor(x: number);
}
declare var c: C;
declare var d: any;
declare var e: any;
declare module Generic {
}

View File

@ -0,0 +1,59 @@
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 (5 errors) ====
class BaseA {
public constructor(public x: number) { }
createInstance() { new BaseA(1); }
}
class BaseB {
protected constructor(public x: number) { }
createInstance() { new BaseB(1); }
}
class BaseC {
private constructor(public x: number) { }
createInstance() { new BaseC(1); }
}
class DerivedA extends BaseA {
constructor(public x: number) { super(x); }
createInstance() { new DerivedA(1); }
createBaseInstance() { new BaseA(1); }
}
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.
}
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
~~~~~~~~~~~~
!!! error TS2673: Constructor of class 'BaseC' is private and only accessible within the class declaration.
}
var ba = new BaseA(1);
var bb = new BaseB(1); // error
~~~~~~~~~~~~
!!! error TS2674: Constructor of class 'BaseB' is protected and only accessible within the class declaration.
var bc = new BaseC(1); // error
~~~~~~~~~~~~
!!! error TS2673: Constructor of class 'BaseC' is private and only accessible within the class declaration.
var da = new DerivedA(1);
var db = new DerivedB(1);
var dc = new DerivedC(1);

View File

@ -0,0 +1,148 @@
//// [classConstructorAccessibility2.ts]
class BaseA {
public constructor(public x: number) { }
createInstance() { new BaseA(1); }
}
class BaseB {
protected constructor(public x: number) { }
createInstance() { new BaseB(1); }
}
class BaseC {
private constructor(public x: number) { }
createInstance() { new BaseC(1); }
}
class DerivedA extends BaseA {
constructor(public x: number) { super(x); }
createInstance() { new DerivedA(1); }
createBaseInstance() { new BaseA(1); }
}
class DerivedB extends BaseB {
constructor(public x: number) { super(x); }
createInstance() { new DerivedB(1); }
createBaseInstance() { new BaseB(1); } // error
}
class DerivedC extends BaseC { // error
constructor(public x: number) { super(x); }
createInstance() { new DerivedC(1); }
createBaseInstance() { new BaseC(1); } // error
}
var ba = new BaseA(1);
var bb = new BaseB(1); // error
var bc = new BaseC(1); // error
var da = new DerivedA(1);
var db = new DerivedB(1);
var dc = new DerivedC(1);
//// [classConstructorAccessibility2.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 BaseA = (function () {
function BaseA(x) {
this.x = x;
}
BaseA.prototype.createInstance = function () { new BaseA(1); };
return BaseA;
}());
var BaseB = (function () {
function BaseB(x) {
this.x = x;
}
BaseB.prototype.createInstance = function () { new BaseB(1); };
return BaseB;
}());
var BaseC = (function () {
function BaseC(x) {
this.x = x;
}
BaseC.prototype.createInstance = function () { new BaseC(1); };
return BaseC;
}());
var DerivedA = (function (_super) {
__extends(DerivedA, _super);
function DerivedA(x) {
_super.call(this, x);
this.x = x;
}
DerivedA.prototype.createInstance = function () { new DerivedA(1); };
DerivedA.prototype.createBaseInstance = function () { new BaseA(1); };
return DerivedA;
}(BaseA));
var DerivedB = (function (_super) {
__extends(DerivedB, _super);
function DerivedB(x) {
_super.call(this, x);
this.x = x;
}
DerivedB.prototype.createInstance = function () { new DerivedB(1); };
DerivedB.prototype.createBaseInstance = function () { new BaseB(1); }; // error
return DerivedB;
}(BaseB));
var DerivedC = (function (_super) {
__extends(DerivedC, _super);
function DerivedC(x) {
_super.call(this, x);
this.x = x;
}
DerivedC.prototype.createInstance = function () { new DerivedC(1); };
DerivedC.prototype.createBaseInstance = function () { new BaseC(1); }; // error
return DerivedC;
}(BaseC));
var ba = new BaseA(1);
var bb = new BaseB(1); // error
var bc = new BaseC(1); // error
var da = new DerivedA(1);
var db = new DerivedB(1);
var dc = new DerivedC(1);
//// [classConstructorAccessibility2.d.ts]
declare class BaseA {
x: number;
constructor(x: number);
createInstance(): void;
}
declare class BaseB {
x: number;
protected constructor(x: number);
createInstance(): void;
}
declare class BaseC {
x: number;
private constructor(x);
createInstance(): void;
}
declare class DerivedA extends BaseA {
x: number;
constructor(x: number);
createInstance(): void;
createBaseInstance(): void;
}
declare class DerivedB extends BaseB {
x: number;
constructor(x: number);
createInstance(): void;
createBaseInstance(): void;
}
declare class DerivedC extends BaseC {
x: number;
constructor(x: number);
createInstance(): void;
createBaseInstance(): void;
}
declare var ba: BaseA;
declare var bb: any;
declare var bc: any;
declare var da: DerivedA;
declare var db: DerivedB;
declare var dc: DerivedC;

View File

@ -0,0 +1,52 @@
tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility3.ts(21,1): error TS2322: Type 'typeof Baz' is not assignable to type 'typeof Foo'.
Cannot assign a 'protected' constructor type to a 'public' constructor type.
tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility3.ts(22,1): error TS2322: Type 'typeof Qux' is not assignable to type 'typeof Foo'.
Cannot assign a 'private' constructor type to a 'public' constructor type.
tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility3.ts(28,1): error TS2322: Type 'typeof Qux' is not assignable to type 'typeof Baz'.
Cannot assign a 'private' constructor type to a 'protected' constructor type.
==== tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility3.ts (3 errors) ====
class Foo {
constructor(public x: number) { }
}
class Bar {
public constructor(public x: number) { }
}
class Baz {
protected constructor(public x: number) { }
}
class Qux {
private constructor(public x: number) { }
}
// b is public
let a = Foo;
a = Bar;
a = Baz; // error Baz is protected
~
!!! error TS2322: Type 'typeof Baz' is not assignable to type 'typeof Foo'.
!!! error TS2322: Cannot assign a 'protected' constructor type to a 'public' constructor type.
a = Qux; // error Qux is private
~
!!! error TS2322: Type 'typeof Qux' is not assignable to type 'typeof Foo'.
!!! error TS2322: Cannot assign a 'private' constructor type to a 'public' constructor type.
// b is protected
let b = Baz;
b = Foo;
b = Bar;
b = Qux; // error Qux is private
~
!!! error TS2322: Type 'typeof Qux' is not assignable to type 'typeof Baz'.
!!! error TS2322: Cannot assign a 'private' constructor type to a 'protected' constructor type.
// c is private
let c = Qux;
c = Foo;
c = Bar;
c = Baz;

View File

@ -0,0 +1,98 @@
//// [classConstructorAccessibility3.ts]
class Foo {
constructor(public x: number) { }
}
class Bar {
public constructor(public x: number) { }
}
class Baz {
protected constructor(public x: number) { }
}
class Qux {
private constructor(public x: number) { }
}
// b is public
let a = Foo;
a = Bar;
a = Baz; // error Baz is protected
a = Qux; // error Qux is private
// b is protected
let b = Baz;
b = Foo;
b = Bar;
b = Qux; // error Qux is private
// c is private
let c = Qux;
c = Foo;
c = Bar;
c = Baz;
//// [classConstructorAccessibility3.js]
var Foo = (function () {
function Foo(x) {
this.x = x;
}
return Foo;
}());
var Bar = (function () {
function Bar(x) {
this.x = x;
}
return Bar;
}());
var Baz = (function () {
function Baz(x) {
this.x = x;
}
return Baz;
}());
var Qux = (function () {
function Qux(x) {
this.x = x;
}
return Qux;
}());
// b is public
var a = Foo;
a = Bar;
a = Baz; // error Baz is protected
a = Qux; // error Qux is private
// b is protected
var b = Baz;
b = Foo;
b = Bar;
b = Qux; // error Qux is private
// c is private
var c = Qux;
c = Foo;
c = Bar;
c = Baz;
//// [classConstructorAccessibility3.d.ts]
declare class Foo {
x: number;
constructor(x: number);
}
declare class Bar {
x: number;
constructor(x: number);
}
declare class Baz {
x: number;
protected constructor(x: number);
}
declare class Qux {
x: number;
private constructor(x);
}
declare let a: typeof Foo;
declare let b: typeof Baz;
declare let c: typeof Qux;

View File

@ -0,0 +1,93 @@
//// [classConstructorAccessibility4.ts]
class A {
private constructor() { }
method() {
class B {
method() {
new A(); // OK
}
}
class C extends A { // OK
}
}
}
class D {
protected constructor() { }
method() {
class E {
method() {
new D(); // OK
}
}
class F extends D { // OK
}
}
}
//// [classConstructorAccessibility4.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 A = (function () {
function A() {
}
A.prototype.method = function () {
var B = (function () {
function B() {
}
B.prototype.method = function () {
new A(); // OK
};
return B;
}());
var C = (function (_super) {
__extends(C, _super);
function C() {
_super.apply(this, arguments);
}
return C;
}(A));
};
return A;
}());
var D = (function () {
function D() {
}
D.prototype.method = function () {
var E = (function () {
function E() {
}
E.prototype.method = function () {
new D(); // OK
};
return E;
}());
var F = (function (_super) {
__extends(F, _super);
function F() {
_super.apply(this, arguments);
}
return F;
}(D));
};
return D;
}());
//// [classConstructorAccessibility4.d.ts]
declare class A {
private constructor();
method(): void;
}
declare class D {
protected constructor();
method(): void;
}

View File

@ -0,0 +1,53 @@
=== tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility4.ts ===
class A {
>A : Symbol(A, Decl(classConstructorAccessibility4.ts, 0, 0))
private constructor() { }
method() {
>method : Symbol(method, Decl(classConstructorAccessibility4.ts, 2, 29))
class B {
>B : Symbol(B, Decl(classConstructorAccessibility4.ts, 4, 14))
method() {
>method : Symbol(method, Decl(classConstructorAccessibility4.ts, 5, 17))
new A(); // OK
>A : Symbol(A, Decl(classConstructorAccessibility4.ts, 0, 0))
}
}
class C extends A { // OK
>C : Symbol(C, Decl(classConstructorAccessibility4.ts, 9, 9))
>A : Symbol(A, Decl(classConstructorAccessibility4.ts, 0, 0))
}
}
}
class D {
>D : Symbol(D, Decl(classConstructorAccessibility4.ts, 14, 1))
protected constructor() { }
method() {
>method : Symbol(method, Decl(classConstructorAccessibility4.ts, 17, 31))
class E {
>E : Symbol(E, Decl(classConstructorAccessibility4.ts, 19, 14))
method() {
>method : Symbol(method, Decl(classConstructorAccessibility4.ts, 20, 17))
new D(); // OK
>D : Symbol(D, Decl(classConstructorAccessibility4.ts, 14, 1))
}
}
class F extends D { // OK
>F : Symbol(F, Decl(classConstructorAccessibility4.ts, 24, 9))
>D : Symbol(D, Decl(classConstructorAccessibility4.ts, 14, 1))
}
}
}

View File

@ -0,0 +1,55 @@
=== tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility4.ts ===
class A {
>A : A
private constructor() { }
method() {
>method : () => void
class B {
>B : B
method() {
>method : () => void
new A(); // OK
>new A() : A
>A : typeof A
}
}
class C extends A { // OK
>C : C
>A : A
}
}
}
class D {
>D : D
protected constructor() { }
method() {
>method : () => void
class E {
>E : E
method() {
>method : () => void
new D(); // OK
>new D() : D
>D : typeof D
}
}
class F extends D { // OK
>F : F
>D : D
}
}
}

View File

@ -0,0 +1,45 @@
tests/cases/conformance/classes/constructorDeclarations/classConstructorOverloadsAccessibility.ts(3,2): error TS2385: Overload signatures must all be public, private or protected.
tests/cases/conformance/classes/constructorDeclarations/classConstructorOverloadsAccessibility.ts(4,2): error TS2385: Overload signatures must all be public, private or protected.
tests/cases/conformance/classes/constructorDeclarations/classConstructorOverloadsAccessibility.ts(12,2): error TS2385: Overload signatures must all be public, private or protected.
==== tests/cases/conformance/classes/constructorDeclarations/classConstructorOverloadsAccessibility.ts (3 errors) ====
class A {
public constructor(a: boolean) // error
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2385: Overload signatures must all be public, private or protected.
protected constructor(a: number) // error
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2385: Overload signatures must all be public, private or protected.
private constructor(a: string)
private constructor() {
}
}
class B {
protected constructor(a: number) // error
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2385: Overload signatures must all be public, private or protected.
constructor(a: string)
constructor() {
}
}
class C {
protected constructor(a: number)
protected constructor(a: string)
protected constructor() {
}
}
class D {
constructor(a: number)
constructor(a: string)
public constructor() {
}
}

View File

@ -0,0 +1,76 @@
//// [classConstructorOverloadsAccessibility.ts]
class A {
public constructor(a: boolean) // error
protected constructor(a: number) // error
private constructor(a: string)
private constructor() {
}
}
class B {
protected constructor(a: number) // error
constructor(a: string)
constructor() {
}
}
class C {
protected constructor(a: number)
protected constructor(a: string)
protected constructor() {
}
}
class D {
constructor(a: number)
constructor(a: string)
public constructor() {
}
}
//// [classConstructorOverloadsAccessibility.js]
var A = (function () {
function A() {
}
return A;
}());
var B = (function () {
function B() {
}
return B;
}());
var C = (function () {
function C() {
}
return C;
}());
var D = (function () {
function D() {
}
return D;
}());
//// [classConstructorOverloadsAccessibility.d.ts]
declare class A {
constructor(a: boolean);
protected constructor(a: number);
private constructor(a);
}
declare class B {
protected constructor(a: number);
constructor(a: string);
}
declare class C {
protected constructor(a: number);
protected constructor(a: string);
}
declare class D {
constructor(a: number);
constructor(a: string);
}

View File

@ -1,10 +1,9 @@
tests/cases/compiler/implicitAnyInAmbientDeclaration.ts(3,9): error TS7008: Member 'publicMember' implicitly has an 'any' type.
tests/cases/compiler/implicitAnyInAmbientDeclaration.ts(6,16): error TS7010: 'publicFunction', which lacks return-type annotation, implicitly has an 'any' return type.
tests/cases/compiler/implicitAnyInAmbientDeclaration.ts(6,31): error TS7006: Parameter 'x' implicitly has an 'any' type.
tests/cases/compiler/implicitAnyInAmbientDeclaration.ts(8,9): error TS1089: 'private' modifier cannot appear on a constructor declaration.
==== tests/cases/compiler/implicitAnyInAmbientDeclaration.ts (4 errors) ====
==== tests/cases/compiler/implicitAnyInAmbientDeclaration.ts (3 errors) ====
module Test {
declare class C {
public publicMember; // this should be an error
@ -19,7 +18,5 @@ tests/cases/compiler/implicitAnyInAmbientDeclaration.ts(8,9): error TS1089: 'pri
!!! error TS7006: Parameter 'x' implicitly has an 'any' type.
private privateFunction(privateParam); // this should not be an error
private constructor(privateParam);
~~~~~~~
!!! error TS1089: 'private' modifier cannot appear on a constructor declaration.
}
}

View File

@ -4,11 +4,10 @@ tests/cases/compiler/implicitAnyInAmbientDeclaration2.d.ts(2,13): error TS7005:
tests/cases/compiler/implicitAnyInAmbientDeclaration2.d.ts(4,5): error TS7008: Member 'publicMember' implicitly has an 'any' type.
tests/cases/compiler/implicitAnyInAmbientDeclaration2.d.ts(7,12): error TS7010: 'publicFunction', which lacks return-type annotation, implicitly has an 'any' return type.
tests/cases/compiler/implicitAnyInAmbientDeclaration2.d.ts(7,27): error TS7006: Parameter 'x' implicitly has an 'any' type.
tests/cases/compiler/implicitAnyInAmbientDeclaration2.d.ts(9,5): error TS1089: 'private' modifier cannot appear on a constructor declaration.
tests/cases/compiler/implicitAnyInAmbientDeclaration2.d.ts(13,24): error TS7006: Parameter 'publicConsParam' implicitly has an 'any' type.
==== tests/cases/compiler/implicitAnyInAmbientDeclaration2.d.ts (8 errors) ====
==== tests/cases/compiler/implicitAnyInAmbientDeclaration2.d.ts (7 errors) ====
declare function foo(x); // this should be an error
~~~
!!! error TS7010: 'foo', which lacks return-type annotation, implicitly has an 'any' return type.
@ -30,8 +29,6 @@ tests/cases/compiler/implicitAnyInAmbientDeclaration2.d.ts(13,24): error TS7006:
!!! error TS7006: Parameter 'x' implicitly has an 'any' type.
private privateFunction(privateParam); // this should not be an error
private constructor(privateParam); // this should not be an error
~~~~~~~
!!! error TS1089: 'private' modifier cannot appear on a constructor declaration.
}
declare class D {

View File

@ -1,9 +0,0 @@
tests/cases/conformance/parser/ecmascript5/ConstructorDeclarations/parserConstructorDeclaration5.ts(2,3): error TS1089: 'private' modifier cannot appear on a constructor declaration.
==== tests/cases/conformance/parser/ecmascript5/ConstructorDeclarations/parserConstructorDeclaration5.ts (1 errors) ====
class C {
private constructor() { }
~~~~~~~
!!! error TS1089: 'private' modifier cannot appear on a constructor declaration.
}

View File

@ -0,0 +1,6 @@
=== tests/cases/conformance/parser/ecmascript5/ConstructorDeclarations/parserConstructorDeclaration5.ts ===
class C {
>C : Symbol(C, Decl(parserConstructorDeclaration5.ts, 0, 0))
private constructor() { }
}

View File

@ -0,0 +1,6 @@
=== tests/cases/conformance/parser/ecmascript5/ConstructorDeclarations/parserConstructorDeclaration5.ts ===
class C {
>C : C
private constructor() { }
}

View File

@ -8,16 +8,15 @@ tests/cases/compiler/protectedMembers.ts(48,1): error TS2445: Property 'sx' is p
tests/cases/compiler/protectedMembers.ts(49,1): error TS2445: Property 'sf' is protected and only accessible within class 'C2' and its subclasses.
tests/cases/compiler/protectedMembers.ts(68,9): error TS2446: Property 'x' is protected and only accessible through an instance of class 'C'.
tests/cases/compiler/protectedMembers.ts(69,9): error TS2446: Property 'x' is protected and only accessible through an instance of class 'C'.
tests/cases/compiler/protectedMembers.ts(86,5): error TS1089: 'protected' modifier cannot appear on a constructor declaration.
tests/cases/compiler/protectedMembers.ts(98,1): error TS2322: Type 'B1' is not assignable to type 'A1'.
tests/cases/compiler/protectedMembers.ts(97,1): error TS2322: Type 'B1' is not assignable to type 'A1'.
Property 'x' is protected but type 'B1' is not a class derived from 'A1'.
tests/cases/compiler/protectedMembers.ts(99,1): error TS2322: Type 'A1' is not assignable to type 'B1'.
tests/cases/compiler/protectedMembers.ts(98,1): error TS2322: Type 'A1' is not assignable to type 'B1'.
Property 'x' is protected in type 'A1' but public in type 'B1'.
tests/cases/compiler/protectedMembers.ts(112,7): error TS2415: Class 'B3' incorrectly extends base class 'A3'.
tests/cases/compiler/protectedMembers.ts(111,7): error TS2415: Class 'B3' incorrectly extends base class 'A3'.
Property 'x' is protected in type 'B3' but public in type 'A3'.
==== tests/cases/compiler/protectedMembers.ts (14 errors) ====
==== tests/cases/compiler/protectedMembers.ts (13 errors) ====
// Class with protected members
class C1 {
protected x: number;
@ -122,10 +121,7 @@ tests/cases/compiler/protectedMembers.ts(112,7): error TS2415: Class 'B3' incorr
}
class CC {
// Error, constructor cannot be protected
protected constructor() {
~~~~~~~~~
!!! error TS1089: 'protected' modifier cannot appear on a constructor declaration.
}
}

View File

@ -83,7 +83,6 @@ interface E extends C {
}
class CC {
// Error, constructor cannot be protected
protected constructor() {
}
}
@ -214,7 +213,6 @@ var D = (function (_super) {
return D;
}(C));
var CC = (function () {
// Error, constructor cannot be protected
function CC() {
}
return CC;

View File

@ -1,36 +1,24 @@
tests/cases/conformance/types/members/typesWithPrivateConstructor.ts(4,5): error TS1089: 'private' modifier cannot appear on a constructor declaration.
tests/cases/conformance/types/members/typesWithPrivateConstructor.ts(8,5): error TS2322: Type 'Function' is not assignable to type '() => void'.
Type 'Function' provides no match for the signature '(): void'
tests/cases/conformance/types/members/typesWithPrivateConstructor.ts(11,5): error TS1089: 'private' modifier cannot appear on a constructor declaration.
tests/cases/conformance/types/members/typesWithPrivateConstructor.ts(12,5): error TS1089: 'private' modifier cannot appear on a constructor declaration.
tests/cases/conformance/types/members/typesWithPrivateConstructor.ts(15,10): error TS2346: Supplied parameters do not match any signature of call target.
tests/cases/conformance/types/members/typesWithPrivateConstructor.ts(6,9): error TS2673: Constructor of class 'C' is private and only accessible within the class declaration.
tests/cases/conformance/types/members/typesWithPrivateConstructor.ts(14,10): error TS2673: Constructor of class 'C2' is private and only accessible within the class declaration.
==== tests/cases/conformance/types/members/typesWithPrivateConstructor.ts (5 errors) ====
// private constructors are not allowed
==== tests/cases/conformance/types/members/typesWithPrivateConstructor.ts (2 errors) ====
class C {
private constructor() { }
~~~~~~~
!!! error TS1089: 'private' modifier cannot appear on a constructor declaration.
}
var c = new C();
var c = new C(); // error C is private
~~~~~~~
!!! error TS2673: Constructor of class 'C' is private and only accessible within the class declaration.
var r: () => void = c.constructor;
~
!!! error TS2322: Type 'Function' is not assignable to type '() => void'.
!!! error TS2322: Type 'Function' provides no match for the signature '(): void'
class C2 {
private constructor(x: number);
~~~~~~~
!!! error TS1089: 'private' modifier cannot appear on a constructor declaration.
private constructor(x: any) { }
~~~~~~~
!!! error TS1089: 'private' modifier cannot appear on a constructor declaration.
}
var c2 = new C2();
var c2 = new C2(); // error C2 is private
~~~~~~~~
!!! error TS2346: Supplied parameters do not match any signature of call target.
!!! error TS2673: Constructor of class 'C2' is private and only accessible within the class declaration.
var r2: (x: number) => void = c2.constructor;

View File

@ -1,11 +1,10 @@
//// [typesWithPrivateConstructor.ts]
// private constructors are not allowed
class C {
private constructor() { }
}
var c = new C();
var c = new C(); // error C is private
var r: () => void = c.constructor;
class C2 {
@ -13,22 +12,34 @@ class C2 {
private constructor(x: any) { }
}
var c2 = new C2();
var c2 = new C2(); // error C2 is private
var r2: (x: number) => void = c2.constructor;
//// [typesWithPrivateConstructor.js]
// private constructors are not allowed
var C = (function () {
function C() {
}
return C;
}());
var c = new C();
var c = new C(); // error C is private
var r = c.constructor;
var C2 = (function () {
function C2(x) {
}
return C2;
}());
var c2 = new C2();
var c2 = new C2(); // error C2 is private
var r2 = c2.constructor;
//// [typesWithPrivateConstructor.d.ts]
declare class C {
private constructor();
}
declare var c: any;
declare var r: () => void;
declare class C2 {
private constructor(x);
}
declare var c2: any;
declare var r2: (x: number) => void;

View File

@ -0,0 +1,24 @@
tests/cases/conformance/types/members/typesWithProtectedConstructor.ts(6,9): error TS2674: Constructor of class 'C' is protected and only accessible within the class declaration.
tests/cases/conformance/types/members/typesWithProtectedConstructor.ts(14,10): error TS2674: Constructor of class 'C2' is protected and only accessible within the class declaration.
==== tests/cases/conformance/types/members/typesWithProtectedConstructor.ts (2 errors) ====
class C {
protected constructor() { }
}
var c = new C(); // error C is protected
~~~~~~~
!!! error TS2674: Constructor of class 'C' is protected and only accessible within the class declaration.
var r: () => void = c.constructor;
class C2 {
protected constructor(x: number);
protected constructor(x: any) { }
}
var c2 = new C2(); // error C2 is protected
~~~~~~~~
!!! error TS2674: Constructor of class 'C2' is protected and only accessible within the class declaration.
var r2: (x: number) => void = c2.constructor;

View File

@ -0,0 +1,45 @@
//// [typesWithProtectedConstructor.ts]
class C {
protected constructor() { }
}
var c = new C(); // error C is protected
var r: () => void = c.constructor;
class C2 {
protected constructor(x: number);
protected constructor(x: any) { }
}
var c2 = new C2(); // error C2 is protected
var r2: (x: number) => void = c2.constructor;
//// [typesWithProtectedConstructor.js]
var C = (function () {
function C() {
}
return C;
}());
var c = new C(); // error C is protected
var r = c.constructor;
var C2 = (function () {
function C2(x) {
}
return C2;
}());
var c2 = new C2(); // error C2 is protected
var r2 = c2.constructor;
//// [typesWithProtectedConstructor.d.ts]
declare class C {
protected constructor();
}
declare var c: any;
declare var r: () => void;
declare class C2 {
protected constructor(x: number);
}
declare var c2: any;
declare var r2: (x: number) => void;

View File

@ -82,7 +82,6 @@ interface E extends C {
}
class CC {
// Error, constructor cannot be protected
protected constructor() {
}
}

View File

@ -1,18 +1,20 @@
// @declaration: true
class C {
public constructor(public x: number) { }
}
class D {
private constructor(public x: number) { } // error
private constructor(public x: number) { }
}
class E {
protected constructor(public x: number) { } // error
protected constructor(public x: number) { }
}
var c = new C(1);
var d = new D(1);
var e = new E(1);
var d = new D(1); // error
var e = new E(1); // error
module Generic {
class C<T> {
@ -20,14 +22,14 @@ module Generic {
}
class D<T> {
private constructor(public x: T) { } // error
private constructor(public x: T) { }
}
class E<T> {
protected constructor(public x: T) { } // error
protected constructor(public x: T) { }
}
var c = new C(1);
var d = new D(1);
var e = new E(1);
var d = new D(1); // error
var e = new E(1); // error
}

View File

@ -0,0 +1,42 @@
// @declaration: true
class BaseA {
public constructor(public x: number) { }
createInstance() { new BaseA(1); }
}
class BaseB {
protected constructor(public x: number) { }
createInstance() { new BaseB(1); }
}
class BaseC {
private constructor(public x: number) { }
createInstance() { new BaseC(1); }
}
class DerivedA extends BaseA {
constructor(public x: number) { super(x); }
createInstance() { new DerivedA(1); }
createBaseInstance() { new BaseA(1); }
}
class DerivedB extends BaseB {
constructor(public x: number) { super(x); }
createInstance() { new DerivedB(1); }
createBaseInstance() { new BaseB(1); } // error
}
class DerivedC extends BaseC { // error
constructor(public x: number) { super(x); }
createInstance() { new DerivedC(1); }
createBaseInstance() { new BaseC(1); } // error
}
var ba = new BaseA(1);
var bb = new BaseB(1); // error
var bc = new BaseC(1); // error
var da = new DerivedA(1);
var db = new DerivedB(1);
var dc = new DerivedC(1);

View File

@ -0,0 +1,35 @@
// @declaration: true
class Foo {
constructor(public x: number) { }
}
class Bar {
public constructor(public x: number) { }
}
class Baz {
protected constructor(public x: number) { }
}
class Qux {
private constructor(public x: number) { }
}
// b is public
let a = Foo;
a = Bar;
a = Baz; // error Baz is protected
a = Qux; // error Qux is private
// b is protected
let b = Baz;
b = Foo;
b = Bar;
b = Qux; // error Qux is private
// c is private
let c = Qux;
c = Foo;
c = Bar;
c = Baz;

View File

@ -0,0 +1,31 @@
// @declaration: true
class A {
private constructor() { }
method() {
class B {
method() {
new A(); // OK
}
}
class C extends A { // OK
}
}
}
class D {
protected constructor() { }
method() {
class E {
method() {
new D(); // OK
}
}
class F extends D { // OK
}
}
}

View File

@ -0,0 +1,34 @@
// @declaration: true
class A {
public constructor(a: boolean) // error
protected constructor(a: number) // error
private constructor(a: string)
private constructor() {
}
}
class B {
protected constructor(a: number) // error
constructor(a: string)
constructor() {
}
}
class C {
protected constructor(a: number)
protected constructor(a: string)
protected constructor() {
}
}
class D {
constructor(a: number)
constructor(a: string)
public constructor() {
}
}

View File

@ -1,10 +1,10 @@
// private constructors are not allowed
// @declaration: true
class C {
private constructor() { }
}
var c = new C();
var c = new C(); // error C is private
var r: () => void = c.constructor;
class C2 {
@ -12,5 +12,5 @@ class C2 {
private constructor(x: any) { }
}
var c2 = new C2();
var c2 = new C2(); // error C2 is private
var r2: (x: number) => void = c2.constructor;

View File

@ -0,0 +1,16 @@
// @declaration: true
class C {
protected constructor() { }
}
var c = new C(); // error C is protected
var r: () => void = c.constructor;
class C2 {
protected constructor(x: number);
protected constructor(x: any) { }
}
var c2 = new C2(); // error C2 is protected
var r2: (x: number) => void = c2.constructor;

View File

@ -0,0 +1,9 @@
/// <reference path='fourslash.ts' />
////class A {
//// private constructor() {}
////}
////var x = new A(/*1*/
goTo.marker("1");
verify.not.signatureHelpPresent();

View File

@ -0,0 +1,9 @@
/// <reference path='fourslash.ts' />
////class A {
//// protected constructor() {}
////}
////var x = new A(/*1*/
goTo.marker("1");
verify.not.signatureHelpPresent();