1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 |
|
25 |
|
26 |
|
27 |
|
28 |
|
29 |
|
30 |
|
31 |
|
32 |
|
33 |
|
34 |
|
35 |
|
36 |
|
37 |
|
38 |
|
39 |
|
40 |
|
41 |
|
42 |
|
43 |
|
44 |
|
45 |
|
46 |
|
47 |
|
48 |
|
49 | var assert = require('assert');
|
50 | var defaultKeywords = require('../utils').curlyBracedKeywords;
|
51 |
|
52 | module.exports = function() {};
|
53 |
|
54 | module.exports.prototype = {
|
55 |
|
56 | configure: function(options) {
|
57 | assert(
|
58 | Array.isArray(options) || options === true || typeof options === 'object',
|
59 | this.getOptionName() + ' option requires array, true value, or object'
|
60 | );
|
61 |
|
62 | var keywordMap = {
|
63 | 'return': 'ReturnStatement',
|
64 | 'break': 'BreakStatement',
|
65 | 'continue': 'ContinueStatement'
|
66 | };
|
67 |
|
68 | if (options === true) {
|
69 | options = defaultKeywords;
|
70 | }
|
71 |
|
72 | if (!Array.isArray(options)) {
|
73 | assert(
|
74 | Array.isArray(options.allExcept),
|
75 | this.getOptionName() + '.allExcept ' +
|
76 | 'property requires an array value'
|
77 | );
|
78 | assert(
|
79 | Array.isArray(options.keywords) || options.keywords === true,
|
80 | this.getOptionName() + '.keywords ' +
|
81 | 'property requires an array value or a value of true'
|
82 | );
|
83 |
|
84 | if (options.keywords === true) {
|
85 | options.keywords = defaultKeywords;
|
86 | }
|
87 |
|
88 | this._exceptions = options.allExcept.map(function(statementType) {
|
89 | return keywordMap[statementType];
|
90 | });
|
91 | options = options.keywords;
|
92 | }
|
93 |
|
94 | this._typeIndex = {};
|
95 | for (var i = 0, l = options.length; i < l; i++) {
|
96 | this._typeIndex[options[i]] = true;
|
97 | }
|
98 | },
|
99 |
|
100 | getOptionName: function() {
|
101 | return 'requireCurlyBraces';
|
102 | },
|
103 |
|
104 | check: function(file, errors) {
|
105 | var typeIndex = this._typeIndex;
|
106 | var exceptions = this._exceptions;
|
107 |
|
108 | function isNotABlockStatement(node) {
|
109 | return node && node.type !== 'BlockStatement';
|
110 | }
|
111 |
|
112 | function addError(typeString, entity) {
|
113 | errors.add(
|
114 | typeString + ' statement without curly braces',
|
115 | entity
|
116 | );
|
117 | }
|
118 |
|
119 | function checkBody(type, typeString) {
|
120 | file.iterateNodesByType(type, function(node) {
|
121 | if (isNotABlockStatement(node.body)) {
|
122 | addError(typeString, node);
|
123 | }
|
124 | });
|
125 | }
|
126 |
|
127 | if (typeIndex.if || typeIndex.else) {
|
128 | file.iterateNodesByType('IfStatement', function(node) {
|
129 | if (typeIndex.if && isNotABlockStatement(node.consequent) &&
|
130 |
|
131 | !(exceptions && exceptions.indexOf(node.consequent.type) !== -1)) {
|
132 |
|
133 | addError('If', node.firstChild);
|
134 | }
|
135 | if (typeIndex.else && isNotABlockStatement(node.alternate) &&
|
136 | node.alternate.type !== 'IfStatement' &&
|
137 |
|
138 | !(exceptions && exceptions.indexOf(node.consequent.type) !== -1)) {
|
139 | addError('Else', node.alternate.getPreviousCodeToken());
|
140 | }
|
141 | });
|
142 | }
|
143 |
|
144 | if (typeIndex.case || typeIndex.default) {
|
145 | file.iterateNodesByType('SwitchCase', function(node) {
|
146 |
|
147 | if (node.consequent.length === 0) {
|
148 | return;
|
149 | }
|
150 |
|
151 | if (node.consequent.length === 1 && node.consequent[0].type === 'BlockStatement') {
|
152 | return;
|
153 | }
|
154 |
|
155 | if (node.test === null && typeIndex.default) {
|
156 | addError('Default', node);
|
157 | }
|
158 |
|
159 | if (node.test !== null && typeIndex.case) {
|
160 | addError('Case', node);
|
161 | }
|
162 | });
|
163 | }
|
164 |
|
165 | if (typeIndex.while) {
|
166 | checkBody('WhileStatement', 'While');
|
167 | }
|
168 |
|
169 | if (typeIndex.for) {
|
170 | checkBody('ForStatement', 'For');
|
171 | checkBody('ForInStatement', 'For in');
|
172 | checkBody('ForOfStatement', 'For of');
|
173 | }
|
174 |
|
175 | if (typeIndex.do) {
|
176 | checkBody('DoWhileStatement', 'Do while');
|
177 | }
|
178 |
|
179 | if (typeIndex.with) {
|
180 | checkBody('WithStatement', 'With');
|
181 | }
|
182 | }
|
183 |
|
184 | };
|