From f869b41f144be3cbed1aa0ad3c66e125d57f9752 Mon Sep 17 00:00:00 2001 From: AbubakerB Date: Wed, 3 Feb 2016 01:07:09 +0000 Subject: [PATCH 01/15] Added private and protected modifiers to constructors --- src/compiler/checker.ts | 101 ++++++++++++++++++++++----- src/compiler/diagnosticMessages.json | 16 +++++ 2 files changed, 101 insertions(+), 16 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 07ec5023d5ba5..1ce5b51c66d21 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5889,16 +5889,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 - // as it would otherwise be possible to new an abstract class. Note that the assignablity - // 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); + 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 assignablity + // 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 (!constructorRelatedTo(sourceSignatures[0], targetSignatures[0], reportErrors)) { + return Ternary.False; } - return Ternary.False; } let result = Ternary.True; @@ -6052,6 +6056,32 @@ namespace ts { } return Ternary.True; } + + function constructorRelatedTo(sourceSignature: Signature, targetSignature: Signature, reportErrors: boolean) { + if (sourceSignature && targetSignature && sourceSignature.declaration && targetSignature.declaration) { + const sourceAccessibility = sourceSignature.declaration.flags & (NodeFlags.Private | NodeFlags.Protected); + const targetAccessibility = targetSignature.declaration.flags & (NodeFlags.Private | NodeFlags.Protected); + + const isRelated = sourceAccessibility === targetAccessibility; + if (!isRelated && reportErrors) { + reportError(Diagnostics.Cannot_assign_a_0_constructor_type_to_a_1_constructor_type, flagsToString(sourceAccessibility), flagsToString(targetAccessibility)); + } + + return isRelated; + } + + return true; + + function flagsToString(flags: NodeFlags) { + if (flags === NodeFlags.Private) { + return "private"; + } + if (flags === NodeFlags.Protected) { + return "protected"; + } + return "public"; + } + } } // Return true if the given type is the constructor type for an abstract class @@ -10103,6 +10133,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); } @@ -10123,6 +10156,37 @@ 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 declaringClass = getDeclaredTypeOfSymbol(declaration.parent.symbol); + const enclosingClassDeclaration = getContainingClass(node); + const enclosingClass = enclosingClassDeclaration ? getDeclaredTypeOfSymbol(getSymbolOfNode(enclosingClassDeclaration)) : undefined; + + // A private or protected constructor can only be instantiated within it's own class + if (declaringClass !== enclosingClass) { + if (flags & NodeFlags.Private) { + error(node, Diagnostics.Constructor_of_type_0_is_private_and_only_accessible_within_class_1, signatureToString(signature), typeToString(declaringClass)); + } + if (flags & NodeFlags.Protected) { + error(node, Diagnostics.Constructor_of_type_0_is_protected_and_only_accessible_within_class_1, signatureToString(signature), typeToString(declaringClass)); + } + return false; + } + + return true; + } + function resolveTaggedTemplateExpression(node: TaggedTemplateExpression, candidatesOutArray: Signature[]): Signature { const tagType = checkExpression(node.tag); const apparentType = getApparentType(tagType); @@ -12059,7 +12123,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); @@ -13928,6 +13992,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); @@ -13983,6 +14048,16 @@ 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) { + error(node, Diagnostics.Cannot_extend_private_class_0, (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 @@ -16348,12 +16423,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/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index c848ebc3a10d6..2ee388ff42e75 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1823,6 +1823,22 @@ "category": "Error", "code": 2671 }, + "Cannot assign a '{0}' constructor type to a '{1}' constructor type.": { + "category": "Error", + "code": 2672 + }, + "Constructor of type '{0}' is private and only accessible within class '{1}'.": { + "category": "Error", + "code": 2673 + }, + "Constructor of type '{0}' is protected and only accessible within class '{1}'.": { + "category": "Error", + "code": 2674 + }, + "Cannot extend private class '{0}'.": { + "category": "Error", + "code": 2675 + }, "Import declaration '{0}' is using private name '{1}'.": { "category": "Error", "code": 4000 From c351ffcc75c1d257f72a3e86faaa640d8daefdf3 Mon Sep 17 00:00:00 2001 From: AbubakerB Date: Wed, 3 Feb 2016 22:48:33 +0000 Subject: [PATCH 02/15] Added and updated tests for constructor visibility --- .../baselines/reference/Protected3.errors.txt | 9 -- tests/baselines/reference/Protected3.symbols | 6 + tests/baselines/reference/Protected3.types | 6 + .../classConstructorAccessibility.errors.txt | 41 ++--- .../classConstructorAccessibility.js | 53 +++++-- .../classConstructorAccessibility2.errors.txt | 59 +++++++ .../classConstructorAccessibility2.js | 148 ++++++++++++++++++ .../classConstructorAccessibility3.errors.txt | 77 +++++++++ .../classConstructorAccessibility3.js | 98 ++++++++++++ ...nstructorOverloadsAccessibility.errors.txt | 45 ++++++ .../classConstructorOverloadsAccessibility.js | 76 +++++++++ ...implicitAnyInAmbientDeclaration.errors.txt | 5 +- ...licitAnyInAmbientDeclaration2.d.errors.txt | 5 +- .../parserConstructorDeclaration5.errors.txt | 9 -- .../parserConstructorDeclaration5.symbols | 6 + .../parserConstructorDeclaration5.types | 6 + .../reference/protectedMembers.errors.txt | 12 +- tests/baselines/reference/protectedMembers.js | 2 - .../typesWithPrivateConstructor.errors.txt | 28 +--- .../reference/typesWithPrivateConstructor.js | 23 ++- .../typesWithProtectedConstructor.errors.txt | 24 +++ .../typesWithProtectedConstructor.js | 45 ++++++ tests/cases/compiler/protectedMembers.ts | 1 - .../classConstructorAccessibility.ts | 18 ++- .../classConstructorAccessibility2.ts | 42 +++++ .../classConstructorAccessibility3.ts | 35 +++++ .../classConstructorOverloadsAccessibility.ts | 34 ++++ .../members/typesWithPrivateConstructor.ts | 6 +- .../members/typesWithProtectedConstructor.ts | 16 ++ .../quickInfoOnPrivateConstructorCall.ts | 9 ++ .../quickInfoOnProtectedConstructorCall.ts | 9 ++ 31 files changed, 843 insertions(+), 110 deletions(-) delete mode 100644 tests/baselines/reference/Protected3.errors.txt create mode 100644 tests/baselines/reference/Protected3.symbols create mode 100644 tests/baselines/reference/Protected3.types create mode 100644 tests/baselines/reference/classConstructorAccessibility2.errors.txt create mode 100644 tests/baselines/reference/classConstructorAccessibility2.js create mode 100644 tests/baselines/reference/classConstructorAccessibility3.errors.txt create mode 100644 tests/baselines/reference/classConstructorAccessibility3.js create mode 100644 tests/baselines/reference/classConstructorOverloadsAccessibility.errors.txt create mode 100644 tests/baselines/reference/classConstructorOverloadsAccessibility.js delete mode 100644 tests/baselines/reference/parserConstructorDeclaration5.errors.txt create mode 100644 tests/baselines/reference/parserConstructorDeclaration5.symbols create mode 100644 tests/baselines/reference/parserConstructorDeclaration5.types create mode 100644 tests/baselines/reference/typesWithProtectedConstructor.errors.txt create mode 100644 tests/baselines/reference/typesWithProtectedConstructor.js create mode 100644 tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility2.ts create mode 100644 tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility3.ts create mode 100644 tests/cases/conformance/classes/constructorDeclarations/classConstructorOverloadsAccessibility.ts create mode 100644 tests/cases/conformance/types/members/typesWithProtectedConstructor.ts create mode 100644 tests/cases/fourslash/quickInfoOnPrivateConstructorCall.ts create mode 100644 tests/cases/fourslash/quickInfoOnProtectedConstructorCall.ts 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..a24ec6c63d1bf 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 type '(x: number): D' is private and only accessible within class 'D'. +tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts(16,9): error TS2674: Constructor of type '(x: number): E' is protected and only accessible within class 'E'. +tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts(32,13): error TS2673: Constructor of type '(x: T): D' is private and only accessible within class 'D'. +tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts(33,13): error TS2674: Constructor of type '(x: T): E' is protected and only accessible within class 'E'. ==== 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 type '(x: number): D' is private and only accessible within class 'D'. + var e = new E(1); // error + ~~~~~~~~ +!!! error TS2674: Constructor of type '(x: number): E' is protected and only accessible within class 'E'. 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 type '(x: T): D' is private and only accessible within class 'D'. + var e = new E(1); // error + ~~~~~~~~ +!!! error TS2674: Constructor of type '(x: T): E' is protected and only accessible within class 'E'. } \ No newline at end of file diff --git a/tests/baselines/reference/classConstructorAccessibility.js b/tests/baselines/reference/classConstructorAccessibility.js index fed963858454b..de7e4a83bb872 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; + constructor(x); +} +declare class E { + x: number; + 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..1c6fc46edb328 --- /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 type '(x: number): BaseB' is protected and only accessible within class 'BaseB'. +tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility2.ts(29,24): error TS2675: Cannot extend private class 'BaseC'. +tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility2.ts(32,28): error TS2673: Constructor of type '(x: number): BaseC' is private and only accessible within class 'BaseC'. +tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility2.ts(36,10): error TS2674: Constructor of type '(x: number): BaseB' is protected and only accessible within class 'BaseB'. +tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility2.ts(37,10): error TS2673: Constructor of type '(x: number): BaseC' is private and only accessible within class 'BaseC'. + + +==== 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 type '(x: number): BaseB' is protected and only accessible within class 'BaseB'. + } + + class DerivedC extends BaseC { // error + ~~~~~ +!!! error TS2675: Cannot extend private class 'BaseC'. + constructor(public x: number) { super(x); } + createInstance() { new DerivedC(1); } + createBaseInstance() { new BaseC(1); } // error + ~~~~~~~~~~~~ +!!! error TS2673: Constructor of type '(x: number): BaseC' is private and only accessible within class 'BaseC'. + } + + var ba = new BaseA(1); + var bb = new BaseB(1); // error + ~~~~~~~~~~~~ +!!! error TS2674: Constructor of type '(x: number): BaseB' is protected and only accessible within class 'BaseB'. + var bc = new BaseC(1); // error + ~~~~~~~~~~~~ +!!! error TS2673: Constructor of type '(x: number): BaseC' is private and only accessible within class 'BaseC'. + + 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..47c0b0bc62671 --- /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; + constructor(x: number); + createInstance(): void; +} +declare class BaseC { + x: number; + 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..c536db1f9da71 --- /dev/null +++ b/tests/baselines/reference/classConstructorAccessibility3.errors.txt @@ -0,0 +1,77 @@ +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(26,1): error TS2322: Type 'typeof Foo' is not assignable to type 'typeof Baz'. + Cannot assign a 'public' constructor type to a 'protected' constructor type. +tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility3.ts(27,1): error TS2322: Type 'typeof Bar' is not assignable to type 'typeof Baz'. + Cannot assign a 'public' constructor type to a 'protected' 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(32,1): error TS2322: Type 'typeof Foo' is not assignable to type 'typeof Qux'. + Cannot assign a 'public' constructor type to a 'private' constructor type. +tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility3.ts(33,1): error TS2322: Type 'typeof Bar' is not assignable to type 'typeof Qux'. + Cannot assign a 'public' constructor type to a 'private' constructor type. +tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility3.ts(34,1): error TS2322: Type 'typeof Baz' is not assignable to type 'typeof Qux'. + Cannot assign a 'protected' constructor type to a 'private' constructor type. + + +==== tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility3.ts (8 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; // error Foo is public + ~ +!!! error TS2322: Type 'typeof Foo' is not assignable to type 'typeof Baz'. +!!! error TS2322: Cannot assign a 'public' constructor type to a 'protected' constructor type. + b = Bar; // error Baz is public + ~ +!!! error TS2322: Type 'typeof Bar' is not assignable to type 'typeof Baz'. +!!! error TS2322: Cannot assign a 'public' constructor type to a 'protected' constructor type. + 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; // error Foo is public + ~ +!!! error TS2322: Type 'typeof Foo' is not assignable to type 'typeof Qux'. +!!! error TS2322: Cannot assign a 'public' constructor type to a 'private' constructor type. + c = Bar; // error Bar is public + ~ +!!! error TS2322: Type 'typeof Bar' is not assignable to type 'typeof Qux'. +!!! error TS2322: Cannot assign a 'public' constructor type to a 'private' constructor type. + c = Baz; // error Baz is protected + ~ +!!! error TS2322: Type 'typeof Baz' is not assignable to type 'typeof Qux'. +!!! error TS2322: Cannot assign a 'protected' constructor type to a 'private' constructor type. \ 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..8e900b6eb2d6d --- /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; // error Foo is public +b = Bar; // error Baz is public +b = Qux; // error Qux is private + +// c is private +let c = Qux; +c = Foo; // error Foo is public +c = Bar; // error Bar is public +c = Baz; // error Baz is protected + +//// [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; // error Foo is public +b = Bar; // error Baz is public +b = Qux; // error Qux is private +// c is private +var c = Qux; +c = Foo; // error Foo is public +c = Bar; // error Bar is public +c = Baz; // error Baz is protected + + +//// [classConstructorAccessibility3.d.ts] +declare class Foo { + x: number; + constructor(x: number); +} +declare class Bar { + x: number; + constructor(x: number); +} +declare class Baz { + x: number; + constructor(x: number); +} +declare class Qux { + x: number; + constructor(x); +} +declare let a: typeof Foo; +declare let b: typeof Baz; +declare let c: typeof Qux; 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..b69257a1c2a5f --- /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); + constructor(a: number); + constructor(a); +} +declare class B { + constructor(a: number); + constructor(a: string); +} +declare class C { + constructor(a: number); + 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..d30bb29e3148a 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 type '(): C' is private and only accessible within class 'C'. +tests/cases/conformance/types/members/typesWithPrivateConstructor.ts(14,10): error TS2673: Constructor of type '(x: number): C2' is private and only accessible within class 'C2'. -==== 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 type '(): C' is private and only accessible within class 'C'. 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 type '(x: number): C2' is private and only accessible within class 'C2'. 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..b3111ec2a7461 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 { + constructor(); +} +declare var c: any; +declare var r: () => void; +declare class C2 { + 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..4dc8add9fc220 --- /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 type '(): C' is protected and only accessible within class 'C'. +tests/cases/conformance/types/members/typesWithProtectedConstructor.ts(14,10): error TS2674: Constructor of type '(x: number): C2' is protected and only accessible within class 'C2'. + + +==== 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 type '(): C' is protected and only accessible within class 'C'. + 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 type '(x: number): C2' is protected and only accessible within class 'C2'. + 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..02f2946453383 --- /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 { + constructor(); +} +declare var c: any; +declare var r: () => void; +declare class C2 { + 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..8508a40d101ff --- /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; // error Foo is public +b = Bar; // error Baz is public +b = Qux; // error Qux is private + +// c is private +let c = Qux; +c = Foo; // error Foo is public +c = Bar; // error Bar is public +c = Baz; // error Baz is protected \ 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 From bbf92ce39187727bd8e547af7a4bfaa957ae2e2d Mon Sep 17 00:00:00 2001 From: AbubakerB Date: Thu, 4 Feb 2016 18:32:56 +0000 Subject: [PATCH 03/15] Added constructor visibility in the declaration emitter --- src/compiler/declarationEmitter.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/declarationEmitter.ts b/src/compiler/declarationEmitter.ts index ab0b16947fc49..2963ddf6c58b4 100644 --- a/src/compiler/declarationEmitter.ts +++ b/src/compiler/declarationEmitter.ts @@ -1316,7 +1316,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) { From 3d529a84c533dc382b1203152d3e45d43a04619b Mon Sep 17 00:00:00 2001 From: AbubakerB Date: Thu, 4 Feb 2016 18:33:53 +0000 Subject: [PATCH 04/15] Update baselines --- .../reference/classConstructorAccessibility.js | 4 ++-- .../reference/classConstructorAccessibility2.js | 4 ++-- .../reference/classConstructorAccessibility3.js | 4 ++-- .../classConstructorOverloadsAccessibility.js | 10 +++++----- .../baselines/reference/typesWithPrivateConstructor.js | 4 ++-- .../reference/typesWithProtectedConstructor.js | 4 ++-- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/tests/baselines/reference/classConstructorAccessibility.js b/tests/baselines/reference/classConstructorAccessibility.js index de7e4a83bb872..efc3f3c273cfa 100644 --- a/tests/baselines/reference/classConstructorAccessibility.js +++ b/tests/baselines/reference/classConstructorAccessibility.js @@ -90,11 +90,11 @@ declare class C { } declare class D { x: number; - constructor(x); + private constructor(x); } declare class E { x: number; - constructor(x: number); + protected constructor(x: number); } declare var c: C; declare var d: any; diff --git a/tests/baselines/reference/classConstructorAccessibility2.js b/tests/baselines/reference/classConstructorAccessibility2.js index 47c0b0bc62671..e19589ece4521 100644 --- a/tests/baselines/reference/classConstructorAccessibility2.js +++ b/tests/baselines/reference/classConstructorAccessibility2.js @@ -114,12 +114,12 @@ declare class BaseA { } declare class BaseB { x: number; - constructor(x: number); + protected constructor(x: number); createInstance(): void; } declare class BaseC { x: number; - constructor(x); + private constructor(x); createInstance(): void; } declare class DerivedA extends BaseA { diff --git a/tests/baselines/reference/classConstructorAccessibility3.js b/tests/baselines/reference/classConstructorAccessibility3.js index 8e900b6eb2d6d..02f5bb45a868a 100644 --- a/tests/baselines/reference/classConstructorAccessibility3.js +++ b/tests/baselines/reference/classConstructorAccessibility3.js @@ -87,11 +87,11 @@ declare class Bar { } declare class Baz { x: number; - constructor(x: number); + protected constructor(x: number); } declare class Qux { x: number; - constructor(x); + private constructor(x); } declare let a: typeof Foo; declare let b: typeof Baz; diff --git a/tests/baselines/reference/classConstructorOverloadsAccessibility.js b/tests/baselines/reference/classConstructorOverloadsAccessibility.js index b69257a1c2a5f..3914c29b78525 100644 --- a/tests/baselines/reference/classConstructorOverloadsAccessibility.js +++ b/tests/baselines/reference/classConstructorOverloadsAccessibility.js @@ -59,16 +59,16 @@ var D = (function () { //// [classConstructorOverloadsAccessibility.d.ts] declare class A { constructor(a: boolean); - constructor(a: number); - constructor(a); + protected constructor(a: number); + private constructor(a); } declare class B { - constructor(a: number); + protected constructor(a: number); constructor(a: string); } declare class C { - constructor(a: number); - constructor(a: string); + protected constructor(a: number); + protected constructor(a: string); } declare class D { constructor(a: number); diff --git a/tests/baselines/reference/typesWithPrivateConstructor.js b/tests/baselines/reference/typesWithPrivateConstructor.js index b3111ec2a7461..1795ee6b3166c 100644 --- a/tests/baselines/reference/typesWithPrivateConstructor.js +++ b/tests/baselines/reference/typesWithPrivateConstructor.js @@ -34,12 +34,12 @@ var r2 = c2.constructor; //// [typesWithPrivateConstructor.d.ts] declare class C { - constructor(); + private constructor(); } declare var c: any; declare var r: () => void; declare class C2 { - constructor(x); + private constructor(x); } declare var c2: any; declare var r2: (x: number) => void; diff --git a/tests/baselines/reference/typesWithProtectedConstructor.js b/tests/baselines/reference/typesWithProtectedConstructor.js index 02f2946453383..e75b3b6ecd3ab 100644 --- a/tests/baselines/reference/typesWithProtectedConstructor.js +++ b/tests/baselines/reference/typesWithProtectedConstructor.js @@ -34,12 +34,12 @@ var r2 = c2.constructor; //// [typesWithProtectedConstructor.d.ts] declare class C { - constructor(); + protected constructor(); } declare var c: any; declare var r: () => void; declare class C2 { - constructor(x: number); + protected constructor(x: number); } declare var c2: any; declare var r2: (x: number) => void; From 42000519347ecefe60687b9976e654781a69bbec Mon Sep 17 00:00:00 2001 From: AbubakerB Date: Thu, 4 Feb 2016 21:00:37 +0000 Subject: [PATCH 05/15] Addressed PR feedback. --- src/compiler/checker.ts | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 1ce5b51c66d21..ebb02a2fdadea 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1711,6 +1711,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; @@ -6059,28 +6069,24 @@ namespace ts { function constructorRelatedTo(sourceSignature: Signature, targetSignature: Signature, reportErrors: boolean) { if (sourceSignature && targetSignature && sourceSignature.declaration && targetSignature.declaration) { + // A public, protected and private signature is assignable to a private signature. + // A public and protected signature is assignable to a protected signature. + // And only a public signature is assignable to public signature. const sourceAccessibility = sourceSignature.declaration.flags & (NodeFlags.Private | NodeFlags.Protected); const targetAccessibility = targetSignature.declaration.flags & (NodeFlags.Private | NodeFlags.Protected); - const isRelated = sourceAccessibility === targetAccessibility; + const isRelated = targetAccessibility === NodeFlags.Private + || (targetAccessibility === NodeFlags.Protected && sourceAccessibility !== NodeFlags.Private) + || (targetAccessibility !== NodeFlags.Protected && !(sourceAccessibility & (NodeFlags.Private | NodeFlags.Protected))); + if (!isRelated && reportErrors) { - reportError(Diagnostics.Cannot_assign_a_0_constructor_type_to_a_1_constructor_type, flagsToString(sourceAccessibility), flagsToString(targetAccessibility)); + reportError(Diagnostics.Cannot_assign_a_0_constructor_type_to_a_1_constructor_type, visibilityToString(sourceAccessibility), visibilityToString(targetAccessibility)); } return isRelated; } return true; - - function flagsToString(flags: NodeFlags) { - if (flags === NodeFlags.Private) { - return "private"; - } - if (flags === NodeFlags.Protected) { - return "protected"; - } - return "public"; - } } } From 4c93eb2e98703ae86c81721d28b03babdf24bc61 Mon Sep 17 00:00:00 2001 From: AbubakerB Date: Thu, 4 Feb 2016 21:00:50 +0000 Subject: [PATCH 06/15] Accept baselines --- .../classConstructorAccessibility3.errors.txt | 37 +++---------------- .../classConstructorAccessibility3.js | 20 +++++----- .../classConstructorAccessibility3.ts | 10 ++--- 3 files changed, 21 insertions(+), 46 deletions(-) diff --git a/tests/baselines/reference/classConstructorAccessibility3.errors.txt b/tests/baselines/reference/classConstructorAccessibility3.errors.txt index c536db1f9da71..1b96db289dc79 100644 --- a/tests/baselines/reference/classConstructorAccessibility3.errors.txt +++ b/tests/baselines/reference/classConstructorAccessibility3.errors.txt @@ -2,21 +2,11 @@ tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessib 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(26,1): error TS2322: Type 'typeof Foo' is not assignable to type 'typeof Baz'. - Cannot assign a 'public' constructor type to a 'protected' constructor type. -tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility3.ts(27,1): error TS2322: Type 'typeof Bar' is not assignable to type 'typeof Baz'. - Cannot assign a 'public' constructor type to a 'protected' 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(32,1): error TS2322: Type 'typeof Foo' is not assignable to type 'typeof Qux'. - Cannot assign a 'public' constructor type to a 'private' constructor type. -tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility3.ts(33,1): error TS2322: Type 'typeof Bar' is not assignable to type 'typeof Qux'. - Cannot assign a 'public' constructor type to a 'private' constructor type. -tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility3.ts(34,1): error TS2322: Type 'typeof Baz' is not assignable to type 'typeof Qux'. - Cannot assign a 'protected' constructor type to a 'private' constructor type. -==== tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility3.ts (8 errors) ==== +==== tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility3.ts (3 errors) ==== class Foo { constructor(public x: number) { } @@ -48,14 +38,8 @@ tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessib // b is protected let b = Baz; - b = Foo; // error Foo is public - ~ -!!! error TS2322: Type 'typeof Foo' is not assignable to type 'typeof Baz'. -!!! error TS2322: Cannot assign a 'public' constructor type to a 'protected' constructor type. - b = Bar; // error Baz is public - ~ -!!! error TS2322: Type 'typeof Bar' is not assignable to type 'typeof Baz'. -!!! error TS2322: Cannot assign a 'public' constructor type to a 'protected' constructor type. + b = Foo; + b = Bar; b = Qux; // error Qux is private ~ !!! error TS2322: Type 'typeof Qux' is not assignable to type 'typeof Baz'. @@ -63,15 +47,6 @@ tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessib // c is private let c = Qux; - c = Foo; // error Foo is public - ~ -!!! error TS2322: Type 'typeof Foo' is not assignable to type 'typeof Qux'. -!!! error TS2322: Cannot assign a 'public' constructor type to a 'private' constructor type. - c = Bar; // error Bar is public - ~ -!!! error TS2322: Type 'typeof Bar' is not assignable to type 'typeof Qux'. -!!! error TS2322: Cannot assign a 'public' constructor type to a 'private' constructor type. - c = Baz; // error Baz is protected - ~ -!!! error TS2322: Type 'typeof Baz' is not assignable to type 'typeof Qux'. -!!! error TS2322: Cannot assign a 'protected' constructor type to a 'private' constructor type. \ No newline at end of file + 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 index 02f5bb45a868a..acc7d38aa5534 100644 --- a/tests/baselines/reference/classConstructorAccessibility3.js +++ b/tests/baselines/reference/classConstructorAccessibility3.js @@ -24,15 +24,15 @@ a = Qux; // error Qux is private // b is protected let b = Baz; -b = Foo; // error Foo is public -b = Bar; // error Baz is public +b = Foo; +b = Bar; b = Qux; // error Qux is private // c is private let c = Qux; -c = Foo; // error Foo is public -c = Bar; // error Bar is public -c = Baz; // error Baz is protected +c = Foo; +c = Bar; +c = Baz; //// [classConstructorAccessibility3.js] var Foo = (function () { @@ -66,14 +66,14 @@ a = Baz; // error Baz is protected a = Qux; // error Qux is private // b is protected var b = Baz; -b = Foo; // error Foo is public -b = Bar; // error Baz is public +b = Foo; +b = Bar; b = Qux; // error Qux is private // c is private var c = Qux; -c = Foo; // error Foo is public -c = Bar; // error Bar is public -c = Baz; // error Baz is protected +c = Foo; +c = Bar; +c = Baz; //// [classConstructorAccessibility3.d.ts] diff --git a/tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility3.ts b/tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility3.ts index 8508a40d101ff..91bb4873d96b4 100644 --- a/tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility3.ts +++ b/tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility3.ts @@ -24,12 +24,12 @@ a = Qux; // error Qux is private // b is protected let b = Baz; -b = Foo; // error Foo is public -b = Bar; // error Baz is public +b = Foo; +b = Bar; b = Qux; // error Qux is private // c is private let c = Qux; -c = Foo; // error Foo is public -c = Bar; // error Bar is public -c = Baz; // error Baz is protected \ No newline at end of file +c = Foo; +c = Bar; +c = Baz; \ No newline at end of file From 5ce0202bc9b93ba53d61f5e298a30dfd9fd1beb2 Mon Sep 17 00:00:00 2001 From: AbubakerB Date: Thu, 4 Feb 2016 21:46:28 +0000 Subject: [PATCH 07/15] Refactored visibility text on modifier grammar check --- src/compiler/checker.ts | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ebb02a2fdadea..2351f6913af28 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -16269,16 +16269,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; } From 16b54e0d9fced4351fa8f2431150be29ddd5bfcc Mon Sep 17 00:00:00 2001 From: AbubakerB Date: Thu, 4 Feb 2016 22:52:19 +0000 Subject: [PATCH 08/15] Addressed PR. Diagnostic messages --- src/compiler/checker.ts | 6 +++--- src/compiler/diagnosticMessages.json | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 2351f6913af28..5c69bb7f356a0 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -10182,10 +10182,10 @@ namespace ts { // A private or protected constructor can only be instantiated within it's own class if (declaringClass !== enclosingClass) { if (flags & NodeFlags.Private) { - error(node, Diagnostics.Constructor_of_type_0_is_private_and_only_accessible_within_class_1, signatureToString(signature), typeToString(declaringClass)); + 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_type_0_is_protected_and_only_accessible_within_class_1, signatureToString(signature), typeToString(declaringClass)); + error(node, Diagnostics.Constructor_of_class_0_is_protected_and_only_accessible_within_the_class_declaration, typeToString(declaringClass)); } return false; } @@ -14059,7 +14059,7 @@ namespace ts { if (signatures.length) { const declaration = signatures[0].declaration; if (declaration && declaration.flags & NodeFlags.Private) { - error(node, Diagnostics.Cannot_extend_private_class_0, (node.expression).text); + error(node, Diagnostics.Cannot_extend_a_class_0_Class_constructor_is_marked_as_private, (node.expression).text); } } } diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 2ee388ff42e75..b88b9b2a0e102 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1827,15 +1827,15 @@ "category": "Error", "code": 2672 }, - "Constructor of type '{0}' is private and only accessible within class '{1}'.": { + "Constructor of class '{0}' is private and only accessible within the class declaration.": { "category": "Error", "code": 2673 }, - "Constructor of type '{0}' is protected and only accessible within class '{1}'.": { + "Constructor of class '{0}' is protected and only accessible within the class declaration.": { "category": "Error", "code": 2674 }, - "Cannot extend private class '{0}'.": { + "Cannot extend a class '{0}'. Class constructor is marked as private.": { "category": "Error", "code": 2675 }, From 037b65781fe268fd3f6206a16a27dfbc7ee4b652 Mon Sep 17 00:00:00 2001 From: AbubakerB Date: Thu, 4 Feb 2016 22:52:38 +0000 Subject: [PATCH 09/15] Accept baselines --- .../classConstructorAccessibility.errors.txt | 16 +++++++-------- .../classConstructorAccessibility2.errors.txt | 20 +++++++++---------- .../typesWithPrivateConstructor.errors.txt | 8 ++++---- .../typesWithProtectedConstructor.errors.txt | 8 ++++---- 4 files changed, 26 insertions(+), 26 deletions(-) diff --git a/tests/baselines/reference/classConstructorAccessibility.errors.txt b/tests/baselines/reference/classConstructorAccessibility.errors.txt index a24ec6c63d1bf..c79633ba33d92 100644 --- a/tests/baselines/reference/classConstructorAccessibility.errors.txt +++ b/tests/baselines/reference/classConstructorAccessibility.errors.txt @@ -1,7 +1,7 @@ -tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts(15,9): error TS2673: Constructor of type '(x: number): D' is private and only accessible within class 'D'. -tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts(16,9): error TS2674: Constructor of type '(x: number): E' is protected and only accessible within class 'E'. -tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts(32,13): error TS2673: Constructor of type '(x: T): D' is private and only accessible within class 'D'. -tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts(33,13): error TS2674: Constructor of type '(x: T): E' is protected and only accessible within class 'E'. +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) ==== @@ -21,10 +21,10 @@ tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessib var c = new C(1); var d = new D(1); // error ~~~~~~~~ -!!! error TS2673: Constructor of type '(x: number): D' is private and only accessible within class 'D'. +!!! 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 type '(x: number): E' is protected and only accessible within class 'E'. +!!! error TS2674: Constructor of class 'E' is protected and only accessible within the class declaration. module Generic { class C { @@ -42,9 +42,9 @@ tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessib var c = new C(1); var d = new D(1); // error ~~~~~~~~ -!!! error TS2673: Constructor of type '(x: T): D' is private and only accessible within class 'D'. +!!! 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 type '(x: T): E' is protected and only accessible within class 'E'. +!!! 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/classConstructorAccessibility2.errors.txt b/tests/baselines/reference/classConstructorAccessibility2.errors.txt index 1c6fc46edb328..7bd784ac268c2 100644 --- a/tests/baselines/reference/classConstructorAccessibility2.errors.txt +++ b/tests/baselines/reference/classConstructorAccessibility2.errors.txt @@ -1,8 +1,8 @@ -tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility2.ts(26,28): error TS2674: Constructor of type '(x: number): BaseB' is protected and only accessible within class 'BaseB'. -tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility2.ts(29,24): error TS2675: Cannot extend private class 'BaseC'. -tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility2.ts(32,28): error TS2673: Constructor of type '(x: number): BaseC' is private and only accessible within class 'BaseC'. -tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility2.ts(36,10): error TS2674: Constructor of type '(x: number): BaseB' is protected and only accessible within class 'BaseB'. -tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility2.ts(37,10): error TS2673: Constructor of type '(x: number): BaseC' is private and only accessible within class 'BaseC'. +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) ==== @@ -33,26 +33,26 @@ tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessib createInstance() { new DerivedB(1); } createBaseInstance() { new BaseB(1); } // error ~~~~~~~~~~~~ -!!! error TS2674: Constructor of type '(x: number): BaseB' is protected and only accessible within class 'BaseB'. +!!! error TS2674: Constructor of class 'BaseB' is protected and only accessible within the class declaration. } class DerivedC extends BaseC { // error ~~~~~ -!!! error TS2675: Cannot extend private class 'BaseC'. +!!! 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 type '(x: number): BaseC' is private and only accessible within class 'BaseC'. +!!! 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 type '(x: number): BaseB' is protected and only accessible within class 'BaseB'. +!!! 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 type '(x: number): BaseC' is private and only accessible within class 'BaseC'. +!!! 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); diff --git a/tests/baselines/reference/typesWithPrivateConstructor.errors.txt b/tests/baselines/reference/typesWithPrivateConstructor.errors.txt index d30bb29e3148a..ab8ea4e26ad18 100644 --- a/tests/baselines/reference/typesWithPrivateConstructor.errors.txt +++ b/tests/baselines/reference/typesWithPrivateConstructor.errors.txt @@ -1,5 +1,5 @@ -tests/cases/conformance/types/members/typesWithPrivateConstructor.ts(6,9): error TS2673: Constructor of type '(): C' is private and only accessible within class 'C'. -tests/cases/conformance/types/members/typesWithPrivateConstructor.ts(14,10): error TS2673: Constructor of type '(x: number): C2' is private and only accessible within class 'C2'. +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 (2 errors) ==== @@ -10,7 +10,7 @@ tests/cases/conformance/types/members/typesWithPrivateConstructor.ts(14,10): err var c = new C(); // error C is private ~~~~~~~ -!!! error TS2673: Constructor of type '(): C' is private and only accessible within class 'C'. +!!! error TS2673: Constructor of class 'C' is private and only accessible within the class declaration. var r: () => void = c.constructor; class C2 { @@ -20,5 +20,5 @@ tests/cases/conformance/types/members/typesWithPrivateConstructor.ts(14,10): err var c2 = new C2(); // error C2 is private ~~~~~~~~ -!!! error TS2673: Constructor of type '(x: number): C2' is private and only accessible within class 'C2'. +!!! 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/typesWithProtectedConstructor.errors.txt b/tests/baselines/reference/typesWithProtectedConstructor.errors.txt index 4dc8add9fc220..2a5a059f44d4a 100644 --- a/tests/baselines/reference/typesWithProtectedConstructor.errors.txt +++ b/tests/baselines/reference/typesWithProtectedConstructor.errors.txt @@ -1,5 +1,5 @@ -tests/cases/conformance/types/members/typesWithProtectedConstructor.ts(6,9): error TS2674: Constructor of type '(): C' is protected and only accessible within class 'C'. -tests/cases/conformance/types/members/typesWithProtectedConstructor.ts(14,10): error TS2674: Constructor of type '(x: number): C2' is protected and only accessible within class 'C2'. +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) ==== @@ -10,7 +10,7 @@ tests/cases/conformance/types/members/typesWithProtectedConstructor.ts(14,10): e var c = new C(); // error C is protected ~~~~~~~ -!!! error TS2674: Constructor of type '(): C' is protected and only accessible within class 'C'. +!!! error TS2674: Constructor of class 'C' is protected and only accessible within the class declaration. var r: () => void = c.constructor; class C2 { @@ -20,5 +20,5 @@ tests/cases/conformance/types/members/typesWithProtectedConstructor.ts(14,10): e var c2 = new C2(); // error C2 is protected ~~~~~~~~ -!!! error TS2674: Constructor of type '(x: number): C2' is protected and only accessible within class 'C2'. +!!! 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 From a6a5a22a32e99c2bfd2d7eb658e7e6ce8c9588b3 Mon Sep 17 00:00:00 2001 From: AbubakerB Date: Fri, 5 Feb 2016 18:53:08 +0000 Subject: [PATCH 10/15] Addressed PR --- src/compiler/checker.ts | 40 ++++++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 5c69bb7f356a0..9a7a92b91ec7e 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5910,7 +5910,7 @@ namespace ts { } return Ternary.False; } - if (!constructorRelatedTo(sourceSignatures[0], targetSignatures[0], reportErrors)) { + if (!constructorVisibilitiesAreCompatible(sourceSignatures[0], targetSignatures[0], reportErrors)) { return Ternary.False; } } @@ -6067,26 +6067,34 @@ namespace ts { return Ternary.True; } - function constructorRelatedTo(sourceSignature: Signature, targetSignature: Signature, reportErrors: boolean) { - if (sourceSignature && targetSignature && sourceSignature.declaration && targetSignature.declaration) { - // A public, protected and private signature is assignable to a private signature. - // A public and protected signature is assignable to a protected signature. - // And only a public signature is assignable to public signature. - const sourceAccessibility = sourceSignature.declaration.flags & (NodeFlags.Private | NodeFlags.Protected); - const targetAccessibility = targetSignature.declaration.flags & (NodeFlags.Private | NodeFlags.Protected); + function constructorVisibilitiesAreCompatible(sourceSignature: Signature, targetSignature: Signature, reportErrors: boolean) { + if (!sourceSignature.declaration || !targetSignature.declaration) { + return true; + } - const isRelated = targetAccessibility === NodeFlags.Private - || (targetAccessibility === NodeFlags.Protected && sourceAccessibility !== NodeFlags.Private) - || (targetAccessibility !== NodeFlags.Protected && !(sourceAccessibility & (NodeFlags.Private | NodeFlags.Protected))); + const sourceAccessibility = sourceSignature.declaration.flags & (NodeFlags.Private | NodeFlags.Protected); + const targetAccessibility = targetSignature.declaration.flags & (NodeFlags.Private | NodeFlags.Protected); - if (!isRelated && reportErrors) { - reportError(Diagnostics.Cannot_assign_a_0_constructor_type_to_a_1_constructor_type, visibilityToString(sourceAccessibility), visibilityToString(targetAccessibility)); - } + // A public, protected and private signature is assignable to a private signature. + if (targetAccessibility === NodeFlags.Private) { + return true; + } - return isRelated; + // A public and protected signature is assignable to a protected signature. + if (targetAccessibility === NodeFlags.Protected && sourceAccessibility !== NodeFlags.Private) { + return true; } - 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; } } From 8ef9599bac0a4559119de60907fcdfb8cded3465 Mon Sep 17 00:00:00 2001 From: AbubakerB Date: Sat, 13 Feb 2016 01:07:33 +0000 Subject: [PATCH 11/15] Allow extending and instantiating a private or protected class within itself --- src/compiler/checker.ts | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 2d1bd26442ea2..d6b67c456ca8b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -10192,12 +10192,11 @@ namespace ts { return true; } + const declaringClassDeclaration = getClassLikeDeclarationOfSymbol(declaration.parent.symbol); const declaringClass = getDeclaredTypeOfSymbol(declaration.parent.symbol); - const enclosingClassDeclaration = getContainingClass(node); - const enclosingClass = enclosingClassDeclaration ? getDeclaredTypeOfSymbol(getSymbolOfNode(enclosingClassDeclaration)) : undefined; // A private or protected constructor can only be instantiated within it's own class - if (declaringClass !== enclosingClass) { + 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)); } @@ -14076,11 +14075,14 @@ 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) { - error(node, Diagnostics.Cannot_extend_a_class_0_Class_constructor_is_marked_as_private, (node.expression).text); + const typeClassDeclaration = getClassLikeDeclarationOfSymbol(type.symbol); + if (!isNodeWithinClass(node, typeClassDeclaration)) { + const signatures = getSignaturesOfType(type, SignatureKind.Construct); + if (signatures.length) { + const declaration = signatures[0].declaration; + if (declaration && declaration.flags & NodeFlags.Private) { + error(node, Diagnostics.Cannot_extend_a_class_0_Class_constructor_is_marked_as_private, (node.expression).text); + } } } } @@ -15408,6 +15410,19 @@ namespace ts { return node.parent && node.parent.kind === SyntaxKind.ExpressionWithTypeArguments; } + function isNodeWithinClass(node: Node, classDeclaration: ClassLikeDeclaration) { + while (true) { + const containingClass = getContainingClass(node); + if (!containingClass) { + return false; + } + if (containingClass === classDeclaration) { + return true; + } + node = containingClass; + } + } + function getLeftSideOfImportEqualsOrExportAssignment(nodeOnRightSide: EntityName): ImportEqualsDeclaration | ExportAssignment { while (nodeOnRightSide.parent.kind === SyntaxKind.QualifiedName) { nodeOnRightSide = nodeOnRightSide.parent; From ec7e80e377fae0360bccb30f937adc2693c592ca Mon Sep 17 00:00:00 2001 From: AbubakerB Date: Sat, 13 Feb 2016 01:10:47 +0000 Subject: [PATCH 12/15] Added tests and accept baselines --- .../classConstructorAccessibility4.errors.txt | 42 +++++++++++++++++++ .../classConstructorAccessibility4.ts | 33 +++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 tests/baselines/reference/classConstructorAccessibility4.errors.txt create mode 100644 tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility4.ts diff --git a/tests/baselines/reference/classConstructorAccessibility4.errors.txt b/tests/baselines/reference/classConstructorAccessibility4.errors.txt new file mode 100644 index 0000000000000..1cc50e3f4c894 --- /dev/null +++ b/tests/baselines/reference/classConstructorAccessibility4.errors.txt @@ -0,0 +1,42 @@ +tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility4.ts(16,9): error TS2673: Constructor of class 'A' is private and only accessible within the class declaration. +tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility4.ts(33,9): error TS2674: Constructor of class 'D' is protected and only accessible within the class declaration. + + +==== tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility4.ts (2 errors) ==== + class A { + private constructor() { } + + method() { + class B { + method() { + new A(); // OK + } + } + + class C extends A { // OK + } + } + } + + var a = new A(); // error + ~~~~~~~ +!!! error TS2673: Constructor of class 'A' is private and only accessible within the class declaration. + + class D { + protected constructor() { } + + method() { + class E { + method() { + new D(); // OK + } + } + + class F extends D { // OK + } + } + } + + var d = new D(); // error + ~~~~~~~ +!!! error TS2674: Constructor of class 'D' is protected and only accessible within the class declaration. \ 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..e75f9be6fde82 --- /dev/null +++ b/tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility4.ts @@ -0,0 +1,33 @@ +class A { + private constructor() { } + + method() { + class B { + method() { + new A(); // OK + } + } + + class C extends A { // OK + } + } +} + +var a = new A(); // error + +class D { + protected constructor() { } + + method() { + class E { + method() { + new D(); // OK + } + } + + class F extends D { // OK + } + } +} + +var d = new D(); // error \ No newline at end of file From 91ea83c72a07dbb0471d2a8e5ba6537e82b0b319 Mon Sep 17 00:00:00 2001 From: AbubakerB Date: Sat, 13 Feb 2016 02:51:25 +0000 Subject: [PATCH 13/15] Addressed PR --- src/compiler/checker.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index d6b67c456ca8b..533fffda80575 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -14075,12 +14075,12 @@ namespace ts { } function checkBaseTypeAccessibility(type: ObjectType, node: ExpressionWithTypeArguments) { - const typeClassDeclaration = getClassLikeDeclarationOfSymbol(type.symbol); - if (!isNodeWithinClass(node, typeClassDeclaration)) { - const signatures = getSignaturesOfType(type, SignatureKind.Construct); - if (signatures.length) { - const declaration = signatures[0].declaration; - if (declaration && declaration.flags & NodeFlags.Private) { + 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); } } From 208830efa3bde4c6c0b2595e3cc085c237424df6 Mon Sep 17 00:00:00 2001 From: AbubakerB Date: Sat, 13 Feb 2016 02:52:25 +0000 Subject: [PATCH 14/15] Updated tests and accepted baseline --- .../classConstructorAccessibility4.errors.txt | 42 -------------- .../classConstructorAccessibility4.symbols | 53 ++++++++++++++++++ .../classConstructorAccessibility4.types | 55 +++++++++++++++++++ .../classConstructorAccessibility4.ts | 8 +-- 4 files changed, 111 insertions(+), 47 deletions(-) delete mode 100644 tests/baselines/reference/classConstructorAccessibility4.errors.txt create mode 100644 tests/baselines/reference/classConstructorAccessibility4.symbols create mode 100644 tests/baselines/reference/classConstructorAccessibility4.types diff --git a/tests/baselines/reference/classConstructorAccessibility4.errors.txt b/tests/baselines/reference/classConstructorAccessibility4.errors.txt deleted file mode 100644 index 1cc50e3f4c894..0000000000000 --- a/tests/baselines/reference/classConstructorAccessibility4.errors.txt +++ /dev/null @@ -1,42 +0,0 @@ -tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility4.ts(16,9): error TS2673: Constructor of class 'A' is private and only accessible within the class declaration. -tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility4.ts(33,9): error TS2674: Constructor of class 'D' is protected and only accessible within the class declaration. - - -==== tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility4.ts (2 errors) ==== - class A { - private constructor() { } - - method() { - class B { - method() { - new A(); // OK - } - } - - class C extends A { // OK - } - } - } - - var a = new A(); // error - ~~~~~~~ -!!! error TS2673: Constructor of class 'A' is private and only accessible within the class declaration. - - class D { - protected constructor() { } - - method() { - class E { - method() { - new D(); // OK - } - } - - class F extends D { // OK - } - } - } - - var d = new D(); // error - ~~~~~~~ -!!! error TS2674: Constructor of class 'D' is protected and only accessible within the class declaration. \ No newline at end of file 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/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility4.ts b/tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility4.ts index e75f9be6fde82..3760f2176aebe 100644 --- a/tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility4.ts +++ b/tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility4.ts @@ -1,3 +1,5 @@ +// @declaration: true + class A { private constructor() { } @@ -13,8 +15,6 @@ class A { } } -var a = new A(); // error - class D { protected constructor() { } @@ -28,6 +28,4 @@ class D { class F extends D { // OK } } -} - -var d = new D(); // error \ No newline at end of file +} \ No newline at end of file From ba8b1680cbf5fa5763fe1d6000a36ac05d8bdb43 Mon Sep 17 00:00:00 2001 From: AbubakerB Date: Sun, 14 Feb 2016 21:16:12 +0000 Subject: [PATCH 15/15] Included previously ignored baseline .js file and slight refactoring --- src/compiler/checker.ts | 7 +- .../classConstructorAccessibility4.js | 93 +++++++++++++++++++ 2 files changed, 96 insertions(+), 4 deletions(-) create mode 100644 tests/baselines/reference/classConstructorAccessibility4.js diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 533fffda80575..f775f56269518 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -15412,14 +15412,13 @@ namespace ts { function isNodeWithinClass(node: Node, classDeclaration: ClassLikeDeclaration) { while (true) { - const containingClass = getContainingClass(node); - if (!containingClass) { + node = getContainingClass(node); + if (!node) { return false; } - if (containingClass === classDeclaration) { + if (node === classDeclaration) { return true; } - node = containingClass; } } 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; +}