diff options
Diffstat (limited to 'tools/node_modules/eslint/lib/rules/func-names.js')
-rw-r--r-- | tools/node_modules/eslint/lib/rules/func-names.js | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/tools/node_modules/eslint/lib/rules/func-names.js b/tools/node_modules/eslint/lib/rules/func-names.js new file mode 100644 index 0000000000..848ce97574 --- /dev/null +++ b/tools/node_modules/eslint/lib/rules/func-names.js @@ -0,0 +1,114 @@ +/** + * @fileoverview Rule to warn when a function expression does not have a name. + * @author Kyle T. Nunery + */ + +"use strict"; + +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const astUtils = require("../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 +//------------------------------------------------------------------------------ + +module.exports = { + meta: { + docs: { + description: "require or disallow named `function` expressions", + category: "Stylistic Issues", + recommended: false + }, + + schema: [ + { + enum: ["always", "as-needed", "never"] + } + ] + }, + + create(context) { + const never = context.options[0] === "never"; + const asNeeded = context.options[0] === "as-needed"; + + /** + * 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 === "AssignmentExpression" && parent.left.type === "Identifier" && parent.right === node) || + (parent.type === "ExportDefaultDeclaration" && parent.declaration === node) || + (parent.type === "AssignmentPattern" && parent.right === node); + } + + return { + "FunctionExpression:exit"(node) { + + // Skip recursive functions. + const nameVar = context.getDeclaredVariables(node)[0]; + + if (isFunctionName(nameVar) && nameVar.references.length > 0) { + return; + } + + const hasName = Boolean(node.id && node.id.name); + const name = astUtils.getFunctionNameWithKind(node); + + if (never) { + if (hasName) { + context.report({ + node, + message: "Unexpected named {{name}}.", + data: { name } + }); + } + } else { + if (!hasName && (asNeeded ? !hasInferredName(node) : !isObjectOrClassMethod(node))) { + context.report({ + node, + message: "Unexpected unnamed {{name}}.", + data: { name } + }); + } + } + } + }; + } +}; |