eslint 1.9.0 → 1.10.3
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 +1 -1
- package/bin/eslint.js +1 -2
- package/lib/ast-utils.js +22 -1
- package/lib/cli-engine.js +15 -7
- package/lib/cli.js +2 -1
- package/lib/config/config-file.js +440 -0
- package/lib/config/config-initializer.js +241 -0
- package/lib/config/config-ops.js +186 -0
- package/lib/{config-validator.js → config/config-validator.js} +10 -2
- package/lib/config.js +39 -183
- package/lib/eslint.js +49 -41
- package/lib/file-finder.js +34 -15
- package/lib/ignored-paths.js +1 -1
- package/lib/options.js +7 -1
- package/lib/rules/block-spacing.js +7 -2
- package/lib/rules/brace-style.js +3 -1
- package/lib/rules/comma-spacing.js +25 -66
- package/lib/rules/consistent-this.js +25 -29
- package/lib/rules/curly.js +37 -7
- package/lib/rules/eqeqeq.js +17 -2
- package/lib/rules/id-length.js +2 -2
- package/lib/rules/indent.js +7 -10
- package/lib/rules/lines-around-comment.js +32 -12
- package/lib/rules/new-cap.js +11 -1
- package/lib/rules/no-alert.js +2 -3
- package/lib/rules/no-catch-shadow.js +7 -13
- package/lib/rules/no-extend-native.js +1 -2
- package/lib/rules/no-fallthrough.js +1 -2
- package/lib/rules/no-implicit-coercion.js +19 -0
- package/lib/rules/no-label-var.js +9 -23
- package/lib/rules/no-multiple-empty-lines.js +1 -1
- package/lib/rules/no-sequences.js +2 -1
- package/lib/rules/no-shadow.js +31 -58
- package/lib/rules/no-spaced-func.js +16 -12
- package/lib/rules/no-undef-init.js +5 -3
- package/lib/rules/no-undef.js +10 -13
- package/lib/rules/no-use-before-define.js +7 -21
- package/lib/rules/operator-linebreak.js +3 -2
- package/lib/rules/quotes.js +34 -15
- package/lib/rules/require-jsdoc.js +61 -2
- package/lib/rules/space-after-keywords.js +2 -0
- package/lib/rules/space-before-function-paren.js +5 -26
- package/lib/rules/space-before-keywords.js +5 -2
- package/lib/rules/spaced-comment.js +1 -3
- package/lib/rules/valid-jsdoc.js +8 -4
- package/lib/rules/vars-on-top.js +2 -2
- package/lib/testers/rule-tester.js +48 -7
- package/lib/util/source-code.js +4 -0
- package/lib/util.js +0 -92
- package/package.json +4 -6
- package/lib/config-initializer.js +0 -146
package/lib/options.js
CHANGED
@@ -112,7 +112,7 @@ module.exports = optionator({
|
|
112
112
|
},
|
113
113
|
{
|
114
114
|
option: "ignore-pattern",
|
115
|
-
type: "String",
|
115
|
+
type: "[String]",
|
116
116
|
description: "Pattern of files to ignore (in addition to those in .eslintignore)"
|
117
117
|
},
|
118
118
|
{
|
@@ -198,6 +198,12 @@ module.exports = optionator({
|
|
198
198
|
alias: "v",
|
199
199
|
type: "Boolean",
|
200
200
|
description: "Outputs the version number"
|
201
|
+
},
|
202
|
+
{
|
203
|
+
option: "inline-config",
|
204
|
+
type: "Boolean",
|
205
|
+
default: "true",
|
206
|
+
description: "Allow comments to change eslint config/rules"
|
201
207
|
}
|
202
208
|
]
|
203
209
|
});
|
@@ -59,8 +59,8 @@ module.exports = function(context) {
|
|
59
59
|
// Gets braces and the first/last token of content.
|
60
60
|
var openBrace = getOpenBrace(node);
|
61
61
|
var closeBrace = context.getLastToken(node);
|
62
|
-
var firstToken =
|
63
|
-
var lastToken =
|
62
|
+
var firstToken = sourceCode.getTokenOrCommentAfter(openBrace);
|
63
|
+
var lastToken = sourceCode.getTokenOrCommentBefore(closeBrace);
|
64
64
|
|
65
65
|
// Skip if the node is invalid or empty.
|
66
66
|
if (openBrace.type !== "Punctuator" ||
|
@@ -72,6 +72,11 @@ module.exports = function(context) {
|
|
72
72
|
return;
|
73
73
|
}
|
74
74
|
|
75
|
+
// Skip line comments for option never
|
76
|
+
if (!always && firstToken.type === "Line") {
|
77
|
+
return;
|
78
|
+
}
|
79
|
+
|
75
80
|
// Check.
|
76
81
|
if (!isValid(openBrace, firstToken)) {
|
77
82
|
context.report({
|
package/lib/rules/brace-style.js
CHANGED
@@ -109,7 +109,9 @@ module.exports = function(context) {
|
|
109
109
|
tokens = context.getTokensBefore(node.alternate, 2);
|
110
110
|
|
111
111
|
if (style === "1tbs") {
|
112
|
-
if (tokens[0].loc.start.line !== tokens[1].loc.start.line &&
|
112
|
+
if (tokens[0].loc.start.line !== tokens[1].loc.start.line &&
|
113
|
+
node.consequent.type === "BlockStatement" &&
|
114
|
+
isCurlyPunctuator(tokens[0]) ) {
|
113
115
|
context.report(node.alternate, CLOSE_MESSAGE);
|
114
116
|
}
|
115
117
|
} else if (tokens[0].loc.start.line === tokens[1].loc.start.line) {
|
@@ -14,6 +14,7 @@ var astUtils = require("../ast-utils");
|
|
14
14
|
module.exports = function(context) {
|
15
15
|
|
16
16
|
var sourceCode = context.getSourceCode();
|
17
|
+
var tokensAndComments = sourceCode.tokensAndComments;
|
17
18
|
|
18
19
|
var options = {
|
19
20
|
before: context.options[0] ? !!context.options[0].before : false,
|
@@ -24,10 +25,6 @@ module.exports = function(context) {
|
|
24
25
|
// Helpers
|
25
26
|
//--------------------------------------------------------------------------
|
26
27
|
|
27
|
-
// the index of the last comment that was checked
|
28
|
-
var lastCommentIndex = 0;
|
29
|
-
var allComments;
|
30
|
-
|
31
28
|
// list of comma tokens to ignore for the check of leading whitespace
|
32
29
|
var commaTokensToIgnore = [];
|
33
30
|
|
@@ -41,39 +38,6 @@ module.exports = function(context) {
|
|
41
38
|
return !!token && (token.type === "Punctuator") && (token.value === ",");
|
42
39
|
}
|
43
40
|
|
44
|
-
/**
|
45
|
-
* Determines if a given source index is in a comment or not by checking
|
46
|
-
* the index against the comment range. Since the check goes straight
|
47
|
-
* through the file, once an index is passed a certain comment, we can
|
48
|
-
* go to the next comment to check that.
|
49
|
-
* @param {int} index The source index to check.
|
50
|
-
* @param {ASTNode[]} comments An array of comment nodes.
|
51
|
-
* @returns {boolean} True if the index is within a comment, false if not.
|
52
|
-
* @private
|
53
|
-
*/
|
54
|
-
function isIndexInComment(index, comments) {
|
55
|
-
|
56
|
-
var comment;
|
57
|
-
lastCommentIndex = 0;
|
58
|
-
|
59
|
-
while (lastCommentIndex < comments.length) {
|
60
|
-
|
61
|
-
comment = comments[lastCommentIndex];
|
62
|
-
|
63
|
-
if (comment.range[0] <= index && index < comment.range[1]) {
|
64
|
-
return true;
|
65
|
-
} else if (index > comment.range[1]) {
|
66
|
-
lastCommentIndex++;
|
67
|
-
} else {
|
68
|
-
break;
|
69
|
-
}
|
70
|
-
|
71
|
-
}
|
72
|
-
|
73
|
-
return false;
|
74
|
-
}
|
75
|
-
|
76
|
-
|
77
41
|
/**
|
78
42
|
* Reports a spacing error with an appropriate message.
|
79
43
|
* @param {ASTNode} node The binary expression node to report.
|
@@ -93,9 +57,6 @@ module.exports = function(context) {
|
|
93
57
|
return fixer.insertTextAfter(node, " ");
|
94
58
|
}
|
95
59
|
} else {
|
96
|
-
/*
|
97
|
-
* Comments handling
|
98
|
-
*/
|
99
60
|
var start, end;
|
100
61
|
var newText = "";
|
101
62
|
|
@@ -107,11 +68,6 @@ module.exports = function(context) {
|
|
107
68
|
end = otherNode.range[0];
|
108
69
|
}
|
109
70
|
|
110
|
-
for (var i = start; i < end; i++) {
|
111
|
-
if (isIndexInComment(i, allComments)) {
|
112
|
-
newText += context.getSource()[i];
|
113
|
-
}
|
114
|
-
}
|
115
71
|
return fixer.replaceTextRange([start, end], newText);
|
116
72
|
}
|
117
73
|
},
|
@@ -137,6 +93,11 @@ module.exports = function(context) {
|
|
137
93
|
) {
|
138
94
|
report(reportItem, "before", tokens.left);
|
139
95
|
}
|
96
|
+
|
97
|
+
if (tokens.right && !options.after && tokens.right.type === "Line") {
|
98
|
+
return false;
|
99
|
+
}
|
100
|
+
|
140
101
|
if (tokens.right && astUtils.isTokenOnSameLine(tokens.comma, tokens.right) &&
|
141
102
|
(options.after !== sourceCode.isSpaceBetweenTokens(tokens.comma, tokens.right))
|
142
103
|
) {
|
@@ -176,30 +137,28 @@ module.exports = function(context) {
|
|
176
137
|
return {
|
177
138
|
"Program:exit": function() {
|
178
139
|
|
179
|
-
var
|
180
|
-
pattern = /,/g,
|
181
|
-
commaToken,
|
182
|
-
previousToken,
|
140
|
+
var previousToken,
|
183
141
|
nextToken;
|
184
142
|
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
if (!isIndexInComment(pattern.lastIndex, allComments)) {
|
190
|
-
commaToken = context.getTokenByRangeStart(pattern.lastIndex - 1);
|
191
|
-
|
192
|
-
if (commaToken && commaToken.type !== "JSXText") {
|
193
|
-
previousToken = context.getTokenBefore(commaToken);
|
194
|
-
nextToken = context.getTokenAfter(commaToken);
|
195
|
-
validateCommaItemSpacing({
|
196
|
-
comma: commaToken,
|
197
|
-
left: isComma(previousToken) || commaTokensToIgnore.indexOf(commaToken) > -1 ? null : previousToken,
|
198
|
-
right: isComma(nextToken) ? null : nextToken
|
199
|
-
}, commaToken);
|
200
|
-
}
|
143
|
+
tokensAndComments.forEach(function(token, i) {
|
144
|
+
|
145
|
+
if (!isComma(token)) {
|
146
|
+
return;
|
201
147
|
}
|
202
|
-
|
148
|
+
|
149
|
+
if (token && token.type === "JSXText") {
|
150
|
+
return;
|
151
|
+
}
|
152
|
+
|
153
|
+
previousToken = tokensAndComments[i - 1];
|
154
|
+
nextToken = tokensAndComments[i + 1];
|
155
|
+
|
156
|
+
validateCommaItemSpacing({
|
157
|
+
comma: token,
|
158
|
+
left: isComma(previousToken) || commaTokensToIgnore.indexOf(token) > -1 ? null : previousToken,
|
159
|
+
right: isComma(nextToken) ? null : nextToken
|
160
|
+
}, token);
|
161
|
+
});
|
203
162
|
},
|
204
163
|
"ArrayExpression": addNullElementsToIgnoreList,
|
205
164
|
"ArrayPattern": addNullElementsToIgnoreList
|
@@ -53,39 +53,35 @@ module.exports = function(context) {
|
|
53
53
|
*/
|
54
54
|
function ensureWasAssigned() {
|
55
55
|
var scope = context.getScope();
|
56
|
+
var variable = scope.set.get(alias);
|
57
|
+
if (!variable) {
|
58
|
+
return;
|
59
|
+
}
|
60
|
+
|
61
|
+
if (variable.defs.some(function(def) {
|
62
|
+
return def.node.type === "VariableDeclarator" &&
|
63
|
+
def.node.init !== null;
|
64
|
+
})) {
|
65
|
+
return;
|
66
|
+
}
|
56
67
|
|
57
|
-
scope.
|
58
|
-
var lookup;
|
59
|
-
|
60
|
-
if (variable.name === alias) {
|
61
|
-
if (variable.defs.some(function(def) {
|
62
|
-
return def.node.type === "VariableDeclarator" &&
|
63
|
-
def.node.init !== null;
|
64
|
-
})) {
|
65
|
-
return true;
|
66
|
-
}
|
67
|
-
|
68
|
-
lookup = scope.type === "global" ? scope : variable;
|
69
|
-
|
70
|
-
// The alias has been declared and not assigned: check it was
|
71
|
-
// assigned later in the same scope.
|
72
|
-
if (!lookup.references.some(function(reference) {
|
73
|
-
var write = reference.writeExpr;
|
74
|
-
|
75
|
-
if (reference.from === scope &&
|
76
|
-
write && write.type === "ThisExpression" &&
|
77
|
-
write.parent.operator === "=") {
|
78
|
-
return true;
|
79
|
-
}
|
80
|
-
})) {
|
81
|
-
variable.defs.map(function(def) {
|
82
|
-
return def.node;
|
83
|
-
}).forEach(reportBadAssignment);
|
84
|
-
}
|
68
|
+
var lookup = (variable.references.length === 0 && scope.type === "global") ? scope : variable;
|
85
69
|
|
70
|
+
// The alias has been declared and not assigned: check it was
|
71
|
+
// assigned later in the same scope.
|
72
|
+
if (!lookup.references.some(function(reference) {
|
73
|
+
var write = reference.writeExpr;
|
74
|
+
|
75
|
+
if (reference.from === scope &&
|
76
|
+
write && write.type === "ThisExpression" &&
|
77
|
+
write.parent.operator === "=") {
|
86
78
|
return true;
|
87
79
|
}
|
88
|
-
})
|
80
|
+
})) {
|
81
|
+
variable.defs.map(function(def) {
|
82
|
+
return def.node;
|
83
|
+
}).forEach(reportBadAssignment);
|
84
|
+
}
|
89
85
|
}
|
90
86
|
|
91
87
|
return {
|
package/lib/rules/curly.js
CHANGED
@@ -51,6 +51,22 @@ module.exports = function(context) {
|
|
51
51
|
return first.loc.start.line === last.loc.end.line;
|
52
52
|
}
|
53
53
|
|
54
|
+
/**
|
55
|
+
* Gets the `else` keyword token of a given `IfStatement` node.
|
56
|
+
* @param {ASTNode} node - A `IfStatement` node to get.
|
57
|
+
* @returns {Token} The `else` keyword token.
|
58
|
+
*/
|
59
|
+
function getElseKeyword(node) {
|
60
|
+
var sourceCode = context.getSourceCode();
|
61
|
+
var token = sourceCode.getTokenAfter(node.consequent);
|
62
|
+
|
63
|
+
while (token.type !== "Keyword" || token.value !== "else") {
|
64
|
+
token = sourceCode.getTokenAfter(token);
|
65
|
+
}
|
66
|
+
|
67
|
+
return token;
|
68
|
+
}
|
69
|
+
|
54
70
|
/**
|
55
71
|
* Checks a given IfStatement node requires braces of the consequent chunk.
|
56
72
|
* This returns `true` when below:
|
@@ -89,11 +105,15 @@ module.exports = function(context) {
|
|
89
105
|
* @private
|
90
106
|
*/
|
91
107
|
function reportExpectedBraceError(node, name, suffix) {
|
92
|
-
context.report(
|
93
|
-
|
108
|
+
context.report({
|
109
|
+
node: node,
|
110
|
+
loc: (name !== "else" ? node : getElseKeyword(node)).loc.start,
|
111
|
+
message: "Expected { after '{{name}}'{{suffix}}.",
|
112
|
+
data: {
|
94
113
|
name: name,
|
95
114
|
suffix: (suffix ? " " + suffix : "")
|
96
|
-
}
|
115
|
+
}
|
116
|
+
});
|
97
117
|
}
|
98
118
|
|
99
119
|
/**
|
@@ -105,12 +125,15 @@ module.exports = function(context) {
|
|
105
125
|
* @private
|
106
126
|
*/
|
107
127
|
function reportUnnecessaryBraceError(node, name, suffix) {
|
108
|
-
context.report(
|
109
|
-
|
128
|
+
context.report({
|
129
|
+
node: node,
|
130
|
+
loc: (name !== "else" ? node : getElseKeyword(node)).loc.start,
|
131
|
+
message: "Unnecessary { after '{{name}}'{{suffix}}.",
|
132
|
+
data: {
|
110
133
|
name: name,
|
111
134
|
suffix: (suffix ? " " + suffix : "")
|
112
135
|
}
|
113
|
-
);
|
136
|
+
});
|
114
137
|
}
|
115
138
|
|
116
139
|
/**
|
@@ -224,9 +247,16 @@ module.exports = function(context) {
|
|
224
247
|
|
225
248
|
"ForStatement": function(node) {
|
226
249
|
prepareCheck(node, node.body, "for", "condition").check();
|
250
|
+
},
|
251
|
+
|
252
|
+
"ForInStatement": function(node) {
|
253
|
+
prepareCheck(node, node.body, "for-in").check();
|
254
|
+
},
|
255
|
+
|
256
|
+
"ForOfStatement": function(node) {
|
257
|
+
prepareCheck(node, node.body, "for-of").check();
|
227
258
|
}
|
228
259
|
};
|
229
|
-
|
230
260
|
};
|
231
261
|
|
232
262
|
module.exports.schema = {
|
package/lib/rules/eqeqeq.js
CHANGED
@@ -13,7 +13,11 @@
|
|
13
13
|
|
14
14
|
module.exports = function(context) {
|
15
15
|
|
16
|
-
var sourceCode = context.getSourceCode()
|
16
|
+
var sourceCode = context.getSourceCode(),
|
17
|
+
replacements = {
|
18
|
+
"==": "===",
|
19
|
+
"!=": "!=="
|
20
|
+
};
|
17
21
|
|
18
22
|
/**
|
19
23
|
* Checks if an expression is a typeof expression
|
@@ -89,7 +93,18 @@ module.exports = function(context) {
|
|
89
93
|
message: "Expected '{{op}}=' and instead saw '{{op}}'.",
|
90
94
|
data: { op: node.operator },
|
91
95
|
fix: function(fixer) {
|
92
|
-
|
96
|
+
var tokens = sourceCode.getTokensBetween(node.left, node.right),
|
97
|
+
opToken,
|
98
|
+
i;
|
99
|
+
|
100
|
+
for (i = 0; i < tokens.length; ++i) {
|
101
|
+
if (tokens[i].value === node.operator) {
|
102
|
+
opToken = tokens[i];
|
103
|
+
break;
|
104
|
+
}
|
105
|
+
}
|
106
|
+
|
107
|
+
return fixer.replaceTextRange(opToken.range, replacements[node.operator]);
|
93
108
|
}
|
94
109
|
});
|
95
110
|
|
package/lib/rules/id-length.js
CHANGED
@@ -25,12 +25,12 @@ module.exports = function(context) {
|
|
25
25
|
}, {});
|
26
26
|
|
27
27
|
var SUPPORTED_EXPRESSIONS = {
|
28
|
-
"MemberExpression": function(parent) {
|
28
|
+
"MemberExpression": properties && function(parent) {
|
29
29
|
return !parent.computed && (
|
30
30
|
// regular property assignment
|
31
31
|
parent.parent.left === parent || (
|
32
32
|
// or the last identifier in an ObjectPattern destructuring
|
33
|
-
parent.parent.type === "Property" &&
|
33
|
+
parent.parent.type === "Property" && parent.parent.value === parent &&
|
34
34
|
parent.parent.parent.type === "ObjectPattern" && parent.parent.parent.parent.left === parent.parent.parent
|
35
35
|
)
|
36
36
|
);
|
package/lib/rules/indent.js
CHANGED
@@ -75,6 +75,11 @@ module.exports = function(context) {
|
|
75
75
|
}
|
76
76
|
}
|
77
77
|
|
78
|
+
var indentPattern = {
|
79
|
+
normal: indentType === "space" ? /^ +/ : /^\t+/,
|
80
|
+
excludeCommas: indentType === "space" ? /^[ ,]+/ : /^[\t,]+/
|
81
|
+
};
|
82
|
+
|
78
83
|
var caseIndentStore = {};
|
79
84
|
|
80
85
|
/**
|
@@ -168,17 +173,9 @@ module.exports = function(context) {
|
|
168
173
|
function getNodeIndent(node, byLastLine, excludeCommas) {
|
169
174
|
var token = byLastLine ? context.getLastToken(node) : context.getFirstToken(node);
|
170
175
|
var src = context.getSource(token, token.loc.start.column);
|
171
|
-
|
172
|
-
var skip = excludeCommas ? "," : "";
|
173
|
-
|
174
|
-
var regExp;
|
175
|
-
if (indentType === "space") {
|
176
|
-
regExp = new RegExp("^[ " + skip + "]+");
|
177
|
-
} else {
|
178
|
-
regExp = new RegExp("^[\t" + skip + "]+");
|
179
|
-
}
|
180
|
-
|
176
|
+
var regExp = excludeCommas ? indentPattern.excludeCommas : indentPattern.normal;
|
181
177
|
var indent = regExp.exec(src);
|
178
|
+
|
182
179
|
return indent ? indent[0].length : 0;
|
183
180
|
}
|
184
181
|
|
@@ -7,6 +7,16 @@
|
|
7
7
|
*/
|
8
8
|
"use strict";
|
9
9
|
|
10
|
+
//------------------------------------------------------------------------------
|
11
|
+
// Requirements
|
12
|
+
//------------------------------------------------------------------------------
|
13
|
+
|
14
|
+
var assign = require("object-assign");
|
15
|
+
|
16
|
+
//------------------------------------------------------------------------------
|
17
|
+
// Helpers
|
18
|
+
//------------------------------------------------------------------------------
|
19
|
+
|
10
20
|
/**
|
11
21
|
* Return an array with with any line numbers that are empty.
|
12
22
|
* @param {Array} lines An array of each line of the file.
|
@@ -57,7 +67,7 @@ function contains(val, array) {
|
|
57
67
|
|
58
68
|
module.exports = function(context) {
|
59
69
|
|
60
|
-
var options = context.options[0]
|
70
|
+
var options = context.options[0] ? assign({}, context.options[0]) : {};
|
61
71
|
options.beforeLineComment = options.beforeLineComment || false;
|
62
72
|
options.afterLineComment = options.afterLineComment || false;
|
63
73
|
options.beforeBlockComment = typeof options.beforeBlockComment !== "undefined" ? options.beforeBlockComment : true;
|
@@ -65,26 +75,34 @@ module.exports = function(context) {
|
|
65
75
|
options.allowBlockStart = options.allowBlockStart || false;
|
66
76
|
options.allowBlockEnd = options.allowBlockEnd || false;
|
67
77
|
|
78
|
+
var sourceCode = context.getSourceCode();
|
68
79
|
/**
|
69
|
-
* Returns whether or not comments are
|
80
|
+
* Returns whether or not comments are on lines starting with or ending with code
|
70
81
|
* @param {ASTNode} node The comment node to check.
|
71
82
|
* @returns {boolean} True if the comment is not alone.
|
72
83
|
*/
|
73
84
|
function codeAroundComment(node) {
|
85
|
+
var token;
|
74
86
|
|
75
|
-
|
87
|
+
token = node;
|
88
|
+
do {
|
89
|
+
token = sourceCode.getTokenOrCommentBefore(token);
|
90
|
+
} while (token && (token.type === "Block" || token.type === "Line"));
|
76
91
|
|
77
|
-
|
78
|
-
|
79
|
-
|
92
|
+
if (token && token.loc.end.line === node.loc.start.line) {
|
93
|
+
return true;
|
94
|
+
}
|
80
95
|
|
81
|
-
|
96
|
+
token = node;
|
97
|
+
do {
|
98
|
+
token = sourceCode.getTokenOrCommentAfter(token);
|
99
|
+
} while (token && (token.type === "Block" || token.type === "Line"));
|
82
100
|
|
83
|
-
|
84
|
-
|
101
|
+
if (token && token.loc.start.line === node.loc.end.line) {
|
102
|
+
return true;
|
103
|
+
}
|
85
104
|
|
86
|
-
|
87
|
-
return !!(preamble || postamble);
|
105
|
+
return false;
|
88
106
|
}
|
89
107
|
|
90
108
|
/**
|
@@ -95,7 +113,9 @@ module.exports = function(context) {
|
|
95
113
|
* @returns {boolean} True if the comment is inside nodeType.
|
96
114
|
*/
|
97
115
|
function isCommentInsideNodeType(node, parent, nodeType) {
|
98
|
-
return parent.type === nodeType ||
|
116
|
+
return parent.type === nodeType ||
|
117
|
+
(parent.body && parent.body.type === nodeType) ||
|
118
|
+
(parent.consequent && parent.consequent.type === nodeType);
|
99
119
|
}
|
100
120
|
|
101
121
|
/**
|
package/lib/rules/new-cap.js
CHANGED
@@ -7,6 +7,16 @@
|
|
7
7
|
|
8
8
|
"use strict";
|
9
9
|
|
10
|
+
//------------------------------------------------------------------------------
|
11
|
+
// Requirements
|
12
|
+
//------------------------------------------------------------------------------
|
13
|
+
|
14
|
+
var assign = require("object-assign");
|
15
|
+
|
16
|
+
//------------------------------------------------------------------------------
|
17
|
+
// Helpers
|
18
|
+
//------------------------------------------------------------------------------
|
19
|
+
|
10
20
|
var CAPS_ALLOWED = [
|
11
21
|
"Array",
|
12
22
|
"Boolean",
|
@@ -67,7 +77,7 @@ function calculateCapIsNewExceptions(config) {
|
|
67
77
|
|
68
78
|
module.exports = function(context) {
|
69
79
|
|
70
|
-
var config = context.options[0]
|
80
|
+
var config = context.options[0] ? assign({}, context.options[0]) : {};
|
71
81
|
config.newIsCap = config.newIsCap !== false;
|
72
82
|
config.capIsNew = config.capIsNew !== false;
|
73
83
|
var skipProperties = config.properties === false;
|
package/lib/rules/no-alert.js
CHANGED
@@ -69,9 +69,8 @@ function findReference(scope, node) {
|
|
69
69
|
* @returns {boolean} Whether or not the name is shadowed globally.
|
70
70
|
*/
|
71
71
|
function isGloballyShadowed(globalScope, identifierName) {
|
72
|
-
|
73
|
-
|
74
|
-
});
|
72
|
+
var variable = globalScope.set.get(identifierName);
|
73
|
+
return Boolean(variable && variable.defs.length > 0);
|
75
74
|
}
|
76
75
|
|
77
76
|
/**
|
@@ -5,6 +5,12 @@
|
|
5
5
|
|
6
6
|
"use strict";
|
7
7
|
|
8
|
+
//------------------------------------------------------------------------------
|
9
|
+
// Requirements
|
10
|
+
//------------------------------------------------------------------------------
|
11
|
+
|
12
|
+
var astUtils = require("../ast-utils");
|
13
|
+
|
8
14
|
//------------------------------------------------------------------------------
|
9
15
|
// Rule Definition
|
10
16
|
//------------------------------------------------------------------------------
|
@@ -22,19 +28,7 @@ module.exports = function(context) {
|
|
22
28
|
* @returns {boolean} True is its been shadowed
|
23
29
|
*/
|
24
30
|
function paramIsShadowing(scope, name) {
|
25
|
-
|
26
|
-
return variable.name === name;
|
27
|
-
});
|
28
|
-
|
29
|
-
if (found) {
|
30
|
-
return true;
|
31
|
-
}
|
32
|
-
|
33
|
-
if (scope.upper) {
|
34
|
-
return paramIsShadowing(scope.upper, name);
|
35
|
-
}
|
36
|
-
|
37
|
-
return false;
|
31
|
+
return astUtils.getVariableByName(scope, name) !== null;
|
38
32
|
}
|
39
33
|
|
40
34
|
//--------------------------------------------------------------------------
|
@@ -68,8 +68,7 @@ module.exports = function(context) {
|
|
68
68
|
|
69
69
|
// verify the object being added to is a native prototype
|
70
70
|
subject = node.arguments[0];
|
71
|
-
object = subject.object;
|
72
|
-
|
71
|
+
object = subject && subject.object;
|
73
72
|
if (object &&
|
74
73
|
object.type === "Identifier" &&
|
75
74
|
(modifiedBuiltins.indexOf(object.name) > -1) &&
|
@@ -48,8 +48,7 @@ module.exports = function(context) {
|
|
48
48
|
|
49
49
|
// check for comment
|
50
50
|
if (!comment || !FALLTHROUGH_COMMENT.test(comment.value)) {
|
51
|
-
|
52
|
-
context.report(switchData.lastCase,
|
51
|
+
context.report(node,
|
53
52
|
"Expected a \"break\" statement before \"{{code}}\".",
|
54
53
|
{ code: node.test ? "case" : "default" });
|
55
54
|
}
|
@@ -113,6 +113,15 @@ function isConcatWithEmptyString(node) {
|
|
113
113
|
);
|
114
114
|
}
|
115
115
|
|
116
|
+
/**
|
117
|
+
* Checks whether or not a node is appended with an empty string.
|
118
|
+
* @param {ASTNode} node - An AssignmentExpression node to check.
|
119
|
+
* @returns {boolean} Whether or not the node is appended with an empty string.
|
120
|
+
*/
|
121
|
+
function isAppendEmptyString(node) {
|
122
|
+
return node.operator === "+=" && node.right.type === "Literal" && node.right.value === "";
|
123
|
+
}
|
124
|
+
|
116
125
|
/**
|
117
126
|
* Gets a node that is the left or right operand of a node, is not the specified literal.
|
118
127
|
* @param {ASTNode} node - A BinaryExpression node to get.
|
@@ -178,6 +187,16 @@ module.exports = function(context) {
|
|
178
187
|
"use `String({{code}})` instead.",
|
179
188
|
{code: context.getSource(getOtherOperand(node, ""))});
|
180
189
|
}
|
190
|
+
},
|
191
|
+
|
192
|
+
"AssignmentExpression": function(node) {
|
193
|
+
// foo += ""
|
194
|
+
if (options.string && isAppendEmptyString(node)) {
|
195
|
+
context.report(
|
196
|
+
node,
|
197
|
+
"use `{{code}} = String({{code}})` instead.",
|
198
|
+
{code: context.getSource(getOtherOperand(node, ""))});
|
199
|
+
}
|
181
200
|
}
|
182
201
|
};
|
183
202
|
};
|