Skip to content

Commit fc52da3

Browse files
committed
feat(5326): allow destructuring with parameter properties
1 parent f58a662 commit fc52da3

File tree

39 files changed

+369
-515
lines changed

39 files changed

+369
-515
lines changed

src/compiler/binder.ts

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3328,11 +3328,29 @@ namespace ts {
33283328
declareSymbolAndAddToSymbolTable(node, SymbolFlags.FunctionScopedVariable, SymbolFlags.ParameterExcludes);
33293329
}
33303330

3331-
// If this is a property-parameter, then also declare the property symbol into the
3332-
// containing class.
3331+
// If this is a property-parameter, then also declare the property symbol into the containing class.
33333332
if (isParameterPropertyDeclaration(node, node.parent)) {
3334-
const classDeclaration = node.parent.parent;
3335-
declareSymbol(classDeclaration.symbol.members!, classDeclaration.symbol, node, SymbolFlags.Property | (node.questionToken ? SymbolFlags.Optional : SymbolFlags.None), SymbolFlags.PropertyExcludes);
3333+
const symbol = node.parent.parent.symbol;
3334+
const members = symbol.members!;
3335+
3336+
if (isBindingPattern(node.name)) {
3337+
bindParameterPropertyFromBindingPattern(node.name, members, symbol);
3338+
}
3339+
else {
3340+
declareSymbol(members, symbol, node, SymbolFlags.Property | (node.questionToken ? SymbolFlags.Optional : SymbolFlags.None), SymbolFlags.PropertyExcludes);
3341+
}
3342+
}
3343+
}
3344+
3345+
function bindParameterPropertyFromBindingPattern(node: ObjectBindingPattern | ArrayBindingPattern, symbolTable: SymbolTable, parent: Symbol | undefined) {
3346+
for (const element of node.elements) {
3347+
if (isOmittedExpression(element)) continue;
3348+
if (isObjectBindingPattern(element.name) || isArrayBindingPattern(element.name)) {
3349+
bindParameterPropertyFromBindingPattern(element.name, symbolTable, parent);
3350+
}
3351+
else {
3352+
declareSymbol(symbolTable, parent, element, SymbolFlags.Property, SymbolFlags.PropertyExcludes);
3353+
}
33363354
}
33373355
}
33383356

src/compiler/checker.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41246,9 +41246,6 @@ namespace ts {
4124641246
else if ((node.kind === SyntaxKind.ImportDeclaration || node.kind === SyntaxKind.ImportEqualsDeclaration) && flags & ModifierFlags.Ambient) {
4124741247
return grammarErrorOnNode(lastDeclare!, Diagnostics.A_0_modifier_cannot_be_used_with_an_import_declaration, "declare");
4124841248
}
41249-
else if (node.kind === SyntaxKind.Parameter && (flags & ModifierFlags.ParameterPropertyModifier) && isBindingPattern((node as ParameterDeclaration).name)) {
41250-
return grammarErrorOnNode(node, Diagnostics.A_parameter_property_may_not_be_declared_using_a_binding_pattern);
41251-
}
4125241249
else if (node.kind === SyntaxKind.Parameter && (flags & ModifierFlags.ParameterPropertyModifier) && (node as ParameterDeclaration).dotDotDotToken) {
4125341250
return grammarErrorOnNode(node, Diagnostics.A_parameter_property_cannot_be_declared_using_a_rest_parameter);
4125441251
}

src/compiler/diagnosticMessages.json

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -583,10 +583,6 @@
583583
"category": "Error",
584584
"code": 1186
585585
},
586-
"A parameter property may not be declared using a binding pattern.": {
587-
"category": "Error",
588-
"code": 1187
589-
},
590586
"Only a single variable declaration is allowed in a 'for...of' statement.": {
591587
"category": "Error",
592588
"code": 1188

src/compiler/transformers/ts.ts

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1962,8 +1962,9 @@ namespace ts {
19621962
// this.x = x;
19631963
// this.y = y;
19641964
// }
1965-
//
1966-
addRange(statements, map(parametersWithPropertyAssignments, transformParameterWithPropertyAssignment));
1965+
1966+
addRange(statements, flatMap(parametersWithPropertyAssignments, p =>
1967+
isObjectBindingPattern(p.name) || isArrayBindingPattern(p.name) ? transformBindingPatternWithPropertyAssignment(p.name) : transformParameterNameWithPropertyAssignment(p.name)));
19671968

19681969
// Add the existing statements, skipping the initial super call.
19691970
addRange(statements, visitNodes(body.statements, visitor, isStatement, indexOfFirstStatement));
@@ -1976,23 +1977,19 @@ namespace ts {
19761977
return block;
19771978
}
19781979

1979-
/**
1980-
* Transforms a parameter into a property assignment statement.
1981-
*
1982-
* @param node The parameter declaration.
1983-
*/
1984-
function transformParameterWithPropertyAssignment(node: ParameterPropertyDeclaration) {
1985-
const name = node.name;
1986-
if (!isIdentifier(name)) {
1987-
return undefined;
1988-
}
1980+
function transformBindingPatternWithPropertyAssignment(node: ObjectBindingPattern | ArrayBindingPattern): readonly ExpressionStatement[] {
1981+
return flatMap(node.elements, n => isOmittedExpression(n) ? undefined :
1982+
isObjectBindingPattern(n.name) || isArrayBindingPattern(n.name) ? transformBindingPatternWithPropertyAssignment(n.name) :
1983+
transformParameterNameWithPropertyAssignment(n.name));
1984+
}
19891985

1986+
function transformParameterNameWithPropertyAssignment(node: Identifier) {
19901987
// TODO(rbuckton): Does this need to be parented?
1991-
const propertyName = setParent(setTextRange(factory.cloneNode(name), name), name.parent);
1988+
const propertyName = setParent(setTextRange(factory.cloneNode(node), node), node.parent);
19921989
setEmitFlags(propertyName, EmitFlags.NoComments | EmitFlags.NoSourceMap);
19931990

19941991
// TODO(rbuckton): Does this need to be parented?
1995-
const localName = setParent(setTextRange(factory.cloneNode(name), name), name.parent);
1992+
const localName = setParent(setTextRange(factory.cloneNode(node), node), node.parent);
19961993
setEmitFlags(localName, EmitFlags.NoComments);
19971994

19981995
return startOnNewLine(
@@ -2006,12 +2003,12 @@ namespace ts {
20062003
factory.createThis(),
20072004
propertyName
20082005
),
2009-
node.name
2006+
node
20102007
),
20112008
localName
20122009
)
20132010
),
2014-
node
2011+
node.parent
20152012
),
20162013
moveRangePos(node, -1)
20172014
)

