UNPKG

4.01 kBJavaScriptView Raw
1/**
2 * Requires an empty line above the specified keywords unless the keyword is the first expression in a block.
3 *
4 * Types: `Boolean` or `Array`
5 *
6 * Values:
7 *
8 * - `true` specifies that the spacedKeywords found in the utils module require an empty line above it
9 * - `Array` specifies quoted keywords which require an empty line above it
10 *
11 * #### Example
12 *
13 * ```js
14 * "requirePaddingNewlinesBeforeKeywords": [
15 * "do",
16 * "for",
17 * "if",
18 * "else"
19 * // etc
20 * ]
21 * ```
22 *
23 * ##### Valid for mode `true`
24 *
25 * ```js
26 * function(a) {
27 * if (!a) {
28 * return false;
29 * }
30 *
31 * for (var i = 0; i < b; i++) {
32 * if (!a[i]) {
33 * return false;
34 * }
35 * }
36 *
37 * while (a) {
38 * a = false;
39 * }
40 * return true;
41 * }
42 * ```
43 *
44 * ##### Invalid
45 *
46 * ```js
47 * function(a) {
48 * if (!a) {
49 * return false;
50 * }
51 * for (var i = 0; i < b; i++) {
52 * if (!a[i]) {
53 * return false;
54 * }
55 * }
56 * while (a) {
57 * a = false;
58 * }
59 * return true;
60 * }
61 * ```
62 *
63 * ##### Valid for mode `['if', for']`
64 *
65 * ```js
66 * function(a) {
67 * if (!a) {
68 * return false;
69 * }
70 *
71 * for (var i = 0; i < b; i++) {
72 * if (!a[i]) {
73 * return false;
74 * }
75 * }
76 * while (a) {
77 * a = false;
78 * }
79 * return true;
80 * }
81 * ```
82 *
83 * ##### Invalid
84 *
85 * ```js
86 * function(a) {
87 * if (!a) {
88 * return false;
89 * }
90 * for (var i = 0; i < b; i++) {
91 * if (!a[i]) {
92 * return false;
93 * }
94 * }
95 * while (a) {
96 * a = false;
97 * }
98 * return true;
99 * }
100 * ```
101 *
102 */
103
104var assert = require('assert');
105var defaultKeywords = require('../utils').spacedKeywords;
106
107module.exports = function() { };
108
109module.exports.prototype = {
110
111 configure: function(keywords) {
112 assert(Array.isArray(keywords) || keywords === true,
113 this.getOptionName() + ' option requires array or true value');
114
115 if (keywords === true) {
116 keywords = defaultKeywords;
117 }
118
119 this._keywords = keywords;
120 },
121
122 getOptionName: function() {
123 return 'requirePaddingNewlinesBeforeKeywords';
124 },
125
126 check: function(file, errors) {
127 var excludedTokens = [':', ',', '(', '='];
128 var specialCases = { 'if': 'else' };
129 file.iterateTokensByTypeAndValue('Keyword', this._keywords, function(token) {
130 var prevToken = token.getPreviousCodeToken();
131
132 if (!prevToken) {
133 return;
134 }
135
136 // Handle special cases listed in specialCasesToken array
137 if (prevToken.value === specialCases[token.value]) {
138 return;
139 }
140
141 // allow returning a function
142 if (prevToken.value === 'return' && token.value === 'function') {
143 return;
144 }
145
146 // Do not report `do...while` statements
147 if (token.value === 'while' && token.parentElement.type === 'DoWhileStatement') {
148 return;
149 }
150
151 // Handle excludedTokens
152 if (excludedTokens.indexOf(prevToken.value) > -1) {
153 return;
154 }
155
156 // Handle all other cases
157 // The { character is there to handle the case of a matching token which happens to be the first
158 // statement in a block
159 // The ) character is there to handle the case of `if (...) matchingKeyword` in which case
160 // requiring padding would break the statement
161 if (prevToken.value !== '{' && prevToken.value !== ')') {
162 errors.assert.linesBetween({
163 token: prevToken,
164 nextToken: token,
165 atLeast: 2,
166 message: 'Keyword `' + token.value + '` should have an empty line above it'
167 });
168 }
169 });
170 }
171};