id-length.js 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. /**
  2. * @fileoverview Rule that warns when identifier names are shorter or longer
  3. * than the values provided in configuration.
  4. * @author Burak Yigit Kaya aka BYK
  5. */
  6. "use strict";
  7. //------------------------------------------------------------------------------
  8. // Rule Definition
  9. //------------------------------------------------------------------------------
  10. module.exports = {
  11. meta: {
  12. type: "suggestion",
  13. docs: {
  14. description: "enforce minimum and maximum identifier lengths",
  15. category: "Stylistic Issues",
  16. recommended: false,
  17. url: "https://eslint.org/docs/rules/id-length"
  18. },
  19. schema: [
  20. {
  21. type: "object",
  22. properties: {
  23. min: {
  24. type: "integer",
  25. default: 2
  26. },
  27. max: {
  28. type: "integer"
  29. },
  30. exceptions: {
  31. type: "array",
  32. uniqueItems: true,
  33. items: {
  34. type: "string"
  35. }
  36. },
  37. properties: {
  38. enum: ["always", "never"]
  39. }
  40. },
  41. additionalProperties: false
  42. }
  43. ],
  44. messages: {
  45. tooShort: "Identifier name '{{name}}' is too short (< {{min}}).",
  46. tooLong: "Identifier name '{{name}}' is too long (> {{max}})."
  47. }
  48. },
  49. create(context) {
  50. const options = context.options[0] || {};
  51. const minLength = typeof options.min !== "undefined" ? options.min : 2;
  52. const maxLength = typeof options.max !== "undefined" ? options.max : Infinity;
  53. const properties = options.properties !== "never";
  54. const exceptions = (options.exceptions ? options.exceptions : [])
  55. .reduce((obj, item) => {
  56. obj[item] = true;
  57. return obj;
  58. }, {});
  59. const SUPPORTED_EXPRESSIONS = {
  60. MemberExpression: properties && function(parent) {
  61. return !parent.computed && (
  62. // regular property assignment
  63. (parent.parent.left === parent && parent.parent.type === "AssignmentExpression" ||
  64. // or the last identifier in an ObjectPattern destructuring
  65. parent.parent.type === "Property" && parent.parent.value === parent &&
  66. parent.parent.parent.type === "ObjectPattern" && parent.parent.parent.parent.left === parent.parent.parent)
  67. );
  68. },
  69. AssignmentPattern(parent, node) {
  70. return parent.left === node;
  71. },
  72. VariableDeclarator(parent, node) {
  73. return parent.id === node;
  74. },
  75. Property: properties && function(parent, node) {
  76. return parent.key === node;
  77. },
  78. ImportDefaultSpecifier: true,
  79. RestElement: true,
  80. FunctionExpression: true,
  81. ArrowFunctionExpression: true,
  82. ClassDeclaration: true,
  83. FunctionDeclaration: true,
  84. MethodDefinition: true,
  85. CatchClause: true
  86. };
  87. return {
  88. Identifier(node) {
  89. const name = node.name;
  90. const parent = node.parent;
  91. const isShort = name.length < minLength;
  92. const isLong = name.length > maxLength;
  93. if (!(isShort || isLong) || exceptions[name]) {
  94. return; // Nothing to report
  95. }
  96. const isValidExpression = SUPPORTED_EXPRESSIONS[parent.type];
  97. if (isValidExpression && (isValidExpression === true || isValidExpression(parent, node))) {
  98. context.report({
  99. node,
  100. messageId: isShort ? "tooShort" : "tooLong",
  101. data: { name, min: minLength, max: maxLength }
  102. });
  103. }
  104. }
  105. };
  106. }
  107. };