Skip to content
This repository was archived by the owner on Mar 23, 2024. It is now read-only.

Commit 1afee41

Browse files
ficristomarkelog
authored andcommitted
disallowNewlineBeforeBlockStatements: add allExcept option
- `allExcept`: Array of exceptions - `"multiLine"`: if the conditions span on multiple lines, require a new line before the curly brace Fixes #1956 Closes gh-2035
1 parent c1afd2e commit 1afee41

2 files changed

Lines changed: 161 additions & 7 deletions

File tree

lib/rules/disallow-newline-before-block-statements.js

Lines changed: 115 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
11
/**
22
* Disallows newline before opening curly brace of all block statements.
33
*
4-
* Type: `Boolean` or `Array`
4+
* Type: `Boolean` or `Array` or `Object`
55
*
66
* Values:
77
*
88
* - `true` always disallows newline before curly brace of block statements
99
* - `Array` specifies block-type keywords after which newlines are disallowed before curly brace
1010
* - Valid types include: `['if', 'else', 'try', 'catch', 'finally', 'do', 'while', 'for', 'function', 'class']`
11+
* - `Object`:
12+
* - `value`: `true` or an Array
13+
* - `allExcept`: Array of exceptions
14+
* - `"multiLine"`: if the conditions span on multiple lines, require a new line before the curly brace
1115
*
1216
* #### Example
1317
*
@@ -162,14 +166,72 @@
162166
* return x - 1;
163167
* }
164168
* ```
169+
*
170+
* #### Example
171+
*
172+
* ```js
173+
* "disallowNewlineBeforeBlockStatements": {
174+
* "value": true,
175+
* "allExcept": ["multiLine"]
176+
* }
177+
* ```
178+
*
179+
* ##### Valid
180+
*
181+
* ```js
182+
* function myFunc(x,
183+
* y)
184+
* {
185+
* return x + y;
186+
* }
187+
*
188+
* function foo() {
189+
* if (bar && baz &&
190+
* bat)
191+
* {
192+
* return true;
193+
* }
194+
* }
195+
* ```
196+
*
197+
* ##### Invalid
198+
*
199+
* ```js
200+
* function myFunc(x,
201+
* y) {
202+
* return x + y;
203+
* }
204+
*
205+
* function foo() {
206+
* if (bar && baz &&
207+
* bat) {
208+
* return true;
209+
* }
210+
* }
211+
* ```
165212
*/
166213

167214
var assert = require('assert');
168215

169216
module.exports = function() {};
170217

