CoolFace
Apppublic

Umama-at-Bluchip/Quick-UI

sourceHugging Faceupdated 2y agoView on Hugging Face
0likes
id-length.js178 linesDownload Raw Back to rules
1/**2 * @fileoverview Rule that warns when identifier names are shorter or longer3 * than the values provided in configuration.4 * @author Burak Yigit Kaya aka BYK5 */6 7"use strict";8 9//------------------------------------------------------------------------------10// Requirements11//------------------------------------------------------------------------------12 13const { getGraphemeCount } = require("../shared/string-utils");14 15//------------------------------------------------------------------------------16// Rule Definition17//------------------------------------------------------------------------------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: 237                    },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: false60            }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 patterns81         * @param {string} name The string to check.82         * @returns {boolean} if the string is a match83         * @private84         */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 assignment94                    (parent.parent.left === parent && parent.parent.type === "AssignmentExpression" ||95 96                    // or the last identifier in an ObjectPattern destructuring97                    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 && properties115                    );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: true129        };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 report146                }147 148                const isValidExpression = SUPPORTED_EXPRESSIONS[parent.type];149 150                /*151                 * We used the range instead of the node because it's possible152                 * for the same identifier to be represented by two different153                 * nodes, with the most clear example being shorthand properties:154                 * { foo }155                 * In this case, "foo" is represented by one node for the name156                 * and one for the value. The only way to know they are the same157                 * 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};178