Skip to content

Commit

Permalink
feat(5326): allow destructuring with parameter properties
Browse files Browse the repository at this point in the history
  • Loading branch information
a-tarasyuk committed Jan 16, 2022
1 parent c71ff4d commit 13014c3
Show file tree
Hide file tree
Showing 38 changed files with 370 additions and 516 deletions.
26 changes: 22 additions & 4 deletions src/compiler/binder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3323,11 +3323,29 @@ namespace ts {
declareSymbolAndAddToSymbolTable(node, SymbolFlags.FunctionScopedVariable, SymbolFlags.ParameterExcludes);
}

// If this is a property-parameter, then also declare the property symbol into the
// containing class.
// If this is a property-parameter, then also declare the property symbol into the containing class.
if (isParameterPropertyDeclaration(node, node.parent)) {
const classDeclaration = node.parent.parent;
declareSymbol(classDeclaration.symbol.members!, classDeclaration.symbol, node, SymbolFlags.Property | (node.questionToken ? SymbolFlags.Optional : SymbolFlags.None), SymbolFlags.PropertyExcludes);
const symbol = node.parent.parent.symbol;
const members = symbol.members!;

if (isBindingPattern(node.name)) {
bindParameterPropertyFromBindingPattern(node.name, members, symbol);
}
else {
declareSymbol(members, symbol, node, SymbolFlags.Property | (node.questionToken ? SymbolFlags.Optional : SymbolFlags.None), SymbolFlags.PropertyExcludes);
}
}
}

function bindParameterPropertyFromBindingPattern(node: ObjectBindingPattern | ArrayBindingPattern, symbolTable: SymbolTable, parent: Symbol | undefined) {
for (const element of node.elements) {
if (isOmittedExpression(element)) continue;
if (isObjectBindingPattern(element.name) || isArrayBindingPattern(element.name)) {
bindParameterPropertyFromBindingPattern(element.name, symbolTable, parent);
}
else {
declareSymbol(symbolTable, parent, element, SymbolFlags.Property, SymbolFlags.PropertyExcludes);
}
}
}

