.gitignore added
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / eslint / lib / rules / no-unsafe-negation.js
1 /**
2  * @fileoverview Rule to disallow negating the left operand of relational operators
3  * @author Toru Nagashima
4  */
5
6 "use strict";
7
8 //------------------------------------------------------------------------------
9 // Requirements
10 //------------------------------------------------------------------------------
11
12 const astUtils = require("./utils/ast-utils");
13
14 //------------------------------------------------------------------------------
15 // Helpers
16 //------------------------------------------------------------------------------
17
18 /**
19  * Checks whether the given operator is `in` or `instanceof`
20  * @param {string} op The operator type to check.
21  * @returns {boolean} `true` if the operator is `in` or `instanceof`
22  */
23 function isInOrInstanceOfOperator(op) {
24     return op === "in" || op === "instanceof";
25 }
26
27 /**
28  * Checks whether the given operator is an ordering relational operator or not.
29  * @param {string} op The operator type to check.
30  * @returns {boolean} `true` if the operator is an ordering relational operator.
31  */
32 function isOrderingRelationalOperator(op) {
33     return op === "<" || op === ">" || op === ">=" || op === "<=";
34 }
35
36 /**
37  * Checks whether the given node is a logical negation expression or not.
38  * @param {ASTNode} node The node to check.
39  * @returns {boolean} `true` if the node is a logical negation expression.
40  */
41 function isNegation(node) {
42     return node.type === "UnaryExpression" && node.operator === "!";
43 }
44
45 //------------------------------------------------------------------------------
46 // Rule Definition
47 //------------------------------------------------------------------------------
48
49 module.exports = {
50     meta: {
51         type: "problem",
52
53         docs: {
54             description: "disallow negating the left operand of relational operators",
55             category: "Possible Errors",
56             recommended: true,
57             url: "https://eslint.org/docs/rules/no-unsafe-negation",
58             suggestion: true
59         },
60
61         schema: [
62             {
63                 type: "object",
64                 properties: {
65                     enforceForOrderingRelations: {
66                         type: "boolean",
67                         default: false
68                     }
69                 },
70                 additionalProperties: false
71             }
72         ],
73
74         fixable: null,
75
76         messages: {
77             unexpected: "Unexpected negating the left operand of '{{operator}}' operator.",
78             suggestNegatedExpression: "Negate '{{operator}}' expression instead of its left operand. This changes the current behavior.",
79             suggestParenthesisedNegation: "Wrap negation in '()' to make the intention explicit. This preserves the current behavior."
80         }
81     },
82
83     create(context) {
84         const sourceCode = context.getSourceCode();
85         const options = context.options[0] || {};
86         const enforceForOrderingRelations = options.enforceForOrderingRelations === true;
87
88         return {
89             BinaryExpression(node) {
90                 const operator = node.operator;
91                 const orderingRelationRuleApplies = enforceForOrderingRelations && isOrderingRelationalOperator(operator);
92
93                 if (
94                     (isInOrInstanceOfOperator(operator) || orderingRelationRuleApplies) &&
95                     isNegation(node.left) &&
96                     !astUtils.isParenthesised(sourceCode, node.left)
97                 ) {
98                     context.report({
99                         node,
100                         loc: node.left.loc,
101                         messageId: "unexpected",
102                         data: { operator },
103                         suggest: [
104                             {
105                                 messageId: "suggestNegatedExpression",
106                                 data: { operator },
107                                 fix(fixer) {
108                                     const negationToken = sourceCode.getFirstToken(node.left);
109                                     const fixRange = [negationToken.range[1], node.range[1]];
110                                     const text = sourceCode.text.slice(fixRange[0], fixRange[1]);
111
112                                     return fixer.replaceTextRange(fixRange, `(${text})`);
113                                 }
114                             },
115                             {
116                                 messageId: "suggestParenthesisedNegation",
117                                 fix(fixer) {
118                                     return fixer.replaceText(node.left, `(${sourceCode.getText(node.left)})`);
119                                 }
120                             }
121                         ]
122                     });
123                 }
124             }
125         };
126     }
127 };