| |
| |
| |
| |
| |
| "use strict"; |
|
|
| |
| |
| |
|
|
| const astUtils = require("./utils/ast-utils"); |
| const esutils = require("esutils"); |
|
|
| |
| |
| |
|
|
| |
| |
| |
| |
| |
| function isModuleExports(pattern) { |
| if ( |
| pattern.type === "MemberExpression" && |
| pattern.object.type === "Identifier" && |
| pattern.object.name === "module" |
| ) { |
| |
| if ( |
| pattern.property.type === "Identifier" && |
| pattern.property.name === "exports" |
| ) { |
| return true; |
| } |
|
|
| |
| if ( |
| pattern.property.type === "Literal" && |
| pattern.property.value === "exports" |
| ) { |
| return true; |
| } |
| } |
| return false; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| function isIdentifier(name, ecmaVersion) { |
| if (ecmaVersion >= 2015) { |
| return esutils.keyword.isIdentifierES6(name); |
| } |
| return esutils.keyword.isIdentifierES5(name); |
| } |
|
|
| |
| |
| |
|
|
| const alwaysOrNever = { enum: ["always", "never"] }; |
| const optionsObject = { |
| type: "object", |
| properties: { |
| considerPropertyDescriptor: { |
| type: "boolean", |
| }, |
| includeCommonJSModuleExports: { |
| type: "boolean", |
| }, |
| }, |
| additionalProperties: false, |
| }; |
|
|
| |
| module.exports = { |
| meta: { |
| type: "suggestion", |
|
|
| docs: { |
| description: |
| "Require function names to match the name of the variable or property to which they are assigned", |
| recommended: false, |
| frozen: true, |
| url: "https://eslint.org/docs/latest/rules/func-name-matching", |
| }, |
|
|
| schema: { |
| anyOf: [ |
| { |
| type: "array", |
| additionalItems: false, |
| items: [alwaysOrNever, optionsObject], |
| }, |
| { |
| type: "array", |
| additionalItems: false, |
| items: [optionsObject], |
| }, |
| ], |
| }, |
|
|
| messages: { |
| matchProperty: |
| "Function name `{{funcName}}` should match property name `{{name}}`.", |
| matchVariable: |
| "Function name `{{funcName}}` should match variable name `{{name}}`.", |
| notMatchProperty: |
| "Function name `{{funcName}}` should not match property name `{{name}}`.", |
| notMatchVariable: |
| "Function name `{{funcName}}` should not match variable name `{{name}}`.", |
| }, |
| }, |
|
|
| create(context) { |
| const options = |
| (typeof context.options[0] === "object" |
| ? context.options[0] |
| : context.options[1]) || {}; |
| const nameMatches = |
| typeof context.options[0] === "string" |
| ? context.options[0] |
| : "always"; |
| const considerPropertyDescriptor = options.considerPropertyDescriptor; |
| const includeModuleExports = options.includeCommonJSModuleExports; |
| const ecmaVersion = context.languageOptions.ecmaVersion; |
|
|
| |
| |
| |
| |
| |
| |
| |
| function isPropertyCall(objName, funcName, node) { |
| if (!node) { |
| return false; |
| } |
| return ( |
| node.type === "CallExpression" && |
| astUtils.isSpecificMemberAccess(node.callee, objName, funcName) |
| ); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| function shouldWarn(x, y) { |
| return ( |
| (nameMatches === "always" && x !== y) || |
| (nameMatches === "never" && x === y) |
| ); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| function report(node, name, funcName, isProp) { |
| let messageId; |
|
|
| if (nameMatches === "always" && isProp) { |
| messageId = "matchProperty"; |
| } else if (nameMatches === "always") { |
| messageId = "matchVariable"; |
| } else if (isProp) { |
| messageId = "notMatchProperty"; |
| } else { |
| messageId = "notMatchVariable"; |
| } |
| context.report({ |
| node, |
| messageId, |
| data: { |
| name, |
| funcName, |
| }, |
| }); |
| } |
|
|
| |
| |
| |
| |
| |
| function isStringLiteral(node) { |
| return node.type === "Literal" && typeof node.value === "string"; |
| } |
|
|
| |
| |
| |
|
|
| return { |
| VariableDeclarator(node) { |
| if ( |
| !node.init || |
| node.init.type !== "FunctionExpression" || |
| node.id.type !== "Identifier" |
| ) { |
| return; |
| } |
| if ( |
| node.init.id && |
| shouldWarn(node.id.name, node.init.id.name) |
| ) { |
| report(node, node.id.name, node.init.id.name, false); |
| } |
| }, |
|
|
| AssignmentExpression(node) { |
| if ( |
| node.right.type !== "FunctionExpression" || |
| (node.left.computed && |
| node.left.property.type !== "Literal") || |
| (!includeModuleExports && isModuleExports(node.left)) || |
| (node.left.type !== "Identifier" && |
| node.left.type !== "MemberExpression") |
| ) { |
| return; |
| } |
|
|
| const isProp = node.left.type === "MemberExpression"; |
| const name = isProp |
| ? astUtils.getStaticPropertyName(node.left) |
| : node.left.name; |
|
|
| if ( |
| node.right.id && |
| name && |
| isIdentifier(name) && |
| shouldWarn(name, node.right.id.name) |
| ) { |
| report(node, name, node.right.id.name, isProp); |
| } |
| }, |
|
|
| "Property, PropertyDefinition[value]"(node) { |
| if ( |
| !(node.value.type === "FunctionExpression" && node.value.id) |
| ) { |
| return; |
| } |
|
|
| if (node.key.type === "Identifier" && !node.computed) { |
| const functionName = node.value.id.name; |
| let propertyName = node.key.name; |
|
|
| if ( |
| considerPropertyDescriptor && |
| propertyName === "value" && |
| node.parent.type === "ObjectExpression" |
| ) { |
| if ( |
| isPropertyCall( |
| "Object", |
| "defineProperty", |
| node.parent.parent, |
| ) || |
| isPropertyCall( |
| "Reflect", |
| "defineProperty", |
| node.parent.parent, |
| ) |
| ) { |
| const property = node.parent.parent.arguments[1]; |
|
|
| if ( |
| isStringLiteral(property) && |
| shouldWarn(property.value, functionName) |
| ) { |
| report( |
| node, |
| property.value, |
| functionName, |
| true, |
| ); |
| } |
| } else if ( |
| isPropertyCall( |
| "Object", |
| "defineProperties", |
| node.parent.parent.parent.parent, |
| ) |
| ) { |
| propertyName = node.parent.parent.key.name; |
| if ( |
| !node.parent.parent.computed && |
| shouldWarn(propertyName, functionName) |
| ) { |
| report(node, propertyName, functionName, true); |
| } |
| } else if ( |
| isPropertyCall( |
| "Object", |
| "create", |
| node.parent.parent.parent.parent, |
| ) |
| ) { |
| propertyName = node.parent.parent.key.name; |
| if ( |
| !node.parent.parent.computed && |
| shouldWarn(propertyName, functionName) |
| ) { |
| report(node, propertyName, functionName, true); |
| } |
| } else if (shouldWarn(propertyName, functionName)) { |
| report(node, propertyName, functionName, true); |
| } |
| } else if (shouldWarn(propertyName, functionName)) { |
| report(node, propertyName, functionName, true); |
| } |
| return; |
| } |
|
|
| if ( |
| isStringLiteral(node.key) && |
| isIdentifier(node.key.value, ecmaVersion) && |
| shouldWarn(node.key.value, node.value.id.name) |
| ) { |
| report(node, node.key.value, node.value.id.name, true); |
| } |
| }, |
| }; |
| }, |
| }; |
|
|