UNPKG

6.33 kBJavaScriptView Raw
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// Rule Definition
10//------------------------------------------------------------------------------
11
12module.exports = {
13 meta: {
14 docs: {
15 description: "require or disallow spacing between function identifiers and their invocations",
16 category: "Stylistic Issues",
17 recommended: false
18 },
19
20 fixable: "whitespace",
21 schema: {
22 anyOf: [
23 {
24 type: "array",
25 items: [
26 {
27 enum: ["never"]
28 }
29 ],
30 minItems: 0,
31 maxItems: 1
32 },
33 {
34 type: "array",
35 items: [
36 {
37 enum: ["always"]
38 },
39 {
40 type: "object",
41 properties: {
42 allowNewlines: {
43 type: "boolean"
44 }
45 },
46 additionalProperties: false
47 }
48 ],
49 minItems: 0,
50 maxItems: 2
51 }
52 ]
53 }
54 },
55
56 create(context) {
57
58 const never = context.options[0] !== "always";
59 const allowNewlines = !never && context.options[1] && context.options[1].allowNewlines;
60 const sourceCode = context.getSourceCode();
61 const text = sourceCode.getText();
62
63 /**
64 * Check if open space is present in a function name
65 * @param {ASTNode} node node to evaluate
66 * @returns {void}
67 * @private
68 */
69 function checkSpacing(node) {
70 const lastCalleeToken = sourceCode.getLastToken(node.callee);
71 let prevToken = lastCalleeToken;
72 let parenToken = sourceCode.getTokenAfter(lastCalleeToken);
73
74 // advances to an open parenthesis.
75 while (
76 parenToken &&
77 parenToken.range[1] < node.range[1] &&
78 parenToken.value !== "("
79 ) {
80 prevToken = parenToken;
81 parenToken = sourceCode.getTokenAfter(parenToken);
82 }
83
84 // Parens in NewExpression are optional
85 if (!(parenToken && parenToken.range[1] < node.range[1])) {
86 return;
87 }
88
89 const hasWhitespace = sourceCode.isSpaceBetweenTokens(prevToken, parenToken);
90 const hasNewline = hasWhitespace &&
91 /\n/.test(text.slice(prevToken.range[1], parenToken.range[0]).replace(/\/\*.*?\*\//g, ""));
92
93 /*
94 * never allowNewlines hasWhitespace hasNewline message
95 * F F F F Missing space between function name and paren.
96 * F F F T (Invalid `!hasWhitespace && hasNewline`)
97 * F F T T Unexpected newline between function name and paren.
98 * F F T F (OK)
99 * F T T F (OK)
100 * F T T T (OK)
101 * F T F T (Invalid `!hasWhitespace && hasNewline`)
102 * F T F F Missing space between function name and paren.
103 * T T F F (Invalid `never && allowNewlines`)
104 * T T F T (Invalid `!hasWhitespace && hasNewline`)
105 * T T T T (Invalid `never && allowNewlines`)
106 * T T T F (Invalid `never && allowNewlines`)
107 * T F T F Unexpected space between function name and paren.
108 * T F T T Unexpected space between function name and paren.
109 * T F F T (Invalid `!hasWhitespace && hasNewline`)
110 * T F F F (OK)
111 *
112 * T T Unexpected space between function name and paren.
113 * F F Missing space between function name and paren.
114 * F F T Unexpected newline between function name and paren.
115 */
116
117 if (never && hasWhitespace) {
118 context.report({
119 node,
120 loc: lastCalleeToken.loc.start,
121 message: "Unexpected space between function name and paren.",
122 fix(fixer) {
123 return fixer.removeRange([prevToken.range[1], parenToken.range[0]]);
124 }
125 });
126 } else if (!never && !hasWhitespace) {
127 context.report({
128 node,
129 loc: lastCalleeToken.loc.start,
130 message: "Missing space between function name and paren.",
131 fix(fixer) {
132 return fixer.insertTextBefore(parenToken, " ");
133 }
134 });
135 } else if (!never && !allowNewlines && hasNewline) {
136 context.report({
137 node,
138 loc: lastCalleeToken.loc.start,
139 message: "Unexpected newline between function name and paren.",
140 fix(fixer) {
141 return fixer.replaceTextRange([prevToken.range[1], parenToken.range[0]], " ");
142 }
143 });
144 }
145 }
146
147 return {
148 CallExpression: checkSpacing,
149 NewExpression: checkSpacing
150 };
151
152 }
153};