171218
module.exports.prototype = {
172-
configure: function(settingValue) {
219+
configure: function(options) {
220+
var settingValue;
221+
this._hasMultiLineEx = false;
222+
if (options.constructor === Object) {
223+
settingValue = options.value;
224+
if (options.allExcept) {
225+
assert(
226+
Array.isArray(options.allExcept) && options.allExcept.length === 1 &&
227+
options.allExcept[0] === 'multiLine',
228+
'allExcept option must be an array whose values can be only `multiLine`'
229+
);
230+
this._hasMultiLineEx = true;
231+
}
232+
} else {
233+
settingValue = options;
234+
}
173235
assert(
174236
Array.isArray(settingValue) && settingValue.length || settingValue === true,
175237
'disallowNewlineBeforeBlockStatements option requires non-empty array value or true value'
@@ -184,6 +246,23 @@ module.exports.prototype = {
184246

185247
check: function(file, errors) {
186248
var setting = this._setting;
249+
var hasMultiLineEx = this._hasMultiLineEx;
250+
251+
function assertSameLine(token, nextToken) {
252+
errors.assert.sameLine({
253+
token: token,
254+
nextToken: nextToken,
255+
message: 'Newline before curly brace for block statement is disallowed'
256+
});
257+
}
258+
function assertDifferentLine(token, nextToken) {
259+
errors.assert.differentLine({
260+
token: token,
261+
nextToken: nextToken,
262+
message: 'Newline before curly brace for block statement is required'
263+
});
264+
}
265+
187266
file.iterateNodesByType(['BlockStatement', 'ClassBody'], function(node) {
188267
if (isBareBlock(node)) {
189268
return;
@@ -193,11 +272,40 @@ module.exports.prototype = {
193272
var openingBrace = file.getFirstNodeToken(node);
194273
var prevToken = file.getPrevToken(openingBrace);
195274

196-
errors.assert.sameLine({
197-
token: prevToken,
198-
nextToken: openingBrace,
199-
message: 'Newline before curly brace for block statement is disallowed'
200-
});
275+
if (hasMultiLineEx !== true) {
276+
assertSameLine(prevToken, openingBrace);
277+
return;
278+
}
279+
280+
// Check if the 'conditions' span on multiple lines.
281+
// The simplest way is to check if the round braces are on different lines.
282+
//
283+
// For example:
284+
// // same line
285+
// for (var i = 0; i < length; i++) {
286+
// }
287+
//
288+
// // different lines:
289+
// for (var i = 0;
290+
// i < length;
291+
// i++)
292+
// {
293+
// }
294+
var parentNode = node.parentNode;
295+
var parentNextToken = file.getFirstNodeToken(parentNode);
296+
var openingRoundBrace = file.findNextToken(parentNextToken, 'Punctuator', '(');
297+
var closingRoundBrace = file.findPrevToken(openingBrace, 'Punctuator', ')');
298+
299+
// Not always the conditions are there: to check look for the presence of round braces.
300+
// For example:
301+
// try {
302+
// } ...
303+
if (openingRoundBrace && closingRoundBrace &&
304+
openingRoundBrace.loc.start.line !== closingRoundBrace.loc.end.line) {
305+
assertDifferentLine(prevToken, openingBrace);
306+
} else {
307+
assertSameLine(prevToken, openingBrace);
308+
}
201309
}
202310
});
203311
}

test/specs/rules/disallow-newline-before-block-statements.js

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,4 +379,50 @@ describe('rules/disallow-newline-before-block-statements', function() {
379379
});
380380
});
381381
});
382+
383+
describe('with option value object and allExcept multiLine - ', function() {
384+
beforeEach(function() {
385+
checker.configure({
386+
disallowNewlineBeforeBlockStatements: {
387+
value: true,
388+
allExcept: ['multiLine']
389+
}
390+
});
391+
});
392+
393+
it('misc checks', function() {
394+
expect(checker.checkString('function foo(a,b) { }'))
395+
.to.have.no.errors();
396+
397+
expect(checker.checkString('function foo(a,\nb) { }'))
398+
.to.have.one.validation.error.from('disallowNewlineBeforeBlockStatements');
399+
400+
expect(checker.checkString('function foo() { for (var i=0; i<len; i++) { } }'))
401+
.to.have.no.errors();
402+
403+
expect(checker.checkString('function foo() { for (var i=0; i<len;\ni++) { } }'))
404+
.to.have.one.validation.error.from('disallowNewlineBeforeBlockStatements');
405+
406+
expect(checker.checkString('function foo() { for (var i=0; i<len;\ni++)\n{ } }'))
407+
.to.have.no.errors();
408+
409+
expect(checker.checkString('function foo() { if (true) { } }'))
410+
.to.have.no.errors();
411+
412+
expect(checker.checkString('function foo() { if (a && b()) { } }'))
413+
.to.have.no.errors();
414+
415+
expect(checker.checkString('function foo() { if (a &&\nb()) { } }'))
416+
.to.have.one.validation.error.from('disallowNewlineBeforeBlockStatements');
417+
418+
expect(checker.checkString('function foo() { if (a &&\nb())\n{ } }'))
419+
.to.have.no.errors();
420+
421+
expect(checker.checkString('(function () {}())'))
422+
.to.have.no.errors();
423+
424+
expect(checker.checkString('try {\n\ty++;\n} catch(e) {\n}'))
425+
.to.have.no.errors();
426+
});
427+
});
382428
});

0 commit comments

Comments
 (0)