UNPKG

4.78 kBJavaScriptView Raw
1/**
2 * Requires newline before opening curly brace of all block statements.
3 *
4 * Type: `Boolean` or `Array`
5 *
6 * Values:
7 *
8 * - `true` always requires newline before curly brace of block statements
9 * - `Array` specifies block-type keywords after which newlines are required before curly brace
10 * - Valid types include: `['if', 'else', 'try', 'catch', 'finally', 'do', 'while', 'for', 'function', 'switch']`
11 *
12 * #### Example
13 *
14 * ```js
15 * "requireNewlineBeforeBlockStatements": true
16 * ```
17 *
18 * ##### Valid
19 *
20 * ```js
21 * function good()
22 * {
23 * var obj =
24 * {
25 * val: true
26 * };
27 *
28 * return {
29 * data: obj
30 * };
31 * }
32 *
33 * if (cond)
34 * {
35 * foo();
36 * }
37 *
38 * for (var e in elements)
39 * {
40 * bar(e);
41 * }
42 *
43 * while (cond)
44 * {
45 * foo();
46 * }
47 * ```
48 *
49 * ##### Invalid
50 *
51 * ```js
52 * function bad(){
53 * var obj = {
54 * val: true
55 * };
56 *
57 * return {
58 * data: obj
59 * };
60 * }
61 *
62 * if (cond){
63 * foo();
64 * }
65 *
66 * for (var e in elements){
67 * bar(e);
68 * }
69 *
70 * while (cond){
71 * foo();
72 * }
73 * ```
74 *
75 * #### Example
76 *
77 * ```js
78 * "requireNewlineBeforeBlockStatements": ["if", "else", "for"]
79 * ```
80 *
81 * ##### Valid
82 *
83 * ```js
84 * if (i > 0)
85 * {
86 * positive = true;
87 * }
88 *
89 * if (i < 0)
90 * {
91 * negative = true;
92 * }
93 * else
94 * {
95 * negative = false;
96 * }
97 *
98 * for (var i = 0, len = myList.length; i < len; ++i)
99 * {
100 * newList.push(myList[i]);
101 * }
102 *
103 * // this is fine, since "function" wasn't configured
104 * function myFunc(x) {
105 * return x + 1;
106 * }
107 * ```
108 *
109 * ##### Invalid
110 *
111 * ```js
112 * if (i < 0) {
113 * negative = true;
114 * }
115 *
116 * if (i < 0) {
117 * negative = true;
118 * } else {
119 * negative = false;
120 * }
121 *
122 * for (var i = 0, len = myList.length; i < len; ++i) {
123 * newList.push(myList[i]);
124 * }
125 * ```
126 *
127 * #### Example
128 *
129 * ```js
130 * "requireNewlineBeforeBlockStatements": ["function", "while"]
131 * ```
132 *
133 * ##### Valid
134 *
135 * ```js
136 * function myFunc(x)
137 * {
138 * return x + 1;
139 * }
140 *
141 * var z = function(x)
142 * {
143 * return x - 1;
144 * }
145 *
146 * // this is fine, since "for" wasn't configured
147 * for (var i = 0, len = myList.length; i < len; ++i) {
148 * newList.push(myList[i]);
149 * }
150 * ```
151 *
152 * ##### Invalid
153 *
154 * ```js
155 * function myFunc(x) {
156 * return x + 1;
157 * }
158 *
159 * var z = function(x) {
160 * return x - 1;
161 * }
162 * ```
163 */
164
165var assert = require('assert');
166
167module.exports = function() {};
168
169module.exports.prototype = {
170 configure: function(settingValue) {
171 assert(
172 Array.isArray(settingValue) && settingValue.length || settingValue === true,
173 'requireNewlineBeforeBlockStatements option requires non-empty array value or true value'
174 );
175
176 this._setting = settingValue;
177 },
178
179 getOptionName: function() {
180 return 'requireNewlineBeforeBlockStatements';
181 },
182
183 check: function(file, errors) {
184 var setting = this._setting;
185
186 function assertDifferentLine(token, nextToken) {
187 errors.assert.differentLine({
188 token: token,
189 nextToken: nextToken,
190 message: 'Newline before curly brace for block statement is required'
191 });
192 }
193
194 file.iterateNodesByType('BlockStatement', function(node) {
195 if (setting === true || setting.indexOf(getBlockType(node)) !== -1) {
196 var openingBrace = node.getFirstToken();
197 var prevToken = openingBrace.getPreviousCodeToken();
198
199 assertDifferentLine(prevToken, openingBrace);
200 }
201 });
202 if (setting === true || setting.indexOf('switch') !== -1) {
203 file.iterateNodesByType(['SwitchStatement'], function(node) {
204 var openingBrace = file.findNextToken(file.getLastNodeToken(node.discriminant), 'Punctuator', '{');
205 var prevToken = file.getPrevToken(openingBrace);
206
207 assertDifferentLine(prevToken, openingBrace);
208 });
209 }
210 }
211};
212
213function getBlockType(node) {
214 var parentElement = node.parentElement;
215 switch (parentElement.type) {
216 case 'IfStatement':
217 return (parentElement.alternate === node) ? 'else' : 'if';
218 case 'FunctionDeclaration':
219 case 'FunctionExpression':
220 case 'ArrowFunctionExpression':
221 return 'function';
222 case 'ForStatement':
223 case 'ForInStatement':
224 case 'ForOfStatement':
225 return 'for';
226 case 'WhileStatement':
227 return 'while';
228 case 'DoWhileStatement':
229 return 'do';
230 case 'TryStatement':
231 return (parentElement.finalizer === node) ? 'finally' : 'try';
232 case 'CatchClause':
233 return 'catch';
234 }
235}