181 lines
3.8 KiB
JavaScript
181 lines
3.8 KiB
JavaScript
import each from "lodash/collection/each";
|
|
import * as t from "babel-types";
|
|
|
|
const PRECEDENCE = {};
|
|
|
|
each([
|
|
["||"],
|
|
["&&"],
|
|
["|"],
|
|
["^"],
|
|
["&"],
|
|
["==", "===", "!=", "!=="],
|
|
["<", ">", "<=", ">=", "in", "instanceof"],
|
|
[">>", "<<", ">>>"],
|
|
["+", "-"],
|
|
["*", "/", "%"],
|
|
["**"]
|
|
], function (tier, i) {
|
|
each(tier, function (op) {
|
|
PRECEDENCE[op] = i;
|
|
});
|
|
});
|
|
|
|
export function NullableTypeAnnotation(node, parent) {
|
|
return t.isArrayTypeAnnotation(parent);
|
|
}
|
|
|
|
export { NullableTypeAnnotation as FunctionTypeAnnotation };
|
|
|
|
export function UpdateExpression(node, parent) {
|
|
if (t.isMemberExpression(parent) && parent.object === node) {
|
|
// (foo++).test()
|
|
return true;
|
|
}
|
|
}
|
|
|
|
export function ObjectExpression(node, parent) {
|
|
if (t.isExpressionStatement(parent)) {
|
|
// ({ foo: "bar" });
|
|
return true;
|
|
}
|
|
|
|
if (t.isMemberExpression(parent) && parent.object === node) {
|
|
// ({ foo: "bar" }).foo
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
export function Binary(node, parent) {
|
|
if ((t.isCallExpression(parent) || t.isNewExpression(parent)) && parent.callee === node) {
|
|
return true;
|
|
}
|
|
|
|
if (t.isUnaryLike(parent)) {
|
|
return true;
|
|
}
|
|
|
|
if (t.isMemberExpression(parent) && parent.object === node) {
|
|
return true;
|
|
}
|
|
|
|
if (t.isBinary(parent)) {
|
|
var parentOp = parent.operator;
|
|
var parentPos = PRECEDENCE[parentOp];
|
|
|
|
var nodeOp = node.operator;
|
|
var nodePos = PRECEDENCE[nodeOp];
|
|
|
|
if (parentPos > nodePos) {
|
|
return true;
|
|
}
|
|
|
|
if (parentPos === nodePos && parent.right === node) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
export function BinaryExpression(node, parent) {
|
|
if (node.operator === "in") {
|
|
// var i = (1 in []);
|
|
if (t.isVariableDeclarator(parent)) {
|
|
return true;
|
|
}
|
|
|
|
// for ((1 in []);;);
|
|
if (t.isFor(parent)) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
export function SequenceExpression(node, parent) {
|
|
if (t.isForStatement(parent)) {
|
|
// Although parentheses wouldn't hurt around sequence
|
|
// expressions in the head of for loops, traditional style
|
|
// dictates that e.g. i++, j++ should not be wrapped with
|
|
// parentheses.
|
|
return false;
|
|
}
|
|
|
|
if (t.isExpressionStatement(parent) && parent.expression === node) {
|
|
return false;
|
|
}
|
|
|
|
// Otherwise err on the side of overparenthesization, adding
|
|
// explicit exceptions above if this proves overzealous.
|
|
return true;
|
|
}
|
|
|
|
export function YieldExpression(node, parent) {
|
|
return t.isBinary(parent) ||
|
|
t.isUnaryLike(parent) ||
|
|
t.isCallExpression(parent) ||
|
|
t.isMemberExpression(parent) ||
|
|
t.isNewExpression(parent) ||
|
|
t.isConditionalExpression(parent) ||
|
|
t.isYieldExpression(parent);
|
|
}
|
|
|
|
export function ClassExpression(node, parent) {
|
|
return t.isExpressionStatement(parent);
|
|
}
|
|
|
|
export function UnaryLike(node, parent) {
|
|
return t.isMemberExpression(parent) && parent.object === node;
|
|
}
|
|
|
|
export function FunctionExpression(node, parent) {
|
|
// function () {};
|
|
if (t.isExpressionStatement(parent)) {
|
|
return true;
|
|
}
|
|
|
|
// (function test() {}).name;
|
|
if (t.isMemberExpression(parent) && parent.object === node) {
|
|
return true;
|
|
}
|
|
|
|
// (function () {})();
|
|
if (t.isCallExpression(parent) && parent.callee === node) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
export function ConditionalExpression(node, parent) {
|
|
if (t.isUnaryLike(parent)) {
|
|
return true;
|
|
}
|
|
|
|
if (t.isBinary(parent)) {
|
|
return true;
|
|
}
|
|
|
|
if (t.isCallExpression(parent) || t.isNewExpression(parent)) {
|
|
if (parent.callee === node) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
if (t.isConditionalExpression(parent) && parent.test === node) {
|
|
return true;
|
|
}
|
|
|
|
if (t.isMemberExpression(parent) && parent.object === node) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
export function AssignmentExpression(node) {
|
|
if (t.isObjectPattern(node.left)) {
|
|
return true;
|
|
} else {
|
|
return ConditionalExpression(...arguments);
|
|
}
|
|
}
|