]>
Commit | Line | Data |
---|---|---|
eb39fafa DC |
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 | ||
7 | "use strict"; | |
8 | ||
9 | //------------------------------------------------------------------------------ | |
10 | // Rule Definition | |
11 | //------------------------------------------------------------------------------ | |
12 | ||
13 | module.exports = { | |
14 | meta: { | |
15 | type: "suggestion", | |
16 | ||
17 | docs: { | |
18 | description: "enforce minimum and maximum identifier lengths", | |
19 | category: "Stylistic Issues", | |
20 | recommended: false, | |
21 | url: "https://eslint.org/docs/rules/id-length" | |
22 | }, | |
23 | ||
24 | schema: [ | |
25 | { | |
26 | type: "object", | |
27 | properties: { | |
28 | min: { | |
29 | type: "integer", | |
30 | default: 2 | |
31 | }, | |
32 | max: { | |
33 | type: "integer" | |
34 | }, | |
35 | exceptions: { | |
36 | type: "array", | |
37 | uniqueItems: true, | |
38 | items: { | |
39 | type: "string" | |
40 | } | |
41 | }, | |
42 | properties: { | |
43 | enum: ["always", "never"] | |
44 | } | |
45 | }, | |
46 | additionalProperties: false | |
47 | } | |
48 | ], | |
49 | messages: { | |
50 | tooShort: "Identifier name '{{name}}' is too short (< {{min}}).", | |
51 | tooLong: "Identifier name '{{name}}' is too long (> {{max}})." | |
52 | } | |
53 | }, | |
54 | ||
55 | create(context) { | |
56 | const options = context.options[0] || {}; | |
57 | const minLength = typeof options.min !== "undefined" ? options.min : 2; | |
58 | const maxLength = typeof options.max !== "undefined" ? options.max : Infinity; | |
59 | const properties = options.properties !== "never"; | |
60 | const exceptions = (options.exceptions ? options.exceptions : []) | |
61 | .reduce((obj, item) => { | |
62 | obj[item] = true; | |
63 | ||
64 | return obj; | |
65 | }, {}); | |
66 | const reportedNode = new Set(); | |
67 | ||
68 | const SUPPORTED_EXPRESSIONS = { | |
69 | MemberExpression: properties && function(parent) { | |
70 | return !parent.computed && ( | |
71 | ||
72 | // regular property assignment | |
73 | (parent.parent.left === parent && parent.parent.type === "AssignmentExpression" || | |
74 | ||
75 | // or the last identifier in an ObjectPattern destructuring | |
76 | parent.parent.type === "Property" && parent.parent.value === parent && | |
77 | parent.parent.parent.type === "ObjectPattern" && parent.parent.parent.parent.left === parent.parent.parent) | |
78 | ); | |
79 | }, | |
80 | AssignmentPattern(parent, node) { | |
81 | return parent.left === node; | |
82 | }, | |
83 | VariableDeclarator(parent, node) { | |
84 | return parent.id === node; | |
85 | }, | |
86 | Property(parent, node) { | |
87 | ||
88 | if (parent.parent.type === "ObjectPattern") { | |
89 | return ( | |
90 | parent.value !== parent.key && parent.value === node || | |
91 | parent.value === parent.key && parent.key === node && properties | |
92 | ); | |
93 | } | |
94 | return properties && !parent.computed && parent.key === node; | |
95 | }, | |
96 | ImportDefaultSpecifier: true, | |
97 | RestElement: true, | |
98 | FunctionExpression: true, | |
99 | ArrowFunctionExpression: true, | |
100 | ClassDeclaration: true, | |
101 | FunctionDeclaration: true, | |
102 | MethodDefinition: true, | |
103 | CatchClause: true, | |
104 | ArrayPattern: true | |
105 | }; | |
106 | ||
107 | return { | |
108 | Identifier(node) { | |
109 | const name = node.name; | |
110 | const parent = node.parent; | |
111 | ||
112 | const isShort = name.length < minLength; | |
113 | const isLong = name.length > maxLength; | |
114 | ||
115 | if (!(isShort || isLong) || exceptions[name]) { | |
116 | return; // Nothing to report | |
117 | } | |
118 | ||
119 | const isValidExpression = SUPPORTED_EXPRESSIONS[parent.type]; | |
120 | ||
121 | if (isValidExpression && !reportedNode.has(node) && (isValidExpression === true || isValidExpression(parent, node))) { | |
122 | reportedNode.add(node); | |
123 | context.report({ | |
124 | node, | |
125 | messageId: isShort ? "tooShort" : "tooLong", | |
126 | data: { name, min: minLength, max: maxLength } | |
127 | }); | |
128 | } | |
129 | } | |
130 | }; | |
131 | } | |
132 | }; |