max-params.js 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. /**
  2. * @fileoverview Rule to flag when a function has too many parameters
  3. * @author Ilya Volodin
  4. */
  5. "use strict";
  6. //------------------------------------------------------------------------------
  7. // Requirements
  8. //------------------------------------------------------------------------------
  9. const astUtils = require("./utils/ast-utils");
  10. const { upperCaseFirst } = require("../shared/string-utils");
  11. //------------------------------------------------------------------------------
  12. // Rule Definition
  13. //------------------------------------------------------------------------------
  14. /** @type {import('../types').Rule.RuleModule} */
  15. module.exports = {
  16. meta: {
  17. type: "suggestion",
  18. dialects: ["typescript", "javascript"],
  19. language: "javascript",
  20. docs: {
  21. description:
  22. "Enforce a maximum number of parameters in function definitions",
  23. recommended: false,
  24. url: "https://eslint.org/docs/latest/rules/max-params",
  25. },
  26. schema: [
  27. {
  28. oneOf: [
  29. {
  30. type: "integer",
  31. minimum: 0,
  32. },
  33. {
  34. type: "object",
  35. properties: {
  36. maximum: {
  37. type: "integer",
  38. minimum: 0,
  39. },
  40. max: {
  41. type: "integer",
  42. minimum: 0,
  43. },
  44. countVoidThis: {
  45. type: "boolean",
  46. description:
  47. "Whether to count a `this` declaration when the type is `void`.",
  48. },
  49. },
  50. additionalProperties: false,
  51. },
  52. ],
  53. },
  54. ],
  55. messages: {
  56. exceed: "{{name}} has too many parameters ({{count}}). Maximum allowed is {{max}}.",
  57. },
  58. },
  59. create(context) {
  60. const sourceCode = context.sourceCode;
  61. const option = context.options[0];
  62. let numParams = 3;
  63. let countVoidThis = false;
  64. if (typeof option === "object") {
  65. if (
  66. Object.hasOwn(option, "maximum") ||
  67. Object.hasOwn(option, "max")
  68. ) {
  69. numParams = option.maximum || option.max;
  70. }
  71. countVoidThis = option.countVoidThis;
  72. }
  73. if (typeof option === "number") {
  74. numParams = option;
  75. }
  76. /**
  77. * Checks a function to see if it has too many parameters.
  78. * @param {ASTNode} node The node to check.
  79. * @returns {void}
  80. * @private
  81. */
  82. function checkFunction(node) {
  83. const hasVoidThisParam =
  84. node.params.length > 0 &&
  85. node.params[0].type === "Identifier" &&
  86. node.params[0].name === "this" &&
  87. node.params[0].typeAnnotation?.typeAnnotation.type ===
  88. "TSVoidKeyword";
  89. const effectiveParamCount =
  90. hasVoidThisParam && !countVoidThis
  91. ? node.params.length - 1
  92. : node.params.length;
  93. if (effectiveParamCount > numParams) {
  94. context.report({
  95. loc: astUtils.getFunctionHeadLoc(node, sourceCode),
  96. node,
  97. messageId: "exceed",
  98. data: {
  99. name: upperCaseFirst(
  100. astUtils.getFunctionNameWithKind(node),
  101. ),
  102. count: effectiveParamCount,
  103. max: numParams,
  104. },
  105. });
  106. }
  107. }
  108. return {
  109. FunctionDeclaration: checkFunction,
  110. ArrowFunctionExpression: checkFunction,
  111. FunctionExpression: checkFunction,
  112. TSDeclareFunction: checkFunction,
  113. TSFunctionType: checkFunction,
  114. };
  115. },
  116. };