]>
Commit | Line | Data |
---|---|---|
eb39fafa DC |
1 | /** |
2 | * @fileoverview Rule to enforce line breaks between arguments of a function call | |
3 | * @author Alexey Gonchar <https://github.com/finico> | |
4 | */ | |
5 | ||
6 | "use strict"; | |
7 | ||
8 | //------------------------------------------------------------------------------ | |
9 | // Rule Definition | |
10 | //------------------------------------------------------------------------------ | |
11 | ||
34eeec05 | 12 | /** @type {import('../shared/types').Rule} */ |
eb39fafa DC |
13 | module.exports = { |
14 | meta: { | |
15 | type: "layout", | |
16 | ||
17 | docs: { | |
18 | description: "enforce line breaks between arguments of a function call", | |
eb39fafa DC |
19 | recommended: false, |
20 | url: "https://eslint.org/docs/rules/function-call-argument-newline" | |
21 | }, | |
22 | ||
23 | fixable: "whitespace", | |
24 | ||
25 | schema: [ | |
26 | { | |
27 | enum: ["always", "never", "consistent"] | |
28 | } | |
29 | ], | |
30 | ||
31 | messages: { | |
32 | unexpectedLineBreak: "There should be no line break here.", | |
33 | missingLineBreak: "There should be a line break after this argument." | |
34 | } | |
35 | }, | |
36 | ||
37 | create(context) { | |
38 | const sourceCode = context.getSourceCode(); | |
39 | ||
40 | const checkers = { | |
41 | unexpected: { | |
42 | messageId: "unexpectedLineBreak", | |
43 | check: (prevToken, currentToken) => prevToken.loc.end.line !== currentToken.loc.start.line, | |
44 | createFix: (token, tokenBefore) => fixer => | |
45 | fixer.replaceTextRange([tokenBefore.range[1], token.range[0]], " ") | |
46 | }, | |
47 | missing: { | |
48 | messageId: "missingLineBreak", | |
49 | check: (prevToken, currentToken) => prevToken.loc.end.line === currentToken.loc.start.line, | |
50 | createFix: (token, tokenBefore) => fixer => | |
51 | fixer.replaceTextRange([tokenBefore.range[1], token.range[0]], "\n") | |
52 | } | |
53 | }; | |
54 | ||
55 | /** | |
56 | * Check all arguments for line breaks in the CallExpression | |
57 | * @param {CallExpression} node node to evaluate | |
58 | * @param {{ messageId: string, check: Function }} checker selected checker | |
59 | * @returns {void} | |
60 | * @private | |
61 | */ | |
62 | function checkArguments(node, checker) { | |
63 | for (let i = 1; i < node.arguments.length; i++) { | |
64 | const prevArgToken = sourceCode.getLastToken(node.arguments[i - 1]); | |
65 | const currentArgToken = sourceCode.getFirstToken(node.arguments[i]); | |
66 | ||
67 | if (checker.check(prevArgToken, currentArgToken)) { | |
68 | const tokenBefore = sourceCode.getTokenBefore( | |
69 | currentArgToken, | |
70 | { includeComments: true } | |
71 | ); | |
72 | ||
73 | const hasLineCommentBefore = tokenBefore.type === "Line"; | |
74 | ||
75 | context.report({ | |
76 | node, | |
77 | loc: { | |
78 | start: tokenBefore.loc.end, | |
79 | end: currentArgToken.loc.start | |
80 | }, | |
81 | messageId: checker.messageId, | |
82 | fix: hasLineCommentBefore ? null : checker.createFix(currentArgToken, tokenBefore) | |
83 | }); | |
84 | } | |
85 | } | |
86 | } | |
87 | ||
88 | /** | |
89 | * Check if open space is present in a function name | |
90 | * @param {CallExpression} node node to evaluate | |
91 | * @returns {void} | |
92 | * @private | |
93 | */ | |
94 | function check(node) { | |
95 | if (node.arguments.length < 2) { | |
96 | return; | |
97 | } | |
98 | ||
99 | const option = context.options[0] || "always"; | |
100 | ||
101 | if (option === "never") { | |
102 | checkArguments(node, checkers.unexpected); | |
103 | } else if (option === "always") { | |
104 | checkArguments(node, checkers.missing); | |
105 | } else if (option === "consistent") { | |
106 | const firstArgToken = sourceCode.getLastToken(node.arguments[0]); | |
107 | const secondArgToken = sourceCode.getFirstToken(node.arguments[1]); | |
108 | ||
109 | if (firstArgToken.loc.end.line === secondArgToken.loc.start.line) { | |
110 | checkArguments(node, checkers.unexpected); | |
111 | } else { | |
112 | checkArguments(node, checkers.missing); | |
113 | } | |
114 | } | |
115 | } | |
116 | ||
117 | return { | |
118 | CallExpression: check, | |
119 | NewExpression: check | |
120 | }; | |
121 | } | |
122 | }; |