Ohm-Management - Projektarbeit B-ME
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

no-magic-numbers.js 5.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. /**
  2. * @fileoverview Rule to flag statements that use magic numbers (adapted from https://github.com/danielstjules/buddy.js)
  3. * @author Vincent Lemeunier
  4. */
  5. "use strict";
  6. //------------------------------------------------------------------------------
  7. // Rule Definition
  8. //------------------------------------------------------------------------------
  9. module.exports = {
  10. meta: {
  11. type: "suggestion",
  12. docs: {
  13. description: "disallow magic numbers",
  14. category: "Best Practices",
  15. recommended: false,
  16. url: "https://eslint.org/docs/rules/no-magic-numbers"
  17. },
  18. schema: [{
  19. type: "object",
  20. properties: {
  21. detectObjects: {
  22. type: "boolean"
  23. },
  24. enforceConst: {
  25. type: "boolean"
  26. },
  27. ignore: {
  28. type: "array",
  29. items: {
  30. type: "number"
  31. },
  32. uniqueItems: true
  33. },
  34. ignoreArrayIndexes: {
  35. type: "boolean"
  36. }
  37. },
  38. additionalProperties: false
  39. }],
  40. messages: {
  41. useConst: "Number constants declarations must use 'const'.",
  42. noMagic: "No magic number: {{raw}}."
  43. }
  44. },
  45. create(context) {
  46. const config = context.options[0] || {},
  47. detectObjects = !!config.detectObjects,
  48. enforceConst = !!config.enforceConst,
  49. ignore = config.ignore || [],
  50. ignoreArrayIndexes = !!config.ignoreArrayIndexes;
  51. /**
  52. * Returns whether the node is number literal
  53. * @param {Node} node - the node literal being evaluated
  54. * @returns {boolean} true if the node is a number literal
  55. */
  56. function isNumber(node) {
  57. return typeof node.value === "number";
  58. }
  59. /**
  60. * Returns whether the number should be ignored
  61. * @param {number} num - the number
  62. * @returns {boolean} true if the number should be ignored
  63. */
  64. function shouldIgnoreNumber(num) {
  65. return ignore.indexOf(num) !== -1;
  66. }
  67. /**
  68. * Returns whether the number should be ignored when used as a radix within parseInt() or Number.parseInt()
  69. * @param {ASTNode} parent - the non-"UnaryExpression" parent
  70. * @param {ASTNode} node - the node literal being evaluated
  71. * @returns {boolean} true if the number should be ignored
  72. */
  73. function shouldIgnoreParseInt(parent, node) {
  74. return parent.type === "CallExpression" && node === parent.arguments[1] &&
  75. (parent.callee.name === "parseInt" ||
  76. parent.callee.type === "MemberExpression" &&
  77. parent.callee.object.name === "Number" &&
  78. parent.callee.property.name === "parseInt");
  79. }
  80. /**
  81. * Returns whether the number should be ignored when used to define a JSX prop
  82. * @param {ASTNode} parent - the non-"UnaryExpression" parent
  83. * @returns {boolean} true if the number should be ignored
  84. */
  85. function shouldIgnoreJSXNumbers(parent) {
  86. return parent.type.indexOf("JSX") === 0;
  87. }
  88. /**
  89. * Returns whether the number should be ignored when used as an array index with enabled 'ignoreArrayIndexes' option.
  90. * @param {ASTNode} parent - the non-"UnaryExpression" parent.
  91. * @returns {boolean} true if the number should be ignored
  92. */
  93. function shouldIgnoreArrayIndexes(parent) {
  94. return parent.type === "MemberExpression" && ignoreArrayIndexes;
  95. }
  96. return {
  97. Literal(node) {
  98. const okTypes = detectObjects ? [] : ["ObjectExpression", "Property", "AssignmentExpression"];
  99. if (!isNumber(node)) {
  100. return;
  101. }
  102. let fullNumberNode;
  103. let parent;
  104. let value;
  105. let raw;
  106. // For negative magic numbers: update the value and parent node
  107. if (node.parent.type === "UnaryExpression" && node.parent.operator === "-") {
  108. fullNumberNode = node.parent;
  109. parent = fullNumberNode.parent;
  110. value = -node.value;
  111. raw = `-${node.raw}`;
  112. } else {
  113. fullNumberNode = node;
  114. parent = node.parent;
  115. value = node.value;
  116. raw = node.raw;
  117. }
  118. if (shouldIgnoreNumber(value) ||
  119. shouldIgnoreParseInt(parent, fullNumberNode) ||
  120. shouldIgnoreArrayIndexes(parent) ||
  121. shouldIgnoreJSXNumbers(parent)) {
  122. return;
  123. }
  124. if (parent.type === "VariableDeclarator") {
  125. if (enforceConst && parent.parent.kind !== "const") {
  126. context.report({
  127. node: fullNumberNode,
  128. messageId: "useConst"
  129. });
  130. }
  131. } else if (
  132. okTypes.indexOf(parent.type) === -1 ||
  133. (parent.type === "AssignmentExpression" && parent.left.type === "Identifier")
  134. ) {
  135. context.report({
  136. node: fullNumberNode,
  137. messageId: "noMagic",
  138. data: {
  139. raw
  140. }
  141. });
  142. }
  143. }
  144. };
  145. }
  146. };