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.
53 lines
1.3 KiB
JavaScript
53 lines
1.3 KiB
JavaScript
"use strict";
|
|
|
|
const matchValue = require("match-value");
|
|
|
|
const operations = require("../operations");
|
|
const typeOf = require("../type-of");
|
|
const NoChange = require("./util/no-change");
|
|
|
|
// FIXME: Generalize to all predicate lists?
|
|
|
|
function createHandler(type) {
|
|
let subItemProperty = matchValue(type, {
|
|
notCondition: "condition",
|
|
notExpression: "expression"
|
|
});
|
|
|
|
return function flattenNotPredicates(expression) {
|
|
// Flattens multiple levels of like-typed not(...) wrappers, ending up with a logically equivalent subtree
|
|
// `notCondition(condition)` -> `notCondition(condition)`
|
|
// `notCondition(notCondition(condition))` -> `condition`
|
|
// `notCondition(notCondition(notCondition(condition)))` -> `notCondition(condition)`
|
|
// etc.
|
|
let notLevels = 0;
|
|
let currentItem = expression;
|
|
|
|
while(typeOf(currentItem) === type) {
|
|
notLevels += 1;
|
|
currentItem = currentItem[subItemProperty];
|
|
}
|
|
|
|
if (notLevels === 1) {
|
|
return NoChange;
|
|
} else {
|
|
let hasNot = (notLevels % 2) === 1;
|
|
|
|
if (hasNot) {
|
|
return operations.not(currentItem);
|
|
} else {
|
|
return currentItem;
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
module.exports = {
|
|
name: "flatten-not-predicates",
|
|
category: [ "readability" ],
|
|
visitors: {
|
|
notExpression: createHandler("notExpression"),
|
|
notCondition: createHandler("notCondition")
|
|
}
|
|
};
|