"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, anyOfValues: operations.anyOf, allOfValues: operations.allOf, }); return function flattenPredicateList(list) { if (Array.isArray(list.items)) { 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; } } else { // Ignore placeholders, SQL fragments, etc. return NoChange; } }; } module.exports = { name: "flatten-predicate-lists", category: [ "readability" ], visitors: { allOfExpressions: createHandler("allOfExpressions"), anyOfExpressions: createHandler("anyOfExpressions"), allOfConditions: createHandler("allOfConditions"), anyOfConditions: createHandler("anyOfConditions"), allOfValues: createHandler("allOfValues"), anyOfValues: createHandler("anyOfValues"), } };