2 * @fileoverview Rule to require parens in arrow function arguments.
7 //------------------------------------------------------------------------------
9 //------------------------------------------------------------------------------
11 const astUtils = require("./utils/ast-utils");
13 //------------------------------------------------------------------------------
15 //------------------------------------------------------------------------------
18 * Get location should be reported by AST node.
19 * @param {ASTNode} node AST Node.
20 * @returns {Location} Location information.
22 function getLocation(node) {
24 start: node.params[0].loc.start,
25 end: node.params[node.params.length - 1].loc.end
29 //------------------------------------------------------------------------------
31 //------------------------------------------------------------------------------
38 description: "require parentheses around arrow function arguments",
39 category: "ECMAScript 6",
41 url: "https://eslint.org/docs/rules/arrow-parens"
48 enum: ["always", "as-needed"]
53 requireForBlockBody: {
58 additionalProperties: false
63 unexpectedParens: "Unexpected parentheses around single function argument.",
64 expectedParens: "Expected parentheses around arrow function argument.",
66 unexpectedParensInline: "Unexpected parentheses around single function argument having a body with no curly braces.",
67 expectedParensBlock: "Expected parentheses around arrow function argument having a body with curly braces."
72 const asNeeded = context.options[0] === "as-needed";
73 const requireForBlockBody = asNeeded && context.options[1] && context.options[1].requireForBlockBody === true;
75 const sourceCode = context.getSourceCode();
78 * Determines whether a arrow function argument end with `)`
79 * @param {ASTNode} node The arrow function node.
82 function parens(node) {
83 const isAsync = node.async;
84 const firstTokenOfParam = sourceCode.getFirstToken(node, isAsync ? 1 : 0);
87 * Remove the parenthesis around a parameter
88 * @param {Fixer} fixer Fixer
89 * @returns {string} fixed parameter
91 function fixParamsWithParenthesis(fixer) {
92 const paramToken = sourceCode.getTokenAfter(firstTokenOfParam);
95 * ES8 allows Trailing commas in function parameter lists and calls
96 * https://github.com/eslint/eslint/issues/8834
98 const closingParenToken = sourceCode.getTokenAfter(paramToken, astUtils.isClosingParenToken);
99 const asyncToken = isAsync ? sourceCode.getTokenBefore(firstTokenOfParam) : null;
100 const shouldAddSpaceForAsync = asyncToken && (asyncToken.range[1] === firstTokenOfParam.range[0]);
102 return fixer.replaceTextRange([
103 firstTokenOfParam.range[0],
104 closingParenToken.range[1]
105 ], `${shouldAddSpaceForAsync ? " " : ""}${paramToken.value}`);
108 // "as-needed", { "requireForBlockBody": true }: x => x
110 requireForBlockBody &&
111 node.params.length === 1 &&
112 node.params[0].type === "Identifier" &&
113 !node.params[0].typeAnnotation &&
114 node.body.type !== "BlockStatement" &&
117 if (astUtils.isOpeningParenToken(firstTokenOfParam)) {
120 messageId: "unexpectedParensInline",
121 loc: getLocation(node),
122 fix: fixParamsWithParenthesis
129 requireForBlockBody &&
130 node.body.type === "BlockStatement"
132 if (!astUtils.isOpeningParenToken(firstTokenOfParam)) {
135 messageId: "expectedParensBlock",
136 loc: getLocation(node),
138 return fixer.replaceText(firstTokenOfParam, `(${firstTokenOfParam.value})`);
145 // "as-needed": x => x
147 node.params.length === 1 &&
148 node.params[0].type === "Identifier" &&
149 !node.params[0].typeAnnotation &&
152 if (astUtils.isOpeningParenToken(firstTokenOfParam)) {
155 messageId: "unexpectedParens",
156 loc: getLocation(node),
157 fix: fixParamsWithParenthesis
163 if (firstTokenOfParam.type === "Identifier") {
164 const after = sourceCode.getTokenAfter(firstTokenOfParam);
167 if (after.value !== ")") {
170 messageId: "expectedParens",
171 loc: getLocation(node),
173 return fixer.replaceText(firstTokenOfParam, `(${firstTokenOfParam.value})`);
181 ArrowFunctionExpression: parens