tests/baselines/reference/declarationEmitDestructuringParameterProperties.errors.txt

Lines changed: 0 additions & 28 deletions
This file was deleted.

tests/baselines/reference/declarationEmitDestructuringParameterProperties.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,18 +20,27 @@ class C3 {
2020
var C1 = /** @class */ (function () {
2121
function C1(_a) {
2222
var x = _a[0], y = _a[1], z = _a[2];
23+
this.x = x;
24+
this.y = y;
25+
this.z = z;
2326
}
2427
return C1;
2528
}());
2629
var C2 = /** @class */ (function () {
2730
function C2(_a) {
2831
var x = _a[0], y = _a[1], z = _a[2];
32+
this.x = x;
33+
this.y = y;
34+
this.z = z;
2935
}
3036
return C2;
3137
}());
3238
var C3 = /** @class */ (function () {
3339
function C3(_a) {
3440
var x = _a.x, y = _a.y, z = _a.z;
41+
this.x = x;
42+
this.y = y;
43+
this.z = z;
3544
}
3645
return C3;
3746
}());

tests/baselines/reference/declarationEmitPrivatePromiseLikeInterface.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,10 @@ exports.Api = void 0;
5252
var Api = /** @class */ (function () {
5353
function Api(http) {
5454
var _this = this;
55-
this.http = http;
5655
this.abc1 = function () { return _this.http.request(); };
5756
this.abc2 = function () { return _this.http.request(); };
5857
this.abc3 = function () { return _this.http.request(); };
58+
this.http = http;
5959
}
6060
return Api;
6161
}());

tests/baselines/reference/destructuringParameterProperties1.errors.txt

Lines changed: 0 additions & 71 deletions
This file was deleted.

tests/baselines/reference/destructuringParameterProperties1.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,18 +33,27 @@ var [c3_x, c3_y, c3_z] = [c3.x, c3.y, c3.z];
3333
var C1 = /** @class */ (function () {
3434
function C1(_a) {
3535
var x = _a[0], y = _a[1], z = _a[2];
36+
this.x = x;
37+
this.y = y;
38+
this.z = z;
3639
}
3740
return C1;
3841
}());
3942
var C2 = /** @class */ (function () {
4043
function C2(_a) {
4144
var x = _a[0], y = _a[1], z = _a[2];
45+
this.x = x;
46+
this.y = y;
47+
this.z = z;
4248
}
4349
return C2;
4450
}());
4551
var C3 = /** @class */ (function () {
4652
function C3(_a) {
4753
var x = _a.x, y = _a.y, z = _a.z;
54+
this.x = x;
55+
this.y = y;
56+
this.z = z;
4857
}
4958
return C3;
5059
}());

tests/baselines/reference/destructuringParameterProperties1.symbols

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,18 @@ c1 = new C1(["larry", "{curly}", "moe"]);
5050

5151
var useC1Properties = c1.x === c1.y && c1.y === c1.z;
5252
>useC1Properties : Symbol(useC1Properties, Decl(destructuringParameterProperties1.ts, 21, 3))
53+
>c1.x : Symbol(C1.x, Decl(destructuringParameterProperties1.ts, 1, 24))
5354
>c1 : Symbol(c1, Decl(destructuringParameterProperties1.ts, 19, 3))
55+
>x : Symbol(C1.x, Decl(destructuringParameterProperties1.ts, 1, 24))
56+
>c1.y : Symbol(C1.y, Decl(destructuringParameterProperties1.ts, 1, 26))
5457
>c1 : Symbol(c1, Decl(destructuringParameterProperties1.ts, 19, 3))
58+
>y : Symbol(C1.y, Decl(destructuringParameterProperties1.ts, 1, 26))
59+
>c1.y : Symbol(C1.y, Decl(destructuringParameterProperties1.ts, 1, 26))
5560
>c1 : Symbol(c1, Decl(destructuringParameterProperties1.ts, 19, 3))
61+
>y : Symbol(C1.y, Decl(destructuringParameterProperties1.ts, 1, 26))
62+
>c1.z : Symbol(C1.z, Decl(destructuringParameterProperties1.ts, 1, 29))
5663
>c1 : Symbol(c1, Decl(destructuringParameterProperties1.ts, 19, 3))
64+
>z : Symbol(C1.z, Decl(destructuringParameterProperties1.ts, 1, 29))
5765

5866
var c2 = new C2(["10", 10, !!10]);
5967
>c2 : Symbol(c2, Decl(destructuringParameterProperties1.ts, 23, 3))
@@ -63,9 +71,15 @@ var [c2_x, c2_y, c2_z] = [c2.x, c2.y, c2.z];
6371
>c2_x : Symbol(c2_x, Decl(destructuringParameterProperties1.ts, 24, 5))
6472
>c2_y : Symbol(c2_y, Decl(destructuringParameterProperties1.ts, 24, 10))
6573
>c2_z : Symbol(c2_z, Decl(destructuringParameterProperties1.ts, 24, 16))
74+
>c2.x : Symbol(C2.x, Decl(destructuringParameterProperties1.ts, 8, 24))
6675
>c2 : Symbol(c2, Decl(destructuringParameterProperties1.ts, 23, 3))
76+
>x : Symbol(C2.x, Decl(destructuringParameterProperties1.ts, 8, 24))
77+
>c2.y : Symbol(C2.y, Decl(destructuringParameterProperties1.ts, 8, 26))
6778
>c2 : Symbol(c2, Decl(destructuringParameterProperties1.ts, 23, 3))
79+
>y : Symbol(C2.y, Decl(destructuringParameterProperties1.ts, 8, 26))
80+
>c2.z : Symbol(C2.z, Decl(destructuringParameterProperties1.ts, 8, 29))
6881
>c2 : Symbol(c2, Decl(destructuringParameterProperties1.ts, 23, 3))
82+
>z : Symbol(C2.z, Decl(destructuringParameterProperties1.ts, 8, 29))
6983

7084
var c3 = new C3({x: 0, y: "", z: false});
7185
>c3 : Symbol(c3, Decl(destructuringParameterProperties1.ts, 26, 3))
@@ -85,7 +99,13 @@ var [c3_x, c3_y, c3_z] = [c3.x, c3.y, c3.z];
8599
>c3_x : Symbol(c3_x, Decl(destructuringParameterProperties1.ts, 28, 5))
86100
>c3_y : Symbol(c3_y, Decl(destructuringParameterProperties1.ts, 28, 10))
87101
>c3_z : Symbol(c3_z, Decl(destructuringParameterProperties1.ts, 28, 16))
102+
>c3.x : Symbol(C3.x, Decl(destructuringParameterProperties1.ts, 15, 24))
88103
>c3 : Symbol(c3, Decl(destructuringParameterProperties1.ts, 26, 3))
104+
>x : Symbol(C3.x, Decl(destructuringParameterProperties1.ts, 15, 24))
105+
>c3.y : Symbol(C3.y, Decl(destructuringParameterProperties1.ts, 15, 27))
89106
>c3 : Symbol(c3, Decl(destructuringParameterProperties1.ts, 26, 3))
107+
>y : Symbol(C3.y, Decl(destructuringParameterProperties1.ts, 15, 27))
108+
>c3.z : Symbol(C3.z, Decl(destructuringParameterProperties1.ts, 15, 30))
90109
>c3 : Symbol(c3, Decl(destructuringParameterProperties1.ts, 26, 3))
110+
>z : Symbol(C3.z, Decl(destructuringParameterProperties1.ts, 15, 30))
91111

0 commit comments

Comments
 (0)