Fix #15062: report errors for parameter properties in private constructors

This commit is contained in:
Mohamed Hegazy
2017-05-09 12:01:10 -07:00
parent 888e264eda
commit a2dec0d03d
13 changed files with 248 additions and 7 deletions

View File

@@ -1266,7 +1266,9 @@ namespace ts {
Diagnostics.Exported_variable_0_has_or_is_using_private_name_1;
}
// This check is to ensure we don't report error on constructor parameter property as that error would be reported during parameter emit
else if (node.kind === SyntaxKind.PropertyDeclaration || node.kind === SyntaxKind.PropertySignature) {
// The only exception here is if the constructor was marked as private. we are not emitting the constructor paramters at all.
else if (node.kind === SyntaxKind.PropertyDeclaration || node.kind === SyntaxKind.PropertySignature ||
(node.kind === SyntaxKind.Parameter && hasModifier(node.parent, ModifierFlags.Private))) {
// TODO(jfreeman): Deal with computed properties in error reporting.
if (hasModifier(node, ModifierFlags.Static)) {
return symbolAccessibilityResult.errorModuleName ?
@@ -1275,7 +1277,7 @@ namespace ts {
Diagnostics.Public_static_property_0_of_exported_class_has_or_is_using_name_1_from_private_module_2 :
Diagnostics.Public_static_property_0_of_exported_class_has_or_is_using_private_name_1;
}
else if (node.parent.kind === SyntaxKind.ClassDeclaration) {
else if (node.parent.kind === SyntaxKind.ClassDeclaration || node.kind === SyntaxKind.Parameter) {
return symbolAccessibilityResult.errorModuleName ?
symbolAccessibilityResult.accessibility === SymbolAccessibility.CannotBeNamed ?
Diagnostics.Public_property_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named :
@@ -1501,6 +1503,11 @@ namespace ts {
write("[");
}
else {
if (node.kind === SyntaxKind.Constructor && hasModifier(node, ModifierFlags.Private)) {
write("();");
writeLine();
return;
}
// Construct signature or constructor type write new Signature
if (node.kind === SyntaxKind.ConstructSignature || node.kind === SyntaxKind.ConstructorType) {
write("new ");

View File

@@ -89,7 +89,7 @@ declare class C {
}
declare class D {
x: number;
private constructor(x);
private constructor();
}
declare class E {
x: number;

View File

@@ -135,7 +135,7 @@ declare class BaseB {
}
declare class BaseC {
x: number;
private constructor(x);
private constructor();
createInstance(): void;
static staticInstance(): void;
}

View File

@@ -90,7 +90,7 @@ declare class Baz {
}
declare class Qux {
x: number;
private constructor(x);
private constructor();
}
declare let a: typeof Foo;
declare let b: typeof Baz;

View File

@@ -59,7 +59,7 @@ var D = (function () {
declare class A {
constructor(a: boolean);
protected constructor(a: number);
private constructor(a);
private constructor();
}
declare class B {
protected constructor(a: number);

View File

@@ -0,0 +1,72 @@
//// [declarationEmitClassPrivateConstructor.ts]
interface PrivateInterface {
}
export class ExportedClass1 {
private constructor(data: PrivateInterface) { }
}
export class ExportedClass2 {
private constructor(private data: PrivateInterface) { }
}
export class ExportedClass3 {
private constructor(private data: PrivateInterface, private n: number) { }
}
export class ExportedClass4 {
private constructor(private data: PrivateInterface, public n:number) { }
}
//// [declarationEmitClassPrivateConstructor.js]
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var ExportedClass1 = (function () {
function ExportedClass1(data) {
}
return ExportedClass1;
}());
exports.ExportedClass1 = ExportedClass1;
var ExportedClass2 = (function () {
function ExportedClass2(data) {
this.data = data;
}
return ExportedClass2;
}());
exports.ExportedClass2 = ExportedClass2;
var ExportedClass3 = (function () {
function ExportedClass3(data, n) {
this.data = data;
this.n = n;
}
return ExportedClass3;
}());
exports.ExportedClass3 = ExportedClass3;
var ExportedClass4 = (function () {
function ExportedClass4(data, n) {
this.data = data;
this.n = n;
}
return ExportedClass4;
}());
exports.ExportedClass4 = ExportedClass4;
//// [declarationEmitClassPrivateConstructor.d.ts]
export declare class ExportedClass1 {
private constructor();
}
export declare class ExportedClass2 {
private data;
private constructor();
}
export declare class ExportedClass3 {
private data;
private n;
private constructor();
}
export declare class ExportedClass4 {
private data;
n: number;
private constructor();
}

View File

@@ -0,0 +1,38 @@
=== tests/cases/compiler/declarationEmitClassPrivateConstructor.ts ===
interface PrivateInterface {
>PrivateInterface : Symbol(PrivateInterface, Decl(declarationEmitClassPrivateConstructor.ts, 0, 0))
}
export class ExportedClass1 {
>ExportedClass1 : Symbol(ExportedClass1, Decl(declarationEmitClassPrivateConstructor.ts, 1, 1))
private constructor(data: PrivateInterface) { }
>data : Symbol(data, Decl(declarationEmitClassPrivateConstructor.ts, 4, 24))
>PrivateInterface : Symbol(PrivateInterface, Decl(declarationEmitClassPrivateConstructor.ts, 0, 0))
}
export class ExportedClass2 {
>ExportedClass2 : Symbol(ExportedClass2, Decl(declarationEmitClassPrivateConstructor.ts, 5, 1))
private constructor(private data: PrivateInterface) { }
>data : Symbol(ExportedClass2.data, Decl(declarationEmitClassPrivateConstructor.ts, 8, 24))
>PrivateInterface : Symbol(PrivateInterface, Decl(declarationEmitClassPrivateConstructor.ts, 0, 0))
}
export class ExportedClass3 {
>ExportedClass3 : Symbol(ExportedClass3, Decl(declarationEmitClassPrivateConstructor.ts, 9, 1))
private constructor(private data: PrivateInterface, private n: number) { }
>data : Symbol(ExportedClass3.data, Decl(declarationEmitClassPrivateConstructor.ts, 12, 24))
>PrivateInterface : Symbol(PrivateInterface, Decl(declarationEmitClassPrivateConstructor.ts, 0, 0))
>n : Symbol(ExportedClass3.n, Decl(declarationEmitClassPrivateConstructor.ts, 12, 55))
}
export class ExportedClass4 {
>ExportedClass4 : Symbol(ExportedClass4, Decl(declarationEmitClassPrivateConstructor.ts, 13, 1))
private constructor(private data: PrivateInterface, public n:number) { }
>data : Symbol(ExportedClass4.data, Decl(declarationEmitClassPrivateConstructor.ts, 16, 24))
>PrivateInterface : Symbol(PrivateInterface, Decl(declarationEmitClassPrivateConstructor.ts, 0, 0))
>n : Symbol(ExportedClass4.n, Decl(declarationEmitClassPrivateConstructor.ts, 16, 55))
}

View File

@@ -0,0 +1,38 @@
=== tests/cases/compiler/declarationEmitClassPrivateConstructor.ts ===
interface PrivateInterface {
>PrivateInterface : PrivateInterface
}
export class ExportedClass1 {
>ExportedClass1 : ExportedClass1
private constructor(data: PrivateInterface) { }
>data : PrivateInterface
>PrivateInterface : PrivateInterface
}
export class ExportedClass2 {
>ExportedClass2 : ExportedClass2
private constructor(private data: PrivateInterface) { }
>data : PrivateInterface
>PrivateInterface : PrivateInterface
}
export class ExportedClass3 {
>ExportedClass3 : ExportedClass3
private constructor(private data: PrivateInterface, private n: number) { }
>data : PrivateInterface
>PrivateInterface : PrivateInterface
>n : number
}
export class ExportedClass4 {
>ExportedClass4 : ExportedClass4
private constructor(private data: PrivateInterface, public n:number) { }
>data : PrivateInterface
>PrivateInterface : PrivateInterface
>n : number
}

View File

@@ -0,0 +1,20 @@
tests/cases/compiler/declarationEmitClassPrivateConstructor2.ts(5,38): error TS4031: Public property 'data' of exported class has or is using private name 'PrivateInterface'.
tests/cases/compiler/declarationEmitClassPrivateConstructor2.ts(10,33): error TS4063: Parameter 'data' of constructor from exported class has or is using private name 'PrivateInterface'.
==== tests/cases/compiler/declarationEmitClassPrivateConstructor2.ts (2 errors) ====
interface PrivateInterface {
}
export class ExportedClass1 {
private constructor(public data: PrivateInterface) { }
~~~~~~~~~~~~~~~~
!!! error TS4031: Public property 'data' of exported class has or is using private name 'PrivateInterface'.
}
export class ExportedClass2 {
protected constructor(data: PrivateInterface) { }
~~~~~~~~~~~~~~~~
!!! error TS4063: Parameter 'data' of constructor from exported class has or is using private name 'PrivateInterface'.
}

View File

@@ -0,0 +1,29 @@
//// [declarationEmitClassPrivateConstructor2.ts]
interface PrivateInterface {
}
export class ExportedClass1 {
private constructor(public data: PrivateInterface) { }
}
export class ExportedClass2 {
protected constructor(data: PrivateInterface) { }
}
//// [declarationEmitClassPrivateConstructor2.js]
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var ExportedClass1 = (function () {
function ExportedClass1(data) {
this.data = data;
}
return ExportedClass1;
}());
exports.ExportedClass1 = ExportedClass1;
var ExportedClass2 = (function () {
function ExportedClass2(data) {
}
return ExportedClass2;
}());
exports.ExportedClass2 = ExportedClass2;

View File

@@ -38,7 +38,7 @@ declare class C {
declare var c: any;
declare var r: () => void;
declare class C2 {
private constructor(x);
private constructor();
}
declare var c2: any;
declare var r2: (x: number) => void;

View File

@@ -0,0 +1,22 @@
// @target: es5
// @module: commonjs
// @declaration: true
interface PrivateInterface {
}
export class ExportedClass1 {
private constructor(data: PrivateInterface) { }
}
export class ExportedClass2 {
private constructor(private data: PrivateInterface) { }
}
export class ExportedClass3 {
private constructor(private data: PrivateInterface, private n: number) { }
}
export class ExportedClass4 {
private constructor(private data: PrivateInterface, public n:number) { }
}

View File

@@ -0,0 +1,15 @@
// @target: es5
// @module: commonjs
// @declaration: true
interface PrivateInterface {
}
export class ExportedClass1 {
private constructor(public data: PrivateInterface) { }
}
export class ExportedClass2 {
protected constructor(data: PrivateInterface) { }
}