eslint-plugin-de-morgan
Version:
ESLint plugin for transforming negated boolean expressions via De Morgan’s laws
51 lines (50 loc) • 1.78 kB
JavaScript
import { isLogicalExpression } from './is-logical-expression.js'
import { findOutermostParenthesizedNode } from './find-outermost-parenthesized-node.js'
import { isUnaryExpression } from './is-unary-expression.js'
import { hasNegationOperator } from './has-negation-operator.js'
/**
* Checks if there is a negation (`!`) inside the outermost parentheses of a
* given negated expression. This is useful for determining if De Morgan's laws
* can be applied without changing the logic.
*
* @param node - The starting node, assumed to be of the form `!(...)`.
* @param context - The ESLint rule context, used to access source code.
* @returns True if there is a negation (`!`) inside the parentheses.
*/
function hasNegationInsideParens(node, context) {
let outermostNode = findOutermostParenthesizedNode(
node,
context.sourceCode.getText(node),
)
if (!isUnaryExpression(outermostNode)) {
return false
}
return hasNegationInside(outermostNode.argument)
}
/**
* Recursively checks if the given expression contains a "relevant" negation
* (`!`). Double negations (`!!`) are ignored as they are typically used for
* type coercion.
*
* @param node - The AST expression node to check.
* @returns True if the expression contains a relevant `!` inside.
*/
function hasNegationInside(node) {
let current = node
while (
isUnaryExpression(current) &&
current.operator === '!' &&
isUnaryExpression(current.argument) &&
current.argument.operator === '!'
) {
current = current.argument.argument
}
if (hasNegationOperator(current)) {
return true
}
if (isLogicalExpression(current)) {
return hasNegationInside(current.left) || hasNegationInside(current.right)
}
return false
}
export { hasNegationInsideParens }