eslint 8.1.0 → 8.2.0
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/lib/rules/key-spacing.js +14 -13
- package/lib/rules/no-use-before-define.js +152 -74
- package/package.json +5 -5
package/README.md
CHANGED
@@ -298,7 +298,7 @@ The following companies, organizations, and individuals support ESLint's ongoing
|
|
298
298
|
<p><a href="https://automattic.com"><img src="https://images.opencollective.com/photomatt/d0ef3e1/logo.png" alt="Automattic" height="undefined"></a></p><h3>Gold Sponsors</h3>
|
299
299
|
<p><a href="https://nx.dev"><img src="https://images.opencollective.com/nx/0efbe42/logo.png" alt="Nx (by Nrwl)" height="96"></a> <a href="https://google.com/chrome"><img src="https://images.opencollective.com/chrome/dc55bd4/logo.png" alt="Chrome's Web Framework & Tools Performance Fund" height="96"></a> <a href="https://www.salesforce.com"><img src="https://images.opencollective.com/salesforce/ca8f997/logo.png" alt="Salesforce" height="96"></a> <a href="https://www.airbnb.com/"><img src="https://images.opencollective.com/airbnb/d327d66/logo.png" alt="Airbnb" height="96"></a> <a href="https://coinbase.com"><img src="https://avatars.githubusercontent.com/u/1885080?v=4" alt="Coinbase" height="96"></a> <a href="https://americanexpress.io"><img src="https://avatars.githubusercontent.com/u/3853301?v=4" alt="American Express" height="96"></a> <a href="https://substack.com/"><img src="https://avatars.githubusercontent.com/u/53023767?v=4" alt="Substack" height="96"></a></p><h3>Silver Sponsors</h3>
|
300
300
|
<p><a href="https://liftoff.io/"><img src="https://images.opencollective.com/liftoff/5c4fa84/logo.png" alt="Liftoff" height="64"></a></p><h3>Bronze Sponsors</h3>
|
301
|
-
<p><a href="https://launchdarkly.com"><img src="https://images.opencollective.com/launchdarkly/574bb9e/logo.png" alt="launchdarkly" height="32"></a> <a href="https://troypoint.com"><img src="https://images.opencollective.com/troypoint/080f96f/avatar.png" alt="TROYPOINT" height="32"></a> <a href="https://
|
301
|
+
<p><a href="https://launchdarkly.com"><img src="https://images.opencollective.com/launchdarkly/574bb9e/logo.png" alt="launchdarkly" height="32"></a> <a href="https://troypoint.com"><img src="https://images.opencollective.com/troypoint/080f96f/avatar.png" alt="TROYPOINT" height="32"></a> <a href="https://www.crosswordsolver.org/anagram-solver/"><img src="https://images.opencollective.com/anagram-solver/2666271/logo.png" alt="Anagram Solver" height="32"></a> <a href="https://www.vpsserver.com"><img src="https://images.opencollective.com/vpsservercom/logo.png" alt="VPS Server" height="32"></a> <a href="https://icons8.com"><img src="https://images.opencollective.com/icons8/7fa1641/logo.png" alt="Icons8: free icons, photos, illustrations, and music" height="32"></a> <a href="https://discord.com"><img src="https://images.opencollective.com/discordapp/f9645d9/logo.png" alt="Discord" height="32"></a> <a href="https://themeisle.com"><img src="https://images.opencollective.com/themeisle/d5592fe/logo.png" alt="ThemeIsle" height="32"></a> <a href="https://www.firesticktricks.com"><img src="https://images.opencollective.com/fire-stick-tricks/b8fbe2c/logo.png" alt="Fire Stick Tricks" height="32"></a> <a href="https://www.practiceignition.com"><img src="https://avatars.githubusercontent.com/u/5753491?v=4" alt="Practice Ignition" height="32"></a></p>
|
302
302
|
<!--sponsorsend-->
|
303
303
|
|
304
304
|
## <a name="technology-sponsors"></a>Technology Sponsors
|
package/lib/rules/key-spacing.js
CHANGED
@@ -427,19 +427,7 @@ module.exports = {
|
|
427
427
|
* @returns {void}
|
428
428
|
*/
|
429
429
|
function report(property, side, whitespace, expected, mode) {
|
430
|
-
const diff = whitespace.length - expected
|
431
|
-
nextColon = getNextColon(property.key),
|
432
|
-
tokenBeforeColon = sourceCode.getTokenBefore(nextColon, { includeComments: true }),
|
433
|
-
tokenAfterColon = sourceCode.getTokenAfter(nextColon, { includeComments: true }),
|
434
|
-
isKeySide = side === "key",
|
435
|
-
isExtra = diff > 0,
|
436
|
-
diffAbs = Math.abs(diff),
|
437
|
-
spaces = Array(diffAbs + 1).join(" ");
|
438
|
-
|
439
|
-
const locStart = isKeySide ? tokenBeforeColon.loc.end : nextColon.loc.start;
|
440
|
-
const locEnd = isKeySide ? nextColon.loc.start : tokenAfterColon.loc.start;
|
441
|
-
const missingLoc = isKeySide ? tokenBeforeColon.loc : tokenAfterColon.loc;
|
442
|
-
const loc = isExtra ? { start: locStart, end: locEnd } : missingLoc;
|
430
|
+
const diff = whitespace.length - expected;
|
443
431
|
|
444
432
|
if ((
|
445
433
|
diff && mode === "strict" ||
|
@@ -447,6 +435,19 @@ module.exports = {
|
|
447
435
|
diff > 0 && !expected && mode === "minimum") &&
|
448
436
|
!(expected && containsLineTerminator(whitespace))
|
449
437
|
) {
|
438
|
+
const nextColon = getNextColon(property.key),
|
439
|
+
tokenBeforeColon = sourceCode.getTokenBefore(nextColon, { includeComments: true }),
|
440
|
+
tokenAfterColon = sourceCode.getTokenAfter(nextColon, { includeComments: true }),
|
441
|
+
isKeySide = side === "key",
|
442
|
+
isExtra = diff > 0,
|
443
|
+
diffAbs = Math.abs(diff),
|
444
|
+
spaces = Array(diffAbs + 1).join(" ");
|
445
|
+
|
446
|
+
const locStart = isKeySide ? tokenBeforeColon.loc.end : nextColon.loc.start;
|
447
|
+
const locEnd = isKeySide ? nextColon.loc.start : tokenAfterColon.loc.start;
|
448
|
+
const missingLoc = isKeySide ? tokenBeforeColon.loc : tokenAfterColon.loc;
|
449
|
+
const loc = isExtra ? { start: locStart, end: locEnd } : missingLoc;
|
450
|
+
|
450
451
|
let fix;
|
451
452
|
|
452
453
|
if (isExtra) {
|
@@ -34,52 +34,91 @@ function parseOptions(options) {
|
|
34
34
|
}
|
35
35
|
|
36
36
|
/**
|
37
|
-
* Checks whether or not a given
|
38
|
-
* @param {
|
39
|
-
* @
|
37
|
+
* Checks whether or not a given location is inside of the range of a given node.
|
38
|
+
* @param {ASTNode} node An node to check.
|
39
|
+
* @param {number} location A location to check.
|
40
|
+
* @returns {boolean} `true` if the location is inside of the range of the node.
|
40
41
|
*/
|
41
|
-
function
|
42
|
-
return
|
42
|
+
function isInRange(node, location) {
|
43
|
+
return node && node.range[0] <= location && location <= node.range[1];
|
43
44
|
}
|
44
45
|
|
45
46
|
/**
|
46
|
-
* Checks whether or not a given
|
47
|
-
* @param {
|
48
|
-
* @param {
|
49
|
-
* @returns {boolean} `true` if the
|
47
|
+
* Checks whether or not a given location is inside of the range of a class static initializer.
|
48
|
+
* @param {ASTNode} node `ClassBody` node to check static initializers.
|
49
|
+
* @param {number} location A location to check.
|
50
|
+
* @returns {boolean} `true` if the location is inside of a class static initializer.
|
50
51
|
*/
|
51
|
-
function
|
52
|
-
return (
|
53
|
-
|
54
|
-
|
55
|
-
|
52
|
+
function isInClassStaticInitializerRange(node, location) {
|
53
|
+
return node.body.some(classMember => (
|
54
|
+
classMember.type === "PropertyDefinition" &&
|
55
|
+
classMember.static &&
|
56
|
+
classMember.value &&
|
57
|
+
isInRange(classMember.value, location)
|
58
|
+
));
|
56
59
|
}
|
57
60
|
|
58
61
|
/**
|
59
|
-
* Checks whether
|
60
|
-
* @param {eslint-scope.
|
61
|
-
* @
|
62
|
-
* @returns {boolean} `true` if the variable is a variable declaration.
|
62
|
+
* Checks whether a given scope is the scope of a static class field initializer.
|
63
|
+
* @param {eslint-scope.Scope} scope A scope to check.
|
64
|
+
* @returns {boolean} `true` if the scope is a class static initializer scope.
|
63
65
|
*/
|
64
|
-
function
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
66
|
+
function isClassStaticInitializerScope(scope) {
|
67
|
+
if (scope.type === "class-field-initializer") {
|
68
|
+
|
69
|
+
// `scope.block` is PropertyDefinition#value node
|
70
|
+
const propertyDefinition = scope.block.parent;
|
71
|
+
|
72
|
+
return propertyDefinition.static;
|
73
|
+
}
|
74
|
+
|
75
|
+
return false;
|
69
76
|
}
|
70
77
|
|
71
78
|
/**
|
72
|
-
* Checks whether
|
73
|
-
*
|
74
|
-
*
|
75
|
-
*
|
79
|
+
* Checks whether a given reference is evaluated in an execution context
|
80
|
+
* that isn't the one where the variable it refers to is defined.
|
81
|
+
* Execution contexts are:
|
82
|
+
* - top-level
|
83
|
+
* - functions
|
84
|
+
* - class field initializers (implicit functions)
|
85
|
+
* Static class field initializers are automatically run during the class definition evaluation,
|
86
|
+
* and therefore we'll consider them as a part of the parent execution context.
|
87
|
+
* Example:
|
88
|
+
*
|
89
|
+
* const x = 1;
|
90
|
+
*
|
91
|
+
* x; // returns `false`
|
92
|
+
* () => x; // returns `true`
|
93
|
+
* class C {
|
94
|
+
* field = x; // returns `true`
|
95
|
+
* static field = x; // returns `false`
|
96
|
+
*
|
97
|
+
* method() {
|
98
|
+
* x; // returns `true`
|
99
|
+
* }
|
100
|
+
* }
|
101
|
+
* @param {eslint-scope.Reference} reference A reference to check.
|
102
|
+
* @returns {boolean} `true` if the reference is from a separate execution context.
|
76
103
|
*/
|
77
|
-
function
|
78
|
-
|
104
|
+
function isFromSeparateExecutionContext(reference) {
|
105
|
+
const variable = reference.resolved;
|
106
|
+
let scope = reference.from;
|
107
|
+
|
108
|
+
// Scope#variableScope represents execution context
|
109
|
+
while (variable.scope.variableScope !== scope.variableScope) {
|
110
|
+
if (isClassStaticInitializerScope(scope.variableScope)) {
|
111
|
+
scope = scope.variableScope.upper;
|
112
|
+
} else {
|
113
|
+
return true;
|
114
|
+
}
|
115
|
+
}
|
116
|
+
|
117
|
+
return false;
|
79
118
|
}
|
80
119
|
|
81
120
|
/**
|
82
|
-
* Checks whether or not a given reference is
|
121
|
+
* Checks whether or not a given reference is evaluated during the initialization of its variable.
|
83
122
|
*
|
84
123
|
* This returns `true` in the following cases:
|
85
124
|
*
|
@@ -88,17 +127,44 @@ function isInRange(node, location) {
|
|
88
127
|
* var {a = a} = obj
|
89
128
|
* for (var a in a) {}
|
90
129
|
* for (var a of a) {}
|
91
|
-
*
|
130
|
+
* var C = class { [C]; }
|
131
|
+
* var C = class { static foo = C; }
|
132
|
+
* class C extends C {}
|
133
|
+
* class C extends (class { static foo = C; }) {}
|
134
|
+
* class C { [C]; }
|
92
135
|
* @param {Reference} reference A reference to check.
|
93
|
-
* @returns {boolean} `true` if the reference is
|
136
|
+
* @returns {boolean} `true` if the reference is evaluated during the initialization.
|
94
137
|
*/
|
95
|
-
function
|
96
|
-
if (
|
138
|
+
function isEvaluatedDuringInitialization(reference) {
|
139
|
+
if (isFromSeparateExecutionContext(reference)) {
|
140
|
+
|
141
|
+
/*
|
142
|
+
* Even if the reference appears in the initializer, it isn't evaluated during the initialization.
|
143
|
+
* For example, `const x = () => x;` is valid.
|
144
|
+
*/
|
97
145
|
return false;
|
98
146
|
}
|
99
147
|
|
100
|
-
let node = variable.identifiers[0].parent;
|
101
148
|
const location = reference.identifier.range[1];
|
149
|
+
const definition = reference.resolved.defs[0];
|
150
|
+
|
151
|
+
if (definition.type === "ClassName") {
|
152
|
+
|
153
|
+
// `ClassDeclaration` or `ClassExpression`
|
154
|
+
const classDefinition = definition.node;
|
155
|
+
|
156
|
+
return (
|
157
|
+
isInRange(classDefinition, location) &&
|
158
|
+
|
159
|
+
/*
|
160
|
+
* Class binding is initialized before running static initializers.
|
161
|
+
* For example, `class C { static foo = C; }` is valid.
|
162
|
+
*/
|
163
|
+
!isInClassStaticInitializerRange(classDefinition.body, location)
|
164
|
+
);
|
165
|
+
}
|
166
|
+
|
167
|
+
let node = definition.name.parent;
|
102
168
|
|
103
169
|
while (node) {
|
104
170
|
if (node.type === "VariableDeclarator") {
|
@@ -167,65 +233,77 @@ module.exports = {
|
|
167
233
|
const options = parseOptions(context.options[0]);
|
168
234
|
|
169
235
|
/**
|
170
|
-
* Determines whether a given
|
171
|
-
*
|
172
|
-
*
|
173
|
-
*
|
236
|
+
* Determines whether a given reference should be checked.
|
237
|
+
*
|
238
|
+
* Returns `false` if the reference is:
|
239
|
+
* - initialization's (e.g., `let a = 1`).
|
240
|
+
* - referring to an undefined variable (i.e., if it's an unresolved reference).
|
241
|
+
* - referring to a variable that is defined, but not in the given source code
|
242
|
+
* (e.g., global environment variable or `arguments` in functions).
|
243
|
+
* - allowed by options.
|
244
|
+
* @param {eslint-scope.Reference} reference The reference
|
245
|
+
* @returns {boolean} `true` if the reference should be checked
|
174
246
|
*/
|
175
|
-
function
|
176
|
-
if (
|
177
|
-
return
|
247
|
+
function shouldCheck(reference) {
|
248
|
+
if (reference.init) {
|
249
|
+
return false;
|
250
|
+
}
|
251
|
+
|
252
|
+
const variable = reference.resolved;
|
253
|
+
|
254
|
+
if (!variable || variable.defs.length === 0) {
|
255
|
+
return false;
|
178
256
|
}
|
179
|
-
|
180
|
-
|
257
|
+
|
258
|
+
const definitionType = variable.defs[0].type;
|
259
|
+
|
260
|
+
if (!options.functions && definitionType === "FunctionName") {
|
261
|
+
return false;
|
181
262
|
}
|
182
|
-
|
183
|
-
|
263
|
+
|
264
|
+
if (
|
265
|
+
(
|
266
|
+
!options.variables && definitionType === "Variable" ||
|
267
|
+
!options.classes && definitionType === "ClassName"
|
268
|
+
) &&
|
269
|
+
|
270
|
+
// don't skip checking the reference if it's in the same execution context, because of TDZ
|
271
|
+
isFromSeparateExecutionContext(reference)
|
272
|
+
) {
|
273
|
+
return false;
|
184
274
|
}
|
275
|
+
|
185
276
|
return true;
|
186
277
|
}
|
187
278
|
|
188
279
|
/**
|
189
|
-
* Finds and validates all
|
190
|
-
* @param {Scope} scope The scope object.
|
280
|
+
* Finds and validates all references in a given scope and its child scopes.
|
281
|
+
* @param {eslint-scope.Scope} scope The scope object.
|
191
282
|
* @returns {void}
|
192
|
-
* @private
|
193
283
|
*/
|
194
|
-
function
|
195
|
-
scope.references.forEach(reference => {
|
284
|
+
function checkReferencesInScope(scope) {
|
285
|
+
scope.references.filter(shouldCheck).forEach(reference => {
|
196
286
|
const variable = reference.resolved;
|
287
|
+
const definitionIdentifier = variable.defs[0].name;
|
197
288
|
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
* - referring to an undefined variable.
|
202
|
-
* - referring to a global environment variable (there're no identifiers).
|
203
|
-
* - located preceded by the variable (except in initializers).
|
204
|
-
* - allowed by options.
|
205
|
-
*/
|
206
|
-
if (reference.init ||
|
207
|
-
!variable ||
|
208
|
-
variable.identifiers.length === 0 ||
|
209
|
-
(variable.identifiers[0].range[1] < reference.identifier.range[1] && !isInInitializer(variable, reference)) ||
|
210
|
-
!isForbidden(variable, reference)
|
289
|
+
if (
|
290
|
+
reference.identifier.range[1] < definitionIdentifier.range[1] ||
|
291
|
+
isEvaluatedDuringInitialization(reference)
|
211
292
|
) {
|
212
|
-
|
293
|
+
context.report({
|
294
|
+
node: reference.identifier,
|
295
|
+
messageId: "usedBeforeDefined",
|
296
|
+
data: reference.identifier
|
297
|
+
});
|
213
298
|
}
|
214
|
-
|
215
|
-
// Reports.
|
216
|
-
context.report({
|
217
|
-
node: reference.identifier,
|
218
|
-
messageId: "usedBeforeDefined",
|
219
|
-
data: reference.identifier
|
220
|
-
});
|
221
299
|
});
|
222
300
|
|
223
|
-
scope.childScopes.forEach(
|
301
|
+
scope.childScopes.forEach(checkReferencesInScope);
|
224
302
|
}
|
225
303
|
|
226
304
|
return {
|
227
305
|
Program() {
|
228
|
-
|
306
|
+
checkReferencesInScope(context.getScope());
|
229
307
|
}
|
230
308
|
};
|
231
309
|
}
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "eslint",
|
3
|
-
"version": "8.
|
3
|
+
"version": "8.2.0",
|
4
4
|
"author": "Nicholas C. Zakas <nicholas+npm@nczconsulting.com>",
|
5
5
|
"description": "An AST-based pattern checker for JavaScript.",
|
6
6
|
"bin": {
|
@@ -47,7 +47,7 @@
|
|
47
47
|
"homepage": "https://eslint.org",
|
48
48
|
"bugs": "https://github.com/eslint/eslint/issues/",
|
49
49
|
"dependencies": {
|
50
|
-
"@eslint/eslintrc": "^1.0.
|
50
|
+
"@eslint/eslintrc": "^1.0.4",
|
51
51
|
"@humanwhocodes/config-array": "^0.6.0",
|
52
52
|
"ajv": "^6.10.0",
|
53
53
|
"chalk": "^4.0.0",
|
@@ -81,7 +81,7 @@
|
|
81
81
|
"progress": "^2.0.0",
|
82
82
|
"regexpp": "^3.2.0",
|
83
83
|
"semver": "^7.2.1",
|
84
|
-
"strip-ansi": "^6.0.
|
84
|
+
"strip-ansi": "^6.0.1",
|
85
85
|
"strip-json-comments": "^3.1.0",
|
86
86
|
"text-table": "^0.2.0",
|
87
87
|
"v8-compile-cache": "^2.0.3"
|
@@ -101,9 +101,9 @@
|
|
101
101
|
"eslint-plugin-eslint-comments": "^3.2.0",
|
102
102
|
"eslint-plugin-eslint-plugin": "^4.0.1",
|
103
103
|
"eslint-plugin-internal-rules": "file:tools/internal-rules",
|
104
|
-
"eslint-plugin-jsdoc": "^
|
104
|
+
"eslint-plugin-jsdoc": "^37.0.0",
|
105
105
|
"eslint-plugin-node": "^11.1.0",
|
106
|
-
"eslint-release": "^3.
|
106
|
+
"eslint-release": "^3.2.0",
|
107
107
|
"eslump": "^3.0.0",
|
108
108
|
"esprima": "^4.0.1",
|
109
109
|
"fs-teardown": "^0.1.3",
|