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.
raqb/src/optimizers/flatten-predicate-lists.js

67 lines
1.9 KiB
JavaScript

"use strict";
const matchValue = require("match-value");
const operations = require("../operations");
const typeOf = require("../type-of");
const NoChange = require("./util/no-change");
const RemoveNode = require("./util/remove-node");
// FIXME: Generalize to all predicate lists?
function createHandler(type) {
let listOperation = matchValue.literal(type, {
anyOfExpressions: operations.anyOf,
allOfExpressions: operations.allOf,
anyOfConditions: operations.anyOf,
allOfConditions: operations.allOf,
});
return function flattenPredicateList(list) {
let hasNestedPredicates = list.items.some((item) => typeOf(item) === type);
let hasSingleItem = (list.items.length === 1); // For unnecessary anyOf/allOf wrapping, which is also handled by this optimizer
let mustFlatten = hasNestedPredicates || hasSingleItem;
if (mustFlatten) {
let actualItems = [];
function collectItemsRecursively(node) {
for (let subItem of node.items) {
if (typeOf(subItem) === type) {
collectItemsRecursively(subItem);
} else {
actualItems.push(subItem);
}
}
}
collectItemsRecursively(list);
if (actualItems.length === 0) {
// FIXME: Do we want to log this as a warning? It *could* occur when items get eliminated by another optimizer, but it could also be the result of a bug...
console.warn("Encountered 0 actual items in predicate list");
return RemoveNode;
} else if (actualItems.length === 1) {
// Wrapping is pointless here.
return actualItems[0];
} else {
return listOperation(actualItems);
}
} else {
return NoChange;
}
};
}
module.exports = {
name: "flatten-predicate-lists",
category: [ "readability" ],
visitors: {
allOfExpressions: createHandler("allOfExpressions"),
anyOfExpressions: createHandler("anyOfExpressions"),
allOfConditions: createHandler("allOfConditions"),
anyOfConditions: createHandler("anyOfConditions"),
}
};