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 |
|
104 | var assert = require('assert');
|
105 | var defaultKeywords = require('../utils').spacedKeywords;
|
106 |
|
107 | module.exports = function() { };
|
108 |
|
109 | module.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 | };
|