no-bitwise.js 2.9 KB

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