diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index bff8662b98ad6..ab057d430a434 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -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 = getClassLikeDeclarationOfSymbol(declaration.parent.symbol); + const declaringClass = 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 = getClassLikeDeclarationOfSymbol(type.symbol); + if (!isNodeWithinClass(node, typeClassDeclaration)) { + error(node, Diagnostics.Cannot_extend_a_class_0_Class_constructor_is_marked_as_private, (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 = 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"); } diff --git a/src/compiler/declarationEmitter.ts b/src/compiler/declarationEmitter.ts index d8bdd2fb52f33..1328a2e84844c 100644 --- a/src/compiler/declarationEmitter.ts +++ b/src/compiler/declarationEmitter.ts @@ -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) { diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 461efb7143e08..16cf191164276 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -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 } -} \ No newline at end of file +} diff --git a/tests/baselines/reference/Protected3.errors.txt b/tests/baselines/reference/Protected3.errors.txt deleted file mode 100644 index 688422a1e0f6f..0000000000000 --- a/tests/baselines/reference/Protected3.errors.txt +++ /dev/null @@ -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. - } \ No newline at end of file diff --git a/tests/baselines/reference/Protected3.symbols b/tests/baselines/reference/Protected3.symbols new file mode 100644 index 0000000000000..a9882189902f4 --- /dev/null +++ b/tests/baselines/reference/Protected3.symbols @@ -0,0 +1,6 @@ +=== tests/cases/conformance/parser/ecmascript5/Protected/Protected3.ts === +class C { +>C : Symbol(C, Decl(Protected3.ts, 0, 0)) + + protected constructor() { } +} diff --git a/tests/baselines/reference/Protected3.types b/tests/baselines/reference/Protected3.types new file mode 100644 index 0000000000000..d3f938a443191 --- /dev/null +++ b/tests/baselines/reference/Protected3.types @@ -0,0 +1,6 @@ +=== tests/cases/conformance/parser/ecmascript5/Protected/Protected3.ts === +class C { +>C : C + + protected constructor() { } +} diff --git a/tests/baselines/reference/classConstructorAccessibility.errors.txt b/tests/baselines/reference/classConstructorAccessibility.errors.txt index c22f3593bc57f..c79633ba33d92 100644 --- a/tests/baselines/reference/classConstructorAccessibility.errors.txt +++ b/tests/baselines/reference/classConstructorAccessibility.errors.txt @@ -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' is private and only accessible within the class declaration. +tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts(33,13): error TS2674: Constructor of class 'E' 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 { @@ -31,19 +32,19 @@ tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessib } class D { - private constructor(public x: T) { } // error - ~~~~~~~ -!!! error TS1089: 'private' modifier cannot appear on a constructor declaration. + private constructor(public x: T) { } } class E { - 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' 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. } \ No newline at end of file diff --git a/tests/baselines/reference/classConstructorAccessibility.js b/tests/baselines/reference/classConstructorAccessibility.js index fed963858454b..efc3f3c273cfa 100644 --- a/tests/baselines/reference/classConstructorAccessibility.js +++ b/tests/baselines/reference/classConstructorAccessibility.js @@ -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 { @@ -21,16 +22,16 @@ module Generic { } class D { - private constructor(public x: T) { } // error + private constructor(public x: T) { } } class E { - 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 { +} diff --git a/tests/baselines/reference/classConstructorAccessibility2.errors.txt b/tests/baselines/reference/classConstructorAccessibility2.errors.txt new file mode 100644 index 0000000000000..7bd784ac268c2 --- /dev/null +++ b/tests/baselines/reference/classConstructorAccessibility2.errors.txt @@ -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); \ No newline at end of file diff --git a/tests/baselines/reference/classConstructorAccessibility2.js b/tests/baselines/reference/classConstructorAccessibility2.js new file mode 100644 index 0000000000000..e19589ece4521 --- /dev/null +++ b/tests/baselines/reference/classConstructorAccessibility2.js @@ -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; diff --git a/tests/baselines/reference/classConstructorAccessibility3.errors.txt b/tests/baselines/reference/classConstructorAccessibility3.errors.txt new file mode 100644 index 0000000000000..1b96db289dc79 --- /dev/null +++ b/tests/baselines/reference/classConstructorAccessibility3.errors.txt @@ -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; \ No newline at end of file diff --git a/tests/baselines/reference/classConstructorAccessibility3.js b/tests/baselines/reference/classConstructorAccessibility3.js new file mode 100644 index 0000000000000..acc7d38aa5534 --- /dev/null +++ b/tests/baselines/reference/classConstructorAccessibility3.js @@ -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; diff --git a/tests/baselines/reference/classConstructorAccessibility4.js b/tests/baselines/reference/classConstructorAccessibility4.js new file mode 100644 index 0000000000000..6342facae21fa --- /dev/null +++ b/tests/baselines/reference/classConstructorAccessibility4.js @@ -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; +} diff --git a/tests/baselines/reference/classConstructorAccessibility4.symbols b/tests/baselines/reference/classConstructorAccessibility4.symbols new file mode 100644 index 0000000000000..e3d8301ca689e --- /dev/null +++ b/tests/baselines/reference/classConstructorAccessibility4.symbols @@ -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)) + } + } +} diff --git a/tests/baselines/reference/classConstructorAccessibility4.types b/tests/baselines/reference/classConstructorAccessibility4.types new file mode 100644 index 0000000000000..1eb5a25e2208b --- /dev/null +++ b/tests/baselines/reference/classConstructorAccessibility4.types @@ -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 + } + } +} diff --git a/tests/baselines/reference/classConstructorOverloadsAccessibility.errors.txt b/tests/baselines/reference/classConstructorOverloadsAccessibility.errors.txt new file mode 100644 index 0000000000000..8882b9f018038 --- /dev/null +++ b/tests/baselines/reference/classConstructorOverloadsAccessibility.errors.txt @@ -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() { + + } + } \ No newline at end of file diff --git a/tests/baselines/reference/classConstructorOverloadsAccessibility.js b/tests/baselines/reference/classConstructorOverloadsAccessibility.js new file mode 100644 index 0000000000000..3914c29b78525 --- /dev/null +++ b/tests/baselines/reference/classConstructorOverloadsAccessibility.js @@ -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); +} diff --git a/tests/baselines/reference/implicitAnyInAmbientDeclaration.errors.txt b/tests/baselines/reference/implicitAnyInAmbientDeclaration.errors.txt index 1e66f26d0d223..493fc13db043c 100644 --- a/tests/baselines/reference/implicitAnyInAmbientDeclaration.errors.txt +++ b/tests/baselines/reference/implicitAnyInAmbientDeclaration.errors.txt @@ -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. } } \ No newline at end of file diff --git a/tests/baselines/reference/implicitAnyInAmbientDeclaration2.d.errors.txt b/tests/baselines/reference/implicitAnyInAmbientDeclaration2.d.errors.txt index 54fe39e2efe84..03de82c731db0 100644 --- a/tests/baselines/reference/implicitAnyInAmbientDeclaration2.d.errors.txt +++ b/tests/baselines/reference/implicitAnyInAmbientDeclaration2.d.errors.txt @@ -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 { diff --git a/tests/baselines/reference/parserConstructorDeclaration5.errors.txt b/tests/baselines/reference/parserConstructorDeclaration5.errors.txt deleted file mode 100644 index 4589ad95a32f7..0000000000000 --- a/tests/baselines/reference/parserConstructorDeclaration5.errors.txt +++ /dev/null @@ -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. - } \ No newline at end of file diff --git a/tests/baselines/reference/parserConstructorDeclaration5.symbols b/tests/baselines/reference/parserConstructorDeclaration5.symbols new file mode 100644 index 0000000000000..6eb3d32a0f0c9 --- /dev/null +++ b/tests/baselines/reference/parserConstructorDeclaration5.symbols @@ -0,0 +1,6 @@ +=== tests/cases/conformance/parser/ecmascript5/ConstructorDeclarations/parserConstructorDeclaration5.ts === +class C { +>C : Symbol(C, Decl(parserConstructorDeclaration5.ts, 0, 0)) + + private constructor() { } +} diff --git a/tests/baselines/reference/parserConstructorDeclaration5.types b/tests/baselines/reference/parserConstructorDeclaration5.types new file mode 100644 index 0000000000000..ae5d2c44b49f8 --- /dev/null +++ b/tests/baselines/reference/parserConstructorDeclaration5.types @@ -0,0 +1,6 @@ +=== tests/cases/conformance/parser/ecmascript5/ConstructorDeclarations/parserConstructorDeclaration5.ts === +class C { +>C : C + + private constructor() { } +} diff --git a/tests/baselines/reference/protectedMembers.errors.txt b/tests/baselines/reference/protectedMembers.errors.txt index c35bc25fe7196..666be34d10c05 100644 --- a/tests/baselines/reference/protectedMembers.errors.txt +++ b/tests/baselines/reference/protectedMembers.errors.txt @@ -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. } } diff --git a/tests/baselines/reference/protectedMembers.js b/tests/baselines/reference/protectedMembers.js index e541f697f4494..dcc68e0c946c4 100644 --- a/tests/baselines/reference/protectedMembers.js +++ b/tests/baselines/reference/protectedMembers.js @@ -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; diff --git a/tests/baselines/reference/typesWithPrivateConstructor.errors.txt b/tests/baselines/reference/typesWithPrivateConstructor.errors.txt index 261038a1f4ab4..ab8ea4e26ad18 100644 --- a/tests/baselines/reference/typesWithPrivateConstructor.errors.txt +++ b/tests/baselines/reference/typesWithPrivateConstructor.errors.txt @@ -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; \ No newline at end of file diff --git a/tests/baselines/reference/typesWithPrivateConstructor.js b/tests/baselines/reference/typesWithPrivateConstructor.js index d894eeda49a07..1795ee6b3166c 100644 --- a/tests/baselines/reference/typesWithPrivateConstructor.js +++ b/tests/baselines/reference/typesWithPrivateConstructor.js @@ -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; diff --git a/tests/baselines/reference/typesWithProtectedConstructor.errors.txt b/tests/baselines/reference/typesWithProtectedConstructor.errors.txt new file mode 100644 index 0000000000000..2a5a059f44d4a --- /dev/null +++ b/tests/baselines/reference/typesWithProtectedConstructor.errors.txt @@ -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; \ No newline at end of file diff --git a/tests/baselines/reference/typesWithProtectedConstructor.js b/tests/baselines/reference/typesWithProtectedConstructor.js new file mode 100644 index 0000000000000..e75b3b6ecd3ab --- /dev/null +++ b/tests/baselines/reference/typesWithProtectedConstructor.js @@ -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; diff --git a/tests/cases/compiler/protectedMembers.ts b/tests/cases/compiler/protectedMembers.ts index ae32e47242505..b7528f26068fb 100644 --- a/tests/cases/compiler/protectedMembers.ts +++ b/tests/cases/compiler/protectedMembers.ts @@ -82,7 +82,6 @@ interface E extends C { } class CC { - // Error, constructor cannot be protected protected constructor() { } } diff --git a/tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts b/tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts index c2e4855e63a3b..1c9a801429db5 100644 --- a/tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts +++ b/tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts @@ -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 { @@ -20,14 +22,14 @@ module Generic { } class D { - private constructor(public x: T) { } // error + private constructor(public x: T) { } } class E { - 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 } diff --git a/tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility2.ts b/tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility2.ts new file mode 100644 index 0000000000000..2a961e2c0679b --- /dev/null +++ b/tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility2.ts @@ -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); \ No newline at end of file diff --git a/tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility3.ts b/tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility3.ts new file mode 100644 index 0000000000000..91bb4873d96b4 --- /dev/null +++ b/tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility3.ts @@ -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; \ No newline at end of file diff --git a/tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility4.ts b/tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility4.ts new file mode 100644 index 0000000000000..3760f2176aebe --- /dev/null +++ b/tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility4.ts @@ -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 + } + } +} \ No newline at end of file diff --git a/tests/cases/conformance/classes/constructorDeclarations/classConstructorOverloadsAccessibility.ts b/tests/cases/conformance/classes/constructorDeclarations/classConstructorOverloadsAccessibility.ts new file mode 100644 index 0000000000000..5ed20d038534d --- /dev/null +++ b/tests/cases/conformance/classes/constructorDeclarations/classConstructorOverloadsAccessibility.ts @@ -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() { + + } +} \ No newline at end of file diff --git a/tests/cases/conformance/types/members/typesWithPrivateConstructor.ts b/tests/cases/conformance/types/members/typesWithPrivateConstructor.ts index 4fb24ca58e45d..321864e175178 100644 --- a/tests/cases/conformance/types/members/typesWithPrivateConstructor.ts +++ b/tests/cases/conformance/types/members/typesWithPrivateConstructor.ts @@ -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; \ No newline at end of file diff --git a/tests/cases/conformance/types/members/typesWithProtectedConstructor.ts b/tests/cases/conformance/types/members/typesWithProtectedConstructor.ts new file mode 100644 index 0000000000000..e7f6adc38a869 --- /dev/null +++ b/tests/cases/conformance/types/members/typesWithProtectedConstructor.ts @@ -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; \ No newline at end of file diff --git a/tests/cases/fourslash/quickInfoOnPrivateConstructorCall.ts b/tests/cases/fourslash/quickInfoOnPrivateConstructorCall.ts new file mode 100644 index 0000000000000..5ebdcd815b293 --- /dev/null +++ b/tests/cases/fourslash/quickInfoOnPrivateConstructorCall.ts @@ -0,0 +1,9 @@ +/// + +////class A { +//// private constructor() {} +////} +////var x = new A(/*1*/ + +goTo.marker("1"); +verify.not.signatureHelpPresent(); \ No newline at end of file diff --git a/tests/cases/fourslash/quickInfoOnProtectedConstructorCall.ts b/tests/cases/fourslash/quickInfoOnProtectedConstructorCall.ts new file mode 100644 index 0000000000000..094a07f3d5104 --- /dev/null +++ b/tests/cases/fourslash/quickInfoOnProtectedConstructorCall.ts @@ -0,0 +1,9 @@ +/// + +////class A { +//// protected constructor() {} +////} +////var x = new A(/*1*/ + +goTo.marker("1"); +verify.not.signatureHelpPresent(); \ No newline at end of file