eslint 8.34.0 → 8.37.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 +11 -12
- package/conf/rule-type-list.json +2 -2
- package/lib/cli-engine/cli-engine.js +2 -2
- package/lib/cli-engine/file-enumerator.js +8 -6
- package/lib/config/default-config.js +1 -4
- package/lib/config/flat-config-array.js +77 -17
- package/lib/config/flat-config-schema.js +4 -18
- package/lib/eslint/eslint-helpers.js +3 -3
- package/lib/linter/linter.js +5 -30
- package/lib/rule-tester/flat-rule-tester.js +1 -1
- package/lib/rule-tester/rule-tester.js +1 -1
- package/lib/rules/camelcase.js +3 -2
- package/lib/rules/consistent-this.js +4 -2
- package/lib/rules/global-require.js +3 -1
- package/lib/rules/handle-callback-err.js +2 -1
- package/lib/rules/id-blacklist.js +3 -2
- package/lib/rules/id-denylist.js +3 -2
- package/lib/rules/id-match.js +3 -2
- package/lib/rules/lines-around-comment.js +11 -0
- package/lib/rules/logical-assignment-operators.js +4 -4
- package/lib/rules/multiline-comment-style.js +42 -3
- package/lib/rules/no-alert.js +3 -1
- package/lib/rules/no-catch-shadow.js +3 -1
- package/lib/rules/no-console.js +3 -2
- package/lib/rules/no-constant-binary-expression.js +36 -27
- package/lib/rules/no-constant-condition.js +3 -2
- package/lib/rules/no-control-regex.js +1 -1
- package/lib/rules/no-else-return.js +13 -12
- package/lib/rules/no-eval.js +5 -5
- package/lib/rules/no-extend-native.js +3 -2
- package/lib/rules/no-extra-boolean-cast.js +1 -1
- package/lib/rules/no-extra-parens.js +1 -1
- package/lib/rules/no-global-assign.js +3 -2
- package/lib/rules/no-implicit-globals.js +3 -2
- package/lib/rules/no-implied-eval.js +5 -4
- package/lib/rules/no-import-assign.js +4 -2
- package/lib/rules/no-invalid-regexp.js +1 -1
- package/lib/rules/no-invalid-this.js +2 -2
- package/lib/rules/no-label-var.js +2 -1
- package/lib/rules/no-lone-blocks.js +3 -2
- package/lib/rules/no-loop-func.js +3 -1
- package/lib/rules/no-misleading-character-class.js +12 -41
- package/lib/rules/no-native-reassign.js +3 -2
- package/lib/rules/no-new-func.js +7 -6
- package/lib/rules/no-new-native-nonconstructor.js +8 -6
- package/lib/rules/no-new-object.js +4 -1
- package/lib/rules/no-new-symbol.js +8 -6
- package/lib/rules/no-obj-calls.js +8 -6
- package/lib/rules/no-promise-executor-return.js +3 -2
- package/lib/rules/no-redeclare.js +3 -3
- package/lib/rules/no-regex-spaces.js +4 -2
- package/lib/rules/no-restricted-globals.js +4 -2
- package/lib/rules/no-setter-return.js +3 -2
- package/lib/rules/no-shadow.js +3 -2
- package/lib/rules/no-undef-init.js +1 -1
- package/lib/rules/no-undef.js +3 -2
- package/lib/rules/no-undefined.js +4 -2
- package/lib/rules/no-unmodified-loop-condition.js +2 -2
- package/lib/rules/no-unused-vars.js +1 -1
- package/lib/rules/no-use-before-define.js +3 -2
- package/lib/rules/no-useless-backreference.js +9 -7
- package/lib/rules/no-useless-return.js +1 -1
- package/lib/rules/object-shorthand.js +3 -2
- package/lib/rules/prefer-arrow-callback.js +1 -1
- package/lib/rules/prefer-exponentiation-operator.js +5 -5
- package/lib/rules/prefer-named-capture-group.js +8 -8
- package/lib/rules/prefer-object-has-own.js +4 -2
- package/lib/rules/prefer-object-spread.js +12 -12
- package/lib/rules/prefer-regex-literals.js +26 -27
- package/lib/rules/prefer-rest-params.js +5 -2
- package/lib/rules/radix.js +11 -11
- package/lib/rules/require-atomic-updates.js +2 -2
- package/lib/rules/require-unicode-regexp.js +63 -7
- package/lib/rules/symbol-description.js +7 -5
- package/lib/rules/utils/regular-expressions.js +42 -0
- package/lib/rules/valid-typeof.js +3 -3
- package/lib/rules/wrap-iife.js +1 -1
- package/lib/source-code/source-code.js +52 -1
- package/lib/source-code/token-store/index.js +1 -1
- package/lib/source-code/token-store/utils.js +14 -4
- package/messages/no-config-found.js +1 -1
- package/package.json +12 -7
- package/conf/eslint-all.js +0 -31
- package/conf/eslint-recommended.js +0 -76
package/README.md
CHANGED
@@ -16,8 +16,7 @@
|
|
16
16
|
[Report Bugs](https://eslint.org/docs/latest/contribute/report-bugs) |
|
17
17
|
[Code of Conduct](https://eslint.org/conduct) |
|
18
18
|
[Twitter](https://twitter.com/geteslint) |
|
19
|
-
[
|
20
|
-
[Chat Room](https://eslint.org/chat)
|
19
|
+
[Discord](https://eslint.org/chat)
|
21
20
|
|
22
21
|
ESLint is a tool for identifying and reporting on patterns found in ECMAScript/JavaScript code. In many ways, it is similar to JSLint and JSHint with a few exceptions:
|
23
22
|
|
@@ -129,7 +128,7 @@ Once a language feature has been adopted into the ECMAScript standard (stage 4 a
|
|
129
128
|
|
130
129
|
### Where to ask for help?
|
131
130
|
|
132
|
-
|
131
|
+
Open a [discussion](https://github.com/eslint/eslint/discussions) or stop by our [Discord server](https://eslint.org/chat).
|
133
132
|
|
134
133
|
### Why doesn't ESLint lock dependency versions?
|
135
134
|
|
@@ -213,11 +212,6 @@ The people who manage releases, review feature requests, and meet regularly to e
|
|
213
212
|
Nicholas C. Zakas
|
214
213
|
</a>
|
215
214
|
</td><td align="center" valign="top" width="11%">
|
216
|
-
<a href="https://github.com/btmills">
|
217
|
-
<img src="https://github.com/btmills.png?s=75" width="75" height="75"><br />
|
218
|
-
Brandon Mills
|
219
|
-
</a>
|
220
|
-
</td><td align="center" valign="top" width="11%">
|
221
215
|
<a href="https://github.com/mdjermanovic">
|
222
216
|
<img src="https://github.com/mdjermanovic.png?s=75" width="75" height="75"><br />
|
223
217
|
Milos Djermanovic
|
@@ -250,9 +244,14 @@ The people who review and fix bugs and help triage issues.
|
|
250
244
|
Bryan Mishkin
|
251
245
|
</a>
|
252
246
|
</td><td align="center" valign="top" width="11%">
|
253
|
-
<a href="https://github.com/
|
254
|
-
<img src="https://github.com/
|
255
|
-
|
247
|
+
<a href="https://github.com/btmills">
|
248
|
+
<img src="https://github.com/btmills.png?s=75" width="75" height="75"><br />
|
249
|
+
Brandon Mills
|
250
|
+
</a>
|
251
|
+
</td><td align="center" valign="top" width="11%">
|
252
|
+
<a href="https://github.com/fasttime">
|
253
|
+
<img src="https://github.com/fasttime.png?s=75" width="75" height="75"><br />
|
254
|
+
Francesco Trotta
|
256
255
|
</a>
|
257
256
|
</td><td align="center" valign="top" width="11%">
|
258
257
|
<a href="https://github.com/yeonjuan">
|
@@ -293,7 +292,7 @@ The following companies, organizations, and individuals support ESLint's ongoing
|
|
293
292
|
<h3>Platinum Sponsors</h3>
|
294
293
|
<p><a href="#"><img src="https://images.opencollective.com/2021-frameworks-fund/logo.png" alt="Chrome Frameworks Fund" height="undefined"></a> <a href="https://automattic.com"><img src="https://images.opencollective.com/automattic/d0ef3e1/logo.png" alt="Automattic" height="undefined"></a></p><h3>Gold Sponsors</h3>
|
295
294
|
<p><a href="https://ridicorp.com/career/"><img src="https://images.opencollective.com/ridi-corporation/175dcf3/logo.png" alt="RIDI" height="96"></a> <a href="https://engineering.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></p><h3>Silver Sponsors</h3>
|
296
|
-
<p><a href="https://sentry.io"><img src="https://avatars.githubusercontent.com/u/1396951?v=4" alt="Sentry" height="64"></a> <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>
|
295
|
+
<p><a href="https://sentry.io"><img src="https://avatars.githubusercontent.com/u/1396951?v=4" alt="Sentry" height="64"></a> <a href="https://liftoff.io/"><img src="https://images.opencollective.com/liftoff/5c4fa84/logo.png" alt="Liftoff" height="64"></a> <a href="https://americanexpress.io"><img src="https://avatars.githubusercontent.com/u/3853301?v=4" alt="American Express" height="64"></a></p><h3>Bronze Sponsors</h3>
|
297
296
|
<p><a href="https://paydaysay.com/"><img src="https://images.opencollective.com/payday-say-organization/9cd2467/logo.png" alt="PayDay Say" 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://nx.dev"><img src="https://images.opencollective.com/nx/0efbe42/logo.png" alt="Nx (by Nrwl)" 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://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://transloadit.com/"><img src="https://avatars.githubusercontent.com/u/125754?v=4" alt="Transloadit" height="32"></a> <a href="https://www.ignitionapp.com"><img src="https://avatars.githubusercontent.com/u/5753491?v=4" alt="Ignition" height="32"></a> <a href="https://herocoders.com"><img src="https://avatars.githubusercontent.com/u/37549774?v=4" alt="HeroCoders" height="32"></a> <a href="https://quickbookstoolhub.com"><img src="https://avatars.githubusercontent.com/u/95090305?u=e5bc398ef775c9ed19f955c675cdc1fb6abf01df&v=4" alt="QuickBooks Tool hub" height="32"></a></p>
|
298
297
|
<!--sponsorsend-->
|
299
298
|
|
package/conf/rule-type-list.json
CHANGED
@@ -6,12 +6,12 @@
|
|
6
6
|
],
|
7
7
|
"deprecated": {
|
8
8
|
"name": "Deprecated",
|
9
|
-
"description": "These rules have been deprecated in accordance with the <a href=\"/
|
9
|
+
"description": "These rules have been deprecated in accordance with the <a href=\"{{ '/use/rule-deprecation' | url }}\">deprecation policy</a>, and replaced by newer rules:",
|
10
10
|
"rules": []
|
11
11
|
},
|
12
12
|
"removed": {
|
13
13
|
"name": "Removed",
|
14
|
-
"description": "These rules from older versions of ESLint (before the <a href=\"/
|
14
|
+
"description": "These rules from older versions of ESLint (before the <a href=\"{{ '/use/rule-deprecation' | url }}\">deprecation policy</a> existed) have been replaced by newer rules:",
|
15
15
|
"rules": [
|
16
16
|
{ "removed": "generator-star", "replacedBy": ["generator-star-spacing"] },
|
17
17
|
{ "removed": "global-strict", "replacedBy": ["strict"] },
|
@@ -615,8 +615,8 @@ class CLIEngine {
|
|
615
615
|
useEslintrc: options.useEslintrc,
|
616
616
|
builtInRules,
|
617
617
|
loadRules,
|
618
|
-
getEslintRecommendedConfig: () => require("
|
619
|
-
getEslintAllConfig: () => require("
|
618
|
+
getEslintRecommendedConfig: () => require("@eslint/js").configs.recommended,
|
619
|
+
getEslintAllConfig: () => require("@eslint/js").configs.all
|
620
620
|
});
|
621
621
|
const fileEnumerator = new FileEnumerator({
|
622
622
|
configArrayFactory,
|
@@ -217,8 +217,8 @@ class FileEnumerator {
|
|
217
217
|
cwd = process.cwd(),
|
218
218
|
configArrayFactory = new CascadingConfigArrayFactory({
|
219
219
|
cwd,
|
220
|
-
getEslintRecommendedConfig: () => require("
|
221
|
-
getEslintAllConfig: () => require("
|
220
|
+
getEslintRecommendedConfig: () => require("@eslint/js").configs.recommended,
|
221
|
+
getEslintAllConfig: () => require("@eslint/js").configs.all
|
222
222
|
}),
|
223
223
|
extensions = null,
|
224
224
|
globInputPaths = true,
|
@@ -349,7 +349,7 @@ class FileEnumerator {
|
|
349
349
|
return this._iterateFilesWithFile(absolutePath);
|
350
350
|
}
|
351
351
|
if (globInputPaths && isGlobPattern(pattern)) {
|
352
|
-
return this._iterateFilesWithGlob(
|
352
|
+
return this._iterateFilesWithGlob(pattern, isDot);
|
353
353
|
}
|
354
354
|
|
355
355
|
return [];
|
@@ -398,15 +398,17 @@ class FileEnumerator {
|
|
398
398
|
_iterateFilesWithGlob(pattern, dotfiles) {
|
399
399
|
debug(`Glob: ${pattern}`);
|
400
400
|
|
401
|
-
const
|
402
|
-
const
|
401
|
+
const { cwd } = internalSlotsMap.get(this);
|
402
|
+
const directoryPath = path.resolve(cwd, getGlobParent(pattern));
|
403
|
+
const absolutePath = path.resolve(cwd, pattern);
|
404
|
+
const globPart = absolutePath.slice(directoryPath.length + 1);
|
403
405
|
|
404
406
|
/*
|
405
407
|
* recursive if there are `**` or path separators in the glob part.
|
406
408
|
* Otherwise, patterns such as `src/*.js`, it doesn't need recursive.
|
407
409
|
*/
|
408
410
|
const recursive = /\*\*|\/|\\/u.test(globPart);
|
409
|
-
const selector = new Minimatch(
|
411
|
+
const selector = new Minimatch(absolutePath, minimatchOpts);
|
410
412
|
|
411
413
|
debug(`recursive? ${recursive}`);
|
412
414
|
|
@@ -19,9 +19,6 @@ exports.defaultConfig = [
|
|
19
19
|
{
|
20
20
|
plugins: {
|
21
21
|
"@": {
|
22
|
-
parsers: {
|
23
|
-
espree: require("espree")
|
24
|
-
},
|
25
22
|
|
26
23
|
/*
|
27
24
|
* Because we try to delay loading rules until absolutely
|
@@ -43,7 +40,7 @@ exports.defaultConfig = [
|
|
43
40
|
languageOptions: {
|
44
41
|
sourceType: "module",
|
45
42
|
ecmaVersion: "latest",
|
46
|
-
parser: "
|
43
|
+
parser: require("espree"),
|
47
44
|
parserOptions: {}
|
48
45
|
}
|
49
46
|
},
|
@@ -13,7 +13,7 @@ const { ConfigArray, ConfigArraySymbol } = require("@humanwhocodes/config-array"
|
|
13
13
|
const { flatConfigSchema } = require("./flat-config-schema");
|
14
14
|
const { RuleValidator } = require("./rule-validator");
|
15
15
|
const { defaultConfig } = require("./default-config");
|
16
|
-
const
|
16
|
+
const jsPlugin = require("@eslint/js");
|
17
17
|
|
18
18
|
//-----------------------------------------------------------------------------
|
19
19
|
// Helpers
|
@@ -36,6 +36,45 @@ function splitPluginIdentifier(identifier) {
|
|
36
36
|
};
|
37
37
|
}
|
38
38
|
|
39
|
+
/**
|
40
|
+
* Returns the name of an object in the config by reading its `meta` key.
|
41
|
+
* @param {Object} object The object to check.
|
42
|
+
* @returns {string?} The name of the object if found or `null` if there
|
43
|
+
* is no name.
|
44
|
+
*/
|
45
|
+
function getObjectId(object) {
|
46
|
+
|
47
|
+
// first check old-style name
|
48
|
+
let name = object.name;
|
49
|
+
|
50
|
+
if (!name) {
|
51
|
+
|
52
|
+
if (!object.meta) {
|
53
|
+
return null;
|
54
|
+
}
|
55
|
+
|
56
|
+
name = object.meta.name;
|
57
|
+
|
58
|
+
if (!name) {
|
59
|
+
return null;
|
60
|
+
}
|
61
|
+
}
|
62
|
+
|
63
|
+
// now check for old-style version
|
64
|
+
let version = object.version;
|
65
|
+
|
66
|
+
if (!version) {
|
67
|
+
version = object.meta && object.meta.version;
|
68
|
+
}
|
69
|
+
|
70
|
+
// if there's a version then append that
|
71
|
+
if (version) {
|
72
|
+
return `${name}@${version}`;
|
73
|
+
}
|
74
|
+
|
75
|
+
return name;
|
76
|
+
}
|
77
|
+
|
39
78
|
const originalBaseConfig = Symbol("originalBaseConfig");
|
40
79
|
|
41
80
|
//-----------------------------------------------------------------------------
|
@@ -96,17 +135,23 @@ class FlatConfigArray extends ConfigArray {
|
|
96
135
|
*/
|
97
136
|
[ConfigArraySymbol.preprocessConfig](config) {
|
98
137
|
if (config === "eslint:recommended") {
|
99
|
-
|
138
|
+
|
139
|
+
// if we are in a Node.js environment warn the user
|
140
|
+
if (typeof process !== "undefined" && process.emitWarning) {
|
141
|
+
process.emitWarning("The 'eslint:recommended' string configuration is deprecated and will be replaced by the @eslint/js package's 'recommended' config.");
|
142
|
+
}
|
143
|
+
|
144
|
+
return jsPlugin.configs.recommended;
|
100
145
|
}
|
101
146
|
|
102
147
|
if (config === "eslint:all") {
|
103
148
|
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
return
|
149
|
+
// if we are in a Node.js environment warn the user
|
150
|
+
if (typeof process !== "undefined" && process.emitWarning) {
|
151
|
+
process.emitWarning("The 'eslint:all' string configuration is deprecated and will be replaced by the @eslint/js package's 'all' config.");
|
152
|
+
}
|
153
|
+
|
154
|
+
return jsPlugin.configs.all;
|
110
155
|
}
|
111
156
|
|
112
157
|
/*
|
@@ -145,16 +190,15 @@ class FlatConfigArray extends ConfigArray {
|
|
145
190
|
|
146
191
|
// Check parser value
|
147
192
|
if (languageOptions && languageOptions.parser) {
|
148
|
-
|
149
|
-
const { pluginName, objectName: localParserName } = splitPluginIdentifier(languageOptions.parser);
|
193
|
+
const { parser } = languageOptions;
|
150
194
|
|
151
|
-
|
195
|
+
if (typeof parser === "object") {
|
196
|
+
parserName = getObjectId(parser);
|
152
197
|
|
153
|
-
if (!
|
154
|
-
|
198
|
+
if (!parserName) {
|
199
|
+
invalidParser = true;
|
155
200
|
}
|
156
201
|
|
157
|
-
languageOptions.parser = plugins[pluginName].parsers[localParserName];
|
158
202
|
} else {
|
159
203
|
invalidParser = true;
|
160
204
|
}
|
@@ -172,6 +216,13 @@ class FlatConfigArray extends ConfigArray {
|
|
172
216
|
}
|
173
217
|
|
174
218
|
config.processor = plugins[pluginName].processors[localProcessorName];
|
219
|
+
} else if (typeof processor === "object") {
|
220
|
+
processorName = getObjectId(processor);
|
221
|
+
|
222
|
+
if (!processorName) {
|
223
|
+
invalidProcessor = true;
|
224
|
+
}
|
225
|
+
|
175
226
|
} else {
|
176
227
|
invalidProcessor = true;
|
177
228
|
}
|
@@ -185,16 +236,25 @@ class FlatConfigArray extends ConfigArray {
|
|
185
236
|
value: function() {
|
186
237
|
|
187
238
|
if (invalidParser) {
|
188
|
-
throw new Error("
|
239
|
+
throw new Error("Could not serialize parser object (missing 'meta' object).");
|
189
240
|
}
|
190
241
|
|
191
242
|
if (invalidProcessor) {
|
192
|
-
throw new Error("
|
243
|
+
throw new Error("Could not serialize processor object (missing 'meta' object).");
|
193
244
|
}
|
194
245
|
|
195
246
|
return {
|
196
247
|
...this,
|
197
|
-
plugins: Object.
|
248
|
+
plugins: Object.entries(plugins).map(([namespace, plugin]) => {
|
249
|
+
|
250
|
+
const pluginId = getObjectId(plugin);
|
251
|
+
|
252
|
+
if (!pluginId) {
|
253
|
+
return namespace;
|
254
|
+
}
|
255
|
+
|
256
|
+
return `${namespace}:${pluginId}`;
|
257
|
+
}),
|
198
258
|
languageOptions: {
|
199
259
|
...languageOptions,
|
200
260
|
parser: parserName
|
@@ -179,18 +179,6 @@ function assertIsObject(value) {
|
|
179
179
|
}
|
180
180
|
}
|
181
181
|
|
182
|
-
/**
|
183
|
-
* Validates that a value is an object or a string.
|
184
|
-
* @param {any} value The value to check.
|
185
|
-
* @returns {void}
|
186
|
-
* @throws {TypeError} If the value isn't an object or a string.
|
187
|
-
*/
|
188
|
-
function assertIsObjectOrString(value) {
|
189
|
-
if ((!value || typeof value !== "object") && typeof value !== "string") {
|
190
|
-
throw new TypeError("Expected an object or string.");
|
191
|
-
}
|
192
|
-
}
|
193
|
-
|
194
182
|
//-----------------------------------------------------------------------------
|
195
183
|
// Low-Level Schemas
|
196
184
|
//-----------------------------------------------------------------------------
|
@@ -242,15 +230,13 @@ const globalsSchema = {
|
|
242
230
|
const parserSchema = {
|
243
231
|
merge: "replace",
|
244
232
|
validate(value) {
|
245
|
-
assertIsObjectOrString(value);
|
246
233
|
|
247
|
-
if (
|
248
|
-
|
234
|
+
if (!value || typeof value !== "object" ||
|
235
|
+
(typeof value.parse !== "function" && typeof value.parseForESLint !== "function")
|
236
|
+
) {
|
237
|
+
throw new TypeError("Expected object with parse() or parseForESLint() method.");
|
249
238
|
}
|
250
239
|
|
251
|
-
if (typeof value === "string") {
|
252
|
-
assertIsPluginMemberName(value);
|
253
|
-
}
|
254
240
|
}
|
255
241
|
};
|
256
242
|
|
@@ -223,7 +223,7 @@ function globMatch({ basePath, pattern }) {
|
|
223
223
|
* should be thrown when a pattern is unmatched.
|
224
224
|
* @returns {Promise<Array<string>>} An array of matching file paths
|
225
225
|
* or an empty array if there are no matches.
|
226
|
-
* @throws {
|
226
|
+
* @throws {UnmatchedSearchPatternsError} If there is a pattern that doesn't
|
227
227
|
* match any files.
|
228
228
|
*/
|
229
229
|
async function globSearch({
|
@@ -526,9 +526,9 @@ async function findFiles({
|
|
526
526
|
}
|
527
527
|
|
528
528
|
// save patterns for later use based on whether globs are enabled
|
529
|
-
if (globInputPaths && isGlobPattern(
|
529
|
+
if (globInputPaths && isGlobPattern(pattern)) {
|
530
530
|
|
531
|
-
const basePath = globParent(
|
531
|
+
const basePath = path.resolve(cwd, globParent(pattern));
|
532
532
|
|
533
533
|
// group in cwd if possible and split out others
|
534
534
|
if (isPathInside(basePath, cwd)) {
|
package/lib/linter/linter.js
CHANGED
@@ -857,47 +857,22 @@ function parse(text, languageOptions, filePath) {
|
|
857
857
|
}
|
858
858
|
}
|
859
859
|
|
860
|
-
/**
|
861
|
-
* Gets the scope for the current node
|
862
|
-
* @param {ScopeManager} scopeManager The scope manager for this AST
|
863
|
-
* @param {ASTNode} currentNode The node to get the scope of
|
864
|
-
* @returns {eslint-scope.Scope} The scope information for this node
|
865
|
-
*/
|
866
|
-
function getScope(scopeManager, currentNode) {
|
867
|
-
|
868
|
-
// On Program node, get the outermost scope to avoid return Node.js special function scope or ES modules scope.
|
869
|
-
const inner = currentNode.type !== "Program";
|
870
|
-
|
871
|
-
for (let node = currentNode; node; node = node.parent) {
|
872
|
-
const scope = scopeManager.acquire(node, inner);
|
873
|
-
|
874
|
-
if (scope) {
|
875
|
-
if (scope.type === "function-expression-name") {
|
876
|
-
return scope.childScopes[0];
|
877
|
-
}
|
878
|
-
return scope;
|
879
|
-
}
|
880
|
-
}
|
881
|
-
|
882
|
-
return scopeManager.scopes[0];
|
883
|
-
}
|
884
|
-
|
885
860
|
/**
|
886
861
|
* Marks a variable as used in the current scope
|
887
|
-
* @param {
|
862
|
+
* @param {SourceCode} sourceCode The source code for the currently linted file.
|
888
863
|
* @param {ASTNode} currentNode The node currently being traversed
|
889
864
|
* @param {LanguageOptions} languageOptions The options used to parse this text
|
890
865
|
* @param {string} name The name of the variable that should be marked as used.
|
891
866
|
* @returns {boolean} True if the variable was found and marked as used, false if not.
|
892
867
|
*/
|
893
|
-
function markVariableAsUsed(
|
868
|
+
function markVariableAsUsed(sourceCode, currentNode, languageOptions, name) {
|
894
869
|
const parserOptions = languageOptions.parserOptions;
|
895
870
|
const sourceType = languageOptions.sourceType;
|
896
871
|
const hasGlobalReturn =
|
897
872
|
(parserOptions.ecmaFeatures && parserOptions.ecmaFeatures.globalReturn) ||
|
898
873
|
sourceType === "commonjs";
|
899
874
|
const specialScope = hasGlobalReturn || sourceType === "module";
|
900
|
-
const currentScope = getScope(
|
875
|
+
const currentScope = sourceCode.getScope(currentNode);
|
901
876
|
|
902
877
|
// Special Node.js scope means we need to start one level deeper
|
903
878
|
const initialScope = currentScope.type === "global" && specialScope ? currentScope.childScopes[0] : currentScope;
|
@@ -1026,9 +1001,9 @@ function runRules(sourceCode, configuredRules, ruleMapper, parserName, languageO
|
|
1026
1001
|
getCwd: () => cwd,
|
1027
1002
|
getFilename: () => filename,
|
1028
1003
|
getPhysicalFilename: () => physicalFilename || filename,
|
1029
|
-
getScope: () => getScope(
|
1004
|
+
getScope: () => sourceCode.getScope(currentNode),
|
1030
1005
|
getSourceCode: () => sourceCode,
|
1031
|
-
markVariableAsUsed: name => markVariableAsUsed(sourceCode
|
1006
|
+
markVariableAsUsed: name => markVariableAsUsed(sourceCode, currentNode, languageOptions, name),
|
1032
1007
|
parserOptions: {
|
1033
1008
|
...languageOptions.parserOptions
|
1034
1009
|
},
|
@@ -345,7 +345,7 @@ class FlatRuleTester {
|
|
345
345
|
* @returns {void}
|
346
346
|
*/
|
347
347
|
static setDefaultConfig(config) {
|
348
|
-
if (typeof config !== "object") {
|
348
|
+
if (typeof config !== "object" || config === null) {
|
349
349
|
throw new TypeError("FlatRuleTester.setDefaultConfig: config must be an object");
|
350
350
|
}
|
351
351
|
sharedDefaultConfig = config;
|
@@ -412,7 +412,7 @@ class RuleTester {
|
|
412
412
|
* @returns {void}
|
413
413
|
*/
|
414
414
|
static setDefaultConfig(config) {
|
415
|
-
if (typeof config !== "object") {
|
415
|
+
if (typeof config !== "object" || config === null) {
|
416
416
|
throw new TypeError("RuleTester.setDefaultConfig: config must be an object");
|
417
417
|
}
|
418
418
|
defaultConfig = config;
|
package/lib/rules/camelcase.js
CHANGED
@@ -73,6 +73,7 @@ module.exports = {
|
|
73
73
|
const ignoreImports = options.ignoreImports;
|
74
74
|
const ignoreGlobals = options.ignoreGlobals;
|
75
75
|
const allow = options.allow || [];
|
76
|
+
const sourceCode = context.getSourceCode();
|
76
77
|
|
77
78
|
//--------------------------------------------------------------------------
|
78
79
|
// Helpers
|
@@ -245,8 +246,8 @@ module.exports = {
|
|
245
246
|
return {
|
246
247
|
|
247
248
|
// Report camelcase of global variable references ------------------
|
248
|
-
Program() {
|
249
|
-
const scope =
|
249
|
+
Program(node) {
|
250
|
+
const scope = sourceCode.getScope(node);
|
250
251
|
|
251
252
|
if (!ignoreGlobals) {
|
252
253
|
|
@@ -36,6 +36,7 @@ module.exports = {
|
|
36
36
|
|
37
37
|
create(context) {
|
38
38
|
let aliases = [];
|
39
|
+
const sourceCode = context.getSourceCode();
|
39
40
|
|
40
41
|
if (context.options.length === 0) {
|
41
42
|
aliases.push("that");
|
@@ -115,10 +116,11 @@ module.exports = {
|
|
115
116
|
|
116
117
|
/**
|
117
118
|
* Check each alias to ensure that is was assigned to the correct value.
|
119
|
+
* @param {ASTNode} node The node that represents the scope to check.
|
118
120
|
* @returns {void}
|
119
121
|
*/
|
120
|
-
function ensureWasAssigned() {
|
121
|
-
const scope =
|
122
|
+
function ensureWasAssigned(node) {
|
123
|
+
const scope = sourceCode.getScope(node);
|
122
124
|
|
123
125
|
aliases.forEach(alias => {
|
124
126
|
checkWasAssigned(alias, scope);
|
@@ -71,9 +71,11 @@ module.exports = {
|
|
71
71
|
},
|
72
72
|
|
73
73
|
create(context) {
|
74
|
+
const sourceCode = context.getSourceCode();
|
75
|
+
|
74
76
|
return {
|
75
77
|
CallExpression(node) {
|
76
|
-
const currentScope =
|
78
|
+
const currentScope = sourceCode.getScope(node);
|
77
79
|
|
78
80
|
if (node.callee.name === "require" && !isShadowed(currentScope, node.callee)) {
|
79
81
|
const isGoodRequire = context.getAncestors().every(parent => ACCEPTABLE_PARENTS.has(parent.type));
|
@@ -38,6 +38,7 @@ module.exports = {
|
|
38
38
|
create(context) {
|
39
39
|
|
40
40
|
const errorArgument = context.options[0] || "err";
|
41
|
+
const sourceCode = context.getSourceCode();
|
41
42
|
|
42
43
|
/**
|
43
44
|
* Checks if the given argument should be interpreted as a regexp pattern.
|
@@ -79,7 +80,7 @@ module.exports = {
|
|
79
80
|
* @returns {void}
|
80
81
|
*/
|
81
82
|
function checkForError(node) {
|
82
|
-
const scope =
|
83
|
+
const scope = sourceCode.getScope(node),
|
83
84
|
parameters = getParameters(scope),
|
84
85
|
firstParameter = parameters[0];
|
85
86
|
|
@@ -140,6 +140,7 @@ module.exports = {
|
|
140
140
|
|
141
141
|
const denyList = new Set(context.options);
|
142
142
|
const reportedNodes = new Set();
|
143
|
+
const sourceCode = context.getSourceCode();
|
143
144
|
|
144
145
|
let globalScope;
|
145
146
|
|
@@ -231,8 +232,8 @@ module.exports = {
|
|
231
232
|
|
232
233
|
return {
|
233
234
|
|
234
|
-
Program() {
|
235
|
-
globalScope =
|
235
|
+
Program(node) {
|
236
|
+
globalScope = sourceCode.getScope(node);
|
236
237
|
},
|
237
238
|
|
238
239
|
Identifier(node) {
|
package/lib/rules/id-denylist.js
CHANGED
@@ -121,6 +121,7 @@ module.exports = {
|
|
121
121
|
|
122
122
|
const denyList = new Set(context.options);
|
123
123
|
const reportedNodes = new Set();
|
124
|
+
const sourceCode = context.getSourceCode();
|
124
125
|
|
125
126
|
let globalScope;
|
126
127
|
|
@@ -210,8 +211,8 @@ module.exports = {
|
|
210
211
|
|
211
212
|
return {
|
212
213
|
|
213
|
-
Program() {
|
214
|
-
globalScope =
|
214
|
+
Program(node) {
|
215
|
+
globalScope = sourceCode.getScope(node);
|
215
216
|
},
|
216
217
|
|
217
218
|
[[
|
package/lib/rules/id-match.js
CHANGED
@@ -67,6 +67,7 @@ module.exports = {
|
|
67
67
|
onlyDeclarations = !!options.onlyDeclarations,
|
68
68
|
ignoreDestructuring = !!options.ignoreDestructuring;
|
69
69
|
|
70
|
+
const sourceCode = context.getSourceCode();
|
70
71
|
let globalScope;
|
71
72
|
|
72
73
|
//--------------------------------------------------------------------------
|
@@ -170,8 +171,8 @@ module.exports = {
|
|
170
171
|
|
171
172
|
return {
|
172
173
|
|
173
|
-
Program() {
|
174
|
-
globalScope =
|
174
|
+
Program(node) {
|
175
|
+
globalScope = sourceCode.getScope(node);
|
175
176
|
},
|
176
177
|
|
177
178
|
Identifier(node) {
|
@@ -113,6 +113,10 @@ module.exports = {
|
|
113
113
|
},
|
114
114
|
applyDefaultIgnorePatterns: {
|
115
115
|
type: "boolean"
|
116
|
+
},
|
117
|
+
afterHashbangComment: {
|
118
|
+
type: "boolean",
|
119
|
+
default: false
|
116
120
|
}
|
117
121
|
},
|
118
122
|
additionalProperties: false
|
@@ -449,6 +453,13 @@ module.exports = {
|
|
449
453
|
before: options.beforeBlockComment
|
450
454
|
});
|
451
455
|
}
|
456
|
+
} else if (token.type === "Shebang") {
|
457
|
+
if (options.afterHashbangComment) {
|
458
|
+
checkForEmptyLine(token, {
|
459
|
+
after: options.afterHashbangComment,
|
460
|
+
before: false
|
461
|
+
});
|
462
|
+
}
|
452
463
|
}
|
453
464
|
});
|
454
465
|
}
|
@@ -112,7 +112,7 @@ function isBooleanCast(expression, scope) {
|
|
112
112
|
/**
|
113
113
|
* Returns true for:
|
114
114
|
* truthiness checks: value, Boolean(value), !!value
|
115
|
-
*
|
115
|
+
* falsiness checks: !value, !Boolean(value)
|
116
116
|
* nullish checks: value == null, value === undefined || value === null
|
117
117
|
* @param {ASTNode} expression Test condition
|
118
118
|
* @param {import('eslint-scope').Scope} scope Scope of the expression
|
@@ -159,7 +159,7 @@ module.exports = {
|
|
159
159
|
type: "suggestion",
|
160
160
|
|
161
161
|
docs: {
|
162
|
-
description: "Require or disallow logical assignment
|
162
|
+
description: "Require or disallow logical assignment operator shorthand",
|
163
163
|
recommended: false,
|
164
164
|
url: "https://eslint.org/docs/rules/logical-assignment-operators"
|
165
165
|
},
|
@@ -206,7 +206,7 @@ module.exports = {
|
|
206
206
|
const mode = context.options[0] === "never" ? "never" : "always";
|
207
207
|
const checkIf = mode === "always" && context.options.length > 1 && context.options[1].enforceForIfStatements;
|
208
208
|
const sourceCode = context.getSourceCode();
|
209
|
-
const isStrict =
|
209
|
+
const isStrict = sourceCode.getScope(sourceCode.ast).isStrict;
|
210
210
|
|
211
211
|
/**
|
212
212
|
* Returns false if the access could be a getter
|
@@ -409,7 +409,7 @@ module.exports = {
|
|
409
409
|
}
|
410
410
|
|
411
411
|
const body = hasBody ? ifNode.consequent.body[0] : ifNode.consequent;
|
412
|
-
const scope =
|
412
|
+
const scope = sourceCode.getScope(ifNode);
|
413
413
|
const existence = getExistence(ifNode.test, scope);
|
414
414
|
|
415
415
|
if (
|