eslint 4.18.0 → 4.19.1
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/CHANGELOG.md +40 -0
- package/README.md +2 -2
- package/conf/environments.js +3 -1
- package/conf/eslint-recommended.js +0 -0
- package/lib/ast-utils.js +25 -29
- package/lib/cli-engine.js +29 -28
- package/lib/code-path-analysis/code-path-state.js +5 -5
- package/lib/code-path-analysis/code-path.js +11 -6
- package/lib/code-path-analysis/fork-context.js +10 -12
- package/lib/config/config-file.js +20 -11
- package/lib/config/config-ops.js +8 -10
- package/lib/config/config-rule.js +2 -3
- package/lib/config/plugins.js +20 -0
- package/lib/config.js +7 -8
- package/lib/file-finder.js +9 -10
- package/lib/ignored-paths.js +4 -4
- package/lib/linter.js +397 -406
- package/lib/load-rules.js +6 -7
- package/lib/rules/accessor-pairs.js +4 -4
- package/lib/rules/array-callback-return.js +8 -6
- package/lib/rules/array-element-newline.js +4 -4
- package/lib/rules/curly.js +11 -10
- package/lib/rules/generator-star-spacing.js +1 -2
- package/lib/rules/indent-legacy.js +7 -10
- package/lib/rules/indent.js +51 -29
- package/lib/rules/keyword-spacing.js +6 -18
- package/lib/rules/max-len.js +12 -5
- package/lib/rules/no-await-in-loop.js +1 -1
- package/lib/rules/no-buffer-constructor.js +1 -1
- package/lib/rules/no-control-regex.js +51 -72
- package/lib/rules/no-else-return.js +7 -6
- package/lib/rules/no-empty-character-class.js +1 -1
- package/lib/rules/no-eval.js +7 -8
- package/lib/rules/no-extra-parens.js +5 -4
- package/lib/rules/no-implicit-coercion.js +6 -9
- package/lib/rules/no-invalid-regexp.js +53 -36
- package/lib/rules/no-irregular-whitespace.js +1 -1
- package/lib/rules/no-loop-func.js +9 -11
- package/lib/rules/no-magic-numbers.js +17 -10
- package/lib/rules/no-return-assign.js +4 -3
- package/lib/rules/no-unexpected-multiline.js +1 -1
- package/lib/rules/no-unsafe-finally.js +7 -4
- package/lib/rules/no-useless-escape.js +2 -2
- package/lib/rules/no-useless-return.js +10 -9
- package/lib/rules/no-var.js +8 -8
- package/lib/rules/object-curly-newline.js +2 -1
- package/lib/rules/one-var.js +140 -97
- package/lib/rules/padding-line-between-statements.js +6 -4
- package/lib/rules/prefer-arrow-callback.js +5 -4
- package/lib/rules/prefer-template.js +5 -3
- package/lib/rules/space-unary-ops.js +1 -3
- package/lib/rules/spaced-comment.js +3 -7
- package/lib/rules/template-tag-spacing.js +0 -0
- package/lib/rules/valid-jsdoc.js +6 -6
- package/lib/rules/vars-on-top.js +7 -17
- package/lib/timing.js +3 -5
- package/lib/util/glob-util.js +11 -11
- package/lib/util/interpolate.js +5 -1
- package/lib/util/naming.js +11 -10
- package/lib/util/npm-util.js +4 -6
- package/lib/util/path-util.js +6 -8
- package/lib/util/source-code-util.js +23 -26
- package/lib/util/source-code.js +4 -3
- package/package.json +4 -3
- package/conf/default-config-options.js +0 -29
@@ -217,8 +217,6 @@ module.exports = {
|
|
217
217
|
*/
|
218
218
|
function checkIfWithoutElse(node) {
|
219
219
|
const parent = node.parent;
|
220
|
-
let consequents,
|
221
|
-
alternate;
|
222
220
|
|
223
221
|
/*
|
224
222
|
* Fixing this would require splitting one statement into two, so no error should
|
@@ -228,12 +226,15 @@ module.exports = {
|
|
228
226
|
return;
|
229
227
|
}
|
230
228
|
|
231
|
-
|
232
|
-
|
229
|
+
const consequents = [];
|
230
|
+
let alternate;
|
231
|
+
|
232
|
+
for (let currentNode = node; currentNode.type === "IfStatement"; currentNode = currentNode.alternate) {
|
233
|
+
if (!currentNode.alternate) {
|
233
234
|
return;
|
234
235
|
}
|
235
|
-
consequents.push(
|
236
|
-
alternate =
|
236
|
+
consequents.push(currentNode.consequent);
|
237
|
+
alternate = currentNode.alternate;
|
237
238
|
}
|
238
239
|
|
239
240
|
if (consequents.every(alwaysReturns)) {
|
@@ -21,7 +21,7 @@
|
|
21
21
|
* 4. `[gimuy]*`: optional regexp flags
|
22
22
|
* 5. `$`: fix the match at the end of the string
|
23
23
|
*/
|
24
|
-
const regex = /^\/([^\\[]|\\.|\[([^\\\]]|\\.)+])*\/[
|
24
|
+
const regex = /^\/([^\\[]|\\.|\[([^\\\]]|\\.)+])*\/[gimuys]*$/;
|
25
25
|
|
26
26
|
//------------------------------------------------------------------------------
|
27
27
|
// Rule Definition
|
package/lib/rules/no-eval.js
CHANGED
@@ -151,18 +151,17 @@ module.exports = {
|
|
151
151
|
* @returns {void}
|
152
152
|
*/
|
153
153
|
function report(node) {
|
154
|
-
let locationNode = node;
|
155
154
|
const parent = node.parent;
|
155
|
+
const locationNode = node.type === "MemberExpression"
|
156
|
+
? node.property
|
157
|
+
: node;
|
156
158
|
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
if (parent.type === "CallExpression" && parent.callee === node) {
|
161
|
-
node = parent;
|
162
|
-
}
|
159
|
+
const reportNode = parent.type === "CallExpression" && parent.callee === node
|
160
|
+
? parent
|
161
|
+
: node;
|
163
162
|
|
164
163
|
context.report({
|
165
|
-
node,
|
164
|
+
node: reportNode,
|
166
165
|
loc: locationNode.loc.start,
|
167
166
|
messageId: "unexpected"
|
168
167
|
});
|
@@ -167,12 +167,13 @@ module.exports = {
|
|
167
167
|
* @private
|
168
168
|
*/
|
169
169
|
function isInReturnStatement(node) {
|
170
|
-
|
171
|
-
if (
|
172
|
-
|
170
|
+
for (let currentNode = node; currentNode; currentNode = currentNode.parent) {
|
171
|
+
if (
|
172
|
+
currentNode.type === "ReturnStatement" ||
|
173
|
+
(currentNode.type === "ArrowFunctionExpression" && currentNode.body.type !== "BlockStatement")
|
174
|
+
) {
|
173
175
|
return true;
|
174
176
|
}
|
175
|
-
node = node.parent;
|
176
177
|
}
|
177
178
|
|
178
179
|
return false;
|
@@ -20,7 +20,6 @@ const ALLOWABLE_OPERATORS = ["~", "!!", "+", "*"];
|
|
20
20
|
* @returns {Object} The parsed and normalized option object.
|
21
21
|
*/
|
22
22
|
function parseOptions(options) {
|
23
|
-
options = options || {};
|
24
23
|
return {
|
25
24
|
boolean: "boolean" in options ? Boolean(options.boolean) : true,
|
26
25
|
number: "number" in options ? Boolean(options.number) : true,
|
@@ -186,7 +185,7 @@ module.exports = {
|
|
186
185
|
},
|
187
186
|
|
188
187
|
create(context) {
|
189
|
-
const options = parseOptions(context.options[0]);
|
188
|
+
const options = parseOptions(context.options[0] || {});
|
190
189
|
const sourceCode = context.getSourceCode();
|
191
190
|
|
192
191
|
/**
|
@@ -197,8 +196,6 @@ module.exports = {
|
|
197
196
|
* @returns {void}
|
198
197
|
*/
|
199
198
|
function report(node, recommendation, shouldFix) {
|
200
|
-
shouldFix = typeof shouldFix === "undefined" ? true : shouldFix;
|
201
|
-
|
202
199
|
context.report({
|
203
200
|
node,
|
204
201
|
message: "use `{{recommendation}}` instead.",
|
@@ -233,7 +230,7 @@ module.exports = {
|
|
233
230
|
if (!operatorAllowed && options.boolean && isDoubleLogicalNegating(node)) {
|
234
231
|
const recommendation = `Boolean(${sourceCode.getText(node.argument.argument)})`;
|
235
232
|
|
236
|
-
report(node, recommendation);
|
233
|
+
report(node, recommendation, true);
|
237
234
|
}
|
238
235
|
|
239
236
|
// ~foo.indexOf(bar)
|
@@ -249,7 +246,7 @@ module.exports = {
|
|
249
246
|
if (!operatorAllowed && options.number && node.operator === "+" && !isNumeric(node.argument)) {
|
250
247
|
const recommendation = `Number(${sourceCode.getText(node.argument)})`;
|
251
248
|
|
252
|
-
report(node, recommendation);
|
249
|
+
report(node, recommendation, true);
|
253
250
|
}
|
254
251
|
},
|
255
252
|
|
@@ -264,7 +261,7 @@ module.exports = {
|
|
264
261
|
if (nonNumericOperand) {
|
265
262
|
const recommendation = `Number(${sourceCode.getText(nonNumericOperand)})`;
|
266
263
|
|
267
|
-
report(node, recommendation);
|
264
|
+
report(node, recommendation, true);
|
268
265
|
}
|
269
266
|
|
270
267
|
// "" + foo
|
@@ -272,7 +269,7 @@ module.exports = {
|
|
272
269
|
if (!operatorAllowed && options.string && isConcatWithEmptyString(node)) {
|
273
270
|
const recommendation = `String(${sourceCode.getText(getNonEmptyOperand(node))})`;
|
274
271
|
|
275
|
-
report(node, recommendation);
|
272
|
+
report(node, recommendation, true);
|
276
273
|
}
|
277
274
|
},
|
278
275
|
|
@@ -285,7 +282,7 @@ module.exports = {
|
|
285
282
|
const code = sourceCode.getText(getNonEmptyOperand(node));
|
286
283
|
const recommendation = `${code} = String(${code})`;
|
287
284
|
|
288
|
-
report(node, recommendation);
|
285
|
+
report(node, recommendation, true);
|
289
286
|
}
|
290
287
|
}
|
291
288
|
};
|
@@ -8,7 +8,10 @@
|
|
8
8
|
// Requirements
|
9
9
|
//------------------------------------------------------------------------------
|
10
10
|
|
11
|
-
const
|
11
|
+
const RegExpValidator = require("regexpp").RegExpValidator;
|
12
|
+
const validator = new RegExpValidator({ ecmaVersion: 2018 });
|
13
|
+
const validFlags = /[gimuys]/g;
|
14
|
+
const undefined1 = void 0;
|
12
15
|
|
13
16
|
//------------------------------------------------------------------------------
|
14
17
|
// Rule Definition
|
@@ -40,10 +43,14 @@ module.exports = {
|
|
40
43
|
create(context) {
|
41
44
|
|
42
45
|
const options = context.options[0];
|
43
|
-
let allowedFlags =
|
46
|
+
let allowedFlags = null;
|
44
47
|
|
45
48
|
if (options && options.allowConstructorFlags) {
|
46
|
-
|
49
|
+
const temp = options.allowConstructorFlags.join("").replace(validFlags, "");
|
50
|
+
|
51
|
+
if (temp) {
|
52
|
+
allowedFlags = new RegExp(`[${temp}]`, "gi");
|
53
|
+
}
|
47
54
|
}
|
48
55
|
|
49
56
|
/**
|
@@ -57,51 +64,61 @@ module.exports = {
|
|
57
64
|
}
|
58
65
|
|
59
66
|
/**
|
60
|
-
*
|
61
|
-
* @param {
|
62
|
-
* @
|
63
|
-
* @
|
67
|
+
* Check syntax error in a given pattern.
|
68
|
+
* @param {string} pattern The RegExp pattern to validate.
|
69
|
+
* @param {boolean} uFlag The Unicode flag.
|
70
|
+
* @returns {string|null} The syntax error.
|
71
|
+
*/
|
72
|
+
function validateRegExpPattern(pattern, uFlag) {
|
73
|
+
try {
|
74
|
+
validator.validatePattern(pattern, undefined1, undefined1, uFlag);
|
75
|
+
return null;
|
76
|
+
} catch (err) {
|
77
|
+
return err.message;
|
78
|
+
}
|
79
|
+
}
|
80
|
+
|
81
|
+
/**
|
82
|
+
* Check syntax error in a given flags.
|
83
|
+
* @param {string} flags The RegExp flags to validate.
|
84
|
+
* @returns {string|null} The syntax error.
|
64
85
|
*/
|
65
|
-
function
|
66
|
-
|
86
|
+
function validateRegExpFlags(flags) {
|
87
|
+
try {
|
88
|
+
validator.validateFlags(flags);
|
89
|
+
return null;
|
90
|
+
} catch (err) {
|
91
|
+
return `Invalid flags supplied to RegExp constructor '${flags}'`;
|
92
|
+
}
|
93
|
+
}
|
94
|
+
|
95
|
+
return {
|
96
|
+
"CallExpression, NewExpression"(node) {
|
97
|
+
if (node.callee.type !== "Identifier" || node.callee.name !== "RegExp" || !isString(node.arguments[0])) {
|
98
|
+
return;
|
99
|
+
}
|
100
|
+
const pattern = node.arguments[0].value;
|
67
101
|
let flags = isString(node.arguments[1]) ? node.arguments[1].value : "";
|
68
102
|
|
69
103
|
if (allowedFlags) {
|
70
|
-
flags = flags.replace(
|
104
|
+
flags = flags.replace(allowedFlags, "");
|
71
105
|
}
|
72
106
|
|
73
|
-
|
74
|
-
|
75
|
-
|
107
|
+
// If flags are unknown, check both are errored or not.
|
108
|
+
const message = validateRegExpFlags(flags) || (
|
109
|
+
flags
|
110
|
+
? validateRegExpPattern(pattern, flags.indexOf("u") !== -1)
|
111
|
+
: validateRegExpPattern(pattern, true) && validateRegExpPattern(pattern, false)
|
112
|
+
);
|
113
|
+
|
114
|
+
if (message) {
|
76
115
|
context.report({
|
77
116
|
node,
|
78
117
|
message: "{{message}}.",
|
79
|
-
data:
|
118
|
+
data: { message }
|
80
119
|
});
|
81
120
|
}
|
82
|
-
|
83
|
-
if (flags) {
|
84
|
-
|
85
|
-
try {
|
86
|
-
espree.parse(`/./${flags}`, context.parserOptions);
|
87
|
-
} catch (ex) {
|
88
|
-
context.report({
|
89
|
-
node,
|
90
|
-
message: "Invalid flags supplied to RegExp constructor '{{flags}}'.",
|
91
|
-
data: {
|
92
|
-
flags
|
93
|
-
}
|
94
|
-
});
|
95
|
-
}
|
96
|
-
}
|
97
|
-
|
98
121
|
}
|
99
|
-
}
|
100
|
-
|
101
|
-
return {
|
102
|
-
CallExpression: check,
|
103
|
-
NewExpression: check
|
104
122
|
};
|
105
|
-
|
106
123
|
}
|
107
124
|
};
|
@@ -101,7 +101,7 @@ module.exports = {
|
|
101
101
|
*/
|
102
102
|
function removeInvalidNodeErrorsInIdentifierOrLiteral(node) {
|
103
103
|
const shouldCheckStrings = skipStrings && (typeof node.value === "string");
|
104
|
-
const shouldCheckRegExps = skipRegExps && (node.
|
104
|
+
const shouldCheckRegExps = skipRegExps && Boolean(node.regex);
|
105
105
|
|
106
106
|
if (shouldCheckStrings || shouldCheckRegExps) {
|
107
107
|
|
@@ -20,9 +20,9 @@
|
|
20
20
|
* `null`.
|
21
21
|
*/
|
22
22
|
function getContainingLoopNode(node) {
|
23
|
-
let
|
23
|
+
for (let currentNode = node; currentNode.parent; currentNode = currentNode.parent) {
|
24
|
+
const parent = currentNode.parent;
|
24
25
|
|
25
|
-
while (parent) {
|
26
26
|
switch (parent.type) {
|
27
27
|
case "WhileStatement":
|
28
28
|
case "DoWhileStatement":
|
@@ -31,7 +31,7 @@ function getContainingLoopNode(node) {
|
|
31
31
|
case "ForStatement":
|
32
32
|
|
33
33
|
// `init` is outside of the loop.
|
34
|
-
if (parent.init !==
|
34
|
+
if (parent.init !== currentNode) {
|
35
35
|
return parent;
|
36
36
|
}
|
37
37
|
break;
|
@@ -40,7 +40,7 @@ function getContainingLoopNode(node) {
|
|
40
40
|
case "ForOfStatement":
|
41
41
|
|
42
42
|
// `right` is outside of the loop.
|
43
|
-
if (parent.right !==
|
43
|
+
if (parent.right !== currentNode) {
|
44
44
|
return parent;
|
45
45
|
}
|
46
46
|
break;
|
@@ -55,9 +55,6 @@ function getContainingLoopNode(node) {
|
|
55
55
|
default:
|
56
56
|
break;
|
57
57
|
}
|
58
|
-
|
59
|
-
node = parent;
|
60
|
-
parent = node.parent;
|
61
58
|
}
|
62
59
|
|
63
60
|
return null;
|
@@ -73,12 +70,13 @@ function getContainingLoopNode(node) {
|
|
73
70
|
* @returns {ASTNode} The most outer loop node.
|
74
71
|
*/
|
75
72
|
function getTopLoopNode(node, excludedNode) {
|
76
|
-
let retv = node;
|
77
73
|
const border = excludedNode ? excludedNode.range[1] : 0;
|
74
|
+
let retv = node;
|
75
|
+
let containingLoopNode = node;
|
78
76
|
|
79
|
-
while (
|
80
|
-
retv =
|
81
|
-
|
77
|
+
while (containingLoopNode && containingLoopNode.range[0] >= border) {
|
78
|
+
retv = containingLoopNode;
|
79
|
+
containingLoopNode = getContainingLoopNode(containingLoopNode);
|
82
80
|
}
|
83
81
|
|
84
82
|
return retv;
|
@@ -101,25 +101,32 @@ module.exports = {
|
|
101
101
|
|
102
102
|
return {
|
103
103
|
Literal(node) {
|
104
|
-
let parent = node.parent,
|
105
|
-
value = node.value,
|
106
|
-
raw = node.raw;
|
107
104
|
const okTypes = detectObjects ? [] : ["ObjectExpression", "Property", "AssignmentExpression"];
|
108
105
|
|
109
106
|
if (!isNumber(node)) {
|
110
107
|
return;
|
111
108
|
}
|
112
109
|
|
110
|
+
let fullNumberNode;
|
111
|
+
let parent;
|
112
|
+
let value;
|
113
|
+
let raw;
|
114
|
+
|
113
115
|
// For negative magic numbers: update the value and parent node
|
114
|
-
if (parent.type === "UnaryExpression" && parent.operator === "-") {
|
115
|
-
|
116
|
+
if (node.parent.type === "UnaryExpression" && node.parent.operator === "-") {
|
117
|
+
fullNumberNode = node.parent;
|
118
|
+
parent = fullNumberNode.parent;
|
119
|
+
value = -node.value;
|
120
|
+
raw = `-${node.raw}`;
|
121
|
+
} else {
|
122
|
+
fullNumberNode = node;
|
116
123
|
parent = node.parent;
|
117
|
-
value =
|
118
|
-
raw =
|
124
|
+
value = node.value;
|
125
|
+
raw = node.raw;
|
119
126
|
}
|
120
127
|
|
121
128
|
if (shouldIgnoreNumber(value) ||
|
122
|
-
shouldIgnoreParseInt(parent,
|
129
|
+
shouldIgnoreParseInt(parent, fullNumberNode) ||
|
123
130
|
shouldIgnoreArrayIndexes(parent) ||
|
124
131
|
shouldIgnoreJSXNumbers(parent)) {
|
125
132
|
return;
|
@@ -128,7 +135,7 @@ module.exports = {
|
|
128
135
|
if (parent.type === "VariableDeclarator") {
|
129
136
|
if (enforceConst && parent.parent.kind !== "const") {
|
130
137
|
context.report({
|
131
|
-
node,
|
138
|
+
node: fullNumberNode,
|
132
139
|
message: "Number constants declarations must use 'const'."
|
133
140
|
});
|
134
141
|
}
|
@@ -137,7 +144,7 @@ module.exports = {
|
|
137
144
|
(parent.type === "AssignmentExpression" && parent.left.type === "Identifier")
|
138
145
|
) {
|
139
146
|
context.report({
|
140
|
-
node,
|
147
|
+
node: fullNumberNode,
|
141
148
|
message: "No magic number: {{raw}}.",
|
142
149
|
data: {
|
143
150
|
raw
|
@@ -46,11 +46,12 @@ module.exports = {
|
|
46
46
|
return;
|
47
47
|
}
|
48
48
|
|
49
|
-
let
|
49
|
+
let currentChild = node;
|
50
|
+
let parent = currentChild.parent;
|
50
51
|
|
51
52
|
// Find ReturnStatement or ArrowFunctionExpression in ancestors.
|
52
53
|
while (parent && !SENTINEL_TYPE.test(parent.type)) {
|
53
|
-
|
54
|
+
currentChild = parent;
|
54
55
|
parent = parent.parent;
|
55
56
|
}
|
56
57
|
|
@@ -60,7 +61,7 @@ module.exports = {
|
|
60
61
|
node: parent,
|
61
62
|
message: "Return statement should not contain assignment."
|
62
63
|
});
|
63
|
-
} else if (parent && parent.type === "ArrowFunctionExpression" && parent.body ===
|
64
|
+
} else if (parent && parent.type === "ArrowFunctionExpression" && parent.body === currentChild) {
|
64
65
|
context.report({
|
65
66
|
node: parent,
|
66
67
|
message: "Arrow function should not return assignment."
|
@@ -33,7 +33,7 @@ module.exports = {
|
|
33
33
|
const TAGGED_TEMPLATE_MESSAGE = "Unexpected newline between template tag and template literal.";
|
34
34
|
const DIVISION_MESSAGE = "Unexpected newline between numerator and division operator.";
|
35
35
|
|
36
|
-
const REGEX_FLAG_MATCHER = /^[
|
36
|
+
const REGEX_FLAG_MATCHER = /^[gimsuy]+$/;
|
37
37
|
|
38
38
|
const sourceCode = context.getSourceCode();
|
39
39
|
|
@@ -60,17 +60,20 @@ module.exports = {
|
|
60
60
|
sentinelNodeType = SENTINEL_NODE_TYPE_RETURN_THROW;
|
61
61
|
}
|
62
62
|
|
63
|
-
|
64
|
-
|
63
|
+
for (
|
64
|
+
let currentNode = node;
|
65
|
+
currentNode && !sentinelNodeType.test(currentNode.type);
|
66
|
+
currentNode = currentNode.parent
|
67
|
+
) {
|
68
|
+
if (currentNode.parent.label && label && (currentNode.parent.label.name === label.name)) {
|
65
69
|
labelInside = true;
|
66
70
|
}
|
67
|
-
if (isFinallyBlock(
|
71
|
+
if (isFinallyBlock(currentNode)) {
|
68
72
|
if (label && labelInside) {
|
69
73
|
return false;
|
70
74
|
}
|
71
75
|
return true;
|
72
76
|
}
|
73
|
-
node = node.parent;
|
74
77
|
}
|
75
78
|
return false;
|
76
79
|
}
|
@@ -25,8 +25,8 @@ function union(setA, setB) {
|
|
25
25
|
}
|
26
26
|
|
27
27
|
const VALID_STRING_ESCAPES = union(new Set("\\nrvtbfux"), astUtils.LINEBREAKS);
|
28
|
-
const REGEX_GENERAL_ESCAPES = new Set("\\
|
29
|
-
const REGEX_NON_CHARCLASS_ESCAPES = union(REGEX_GENERAL_ESCAPES, new Set("^/.$*+?[{}|()
|
28
|
+
const REGEX_GENERAL_ESCAPES = new Set("\\bcdDfnpPrsStvwWxu0123456789]");
|
29
|
+
const REGEX_NON_CHARCLASS_ESCAPES = union(REGEX_GENERAL_ESCAPES, new Set("^/.$*+?[{}|()Bk"));
|
30
30
|
|
31
31
|
/**
|
32
32
|
* Parses a regular expression into a list of characters with character class info.
|
@@ -56,12 +56,14 @@ function isRemovable(node) {
|
|
56
56
|
* @returns {boolean} `true` if the node is in a `finally` block.
|
57
57
|
*/
|
58
58
|
function isInFinally(node) {
|
59
|
-
|
60
|
-
|
59
|
+
for (
|
60
|
+
let currentNode = node;
|
61
|
+
currentNode && currentNode.parent && !astUtils.isFunction(currentNode);
|
62
|
+
currentNode = currentNode.parent
|
63
|
+
) {
|
64
|
+
if (currentNode.parent.type === "TryStatement" && currentNode.parent.finalizer === currentNode) {
|
61
65
|
return true;
|
62
66
|
}
|
63
|
-
|
64
|
-
node = node.parent;
|
65
67
|
}
|
66
68
|
|
67
69
|
return false;
|
@@ -116,13 +118,12 @@ module.exports = {
|
|
116
118
|
*
|
117
119
|
* @param {ASTNode[]} uselessReturns - The collected return statements.
|
118
120
|
* @param {CodePathSegment[]} prevSegments - The previous segments to traverse.
|
119
|
-
* @param {WeakSet<CodePathSegment>} [
|
121
|
+
* @param {WeakSet<CodePathSegment>} [providedTraversedSegments] A set of segments that have already been traversed in this call
|
120
122
|
* @returns {ASTNode[]} `uselessReturns`.
|
121
123
|
*/
|
122
|
-
function getUselessReturns(uselessReturns, prevSegments,
|
123
|
-
|
124
|
-
|
125
|
-
}
|
124
|
+
function getUselessReturns(uselessReturns, prevSegments, providedTraversedSegments) {
|
125
|
+
const traversedSegments = providedTraversedSegments || new WeakSet();
|
126
|
+
|
126
127
|
for (const segment of prevSegments) {
|
127
128
|
if (!segment.reachable) {
|
128
129
|
if (!traversedSegments.has(segment)) {
|
package/lib/rules/no-var.js
CHANGED
@@ -33,10 +33,12 @@ function isGlobal(variable) {
|
|
33
33
|
* scope.
|
34
34
|
*/
|
35
35
|
function getEnclosingFunctionScope(scope) {
|
36
|
-
|
37
|
-
|
36
|
+
let currentScope = scope;
|
37
|
+
|
38
|
+
while (currentScope.type !== "function" && currentScope.type !== "global") {
|
39
|
+
currentScope = currentScope.upper;
|
38
40
|
}
|
39
|
-
return
|
41
|
+
return currentScope;
|
40
42
|
}
|
41
43
|
|
42
44
|
/**
|
@@ -87,12 +89,10 @@ const SCOPE_NODE_TYPE = /^(?:Program|BlockStatement|SwitchStatement|ForStatement
|
|
87
89
|
* `ForOfStatement`.
|
88
90
|
*/
|
89
91
|
function getScopeNode(node) {
|
90
|
-
|
91
|
-
if (SCOPE_NODE_TYPE.test(
|
92
|
-
return
|
92
|
+
for (let currentNode = node; currentNode; currentNode = currentNode.parent) {
|
93
|
+
if (SCOPE_NODE_TYPE.test(currentNode.type)) {
|
94
|
+
return currentNode;
|
93
95
|
}
|
94
|
-
|
95
|
-
node = node.parent;
|
96
96
|
}
|
97
97
|
|
98
98
|
/* istanbul ignore next : unreachable */
|
@@ -116,7 +116,8 @@ function areLineBreaksRequired(node, options, first, last) {
|
|
116
116
|
} else {
|
117
117
|
|
118
118
|
// is ImportDeclaration or ExportNamedDeclaration
|
119
|
-
objectProperties = node.specifiers
|
119
|
+
objectProperties = node.specifiers
|
120
|
+
.filter(s => s.type === "ImportSpecifier" || s.type === "ExportSpecifier");
|
120
121
|
}
|
121
122
|
|
122
123
|
return objectProperties.length >= options.minProperties ||
|