1 | /**
|
---|
2 | * @fileoverview Rule to flag bitwise identifiers
|
---|
3 | * @author Nicholas C. Zakas
|
---|
4 | */
|
---|
5 |
|
---|
6 | "use strict";
|
---|
7 |
|
---|
8 | /*
|
---|
9 | *
|
---|
10 | * Set of bitwise operators.
|
---|
11 | *
|
---|
12 | */
|
---|
13 | const BITWISE_OPERATORS = [
|
---|
14 | "^", "|", "&", "<<", ">>", ">>>",
|
---|
15 | "^=", "|=", "&=", "<<=", ">>=", ">>>=",
|
---|
16 | "~"
|
---|
17 | ];
|
---|
18 |
|
---|
19 | //------------------------------------------------------------------------------
|
---|
20 | // Rule Definition
|
---|
21 | //------------------------------------------------------------------------------
|
---|
22 |
|
---|
23 | /** @type {import('../shared/types').Rule} */
|
---|
24 | module.exports = {
|
---|
25 | meta: {
|
---|
26 | type: "suggestion",
|
---|
27 |
|
---|
28 | docs: {
|
---|
29 | description: "Disallow bitwise operators",
|
---|
30 | recommended: false,
|
---|
31 | url: "https://eslint.org/docs/latest/rules/no-bitwise"
|
---|
32 | },
|
---|
33 |
|
---|
34 | schema: [
|
---|
35 | {
|
---|
36 | type: "object",
|
---|
37 | properties: {
|
---|
38 | allow: {
|
---|
39 | type: "array",
|
---|
40 | items: {
|
---|
41 | enum: BITWISE_OPERATORS
|
---|
42 | },
|
---|
43 | uniqueItems: true
|
---|
44 | },
|
---|
45 | int32Hint: {
|
---|
46 | type: "boolean",
|
---|
47 | default: false
|
---|
48 | }
|
---|
49 | },
|
---|
50 | additionalProperties: false
|
---|
51 | }
|
---|
52 | ],
|
---|
53 |
|
---|
54 | messages: {
|
---|
55 | unexpected: "Unexpected use of '{{operator}}'."
|
---|
56 | }
|
---|
57 | },
|
---|
58 |
|
---|
59 | create(context) {
|
---|
60 | const options = context.options[0] || {};
|
---|
61 | const allowed = options.allow || [];
|
---|
62 | const int32Hint = options.int32Hint === true;
|
---|
63 |
|
---|
64 | /**
|
---|
65 | * Reports an unexpected use of a bitwise operator.
|
---|
66 | * @param {ASTNode} node Node which contains the bitwise operator.
|
---|
67 | * @returns {void}
|
---|
68 | */
|
---|
69 | function report(node) {
|
---|
70 | context.report({ node, messageId: "unexpected", data: { operator: node.operator } });
|
---|
71 | }
|
---|
72 |
|
---|
73 | /**
|
---|
74 | * Checks if the given node has a bitwise operator.
|
---|
75 | * @param {ASTNode} node The node to check.
|
---|
76 | * @returns {boolean} Whether or not the node has a bitwise operator.
|
---|
77 | */
|
---|
78 | function hasBitwiseOperator(node) {
|
---|
79 | return BITWISE_OPERATORS.includes(node.operator);
|
---|
80 | }
|
---|
81 |
|
---|
82 | /**
|
---|
83 | * Checks if exceptions were provided, e.g. `{ allow: ['~', '|'] }`.
|
---|
84 | * @param {ASTNode} node The node to check.
|
---|
85 | * @returns {boolean} Whether or not the node has a bitwise operator.
|
---|
86 | */
|
---|
87 | function allowedOperator(node) {
|
---|
88 | return allowed.includes(node.operator);
|
---|
89 | }
|
---|
90 |
|
---|
91 | /**
|
---|
92 | * Checks if the given bitwise operator is used for integer typecasting, i.e. "|0"
|
---|
93 | * @param {ASTNode} node The node to check.
|
---|
94 | * @returns {boolean} whether the node is used in integer typecasting.
|
---|
95 | */
|
---|
96 | function isInt32Hint(node) {
|
---|
97 | return int32Hint && node.operator === "|" && node.right &&
|
---|
98 | node.right.type === "Literal" && node.right.value === 0;
|
---|
99 | }
|
---|
100 |
|
---|
101 | /**
|
---|
102 | * Report if the given node contains a bitwise operator.
|
---|
103 | * @param {ASTNode} node The node to check.
|
---|
104 | * @returns {void}
|
---|
105 | */
|
---|
106 | function checkNodeForBitwiseOperator(node) {
|
---|
107 | if (hasBitwiseOperator(node) && !allowedOperator(node) && !isInt32Hint(node)) {
|
---|
108 | report(node);
|
---|
109 | }
|
---|
110 | }
|
---|
111 |
|
---|
112 | return {
|
---|
113 | AssignmentExpression: checkNodeForBitwiseOperator,
|
---|
114 | BinaryExpression: checkNodeForBitwiseOperator,
|
---|
115 | UnaryExpression: checkNodeForBitwiseOperator
|
---|
116 | };
|
---|
117 |
|
---|
118 | }
|
---|
119 | };
|
---|