Skip to content

Commit

Permalink
refactor: simplify toAssignable routine (#11032)
Browse files Browse the repository at this point in the history
* refactor: remove isBinding parameter

* remove unused contextDescription

* refactor: remove unnecessary nullish check

* refactor: simplify toAssignable on ParenthesizedExpression

* tests: categorize createParenthesizedExpression tests
  • Loading branch information
JLHwung authored and nicolo-ribaudo committed Jan 20, 2020
1 parent 9bc04ba commit 43b23e0
Show file tree
Hide file tree
Showing 42 changed files with 234 additions and 162 deletions.
17 changes: 7 additions & 10 deletions packages/babel-parser/src/parser/expression.js
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ export default class ExpressionParser extends LValParser {
this.expectPlugin("logicalAssignment");
}
if (this.match(tt.eq)) {
node.left = this.toAssignable(left, undefined, "assignment expression");
node.left = this.toAssignable(left);
refExpressionErrors.doubleProto = -1; // reset because double __proto__ is valid in assignment expression
} else {
node.left = left;
Expand Down Expand Up @@ -1857,15 +1857,17 @@ export default class ExpressionParser extends LValParser {
): N.ArrowFunctionExpression {
this.scope.enter(functionFlags(isAsync, false) | SCOPE_ARROW);
this.initFunction(node, isAsync);

const oldMaybeInArrowParameters = this.state.maybeInArrowParameters;
const oldYieldPos = this.state.yieldPos;
const oldAwaitPos = this.state.awaitPos;

if (params) {
this.state.maybeInArrowParameters = true;
this.setArrowFunctionParameters(node, params, trailingCommaPos);
}
this.state.maybeInArrowParameters = false;
this.state.yieldPos = -1;
this.state.awaitPos = -1;

if (params) this.setArrowFunctionParameters(node, params, trailingCommaPos);
this.parseFunctionBody(node, true);

this.scope.exit();
Expand All @@ -1881,12 +1883,7 @@ export default class ExpressionParser extends LValParser {
params: N.Expression[],
trailingCommaPos: ?number,
): void {
node.params = this.toAssignableList(
params,
true,
"arrow function parameters",
trailingCommaPos,
);
node.params = this.toAssignableList(params, trailingCommaPos);
}

parseFunctionBodyAndFinish(
Expand Down
163 changes: 68 additions & 95 deletions packages/babel-parser/src/parser/lval.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,114 +50,89 @@ export default class LValParser extends NodeUtils {
// NOTE: There is a corresponding "isAssignable" method in flow.js.
// When this one is updated, please check if also that one needs to be updated.

toAssignable(
node: Node,
isBinding: ?boolean,
contextDescription: string,
): Node {
if (node) {
toAssignable(node: Node): Node {
let parenthesized = undefined;
if (node.type === "ParenthesizedExpression" || node.extra?.parenthesized) {
parenthesized = unwrapParenthesizedExpression(node);
if (
(this.options.createParenthesizedExpressions &&
node.type === "ParenthesizedExpression") ||
node.extra?.parenthesized
parenthesized.type !== "Identifier" &&
parenthesized.type !== "MemberExpression"
) {
const parenthesized = unwrapParenthesizedExpression(node);
if (
parenthesized.type !== "Identifier" &&
parenthesized.type !== "MemberExpression"
) {
this.raise(node.start, "Invalid parenthesized assignment pattern");
}
this.raise(node.start, "Invalid parenthesized assignment pattern");
}
}

switch (node.type) {
case "Identifier":
case "ObjectPattern":
case "ArrayPattern":
case "AssignmentPattern":
break;

switch (node.type) {
case "Identifier":
case "ObjectPattern":
case "ArrayPattern":
case "AssignmentPattern":
break;

case "ObjectExpression":
node.type = "ObjectPattern";
for (
let i = 0, length = node.properties.length, last = length - 1;
i < length;
i++
case "ObjectExpression":
node.type = "ObjectPattern";
for (
let i = 0, length = node.properties.length, last = length - 1;
i < length;
i++
) {
const prop = node.properties[i];
const isLast = i === last;
this.toAssignableObjectExpressionProp(prop, isLast);

if (
isLast &&
prop.type === "RestElement" &&
node.extra?.trailingComma
) {
const prop = node.properties[i];
const isLast = i === last;
this.toAssignableObjectExpressionProp(prop, isBinding, isLast);

if (
isLast &&
prop.type === "RestElement" &&
node.extra?.trailingComma
) {
this.raiseRestNotLast(node.extra.trailingComma);
}
this.raiseRestNotLast(node.extra.trailingComma);
}
break;

case "ObjectProperty":
this.toAssignable(node.value, isBinding, contextDescription);
break;

case "SpreadElement": {
this.checkToRestConversion(node);

node.type = "RestElement";
const arg = node.argument;
this.toAssignable(arg, isBinding, contextDescription);
break;
}
break;

case "ArrayExpression":
node.type = "ArrayPattern";
this.toAssignableList(
node.elements,
isBinding,
contextDescription,
node.extra?.trailingComma,
);
break;
case "ObjectProperty":
this.toAssignable(node.value);
break;

case "AssignmentExpression":
if (node.operator !== "=") {
this.raise(
node.left.end,
"Only '=' operator can be used for specifying default value.",
);
}
case "SpreadElement": {
this.checkToRestConversion(node);

node.type = "AssignmentPattern";
delete node.operator;
this.toAssignable(node.left, isBinding, contextDescription);
break;
node.type = "RestElement";
const arg = node.argument;
this.toAssignable(arg);
break;
}

case "ArrayExpression":
node.type = "ArrayPattern";
this.toAssignableList(node.elements, node.extra?.trailingComma);
break;

case "ParenthesizedExpression":
node.expression = this.toAssignable(
node.expression,
isBinding,
contextDescription,
case "AssignmentExpression":
if (node.operator !== "=") {
this.raise(
node.left.end,
"Only '=' operator can be used for specifying default value.",
);
break;
}

case "MemberExpression":
if (!isBinding) break;
node.type = "AssignmentPattern";
delete node.operator;
this.toAssignable(node.left);
break;

default:
// We don't know how to deal with this node. It will
// be reported by a later call to checkLVal
}
case "ParenthesizedExpression":
this.toAssignable(((parenthesized: any): Expression));
break;

default:
// We don't know how to deal with this node. It will
// be reported by a later call to checkLVal
}
return node;
}

toAssignableObjectExpressionProp(
prop: Node,
isBinding: ?boolean,
isLast: boolean,
) {
toAssignableObjectExpressionProp(prop: Node, isLast: boolean) {
if (prop.type === "ObjectMethod") {
const error =
prop.kind === "get" || prop.kind === "set"
Expand All @@ -168,16 +143,14 @@ export default class LValParser extends NodeUtils {
} else if (prop.type === "SpreadElement" && !isLast) {
this.raiseRestNotLast(prop.start);
} else {
this.toAssignable(prop, isBinding, "object destructuring pattern");
this.toAssignable(prop);
}
}

// Convert list of expression atoms to binding list.

toAssignableList(
exprList: Expression[],
isBinding: ?boolean,
contextDescription: string,
trailingCommaPos?: ?number,
): $ReadOnlyArray<Pattern> {
let end = exprList.length;
Expand All @@ -188,7 +161,7 @@ export default class LValParser extends NodeUtils {
} else if (last && last.type === "SpreadElement") {
last.type = "RestElement";
const arg = last.argument;
this.toAssignable(arg, isBinding, contextDescription);
this.toAssignable(arg);
if (
arg.type !== "Identifier" &&
arg.type !== "MemberExpression" &&
Expand All @@ -208,7 +181,7 @@ export default class LValParser extends NodeUtils {
for (let i = 0; i < end; i++) {
const elt = exprList[i];
if (elt) {
this.toAssignable(elt, isBinding, contextDescription);
this.toAssignable(elt);
if (elt.type === "RestElement") {
this.raiseRestNotLast(elt.start);
}
Expand Down
2 changes: 1 addition & 1 deletion packages/babel-parser/src/parser/statement.js
Original file line number Diff line number Diff line change
Expand Up @@ -537,10 +537,10 @@ export default class StatementParser extends ExpressionParser {
const refExpressionErrors = new ExpressionErrors();
const init = this.parseExpression(true, refExpressionErrors);
if (this.match(tt._in) || this.isContextual("of")) {
this.toAssignable(init);
const description = this.isContextual("of")
? "for-of statement"
: "for-in statement";
this.toAssignable(init, undefined, description);
this.checkLVal(init, undefined, undefined, description);
return this.parseForIn(node, init, awaitAt);
} else {
Expand Down
18 changes: 5 additions & 13 deletions packages/babel-parser/src/plugins/estree.js
Original file line number Diff line number Diff line change
Expand Up @@ -362,25 +362,17 @@ export default (superClass: Class<Parser>): Class<Parser> =>
return (node: any);
}

toAssignable(
node: N.Node,
isBinding: ?boolean,
contextDescription: string,
): N.Node {
toAssignable(node: N.Node): N.Node {
if (isSimpleProperty(node)) {
this.toAssignable(node.value, isBinding, contextDescription);
this.toAssignable(node.value);

return node;
}

return super.toAssignable(node, isBinding, contextDescription);
return super.toAssignable(node);
}

toAssignableObjectExpressionProp(
prop: N.Node,
isBinding: ?boolean,
isLast: boolean,
) {
toAssignableObjectExpressionProp(prop: N.Node, isLast: boolean) {
if (prop.kind === "get" || prop.kind === "set") {
throw this.raise(
prop.key.start,
Expand All @@ -392,7 +384,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
"Object pattern can't contain methods",
);
} else {
super.toAssignableObjectExpressionProp(prop, isBinding, isLast);
super.toAssignableObjectExpressionProp(prop, isLast);
}
}

Expand Down
25 changes: 4 additions & 21 deletions packages/babel-parser/src/plugins/flow.js
Original file line number Diff line number Diff line change
Expand Up @@ -1886,8 +1886,6 @@ export default (superClass: Class<Parser>): Class<Parser> =>
// node.params is Expression[] instead of $ReadOnlyArray<Pattern> because it
// has not been converted yet.
((node.params: any): N.Expression[]),
true,
"arrow function parameters",
node.extra?.trailingComma,
);
// Enter scope, as checkParams defines bindings
Expand Down Expand Up @@ -2091,27 +2089,17 @@ export default (superClass: Class<Parser>): Class<Parser> =>
}
}

toAssignable(
node: N.Node,
isBinding: ?boolean,
contextDescription: string,
): N.Node {
toAssignable(node: N.Node): N.Node {
if (node.type === "TypeCastExpression") {
return super.toAssignable(
this.typeCastToParameter(node),
isBinding,
contextDescription,
);
return super.toAssignable(this.typeCastToParameter(node));
} else {
return super.toAssignable(node, isBinding, contextDescription);
return super.toAssignable(node);
}
}

// turn type casts that we found in function parameter head into type annotated params
toAssignableList(
exprList: N.Expression[],
isBinding: ?boolean,
contextDescription: string,
trailingCommaPos?: ?number,
): $ReadOnlyArray<N.Pattern> {
for (let i = 0; i < exprList.length; i++) {
Expand All @@ -2120,12 +2108,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
exprList[i] = this.typeCastToParameter(expr);
}
}
return super.toAssignableList(
exprList,
isBinding,
contextDescription,
trailingCommaPos,
);
return super.toAssignableList(exprList, trailingCommaPos);
}

// this is a list of nodes, from something like a call expression, we need to filter the
Expand Down
Loading

0 comments on commit 43b23e0

Please sign in to comment.