]>
git.proxmox.com Git - pve-eslint.git/blob - eslint/lib/rules/no-mixed-operators.js
c75d01147c9030d81f3085ea848f0f63b709493b
2 * @fileoverview Rule to disallow mixed binary operators.
3 * @author Toru Nagashima
8 //------------------------------------------------------------------------------
10 //------------------------------------------------------------------------------
12 const astUtils
= require ( "./utils/ast-utils.js" );
14 //------------------------------------------------------------------------------
16 //------------------------------------------------------------------------------
18 const ARITHMETIC_OPERATORS
= [ "+" , "-" , "*" , "/" , "%" , "**" ];
19 const BITWISE_OPERATORS
= [ "&" , "|" , "^" , "~" , "<<" , ">>" , ">>>" ];
20 const COMPARISON_OPERATORS
= [ "==" , "!=" , "===" , "!==" , ">" , ">=" , "<" , "<=" ];
21 const LOGICAL_OPERATORS
= [ "&&" , "||" ];
22 const RELATIONAL_OPERATORS
= [ "in" , "instanceof" ];
23 const TERNARY_OPERATOR
= [ "?:" ];
24 const COALESCE_OPERATOR
= [ "??" ];
25 const ALL_OPERATORS
= []. concat (
34 const DEFAULT_GROUPS
= [
41 const TARGET_NODE_TYPE
= /^(?:Binary|Logical|Conditional)Expression$/u ;
45 * @param {Object|undefined} options A options object to normalize.
46 * @returns {Object} Normalized option object.
48 function normalizeOptions ( options
= {}) {
49 const hasGroups
= options
. groups
&& options
. groups
. length
> 0 ;
50 const groups
= hasGroups
? options
. groups
: DEFAULT_GROUPS
;
51 const allowSamePrecedence
= options
. allowSamePrecedence
!== false ;
60 * Checks whether any group which includes both given operator exists or not.
61 * @param {Array<string[]>} groups A list of groups to check.
62 * @param {string} left An operator.
63 * @param {string} right Another operator.
64 * @returns {boolean} `true` if such group existed.
66 function includesBothInAGroup ( groups
, left
, right
) {
67 return groups
. some ( group
=> group
. indexOf ( left
) !== - 1 && group
. indexOf ( right
) !== - 1 );
71 * Checks whether the given node is a conditional expression and returns the test node else the left node.
72 * @param {ASTNode} node A node which can be a BinaryExpression or a LogicalExpression node.
73 * This parent node can be BinaryExpression, LogicalExpression
74 * , or a ConditionalExpression node
75 * @returns {ASTNode} node the appropriate node(left or test).
77 function getChildNode ( node
) {
78 return node
. type
=== "ConditionalExpression" ? node
. test
: node
. left
;
81 //------------------------------------------------------------------------------
83 //------------------------------------------------------------------------------
85 /** @type {import('../shared/types').Rule} */
91 description
: "disallow mixed binary operators" ,
93 url
: "https://eslint.org/docs/rules/no-mixed-operators"
104 items
: { enum : ALL_OPERATORS
},
110 allowSamePrecedence
: {
115 additionalProperties
: false
120 unexpectedMixedOperator
: "Unexpected mix of '{{leftOperator}}' and '{{rightOperator}}'. Use parentheses to clarify the intended order of operations."
125 const sourceCode
= context
. getSourceCode ();
126 const options
= normalizeOptions ( context
. options
[ 0 ]);
129 * Checks whether a given node should be ignored by options or not.
130 * @param {ASTNode} node A node to check. This is a BinaryExpression
131 * node or a LogicalExpression node. This parent node is one of
133 * @returns {boolean} `true` if the node should be ignored.
135 function shouldIgnore ( node
) {
137 const b
= node
. parent
;
140 ! includesBothInAGroup ( options
. groups
, a
. operator
, b
. type
=== "ConditionalExpression" ? "?:" : b
. operator
) ||
142 options
. allowSamePrecedence
&&
143 astUtils
. getPrecedence ( a
) === astUtils
. getPrecedence ( b
)
149 * Checks whether the operator of a given node is mixed with parent
150 * node's operator or not.
151 * @param {ASTNode} node A node to check. This is a BinaryExpression
152 * node or a LogicalExpression node. This parent node is one of
154 * @returns {boolean} `true` if the node was mixed.
156 function isMixedWithParent ( node
) {
159 node
. operator
!== node
. parent
. operator
&&
160 ! astUtils
. isParenthesised ( sourceCode
, node
)
165 * Gets the operator token of a given node.
166 * @param {ASTNode} node A node to check. This is a BinaryExpression
167 * node or a LogicalExpression node.
168 * @returns {Token} The operator token of the node.
170 function getOperatorToken ( node
) {
171 return sourceCode
. getTokenAfter ( getChildNode ( node
), astUtils
. isNotClosingParenToken
);
175 * Reports both the operator of a given node and the operator of the
177 * @param {ASTNode} node A node to check. This is a BinaryExpression
178 * node or a LogicalExpression node. This parent node is one of
182 function reportBothOperators ( node
) {
183 const parent
= node
. parent
;
184 const left
= ( getChildNode ( parent
) === node
) ? node
: parent
;
185 const right
= ( getChildNode ( parent
) !== node
) ? node
: parent
;
187 leftOperator
: left
. operator
|| "?:" ,
188 rightOperator
: right
. operator
|| "?:"
193 loc
: getOperatorToken ( left
). loc
,
194 messageId
: "unexpectedMixedOperator" ,
199 loc
: getOperatorToken ( right
). loc
,
200 messageId
: "unexpectedMixedOperator" ,
206 * Checks between the operator of this node and the operator of the
208 * @param {ASTNode} node A node to check.
211 function check ( node
) {
213 TARGET_NODE_TYPE
. test ( node
. parent
. type
) &&
214 isMixedWithParent ( node
) &&
217 reportBothOperators ( node
);
222 BinaryExpression
: check
,
223 LogicalExpression
: check