An error occurred while loading the file. Please try again.
-
Rosanny Sihombing authoredcea2f272
/**
* @fileoverview Rule to disallow negating the left operand of relational operators
* @author Toru Nagashima
*/
"use strict";
//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------
const astUtils = require("./utils/ast-utils");
//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------
/**
* Checks whether the given operator is `in` or `instanceof`
* @param {string} op The operator type to check.
* @returns {boolean} `true` if the operator is `in` or `instanceof`
*/
function isInOrInstanceOfOperator(op) {
return op === "in" || op === "instanceof";
}
/**
* Checks whether the given operator is an ordering relational operator or not.
* @param {string} op The operator type to check.
* @returns {boolean} `true` if the operator is an ordering relational operator.
*/
function isOrderingRelationalOperator(op) {
return op === "<" || op === ">" || op === ">=" || op === "<=";
}
/**
* Checks whether the given node is a logical negation expression or not.
* @param {ASTNode} node The node to check.
* @returns {boolean} `true` if the node is a logical negation expression.
*/
function isNegation(node) {
return node.type === "UnaryExpression" && node.operator === "!";
}
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = {
meta: {
type: "problem",
docs: {
description: "disallow negating the left operand of relational operators",
category: "Possible Errors",
recommended: true,
url: "https://eslint.org/docs/rules/no-unsafe-negation",
suggestion: true
},
schema: [
{
type: "object",
properties: {
enforceForOrderingRelations: {
type: "boolean",
default: false
}
},
additionalProperties: false
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
}
],
fixable: null,
messages: {
unexpected: "Unexpected negating the left operand of '{{operator}}' operator.",
suggestNegatedExpression: "Negate '{{operator}}' expression instead of its left operand. This changes the current behavior.",
suggestParenthesisedNegation: "Wrap negation in '()' to make the intention explicit. This preserves the current behavior."
}
},
create(context) {
const sourceCode = context.getSourceCode();
const options = context.options[0] || {};
const enforceForOrderingRelations = options.enforceForOrderingRelations === true;
return {
BinaryExpression(node) {
const operator = node.operator;
const orderingRelationRuleApplies = enforceForOrderingRelations && isOrderingRelationalOperator(operator);
if (
(isInOrInstanceOfOperator(operator) || orderingRelationRuleApplies) &&
isNegation(node.left) &&
!astUtils.isParenthesised(sourceCode, node.left)
) {
context.report({
node,
loc: node.left.loc,
messageId: "unexpected",
data: { operator },
suggest: [
{
messageId: "suggestNegatedExpression",
data: { operator },
fix(fixer) {
const negationToken = sourceCode.getFirstToken(node.left);
const fixRange = [negationToken.range[1], node.range[1]];
const text = sourceCode.text.slice(fixRange[0], fixRange[1]);
return fixer.replaceTextRange(fixRange, `(${text})`);
}
},
{
messageId: "suggestParenthesisedNegation",
fix(fixer) {
return fixer.replaceText(node.left, `(${sourceCode.getText(node.left)})`);
}
}
]
});
}
}
};
}
};