.gitignore added
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / eslint / lib / rules / func-call-spacing.js
1 /**
2  * @fileoverview Rule to control spacing within function calls
3  * @author Matt DuVall <http://www.mattduvall.com>
4  */
5
6 "use strict";
7
8 //------------------------------------------------------------------------------
9 // Requirements
10 //------------------------------------------------------------------------------
11
12 const astUtils = require("./utils/ast-utils");
13
14 //------------------------------------------------------------------------------
15 // Rule Definition
16 //------------------------------------------------------------------------------
17
18 module.exports = {
19     meta: {
20         type: "layout",
21
22         docs: {
23             description: "require or disallow spacing between function identifiers and their invocations",
24             category: "Stylistic Issues",
25             recommended: false,
26             url: "https://eslint.org/docs/rules/func-call-spacing"
27         },
28
29         fixable: "whitespace",
30
31         schema: {
32             anyOf: [
33                 {
34                     type: "array",
35                     items: [
36                         {
37                             enum: ["never"]
38                         }
39                     ],
40                     minItems: 0,
41                     maxItems: 1
42                 },
43                 {
44                     type: "array",
45                     items: [
46                         {
47                             enum: ["always"]
48                         },
49                         {
50                             type: "object",
51                             properties: {
52                                 allowNewlines: {
53                                     type: "boolean"
54                                 }
55                             },
56                             additionalProperties: false
57                         }
58                     ],
59                     minItems: 0,
60                     maxItems: 2
61                 }
62             ]
63         },
64
65         messages: {
66             unexpectedWhitespace: "Unexpected whitespace between function name and paren.",
67             unexpectedNewline: "Unexpected newline between function name and paren.",
68             missing: "Missing space between function name and paren."
69         }
70     },
71
72     create(context) {
73
74         const never = context.options[0] !== "always";
75         const allowNewlines = !never && context.options[1] && context.options[1].allowNewlines;
76         const sourceCode = context.getSourceCode();
77         const text = sourceCode.getText();
78
79         /**
80          * Check if open space is present in a function name
81          * @param {ASTNode} node node to evaluate
82          * @param {Token} leftToken The last token of the callee. This may be the closing parenthesis that encloses the callee.
83          * @param {Token} rightToken Tha first token of the arguments. this is the opening parenthesis that encloses the arguments.
84          * @returns {void}
85          * @private
86          */
87         function checkSpacing(node, leftToken, rightToken) {
88             const textBetweenTokens = text.slice(leftToken.range[1], rightToken.range[0]).replace(/\/\*.*?\*\//gu, "");
89             const hasWhitespace = /\s/u.test(textBetweenTokens);
90             const hasNewline = hasWhitespace && astUtils.LINEBREAK_MATCHER.test(textBetweenTokens);
91
92             /*
93              * never allowNewlines hasWhitespace hasNewline message
94              * F     F             F             F          Missing space between function name and paren.
95              * F     F             F             T          (Invalid `!hasWhitespace && hasNewline`)
96              * F     F             T             T          Unexpected newline between function name and paren.
97              * F     F             T             F          (OK)
98              * F     T             T             F          (OK)
99              * F     T             T             T          (OK)
100              * F     T             F             T          (Invalid `!hasWhitespace && hasNewline`)
101              * F     T             F             F          Missing space between function name and paren.
102              * T     T             F             F          (Invalid `never && allowNewlines`)
103              * T     T             F             T          (Invalid `!hasWhitespace && hasNewline`)
104              * T     T             T             T          (Invalid `never && allowNewlines`)
105              * T     T             T             F          (Invalid `never && allowNewlines`)
106              * T     F             T             F          Unexpected space between function name and paren.
107              * T     F             T             T          Unexpected space between function name and paren.
108              * T     F             F             T          (Invalid `!hasWhitespace && hasNewline`)
109              * T     F             F             F          (OK)
110              *
111              * T                   T                        Unexpected space between function name and paren.
112              * F                   F                        Missing space between function name and paren.
113              * F     F                           T          Unexpected newline between function name and paren.
114              */
115
116             if (never && hasWhitespace) {
117                 context.report({
118                     node,
119                     loc: {
120                         start: leftToken.loc.end,
121                         end: {
122                             line: rightToken.loc.start.line,
123                             column: rightToken.loc.start.column - 1
124                         }
125                     },
126                     messageId: "unexpectedWhitespace",
127                     fix(fixer) {
128
129                         // Don't remove comments.
130                         if (sourceCode.commentsExistBetween(leftToken, rightToken)) {
131                             return null;
132                         }
133
134                         // If `?.` exists, it doesn't hide no-unexpected-multiline errors
135                         if (node.optional) {
136                             return fixer.replaceTextRange([leftToken.range[1], rightToken.range[0]], "?.");
137                         }
138
139                         /*
140                          * Only autofix if there is no newline
141                          * https://github.com/eslint/eslint/issues/7787
142                          */
143                         if (hasNewline) {
144                             return null;
145                         }
146                         return fixer.removeRange([leftToken.range[1], rightToken.range[0]]);
147                     }
148                 });
149             } else if (!never && !hasWhitespace) {
150                 context.report({
151                     node,
152                     loc: {
153                         start: {
154                             line: leftToken.loc.end.line,
155                             column: leftToken.loc.end.column - 1
156                         },
157                         end: rightToken.loc.start
158                     },
159                     messageId: "missing",
160                     fix(fixer) {
161                         if (node.optional) {
162                             return null; // Not sure if inserting a space to either before/after `?.` token.
163                         }
164                         return fixer.insertTextBefore(rightToken, " ");
165                     }
166                 });
167             } else if (!never && !allowNewlines && hasNewline) {
168                 context.report({
169                     node,
170                     loc: {
171                         start: leftToken.loc.end,
172                         end: rightToken.loc.start
173                     },
174                     messageId: "unexpectedNewline",
175                     fix(fixer) {
176
177                         /*
178                          * Only autofix if there is no newline
179                          * https://github.com/eslint/eslint/issues/7787
180                          * But if `?.` exists, it doesn't hide no-unexpected-multiline errors
181                          */
182                         if (!node.optional) {
183                             return null;
184                         }
185
186                         // Don't remove comments.
187                         if (sourceCode.commentsExistBetween(leftToken, rightToken)) {
188                             return null;
189                         }
190
191                         const range = [leftToken.range[1], rightToken.range[0]];
192                         const qdToken = sourceCode.getTokenAfter(leftToken);
193
194                         if (qdToken.range[0] === leftToken.range[1]) {
195                             return fixer.replaceTextRange(range, "?. ");
196                         }
197                         if (qdToken.range[1] === rightToken.range[0]) {
198                             return fixer.replaceTextRange(range, " ?.");
199                         }
200                         return fixer.replaceTextRange(range, " ?. ");
201                     }
202                 });
203             }
204         }
205
206         return {
207             "CallExpression, NewExpression"(node) {
208                 const lastToken = sourceCode.getLastToken(node);
209                 const lastCalleeToken = sourceCode.getLastToken(node.callee);
210                 const parenToken = sourceCode.getFirstTokenBetween(lastCalleeToken, lastToken, astUtils.isOpeningParenToken);
211                 const prevToken = parenToken && sourceCode.getTokenBefore(parenToken, astUtils.isNotQuestionDotToken);
212
213                 // Parens in NewExpression are optional
214                 if (!(parenToken && parenToken.range[1] < node.range[1])) {
215                     return;
216                 }
217
218                 checkSpacing(node, prevToken, parenToken);
219             },
220
221             ImportExpression(node) {
222                 const leftToken = sourceCode.getFirstToken(node);
223                 const rightToken = sourceCode.getTokenAfter(leftToken);
224
225                 checkSpacing(node, leftToken, rightToken);
226             }
227         };
228
229     }
230 };