source: imaps-frontend/node_modules/eslint/lib/rules/id-length.js

main
Last change on this file was d565449, checked in by stefan toskovski <stefantoska84@…>, 4 weeks ago

Update repo after prototype presentation

  • Property mode set to 100644
File size: 6.5 KB
Line 
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// Requirements
11//------------------------------------------------------------------------------
12
13const { getGraphemeCount } = require("../shared/string-utils");
14
15//------------------------------------------------------------------------------
16// Rule Definition
17//------------------------------------------------------------------------------
18
19/** @type {import('../shared/types').Rule} */
20module.exports = {
21 meta: {
22 type: "suggestion",
23
24 docs: {
25 description: "Enforce minimum and maximum identifier lengths",
26 recommended: false,
27 url: "https://eslint.org/docs/latest/rules/id-length"
28 },
29
30 schema: [
31 {
32 type: "object",
33 properties: {
34 min: {
35 type: "integer",
36 default: 2
37 },
38 max: {
39 type: "integer"
40 },
41 exceptions: {
42 type: "array",
43 uniqueItems: true,
44 items: {
45 type: "string"
46 }
47 },
48 exceptionPatterns: {
49 type: "array",
50 uniqueItems: true,
51 items: {
52 type: "string"
53 }
54 },
55 properties: {
56 enum: ["always", "never"]
57 }
58 },
59 additionalProperties: false
60 }
61 ],
62 messages: {
63 tooShort: "Identifier name '{{name}}' is too short (< {{min}}).",
64 tooShortPrivate: "Identifier name '#{{name}}' is too short (< {{min}}).",
65 tooLong: "Identifier name '{{name}}' is too long (> {{max}}).",
66 tooLongPrivate: "Identifier name #'{{name}}' is too long (> {{max}})."
67 }
68 },
69
70 create(context) {
71 const options = context.options[0] || {};
72 const minLength = typeof options.min !== "undefined" ? options.min : 2;
73 const maxLength = typeof options.max !== "undefined" ? options.max : Infinity;
74 const properties = options.properties !== "never";
75 const exceptions = new Set(options.exceptions);
76 const exceptionPatterns = (options.exceptionPatterns || []).map(pattern => new RegExp(pattern, "u"));
77 const reportedNodes = new Set();
78
79 /**
80 * Checks if a string matches the provided exception patterns
81 * @param {string} name The string to check.
82 * @returns {boolean} if the string is a match
83 * @private
84 */
85 function matchesExceptionPattern(name) {
86 return exceptionPatterns.some(pattern => pattern.test(name));
87 }
88
89 const SUPPORTED_EXPRESSIONS = {
90 MemberExpression: properties && function(parent) {
91 return !parent.computed && (
92
93 // regular property assignment
94 (parent.parent.left === parent && parent.parent.type === "AssignmentExpression" ||
95
96 // or the last identifier in an ObjectPattern destructuring
97 parent.parent.type === "Property" && parent.parent.value === parent &&
98 parent.parent.parent.type === "ObjectPattern" && parent.parent.parent.parent.left === parent.parent.parent)
99 );
100 },
101 AssignmentPattern(parent, node) {
102 return parent.left === node;
103 },
104 VariableDeclarator(parent, node) {
105 return parent.id === node;
106 },
107 Property(parent, node) {
108
109 if (parent.parent.type === "ObjectPattern") {
110 const isKeyAndValueSame = parent.value.name === parent.key.name;
111
112 return (
113 !isKeyAndValueSame && parent.value === node ||
114 isKeyAndValueSame && parent.key === node && properties
115 );
116 }
117 return properties && !parent.computed && parent.key.name === node.name;
118 },
119 ImportDefaultSpecifier: true,
120 RestElement: true,
121 FunctionExpression: true,
122 ArrowFunctionExpression: true,
123 ClassDeclaration: true,
124 FunctionDeclaration: true,
125 MethodDefinition: true,
126 PropertyDefinition: true,
127 CatchClause: true,
128 ArrayPattern: true
129 };
130
131 return {
132 [[
133 "Identifier",
134 "PrivateIdentifier"
135 ]](node) {
136 const name = node.name;
137 const parent = node.parent;
138
139 const nameLength = getGraphemeCount(name);
140
141 const isShort = nameLength < minLength;
142 const isLong = nameLength > maxLength;
143
144 if (!(isShort || isLong) || exceptions.has(name) || matchesExceptionPattern(name)) {
145 return; // Nothing to report
146 }
147
148 const isValidExpression = SUPPORTED_EXPRESSIONS[parent.type];
149
150 /*
151 * We used the range instead of the node because it's possible
152 * for the same identifier to be represented by two different
153 * nodes, with the most clear example being shorthand properties:
154 * { foo }
155 * In this case, "foo" is represented by one node for the name
156 * and one for the value. The only way to know they are the same
157 * is to look at the range.
158 */
159 if (isValidExpression && !reportedNodes.has(node.range.toString()) && (isValidExpression === true || isValidExpression(parent, node))) {
160 reportedNodes.add(node.range.toString());
161
162 let messageId = isShort ? "tooShort" : "tooLong";
163
164 if (node.type === "PrivateIdentifier") {
165 messageId += "Private";
166 }
167
168 context.report({
169 node,
170 messageId,
171 data: { name, min: minLength, max: maxLength }
172 });
173 }
174 }
175 };
176 }
177};
Note: See TracBrowser for help on using the repository browser.