source: imaps-frontend/node_modules/eslint/lib/rules/function-paren-newline.js

main
Last change on this file was d565449, checked in by stefan toskovski <stefantoska84@…>, 4 weeks ago

Update repo after prototype presentation

  • Property mode set to 100644
File size: 11.6 KB
RevLine 
[d565449]1/**
2 * @fileoverview enforce consistent line breaks inside function parentheses
3 * @author Teddy Katz
4 * @deprecated in ESLint v8.53.0
5 */
6"use strict";
7
8//------------------------------------------------------------------------------
9// Requirements
10//------------------------------------------------------------------------------
11
12const astUtils = require("./utils/ast-utils");
13
14//------------------------------------------------------------------------------
15// Rule Definition
16//------------------------------------------------------------------------------
17
18/** @type {import('../shared/types').Rule} */
19module.exports = {
20 meta: {
21 deprecated: true,
22 replacedBy: [],
23 type: "layout",
24
25 docs: {
26 description: "Enforce consistent line breaks inside function parentheses",
27 recommended: false,
28 url: "https://eslint.org/docs/latest/rules/function-paren-newline"
29 },
30
31 fixable: "whitespace",
32
33 schema: [
34 {
35 oneOf: [
36 {
37 enum: ["always", "never", "consistent", "multiline", "multiline-arguments"]
38 },
39 {
40 type: "object",
41 properties: {
42 minItems: {
43 type: "integer",
44 minimum: 0
45 }
46 },
47 additionalProperties: false
48 }
49 ]
50 }
51 ],
52
53 messages: {
54 expectedBefore: "Expected newline before ')'.",
55 expectedAfter: "Expected newline after '('.",
56 expectedBetween: "Expected newline between arguments/params.",
57 unexpectedBefore: "Unexpected newline before ')'.",
58 unexpectedAfter: "Unexpected newline after '('."
59 }
60 },
61
62 create(context) {
63 const sourceCode = context.sourceCode;
64 const rawOption = context.options[0] || "multiline";
65 const multilineOption = rawOption === "multiline";
66 const multilineArgumentsOption = rawOption === "multiline-arguments";
67 const consistentOption = rawOption === "consistent";
68 let minItems;
69
70 if (typeof rawOption === "object") {
71 minItems = rawOption.minItems;
72 } else if (rawOption === "always") {
73 minItems = 0;
74 } else if (rawOption === "never") {
75 minItems = Infinity;
76 } else {
77 minItems = null;
78 }
79
80 //----------------------------------------------------------------------
81 // Helpers
82 //----------------------------------------------------------------------
83
84 /**
85 * Determines whether there should be newlines inside function parens
86 * @param {ASTNode[]} elements The arguments or parameters in the list
87 * @param {boolean} hasLeftNewline `true` if the left paren has a newline in the current code.
88 * @returns {boolean} `true` if there should be newlines inside the function parens
89 */
90 function shouldHaveNewlines(elements, hasLeftNewline) {
91 if (multilineArgumentsOption && elements.length === 1) {
92 return hasLeftNewline;
93 }
94 if (multilineOption || multilineArgumentsOption) {
95 return elements.some((element, index) => index !== elements.length - 1 && element.loc.end.line !== elements[index + 1].loc.start.line);
96 }
97 if (consistentOption) {
98 return hasLeftNewline;
99 }
100 return elements.length >= minItems;
101 }
102
103 /**
104 * Validates parens
105 * @param {Object} parens An object with keys `leftParen` for the left paren token, and `rightParen` for the right paren token
106 * @param {ASTNode[]} elements The arguments or parameters in the list
107 * @returns {void}
108 */
109 function validateParens(parens, elements) {
110 const leftParen = parens.leftParen;
111 const rightParen = parens.rightParen;
112 const tokenAfterLeftParen = sourceCode.getTokenAfter(leftParen);
113 const tokenBeforeRightParen = sourceCode.getTokenBefore(rightParen);
114 const hasLeftNewline = !astUtils.isTokenOnSameLine(leftParen, tokenAfterLeftParen);
115 const hasRightNewline = !astUtils.isTokenOnSameLine(tokenBeforeRightParen, rightParen);
116 const needsNewlines = shouldHaveNewlines(elements, hasLeftNewline);
117
118 if (hasLeftNewline && !needsNewlines) {
119 context.report({
120 node: leftParen,
121 messageId: "unexpectedAfter",
122 fix(fixer) {
123 return sourceCode.getText().slice(leftParen.range[1], tokenAfterLeftParen.range[0]).trim()
124
125 // If there is a comment between the ( and the first element, don't do a fix.
126 ? null
127 : fixer.removeRange([leftParen.range[1], tokenAfterLeftParen.range[0]]);
128 }
129 });
130 } else if (!hasLeftNewline && needsNewlines) {
131 context.report({
132 node: leftParen,
133 messageId: "expectedAfter",
134 fix: fixer => fixer.insertTextAfter(leftParen, "\n")
135 });
136 }
137
138 if (hasRightNewline && !needsNewlines) {
139 context.report({
140 node: rightParen,
141 messageId: "unexpectedBefore",
142 fix(fixer) {
143 return sourceCode.getText().slice(tokenBeforeRightParen.range[1], rightParen.range[0]).trim()
144
145 // If there is a comment between the last element and the ), don't do a fix.
146 ? null
147 : fixer.removeRange([tokenBeforeRightParen.range[1], rightParen.range[0]]);
148 }
149 });
150 } else if (!hasRightNewline && needsNewlines) {
151 context.report({
152 node: rightParen,
153 messageId: "expectedBefore",
154 fix: fixer => fixer.insertTextBefore(rightParen, "\n")
155 });
156 }
157 }
158
159 /**
160 * Validates a list of arguments or parameters
161 * @param {Object} parens An object with keys `leftParen` for the left paren token, and `rightParen` for the right paren token
162 * @param {ASTNode[]} elements The arguments or parameters in the list
163 * @returns {void}
164 */
165 function validateArguments(parens, elements) {
166 const leftParen = parens.leftParen;
167 const tokenAfterLeftParen = sourceCode.getTokenAfter(leftParen);
168 const hasLeftNewline = !astUtils.isTokenOnSameLine(leftParen, tokenAfterLeftParen);
169 const needsNewlines = shouldHaveNewlines(elements, hasLeftNewline);
170
171 for (let i = 0; i <= elements.length - 2; i++) {
172 const currentElement = elements[i];
173 const nextElement = elements[i + 1];
174 const hasNewLine = currentElement.loc.end.line !== nextElement.loc.start.line;
175
176 if (!hasNewLine && needsNewlines) {
177 context.report({
178 node: currentElement,
179 messageId: "expectedBetween",
180 fix: fixer => fixer.insertTextBefore(nextElement, "\n")
181 });
182 }
183 }
184 }
185
186 /**
187 * Gets the left paren and right paren tokens of a node.
188 * @param {ASTNode} node The node with parens
189 * @throws {TypeError} Unexpected node type.
190 * @returns {Object} An object with keys `leftParen` for the left paren token, and `rightParen` for the right paren token.
191 * Can also return `null` if an expression has no parens (e.g. a NewExpression with no arguments, or an ArrowFunctionExpression
192 * with a single parameter)
193 */
194 function getParenTokens(node) {
195 switch (node.type) {
196 case "NewExpression":
197 if (!node.arguments.length &&
198 !(
199 astUtils.isOpeningParenToken(sourceCode.getLastToken(node, { skip: 1 })) &&
200 astUtils.isClosingParenToken(sourceCode.getLastToken(node)) &&
201 node.callee.range[1] < node.range[1]
202 )
203 ) {
204
205 // If the NewExpression does not have parens (e.g. `new Foo`), return null.
206 return null;
207 }
208
209 // falls through
210
211 case "CallExpression":
212 return {
213 leftParen: sourceCode.getTokenAfter(node.callee, astUtils.isOpeningParenToken),
214 rightParen: sourceCode.getLastToken(node)
215 };
216
217 case "FunctionDeclaration":
218 case "FunctionExpression": {
219 const leftParen = sourceCode.getFirstToken(node, astUtils.isOpeningParenToken);
220 const rightParen = node.params.length
221 ? sourceCode.getTokenAfter(node.params[node.params.length - 1], astUtils.isClosingParenToken)
222 : sourceCode.getTokenAfter(leftParen);
223
224 return { leftParen, rightParen };
225 }
226
227 case "ArrowFunctionExpression": {
228 const firstToken = sourceCode.getFirstToken(node, { skip: (node.async ? 1 : 0) });
229
230 if (!astUtils.isOpeningParenToken(firstToken)) {
231
232 // If the ArrowFunctionExpression has a single param without parens, return null.
233 return null;
234 }
235
236 const rightParen = node.params.length
237 ? sourceCode.getTokenAfter(node.params[node.params.length - 1], astUtils.isClosingParenToken)
238 : sourceCode.getTokenAfter(firstToken);
239
240 return {
241 leftParen: firstToken,
242 rightParen
243 };
244 }
245
246 case "ImportExpression": {
247 const leftParen = sourceCode.getFirstToken(node, 1);
248 const rightParen = sourceCode.getLastToken(node);
249
250 return { leftParen, rightParen };
251 }
252
253 default:
254 throw new TypeError(`unexpected node with type ${node.type}`);
255 }
256 }
257
258 //----------------------------------------------------------------------
259 // Public
260 //----------------------------------------------------------------------
261
262 return {
263 [[
264 "ArrowFunctionExpression",
265 "CallExpression",
266 "FunctionDeclaration",
267 "FunctionExpression",
268 "ImportExpression",
269 "NewExpression"
270 ]](node) {
271 const parens = getParenTokens(node);
272 let params;
273
274 if (node.type === "ImportExpression") {
275 params = [node.source];
276 } else if (astUtils.isFunction(node)) {
277 params = node.params;
278 } else {
279 params = node.arguments;
280 }
281
282 if (parens) {
283 validateParens(parens, params);
284
285 if (multilineArgumentsOption) {
286 validateArguments(parens, params);
287 }
288 }
289 }
290 };
291 }
292};
Note: See TracBrowser for help on using the repository browser.