Expand Down
3 changes: 0 additions & 3 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42755,9 +42755,6 @@ namespace ts {
else if ((node.kind === SyntaxKind.ImportDeclaration || node.kind === SyntaxKind.ImportEqualsDeclaration) && flags & ModifierFlags.Ambient) {
return grammarErrorOnNode(lastDeclare!, Diagnostics.A_0_modifier_cannot_be_used_with_an_import_declaration, "declare");
}
else if (node.kind === SyntaxKind.Parameter && (flags & ModifierFlags.ParameterPropertyModifier) && isBindingPattern((node as ParameterDeclaration).name)) {
return grammarErrorOnNode(node, Diagnostics.A_parameter_property_may_not_be_declared_using_a_binding_pattern);
}
else if (node.kind === SyntaxKind.Parameter && (flags & ModifierFlags.ParameterPropertyModifier) && (node as ParameterDeclaration).dotDotDotToken) {
return grammarErrorOnNode(node, Diagnostics.A_parameter_property_cannot_be_declared_using_a_rest_parameter);
}
Expand Down
4 changes: 0 additions & 4 deletions src/compiler/diagnosticMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -567,10 +567,6 @@
"category": "Error",
"code": 1186
},
"A parameter property may not be declared using a binding pattern.": {
"category": "Error",
"code": 1187
},
"Only a single variable declaration is allowed in a 'for...of' statement.": {
"category": "Error",
"code": 1188
Expand Down
33 changes: 15 additions & 18 deletions src/compiler/transformers/ts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1959,15 +1959,16 @@ namespace ts {
// this.y = y;
// }
//
const parameterPropertyAssignments = mapDefined(parametersWithPropertyAssignments, transformParameterWithPropertyAssignment);

const assignments = flatMapToMutable(parametersWithPropertyAssignments, p =>
isObjectBindingPattern(p.name) || isArrayBindingPattern(p.name) ? transformBindingPatternWithPropertyAssignment(p.name) :
isIdentifier(p.name) ? transformParameterNameWithPropertyAssignment(p.name) : undefined);
// If there is a super() call, the parameter properties go immediately after it
if (superStatementIndex >= 0) {
addRange(statements, parameterPropertyAssignments);
addRange(statements, assignments);
}
// Since there was no super() call, parameter properties are the first statements in the constructor
else {
statements = addRange(parameterPropertyAssignments, statements);
statements = addRange(assignments, statements);
}

// Add remaining statements from the body, skipping the super() call if it was found
Expand All @@ -1981,23 +1982,19 @@ namespace ts {
return block;
}

/**
* Transforms a parameter into a property assignment statement.
*
* @param node The parameter declaration.
*/
function transformParameterWithPropertyAssignment(node: ParameterPropertyDeclaration) {
const name = node.name;
if (!isIdentifier(name)) {
return undefined;
}
function transformBindingPatternWithPropertyAssignment(node: ObjectBindingPattern | ArrayBindingPattern): ExpressionStatement[] {
return flatMapToMutable(node.elements, n => isOmittedExpression(n) ? undefined :
isObjectBindingPattern(n.name) || isArrayBindingPattern(n.name) ? transformBindingPatternWithPropertyAssignment(n.name) :
isIdentifier(n.name) ? transformParameterNameWithPropertyAssignment(n.name) : undefined);
}

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

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

return startOnNewLine(
Expand All @@ -2011,12 +2008,12 @@ namespace ts {
factory.createThis(),
propertyName
),
node.name
node
),
localName
)
),
node
node.parent
),
moveRangePos(node, -1)
)
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,27 @@ class C3 {
var C1 = /** @class */ (function () {
function C1(_a) {
var x = _a[0], y = _a[1], z = _a[2];
this.x = x;
this.y = y;
this.z = z;
}
return C1;
}());
var C2 = /** @class */ (function () {
function C2(_a) {
var x = _a[0], y = _a[1], z = _a[2];
this.x = x;
this.y = y;
this.z = z;
}
return C2;
}());
var C3 = /** @class */ (function () {
function C3(_a) {
var x = _a.x, y = _a.y, z = _a.z;
this.x = x;
this.y = y;
this.z = z;
}
return C3;
}());
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -33,18 +33,27 @@ var [c3_x, c3_y, c3_z] = [c3.x, c3.y, c3.z];
var C1 = /** @class */ (function () {
function C1(_a) {
var x = _a[0], y = _a[1], z = _a[2];
this.x = x;
this.y = y;
this.z = z;
}
return C1;
}());
var C2 = /** @class */ (function () {
function C2(_a) {
var x = _a[0], y = _a[1], z = _a[2];
this.x = x;
this.y = y;
this.z = z;
}
return C2;
}());
var C3 = /** @class */ (function () {
function C3(_a) {
var x = _a.x, y = _a.y, z = _a.z;
this.x = x;
this.y = y;
this.z = z;
}
return C3;
}());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,18 @@ c1 = new C1(["larry", "{curly}", "moe"]);

var useC1Properties = c1.x === c1.y && c1.y === c1.z;
>useC1Properties : Symbol(useC1Properties, Decl(destructuringParameterProperties1.ts, 21, 3))
>c1.x : Symbol(C1.x, Decl(destructuringParameterProperties1.ts, 1, 24))
>c1 : Symbol(c1, Decl(destructuringParameterProperties1.ts, 19, 3))
>x : Symbol(C1.x, Decl(destructuringParameterProperties1.ts, 1, 24))
>c1.y : Symbol(C1.y, Decl(destructuringParameterProperties1.ts, 1, 26))
>c1 : Symbol(c1, Decl(destructuringParameterProperties1.ts, 19, 3))
>y : Symbol(C1.y, Decl(destructuringParameterProperties1.ts, 1, 26))
>c1.y : Symbol(C1.y, Decl(destructuringParameterProperties1.ts, 1, 26))
>c1 : Symbol(c1, Decl(destructuringParameterProperties1.ts, 19, 3))
>y : Symbol(C1.y, Decl(destructuringParameterProperties1.ts, 1, 26))
>c1.z : Symbol(C1.z, Decl(destructuringParameterProperties1.ts, 1, 29))
>c1 : Symbol(c1, Decl(destructuringParameterProperties1.ts, 19, 3))
>z : Symbol(C1.z, Decl(destructuringParameterProperties1.ts, 1, 29))

var c2 = new C2(["10", 10, !!10]);
>c2 : Symbol(c2, Decl(destructuringParameterProperties1.ts, 23, 3))
Expand All @@ -63,9 +71,15 @@ var [c2_x, c2_y, c2_z] = [c2.x, c2.y, c2.z];
>c2_x : Symbol(c2_x, Decl(destructuringParameterProperties1.ts, 24, 5))
>c2_y : Symbol(c2_y, Decl(destructuringParameterProperties1.ts, 24, 10))
>c2_z : Symbol(c2_z, Decl(destructuringParameterProperties1.ts, 24, 16))
>c2.x : Symbol(C2.x, Decl(destructuringParameterProperties1.ts, 8, 24))
>c2 : Symbol(c2, Decl(destructuringParameterProperties1.ts, 23, 3))
>x : Symbol(C2.x, Decl(destructuringParameterProperties1.ts, 8, 24))
>c2.y : Symbol(C2.y, Decl(destructuringParameterProperties1.ts, 8, 26))
>c2 : Symbol(c2, Decl(destructuringParameterProperties1.ts, 23, 3))
>y : Symbol(C2.y, Decl(destructuringParameterProperties1.ts, 8, 26))
>c2.z : Symbol(C2.z, Decl(destructuringParameterProperties1.ts, 8, 29))
>c2 : Symbol(c2, Decl(destructuringParameterProperties1.ts, 23, 3))
>z : Symbol(C2.z, Decl(destructuringParameterProperties1.ts, 8, 29))

var c3 = new C3({x: 0, y: "", z: false});
>c3 : Symbol(c3, Decl(destructuringParameterProperties1.ts, 26, 3))
Expand All @@ -85,7 +99,13 @@ var [c3_x, c3_y, c3_z] = [c3.x, c3.y, c3.z];
>c3_x : Symbol(c3_x, Decl(destructuringParameterProperties1.ts, 28, 5))
>c3_y : Symbol(c3_y, Decl(destructuringParameterProperties1.ts, 28, 10))
>c3_z : Symbol(c3_z, Decl(destructuringParameterProperties1.ts, 28, 16))
>c3.x : Symbol(C3.x, Decl(destructuringParameterProperties1.ts, 15, 24))
>c3 : Symbol(c3, Decl(destructuringParameterProperties1.ts, 26, 3))
>x : Symbol(C3.x, Decl(destructuringParameterProperties1.ts, 15, 24))
>c3.y : Symbol(C3.y, Decl(destructuringParameterProperties1.ts, 15, 27))
>c3 : Symbol(c3, Decl(destructuringParameterProperties1.ts, 26, 3))
>y : Symbol(C3.y, Decl(destructuringParameterProperties1.ts, 15, 27))
>c3.z : Symbol(C3.z, Decl(destructuringParameterProperties1.ts, 15, 30))
>c3 : Symbol(c3, Decl(destructuringParameterProperties1.ts, 26, 3))
>z : Symbol(C3.z, Decl(destructuringParameterProperties1.ts, 15, 30))

Loading

0 comments on commit 13014c3

Please sign in to comment.