|                                                                                                                                                                                               |  | /** * @fileoverview Rule to warn when a function expression does not have a name. * @author Kyle T. Nunery */
"use strict";
//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------
const astUtils = require("./utils/ast-utils");
/** * Checks whether or not a given variable is a function name. * @param {eslint-scope.Variable} variable A variable to check. * @returns {boolean} `true` if the variable is a function name. */function isFunctionName(variable) {    return variable && variable.defs[0].type === "FunctionName";}
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */module.exports = {    meta: {        type: "suggestion",
        docs: {            description: "Require or disallow named `function` expressions",            recommended: false,            url: "https://eslint.org/docs/latest/rules/func-names"        },
        schema: {            definitions: {                value: {                    enum: [                        "always",                        "as-needed",                        "never"                    ]                }            },            items: [                {                    $ref: "#/definitions/value"                },                {                    type: "object",                    properties: {                        generators: {                            $ref: "#/definitions/value"                        }                    },                    additionalProperties: false                }            ]        },
        messages: {            unnamed: "Unexpected unnamed {{name}}.",            named: "Unexpected named {{name}}."        }    },
    create(context) {
        const sourceCode = context.sourceCode;
        /**         * Returns the config option for the given node.         * @param {ASTNode} node A node to get the config for.         * @returns {string} The config option.         */        function getConfigForNode(node) {            if (                node.generator &&                context.options.length > 1 &&                context.options[1].generators            ) {                return context.options[1].generators;            }
            return context.options[0] || "always";        }
        /**         * Determines whether the current FunctionExpression node is a get, set, or         * shorthand method in an object literal or a class.         * @param {ASTNode} node A node to check.         * @returns {boolean} True if the node is a get, set, or shorthand method.         */        function isObjectOrClassMethod(node) {            const parent = node.parent;
            return (parent.type === "MethodDefinition" || (                parent.type === "Property" && (                    parent.method ||                    parent.kind === "get" ||                    parent.kind === "set"                )            ));        }
        /**         * Determines whether the current FunctionExpression node has a name that would be         * inferred from context in a conforming ES6 environment.         * @param {ASTNode} node A node to check.         * @returns {boolean} True if the node would have a name assigned automatically.         */        function hasInferredName(node) {            const parent = node.parent;
            return isObjectOrClassMethod(node) ||                (parent.type === "VariableDeclarator" && parent.id.type === "Identifier" && parent.init === node) ||                (parent.type === "Property" && parent.value === node) ||                (parent.type === "PropertyDefinition" && parent.value === node) ||                (parent.type === "AssignmentExpression" && parent.left.type === "Identifier" && parent.right === node) ||                (parent.type === "AssignmentPattern" && parent.left.type === "Identifier" && parent.right === node);        }
        /**         * Reports that an unnamed function should be named         * @param {ASTNode} node The node to report in the event of an error.         * @returns {void}         */        function reportUnexpectedUnnamedFunction(node) {            context.report({                node,                messageId: "unnamed",                loc: astUtils.getFunctionHeadLoc(node, sourceCode),                data: { name: astUtils.getFunctionNameWithKind(node) }            });        }
        /**         * Reports that a named function should be unnamed         * @param {ASTNode} node The node to report in the event of an error.         * @returns {void}         */        function reportUnexpectedNamedFunction(node) {            context.report({                node,                messageId: "named",                loc: astUtils.getFunctionHeadLoc(node, sourceCode),                data: { name: astUtils.getFunctionNameWithKind(node) }            });        }
        /**         * The listener for function nodes.         * @param {ASTNode} node function node         * @returns {void}         */        function handleFunction(node) {
            // Skip recursive functions.
            const nameVar = sourceCode.getDeclaredVariables(node)[0];
            if (isFunctionName(nameVar) && nameVar.references.length > 0) {                return;            }
            const hasName = Boolean(node.id && node.id.name);            const config = getConfigForNode(node);
            if (config === "never") {                if (hasName && node.type !== "FunctionDeclaration") {                    reportUnexpectedNamedFunction(node);                }            } else if (config === "as-needed") {                if (!hasName && !hasInferredName(node)) {                    reportUnexpectedUnnamedFunction(node);                }            } else {                if (!hasName && !isObjectOrClassMethod(node)) {                    reportUnexpectedUnnamedFunction(node);                }            }        }
        return {            "FunctionExpression:exit": handleFunction,            "ExportDefaultDeclaration > FunctionDeclaration": handleFunction        };    }};
 |