From 708f4233e256a96c59d5336d94076e91fe28db97 Mon Sep 17 00:00:00 2001 From: AbubakerB Date: Thu, 6 Aug 2015 00:48:53 +0100 Subject: [PATCH 01/14] Fixes issue #2341 --- src/compiler/checker.ts | 59 ++++++++++++++++--- .../diagnosticInformationMap.generated.ts | 3 + src/compiler/diagnosticMessages.json | 12 ++++ 3 files changed, 66 insertions(+), 8 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index bce4d21032df8..b578c848b040c 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -8641,6 +8641,37 @@ namespace ts { result = chooseOverload(candidates, assignableRelation); } if (result) { + // Check to see if constructor accessibility is valid for this call + let constructor = result.declaration; + if (constructor && (node).expression) { + let expressionType = checkExpression((node).expression); + expressionType = getApparentType(expressionType); + if (expressionType !== unknownType) { + let declaration = expressionType.symbol && getDeclarationOfKind(expressionType.symbol, SyntaxKind.ClassDeclaration); + if (declaration) { + // Get the declaring and enclosing class instance types + let enclosingClassDeclaration = getContainingClass(node); + let enclosingClass = enclosingClassDeclaration ? getDeclaredTypeOfSymbol(getSymbolOfNode(enclosingClassDeclaration)) : undefined; + + let declaringClass = getDeclaredTypeOfSymbol(getSymbolOfNode(declaration)); + if (constructor.flags & NodeFlags.Private) { + // A private constructor is only accessible in the declaring class + if (declaringClass !== enclosingClass) { + error(node, Diagnostics.Constructor_0_1_is_private_and_only_accessible_within_class_0, typeToString(declaringClass), signatureToString(result)); + return resolveErrorCall(node); + } + } + else if (constructor.flags & NodeFlags.Protected) { + // A protected constructor is only accessible in the declaring class and classes derived from it + if (!enclosingClass || !hasBaseType(enclosingClass, declaringClass)) { + error(node, Diagnostics.Constructor_0_1_is_protected_and_only_accessible_within_class_0_and_its_subclasses, typeToString(declaringClass), signatureToString(result)); + return resolveErrorCall(node); + } + } + } + } + } + return result; } @@ -10738,7 +10769,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); @@ -14778,12 +14809,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"); } @@ -15003,7 +15028,25 @@ namespace ts { if (heritageClause.types.length > 1) { return grammarErrorOnFirstToken(heritageClause.types[1], Diagnostics.Classes_can_only_extend_a_single_class); } - + + // if the base class (the class to extend) has a private constructor, + // then the derived class should not be allowed to extend it. + if (heritageClause.types.length == 1) { + let expression = heritageClause.types[0].expression; + if (expression) { + let baseType = getApparentType(checkExpression(expression)); + if (baseType !== unknownType) { + let signatures = getSignaturesOfType(baseType, SignatureKind.Construct); + for (let signature of signatures) { + let constuctor = signature.declaration; + if (constuctor && constuctor.flags & NodeFlags.Private) { + return grammarErrorOnFirstToken(expression, Diagnostics.Cannot_extend_private_class_0, (expression).text); + } + } + } + } + } + seenExtendsClause = true; } else { diff --git a/src/compiler/diagnosticInformationMap.generated.ts b/src/compiler/diagnosticInformationMap.generated.ts index 5ccc0a0db9b40..e39b4e060829a 100644 --- a/src/compiler/diagnosticInformationMap.generated.ts +++ b/src/compiler/diagnosticInformationMap.generated.ts @@ -427,6 +427,9 @@ namespace ts { Cannot_emit_namespaced_JSX_elements_in_React: { code: 2650, category: DiagnosticCategory.Error, key: "Cannot emit namespaced JSX elements in React" }, A_member_initializer_in_a_const_enum_declaration_cannot_reference_members_declared_after_it_including_members_defined_in_other_const_enums: { code: 2651, category: DiagnosticCategory.Error, key: "A member initializer in a 'const' enum declaration cannot reference members declared after it, including members defined in other 'const' enums." }, Merged_declaration_0_cannot_include_a_default_export_declaration_Consider_adding_a_separate_export_default_0_declaration_instead: { code: 2652, category: DiagnosticCategory.Error, key: "Merged declaration '{0}' cannot include a default export declaration. Consider adding a separate 'export default {0}' declaration instead." }, + Cannot_extend_private_class_0: { code: 2653, category: DiagnosticCategory.Error, key: "Cannot extend private class '{0}'." }, + Constructor_0_1_is_protected_and_only_accessible_within_class_0_and_its_subclasses: { code: 2654, category: DiagnosticCategory.Error, key: "Constructor '{0}{1}' is protected and only accessible within class '{0}' and its subclasses." }, + Constructor_0_1_is_private_and_only_accessible_within_class_0: { code: 2655, category: DiagnosticCategory.Error, key: "Constructor '{0}{1}' is private and only accessible within class '{0}'." }, Import_declaration_0_is_using_private_name_1: { code: 4000, category: DiagnosticCategory.Error, key: "Import declaration '{0}' is using private name '{1}'." }, Type_parameter_0_of_exported_class_has_or_is_using_private_name_1: { code: 4002, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of exported class has or is using private name '{1}'." }, Type_parameter_0_of_exported_interface_has_or_is_using_private_name_1: { code: 4004, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of exported interface has or is using private name '{1}'." }, diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index e138e2ddac489..5cba7c6e95a95 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1697,6 +1697,18 @@ "category": "Error", "code": 2652 }, + "Cannot extend private class '{0}'.": { + "category": "Error", + "code": 2653 + }, + "Constructor '{0}{1}' is protected and only accessible within class '{0}' and its subclasses.": { + "category": "Error", + "code": 2654 + }, + "Constructor '{0}{1}' is private and only accessible within class '{0}'.": { + "category": "Error", + "code": 2655 + }, "Import declaration '{0}' is using private name '{1}'.": { "category": "Error", "code": 4000 From 9dfa9c72edd4aa40fada47fb9deb992b29a77303 Mon Sep 17 00:00:00 2001 From: AbubakerB Date: Thu, 6 Aug 2015 00:51:49 +0100 Subject: [PATCH 02/14] Add tests for issue #2341 --- .../classConstructorAccessibility.ts | 16 +++--- .../classConstructorAccessibility2.ts | 49 +++++++++++++++++++ .../classConstructorOverloadsAccessibility.ts | 32 ++++++++++++ 3 files changed, 89 insertions(+), 8 deletions(-) create mode 100644 tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility2.ts create mode 100644 tests/cases/conformance/classes/constructorDeclarations/classConstructorOverloadsAccessibility.ts diff --git a/tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts b/tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts index c2e4855e63a3b..b3d4ab444cda0 100644 --- a/tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts +++ b/tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts @@ -3,16 +3,16 @@ class C { } 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 - D is private +var e = new E(1); // error - E is protected module Generic { class C { @@ -20,14 +20,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 - D is private + var e = new E(1); // error - E is protected } diff --git a/tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility2.ts b/tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility2.ts new file mode 100644 index 0000000000000..ff94e05204309 --- /dev/null +++ b/tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility2.ts @@ -0,0 +1,49 @@ +class A { + private constructor(a: string) // only private access + private constructor() { + + } + + static method() { + var t1 = new A("test"); // private is accessible in static method + } + + method() { + var t1 = new A("1"); // private is accessible in own class + } +} + +class A_ext extends A { // Cannot extend private class A + method() { + var t1 = new A(""); // error - A is private and only accessible in it's own class + } +} + +class B { + protected constructor() { + } + + method() { + var t1 = new B(); // protected is accessible in own class + } +} + +class B_ext extends B { + method() { + var t1 = new B(); // protected is accessible in sub-class + } +} + +class C { + public constructor(){ + + } + methodA() { + var t1 = new C(); // public is accessible anywhere + } +} + +// check global scope +var t1 = new A(""); // error - A is private +var t2 = new B(); // error - B is protected +var t3 = new C(); \ 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..4bee5614f8757 --- /dev/null +++ b/tests/cases/conformance/classes/constructorDeclarations/classConstructorOverloadsAccessibility.ts @@ -0,0 +1,32 @@ +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) // ok + constructor(a: string) // ok + public constructor() { + + } +} \ No newline at end of file From 6d01766acd2aeeac59b0ff936d954a9459a9c770 Mon Sep 17 00:00:00 2001 From: AbubakerB Date: Thu, 6 Aug 2015 01:05:29 +0100 Subject: [PATCH 03/14] Accept baselines --- .../baselines/reference/Protected3.errors.txt | 9 -- tests/baselines/reference/Protected3.symbols | 6 + tests/baselines/reference/Protected3.types | 6 + .../classConstructorAccessibility.errors.txt | 40 +++---- .../classConstructorAccessibility.js | 32 +++--- .../classConstructorAccessibility2.errors.txt | 64 +++++++++++ .../classConstructorAccessibility2.js | 108 ++++++++++++++++++ ...nstructorOverloadsAccessibility.errors.txt | 44 +++++++ .../classConstructorOverloadsAccessibility.js | 55 +++++++++ ...implicitAnyInAmbientDeclaration.errors.txt | 5 +- ...licitAnyInAmbientDeclaration2.d.errors.txt | 5 +- .../parserConstructorDeclaration5.errors.txt | 9 -- .../parserConstructorDeclaration5.symbols | 6 + .../parserConstructorDeclaration5.types | 6 + .../reference/protectedMembers.errors.txt | 5 +- .../typesWithPrivateConstructor.errors.txt | 17 +-- 16 files changed, 338 insertions(+), 79 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/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 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..bcd210b65279c 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(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(14,9): error TS2655: Constructor 'D(x: number): D' is private and only accessible within class 'D'. +tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts(15,9): error TS2654: Constructor 'E(x: number): E' is protected and only accessible within class 'E' and its subclasses. +tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts(31,13): error TS2655: Constructor 'D(x: number): D' is private and only accessible within class 'D'. +tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts(32,13): error TS2654: Constructor 'E(x: number): E' is protected and only accessible within class 'E' and its subclasses. ==== tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts (4 errors) ==== @@ -10,20 +10,20 @@ tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessib } 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 - D is private + ~~~~~~~~ +!!! error TS2655: Constructor 'D(x: number): D' is private and only accessible within class 'D'. + var e = new E(1); // error - E is protected + ~~~~~~~~ +!!! error TS2654: Constructor 'E(x: number): E' is protected and only accessible within class 'E' and its subclasses. module Generic { class C { @@ -31,19 +31,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 - D is private + ~~~~~~~~ +!!! error TS2655: Constructor 'D(x: number): D' is private and only accessible within class 'D'. + var e = new E(1); // error - E is protected + ~~~~~~~~ +!!! error TS2654: Constructor 'E(x: number): E' is protected and only accessible within class 'E' and its subclasses. } \ No newline at end of file diff --git a/tests/baselines/reference/classConstructorAccessibility.js b/tests/baselines/reference/classConstructorAccessibility.js index 15b12190392a4..70c1646fe3596 100644 --- a/tests/baselines/reference/classConstructorAccessibility.js +++ b/tests/baselines/reference/classConstructorAccessibility.js @@ -4,16 +4,16 @@ class C { } 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 - D is private +var e = new E(1); // error - E is protected module Generic { class C { @@ -21,16 +21,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 - D is private + var e = new E(1); // error - E is protected } @@ -44,18 +44,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 - D is private +var e = new E(1); // error - E is protected var Generic; (function (Generic) { var C = (function () { @@ -67,16 +67,16 @@ 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 - D is private + var e = new E(1); // error - E is protected })(Generic || (Generic = {})); diff --git a/tests/baselines/reference/classConstructorAccessibility2.errors.txt b/tests/baselines/reference/classConstructorAccessibility2.errors.txt new file mode 100644 index 0000000000000..7ebe0259f7c04 --- /dev/null +++ b/tests/baselines/reference/classConstructorAccessibility2.errors.txt @@ -0,0 +1,64 @@ +tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility2.ts(16,21): error TS2653: Cannot extend private class 'A'. +tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility2.ts(18,12): error TS2655: Constructor 'A(a: string): A' is private and only accessible within class 'A'. +tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility2.ts(47,10): error TS2655: Constructor 'A(a: string): A' is private and only accessible within class 'A'. +tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility2.ts(48,10): error TS2654: Constructor 'B(): B' is protected and only accessible within class 'B' and its subclasses. + + +==== tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility2.ts (4 errors) ==== + class A { + private constructor(a: string) // only private access + private constructor() { + + } + + static method() { + var t1 = new A("test"); // private is accessible in static method + } + + method() { + var t1 = new A("1"); // private is accessible in own class + } + } + + class A_ext extends A { // Cannot extend private class A + ~ +!!! error TS2653: Cannot extend private class 'A'. + method() { + var t1 = new A(""); // error - A is private and only accessible in it's own class + ~~~~~~~~~ +!!! error TS2655: Constructor 'A(a: string): A' is private and only accessible within class 'A'. + } + } + + class B { + protected constructor() { + } + + method() { + var t1 = new B(); // protected is accessible in own class + } + } + + class B_ext extends B { + method() { + var t1 = new B(); // protected is accessible in sub-class + } + } + + class C { + public constructor(){ + + } + methodA() { + var t1 = new C(); // public is accessible anywhere + } + } + + // check global scope + var t1 = new A(""); // error - A is private + ~~~~~~~~~ +!!! error TS2655: Constructor 'A(a: string): A' is private and only accessible within class 'A'. + var t2 = new B(); // error - B is protected + ~~~~~~~ +!!! error TS2654: Constructor 'B(): B' is protected and only accessible within class 'B' and its subclasses. + var t3 = new C(); \ 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..d2004161290cc --- /dev/null +++ b/tests/baselines/reference/classConstructorAccessibility2.js @@ -0,0 +1,108 @@ +//// [classConstructorAccessibility2.ts] +class A { + private constructor(a: string) // only private access + private constructor() { + + } + + static method() { + var t1 = new A("test"); // private is accessible in static method + } + + method() { + var t1 = new A("1"); // private is accessible in own class + } +} + +class A_ext extends A { // Cannot extend private class A + method() { + var t1 = new A(""); // error - A is private and only accessible in it's own class + } +} + +class B { + protected constructor() { + } + + method() { + var t1 = new B(); // protected is accessible in own class + } +} + +class B_ext extends B { + method() { + var t1 = new B(); // protected is accessible in sub-class + } +} + +class C { + public constructor(){ + + } + methodA() { + var t1 = new C(); // public is accessible anywhere + } +} + +// check global scope +var t1 = new A(""); // error - A is private +var t2 = new B(); // error - B is protected +var t3 = new C(); + +//// [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 A = (function () { + function A() { + } + A.method = function () { + var t1 = new A("test"); // private is accessible in static method + }; + A.prototype.method = function () { + var t1 = new A("1"); // private is accessible in own class + }; + return A; +})(); +var A_ext = (function (_super) { + __extends(A_ext, _super); + function A_ext() { + _super.apply(this, arguments); + } + A_ext.prototype.method = function () { + var t1 = new A(""); // error - A is private and only accessible in it's own class + }; + return A_ext; +})(A); +var B = (function () { + function B() { + } + B.prototype.method = function () { + var t1 = new B(); // protected is accessible in own class + }; + return B; +})(); +var B_ext = (function (_super) { + __extends(B_ext, _super); + function B_ext() { + _super.apply(this, arguments); + } + B_ext.prototype.method = function () { + var t1 = new B(); // protected is accessible in sub-class + }; + return B_ext; +})(B); +var C = (function () { + function C() { + } + C.prototype.methodA = function () { + var t1 = new C(); // public is accessible anywhere + }; + return C; +})(); +// check global scope +var t1 = new A(""); // error - A is private +var t2 = new B(); // error - B is protected +var t3 = new C(); diff --git a/tests/baselines/reference/classConstructorOverloadsAccessibility.errors.txt b/tests/baselines/reference/classConstructorOverloadsAccessibility.errors.txt new file mode 100644 index 0000000000000..69371d5e7da9b --- /dev/null +++ b/tests/baselines/reference/classConstructorOverloadsAccessibility.errors.txt @@ -0,0 +1,44 @@ +tests/cases/conformance/classes/constructorDeclarations/classConstructorOverloadsAccessibility.ts(2,2): error TS2385: Overload signatures must all be public, private or protected. +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(11,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) // ok + constructor(a: string) // ok + 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..2027261aa06ea --- /dev/null +++ b/tests/baselines/reference/classConstructorOverloadsAccessibility.js @@ -0,0 +1,55 @@ +//// [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) // ok + constructor(a: string) // ok + 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; +})(); diff --git a/tests/baselines/reference/implicitAnyInAmbientDeclaration.errors.txt b/tests/baselines/reference/implicitAnyInAmbientDeclaration.errors.txt index 4775ec0511bec..88acd5668b725 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,9): 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 11f2ae90d3520..7deacb342e01b 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,5): 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..82bf9b71f0147 100644 --- a/tests/baselines/reference/protectedMembers.errors.txt +++ b/tests/baselines/reference/protectedMembers.errors.txt @@ -8,7 +8,6 @@ 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'. 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'. @@ -17,7 +16,7 @@ tests/cases/compiler/protectedMembers.ts(112,7): error TS2415: Class 'B3' incorr 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; @@ -124,8 +123,6 @@ 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/typesWithPrivateConstructor.errors.txt b/tests/baselines/reference/typesWithPrivateConstructor.errors.txt index 2440e51cd3972..4bffd7f9b7d5c 100644 --- a/tests/baselines/reference/typesWithPrivateConstructor.errors.txt +++ b/tests/baselines/reference/typesWithPrivateConstructor.errors.txt @@ -1,31 +1,22 @@ -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'. -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(7,9): error TS2655: Constructor 'C(): C' is private and only accessible within class 'C'. 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 (5 errors) ==== +==== tests/cases/conformance/types/members/typesWithPrivateConstructor.ts (2 errors) ==== // private constructors are not allowed class C { private constructor() { } - ~~~~~~~ -!!! error TS1089: 'private' modifier cannot appear on a constructor declaration. } var c = new C(); + ~~~~~~~ +!!! error TS2655: Constructor 'C(): C' is private and only accessible within class 'C'. var r: () => void = c.constructor; - ~ -!!! error TS2322: Type 'Function' is not assignable to type '() => 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(); From 7105a41016d630c3b8436de901bfad662d7c0b02 Mon Sep 17 00:00:00 2001 From: AbubakerB Date: Wed, 12 Aug 2015 00:13:06 +0100 Subject: [PATCH 04/14] Add check on construct signature and relevant test cases. --- src/compiler/checker.ts | 22 +++++++++++++++++++ .../diagnosticInformationMap.generated.ts | 5 +++-- src/compiler/diagnosticMessages.json | 8 +++++-- .../classConstructorAccessibility.ts | 13 +++++++++++ 4 files changed, 44 insertions(+), 4 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index b578c848b040c..30957b8529d23 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5097,6 +5097,11 @@ namespace ts { let targetSig = targetSignatures[0]; if (sourceSig && targetSig) { + result &= signatureVisibilityRelatedTo(sourceSig, targetSig); + if (result !== Ternary.True) { + return result; + } + let sourceErasedSignature = getErasedSignature(sourceSig); let targetErasedSignature = getErasedSignature(targetSig); @@ -5136,6 +5141,23 @@ namespace ts { } } return result; + + function signatureVisibilityRelatedTo(sourceSig: Signature, targetSig: Signature) { + if (!sourceSig || !targetSig) return Ternary.True; + if (sourceSig.declaration.kind !== SyntaxKind.Constructor) return Ternary.True; + + if (sourceSig.declaration && targetSig.declaration) { + let sourceVisibility = sourceSig.declaration.modifiers ? sourceSig.declaration.modifiers.flags : 0; + let targetVisibility = targetSig.declaration.modifiers ? targetSig.declaration.modifiers.flags : 0; + if (sourceVisibility !== targetVisibility && (!((sourceVisibility | targetVisibility) & NodeFlags.Public))) { + if (reportErrors) { + reportError(Diagnostics.Cannot_assign_a_non_public_constructor_type_to_a_public_constructor_type); + } + return Ternary.False; + } + } + return Ternary.True; + } } function signatureRelatedTo(source: Signature, target: Signature, reportErrors: boolean): Ternary { diff --git a/src/compiler/diagnosticInformationMap.generated.ts b/src/compiler/diagnosticInformationMap.generated.ts index e39b4e060829a..3080a255d17ab 100644 --- a/src/compiler/diagnosticInformationMap.generated.ts +++ b/src/compiler/diagnosticInformationMap.generated.ts @@ -428,8 +428,9 @@ namespace ts { A_member_initializer_in_a_const_enum_declaration_cannot_reference_members_declared_after_it_including_members_defined_in_other_const_enums: { code: 2651, category: DiagnosticCategory.Error, key: "A member initializer in a 'const' enum declaration cannot reference members declared after it, including members defined in other 'const' enums." }, Merged_declaration_0_cannot_include_a_default_export_declaration_Consider_adding_a_separate_export_default_0_declaration_instead: { code: 2652, category: DiagnosticCategory.Error, key: "Merged declaration '{0}' cannot include a default export declaration. Consider adding a separate 'export default {0}' declaration instead." }, Cannot_extend_private_class_0: { code: 2653, category: DiagnosticCategory.Error, key: "Cannot extend private class '{0}'." }, - Constructor_0_1_is_protected_and_only_accessible_within_class_0_and_its_subclasses: { code: 2654, category: DiagnosticCategory.Error, key: "Constructor '{0}{1}' is protected and only accessible within class '{0}' and its subclasses." }, - Constructor_0_1_is_private_and_only_accessible_within_class_0: { code: 2655, category: DiagnosticCategory.Error, key: "Constructor '{0}{1}' is private and only accessible within class '{0}'." }, + Constructor_0_is_protected_and_only_accessible_within_class_1_and_its_subclasses: { code: 2654, category: DiagnosticCategory.Error, key: "Constructor '{0}' is protected and only accessible within class '{1}' and its subclasses." }, + Constructor_0_is_private_and_only_accessible_within_class_1: { code: 2655, category: DiagnosticCategory.Error, key: "Constructor '{0}' is private and only accessible within class '{1}'." }, + Cannot_assign_a_non_public_constructor_type_to_a_public_constructor_type: { code: 2656, category: DiagnosticCategory.Error, key: "Cannot assign a non-public constructor type to a public constructor type." }, Import_declaration_0_is_using_private_name_1: { code: 4000, category: DiagnosticCategory.Error, key: "Import declaration '{0}' is using private name '{1}'." }, Type_parameter_0_of_exported_class_has_or_is_using_private_name_1: { code: 4002, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of exported class has or is using private name '{1}'." }, Type_parameter_0_of_exported_interface_has_or_is_using_private_name_1: { code: 4004, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of exported interface has or is using private name '{1}'." }, diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 5cba7c6e95a95..cbf6ac1eb63d0 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1701,14 +1701,18 @@ "category": "Error", "code": 2653 }, - "Constructor '{0}{1}' is protected and only accessible within class '{0}' and its subclasses.": { + "Constructor '{0}' is protected and only accessible within class '{1}' and its subclasses.": { "category": "Error", "code": 2654 }, - "Constructor '{0}{1}' is private and only accessible within class '{0}'.": { + "Constructor '{0}' is private and only accessible within class '{1}'.": { "category": "Error", "code": 2655 }, + "Cannot assign a non-public constructor type to a public constructor type.": { + "category": "Error", + "code": 2656 + }, "Import declaration '{0}' is using private name '{1}'.": { "category": "Error", "code": 4000 diff --git a/tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts b/tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts index b3d4ab444cda0..09d4f8d91b669 100644 --- a/tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts +++ b/tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts @@ -1,3 +1,7 @@ +class B { + constructor(public x: number) { } +} + class C { public constructor(public x: number) { } } @@ -10,6 +14,7 @@ class E { protected constructor(public x: number) { } } +var b = new B(1); var c = new C(1); var d = new D(1); // error - D is private var e = new E(1); // error - E is protected @@ -27,7 +32,15 @@ module Generic { protected constructor(public x: T) { } } + var b = new B(1); var c = new C(1); var d = new D(1); // error - D is private var e = new E(1); // error - E is protected } + +// make sure signatures are covered. +let sig: new(x: number) => any; +sig = B; +sig = C; +sig = D; // error - non-public to public +sig = E; // error - non-public to public \ No newline at end of file From 51bf39598ce38ea422de127c2cc6384a8a92ccdd Mon Sep 17 00:00:00 2001 From: AbubakerB Date: Wed, 12 Aug 2015 00:16:38 +0100 Subject: [PATCH 05/14] Refactor constructor call visibility check --- src/compiler/checker.ts | 65 +++++++++++++++++++++++------------------ src/compiler/types.ts | 6 ++-- 2 files changed, 39 insertions(+), 32 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 30957b8529d23..07689a70ba84e 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -8664,35 +8664,7 @@ namespace ts { } if (result) { // Check to see if constructor accessibility is valid for this call - let constructor = result.declaration; - if (constructor && (node).expression) { - let expressionType = checkExpression((node).expression); - expressionType = getApparentType(expressionType); - if (expressionType !== unknownType) { - let declaration = expressionType.symbol && getDeclarationOfKind(expressionType.symbol, SyntaxKind.ClassDeclaration); - if (declaration) { - // Get the declaring and enclosing class instance types - let enclosingClassDeclaration = getContainingClass(node); - let enclosingClass = enclosingClassDeclaration ? getDeclaredTypeOfSymbol(getSymbolOfNode(enclosingClassDeclaration)) : undefined; - - let declaringClass = getDeclaredTypeOfSymbol(getSymbolOfNode(declaration)); - if (constructor.flags & NodeFlags.Private) { - // A private constructor is only accessible in the declaring class - if (declaringClass !== enclosingClass) { - error(node, Diagnostics.Constructor_0_1_is_private_and_only_accessible_within_class_0, typeToString(declaringClass), signatureToString(result)); - return resolveErrorCall(node); - } - } - else if (constructor.flags & NodeFlags.Protected) { - // A protected constructor is only accessible in the declaring class and classes derived from it - if (!enclosingClass || !hasBaseType(enclosingClass, declaringClass)) { - error(node, Diagnostics.Constructor_0_1_is_protected_and_only_accessible_within_class_0_and_its_subclasses, typeToString(declaringClass), signatureToString(result)); - return resolveErrorCall(node); - } - } - } - } - } + checkConstructorVisibility(result, node); return result; } @@ -8750,6 +8722,41 @@ namespace ts { } return resolveErrorCall(node); + + function checkConstructorVisibility(signature: Signature, node: NewExpression) { + let constructor = result.declaration; + let expression = (node).expression; + + if (!constructor || !expression) return; + // if constructor is public, we dont need to check visibility + if (constructor.flags & NodeFlags.Public) return; + + let expressionType = checkExpression(expression); + expressionType = getApparentType(expressionType); + if (expressionType === unknownType) return; + + let declaration = expressionType.symbol && getDeclarationOfKind(expressionType.symbol, SyntaxKind.ClassDeclaration); + if (!declaration) return; + + // Get the declaring and enclosing class instance types + let enclosingClassDeclaration = getContainingClass(node); + let enclosingClass = enclosingClassDeclaration ? getDeclaredTypeOfSymbol(getSymbolOfNode(enclosingClassDeclaration)) : undefined; + let declaringClass = getDeclaredTypeOfSymbol(getSymbolOfNode(declaration)); + if (constructor.flags & NodeFlags.Private) { + // A private constructor is only accessible in the declaring class + if (declaringClass !== enclosingClass) { + reportError(Diagnostics.Constructor_0_is_private_and_only_accessible_within_class_1, signatureToString(result), typeToString(declaringClass)); + //return resolveErrorCall(node); + } + } + else if (constructor.flags & NodeFlags.Protected) { + // A protected constructor is only accessible in the declaring class and classes derived from it + if (!enclosingClass || !hasBaseType(enclosingClass, declaringClass)) { + reportError(Diagnostics.Constructor_0_is_protected_and_only_accessible_within_class_1_and_its_subclasses, signatureToString(result), typeToString(declaringClass)); + //return resolveErrorCall(node); + } + } + } function reportError(message: DiagnosticMessage, arg0?: string, arg1?: string, arg2?: string): void { let errorInfo: DiagnosticMessageChain; diff --git a/src/compiler/types.ts b/src/compiler/types.ts index da43984ee1377..4e965ee473085 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -360,9 +360,9 @@ namespace ts { export const enum NodeFlags { Export = 0x00000001, // Declarations Ambient = 0x00000002, // Declarations - Public = 0x00000010, // Property/Method - Private = 0x00000020, // Property/Method - Protected = 0x00000040, // Property/Method + Public = 0x00000010, // Property/Method/Constructor + Private = 0x00000020, // Property/Method/Constructor + Protected = 0x00000040, // Property/Method/Constructor Static = 0x00000080, // Property/Method Abstract = 0x00000100, // Class/Method/ConstructSignature Async = 0x00000200, // Property/Method/Function From c87c3c5eba68b3e349affb3d1571b951d4e478d2 Mon Sep 17 00:00:00 2001 From: AbubakerB Date: Wed, 12 Aug 2015 00:21:22 +0100 Subject: [PATCH 06/14] Clean ups! --- src/compiler/checker.ts | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 07689a70ba84e..eb68b193fcb6d 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5143,17 +5143,16 @@ namespace ts { return result; function signatureVisibilityRelatedTo(sourceSig: Signature, targetSig: Signature) { - if (!sourceSig || !targetSig) return Ternary.True; - if (sourceSig.declaration.kind !== SyntaxKind.Constructor) return Ternary.True; - - if (sourceSig.declaration && targetSig.declaration) { - let sourceVisibility = sourceSig.declaration.modifiers ? sourceSig.declaration.modifiers.flags : 0; - let targetVisibility = targetSig.declaration.modifiers ? targetSig.declaration.modifiers.flags : 0; - if (sourceVisibility !== targetVisibility && (!((sourceVisibility | targetVisibility) & NodeFlags.Public))) { - if (reportErrors) { - reportError(Diagnostics.Cannot_assign_a_non_public_constructor_type_to_a_public_constructor_type); + if (sourceSig && targetSig && sourceSig.declaration.kind === SyntaxKind.Constructor) { + if (sourceSig.declaration && targetSig.declaration) { + let sourceVisibility = sourceSig.declaration.modifiers ? sourceSig.declaration.modifiers.flags : 0; + let targetVisibility = targetSig.declaration.modifiers ? targetSig.declaration.modifiers.flags : 0; + if (sourceVisibility !== targetVisibility && (!((sourceVisibility | targetVisibility) & NodeFlags.Public))) { + if (reportErrors) { + reportError(Diagnostics.Cannot_assign_a_non_public_constructor_type_to_a_public_constructor_type); + } + return Ternary.False; } - return Ternary.False; } } return Ternary.True; @@ -8746,14 +8745,12 @@ namespace ts { // A private constructor is only accessible in the declaring class if (declaringClass !== enclosingClass) { reportError(Diagnostics.Constructor_0_is_private_and_only_accessible_within_class_1, signatureToString(result), typeToString(declaringClass)); - //return resolveErrorCall(node); } } else if (constructor.flags & NodeFlags.Protected) { // A protected constructor is only accessible in the declaring class and classes derived from it if (!enclosingClass || !hasBaseType(enclosingClass, declaringClass)) { reportError(Diagnostics.Constructor_0_is_protected_and_only_accessible_within_class_1_and_its_subclasses, signatureToString(result), typeToString(declaringClass)); - //return resolveErrorCall(node); } } } From f66e66da35b93d305fa78c468ea850d2816f83d1 Mon Sep 17 00:00:00 2001 From: AbubakerB Date: Wed, 12 Aug 2015 01:19:31 +0100 Subject: [PATCH 07/14] null check and only check signature visibility on Construct Kind. --- src/compiler/checker.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index eb68b193fcb6d..2b79bfc9c4284 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5097,9 +5097,11 @@ namespace ts { let targetSig = targetSignatures[0]; if (sourceSig && targetSig) { - result &= signatureVisibilityRelatedTo(sourceSig, targetSig); - if (result !== Ternary.True) { - return result; + if (kind === SignatureKind.Construct) { + result &= signatureVisibilityRelatedTo(sourceSig, targetSig); + if (result !== Ternary.True) { + return result; + } } let sourceErasedSignature = getErasedSignature(sourceSig); @@ -5143,7 +5145,7 @@ namespace ts { return result; function signatureVisibilityRelatedTo(sourceSig: Signature, targetSig: Signature) { - if (sourceSig && targetSig && sourceSig.declaration.kind === SyntaxKind.Constructor) { + if (sourceSig && targetSig && sourceSig.declaration && sourceSig.declaration.kind === SyntaxKind.Constructor) { if (sourceSig.declaration && targetSig.declaration) { let sourceVisibility = sourceSig.declaration.modifiers ? sourceSig.declaration.modifiers.flags : 0; let targetVisibility = targetSig.declaration.modifiers ? targetSig.declaration.modifiers.flags : 0; @@ -8723,14 +8725,12 @@ namespace ts { return resolveErrorCall(node); function checkConstructorVisibility(signature: Signature, node: NewExpression) { - let constructor = result.declaration; - let expression = (node).expression; - - if (!constructor || !expression) return; + let constructor = result.declaration; + if (!constructor || !node.expression) return; // if constructor is public, we dont need to check visibility if (constructor.flags & NodeFlags.Public) return; - let expressionType = checkExpression(expression); + let expressionType = checkExpression(node.expression); expressionType = getApparentType(expressionType); if (expressionType === unknownType) return; From 5421ac83e5f2f0f97c44b86f2d81c840cb4adfcb Mon Sep 17 00:00:00 2001 From: AbubakerB Date: Wed, 12 Aug 2015 01:29:14 +0100 Subject: [PATCH 08/14] Accept baselines --- .../classConstructorAccessibility.errors.txt | 42 ++++++++++++++----- .../classConstructorAccessibility.js | 28 ++++++++++++- .../classConstructorAccessibility2.errors.txt | 12 +++--- ...nstructorOverloadsAccessibility.errors.txt | 8 +++- .../typesWithPrivateConstructor.errors.txt | 9 ++-- 5 files changed, 78 insertions(+), 21 deletions(-) diff --git a/tests/baselines/reference/classConstructorAccessibility.errors.txt b/tests/baselines/reference/classConstructorAccessibility.errors.txt index bcd210b65279c..ace365ec9734c 100644 --- a/tests/baselines/reference/classConstructorAccessibility.errors.txt +++ b/tests/baselines/reference/classConstructorAccessibility.errors.txt @@ -1,10 +1,18 @@ -tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts(14,9): error TS2655: Constructor 'D(x: number): D' is private and only accessible within class 'D'. -tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts(15,9): error TS2654: Constructor 'E(x: number): E' is protected and only accessible within class 'E' and its subclasses. -tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts(31,13): error TS2655: Constructor 'D(x: number): D' is private and only accessible within class 'D'. -tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts(32,13): error TS2654: Constructor 'E(x: number): E' is protected and only accessible within class 'E' and its subclasses. +tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts(19,9): error TS2655: Constructor '(x: number): D' is private and only accessible within class 'D'. +tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts(20,9): error TS2654: Constructor '(x: number): E' is protected and only accessible within class 'E' and its subclasses. +tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts(37,13): error TS2655: Constructor '(x: number): D' is private and only accessible within class 'D'. +tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts(38,13): error TS2654: Constructor '(x: number): E' is protected and only accessible within class 'E' and its subclasses. +tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts(45,1): error TS2322: Type 'typeof D' is not assignable to type 'new (x: number) => any'. + Cannot assign a non-public constructor type to a public constructor type. +tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts(46,1): error TS2322: Type 'typeof E' is not assignable to type 'new (x: number) => any'. + Cannot assign a non-public constructor type to a public constructor type. -==== tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts (4 errors) ==== +==== tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts (6 errors) ==== + class B { + constructor(public x: number) { } + } + class C { public constructor(public x: number) { } } @@ -17,13 +25,14 @@ tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessib protected constructor(public x: number) { } } + var b = new B(1); var c = new C(1); var d = new D(1); // error - D is private ~~~~~~~~ -!!! error TS2655: Constructor 'D(x: number): D' is private and only accessible within class 'D'. +!!! error TS2655: Constructor '(x: number): D' is private and only accessible within class 'D'. var e = new E(1); // error - E is protected ~~~~~~~~ -!!! error TS2654: Constructor 'E(x: number): E' is protected and only accessible within class 'E' and its subclasses. +!!! error TS2654: Constructor '(x: number): E' is protected and only accessible within class 'E' and its subclasses. module Generic { class C { @@ -38,12 +47,25 @@ tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessib protected constructor(public x: T) { } } + var b = new B(1); var c = new C(1); var d = new D(1); // error - D is private ~~~~~~~~ -!!! error TS2655: Constructor 'D(x: number): D' is private and only accessible within class 'D'. +!!! error TS2655: Constructor '(x: number): D' is private and only accessible within class 'D'. var e = new E(1); // error - E is protected ~~~~~~~~ -!!! error TS2654: Constructor 'E(x: number): E' is protected and only accessible within class 'E' and its subclasses. +!!! error TS2654: Constructor '(x: number): E' is protected and only accessible within class 'E' and its subclasses. } - \ No newline at end of file + + // make sure signatures are covered. + let sig: new(x: number) => any; + sig = B; + sig = C; + sig = D; // error - non-public to public + ~~~ +!!! error TS2322: Type 'typeof D' is not assignable to type 'new (x: number) => any'. +!!! error TS2322: Cannot assign a non-public constructor type to a public constructor type. + sig = E; // error - non-public to public + ~~~ +!!! error TS2322: Type 'typeof E' is not assignable to type 'new (x: number) => any'. +!!! error TS2322: Cannot assign a non-public constructor type to a public constructor type. \ No newline at end of file diff --git a/tests/baselines/reference/classConstructorAccessibility.js b/tests/baselines/reference/classConstructorAccessibility.js index 70c1646fe3596..6eaa819987b02 100644 --- a/tests/baselines/reference/classConstructorAccessibility.js +++ b/tests/baselines/reference/classConstructorAccessibility.js @@ -1,4 +1,8 @@ //// [classConstructorAccessibility.ts] +class B { + constructor(public x: number) { } +} + class C { public constructor(public x: number) { } } @@ -11,6 +15,7 @@ class E { protected constructor(public x: number) { } } +var b = new B(1); var c = new C(1); var d = new D(1); // error - D is private var e = new E(1); // error - E is protected @@ -28,13 +33,26 @@ module Generic { protected constructor(public x: T) { } } + var b = new B(1); var c = new C(1); var d = new D(1); // error - D is private var e = new E(1); // error - E is protected } - + +// make sure signatures are covered. +let sig: new(x: number) => any; +sig = B; +sig = C; +sig = D; // error - non-public to public +sig = E; // error - non-public to public //// [classConstructorAccessibility.js] +var B = (function () { + function B(x) { + this.x = x; + } + return B; +})(); var C = (function () { function C(x) { this.x = x; @@ -53,6 +71,7 @@ var E = (function () { } return E; })(); +var b = new B(1); var c = new C(1); var d = new D(1); // error - D is private var e = new E(1); // error - E is protected @@ -76,7 +95,14 @@ var Generic; } return E; })(); + var b = new B(1); var c = new C(1); var d = new D(1); // error - D is private var e = new E(1); // error - E is protected })(Generic || (Generic = {})); +// make sure signatures are covered. +var sig; +sig = B; +sig = C; +sig = D; // error - non-public to public +sig = E; // error - non-public to public diff --git a/tests/baselines/reference/classConstructorAccessibility2.errors.txt b/tests/baselines/reference/classConstructorAccessibility2.errors.txt index 7ebe0259f7c04..2be304548a43c 100644 --- a/tests/baselines/reference/classConstructorAccessibility2.errors.txt +++ b/tests/baselines/reference/classConstructorAccessibility2.errors.txt @@ -1,7 +1,7 @@ tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility2.ts(16,21): error TS2653: Cannot extend private class 'A'. -tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility2.ts(18,12): error TS2655: Constructor 'A(a: string): A' is private and only accessible within class 'A'. -tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility2.ts(47,10): error TS2655: Constructor 'A(a: string): A' is private and only accessible within class 'A'. -tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility2.ts(48,10): error TS2654: Constructor 'B(): B' is protected and only accessible within class 'B' and its subclasses. +tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility2.ts(18,12): error TS2655: Constructor '(a: string): A' is private and only accessible within class 'A'. +tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility2.ts(47,10): error TS2655: Constructor '(a: string): A' is private and only accessible within class 'A'. +tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility2.ts(48,10): error TS2654: Constructor '(): B' is protected and only accessible within class 'B' and its subclasses. ==== tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility2.ts (4 errors) ==== @@ -26,7 +26,7 @@ tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessib method() { var t1 = new A(""); // error - A is private and only accessible in it's own class ~~~~~~~~~ -!!! error TS2655: Constructor 'A(a: string): A' is private and only accessible within class 'A'. +!!! error TS2655: Constructor '(a: string): A' is private and only accessible within class 'A'. } } @@ -57,8 +57,8 @@ tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessib // check global scope var t1 = new A(""); // error - A is private ~~~~~~~~~ -!!! error TS2655: Constructor 'A(a: string): A' is private and only accessible within class 'A'. +!!! error TS2655: Constructor '(a: string): A' is private and only accessible within class 'A'. var t2 = new B(); // error - B is protected ~~~~~~~ -!!! error TS2654: Constructor 'B(): B' is protected and only accessible within class 'B' and its subclasses. +!!! error TS2654: Constructor '(): B' is protected and only accessible within class 'B' and its subclasses. var t3 = new C(); \ No newline at end of file diff --git a/tests/baselines/reference/classConstructorOverloadsAccessibility.errors.txt b/tests/baselines/reference/classConstructorOverloadsAccessibility.errors.txt index 69371d5e7da9b..a21a504192d7b 100644 --- a/tests/baselines/reference/classConstructorOverloadsAccessibility.errors.txt +++ b/tests/baselines/reference/classConstructorOverloadsAccessibility.errors.txt @@ -1,9 +1,11 @@ tests/cases/conformance/classes/constructorDeclarations/classConstructorOverloadsAccessibility.ts(2,2): error TS2385: Overload signatures must all be public, private or protected. 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(3,2): error TS2394: Overload signature is not compatible with function implementation. tests/cases/conformance/classes/constructorDeclarations/classConstructorOverloadsAccessibility.ts(11,2): error TS2385: Overload signatures must all be public, private or protected. +tests/cases/conformance/classes/constructorDeclarations/classConstructorOverloadsAccessibility.ts(11,2): error TS2394: Overload signature is not compatible with function implementation. -==== tests/cases/conformance/classes/constructorDeclarations/classConstructorOverloadsAccessibility.ts (3 errors) ==== +==== tests/cases/conformance/classes/constructorDeclarations/classConstructorOverloadsAccessibility.ts (5 errors) ==== class A { public constructor(a: boolean) // error ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -11,6 +13,8 @@ tests/cases/conformance/classes/constructorDeclarations/classConstructorOverload protected constructor(a: number) // error ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ !!! error TS2385: Overload signatures must all be public, private or protected. + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2394: Overload signature is not compatible with function implementation. private constructor(a: string) private constructor() { @@ -21,6 +25,8 @@ tests/cases/conformance/classes/constructorDeclarations/classConstructorOverload protected constructor(a: number) // error ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ !!! error TS2385: Overload signatures must all be public, private or protected. + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2394: Overload signature is not compatible with function implementation. constructor(a: string) constructor() { diff --git a/tests/baselines/reference/typesWithPrivateConstructor.errors.txt b/tests/baselines/reference/typesWithPrivateConstructor.errors.txt index 4bffd7f9b7d5c..e10c678b7fb9c 100644 --- a/tests/baselines/reference/typesWithPrivateConstructor.errors.txt +++ b/tests/baselines/reference/typesWithPrivateConstructor.errors.txt @@ -1,8 +1,9 @@ -tests/cases/conformance/types/members/typesWithPrivateConstructor.ts(7,9): error TS2655: Constructor 'C(): C' is private and only accessible within class 'C'. +tests/cases/conformance/types/members/typesWithPrivateConstructor.ts(7,9): error TS2655: Constructor '(): C' is private and only accessible within class 'C'. +tests/cases/conformance/types/members/typesWithPrivateConstructor.ts(8,5): error TS2322: Type 'Function' is not assignable to type '() => void'. 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 (2 errors) ==== +==== tests/cases/conformance/types/members/typesWithPrivateConstructor.ts (3 errors) ==== // private constructors are not allowed class C { @@ -11,8 +12,10 @@ tests/cases/conformance/types/members/typesWithPrivateConstructor.ts(15,10): err var c = new C(); ~~~~~~~ -!!! error TS2655: Constructor 'C(): C' is private and only accessible within class 'C'. +!!! error TS2655: Constructor '(): C' is private and only accessible within class 'C'. var r: () => void = c.constructor; + ~ +!!! error TS2322: Type 'Function' is not assignable to type '() => void'. class C2 { private constructor(x: number); From ffec744c0ba1898bedbe3402e998755c22d13530 Mon Sep 17 00:00:00 2001 From: AbubakerB Date: Mon, 14 Sep 2015 22:34:27 +0100 Subject: [PATCH 09/14] Addressed CR feedback --- src/compiler/checker.ts | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 2b79bfc9c4284..89cda746ba421 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -8726,16 +8726,24 @@ namespace ts { function checkConstructorVisibility(signature: Signature, node: NewExpression) { let constructor = result.declaration; - if (!constructor || !node.expression) return; - // if constructor is public, we dont need to check visibility - if (constructor.flags & NodeFlags.Public) return; + if (!constructor || !node.expression) { + return; + } + // if constructor is public, we don't need to check visibility + if (constructor.flags & NodeFlags.Public) { + return; + } let expressionType = checkExpression(node.expression); expressionType = getApparentType(expressionType); - if (expressionType === unknownType) return; + if (expressionType === unknownType) { + return; + } let declaration = expressionType.symbol && getDeclarationOfKind(expressionType.symbol, SyntaxKind.ClassDeclaration); - if (!declaration) return; + if (!declaration) { + return; + } // Get the declaring and enclosing class instance types let enclosingClassDeclaration = getContainingClass(node); @@ -15065,7 +15073,7 @@ namespace ts { let signatures = getSignaturesOfType(baseType, SignatureKind.Construct); for (let signature of signatures) { let constuctor = signature.declaration; - if (constuctor && constuctor.flags & NodeFlags.Private) { + if (constuctor && (constuctor.flags & NodeFlags.Private)) { return grammarErrorOnFirstToken(expression, Diagnostics.Cannot_extend_private_class_0, (expression).text); } } From 0e8ecbd94c8036b95ff2bbc5d744bfc33b25740e Mon Sep 17 00:00:00 2001 From: AbubakerB Date: Mon, 14 Sep 2015 22:35:44 +0100 Subject: [PATCH 10/14] Changed error message for mismatching ctor signature --- src/compiler/checker.ts | 12 +++++++++++- src/compiler/diagnosticInformationMap.generated.ts | 2 +- src/compiler/diagnosticMessages.json | 2 +- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 89cda746ba421..ec590b6765971 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5151,13 +5151,23 @@ namespace ts { let targetVisibility = targetSig.declaration.modifiers ? targetSig.declaration.modifiers.flags : 0; if (sourceVisibility !== targetVisibility && (!((sourceVisibility | targetVisibility) & NodeFlags.Public))) { if (reportErrors) { - reportError(Diagnostics.Cannot_assign_a_non_public_constructor_type_to_a_public_constructor_type); + reportError(Diagnostics.Cannot_assign_a_0_constructor_to_a_1_constructor, visibilityToText(sourceVisibility), visibilityToText(targetVisibility)); } return Ternary.False; } } } return Ternary.True; + + function visibilityToText(flag: NodeFlags) { + if (flag === NodeFlags.Private) { + return "private"; + } + if (flag === NodeFlags.Protected) { + return "protected"; + } + return "public"; + } } } diff --git a/src/compiler/diagnosticInformationMap.generated.ts b/src/compiler/diagnosticInformationMap.generated.ts index 3080a255d17ab..378a54b8bd6c1 100644 --- a/src/compiler/diagnosticInformationMap.generated.ts +++ b/src/compiler/diagnosticInformationMap.generated.ts @@ -430,7 +430,7 @@ namespace ts { Cannot_extend_private_class_0: { code: 2653, category: DiagnosticCategory.Error, key: "Cannot extend private class '{0}'." }, Constructor_0_is_protected_and_only_accessible_within_class_1_and_its_subclasses: { code: 2654, category: DiagnosticCategory.Error, key: "Constructor '{0}' is protected and only accessible within class '{1}' and its subclasses." }, Constructor_0_is_private_and_only_accessible_within_class_1: { code: 2655, category: DiagnosticCategory.Error, key: "Constructor '{0}' is private and only accessible within class '{1}'." }, - Cannot_assign_a_non_public_constructor_type_to_a_public_constructor_type: { code: 2656, category: DiagnosticCategory.Error, key: "Cannot assign a non-public constructor type to a public constructor type." }, + Cannot_assign_a_0_constructor_to_a_1_constructor: { code: 2656, category: DiagnosticCategory.Error, key: "Cannot assign a {0} constructor to a {1} constructor." }, Import_declaration_0_is_using_private_name_1: { code: 4000, category: DiagnosticCategory.Error, key: "Import declaration '{0}' is using private name '{1}'." }, Type_parameter_0_of_exported_class_has_or_is_using_private_name_1: { code: 4002, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of exported class has or is using private name '{1}'." }, Type_parameter_0_of_exported_interface_has_or_is_using_private_name_1: { code: 4004, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of exported interface has or is using private name '{1}'." }, diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index cbf6ac1eb63d0..856d116ee3084 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1709,7 +1709,7 @@ "category": "Error", "code": 2655 }, - "Cannot assign a non-public constructor type to a public constructor type.": { + "Cannot assign a {0} constructor to a {1} constructor.": { "category": "Error", "code": 2656 }, From 3732fcdbf12a2e7279f19b85b462a7ccec010f67 Mon Sep 17 00:00:00 2001 From: AbubakerB Date: Mon, 14 Sep 2015 22:36:36 +0100 Subject: [PATCH 11/14] Addressed test PR feedback. --- .../classConstructorAccessibility.ts | 6 +++-- .../classConstructorAccessibility2.ts | 25 ++++++++++++++++++- .../classConstructorOverloadsAccessibility.ts | 2 ++ 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts b/tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts index 09d4f8d91b669..922c93eae7449 100644 --- a/tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts +++ b/tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts @@ -1,3 +1,5 @@ +// @declaration: true + class B { constructor(public x: number) { } } @@ -42,5 +44,5 @@ module Generic { let sig: new(x: number) => any; sig = B; sig = C; -sig = D; // error - non-public to public -sig = E; // error - non-public to public \ No newline at end of file +sig = D; // error - private to public +sig = E; // error - protected to public \ No newline at end of file diff --git a/tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility2.ts b/tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility2.ts index ff94e05204309..737932d2f6e43 100644 --- a/tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility2.ts +++ b/tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility2.ts @@ -1,3 +1,5 @@ +// @declaration: true + class A { private constructor(a: string) // only private access private constructor() { @@ -46,4 +48,25 @@ class C { // check global scope var t1 = new A(""); // error - A is private var t2 = new B(); // error - B is protected -var t3 = new C(); \ No newline at end of file +var t3 = new C(); + +// check Derived super call of a protected Base +class Base { + protected constructor() { + } +} + +class Derived extends Base { + protected constructor() { + super(); + } +} + +class SuperDerived extends Derived { + private constructor(){ + super(); + } +} + +var baseCtor = Base; +baseCtor = Derived; \ No newline at end of file diff --git a/tests/cases/conformance/classes/constructorDeclarations/classConstructorOverloadsAccessibility.ts b/tests/cases/conformance/classes/constructorDeclarations/classConstructorOverloadsAccessibility.ts index 4bee5614f8757..48b3ac21128b2 100644 --- a/tests/cases/conformance/classes/constructorDeclarations/classConstructorOverloadsAccessibility.ts +++ b/tests/cases/conformance/classes/constructorDeclarations/classConstructorOverloadsAccessibility.ts @@ -1,3 +1,5 @@ +// @declaration: true + class A { public constructor(a: boolean) // error protected constructor(a: number) // error From f2d3b2939fbb650e9ec86370a089c1dfc201c11d Mon Sep 17 00:00:00 2001 From: AbubakerB Date: Mon, 14 Sep 2015 22:37:47 +0100 Subject: [PATCH 12/14] Accepted new baselines --- .../classConstructorAccessibility.errors.txt | 25 +++--- .../classConstructorAccessibility.js | 35 +++++++- .../classConstructorAccessibility2.errors.txt | 32 ++++++-- .../classConstructorAccessibility2.js | 81 ++++++++++++++++++- ...nstructorOverloadsAccessibility.errors.txt | 9 ++- .../classConstructorOverloadsAccessibility.js | 21 +++++ 6 files changed, 177 insertions(+), 26 deletions(-) diff --git a/tests/baselines/reference/classConstructorAccessibility.errors.txt b/tests/baselines/reference/classConstructorAccessibility.errors.txt index ace365ec9734c..d27993dacb0ee 100644 --- a/tests/baselines/reference/classConstructorAccessibility.errors.txt +++ b/tests/baselines/reference/classConstructorAccessibility.errors.txt @@ -1,14 +1,15 @@ -tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts(19,9): error TS2655: Constructor '(x: number): D' is private and only accessible within class 'D'. -tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts(20,9): error TS2654: Constructor '(x: number): E' is protected and only accessible within class 'E' and its subclasses. -tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts(37,13): error TS2655: Constructor '(x: number): D' is private and only accessible within class 'D'. -tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts(38,13): error TS2654: Constructor '(x: number): E' is protected and only accessible within class 'E' and its subclasses. -tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts(45,1): error TS2322: Type 'typeof D' is not assignable to type 'new (x: number) => any'. - Cannot assign a non-public constructor type to a public constructor type. -tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts(46,1): error TS2322: Type 'typeof E' is not assignable to type 'new (x: number) => any'. - Cannot assign a non-public constructor type to a public constructor type. +tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts(20,9): error TS2655: Constructor '(x: number): D' is private and only accessible within class 'D'. +tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts(21,9): error TS2654: Constructor '(x: number): E' is protected and only accessible within class 'E' and its subclasses. +tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts(38,13): error TS2655: Constructor '(x: number): D' is private and only accessible within class 'D'. +tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts(39,13): error TS2654: Constructor '(x: number): E' is protected and only accessible within class 'E' and its subclasses. +tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts(46,1): error TS2322: Type 'typeof D' is not assignable to type 'new (x: number) => any'. + Cannot assign a private constructor to a public constructor. +tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts(47,1): error TS2322: Type 'typeof E' is not assignable to type 'new (x: number) => any'. + Cannot assign a protected constructor to a public constructor. ==== tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts (6 errors) ==== + class B { constructor(public x: number) { } } @@ -61,11 +62,11 @@ tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessib let sig: new(x: number) => any; sig = B; sig = C; - sig = D; // error - non-public to public + sig = D; // error - private to public ~~~ !!! error TS2322: Type 'typeof D' is not assignable to type 'new (x: number) => any'. -!!! error TS2322: Cannot assign a non-public constructor type to a public constructor type. - sig = E; // error - non-public to public +!!! error TS2322: Cannot assign a private constructor to a public constructor. + sig = E; // error - protected to public ~~~ !!! error TS2322: Type 'typeof E' is not assignable to type 'new (x: number) => any'. -!!! error TS2322: Cannot assign a non-public constructor type to a public constructor type. \ No newline at end of file +!!! error TS2322: Cannot assign a protected constructor to a public constructor. \ No newline at end of file diff --git a/tests/baselines/reference/classConstructorAccessibility.js b/tests/baselines/reference/classConstructorAccessibility.js index 6eaa819987b02..f1f2509b905ba 100644 --- a/tests/baselines/reference/classConstructorAccessibility.js +++ b/tests/baselines/reference/classConstructorAccessibility.js @@ -1,4 +1,5 @@ //// [classConstructorAccessibility.ts] + class B { constructor(public x: number) { } } @@ -43,8 +44,8 @@ module Generic { let sig: new(x: number) => any; sig = B; sig = C; -sig = D; // error - non-public to public -sig = E; // error - non-public to public +sig = D; // error - private to public +sig = E; // error - protected to public //// [classConstructorAccessibility.js] var B = (function () { @@ -104,5 +105,31 @@ var Generic; var sig; sig = B; sig = C; -sig = D; // error - non-public to public -sig = E; // error - non-public to public +sig = D; // error - private to public +sig = E; // error - protected to public + + +//// [classConstructorAccessibility.d.ts] +declare class B { + x: number; + constructor(x: number); +} +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 b: B; +declare var c: C; +declare var d: D; +declare var e: E; +declare module Generic { +} +declare let sig: new (x: number) => any; diff --git a/tests/baselines/reference/classConstructorAccessibility2.errors.txt b/tests/baselines/reference/classConstructorAccessibility2.errors.txt index 2be304548a43c..1e31715d3dc96 100644 --- a/tests/baselines/reference/classConstructorAccessibility2.errors.txt +++ b/tests/baselines/reference/classConstructorAccessibility2.errors.txt @@ -1,10 +1,11 @@ -tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility2.ts(16,21): error TS2653: Cannot extend private class 'A'. -tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility2.ts(18,12): error TS2655: Constructor '(a: string): A' is private and only accessible within class 'A'. -tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility2.ts(47,10): error TS2655: Constructor '(a: string): A' is private and only accessible within class 'A'. -tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility2.ts(48,10): error TS2654: Constructor '(): B' is protected and only accessible within class 'B' and its subclasses. +tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility2.ts(17,21): error TS2653: Cannot extend private class 'A'. +tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility2.ts(19,12): error TS2655: Constructor '(a: string): A' is private and only accessible within class 'A'. +tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility2.ts(48,10): error TS2655: Constructor '(a: string): A' is private and only accessible within class 'A'. +tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility2.ts(49,10): error TS2654: Constructor '(): B' is protected and only accessible within class 'B' and its subclasses. ==== tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility2.ts (4 errors) ==== + class A { private constructor(a: string) // only private access private constructor() { @@ -61,4 +62,25 @@ tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessib var t2 = new B(); // error - B is protected ~~~~~~~ !!! error TS2654: Constructor '(): B' is protected and only accessible within class 'B' and its subclasses. - var t3 = new C(); \ No newline at end of file + var t3 = new C(); + + // check Derived super call of a protected Base + class Base { + protected constructor() { + } + } + + class Derived extends Base { + protected constructor() { + super(); + } + } + + class SuperDerived extends Derived { + private constructor(){ + super(); + } + } + + var baseCtor = Base; + baseCtor = Derived; \ No newline at end of file diff --git a/tests/baselines/reference/classConstructorAccessibility2.js b/tests/baselines/reference/classConstructorAccessibility2.js index d2004161290cc..cb6be6ced24f2 100644 --- a/tests/baselines/reference/classConstructorAccessibility2.js +++ b/tests/baselines/reference/classConstructorAccessibility2.js @@ -1,4 +1,5 @@ //// [classConstructorAccessibility2.ts] + class A { private constructor(a: string) // only private access private constructor() { @@ -47,7 +48,28 @@ class C { // check global scope var t1 = new A(""); // error - A is private var t2 = new B(); // error - B is protected -var t3 = new C(); +var t3 = new C(); + +// check Derived super call of a protected Base +class Base { + protected constructor() { + } +} + +class Derived extends Base { + protected constructor() { + super(); + } +} + +class SuperDerived extends Derived { + private constructor(){ + super(); + } +} + +var baseCtor = Base; +baseCtor = Derived; //// [classConstructorAccessibility2.js] var __extends = (this && this.__extends) || function (d, b) { @@ -106,3 +128,60 @@ var C = (function () { var t1 = new A(""); // error - A is private var t2 = new B(); // error - B is protected var t3 = new C(); +// check Derived super call of a protected Base +var Base = (function () { + function Base() { + } + return Base; +})(); +var Derived = (function (_super) { + __extends(Derived, _super); + function Derived() { + _super.call(this); + } + return Derived; +})(Base); +var SuperDerived = (function (_super) { + __extends(SuperDerived, _super); + function SuperDerived() { + _super.call(this); + } + return SuperDerived; +})(Derived); +var baseCtor = Base; +baseCtor = Derived; + + +//// [classConstructorAccessibility2.d.ts] +declare class A { + constructor(a); + static method(): void; + method(): void; +} +declare class A_ext extends A { + method(): void; +} +declare class B { + constructor(); + method(): void; +} +declare class B_ext extends B { + method(): void; +} +declare class C { + constructor(); + methodA(): void; +} +declare var t1: A; +declare var t2: B; +declare var t3: C; +declare class Base { + constructor(); +} +declare class Derived extends Base { + constructor(); +} +declare class SuperDerived extends Derived { + constructor(); +} +declare var baseCtor: typeof Base; diff --git a/tests/baselines/reference/classConstructorOverloadsAccessibility.errors.txt b/tests/baselines/reference/classConstructorOverloadsAccessibility.errors.txt index a21a504192d7b..7cde7beaa5f53 100644 --- a/tests/baselines/reference/classConstructorOverloadsAccessibility.errors.txt +++ b/tests/baselines/reference/classConstructorOverloadsAccessibility.errors.txt @@ -1,11 +1,12 @@ -tests/cases/conformance/classes/constructorDeclarations/classConstructorOverloadsAccessibility.ts(2,2): error TS2385: Overload signatures must all be public, private or protected. 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(3,2): error TS2394: Overload signature is not compatible with function implementation. -tests/cases/conformance/classes/constructorDeclarations/classConstructorOverloadsAccessibility.ts(11,2): error TS2385: Overload signatures must all be public, private or protected. -tests/cases/conformance/classes/constructorDeclarations/classConstructorOverloadsAccessibility.ts(11,2): error TS2394: Overload signature is not compatible with function implementation. +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(4,2): error TS2394: Overload signature is not compatible with function implementation. +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(12,2): error TS2394: Overload signature is not compatible with function implementation. ==== tests/cases/conformance/classes/constructorDeclarations/classConstructorOverloadsAccessibility.ts (5 errors) ==== + class A { public constructor(a: boolean) // error ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/tests/baselines/reference/classConstructorOverloadsAccessibility.js b/tests/baselines/reference/classConstructorOverloadsAccessibility.js index 2027261aa06ea..c0b252cd77dbb 100644 --- a/tests/baselines/reference/classConstructorOverloadsAccessibility.js +++ b/tests/baselines/reference/classConstructorOverloadsAccessibility.js @@ -1,4 +1,5 @@ //// [classConstructorOverloadsAccessibility.ts] + class A { public constructor(a: boolean) // error protected constructor(a: number) // error @@ -53,3 +54,23 @@ var D = (function () { } 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); +} From 35fceb959b3e21f0817bf3c5047769b0de8e02db Mon Sep 17 00:00:00 2001 From: AbubakerB Date: Tue, 15 Sep 2015 21:51:10 +0100 Subject: [PATCH 13/14] Addressed PR feedback - Amended diagnostic messages --- src/compiler/checker.ts | 4 ++-- src/compiler/diagnosticInformationMap.generated.ts | 4 ++-- src/compiler/diagnosticMessages.json | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ec590b6765971..746522e61faf1 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -8762,13 +8762,13 @@ namespace ts { if (constructor.flags & NodeFlags.Private) { // A private constructor is only accessible in the declaring class if (declaringClass !== enclosingClass) { - reportError(Diagnostics.Constructor_0_is_private_and_only_accessible_within_class_1, signatureToString(result), typeToString(declaringClass)); + reportError(Diagnostics.Constructor_of_type_0_is_private_and_only_accessible_within_class_1, signatureToString(result), typeToString(declaringClass)); } } else if (constructor.flags & NodeFlags.Protected) { // A protected constructor is only accessible in the declaring class and classes derived from it if (!enclosingClass || !hasBaseType(enclosingClass, declaringClass)) { - reportError(Diagnostics.Constructor_0_is_protected_and_only_accessible_within_class_1_and_its_subclasses, signatureToString(result), typeToString(declaringClass)); + reportError(Diagnostics.Constructor_of_type_0_is_protected_and_only_accessible_within_class_1_and_its_subclasses, signatureToString(result), typeToString(declaringClass)); } } } diff --git a/src/compiler/diagnosticInformationMap.generated.ts b/src/compiler/diagnosticInformationMap.generated.ts index 378a54b8bd6c1..704615b2f4adb 100644 --- a/src/compiler/diagnosticInformationMap.generated.ts +++ b/src/compiler/diagnosticInformationMap.generated.ts @@ -428,8 +428,8 @@ namespace ts { A_member_initializer_in_a_const_enum_declaration_cannot_reference_members_declared_after_it_including_members_defined_in_other_const_enums: { code: 2651, category: DiagnosticCategory.Error, key: "A member initializer in a 'const' enum declaration cannot reference members declared after it, including members defined in other 'const' enums." }, Merged_declaration_0_cannot_include_a_default_export_declaration_Consider_adding_a_separate_export_default_0_declaration_instead: { code: 2652, category: DiagnosticCategory.Error, key: "Merged declaration '{0}' cannot include a default export declaration. Consider adding a separate 'export default {0}' declaration instead." }, Cannot_extend_private_class_0: { code: 2653, category: DiagnosticCategory.Error, key: "Cannot extend private class '{0}'." }, - Constructor_0_is_protected_and_only_accessible_within_class_1_and_its_subclasses: { code: 2654, category: DiagnosticCategory.Error, key: "Constructor '{0}' is protected and only accessible within class '{1}' and its subclasses." }, - Constructor_0_is_private_and_only_accessible_within_class_1: { code: 2655, category: DiagnosticCategory.Error, key: "Constructor '{0}' is private and only accessible within class '{1}'." }, + Constructor_of_type_0_is_protected_and_only_accessible_within_class_1_and_its_subclasses: { code: 2654, category: DiagnosticCategory.Error, key: "Constructor of type '{0}' is protected and only accessible within class '{1}' and its subclasses." }, + Constructor_of_type_0_is_private_and_only_accessible_within_class_1: { code: 2655, category: DiagnosticCategory.Error, key: "Constructor of type '{0}' is private and only accessible within class '{1}'." }, Cannot_assign_a_0_constructor_to_a_1_constructor: { code: 2656, category: DiagnosticCategory.Error, key: "Cannot assign a {0} constructor to a {1} constructor." }, Import_declaration_0_is_using_private_name_1: { code: 4000, category: DiagnosticCategory.Error, key: "Import declaration '{0}' is using private name '{1}'." }, Type_parameter_0_of_exported_class_has_or_is_using_private_name_1: { code: 4002, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of exported class has or is using private name '{1}'." }, diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 856d116ee3084..8877da4d0c780 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1701,11 +1701,11 @@ "category": "Error", "code": 2653 }, - "Constructor '{0}' is protected and only accessible within class '{1}' and its subclasses.": { + "Constructor of type '{0}' is protected and only accessible within class '{1}' and its subclasses.": { "category": "Error", "code": 2654 }, - "Constructor '{0}' is private and only accessible within class '{1}'.": { + "Constructor of type '{0}' is private and only accessible within class '{1}'.": { "category": "Error", "code": 2655 }, From f6d8a0cb154a88bb1f5b9fd1c072d5c3141c2688 Mon Sep 17 00:00:00 2001 From: AbubakerB Date: Tue, 15 Sep 2015 21:52:51 +0100 Subject: [PATCH 14/14] Accept baselines --- .../classConstructorAccessibility.errors.txt | 16 ++++++++-------- .../classConstructorAccessibility2.errors.txt | 12 ++++++------ .../typesWithPrivateConstructor.errors.txt | 4 ++-- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/tests/baselines/reference/classConstructorAccessibility.errors.txt b/tests/baselines/reference/classConstructorAccessibility.errors.txt index d27993dacb0ee..4520b90457bdd 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(20,9): error TS2655: Constructor '(x: number): D' is private and only accessible within class 'D'. -tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts(21,9): error TS2654: Constructor '(x: number): E' is protected and only accessible within class 'E' and its subclasses. -tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts(38,13): error TS2655: Constructor '(x: number): D' is private and only accessible within class 'D'. -tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts(39,13): error TS2654: Constructor '(x: number): E' is protected and only accessible within class 'E' and its subclasses. +tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts(20,9): error TS2655: Constructor of type '(x: number): D' is private and only accessible within class 'D'. +tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts(21,9): error TS2654: Constructor of type '(x: number): E' is protected and only accessible within class 'E' and its subclasses. +tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts(38,13): error TS2655: Constructor of type '(x: number): D' is private and only accessible within class 'D'. +tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts(39,13): error TS2654: Constructor of type '(x: number): E' is protected and only accessible within class 'E' and its subclasses. tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts(46,1): error TS2322: Type 'typeof D' is not assignable to type 'new (x: number) => any'. Cannot assign a private constructor to a public constructor. tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility.ts(47,1): error TS2322: Type 'typeof E' is not assignable to type 'new (x: number) => any'. @@ -30,10 +30,10 @@ tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessib var c = new C(1); var d = new D(1); // error - D is private ~~~~~~~~ -!!! error TS2655: Constructor '(x: number): D' is private and only accessible within class 'D'. +!!! error TS2655: Constructor of type '(x: number): D' is private and only accessible within class 'D'. var e = new E(1); // error - E is protected ~~~~~~~~ -!!! error TS2654: Constructor '(x: number): E' is protected and only accessible within class 'E' and its subclasses. +!!! error TS2654: Constructor of type '(x: number): E' is protected and only accessible within class 'E' and its subclasses. module Generic { class C { @@ -52,10 +52,10 @@ tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessib var c = new C(1); var d = new D(1); // error - D is private ~~~~~~~~ -!!! error TS2655: Constructor '(x: number): D' is private and only accessible within class 'D'. +!!! error TS2655: Constructor of type '(x: number): D' is private and only accessible within class 'D'. var e = new E(1); // error - E is protected ~~~~~~~~ -!!! error TS2654: Constructor '(x: number): E' is protected and only accessible within class 'E' and its subclasses. +!!! error TS2654: Constructor of type '(x: number): E' is protected and only accessible within class 'E' and its subclasses. } // make sure signatures are covered. diff --git a/tests/baselines/reference/classConstructorAccessibility2.errors.txt b/tests/baselines/reference/classConstructorAccessibility2.errors.txt index 1e31715d3dc96..c54a27cc05e64 100644 --- a/tests/baselines/reference/classConstructorAccessibility2.errors.txt +++ b/tests/baselines/reference/classConstructorAccessibility2.errors.txt @@ -1,7 +1,7 @@ tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility2.ts(17,21): error TS2653: Cannot extend private class 'A'. -tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility2.ts(19,12): error TS2655: Constructor '(a: string): A' is private and only accessible within class 'A'. -tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility2.ts(48,10): error TS2655: Constructor '(a: string): A' is private and only accessible within class 'A'. -tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility2.ts(49,10): error TS2654: Constructor '(): B' is protected and only accessible within class 'B' and its subclasses. +tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility2.ts(19,12): error TS2655: Constructor of type '(a: string): A' is private and only accessible within class 'A'. +tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility2.ts(48,10): error TS2655: Constructor of type '(a: string): A' is private and only accessible within class 'A'. +tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility2.ts(49,10): error TS2654: Constructor of type '(): B' is protected and only accessible within class 'B' and its subclasses. ==== tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessibility2.ts (4 errors) ==== @@ -27,7 +27,7 @@ tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessib method() { var t1 = new A(""); // error - A is private and only accessible in it's own class ~~~~~~~~~ -!!! error TS2655: Constructor '(a: string): A' is private and only accessible within class 'A'. +!!! error TS2655: Constructor of type '(a: string): A' is private and only accessible within class 'A'. } } @@ -58,10 +58,10 @@ tests/cases/conformance/classes/constructorDeclarations/classConstructorAccessib // check global scope var t1 = new A(""); // error - A is private ~~~~~~~~~ -!!! error TS2655: Constructor '(a: string): A' is private and only accessible within class 'A'. +!!! error TS2655: Constructor of type '(a: string): A' is private and only accessible within class 'A'. var t2 = new B(); // error - B is protected ~~~~~~~ -!!! error TS2654: Constructor '(): B' is protected and only accessible within class 'B' and its subclasses. +!!! error TS2654: Constructor of type '(): B' is protected and only accessible within class 'B' and its subclasses. var t3 = new C(); // check Derived super call of a protected Base diff --git a/tests/baselines/reference/typesWithPrivateConstructor.errors.txt b/tests/baselines/reference/typesWithPrivateConstructor.errors.txt index e10c678b7fb9c..ddbae5a90f053 100644 --- a/tests/baselines/reference/typesWithPrivateConstructor.errors.txt +++ b/tests/baselines/reference/typesWithPrivateConstructor.errors.txt @@ -1,4 +1,4 @@ -tests/cases/conformance/types/members/typesWithPrivateConstructor.ts(7,9): error TS2655: Constructor '(): C' is private and only accessible within class 'C'. +tests/cases/conformance/types/members/typesWithPrivateConstructor.ts(7,9): error TS2655: Constructor of type '(): C' is private and only accessible within class 'C'. tests/cases/conformance/types/members/typesWithPrivateConstructor.ts(8,5): error TS2322: Type 'Function' is not assignable to type '() => void'. tests/cases/conformance/types/members/typesWithPrivateConstructor.ts(15,10): error TS2346: Supplied parameters do not match any signature of call target. @@ -12,7 +12,7 @@ tests/cases/conformance/types/members/typesWithPrivateConstructor.ts(15,10): err var c = new C(); ~~~~~~~ -!!! error TS2655: Constructor '(): C' is private and only accessible within class 'C'. +!!! error TS2655: 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'.