UNPKG

5.52 kBJavaScriptView Raw
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
89var assert = require('assert');
90
91module.exports = function() {};
92
93module.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};