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.

radix.js 5.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. /**
  2. * @fileoverview Rule to flag use of parseInt without a radix argument
  3. * @author James Allardice
  4. */
  5. "use strict";
  6. //------------------------------------------------------------------------------
  7. // Requirements
  8. //------------------------------------------------------------------------------
  9. const astUtils = require("../util/ast-utils");
  10. //------------------------------------------------------------------------------
  11. // Helpers
  12. //------------------------------------------------------------------------------
  13. const MODE_ALWAYS = "always",
  14. MODE_AS_NEEDED = "as-needed";
  15. /**
  16. * Checks whether a given variable is shadowed or not.
  17. *
  18. * @param {eslint-scope.Variable} variable - A variable to check.
  19. * @returns {boolean} `true` if the variable is shadowed.
  20. */
  21. function isShadowed(variable) {
  22. return variable.defs.length >= 1;
  23. }
  24. /**
  25. * Checks whether a given node is a MemberExpression of `parseInt` method or not.
  26. *
  27. * @param {ASTNode} node - A node to check.
  28. * @returns {boolean} `true` if the node is a MemberExpression of `parseInt`
  29. * method.
  30. */
  31. function isParseIntMethod(node) {
  32. return (
  33. node.type === "MemberExpression" &&
  34. !node.computed &&
  35. node.property.type === "Identifier" &&
  36. node.property.name === "parseInt"
  37. );
  38. }
  39. /**
  40. * Checks whether a given node is a valid value of radix or not.
  41. *
  42. * The following values are invalid.
  43. *
  44. * - A literal except numbers.
  45. * - undefined.
  46. *
  47. * @param {ASTNode} radix - A node of radix to check.
  48. * @returns {boolean} `true` if the node is valid.
  49. */
  50. function isValidRadix(radix) {
  51. return !(
  52. (radix.type === "Literal" && typeof radix.value !== "number") ||
  53. (radix.type === "Identifier" && radix.name === "undefined")
  54. );
  55. }
  56. /**
  57. * Checks whether a given node is a default value of radix or not.
  58. *
  59. * @param {ASTNode} radix - A node of radix to check.
  60. * @returns {boolean} `true` if the node is the literal node of `10`.
  61. */
  62. function isDefaultRadix(radix) {
  63. return radix.type === "Literal" && radix.value === 10;
  64. }
  65. //------------------------------------------------------------------------------
  66. // Rule Definition
  67. //------------------------------------------------------------------------------
  68. module.exports = {
  69. meta: {
  70. type: "suggestion",
  71. docs: {
  72. description: "enforce the consistent use of the radix argument when using `parseInt()`",
  73. category: "Best Practices",
  74. recommended: false,
  75. url: "https://eslint.org/docs/rules/radix"
  76. },
  77. schema: [
  78. {
  79. enum: ["always", "as-needed"]
  80. }
  81. ]
  82. },
  83. create(context) {
  84. const mode = context.options[0] || MODE_ALWAYS;
  85. /**
  86. * Checks the arguments of a given CallExpression node and reports it if it
  87. * offends this rule.
  88. *
  89. * @param {ASTNode} node - A CallExpression node to check.
  90. * @returns {void}
  91. */
  92. function checkArguments(node) {
  93. const args = node.arguments;
  94. switch (args.length) {
  95. case 0:
  96. context.report({
  97. node,
  98. message: "Missing parameters."
  99. });
  100. break;
  101. case 1:
  102. if (mode === MODE_ALWAYS) {
  103. context.report({
  104. node,
  105. message: "Missing radix parameter."
  106. });
  107. }
  108. break;
  109. default:
  110. if (mode === MODE_AS_NEEDED && isDefaultRadix(args[1])) {
  111. context.report({
  112. node,
  113. message: "Redundant radix parameter."
  114. });
  115. } else if (!isValidRadix(args[1])) {
  116. context.report({
  117. node,
  118. message: "Invalid radix parameter."
  119. });
  120. }
  121. break;
  122. }
  123. }
  124. return {
  125. "Program:exit"() {
  126. const scope = context.getScope();
  127. let variable;
  128. // Check `parseInt()`
  129. variable = astUtils.getVariableByName(scope, "parseInt");
  130. if (!isShadowed(variable)) {
  131. variable.references.forEach(reference => {
  132. const node = reference.identifier;
  133. if (astUtils.isCallee(node)) {
  134. checkArguments(node.parent);
  135. }
  136. });
  137. }
  138. // Check `Number.parseInt()`
  139. variable = astUtils.getVariableByName(scope, "Number");
  140. if (!isShadowed(variable)) {
  141. variable.references.forEach(reference => {
  142. const node = reference.identifier.parent;
  143. if (isParseIntMethod(node) && astUtils.isCallee(node)) {
  144. checkArguments(node.parent);
  145. }
  146. });
  147. }
  148. }
  149. };
  150. }
  151. };