You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

101 lines
2.4 KiB
JavaScript

'use strict';
const getNodes = require("../node/get-nodes");
const getNodeSequences = require("../node/get-node-sequences");
/* Simple node types are always simple, no matter what. */
let simpleNodeTypes = new Set([
"Literal",
"Identifier",
"ThisExpression",
"ContinueStatement",
"MemberExpression", /* FIXME: This may be wrong if a computed property is involved? */
]);
/* "Semi-simple" node types are only considered simple if all of their children are also simple. */
let semiSimpleNodeTypes = new Set([
"BinaryExpression",
"UnaryExpression",
"UpdateExpression",
"LogicalExpression",
"AssignmentPattern",
"AssignmentExpression",
"VariableDeclarator",
"Property",
"ReturnStatement",
"IfStatement",
"ConditionalExpression",
"ExpressionStatement"
]);
/* TODO: CallExpression is only simple if nested one level deep at most. */
function checkChildNodes(node, predicate) {
let nodeProperties = node.getNodeProperties();
let nodeSequenceProperties = node.getNodeSequenceProperties();
let checkFailed = false;
for (let property of nodeProperties) {
if (!predicate(node[property])) {
checkFailed = true;
}
}
for (let property of nodeSequenceProperties) {
for (let item of node[property]) {
if (!predicate(item)) {
checkFailed = true;
}
}
}
return !checkFailed;
}
function _isSimple(node) {
if (simpleNodeTypes.has(node.type)) {
return true;
} else if (semiSimpleNodeTypes.has(node.type)) {
return checkChildNodes(node, (childNode) => childNode.isSimple());
} else if (node.type === "CallExpression") {
return checkChildNodes(node, (childNode) => childNode.type !== "CallExpression" && childNode.isSimple());
} else if (node.type === "ObjectExpression") {
return (node.properties.length === 0);
} else if (node.type === "ArrayExpression") {
return (node.elements.length === 0);
} else {
return false;
}
}
function isSimple() {
if (this._cacheIsSimple != null) {
return this._cacheIsSimple;
} else {
let result = _isSimple(this);
this._cacheIsSimple = result;
return result;
}
}
function getNodeProperties() {
return getNodes(this);
}
function getNodeSequenceProperties() {
return getNodeSequences(this);
}
module.exports = function createUtilityMethodsProcessor() {
return {
onEnter: function onEnter(node) {
Object.assign(node, {
isSimple: isSimple,
getNodeProperties: getNodeProperties,
getNodeSequenceProperties: getNodeSequenceProperties
});
}
};
};