UNPKG

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