1 | /**
|
2 | * Requires space before `()` or `{}` in function expressions (both [named](#requirespacesinnamedfunctionexpression)
|
3 | * and [anonymous](#requirespacesinanonymousfunctionexpression)) and function declarations.
|
4 | *
|
5 | * Types: `Object`
|
6 | *
|
7 | * - `Object` (at least one of properties must be present and it must be set to true):
|
8 | * - `'beforeOpeningRoundBrace'`
|
9 | * - `true` validates that there is a space before `()`
|
10 | * - `'beforeOpeningCurlyBrace'`
|
11 | * - `true` validates that there is a space before `{}`
|
12 | *
|
13 | * #### Example
|
14 | *
|
15 | * ```js
|
16 | * "requireSpacesInFunction": {
|
17 | * "beforeOpeningRoundBrace": true,
|
18 | * "beforeOpeningCurlyBrace": true
|
19 | * }
|
20 | * ```
|
21 | * ```js
|
22 | * "requireSpacesInFunction": {
|
23 | * "beforeOpeningRoundBrace": true
|
24 | * }
|
25 | * ```
|
26 | * ```js
|
27 | * "requireSpacesInFunction": {
|
28 | * "beforeOpeningCurlyBrace": true
|
29 | * }
|
30 | * ```
|
31 | *
|
32 | * ##### Valid for mode `{ "beforeOpeningRoundBrace": true, "beforeOpeningCurlyBrace": true }`
|
33 | *
|
34 | * ```js
|
35 | * var x = function () {};
|
36 | * var x = function a () {};
|
37 | * function a () {}
|
38 | * var x = async function () {};
|
39 | * var x = async function a () {};
|
40 | * async function a () {}
|
41 | * ```
|
42 | *
|
43 | * ##### Valid for mode `{ "beforeOpeningRoundBrace": true }`
|
44 | *
|
45 | * ```js
|
46 | * var x = function (){};
|
47 | * var x = function a (){};
|
48 | * function a (){}
|
49 | * var x = async function (){};
|
50 | * var x = async function a (){};
|
51 | * async function a (){}
|
52 | * ```
|
53 | *
|
54 | * ##### Valid for mode `{ "beforeOpeningCurlyBrace": true }`
|
55 | *
|
56 | * ```js
|
57 | * var x = function() {};
|
58 | * var x = function a() {};
|
59 | * function a() {}
|
60 | * var x = async function() {};
|
61 | * var x = async function a() {};
|
62 | * async function a() {}
|
63 | * ```
|
64 | *
|
65 | * ##### Invalid for mode `{ "beforeOpeningRoundBrace": true, "beforeOpeningCurlyBrace": true }`
|
66 | *
|
67 | * ```js
|
68 | * var x = function() {};
|
69 | * var x = function (){};
|
70 | * var x = function(){};
|
71 | * var x = function a() {};
|
72 | * var x = function a (){};
|
73 | * var x = function a(){};
|
74 | * function a() {}
|
75 | * function a (){}
|
76 | * function a(){}
|
77 | * var x = async function() {};
|
78 | * var x = async function (){};
|
79 | * var x = async function(){};
|
80 | * var x = async function a() {};
|
81 | * var x = async function a (){};
|
82 | * var x = async function a(){};
|
83 | * async function a() {}
|
84 | * async function a (){}
|
85 | * async function a(){}
|
86 | * ```
|
87 | */
|
88 |
|
89 | var assert = require('assert');
|
90 |
|
91 | module.exports = function() {};
|
92 |
|
93 | module.exports.prototype = {
|
94 | configure: function(options) {
|
95 | assert(
|
96 | typeof options === 'object',
|
97 | this.getOptionName() + ' option must be the object'
|
98 | );
|
99 |
|
100 | if ('beforeOpeningRoundBrace' in options) {
|
101 | assert(
|
102 | options.beforeOpeningRoundBrace === true,
|
103 | this.getOptionName() + '.beforeOpeningRoundBrace ' +
|
104 | 'property requires true value or should be removed'
|
105 | );
|
106 | }
|
107 |
|
108 | if ('beforeOpeningCurlyBrace' in options) {
|
109 | assert(
|
110 | options.beforeOpeningCurlyBrace === true,
|
111 | this.getOptionName() + '.beforeOpeningCurlyBrace ' +
|
112 | 'property requires true value or should be removed'
|
113 | );
|
114 | }
|
115 |
|
116 | assert(
|
117 | options.beforeOpeningCurlyBrace || options.beforeOpeningRoundBrace,
|
118 | this.getOptionName() + ' must have beforeOpeningCurlyBrace or beforeOpeningRoundBrace property'
|
119 | );
|
120 |
|
121 | this._beforeOpeningRoundBrace = Boolean(options.beforeOpeningRoundBrace);
|
122 | this._beforeOpeningCurlyBrace = Boolean(options.beforeOpeningCurlyBrace);
|
123 | },
|
124 |
|
125 | getOptionName: function() {
|
126 | return 'requireSpacesInFunction';
|
127 | },
|
128 |
|
129 | check: function(file, errors) {
|
130 | var beforeOpeningRoundBrace = this._beforeOpeningRoundBrace;
|
131 | var beforeOpeningCurlyBrace = this._beforeOpeningCurlyBrace;
|
132 |
|
133 | file.iterateNodesByType(['FunctionDeclaration', 'FunctionExpression'], function(node) {
|
134 | // for a named function, use node.id
|
135 | var functionNode = node.id || node;
|
136 | var parent = node.parentElement;
|
137 |
|
138 | // Ignore syntactic sugar for getters and setters.
|
139 | if (parent.type === 'Property' && (parent.kind === 'get' || parent.kind === 'set')) {
|
140 | return;
|
141 | }
|
142 |
|
143 | // shorthand or constructor methods
|
144 | if (parent.method || parent.type === 'MethodDefinition') {
|
145 | functionNode = parent.key;
|
146 | }
|
147 |
|
148 | if (beforeOpeningRoundBrace) {
|
149 | var functionToken = file.getFirstNodeToken(functionNode);
|
150 | if (node.async && functionToken.value === 'async') {
|
151 | functionToken = file.getNextToken(functionToken);
|
152 | }
|
153 | // if generator, set token to be * instead
|
154 | if (node.generator && functionToken.value === 'function') {
|
155 | functionToken = file.getNextToken(functionToken);
|
156 | }
|
157 | errors.assert.whitespaceBetween({
|
158 | token: functionToken,
|
159 | nextToken: file.getNextToken(functionToken),
|
160 | message: 'Missing space before opening round brace'
|
161 | });
|
162 | }
|
163 |
|
164 | if (beforeOpeningCurlyBrace) {
|
165 | var bodyToken = file.getFirstNodeToken(node.body);
|
166 | errors.assert.whitespaceBetween({
|
167 | token: file.getPrevToken(bodyToken),
|
168 | nextToken: bodyToken,
|
169 | message: 'Missing space before opening curly brace'
|
170 | });
|
171 | }
|
172 | });
|
173 | }
|
174 |
|
175 | };
|