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

Commit 74b11a4

Browse files
schempymarkelog
authored andcommitted
New rule: requireNewlineBeforeSingleStatementsInIf
Valid: if (x) doX(); else doY(); Invalid: if (x) doX(); else doY(); Fixes #1829 Closes gh-2138
1 parent f7ba2ea commit 74b11a4

File tree

3 files changed

+141
-0
lines changed

3 files changed

+141
-0
lines changed

lib/config/configuration.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1144,6 +1144,8 @@ Configuration.prototype.registerDefaultRules = function() {
11441144
this.registerRule(require('../rules/require-aligned-multiline-params'));
11451145

11461146
this.registerRule(require('../rules/require-early-return'));
1147+
1148+
this.registerRule(require('../rules/require-newline-before-single-statements-in-if'));
11471149
};
11481150

11491151
/**
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
/**
2+
* Requires newline before single if statements
3+
*
4+
* Type: `Boolean`
5+
*
6+
* Value: `true`
7+
*
8+
* #### Example
9+
*
10+
* ```js
11+
* "requireNewlineBeforeSingleStatementsInIf": true
12+
* ```
13+
*
14+
* ##### Valid
15+
*
16+
* ```js
17+
* if (x)
18+
* doX();
19+
* else
20+
* doY();
21+
*
22+
* if (x)
23+
* doX();
24+
* else if (v)
25+
* doV();
26+
* else
27+
* doY();
28+
* ```
29+
*
30+
* ##### Invalid
31+
*
32+
* ```js
33+
* if (x) doX();
34+
* else doY();
35+
*
36+
* if (x) doX();
37+
* else if (v) doV();
38+
* else doY();
39+
* ```
40+
*/
41+
42+
var assert = require('assert');
43+
44+
module.exports = function() {};
45+
46+
module.exports.prototype = {
47+
48+
configure: function(value) {
49+
assert(
50+
value === true,
51+
this.getOptionName() + ' option requires a true value or should be removed'
52+
);
53+
},
54+
55+
getOptionName: function() {
56+
return 'requireNewlineBeforeSingleStatementsInIf';
57+
},
58+
59+
check: function(file, errors) {
60+
function isExpressionStatement(entity) {
61+
return entity.type === 'ExpressionStatement';
62+
}
63+
64+
function assertDifferentLine(token, nextToken) {
65+
errors.assert.differentLine({
66+
token: token,
67+
nextToken: nextToken,
68+
message: 'Newline before single statement in if is required'
69+
});
70+
}
71+
72+
// Recursively locate a token based on it's type.
73+
function getToken(entity, tokenType, tokenProperty) {
74+
if (entity.type === tokenType || !entity[tokenProperty]) {
75+
return entity;
76+
} else {
77+
return getToken(entity[tokenProperty], tokenType, tokenProperty);
78+
}
79+
}
80+
81+
file.iterateNodesByType('IfStatement', function(node) {
82+
var consequentNode = node.consequent;
83+
var alternateNode = node.alternate;
84+
85+
if (isExpressionStatement(consequentNode)) {
86+
assertDifferentLine(consequentNode, getToken(consequentNode, 'Keyword', 'previousSibling'));
87+
}
88+
89+
if (isExpressionStatement(alternateNode)) {
90+
assertDifferentLine(alternateNode, getToken(alternateNode, 'Keyword', 'previousSibling'));
91+
}
92+
});
93+
}
94+
};
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
var Checker = require('../../../lib/checker');
2+
var expect = require('chai').expect;
3+
4+
describe('rules/require-newline-before-single-statements-in-if', function() {
5+
var checker;
6+
7+
beforeEach(function() {
8+
checker = new Checker();
9+
checker.registerDefaultRules();
10+
});
11+
12+
describe('value true', function() {
13+
beforeEach(function() {
14+
checker.configure({ requireNewlineBeforeSingleStatementsInIf: true });
15+
});
16+
17+
it('should ignore if in a block statment', function() {
18+
expect(checker.checkString('if (x) {\n doX();\n} else {\n doY();\n}')).to.have.no.errors();
19+
});
20+
21+
it('should not report missing newline before conditional statement', function() {
22+
expect(checker.checkString('if (x)\ndoX();\nelse \ndoY();\n')).to.have.no.errors();
23+
});
24+
25+
it('should not report missing newline before conditional for nested else if', function() {
26+
expect(checker.checkString('if (x)\ndoX();\nelse if (v)\ndoV();\nelse\ndoY();'))
27+
.to.have.no.errors();
28+
});
29+
30+
it('should report missing newline before conditional for consequent', function() {
31+
expect(checker.checkString('if (x) doX();\nelse\n doY();'))
32+
.to.have.one.validation.error.from('requireNewlineBeforeSingleStatementsInIf');
33+
});
34+
35+
it('should report missing newline before conditional for alternate', function() {
36+
expect(checker.checkString('if (x)\ndoX();\nelse doY();'))
37+
.to.have.one.validation.error.from('requireNewlineBeforeSingleStatementsInIf');
38+
});
39+
40+
it('should report missing newline before conditional for nested else if', function() {
41+
expect(checker.checkString('if (x)\ndoX();\nelse if (v) doV();\nelse\ndoY();'))
42+
.to.have.one.validation.error.from('requireNewlineBeforeSingleStatementsInIf');
43+
});
44+
});
45+
});

0 commit comments

Comments
 (0)