| /** | |
|  * @fileoverview Rule to validate spacing before function paren. | |
|  * @author Mathias Schreck <https://github.com/lo1tuma> | |
|  * @deprecated in ESLint v8.53.0 | |
|  */ | |
| "use strict"; | |
| 
 | |
| //------------------------------------------------------------------------------ | |
| // Requirements | |
| //------------------------------------------------------------------------------ | |
|  | |
| const astUtils = require("./utils/ast-utils"); | |
| 
 | |
| //------------------------------------------------------------------------------ | |
| // Rule Definition | |
| //------------------------------------------------------------------------------ | |
|  | |
| /** @type {import('../shared/types').Rule} */ | |
| module.exports = { | |
|     meta: { | |
|         deprecated: true, | |
|         replacedBy: [], | |
|         type: "layout", | |
| 
 | |
|         docs: { | |
|             description: "Enforce consistent spacing before `function` definition opening parenthesis", | |
|             recommended: false, | |
|             url: "https://eslint.org/docs/latest/rules/space-before-function-paren" | |
|         }, | |
| 
 | |
|         fixable: "whitespace", | |
| 
 | |
|         schema: [ | |
|             { | |
|                 oneOf: [ | |
|                     { | |
|                         enum: ["always", "never"] | |
|                     }, | |
|                     { | |
|                         type: "object", | |
|                         properties: { | |
|                             anonymous: { | |
|                                 enum: ["always", "never", "ignore"] | |
|                             }, | |
|                             named: { | |
|                                 enum: ["always", "never", "ignore"] | |
|                             }, | |
|                             asyncArrow: { | |
|                                 enum: ["always", "never", "ignore"] | |
|                             } | |
|                         }, | |
|                         additionalProperties: false | |
|                     } | |
|                 ] | |
|             } | |
|         ], | |
| 
 | |
|         messages: { | |
|             unexpectedSpace: "Unexpected space before function parentheses.", | |
|             missingSpace: "Missing space before function parentheses." | |
|         } | |
|     }, | |
| 
 | |
|     create(context) { | |
|         const sourceCode = context.sourceCode; | |
|         const baseConfig = typeof context.options[0] === "string" ? context.options[0] : "always"; | |
|         const overrideConfig = typeof context.options[0] === "object" ? context.options[0] : {}; | |
| 
 | |
|         /** | |
|          * Determines whether a function has a name. | |
|          * @param {ASTNode} node The function node. | |
|          * @returns {boolean} Whether the function has a name. | |
|          */ | |
|         function isNamedFunction(node) { | |
|             if (node.id) { | |
|                 return true; | |
|             } | |
| 
 | |
|             const parent = node.parent; | |
| 
 | |
|             return parent.type === "MethodDefinition" || | |
|                 (parent.type === "Property" && | |
|                     ( | |
|                         parent.kind === "get" || | |
|                         parent.kind === "set" || | |
|                         parent.method | |
|                     ) | |
|                 ); | |
|         } | |
| 
 | |
|         /** | |
|          * Gets the config for a given function | |
|          * @param {ASTNode} node The function node | |
|          * @returns {string} "always", "never", or "ignore" | |
|          */ | |
|         function getConfigForFunction(node) { | |
|             if (node.type === "ArrowFunctionExpression") { | |
| 
 | |
|                 // Always ignore non-async functions and arrow functions without parens, e.g. async foo => bar | |
|                 if (node.async && astUtils.isOpeningParenToken(sourceCode.getFirstToken(node, { skip: 1 }))) { | |
|                     return overrideConfig.asyncArrow || baseConfig; | |
|                 } | |
|             } else if (isNamedFunction(node)) { | |
|                 return overrideConfig.named || baseConfig; | |
| 
 | |
|             // `generator-star-spacing` should warn anonymous generators. E.g. `function* () {}` | |
|             } else if (!node.generator) { | |
|                 return overrideConfig.anonymous || baseConfig; | |
|             } | |
| 
 | |
|             return "ignore"; | |
|         } | |
| 
 | |
|         /** | |
|          * Checks the parens of a function node | |
|          * @param {ASTNode} node A function node | |
|          * @returns {void} | |
|          */ | |
|         function checkFunction(node) { | |
|             const functionConfig = getConfigForFunction(node); | |
| 
 | |
|             if (functionConfig === "ignore") { | |
|                 return; | |
|             } | |
| 
 | |
|             const rightToken = sourceCode.getFirstToken(node, astUtils.isOpeningParenToken); | |
|             const leftToken = sourceCode.getTokenBefore(rightToken); | |
|             const hasSpacing = sourceCode.isSpaceBetweenTokens(leftToken, rightToken); | |
| 
 | |
|             if (hasSpacing && functionConfig === "never") { | |
|                 context.report({ | |
|                     node, | |
|                     loc: { | |
|                         start: leftToken.loc.end, | |
|                         end: rightToken.loc.start | |
|                     }, | |
|                     messageId: "unexpectedSpace", | |
|                     fix(fixer) { | |
|                         const comments = sourceCode.getCommentsBefore(rightToken); | |
| 
 | |
|                         // Don't fix anything if there's a single line comment between the left and the right token | |
|                         if (comments.some(comment => comment.type === "Line")) { | |
|                             return null; | |
|                         } | |
|                         return fixer.replaceTextRange( | |
|                             [leftToken.range[1], rightToken.range[0]], | |
|                             comments.reduce((text, comment) => text + sourceCode.getText(comment), "") | |
|                         ); | |
|                     } | |
|                 }); | |
|             } else if (!hasSpacing && functionConfig === "always") { | |
|                 context.report({ | |
|                     node, | |
|                     loc: rightToken.loc, | |
|                     messageId: "missingSpace", | |
|                     fix: fixer => fixer.insertTextAfter(leftToken, " ") | |
|                 }); | |
|             } | |
|         } | |
| 
 | |
|         return { | |
|             ArrowFunctionExpression: checkFunction, | |
|             FunctionDeclaration: checkFunction, | |
|             FunctionExpression: checkFunction | |
|         }; | |
|     } | |
| };
 |