eslint 0.5.0 → 0.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -8
- package/conf/environments.json +29 -12
- package/conf/eslint.json +7 -0
- package/lib/cli.js +21 -12
- package/lib/config.js +36 -13
- package/lib/eslint.js +218 -63
- package/lib/formatters/checkstyle.js +4 -6
- package/lib/formatters/compact.js +2 -5
- package/lib/formatters/junit.js +2 -5
- package/lib/formatters/stylish.js +2 -1
- package/lib/formatters/tap.js +3 -6
- package/lib/load-rules.js +3 -1
- package/lib/options.js +56 -47
- package/lib/rules/block-scoped-var.js +38 -4
- package/lib/rules/brace-style.js +6 -2
- package/lib/rules/default-case.js +64 -0
- package/lib/rules/eqeqeq.js +4 -0
- package/lib/rules/new-cap.js +1 -1
- package/lib/rules/no-comma-dangle.js +1 -1
- package/lib/rules/no-constant-condition.js +2 -1
- package/lib/rules/no-delete-var.js +1 -1
- package/lib/rules/no-else-return.js +1 -1
- package/lib/rules/no-extend-native.js +6 -2
- package/lib/rules/no-extra-parens.js +68 -33
- package/lib/rules/no-extra-strict.js +1 -1
- package/lib/rules/no-fallthrough.js +8 -0
- package/lib/rules/no-inner-declarations.js +70 -0
- package/lib/rules/no-invalid-regexp.js +2 -2
- package/lib/rules/no-lonely-if.js +28 -0
- package/lib/rules/no-mixed-requires.js +1 -1
- package/lib/rules/no-new-require.js +23 -0
- package/lib/rules/no-redeclare.js +4 -1
- package/lib/rules/no-restricted-modules.js +72 -0
- package/lib/rules/no-sequences.js +92 -0
- package/lib/rules/no-shadow-restricted-names.js +4 -2
- package/lib/rules/no-shadow.js +1 -1
- package/lib/rules/no-spaced-func.js +5 -3
- package/lib/rules/no-sparse-arrays.js +1 -3
- package/lib/rules/no-unused-vars.js +10 -4
- package/lib/rules/no-use-before-define.js +11 -2
- package/lib/rules/semi.js +11 -3
- package/lib/rules/sort-vars.js +1 -1
- package/lib/rules/space-after-keywords.js +64 -0
- package/lib/rules/space-infix-ops.js +11 -9
- package/lib/rules/space-return-throw-case.js +11 -3
- package/lib/rules/space-unary-word-ops.js +3 -2
- package/lib/rules/valid-jsdoc.js +18 -3
- package/package.json +8 -5
@@ -46,7 +46,16 @@ module.exports = function(context) {
|
|
46
46
|
* @returns {Boolean} true when the identifier is in property position.
|
47
47
|
*/
|
48
48
|
function isProperty(id, parent) {
|
49
|
-
|
49
|
+
switch (parent.type) {
|
50
|
+
case "MemberExpression":
|
51
|
+
return id === parent.property && !parent.computed;
|
52
|
+
|
53
|
+
case "Property":
|
54
|
+
return id === parent.key;
|
55
|
+
|
56
|
+
default:
|
57
|
+
return false;
|
58
|
+
}
|
50
59
|
}
|
51
60
|
|
52
61
|
/**
|
@@ -84,6 +93,13 @@ module.exports = function(context) {
|
|
84
93
|
return id.name;
|
85
94
|
}));
|
86
95
|
declare(node.id ? [node.id.name] : []);
|
96
|
+
declare(["arguments"]);
|
97
|
+
}
|
98
|
+
|
99
|
+
function variableDeclarationHandler(node) {
|
100
|
+
declare(node.declarations.map(function(decl) {
|
101
|
+
return decl.id.name;
|
102
|
+
}));
|
87
103
|
}
|
88
104
|
|
89
105
|
return {
|
@@ -98,9 +114,7 @@ module.exports = function(context) {
|
|
98
114
|
pushScope();
|
99
115
|
statements.forEach(function(stmt) {
|
100
116
|
if (stmt.type === "VariableDeclaration") {
|
101
|
-
|
102
|
-
return decl.id.name;
|
103
|
-
}));
|
117
|
+
variableDeclarationHandler(stmt);
|
104
118
|
} else if (stmt.type === "FunctionDeclaration") {
|
105
119
|
declare([stmt.id.name]);
|
106
120
|
}
|
@@ -113,9 +127,29 @@ module.exports = function(context) {
|
|
113
127
|
pushScope();
|
114
128
|
declare([node.param.name]);
|
115
129
|
},
|
130
|
+
"CatchClause:exit": popScope,
|
116
131
|
|
117
132
|
"FunctionDeclaration": functionHandler,
|
133
|
+
"FunctionDeclaration:exit": popScope,
|
134
|
+
|
118
135
|
"FunctionExpression": functionHandler,
|
136
|
+
"FunctionExpression:exit": popScope,
|
137
|
+
|
138
|
+
"ForStatement": function(node) {
|
139
|
+
pushScope();
|
140
|
+
if (node.init && node.init.type === "VariableDeclaration") {
|
141
|
+
variableDeclarationHandler(node.init);
|
142
|
+
}
|
143
|
+
},
|
144
|
+
"ForStatement:exit": popScope,
|
145
|
+
|
146
|
+
"ForInStatement": function(node) {
|
147
|
+
pushScope();
|
148
|
+
if (node.left.type === "VariableDeclaration") {
|
149
|
+
variableDeclarationHandler(node.left);
|
150
|
+
}
|
151
|
+
},
|
152
|
+
"ForInStatement:exit": popScope,
|
119
153
|
|
120
154
|
"Identifier": function(node) {
|
121
155
|
var ancestor = context.getAncestors().pop();
|
package/lib/rules/brace-style.js
CHANGED
@@ -13,6 +13,7 @@ module.exports = function(context) {
|
|
13
13
|
var style = context.options[0] || "1tbs";
|
14
14
|
|
15
15
|
var OPEN_MESSAGE = "Opening curly brace does not appear on the same line as controlling statement.",
|
16
|
+
BODY_MESSAGE = "Statement inside of curly braces should be on next line.",
|
16
17
|
CLOSE_MESSAGE = "Closing curly brace does not appear on the same line as the subsequent block.",
|
17
18
|
CLOSE_MESSAGE_STROUSTRUP = "Closing curly brace appears on the same line as the subsequent block.";
|
18
19
|
|
@@ -33,11 +34,14 @@ module.exports = function(context) {
|
|
33
34
|
[].forEach.call(blockProperties, function(blockProp) {
|
34
35
|
var block = node[blockProp], previousToken, curlyToken;
|
35
36
|
block = node[blockProp];
|
36
|
-
if(block && block.type === "BlockStatement") {
|
37
|
+
if (block && block.type === "BlockStatement") {
|
37
38
|
previousToken = context.getTokenBefore(block);
|
38
39
|
curlyToken = context.getFirstToken(block);
|
40
|
+
|
39
41
|
if (previousToken.loc.start.line !== curlyToken.loc.start.line) {
|
40
42
|
context.report(node, OPEN_MESSAGE);
|
43
|
+
} else if (block.body.length && curlyToken.loc.start.line === block.body[0].loc.start.line) {
|
44
|
+
context.report(block.body[0], BODY_MESSAGE);
|
41
45
|
}
|
42
46
|
}
|
43
47
|
});
|
@@ -123,7 +127,7 @@ module.exports = function(context) {
|
|
123
127
|
*/
|
124
128
|
function checkSwitchStatement(node) {
|
125
129
|
var tokens;
|
126
|
-
if(node.cases && node.cases.length) {
|
130
|
+
if (node.cases && node.cases.length) {
|
127
131
|
tokens = context.getTokensBefore(node.cases[0], 2);
|
128
132
|
if (tokens[0].loc.start.line !== tokens[1].loc.start.line) {
|
129
133
|
context.report(node, OPEN_MESSAGE);
|
@@ -0,0 +1,64 @@
|
|
1
|
+
/**
|
2
|
+
* @fileoverview require default case in switch statements
|
3
|
+
* @author Aliaksei Shytkin
|
4
|
+
*/
|
5
|
+
"use strict";
|
6
|
+
|
7
|
+
var COMMENT_VALUE = "no default";
|
8
|
+
|
9
|
+
//------------------------------------------------------------------------------
|
10
|
+
// Rule Definition
|
11
|
+
//------------------------------------------------------------------------------
|
12
|
+
|
13
|
+
module.exports = function(context) {
|
14
|
+
|
15
|
+
//--------------------------------------------------------------------------
|
16
|
+
// Helpers
|
17
|
+
//--------------------------------------------------------------------------
|
18
|
+
|
19
|
+
/**
|
20
|
+
* Shortcut to get last element of array
|
21
|
+
* @param {*[]} collection Array
|
22
|
+
* @returns {*} Last element
|
23
|
+
*/
|
24
|
+
function last(collection) {
|
25
|
+
return collection[collection.length - 1];
|
26
|
+
}
|
27
|
+
|
28
|
+
//--------------------------------------------------------------------------
|
29
|
+
// Public
|
30
|
+
//--------------------------------------------------------------------------
|
31
|
+
|
32
|
+
return {
|
33
|
+
|
34
|
+
"SwitchStatement": function(node) {
|
35
|
+
|
36
|
+
if (!node.cases.length) {
|
37
|
+
// skip check of empty switch because there is no easy way
|
38
|
+
// to extract comments inside it now
|
39
|
+
return;
|
40
|
+
}
|
41
|
+
|
42
|
+
var hasDefault = node.cases.some(function(v) {
|
43
|
+
return v.test === null;
|
44
|
+
});
|
45
|
+
|
46
|
+
if (!hasDefault) {
|
47
|
+
|
48
|
+
var comment;
|
49
|
+
var comments;
|
50
|
+
|
51
|
+
var lastCase = last(node.cases);
|
52
|
+
comments = context.getComments(lastCase).trailing;
|
53
|
+
|
54
|
+
if (comments.length) {
|
55
|
+
comment = last(comments);
|
56
|
+
}
|
57
|
+
|
58
|
+
if (!comment || comment.value.trim() !== COMMENT_VALUE) {
|
59
|
+
context.report(node, "Expected a default case.");
|
60
|
+
}
|
61
|
+
}
|
62
|
+
}
|
63
|
+
};
|
64
|
+
};
|
package/lib/rules/eqeqeq.js
CHANGED
@@ -36,6 +36,10 @@ module.exports = function(context) {
|
|
36
36
|
return;
|
37
37
|
}
|
38
38
|
|
39
|
+
if (context.options[0] === "allow-null" && isNullCheck(node)) {
|
40
|
+
return;
|
41
|
+
}
|
42
|
+
|
39
43
|
if (operator === "==") {
|
40
44
|
context.report(node, "Expected '===' and instead saw '=='.");
|
41
45
|
} else if (operator === "!=") {
|
package/lib/rules/new-cap.js
CHANGED
@@ -22,7 +22,7 @@ module.exports = function(context) {
|
|
22
22
|
constructorName = node.callee.name;
|
23
23
|
}
|
24
24
|
|
25
|
-
if (constructorName && constructorName.charAt(0)
|
25
|
+
if (constructorName && constructorName.charAt(0) !== constructorName.charAt(0).toUpperCase()) {
|
26
26
|
context.report(node, "A constructor name should start with an uppercase letter.");
|
27
27
|
}
|
28
28
|
}
|
@@ -22,7 +22,7 @@ module.exports = function(context) {
|
|
22
22
|
lastItem = items[items.length - 1];
|
23
23
|
// The last token in an object/array literal will always be a closing
|
24
24
|
// curly, so we check the second to last token for a comma.
|
25
|
-
if(secondToLastToken.value === "," && items.length && lastItem) {
|
25
|
+
if (secondToLastToken.value === "," && items.length && lastItem) {
|
26
26
|
context.report(lastItem, secondToLastToken.loc.start, "Trailing comma.");
|
27
27
|
}
|
28
28
|
}
|
@@ -23,7 +23,7 @@ module.exports = function(context) {
|
|
23
23
|
* @private
|
24
24
|
*/
|
25
25
|
function isConstant(node) {
|
26
|
-
switch(node.type) {
|
26
|
+
switch (node.type) {
|
27
27
|
case "Literal":
|
28
28
|
case "FunctionExpression":
|
29
29
|
case "ObjectExpression":
|
@@ -38,6 +38,7 @@ module.exports = function(context) {
|
|
38
38
|
return isConstant(node.right);
|
39
39
|
case "SequenceExpression":
|
40
40
|
return isConstant(node.expressions[node.expressions.length - 1]);
|
41
|
+
// no default
|
41
42
|
}
|
42
43
|
return false;
|
43
44
|
}
|
@@ -15,7 +15,7 @@ module.exports = function(context) {
|
|
15
15
|
|
16
16
|
"UnaryExpression": function(node) {
|
17
17
|
if (node.operator === "delete" && node.argument.type === "Identifier") {
|
18
|
-
context.report(node, "Variables should not be deleted
|
18
|
+
context.report(node, "Variables should not be deleted.");
|
19
19
|
}
|
20
20
|
}
|
21
21
|
};
|
@@ -17,7 +17,7 @@ module.exports = function(context) {
|
|
17
17
|
|
18
18
|
function checkForReturnStatement(node, alternate) {
|
19
19
|
if (node.type === "ReturnStatement") {
|
20
|
-
context.report(alternate, "Unexpected 'else' after 'return'
|
20
|
+
context.report(alternate, "Unexpected 'else' after 'return'.");
|
21
21
|
}
|
22
22
|
}
|
23
23
|
|
@@ -27,13 +27,17 @@ module.exports = function(context) {
|
|
27
27
|
"AssignmentExpression": function(node) {
|
28
28
|
var lhs = node.left, affectsProto;
|
29
29
|
|
30
|
-
if (lhs.type !== "MemberExpression" || lhs.object.type !== "MemberExpression") {
|
30
|
+
if (lhs.type !== "MemberExpression" || lhs.object.type !== "MemberExpression") {
|
31
|
+
return;
|
32
|
+
}
|
31
33
|
|
32
34
|
affectsProto = lhs.object.computed ?
|
33
35
|
lhs.object.property.type === "Literal" && lhs.object.property.value === "prototype" :
|
34
36
|
lhs.object.property.name === "prototype";
|
35
37
|
|
36
|
-
if (!affectsProto) {
|
38
|
+
if (!affectsProto) {
|
39
|
+
return;
|
40
|
+
}
|
37
41
|
|
38
42
|
BUILTINS.forEach(function(builtin) {
|
39
43
|
if (lhs.object.object.name === builtin) {
|
@@ -30,7 +30,7 @@ module.exports = function(context) {
|
|
30
30
|
|
31
31
|
function precedence(node) {
|
32
32
|
|
33
|
-
switch(node.type) {
|
33
|
+
switch (node.type) {
|
34
34
|
case "SequenceExpression":
|
35
35
|
return 0;
|
36
36
|
|
@@ -41,16 +41,17 @@ module.exports = function(context) {
|
|
41
41
|
return 3;
|
42
42
|
|
43
43
|
case "LogicalExpression":
|
44
|
-
switch(node.operator) {
|
44
|
+
switch (node.operator) {
|
45
45
|
case "||":
|
46
46
|
return 4;
|
47
47
|
case "&&":
|
48
48
|
return 5;
|
49
|
+
// no default
|
49
50
|
}
|
50
51
|
|
51
52
|
/* falls through */
|
52
53
|
case "BinaryExpression":
|
53
|
-
switch(node.operator) {
|
54
|
+
switch (node.operator) {
|
54
55
|
case "|":
|
55
56
|
return 6;
|
56
57
|
case "^":
|
@@ -80,6 +81,7 @@ module.exports = function(context) {
|
|
80
81
|
case "/":
|
81
82
|
case "%":
|
82
83
|
return 13;
|
84
|
+
// no default
|
83
85
|
}
|
84
86
|
/* falls through */
|
85
87
|
case "UnaryExpression":
|
@@ -87,9 +89,14 @@ module.exports = function(context) {
|
|
87
89
|
case "UpdateExpression":
|
88
90
|
return 15;
|
89
91
|
case "CallExpression":
|
92
|
+
// IIFE is allowed to have parens in any position (#655)
|
93
|
+
if (node.callee.type === "FunctionExpression") {
|
94
|
+
return -1;
|
95
|
+
}
|
90
96
|
return 16;
|
91
97
|
case "NewExpression":
|
92
98
|
return 17;
|
99
|
+
// no default
|
93
100
|
}
|
94
101
|
return 18;
|
95
102
|
}
|
@@ -99,22 +106,22 @@ module.exports = function(context) {
|
|
99
106
|
}
|
100
107
|
|
101
108
|
function dryUnaryUpdate(node) {
|
102
|
-
if(isParenthesised(node.argument) && precedence(node.argument) >= precedence(node)) {
|
109
|
+
if (isParenthesised(node.argument) && precedence(node.argument) >= precedence(node)) {
|
103
110
|
report(node.argument);
|
104
111
|
}
|
105
112
|
}
|
106
113
|
|
107
114
|
function dryCallNew(node) {
|
108
|
-
if(isParenthesised(node.callee) && precedence(node.callee) >= precedence(node)) {
|
115
|
+
if (isParenthesised(node.callee) && precedence(node.callee) >= precedence(node)) {
|
109
116
|
report(node.callee);
|
110
117
|
}
|
111
|
-
if(node.arguments.length === 1) {
|
112
|
-
if(isParenthesisedTwice(node.arguments[0]) && precedence(node.arguments[0]) >= precedence({type: "AssignmentExpression"})) {
|
118
|
+
if (node.arguments.length === 1) {
|
119
|
+
if (isParenthesisedTwice(node.arguments[0]) && precedence(node.arguments[0]) >= precedence({type: "AssignmentExpression"})) {
|
113
120
|
report(node.arguments[0]);
|
114
121
|
}
|
115
122
|
} else {
|
116
123
|
[].forEach.call(node.arguments, function(arg){
|
117
|
-
if(isParenthesised(arg) && precedence(arg) >= precedence({type: "AssignmentExpression"})) {
|
124
|
+
if (isParenthesised(arg) && precedence(arg) >= precedence({type: "AssignmentExpression"})) {
|
118
125
|
report(arg);
|
119
126
|
}
|
120
127
|
});
|
@@ -123,10 +130,10 @@ module.exports = function(context) {
|
|
123
130
|
|
124
131
|
function dryBinaryLogical(node) {
|
125
132
|
var prec = precedence(node);
|
126
|
-
if(isParenthesised(node.left) && precedence(node.left) >= prec) {
|
133
|
+
if (isParenthesised(node.left) && precedence(node.left) >= prec) {
|
127
134
|
report(node.left);
|
128
135
|
}
|
129
|
-
if(isParenthesised(node.right) && precedence(node.right) > prec) {
|
136
|
+
if (isParenthesised(node.right) && precedence(node.right) > prec) {
|
130
137
|
report(node.right);
|
131
138
|
}
|
132
139
|
}
|
@@ -134,55 +141,69 @@ module.exports = function(context) {
|
|
134
141
|
return {
|
135
142
|
"ArrayExpression": function(node) {
|
136
143
|
[].forEach.call(node.elements, function(e) {
|
137
|
-
if(e && isParenthesised(e) && precedence(e) >= precedence({type: "AssignmentExpression"})) {
|
144
|
+
if (e && isParenthesised(e) && precedence(e) >= precedence({type: "AssignmentExpression"})) {
|
138
145
|
report(e);
|
139
146
|
}
|
140
147
|
});
|
141
148
|
},
|
142
149
|
"AssignmentExpression": function(node) {
|
143
|
-
if(isParenthesised(node.right) && precedence(node.right) >= precedence(node)) {
|
150
|
+
if (isParenthesised(node.right) && precedence(node.right) >= precedence(node)) {
|
144
151
|
report(node.right);
|
145
152
|
}
|
146
153
|
},
|
147
154
|
"BinaryExpression": dryBinaryLogical,
|
148
155
|
"CallExpression": dryCallNew,
|
149
156
|
"ConditionalExpression": function(node) {
|
150
|
-
if(isParenthesised(node.test) && precedence(node.test) >= precedence({type: "LogicalExpression", operator: "||"})) {
|
157
|
+
if (isParenthesised(node.test) && precedence(node.test) >= precedence({type: "LogicalExpression", operator: "||"})) {
|
151
158
|
report(node.test);
|
152
159
|
}
|
153
|
-
if(isParenthesised(node.consequent) && precedence(node.consequent) >= precedence({type: "AssignmentExpression"})) {
|
160
|
+
if (isParenthesised(node.consequent) && precedence(node.consequent) >= precedence({type: "AssignmentExpression"})) {
|
154
161
|
report(node.consequent);
|
155
162
|
}
|
156
|
-
if(isParenthesised(node.alternate) && precedence(node.alternate) >= precedence({type: "AssignmentExpression"})) {
|
163
|
+
if (isParenthesised(node.alternate) && precedence(node.alternate) >= precedence({type: "AssignmentExpression"})) {
|
157
164
|
report(node.alternate);
|
158
165
|
}
|
159
166
|
},
|
160
167
|
"DoWhileStatement": function(node) {
|
161
|
-
if(isParenthesisedTwice(node.test)) {
|
168
|
+
if (isParenthesisedTwice(node.test)) {
|
169
|
+
report(node.test);
|
170
|
+
}
|
162
171
|
},
|
163
172
|
"ExpressionStatement": function(node) {
|
164
173
|
var firstToken;
|
165
|
-
if(isParenthesised(node.expression)) {
|
174
|
+
if (isParenthesised(node.expression)) {
|
166
175
|
firstToken = context.getFirstToken(node.expression);
|
167
|
-
if(firstToken.value !== "function" && firstToken.value !== "{") {
|
176
|
+
if (firstToken.value !== "function" && firstToken.value !== "{") {
|
168
177
|
report(node.expression);
|
169
178
|
}
|
170
179
|
}
|
171
180
|
},
|
172
181
|
"ForInStatement": function(node) {
|
173
|
-
if(isParenthesised(node.right)) {
|
182
|
+
if (isParenthesised(node.right)) {
|
183
|
+
report(node.right);
|
184
|
+
}
|
174
185
|
},
|
175
186
|
"ForStatement": function(node) {
|
176
|
-
if(node.init && isParenthesised(node.init)) {
|
177
|
-
|
178
|
-
|
187
|
+
if (node.init && isParenthesised(node.init)) {
|
188
|
+
report(node.init);
|
189
|
+
}
|
190
|
+
|
191
|
+
if (node.test && isParenthesised(node.test)) {
|
192
|
+
report(node.test);
|
193
|
+
}
|
194
|
+
|
195
|
+
if (node.update && isParenthesised(node.update)) {
|
196
|
+
report(node.update);
|
197
|
+
}
|
179
198
|
},
|
180
199
|
"IfStatement": function(node) {
|
181
|
-
if(isParenthesisedTwice(node.test)) {
|
200
|
+
if (isParenthesisedTwice(node.test)) {
|
201
|
+
report(node.test);
|
202
|
+
}
|
182
203
|
},
|
183
204
|
"LogicalExpression": dryBinaryLogical,
|
184
205
|
"MemberExpression": function(node) {
|
185
|
-
if(
|
206
|
+
if (
|
186
207
|
isParenthesised(node.object) &&
|
187
208
|
precedence(node.object) >= precedence(node) &&
|
188
209
|
(
|
@@ -201,40 +222,54 @@ module.exports = function(context) {
|
|
201
222
|
"ObjectExpression": function(node) {
|
202
223
|
[].forEach.call(node.properties, function(e) {
|
203
224
|
var v = e.value;
|
204
|
-
if(v && isParenthesised(v) && precedence(v) >= precedence({type: "AssignmentExpression"})) {
|
225
|
+
if (v && isParenthesised(v) && precedence(v) >= precedence({type: "AssignmentExpression"})) {
|
205
226
|
report(v);
|
206
227
|
}
|
207
228
|
});
|
208
229
|
},
|
209
230
|
"ReturnStatement": function(node) {
|
210
|
-
if(node.argument && isParenthesised(node.argument)) {
|
231
|
+
if (node.argument && isParenthesised(node.argument)) {
|
232
|
+
report(node.argument);
|
233
|
+
}
|
211
234
|
},
|
212
235
|
"SequenceExpression": function(node) {
|
213
236
|
[].forEach.call(node.expressions, function(e) {
|
214
|
-
if(isParenthesised(e)
|
237
|
+
if (isParenthesised(e) && precedence(e) >= precedence(node)) {
|
238
|
+
report(e);
|
239
|
+
}
|
215
240
|
});
|
216
241
|
},
|
217
242
|
"SwitchCase": function(node) {
|
218
|
-
if(node.test && isParenthesised(node.test)) {
|
243
|
+
if (node.test && isParenthesised(node.test)) {
|
244
|
+
report(node.test);
|
245
|
+
}
|
219
246
|
},
|
220
247
|
"SwitchStatement": function(node) {
|
221
|
-
if(isParenthesisedTwice(node.discriminant)) {
|
248
|
+
if (isParenthesisedTwice(node.discriminant)) {
|
249
|
+
report(node.discriminant);
|
250
|
+
}
|
222
251
|
},
|
223
252
|
"ThrowStatement": function(node) {
|
224
|
-
if(isParenthesised(node.argument)) {
|
253
|
+
if (isParenthesised(node.argument)) {
|
254
|
+
report(node.argument);
|
255
|
+
}
|
225
256
|
},
|
226
257
|
"UnaryExpression": dryUnaryUpdate,
|
227
258
|
"UpdateExpression": dryUnaryUpdate,
|
228
259
|
"VariableDeclarator": function(node) {
|
229
|
-
if(node.init && isParenthesised(node.init) && precedence(node.init) >= precedence({type: "AssignmentExpression"})) {
|
260
|
+
if (node.init && isParenthesised(node.init) && precedence(node.init) >= precedence({type: "AssignmentExpression"})) {
|
230
261
|
report(node.init);
|
231
262
|
}
|
232
263
|
},
|
233
264
|
"WhileStatement": function(node) {
|
234
|
-
if(isParenthesisedTwice(node.test)) {
|
265
|
+
if (isParenthesisedTwice(node.test)) {
|
266
|
+
report(node.test);
|
267
|
+
}
|
235
268
|
},
|
236
269
|
"WithStatement": function(node) {
|
237
|
-
if(isParenthesisedTwice(node.object)) {
|
270
|
+
if (isParenthesisedTwice(node.object)) {
|
271
|
+
report(node.object);
|
272
|
+
}
|
238
273
|
}
|
239
274
|
};
|
240
275
|
|
@@ -25,6 +25,14 @@ module.exports = function(context) {
|
|
25
25
|
comments,
|
26
26
|
comment;
|
27
27
|
|
28
|
+
/*
|
29
|
+
* Some developers wrap case bodies in blocks, so if there is just one
|
30
|
+
* node and it's a block statement, check inside.
|
31
|
+
*/
|
32
|
+
if (consequent.length === 1 && consequent[0].type === "BlockStatement") {
|
33
|
+
consequent = consequent[0];
|
34
|
+
}
|
35
|
+
|
28
36
|
// checking on previous case
|
29
37
|
if (!switchData.lastCaseClosed) {
|
30
38
|
|
@@ -0,0 +1,70 @@
|
|
1
|
+
/**
|
2
|
+
* @fileoverview Rule to enforce declarations in program or function body root.
|
3
|
+
* @author Brandon Mills
|
4
|
+
*/
|
5
|
+
|
6
|
+
//------------------------------------------------------------------------------
|
7
|
+
// Rule Definition
|
8
|
+
//------------------------------------------------------------------------------
|
9
|
+
|
10
|
+
module.exports = function(context) {
|
11
|
+
|
12
|
+
"use strict";
|
13
|
+
|
14
|
+
/**
|
15
|
+
* Find the nearest Program or Function ancestor node.
|
16
|
+
* @returns {Object} Ancestor's type and distance from node.
|
17
|
+
*/
|
18
|
+
function nearestBody() {
|
19
|
+
var ancestors = context.getAncestors(),
|
20
|
+
ancestor = ancestors.pop(),
|
21
|
+
generation = 1;
|
22
|
+
|
23
|
+
while (ancestor && ["Program", "FunctionDeclaration",
|
24
|
+
"FunctionExpression"].indexOf(ancestor.type) < 0) {
|
25
|
+
generation += 1;
|
26
|
+
ancestor = ancestors.pop();
|
27
|
+
}
|
28
|
+
|
29
|
+
return {
|
30
|
+
// Type of containing ancestor
|
31
|
+
type: ancestor.type,
|
32
|
+
// Separation between ancestor and node
|
33
|
+
distance: generation
|
34
|
+
};
|
35
|
+
}
|
36
|
+
|
37
|
+
/**
|
38
|
+
* Ensure that a given node is at a program or function body's root.
|
39
|
+
* @param {ASTNode} node Declaration node to check.
|
40
|
+
* @returns {void}
|
41
|
+
*/
|
42
|
+
function check(node) {
|
43
|
+
var body = nearestBody(node),
|
44
|
+
valid = ((body.type === "Program" && body.distance === 1) ||
|
45
|
+
body.distance === 2);
|
46
|
+
|
47
|
+
if (!valid) {
|
48
|
+
context.report(node, "Move {{type}} declaration to {{body}} root.",
|
49
|
+
{
|
50
|
+
type: (node.type === "FunctionDeclaration" ?
|
51
|
+
"function" : "variable"),
|
52
|
+
body: (body.type === "Program" ?
|
53
|
+
"program" : "function body")
|
54
|
+
}
|
55
|
+
);
|
56
|
+
}
|
57
|
+
}
|
58
|
+
|
59
|
+
return {
|
60
|
+
|
61
|
+
"FunctionDeclaration": check,
|
62
|
+
"VariableDeclaration": function(node) {
|
63
|
+
if (context.options[0] === "both") {
|
64
|
+
check(node);
|
65
|
+
}
|
66
|
+
}
|
67
|
+
|
68
|
+
};
|
69
|
+
|
70
|
+
};
|
@@ -15,9 +15,9 @@ module.exports = function(context) {
|
|
15
15
|
}
|
16
16
|
|
17
17
|
function check(node) {
|
18
|
-
if(node.callee.type === "Identifier" && node.callee.name === "RegExp" && isString(node.arguments[0])) {
|
18
|
+
if (node.callee.type === "Identifier" && node.callee.name === "RegExp" && isString(node.arguments[0])) {
|
19
19
|
try {
|
20
|
-
if(isString(node.arguments[1])) {
|
20
|
+
if (isString(node.arguments[1])) {
|
21
21
|
void new RegExp(node.arguments[0].value, node.arguments[1].value);
|
22
22
|
} else {
|
23
23
|
void new RegExp(node.arguments[0].value);
|
@@ -0,0 +1,28 @@
|
|
1
|
+
/**
|
2
|
+
* @fileoverview Rule to disallow if as the only statmenet in an else block
|
3
|
+
* @author Brandon Mills
|
4
|
+
*/
|
5
|
+
"use strict";
|
6
|
+
|
7
|
+
//------------------------------------------------------------------------------
|
8
|
+
// Rule Definition
|
9
|
+
//------------------------------------------------------------------------------
|
10
|
+
|
11
|
+
module.exports = function(context) {
|
12
|
+
|
13
|
+
return {
|
14
|
+
"IfStatement": function(node) {
|
15
|
+
var ancestors = context.getAncestors(),
|
16
|
+
parent = ancestors.pop(),
|
17
|
+
grandparent = ancestors.pop();
|
18
|
+
|
19
|
+
if (parent && parent.type === "BlockStatement" &&
|
20
|
+
parent.body.length === 1 && grandparent &&
|
21
|
+
grandparent.type === "IfStatement" &&
|
22
|
+
parent === grandparent.alternate) {
|
23
|
+
context.report(node, "Unexpected if as the only statement in an else block.");
|
24
|
+
}
|
25
|
+
}
|
26
|
+
};
|
27
|
+
|
28
|
+
};
|
@@ -127,7 +127,7 @@ module.exports = function(context) {
|
|
127
127
|
var found = {};
|
128
128
|
|
129
129
|
declarations.forEach(function (declaration) {
|
130
|
-
if(getDeclarationType(declaration.init) === DECL_REQUIRE) {
|
130
|
+
if (getDeclarationType(declaration.init) === DECL_REQUIRE) {
|
131
131
|
found[inferModuleType(declaration.init)] = true;
|
132
132
|
}
|
133
133
|
});
|