From ad2634e34309954b80ed6f2ed1d5d8de3460dc5d Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Wed, 11 May 2016 08:29:03 -0700 Subject: [PATCH 1/6] Fix #7590: Allow 'readonly' to be used in constructor parameters --- src/compiler/checker.ts | 9 ++--- src/compiler/declarationEmitter.ts | 2 +- src/compiler/emitter.ts | 2 +- src/compiler/types.ts | 4 ++- src/compiler/utilities.ts | 2 +- .../readonlyInAmbientClass.errors.txt | 9 +++++ .../reference/readonlyInAmbientClass.js | 6 ++++ ...readonlyInConstructorParameters.errors.txt | 25 +++++++++++++ .../readonlyInConstructorParameters.js | 36 +++++++++++++++++++ .../reference/readonlyReadonly.errors.txt | 13 +++++++ tests/baselines/reference/readonlyReadonly.js | 13 +++++++ .../readonlyInAmbientClass.ts | 3 ++ .../readonlyInConstructorParameters.ts | 13 +++++++ .../constructorParameters/readonlyReadonly.ts | 4 +++ 14 files changed, 133 insertions(+), 8 deletions(-) create mode 100644 tests/baselines/reference/readonlyInAmbientClass.errors.txt create mode 100644 tests/baselines/reference/readonlyInAmbientClass.js create mode 100644 tests/baselines/reference/readonlyInConstructorParameters.errors.txt create mode 100644 tests/baselines/reference/readonlyInConstructorParameters.js create mode 100644 tests/baselines/reference/readonlyReadonly.errors.txt create mode 100644 tests/baselines/reference/readonlyReadonly.js create mode 100644 tests/cases/conformance/classes/constructorDeclarations/constructorParameters/readonlyInAmbientClass.ts create mode 100644 tests/cases/conformance/classes/constructorDeclarations/constructorParameters/readonlyInConstructorParameters.ts create mode 100644 tests/cases/conformance/classes/constructorDeclarations/constructorParameters/readonlyReadonly.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ab1433320f5..296d3ead675 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -12658,7 +12658,7 @@ namespace ts { checkVariableLikeDeclaration(node); let func = getContainingFunction(node); - if (node.flags & NodeFlags.AccessibilityModifier) { + if (node.flags & NodeFlags.ConstructorParameterModifier) { func = getContainingFunction(node); if (!(func.kind === SyntaxKind.Constructor && nodeIsPresent(func.body))) { error(node, Diagnostics.A_parameter_property_is_only_allowed_in_a_constructor_implementation); @@ -12994,7 +12994,7 @@ namespace ts { // or the containing class declares instance member variables with initializers. const superCallShouldBeFirst = forEach((node.parent).members, isInstancePropertyWithInitializer) || - forEach(node.parameters, p => p.flags & (NodeFlags.Public | NodeFlags.Private | NodeFlags.Protected)); + forEach(node.parameters, p => p.flags & NodeFlags.ConstructorParameterModifier); // Skip past any prologue directives to find the first statement // to ensure that it was a super call. @@ -17651,7 +17651,8 @@ namespace ts { if (flags & NodeFlags.Readonly) { return grammarErrorOnNode(modifier, Diagnostics._0_modifier_already_seen, "readonly"); } - else if (node.kind !== SyntaxKind.PropertyDeclaration && node.kind !== SyntaxKind.PropertySignature && node.kind !== SyntaxKind.IndexSignature) { + else if (node.kind !== SyntaxKind.PropertyDeclaration && node.kind !== SyntaxKind.PropertySignature && node.kind !== SyntaxKind.IndexSignature && + !(node.kind == SyntaxKind.Parameter && isParameterPropertyDeclaration( node))) { return grammarErrorOnNode(modifier, Diagnostics.readonly_modifier_can_only_appear_on_a_property_declaration_or_index_signature); } flags |= NodeFlags.Readonly; @@ -17759,7 +17760,7 @@ namespace ts { else if ((node.kind === SyntaxKind.ImportDeclaration || node.kind === SyntaxKind.ImportEqualsDeclaration) && flags & NodeFlags.Ambient) { return grammarErrorOnNode(lastDeclare, Diagnostics.A_0_modifier_cannot_be_used_with_an_import_declaration, "declare"); } - else if (node.kind === SyntaxKind.Parameter && (flags & NodeFlags.AccessibilityModifier) && isBindingPattern((node).name)) { + else if (node.kind === SyntaxKind.Parameter && (flags & NodeFlags.ConstructorParameterModifier) && isBindingPattern((node).name)) { return grammarErrorOnNode(node, Diagnostics.A_parameter_property_may_not_be_a_binding_pattern); } if (flags & NodeFlags.Async) { diff --git a/src/compiler/declarationEmitter.ts b/src/compiler/declarationEmitter.ts index aceec933227..90ac0c0719b 100644 --- a/src/compiler/declarationEmitter.ts +++ b/src/compiler/declarationEmitter.ts @@ -1051,7 +1051,7 @@ namespace ts { function emitParameterProperties(constructorDeclaration: ConstructorDeclaration) { if (constructorDeclaration) { forEach(constructorDeclaration.parameters, param => { - if (param.flags & NodeFlags.AccessibilityModifier) { + if (param.flags & NodeFlags.ConstructorParameterModifier) { emitPropertyDeclaration(param); } }); diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index a1f02f520d8..0e14adf07b4 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -4979,7 +4979,7 @@ const _super = (function (geti, seti) { function emitParameterPropertyAssignments(node: ConstructorDeclaration) { forEach(node.parameters, param => { - if (param.flags & NodeFlags.AccessibilityModifier) { + if (param.flags & NodeFlags.ConstructorParameterModifier) { writeLine(); emitStart(param); emitStart(param.name); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index c367bffea3b..0899b01620e 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -407,8 +407,10 @@ namespace ts { HasAggregatedChildData = 1 << 29, // If we've computed data from children and cached it in this node HasJsxSpreadAttribute = 1 << 30, - Modifier = Export | Ambient | Public | Private | Protected | Static | Abstract | Default | Async, + Modifier = Export | Ambient | Public | Private | Protected | Static | Abstract | Default | Async | Readonly, AccessibilityModifier = Public | Private | Protected, + // Accessibility modifiers and 'readonly' can be attached to a parameter in a constructor to make it a property. + ConstructorParameterModifier = AccessibilityModifier | Readonly, BlockScoped = Let | Const, ReachabilityCheckFlags = HasImplicitReturn | HasExplicitReturn, diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 208723159c2..fc5fb8aac0b 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -3021,7 +3021,7 @@ namespace ts { } export function isParameterPropertyDeclaration(node: ParameterDeclaration): boolean { - return node.flags & NodeFlags.AccessibilityModifier && node.parent.kind === SyntaxKind.Constructor && isClassLike(node.parent.parent); + return node.flags & NodeFlags.ConstructorParameterModifier && node.parent.kind === SyntaxKind.Constructor && isClassLike(node.parent.parent); } export function startsWith(str: string, prefix: string): boolean { diff --git a/tests/baselines/reference/readonlyInAmbientClass.errors.txt b/tests/baselines/reference/readonlyInAmbientClass.errors.txt new file mode 100644 index 00000000000..303f04038f3 --- /dev/null +++ b/tests/baselines/reference/readonlyInAmbientClass.errors.txt @@ -0,0 +1,9 @@ +tests/cases/conformance/classes/constructorDeclarations/constructorParameters/readonlyInAmbientClass.ts(2,14): error TS2369: A parameter property is only allowed in a constructor implementation. + + +==== tests/cases/conformance/classes/constructorDeclarations/constructorParameters/readonlyInAmbientClass.ts (1 errors) ==== + declare class C{ + constructor(readonly x: number); + ~~~~~~~~~~~~~~~~~~ +!!! error TS2369: A parameter property is only allowed in a constructor implementation. + } \ No newline at end of file diff --git a/tests/baselines/reference/readonlyInAmbientClass.js b/tests/baselines/reference/readonlyInAmbientClass.js new file mode 100644 index 00000000000..9be7c1702c9 --- /dev/null +++ b/tests/baselines/reference/readonlyInAmbientClass.js @@ -0,0 +1,6 @@ +//// [readonlyInAmbientClass.ts] +declare class C{ + constructor(readonly x: number); +} + +//// [readonlyInAmbientClass.js] diff --git a/tests/baselines/reference/readonlyInConstructorParameters.errors.txt b/tests/baselines/reference/readonlyInConstructorParameters.errors.txt new file mode 100644 index 00000000000..6e4b549ce74 --- /dev/null +++ b/tests/baselines/reference/readonlyInConstructorParameters.errors.txt @@ -0,0 +1,25 @@ +tests/cases/conformance/classes/constructorDeclarations/constructorParameters/readonlyInConstructorParameters.ts(4,1): error TS2450: Left-hand side of assignment expression cannot be a constant or a read-only property. +tests/cases/conformance/classes/constructorDeclarations/constructorParameters/readonlyInConstructorParameters.ts(7,26): error TS1029: 'public' modifier must precede 'readonly' modifier. +tests/cases/conformance/classes/constructorDeclarations/constructorParameters/readonlyInConstructorParameters.ts(13,10): error TS2341: Property 'x' is private and only accessible within class 'F'. + + +==== tests/cases/conformance/classes/constructorDeclarations/constructorParameters/readonlyInConstructorParameters.ts (3 errors) ==== + class C { + constructor(readonly x: number) {} + } + new C(1).x = 2; + ~~~~~~~~~~ +!!! error TS2450: Left-hand side of assignment expression cannot be a constant or a read-only property. + + class E { + constructor(readonly public x: number) {} + ~~~~~~ +!!! error TS1029: 'public' modifier must precede 'readonly' modifier. + } + + class F { + constructor(private readonly x: number) {} + } + new F(1).x; + ~ +!!! error TS2341: Property 'x' is private and only accessible within class 'F'. \ No newline at end of file diff --git a/tests/baselines/reference/readonlyInConstructorParameters.js b/tests/baselines/reference/readonlyInConstructorParameters.js new file mode 100644 index 00000000000..41e9c57cd72 --- /dev/null +++ b/tests/baselines/reference/readonlyInConstructorParameters.js @@ -0,0 +1,36 @@ +//// [readonlyInConstructorParameters.ts] +class C { + constructor(readonly x: number) {} +} +new C(1).x = 2; + +class E { + constructor(readonly public x: number) {} +} + +class F { + constructor(private readonly x: number) {} +} +new F(1).x; + +//// [readonlyInConstructorParameters.js] +var C = (function () { + function C(x) { + this.x = x; + } + return C; +}()); +new C(1).x = 2; +var E = (function () { + function E(x) { + this.x = x; + } + return E; +}()); +var F = (function () { + function F(x) { + this.x = x; + } + return F; +}()); +new F(1).x; diff --git a/tests/baselines/reference/readonlyReadonly.errors.txt b/tests/baselines/reference/readonlyReadonly.errors.txt new file mode 100644 index 00000000000..b1ea129303a --- /dev/null +++ b/tests/baselines/reference/readonlyReadonly.errors.txt @@ -0,0 +1,13 @@ +tests/cases/conformance/classes/constructorDeclarations/constructorParameters/readonlyReadonly.ts(2,14): error TS1030: 'readonly' modifier already seen. +tests/cases/conformance/classes/constructorDeclarations/constructorParameters/readonlyReadonly.ts(3,26): error TS1030: 'readonly' modifier already seen. + + +==== tests/cases/conformance/classes/constructorDeclarations/constructorParameters/readonlyReadonly.ts (2 errors) ==== + class C { + readonly readonly x: number; + ~~~~~~~~ +!!! error TS1030: 'readonly' modifier already seen. + constructor(readonly readonly y: number) {} + ~~~~~~~~ +!!! error TS1030: 'readonly' modifier already seen. + } \ No newline at end of file diff --git a/tests/baselines/reference/readonlyReadonly.js b/tests/baselines/reference/readonlyReadonly.js new file mode 100644 index 00000000000..0b804e147b6 --- /dev/null +++ b/tests/baselines/reference/readonlyReadonly.js @@ -0,0 +1,13 @@ +//// [readonlyReadonly.ts] +class C { + readonly readonly x: number; + constructor(readonly readonly y: number) {} +} + +//// [readonlyReadonly.js] +var C = (function () { + function C(y) { + this.y = y; + } + return C; +}()); diff --git a/tests/cases/conformance/classes/constructorDeclarations/constructorParameters/readonlyInAmbientClass.ts b/tests/cases/conformance/classes/constructorDeclarations/constructorParameters/readonlyInAmbientClass.ts new file mode 100644 index 00000000000..ca710532dd3 --- /dev/null +++ b/tests/cases/conformance/classes/constructorDeclarations/constructorParameters/readonlyInAmbientClass.ts @@ -0,0 +1,3 @@ +declare class C{ + constructor(readonly x: number); +} \ No newline at end of file diff --git a/tests/cases/conformance/classes/constructorDeclarations/constructorParameters/readonlyInConstructorParameters.ts b/tests/cases/conformance/classes/constructorDeclarations/constructorParameters/readonlyInConstructorParameters.ts new file mode 100644 index 00000000000..dbcdff7a2d9 --- /dev/null +++ b/tests/cases/conformance/classes/constructorDeclarations/constructorParameters/readonlyInConstructorParameters.ts @@ -0,0 +1,13 @@ +class C { + constructor(readonly x: number) {} +} +new C(1).x = 2; + +class E { + constructor(readonly public x: number) {} +} + +class F { + constructor(private readonly x: number) {} +} +new F(1).x; \ No newline at end of file diff --git a/tests/cases/conformance/classes/constructorDeclarations/constructorParameters/readonlyReadonly.ts b/tests/cases/conformance/classes/constructorDeclarations/constructorParameters/readonlyReadonly.ts new file mode 100644 index 00000000000..8fb611a0181 --- /dev/null +++ b/tests/cases/conformance/classes/constructorDeclarations/constructorParameters/readonlyReadonly.ts @@ -0,0 +1,4 @@ +class C { + readonly readonly x: number; + constructor(readonly readonly y: number) {} +} \ No newline at end of file From a9742c58610db0785b051f7da3c668ce5ade72a6 Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Wed, 11 May 2016 09:48:37 -0700 Subject: [PATCH 2/6] Change name from ConstructorParameterModifier to ParameterPropertyModifier --- src/compiler/checker.ts | 6 +++--- src/compiler/declarationEmitter.ts | 2 +- src/compiler/emitter.ts | 2 +- src/compiler/types.ts | 2 +- src/compiler/utilities.ts | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 296d3ead675..3350a4f08fb 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -12658,7 +12658,7 @@ namespace ts { checkVariableLikeDeclaration(node); let func = getContainingFunction(node); - if (node.flags & NodeFlags.ConstructorParameterModifier) { + if (node.flags & NodeFlags.ParameterPropertyModifier) { func = getContainingFunction(node); if (!(func.kind === SyntaxKind.Constructor && nodeIsPresent(func.body))) { error(node, Diagnostics.A_parameter_property_is_only_allowed_in_a_constructor_implementation); @@ -12994,7 +12994,7 @@ namespace ts { // or the containing class declares instance member variables with initializers. const superCallShouldBeFirst = forEach((node.parent).members, isInstancePropertyWithInitializer) || - forEach(node.parameters, p => p.flags & NodeFlags.ConstructorParameterModifier); + forEach(node.parameters, p => p.flags & NodeFlags.ParameterPropertyModifier); // Skip past any prologue directives to find the first statement // to ensure that it was a super call. @@ -17760,7 +17760,7 @@ namespace ts { else if ((node.kind === SyntaxKind.ImportDeclaration || node.kind === SyntaxKind.ImportEqualsDeclaration) && flags & NodeFlags.Ambient) { return grammarErrorOnNode(lastDeclare, Diagnostics.A_0_modifier_cannot_be_used_with_an_import_declaration, "declare"); } - else if (node.kind === SyntaxKind.Parameter && (flags & NodeFlags.ConstructorParameterModifier) && isBindingPattern((node).name)) { + else if (node.kind === SyntaxKind.Parameter && (flags & NodeFlags.ParameterPropertyModifier) && isBindingPattern((node).name)) { return grammarErrorOnNode(node, Diagnostics.A_parameter_property_may_not_be_a_binding_pattern); } if (flags & NodeFlags.Async) { diff --git a/src/compiler/declarationEmitter.ts b/src/compiler/declarationEmitter.ts index 90ac0c0719b..c24135ba52e 100644 --- a/src/compiler/declarationEmitter.ts +++ b/src/compiler/declarationEmitter.ts @@ -1051,7 +1051,7 @@ namespace ts { function emitParameterProperties(constructorDeclaration: ConstructorDeclaration) { if (constructorDeclaration) { forEach(constructorDeclaration.parameters, param => { - if (param.flags & NodeFlags.ConstructorParameterModifier) { + if (param.flags & NodeFlags.ParameterPropertyModifier) { emitPropertyDeclaration(param); } }); diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 0e14adf07b4..39fb7bff1d9 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -4979,7 +4979,7 @@ const _super = (function (geti, seti) { function emitParameterPropertyAssignments(node: ConstructorDeclaration) { forEach(node.parameters, param => { - if (param.flags & NodeFlags.ConstructorParameterModifier) { + if (param.flags & NodeFlags.ParameterPropertyModifier) { writeLine(); emitStart(param); emitStart(param.name); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 0899b01620e..6f1df6f14fd 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -410,7 +410,7 @@ namespace ts { Modifier = Export | Ambient | Public | Private | Protected | Static | Abstract | Default | Async | Readonly, AccessibilityModifier = Public | Private | Protected, // Accessibility modifiers and 'readonly' can be attached to a parameter in a constructor to make it a property. - ConstructorParameterModifier = AccessibilityModifier | Readonly, + ParameterPropertyModifier = AccessibilityModifier | Readonly, BlockScoped = Let | Const, ReachabilityCheckFlags = HasImplicitReturn | HasExplicitReturn, diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index fc5fb8aac0b..0f875cc87ca 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -3021,7 +3021,7 @@ namespace ts { } export function isParameterPropertyDeclaration(node: ParameterDeclaration): boolean { - return node.flags & NodeFlags.ConstructorParameterModifier && node.parent.kind === SyntaxKind.Constructor && isClassLike(node.parent.parent); + return node.flags & NodeFlags.ParameterPropertyModifier && node.parent.kind === SyntaxKind.Constructor && isClassLike(node.parent.parent); } export function startsWith(str: string, prefix: string): boolean { From 02f2ed798f3e5b5e72ab4a5fd8df83c01cdf8f47 Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Wed, 11 May 2016 13:14:22 -0700 Subject: [PATCH 3/6] Add declaration emit tests for readonly parameter property --- .../reference/declarationEmit_readonly.js | 20 +++++++++++++++++++ .../declarationEmit_readonly.symbols | 8 ++++++++ .../reference/declarationEmit_readonly.types | 8 ++++++++ .../declarationEmit_readonly.ts | 5 +++++ 4 files changed, 41 insertions(+) create mode 100644 tests/baselines/reference/declarationEmit_readonly.js create mode 100644 tests/baselines/reference/declarationEmit_readonly.symbols create mode 100644 tests/baselines/reference/declarationEmit_readonly.types create mode 100644 tests/cases/conformance/classes/constructorDeclarations/constructorParameters/declarationEmit_readonly.ts diff --git a/tests/baselines/reference/declarationEmit_readonly.js b/tests/baselines/reference/declarationEmit_readonly.js new file mode 100644 index 00000000000..4925e5dafae --- /dev/null +++ b/tests/baselines/reference/declarationEmit_readonly.js @@ -0,0 +1,20 @@ +//// [declarationEmit_readonly.ts] + +class C { + constructor(readonly x: number) {} +} + +//// [declarationEmit_readonly.js] +var C = (function () { + function C(x) { + this.x = x; + } + return C; +}()); + + +//// [declarationEmit_readonly.d.ts] +declare class C { + readonly x: number; + constructor(x: number); +} diff --git a/tests/baselines/reference/declarationEmit_readonly.symbols b/tests/baselines/reference/declarationEmit_readonly.symbols new file mode 100644 index 00000000000..eadb7dc3ddf --- /dev/null +++ b/tests/baselines/reference/declarationEmit_readonly.symbols @@ -0,0 +1,8 @@ +=== tests/cases/conformance/classes/constructorDeclarations/constructorParameters/declarationEmit_readonly.ts === + +class C { +>C : Symbol(C, Decl(declarationEmit_readonly.ts, 0, 0)) + + constructor(readonly x: number) {} +>x : Symbol(C.x, Decl(declarationEmit_readonly.ts, 2, 16)) +} diff --git a/tests/baselines/reference/declarationEmit_readonly.types b/tests/baselines/reference/declarationEmit_readonly.types new file mode 100644 index 00000000000..3036c234ae5 --- /dev/null +++ b/tests/baselines/reference/declarationEmit_readonly.types @@ -0,0 +1,8 @@ +=== tests/cases/conformance/classes/constructorDeclarations/constructorParameters/declarationEmit_readonly.ts === + +class C { +>C : C + + constructor(readonly x: number) {} +>x : number +} diff --git a/tests/cases/conformance/classes/constructorDeclarations/constructorParameters/declarationEmit_readonly.ts b/tests/cases/conformance/classes/constructorDeclarations/constructorParameters/declarationEmit_readonly.ts new file mode 100644 index 00000000000..76b41eabba4 --- /dev/null +++ b/tests/cases/conformance/classes/constructorDeclarations/constructorParameters/declarationEmit_readonly.ts @@ -0,0 +1,5 @@ +// @declaration: true + +class C { + constructor(readonly x: number) {} +} \ No newline at end of file From 40afe4a4dd5b398c5882069488e3bab4b7976f27 Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Wed, 11 May 2016 13:54:50 -0700 Subject: [PATCH 4/6] Don't report error twice for readonly in method --- src/compiler/checker.ts | 4 ++-- tests/baselines/reference/readonlyInAmbientClass.errors.txt | 6 +++++- tests/baselines/reference/readonlyInAmbientClass.js | 1 + .../constructorParameters/readonlyInAmbientClass.ts | 1 + 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 3350a4f08fb..e516a6319ec 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -17651,8 +17651,8 @@ namespace ts { if (flags & NodeFlags.Readonly) { return grammarErrorOnNode(modifier, Diagnostics._0_modifier_already_seen, "readonly"); } - else if (node.kind !== SyntaxKind.PropertyDeclaration && node.kind !== SyntaxKind.PropertySignature && node.kind !== SyntaxKind.IndexSignature && - !(node.kind == SyntaxKind.Parameter && isParameterPropertyDeclaration( node))) { + else if (node.kind !== SyntaxKind.PropertyDeclaration && node.kind !== SyntaxKind.PropertySignature && node.kind !== SyntaxKind.IndexSignature && node.kind !== SyntaxKind.Parameter) { + // If node.kind === SyntaxKind.Parameter, checkParameter report an error if it's not a parameter property. return grammarErrorOnNode(modifier, Diagnostics.readonly_modifier_can_only_appear_on_a_property_declaration_or_index_signature); } flags |= NodeFlags.Readonly; diff --git a/tests/baselines/reference/readonlyInAmbientClass.errors.txt b/tests/baselines/reference/readonlyInAmbientClass.errors.txt index 303f04038f3..844e8b58ef8 100644 --- a/tests/baselines/reference/readonlyInAmbientClass.errors.txt +++ b/tests/baselines/reference/readonlyInAmbientClass.errors.txt @@ -1,9 +1,13 @@ tests/cases/conformance/classes/constructorDeclarations/constructorParameters/readonlyInAmbientClass.ts(2,14): error TS2369: A parameter property is only allowed in a constructor implementation. +tests/cases/conformance/classes/constructorDeclarations/constructorParameters/readonlyInAmbientClass.ts(3,9): error TS2369: A parameter property is only allowed in a constructor implementation. -==== tests/cases/conformance/classes/constructorDeclarations/constructorParameters/readonlyInAmbientClass.ts (1 errors) ==== +==== tests/cases/conformance/classes/constructorDeclarations/constructorParameters/readonlyInAmbientClass.ts (2 errors) ==== declare class C{ constructor(readonly x: number); ~~~~~~~~~~~~~~~~~~ +!!! error TS2369: A parameter property is only allowed in a constructor implementation. + method(readonly x: number); + ~~~~~~~~~~~~~~~~~~ !!! error TS2369: A parameter property is only allowed in a constructor implementation. } \ No newline at end of file diff --git a/tests/baselines/reference/readonlyInAmbientClass.js b/tests/baselines/reference/readonlyInAmbientClass.js index 9be7c1702c9..0e199b5ca4f 100644 --- a/tests/baselines/reference/readonlyInAmbientClass.js +++ b/tests/baselines/reference/readonlyInAmbientClass.js @@ -1,6 +1,7 @@ //// [readonlyInAmbientClass.ts] declare class C{ constructor(readonly x: number); + method(readonly x: number); } //// [readonlyInAmbientClass.js] diff --git a/tests/cases/conformance/classes/constructorDeclarations/constructorParameters/readonlyInAmbientClass.ts b/tests/cases/conformance/classes/constructorDeclarations/constructorParameters/readonlyInAmbientClass.ts index ca710532dd3..c84594eb4f0 100644 --- a/tests/cases/conformance/classes/constructorDeclarations/constructorParameters/readonlyInAmbientClass.ts +++ b/tests/cases/conformance/classes/constructorDeclarations/constructorParameters/readonlyInAmbientClass.ts @@ -1,3 +1,4 @@ declare class C{ constructor(readonly x: number); + method(readonly x: number); } \ No newline at end of file From ce596732ab11f98546848847e489619e9d6e2ef4 Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Wed, 11 May 2016 14:14:52 -0700 Subject: [PATCH 5/6] Remove duplicate check for misplaced parameter properties (taken care of by checkParameter) --- src/compiler/checker.ts | 3 --- ...rParameterAccessibilityModifier.errors.txt | 8 +------ ...rserMemberAccessorDeclaration15.errors.txt | 5 +--- ...readonlyInNonPropertyParameters.errors.txt | 19 +++++++++++++++ .../readonlyInNonPropertyParameters.js | 23 +++++++++++++++++++ .../readonlyInNonPropertyParameters.ts | 8 +++++++ 6 files changed, 52 insertions(+), 14 deletions(-) create mode 100644 tests/baselines/reference/readonlyInNonPropertyParameters.errors.txt create mode 100644 tests/baselines/reference/readonlyInNonPropertyParameters.js create mode 100644 tests/cases/compiler/readonlyInNonPropertyParameters.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index e516a6319ec..acab10a9ac3 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -18225,9 +18225,6 @@ namespace ts { if (parameter.dotDotDotToken) { return grammarErrorOnNode(parameter.dotDotDotToken, Diagnostics.A_set_accessor_cannot_have_rest_parameter); } - else if (parameter.flags & NodeFlags.Modifier) { - return grammarErrorOnNode(accessor.name, Diagnostics.A_parameter_property_is_only_allowed_in_a_constructor_implementation); - } else if (parameter.questionToken) { return grammarErrorOnNode(parameter.questionToken, Diagnostics.A_set_accessor_cannot_have_an_optional_parameter); } diff --git a/tests/baselines/reference/accessorParameterAccessibilityModifier.errors.txt b/tests/baselines/reference/accessorParameterAccessibilityModifier.errors.txt index fad1d8ff10a..3036e734105 100644 --- a/tests/baselines/reference/accessorParameterAccessibilityModifier.errors.txt +++ b/tests/baselines/reference/accessorParameterAccessibilityModifier.errors.txt @@ -1,20 +1,14 @@ -tests/cases/compiler/accessorParameterAccessibilityModifier.ts(3,9): error TS2369: A parameter property is only allowed in a constructor implementation. tests/cases/compiler/accessorParameterAccessibilityModifier.ts(3,11): error TS2369: A parameter property is only allowed in a constructor implementation. -tests/cases/compiler/accessorParameterAccessibilityModifier.ts(4,16): error TS2369: A parameter property is only allowed in a constructor implementation. tests/cases/compiler/accessorParameterAccessibilityModifier.ts(4,18): error TS2369: A parameter property is only allowed in a constructor implementation. -==== tests/cases/compiler/accessorParameterAccessibilityModifier.ts (4 errors) ==== +==== tests/cases/compiler/accessorParameterAccessibilityModifier.ts (2 errors) ==== class C { set X(public v) { } - ~ -!!! error TS2369: A parameter property is only allowed in a constructor implementation. ~~~~~~~~ !!! error TS2369: A parameter property is only allowed in a constructor implementation. static set X(public v2) { } - ~ -!!! error TS2369: A parameter property is only allowed in a constructor implementation. ~~~~~~~~~ !!! error TS2369: A parameter property is only allowed in a constructor implementation. } \ No newline at end of file diff --git a/tests/baselines/reference/parserMemberAccessorDeclaration15.errors.txt b/tests/baselines/reference/parserMemberAccessorDeclaration15.errors.txt index f76264f6090..cba1e1fee92 100644 --- a/tests/baselines/reference/parserMemberAccessorDeclaration15.errors.txt +++ b/tests/baselines/reference/parserMemberAccessorDeclaration15.errors.txt @@ -1,12 +1,9 @@ -tests/cases/conformance/parser/ecmascript5/MemberAccessorDeclarations/parserMemberAccessorDeclaration15.ts(2,8): error TS2369: A parameter property is only allowed in a constructor implementation. tests/cases/conformance/parser/ecmascript5/MemberAccessorDeclarations/parserMemberAccessorDeclaration15.ts(2,12): error TS2369: A parameter property is only allowed in a constructor implementation. -==== tests/cases/conformance/parser/ecmascript5/MemberAccessorDeclarations/parserMemberAccessorDeclaration15.ts (2 errors) ==== +==== tests/cases/conformance/parser/ecmascript5/MemberAccessorDeclarations/parserMemberAccessorDeclaration15.ts (1 errors) ==== class C { set Foo(public a: number) { } - ~~~ -!!! error TS2369: A parameter property is only allowed in a constructor implementation. ~~~~~~~~~~~~~~~~ !!! error TS2369: A parameter property is only allowed in a constructor implementation. } \ No newline at end of file diff --git a/tests/baselines/reference/readonlyInNonPropertyParameters.errors.txt b/tests/baselines/reference/readonlyInNonPropertyParameters.errors.txt new file mode 100644 index 00000000000..696404c6d98 --- /dev/null +++ b/tests/baselines/reference/readonlyInNonPropertyParameters.errors.txt @@ -0,0 +1,19 @@ +tests/cases/compiler/readonlyInNonPropertyParameters.ts(4,9): error TS2369: A parameter property is only allowed in a constructor implementation. +tests/cases/compiler/readonlyInNonPropertyParameters.ts(5,8): error TS2369: A parameter property is only allowed in a constructor implementation. +tests/cases/compiler/readonlyInNonPropertyParameters.ts(7,2): error TS2369: A parameter property is only allowed in a constructor implementation. + + +==== tests/cases/compiler/readonlyInNonPropertyParameters.ts (3 errors) ==== + + // `readonly` won't work outside of property parameters + class X { + method(readonly x: number) {} + ~~~~~~~~~~~~~~~~~~ +!!! error TS2369: A parameter property is only allowed in a constructor implementation. + set x(readonly value: number) {} + ~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2369: A parameter property is only allowed in a constructor implementation. + } + (readonly x) => 0; + ~~~~~~~~~~ +!!! error TS2369: A parameter property is only allowed in a constructor implementation. \ No newline at end of file diff --git a/tests/baselines/reference/readonlyInNonPropertyParameters.js b/tests/baselines/reference/readonlyInNonPropertyParameters.js new file mode 100644 index 00000000000..484a726dc4d --- /dev/null +++ b/tests/baselines/reference/readonlyInNonPropertyParameters.js @@ -0,0 +1,23 @@ +//// [readonlyInNonPropertyParameters.ts] + +// `readonly` won't work outside of property parameters +class X { + method(readonly x: number) {} + set x(readonly value: number) {} +} +(readonly x) => 0; + +//// [readonlyInNonPropertyParameters.js] +// `readonly` won't work outside of property parameters +var X = (function () { + function X() { + } + X.prototype.method = function (x) { }; + Object.defineProperty(X.prototype, "x", { + set: function (value) { }, + enumerable: true, + configurable: true + }); + return X; +}()); +(function (x) { return 0; }); diff --git a/tests/cases/compiler/readonlyInNonPropertyParameters.ts b/tests/cases/compiler/readonlyInNonPropertyParameters.ts new file mode 100644 index 00000000000..7373d046e38 --- /dev/null +++ b/tests/cases/compiler/readonlyInNonPropertyParameters.ts @@ -0,0 +1,8 @@ +//@target: ES5 + +// `readonly` won't work outside of property parameters +class X { + method(readonly x: number) {} + set x(readonly value: number) {} +} +(readonly x) => 0; \ No newline at end of file From 22ee90a744d123c5123ac198e4255f94a3ae5720 Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Wed, 11 May 2016 14:32:59 -0700 Subject: [PATCH 6/6] Add test for lambda parameter named 'readonly' --- .../reference/readonlyInNonPropertyParameters.errors.txt | 4 +++- .../baselines/reference/readonlyInNonPropertyParameters.js | 6 +++++- tests/cases/compiler/readonlyInNonPropertyParameters.ts | 4 +++- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/tests/baselines/reference/readonlyInNonPropertyParameters.errors.txt b/tests/baselines/reference/readonlyInNonPropertyParameters.errors.txt index 696404c6d98..9e759cb8343 100644 --- a/tests/baselines/reference/readonlyInNonPropertyParameters.errors.txt +++ b/tests/baselines/reference/readonlyInNonPropertyParameters.errors.txt @@ -16,4 +16,6 @@ tests/cases/compiler/readonlyInNonPropertyParameters.ts(7,2): error TS2369: A pa } (readonly x) => 0; ~~~~~~~~~~ -!!! error TS2369: A parameter property is only allowed in a constructor implementation. \ No newline at end of file +!!! error TS2369: A parameter property is only allowed in a constructor implementation. + // OK to use `readonly` as a name + (readonly) => 0; \ No newline at end of file diff --git a/tests/baselines/reference/readonlyInNonPropertyParameters.js b/tests/baselines/reference/readonlyInNonPropertyParameters.js index 484a726dc4d..db58f73d2ff 100644 --- a/tests/baselines/reference/readonlyInNonPropertyParameters.js +++ b/tests/baselines/reference/readonlyInNonPropertyParameters.js @@ -5,7 +5,9 @@ class X { method(readonly x: number) {} set x(readonly value: number) {} } -(readonly x) => 0; +(readonly x) => 0; +// OK to use `readonly` as a name +(readonly) => 0; //// [readonlyInNonPropertyParameters.js] // `readonly` won't work outside of property parameters @@ -21,3 +23,5 @@ var X = (function () { return X; }()); (function (x) { return 0; }); +// OK to use `readonly` as a name +(function (readonly) { return 0; }); diff --git a/tests/cases/compiler/readonlyInNonPropertyParameters.ts b/tests/cases/compiler/readonlyInNonPropertyParameters.ts index 7373d046e38..e3334e39719 100644 --- a/tests/cases/compiler/readonlyInNonPropertyParameters.ts +++ b/tests/cases/compiler/readonlyInNonPropertyParameters.ts @@ -5,4 +5,6 @@ class X { method(readonly x: number) {} set x(readonly value: number) {} } -(readonly x) => 0; \ No newline at end of file +(readonly x) => 0; +// OK to use `readonly` as a name +(readonly) => 0; \ No newline at end of file