]> git.proxmox.com Git - pve-eslint.git/blame - eslint/lib/rules/arrow-parens.js
update to 7.1.0 sources
[pve-eslint.git] / eslint / lib / rules / arrow-parens.js
CommitLineData
eb39fafa
DC
1/**
2 * @fileoverview Rule to require parens in arrow function arguments.
3 * @author Jxck
4 */
5"use strict";
6
7//------------------------------------------------------------------------------
8// Requirements
9//------------------------------------------------------------------------------
10
11const astUtils = require("./utils/ast-utils");
12
13//------------------------------------------------------------------------------
14// Helpers
15//------------------------------------------------------------------------------
16
17/**
18 * Get location should be reported by AST node.
19 * @param {ASTNode} node AST Node.
20 * @returns {Location} Location information.
21 */
22function getLocation(node) {
23 return {
24 start: node.params[0].loc.start,
25 end: node.params[node.params.length - 1].loc.end
26 };
27}
28
29//------------------------------------------------------------------------------
30// Rule Definition
31//------------------------------------------------------------------------------
32
33module.exports = {
34 meta: {
35 type: "layout",
36
37 docs: {
38 description: "require parentheses around arrow function arguments",
39 category: "ECMAScript 6",
40 recommended: false,
41 url: "https://eslint.org/docs/rules/arrow-parens"
42 },
43
44 fixable: "code",
45
46 schema: [
47 {
48 enum: ["always", "as-needed"]
49 },
50 {
51 type: "object",
52 properties: {
53 requireForBlockBody: {
54 type: "boolean",
55 default: false
56 }
57 },
58 additionalProperties: false
59 }
60 ],
61
62 messages: {
63 unexpectedParens: "Unexpected parentheses around single function argument.",
64 expectedParens: "Expected parentheses around arrow function argument.",
65
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."
68 }
69 },
70
71 create(context) {
72 const asNeeded = context.options[0] === "as-needed";
73 const requireForBlockBody = asNeeded && context.options[1] && context.options[1].requireForBlockBody === true;
74
75 const sourceCode = context.getSourceCode();
76
77 /**
78 * Determines whether a arrow function argument end with `)`
79 * @param {ASTNode} node The arrow function node.
80 * @returns {void}
81 */
82 function parens(node) {
83 const isAsync = node.async;
84 const firstTokenOfParam = sourceCode.getFirstToken(node, isAsync ? 1 : 0);
85
86 /**
87 * Remove the parenthesis around a parameter
88 * @param {Fixer} fixer Fixer
89 * @returns {string} fixed parameter
90 */
91 function fixParamsWithParenthesis(fixer) {
92 const paramToken = sourceCode.getTokenAfter(firstTokenOfParam);
93
94 /*
95 * ES8 allows Trailing commas in function parameter lists and calls
96 * https://github.com/eslint/eslint/issues/8834
97 */
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]);
101
102 return fixer.replaceTextRange([
103 firstTokenOfParam.range[0],
104 closingParenToken.range[1]
105 ], `${shouldAddSpaceForAsync ? " " : ""}${paramToken.value}`);
106 }
107
ebb53d86
TL
108 /**
109 * Checks whether there are comments inside the params or not.
110 * @returns {boolean} `true` if there are comments inside of parens, else `false`
111 */
112 function hasCommentsInParens() {
113 if (astUtils.isOpeningParenToken(firstTokenOfParam)) {
114 const closingParenToken = sourceCode.getTokenAfter(node.params[0], astUtils.isClosingParenToken);
115
116 return closingParenToken && sourceCode.commentsExistBetween(firstTokenOfParam, closingParenToken);
117 }
118 return false;
119
120 }
121
122 if (hasCommentsInParens()) {
123 return;
124 }
125
eb39fafa
DC
126 // "as-needed", { "requireForBlockBody": true }: x => x
127 if (
128 requireForBlockBody &&
eb39fafa
DC
129 node.params[0].type === "Identifier" &&
130 !node.params[0].typeAnnotation &&
131 node.body.type !== "BlockStatement" &&
132 !node.returnType
133 ) {
134 if (astUtils.isOpeningParenToken(firstTokenOfParam)) {
135 context.report({
136 node,
137 messageId: "unexpectedParensInline",
138 loc: getLocation(node),
139 fix: fixParamsWithParenthesis
140 });
141 }
142 return;
143 }
144
145 if (
146 requireForBlockBody &&
147 node.body.type === "BlockStatement"
148 ) {
149 if (!astUtils.isOpeningParenToken(firstTokenOfParam)) {
150 context.report({
151 node,
152 messageId: "expectedParensBlock",
153 loc: getLocation(node),
154 fix(fixer) {
155 return fixer.replaceText(firstTokenOfParam, `(${firstTokenOfParam.value})`);
156 }
157 });
158 }
159 return;
160 }
161
162 // "as-needed": x => x
163 if (asNeeded &&
eb39fafa
DC
164 node.params[0].type === "Identifier" &&
165 !node.params[0].typeAnnotation &&
166 !node.returnType
167 ) {
168 if (astUtils.isOpeningParenToken(firstTokenOfParam)) {
169 context.report({
170 node,
171 messageId: "unexpectedParens",
172 loc: getLocation(node),
173 fix: fixParamsWithParenthesis
174 });
175 }
176 return;
177 }
178
179 if (firstTokenOfParam.type === "Identifier") {
180 const after = sourceCode.getTokenAfter(firstTokenOfParam);
181
182 // (x) => x
183 if (after.value !== ")") {
184 context.report({
185 node,
186 messageId: "expectedParens",
187 loc: getLocation(node),
188 fix(fixer) {
189 return fixer.replaceText(firstTokenOfParam, `(${firstTokenOfParam.value})`);
190 }
191 });
192 }
193 }
194 }
195
196 return {
ebb53d86 197 "ArrowFunctionExpression[params.length=1]": parens
eb39fafa
DC
198 };
199 }
200};