eslint 7.16.0 → 7.20.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/CHANGELOG.md +71 -0
- package/README.md +29 -8
- package/lib/cli-engine/cli-engine.js +1 -1
- package/lib/eslint/eslint.js +2 -2
- package/lib/init/autoconfig.js +1 -1
- package/lib/init/config-initializer.js +2 -1
- package/lib/linter/linter.js +3 -1
- package/lib/linter/node-event-generator.js +4 -2
- package/lib/rules/arrow-body-style.js +1 -1
- package/lib/rules/callback-return.js +2 -2
- package/lib/rules/complexity.js +7 -1
- package/lib/rules/dot-location.js +1 -1
- package/lib/rules/func-call-spacing.js +2 -2
- package/lib/rules/indent.js +1 -0
- package/lib/rules/multiline-ternary.js +63 -6
- package/lib/rules/no-constant-condition.js +16 -3
- package/lib/rules/no-control-regex.js +0 -1
- package/lib/rules/no-extend-native.js +1 -1
- package/lib/rules/no-extra-parens.js +43 -23
- package/lib/rules/no-import-assign.js +4 -4
- package/lib/rules/no-invalid-regexp.js +36 -9
- package/lib/rules/no-restricted-exports.js +1 -1
- package/lib/rules/no-shadow.js +35 -3
- package/lib/rules/no-this-before-super.js +1 -1
- package/lib/rules/no-unused-expressions.js +12 -1
- package/lib/rules/no-useless-escape.js +4 -4
- package/lib/rules/no-useless-rename.js +22 -22
- package/lib/rules/one-var.js +30 -4
- package/lib/rules/prefer-const.js +17 -4
- package/lib/rules/prefer-destructuring.js +2 -2
- package/lib/rules/prefer-reflect.js +2 -2
- package/lib/rules/space-infix-ops.js +3 -1
- package/lib/rules/space-unary-ops.js +1 -1
- package/lib/rules/utils/ast-utils.js +2 -2
- package/lib/shared/deprecation-warnings.js +1 -1
- package/lib/shared/types.js +2 -2
- package/package.json +5 -5
package/CHANGELOG.md
CHANGED
@@ -1,3 +1,74 @@
|
|
1
|
+
v7.20.0 - February 12, 2021
|
2
|
+
|
3
|
+
* [`f4ac3b0`](https://github.com/eslint/eslint/commit/f4ac3b0e7072fbd3c14e9c64ff0c2c255a4eb730) Docs: fix sibling selector descriptions (#14099) (Milos Djermanovic)
|
4
|
+
* [`9d6063a`](https://github.com/eslint/eslint/commit/9d6063add931f0803cae1676d5df307baf114360) Fix: Crash with esquery when using JSX (fixes #13639) (#14072) (Yosuke Ota)
|
5
|
+
* [`a0871f1`](https://github.com/eslint/eslint/commit/a0871f1840060bd23cfe0952a096b107142db2f0) Docs: Triage process (#14014) (Nicholas C. Zakas)
|
6
|
+
* [`ad90761`](https://github.com/eslint/eslint/commit/ad9076183bc2c2029525edfc4596e403999348d1) Update: add enforceForJSX option to no-unused-expressions rule (#14012) (Duncan Beevers)
|
7
|
+
* [`d6c84af`](https://github.com/eslint/eslint/commit/d6c84af67318537177ffac0120a81af08e3e9df4) Fix: `--init` autoconfig shouldn't add deprecated rules (fixes #14017) (#14060) (Milos Djermanovic)
|
8
|
+
* [`9b277a1`](https://github.com/eslint/eslint/commit/9b277a16a7261e51b7ba36d6de7f996e9203a6a4) Fix: Support ENOTDIR error code in the folder existence checking utility (#13973) (Constantine Genchevsky)
|
9
|
+
* [`7aeb127`](https://github.com/eslint/eslint/commit/7aeb12798f2b9da706f3593f26a02e717929c9af) Upgrade: pin @babel/code-frame@7.12.11 (#14067) (Milos Djermanovic)
|
10
|
+
* [`b4e2af5`](https://github.com/eslint/eslint/commit/b4e2af5db1c29343ffec2cd104b04bf39b77ee56) Docs: Add more fields to bug report template (#14039) (Nicholas C. Zakas)
|
11
|
+
* [`96f1d49`](https://github.com/eslint/eslint/commit/96f1d49a4647e59f2fb918be096654e290513adc) Sponsors: Sync README with website (ESLint Jenkins)
|
12
|
+
* [`cb27b0a`](https://github.com/eslint/eslint/commit/cb27b0abeda6dfee55dd43b9cbe12afad321f55d) Build: package.json update for eslint-config-eslint release (ESLint Jenkins)
|
13
|
+
* [`4cab165`](https://github.com/eslint/eslint/commit/4cab165bf4e6e5e9f42a59a37a8ff2548c0af87d) Sponsors: Sync README with website (ESLint Jenkins)
|
14
|
+
|
15
|
+
v7.19.0 - January 30, 2021
|
16
|
+
|
17
|
+
* [`ce7f061`](https://github.com/eslint/eslint/commit/ce7f06121d9eb9cc2b3da24b4456b4d382e1413b) Update: add shadowed variable loc to message in no-shadow (fixes #13646) (#13841) (t-mangoe)
|
18
|
+
* [`c60e23f`](https://github.com/eslint/eslint/commit/c60e23ff306a14ca6eabcadb275ed27995fcc6e4) Update: fix `let` logic in for-in and for-of loops in no-extra-parens (#14011) (Milos Djermanovic)
|
19
|
+
* [`d76e8f6`](https://github.com/eslint/eslint/commit/d76e8f69bd791357c67ada7b5c55608acf29b622) Fix: no-useless-rename invalid autofix with parenthesized identifiers (#14032) (Milos Djermanovic)
|
20
|
+
* [`5800d92`](https://github.com/eslint/eslint/commit/5800d921144ec330b6ee7cd03364434007331354) Docs: Clarify stylistic rule update policy (#14052) (Brandon Mills)
|
21
|
+
* [`0ccf6d2`](https://github.com/eslint/eslint/commit/0ccf6d200147437b338cadb34546451972befd75) Docs: remove configuring.md (#14036) (Milos Djermanovic)
|
22
|
+
* [`65bb0ab`](https://github.com/eslint/eslint/commit/65bb0abde56f72586036fff151aa2d13f1b7be6c) Chore: Clean up new issue workflow (#14040) (Nicholas C. Zakas)
|
23
|
+
* [`e1da90f`](https://github.com/eslint/eslint/commit/e1da90fc414a3c9c16f52db4a5bd81bd4f9532a4) Fix: nested indenting for offsetTernaryExpressions: true (fixes #13971) (#13972) (Chris Brody)
|
24
|
+
* [`1a078b9`](https://github.com/eslint/eslint/commit/1a078b9166f29cb3760435ddbc1a0da4a0974d4a) Update: check ternary `:` even if `?` was reported in space-infix-ops (#13963) (Milos Djermanovic)
|
25
|
+
* [`fb27422`](https://github.com/eslint/eslint/commit/fb274226242eaebc1480fc9c901202986afc3c8a) Fix: extend prefer-const fixer range to whole declaration (fixes #13899) (#14033) (Nitin Kumar)
|
26
|
+
* [`e0b05c7`](https://github.com/eslint/eslint/commit/e0b05c704f3ce6f549d14718236d22fe49fcb611) Docs: add a correct example to no-unsafe-optional-chaining (refs #14029) (#14050) (armin yahya)
|
27
|
+
* [`46e836d`](https://github.com/eslint/eslint/commit/46e836d46442d2ec756038a2e12ba19b74394dbd) Sponsors: Sync README with website (ESLint Jenkins)
|
28
|
+
* [`3fc4fa4`](https://github.com/eslint/eslint/commit/3fc4fa485ca9ccd5e16dbc7e53ba31452d22dc4a) Docs: update configuring links (#14038) (Milos Djermanovic)
|
29
|
+
* [`8561c21`](https://github.com/eslint/eslint/commit/8561c2116ef89e53ebffb750066f1b00a4acdb76) Docs: fix broken links in configuring/README.md (#14046) (Milos Djermanovic)
|
30
|
+
* [`1c309eb`](https://github.com/eslint/eslint/commit/1c309ebca4a81a0faf397103dbc621019dea8c9c) Update: fix no-invalid-regexp false negatives with no flags specified (#14018) (Milos Djermanovic)
|
31
|
+
* [`f6602d5`](https://github.com/eslint/eslint/commit/f6602d569427e9e2a4f3b5ca3fc3a8bffb28d15e) Docs: Reorganize Configuration Documentation (#13837) (klkhan)
|
32
|
+
* [`c753b44`](https://github.com/eslint/eslint/commit/c753b442ef67867a178ffc2ad29b4e0534f72469) Sponsors: Sync README with website (ESLint Jenkins)
|
33
|
+
* [`a4fdb70`](https://github.com/eslint/eslint/commit/a4fdb7001aa41b9ad8bb92cc8a47b9135c94afc7) Docs: Fixed Typo (#14007) (Yash Singh)
|
34
|
+
* [`f7ca481`](https://github.com/eslint/eslint/commit/f7ca48165d025e01c38698352cff24d1de87cc8b) Docs: Explain why we disable lock files (refs eslint/tsc-meetings#234) (#14006) (Brandon Mills)
|
35
|
+
|
36
|
+
v7.18.0 - January 15, 2021
|
37
|
+
|
38
|
+
* [`e3264b2`](https://github.com/eslint/eslint/commit/e3264b26a625d926a1ea96df1c4b643af5c3797c) Upgrade: @eslint/eslintrc to improve error message for invalid extends (#14009) (Milos Djermanovic)
|
39
|
+
* [`f17c3c3`](https://github.com/eslint/eslint/commit/f17c3c371789ffa84f0cda57101e8193899adbe6) Update: check logical assignment operators in the complexity rule (#13979) (Milos Djermanovic)
|
40
|
+
* [`672deb0`](https://github.com/eslint/eslint/commit/672deb057a14a7acad8c669189870009f1edb8a6) Docs: fix no-invalid-regexp docs regarding ecmaVersion (#13991) (Milos Djermanovic)
|
41
|
+
* [`179a910`](https://github.com/eslint/eslint/commit/179a910b32e853bc12a9dd71f7c10e762cbeac44) Fix: --init crash on question to upgrade/downgrade ESLint (fixes #13978) (#13995) (Milos Djermanovic)
|
42
|
+
* [`292b1c0`](https://github.com/eslint/eslint/commit/292b1c0017bc442d399f67e01d699c59e6b71453) Fix: no-extra-parens false positive with `let` identifier in for-loop (#13981) (Milos Djermanovic)
|
43
|
+
* [`de61f94`](https://github.com/eslint/eslint/commit/de61f9444cf58a4d70e126ab3d10bf20851de7c9) Sponsors: Sync README with website (ESLint Jenkins)
|
44
|
+
* [`9250d16`](https://github.com/eslint/eslint/commit/9250d167ceb5684669eabe93dae326e33f0684f2) Upgrade: Bump lodash to fix security issue (#13993) (Frederik Prijck)
|
45
|
+
* [`75fea9b`](https://github.com/eslint/eslint/commit/75fea9bcdd3dde5a07e0089d9011a4df518cdbe3) Sponsors: Sync README with website (ESLint Jenkins)
|
46
|
+
* [`f2687e7`](https://github.com/eslint/eslint/commit/f2687e71f9e2a2773f821c4dc1a02abe95b97df4) Docs: update space-in-parens related rules (#13985) (Chris Brody)
|
47
|
+
* [`4a38bbe`](https://github.com/eslint/eslint/commit/4a38bbe81b4b29ca1a4e62d0a0cc8d525455b063) Docs: space-in-parens examples with no arguments etc. (#13987) (Chris Brody)
|
48
|
+
* [`3e49169`](https://github.com/eslint/eslint/commit/3e491698687aa08b3b798cee0931f0872ca1bc55) Sponsors: Sync README with website (ESLint Jenkins)
|
49
|
+
* [`c5bf1f2`](https://github.com/eslint/eslint/commit/c5bf1f2150a9fbbb9e74c04808dc3bfeda1ed321) Sponsors: Sync README with website (ESLint Jenkins)
|
50
|
+
* [`98a729c`](https://github.com/eslint/eslint/commit/98a729c9def54cee9e5478e75e8bd6f28167d5e8) Sponsors: Sync README with website (ESLint Jenkins)
|
51
|
+
* [`e83a696`](https://github.com/eslint/eslint/commit/e83a6962b51b05c2ddfe42b0748b405d515eeb9d) Sponsors: Sync README with website (ESLint Jenkins)
|
52
|
+
* [`78cb483`](https://github.com/eslint/eslint/commit/78cb48345c725e9f90fd0e631c476802244df4a4) Chore: test `foo( )` with space-in-parens option "always" (#13986) (Chris Brody)
|
53
|
+
* [`f6948f6`](https://github.com/eslint/eslint/commit/f6948f6bdc763dca0787bb2786bc9f6f9ed88f43) Docs: Update semantic versioning policy (#13970) (Nicholas C. Zakas)
|
54
|
+
* [`0688212`](https://github.com/eslint/eslint/commit/068821248e2d2eff11152f270102d537d8fa8126) Sponsors: Sync README with website (ESLint Jenkins)
|
55
|
+
* [`aeba5e5`](https://github.com/eslint/eslint/commit/aeba5e5e6062095a06d9b867d7e7ee75422f25b9) Chore: fix typo (#13975) (Nitin Kumar)
|
56
|
+
* [`4ee1134`](https://github.com/eslint/eslint/commit/4ee113414bdcbea240a5d9db27da6a10df472005) Sponsors: Sync README with website (ESLint Jenkins)
|
57
|
+
|
58
|
+
v7.17.0 - January 1, 2021
|
59
|
+
|
60
|
+
* [`e128e77`](https://github.com/eslint/eslint/commit/e128e775e9fa116a0ad68a071f1f0997589f8cd4) Update: check logical assignment in no-constant-condition (#13946) (Milos Djermanovic)
|
61
|
+
* [`cc48713`](https://github.com/eslint/eslint/commit/cc4871369645c3409dc56ded7a555af8a9f63d51) Chore: refactor calculating range and loc in no-useless-escape (#13964) (Milos Djermanovic)
|
62
|
+
* [`535fe47`](https://github.com/eslint/eslint/commit/535fe47fee6544b4957378f9408117c8318d4762) Update: use regexpp's default ecmaVersion in no-control-regex (#13969) (Milos Djermanovic)
|
63
|
+
* [`83e98cd`](https://github.com/eslint/eslint/commit/83e98cd48ce3d1acf729f4fb9be40cff332abd6e) Fix: use regexpp's default ecmaVersion in no-invalid-regexp (#13968) (Milos Djermanovic)
|
64
|
+
* [`7297363`](https://github.com/eslint/eslint/commit/7297363ea355d0e3b2a74aaec586126deb91fd93) Docs: fix examples for no-multi-str (#13966) (Milos Djermanovic)
|
65
|
+
* [`0649871`](https://github.com/eslint/eslint/commit/06498716bfba65ed8c7217917a29a07ad267193a) Update: add autofix to rule multiline-ternary (#13958) (薛定谔的猫)
|
66
|
+
* [`f6e7e32`](https://github.com/eslint/eslint/commit/f6e7e3231bc43c989f8c953de8e0d328bac5eea0) Fix: no-useless-escape wrong loc and fix with CRLF in template elements (#13953) (Milos Djermanovic)
|
67
|
+
* [`19c69c0`](https://github.com/eslint/eslint/commit/19c69c0293a98634ff0d4884a0cdabc1213ebcb4) Fix: one-var shouldn't split declaration if it isn't in a statement list (#13959) (Milos Djermanovic)
|
68
|
+
* [`e451b96`](https://github.com/eslint/eslint/commit/e451b9664aface32ad9321eaf5619c875dc76553) Docs: update build tool for webpack (#13962) (Sam Chen)
|
69
|
+
* [`c3e9acc`](https://github.com/eslint/eslint/commit/c3e9accce2f61b04ab699fd37c90703305281aa3) Chore: fix typos (#13960) (YeonJuan)
|
70
|
+
* [`7289ecf`](https://github.com/eslint/eslint/commit/7289ecf58ed0d2e7f0ad7f1e5004c8927a7bf805) Sponsors: Sync README with website (ESLint Jenkins)
|
71
|
+
|
1
72
|
v7.16.0 - December 18, 2020
|
2
73
|
|
3
74
|
* [`a62ad6f`](https://github.com/eslint/eslint/commit/a62ad6f03151358b93b5fede022a30d67310705c) Update: fix false negative of no-extra-parens with NewExpression (#13930) (Milos Djermanovic)
|
package/README.md
CHANGED
@@ -35,10 +35,11 @@ ESLint is a tool for identifying and reporting on patterns found in ECMAScript/J
|
|
35
35
|
6. [Releases](#releases)
|
36
36
|
7. [Security Policy](#security-policy)
|
37
37
|
8. [Semantic Versioning Policy](#semantic-versioning-policy)
|
38
|
-
9. [
|
39
|
-
10. [
|
40
|
-
11. [
|
41
|
-
12. [
|
38
|
+
9. [Stylistic Rule Updates](#stylistic-rule-updates)
|
39
|
+
10. [License](#license)
|
40
|
+
11. [Team](#team)
|
41
|
+
12. [Sponsors](#sponsors)
|
42
|
+
13. [Technology Sponsors](#technology-sponsors)
|
42
43
|
|
43
44
|
## <a name="installation-and-usage"></a>Installation and Usage
|
44
45
|
|
@@ -136,6 +137,16 @@ Once a language feature has been adopted into the ECMAScript standard (stage 4 a
|
|
136
137
|
|
137
138
|
Join our [Mailing List](https://groups.google.com/group/eslint) or [Chatroom](https://eslint.org/chat).
|
138
139
|
|
140
|
+
### Why doesn't ESLint lock dependency versions?
|
141
|
+
|
142
|
+
Lock files like `package-lock.json` are helpful for deployed applications. They ensure that dependencies are consistent between environments and across deployments.
|
143
|
+
|
144
|
+
Packages like `eslint` that get published to the npm registry do not include lock files. `npm install eslint` as a user will respect version constraints in ESLint's `package.json`. ESLint and its dependencies will be included in the user's lock file if one exists, but ESLint's own lock file would not be used.
|
145
|
+
|
146
|
+
We intentionally don't lock dependency versions so that we have the latest compatible dependency versions in development and CI that our users get when installing ESLint in a project.
|
147
|
+
|
148
|
+
The Twilio blog has a [deeper dive](https://www.twilio.com/blog/lockfiles-nodejs) to learn more.
|
149
|
+
|
139
150
|
## <a name="releases"></a>Releases
|
140
151
|
|
141
152
|
We have scheduled releases every two weeks on Friday or Saturday. You can follow a [release issue](https://github.com/eslint/eslint/issues?q=is%3Aopen+is%3Aissue+label%3Arelease) for updates about the scheduling of any particular release.
|
@@ -158,6 +169,7 @@ ESLint follows [semantic versioning](https://semver.org). However, due to the na
|
|
158
169
|
* A bug fix in a rule that results in ESLint reporting more linting errors.
|
159
170
|
* A new rule is created.
|
160
171
|
* A new option to an existing rule that does not result in ESLint reporting more linting errors by default.
|
172
|
+
* A new addition to an existing rule to support a newly-added language feature (within the last 12 months) that will result in ESLint reporting more linting errors by default.
|
161
173
|
* An existing rule is deprecated.
|
162
174
|
* A new CLI capability is created.
|
163
175
|
* New capabilities to the public API are added (new classes, new methods, new arguments to existing methods, etc.).
|
@@ -176,6 +188,15 @@ ESLint follows [semantic versioning](https://semver.org). However, due to the na
|
|
176
188
|
|
177
189
|
According to our policy, any minor update may report more linting errors than the previous release (ex: from a bug fix). As such, we recommend using the tilde (`~`) in `package.json` e.g. `"eslint": "~3.1.0"` to guarantee the results of your builds.
|
178
190
|
|
191
|
+
## <a name="stylistic-rule-updates"></a>Stylistic Rule Updates
|
192
|
+
|
193
|
+
Stylistic rules are frozen according to [our policy](https://eslint.org/blog/2020/05/changes-to-rules-policies) on how we evaluate new rules and rule changes.
|
194
|
+
This means:
|
195
|
+
|
196
|
+
* **Bug fixes**: We will still fix bugs in stylistic rules.
|
197
|
+
* **New ECMAScript features**: We will also make sure stylistic rules are compatible with new ECMAScript features.
|
198
|
+
* **New options**: We will **not** add any new options to stylistic rules unless an option is the only way to fix a bug or support a newly-added ECMAScript feature.
|
199
|
+
|
179
200
|
## <a name="license"></a>License
|
180
201
|
|
181
202
|
[](https://app.fossa.io/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Feslint%2Feslint?ref=badge_large)
|
@@ -259,10 +280,10 @@ The following companies, organizations, and individuals support ESLint's ongoing
|
|
259
280
|
<!-- NOTE: This section is autogenerated. Do not manually edit.-->
|
260
281
|
<!--sponsorsstart-->
|
261
282
|
<h3>Platinum Sponsors</h3>
|
262
|
-
<p><a href="https://automattic.com"><img src="https://images.opencollective.com/photomatt/
|
263
|
-
<p><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.shopify.com"><img src="https://images.opencollective.com/shopify/e780cd4/logo.png" alt="Shopify" 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://aka.ms/microsoftfossfund"><img src="https://
|
264
|
-
<p><a href="https://liftoff.io/"><img src="https://images.opencollective.com/liftoff/5c4fa84/logo.png" alt="Liftoff" height="64"></a> <a href="https://www.ampproject.org/"><img src="https://images.opencollective.com/amp/c8a3b25/logo.png" alt="AMP Project" height="64"></a></p><h3>Bronze Sponsors</h3>
|
265
|
-
<p><a href="https://writersperhour.com"><img src="https://images.opencollective.com/writersperhour/5787d4b/logo.png" alt="Writers Per Hour" height="32"></a> <a href="https://www.betacalendars.com/
|
283
|
+
<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>
|
284
|
+
<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.shopify.com"><img src="https://images.opencollective.com/shopify/e780cd4/logo.png" alt="Shopify" 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://aka.ms/microsoftfossfund"><img src="https://avatars.githubusercontent.com/u/67931232?u=7fddc652a464d7151b97e8f108392af7d54fa3e8&v=4" alt="Microsoft FOSS Fund Sponsorships" height="96"></a></p><h3>Silver Sponsors</h3>
|
285
|
+
<p><a href="https://retool.com/"><img src="https://images.opencollective.com/retool/98ea68e/logo.png" alt="Retool" 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://www.ampproject.org/"><img src="https://images.opencollective.com/amp/c8a3b25/logo.png" alt="AMP Project" height="64"></a></p><h3>Bronze Sponsors</h3>
|
286
|
+
<p><a href="https://writersperhour.com"><img src="https://images.opencollective.com/writersperhour/5787d4b/logo.png" alt="Writers Per Hour" height="32"></a> <a href="https://www.betacalendars.com/march-calendar.html"><img src="https://images.opencollective.com/betacalendars/9334b33/logo.png" alt="March 2021 calendar" height="32"></a> <a href="https://buy.fineproxy.org/eng/"><img src="https://images.opencollective.com/buy-fineproxy-org/b282e39/logo.png" alt="Buy.Fineproxy.Org" 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="null"><img src="https://images.opencollective.com/bugsnag-stability-monitoring/c2cef36/logo.png" alt="Bugsnag Stability Monitoring" height="32"></a> <a href="https://mixpanel.com"><img src="https://images.opencollective.com/mixpanel/cd682f7/logo.png" alt="Mixpanel" 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://discordapp.com"><img src="https://images.opencollective.com/discordapp/7e3d9a9/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></p>
|
266
287
|
<!--sponsorsend-->
|
267
288
|
|
268
289
|
## <a name="technology-sponsors"></a>Technology Sponsors
|
@@ -531,7 +531,7 @@ function directoryExists(resolvedPath) {
|
|
531
531
|
try {
|
532
532
|
return fs.statSync(resolvedPath).isDirectory();
|
533
533
|
} catch (error) {
|
534
|
-
if (error && error.code === "ENOENT") {
|
534
|
+
if (error && (error.code === "ENOENT" || error.code === "ENOTDIR")) {
|
535
535
|
return false;
|
536
536
|
}
|
537
537
|
throw error;
|
package/lib/eslint/eslint.js
CHANGED
@@ -272,7 +272,7 @@ function processOptions({
|
|
272
272
|
errors.push("'rulePaths' must be an array of non-empty strings.");
|
273
273
|
}
|
274
274
|
if (typeof useEslintrc !== "boolean") {
|
275
|
-
errors.push("'
|
275
|
+
errors.push("'useEslintrc' must be a boolean.");
|
276
276
|
}
|
277
277
|
|
278
278
|
if (errors.length > 0) {
|
@@ -563,7 +563,7 @@ class ESLint {
|
|
563
563
|
|
564
564
|
/**
|
565
565
|
* Returns the formatter representing the given formatter name.
|
566
|
-
* @param {string} [name] The name of the
|
566
|
+
* @param {string} [name] The name of the formatter to load.
|
567
567
|
* The following values are allowed:
|
568
568
|
* - `undefined` ... Load `stylish` builtin formatter.
|
569
569
|
* - A builtin formatter name ... Load the builtin formatter.
|
package/lib/init/autoconfig.js
CHANGED
@@ -85,7 +85,7 @@ class Registry {
|
|
85
85
|
* @returns {void}
|
86
86
|
*/
|
87
87
|
populateFromCoreRules() {
|
88
|
-
const rulesConfig = configRule.createCoreRuleConfigs();
|
88
|
+
const rulesConfig = configRule.createCoreRuleConfigs(/* noDeprecated = */ true);
|
89
89
|
|
90
90
|
this.rules = makeRegistryItems(rulesConfig);
|
91
91
|
}
|
@@ -565,7 +565,8 @@ function promptUser() {
|
|
565
565
|
{
|
566
566
|
type: "toggle",
|
567
567
|
name: "installESLint",
|
568
|
-
message(
|
568
|
+
message() {
|
569
|
+
const { answers } = this.state;
|
569
570
|
const verb = semver.ltr(answers.localESLintVersion, answers.requiredESLintVersionRange)
|
570
571
|
? "upgrade"
|
571
572
|
: "downgrade";
|
package/lib/linter/linter.js
CHANGED
@@ -942,7 +942,9 @@ function runRules(sourceCode, configuredRules, ruleMapper, parserOptions, parser
|
|
942
942
|
});
|
943
943
|
|
944
944
|
// only run code path analyzer if the top level node is "Program", skip otherwise
|
945
|
-
const eventGenerator = nodeQueue[0].node.type === "Program"
|
945
|
+
const eventGenerator = nodeQueue[0].node.type === "Program"
|
946
|
+
? new CodePathAnalyzer(new NodeEventGenerator(emitter, { visitorKeys: sourceCode.visitorKeys, fallback: Traverser.getKeys }))
|
947
|
+
: new NodeEventGenerator(emitter, { visitorKeys: sourceCode.visitorKeys, fallback: Traverser.getKeys });
|
946
948
|
|
947
949
|
nodeQueue.forEach(traversalInfo => {
|
948
950
|
currentNode = traversalInfo.node;
|
@@ -208,10 +208,12 @@ class NodeEventGenerator {
|
|
208
208
|
* An SafeEmitter which is the destination of events. This emitter must already
|
209
209
|
* have registered listeners for all of the events that it needs to listen for.
|
210
210
|
* (See lib/linter/safe-emitter.js for more details on `SafeEmitter`.)
|
211
|
+
* @param {ESQueryOptions} esqueryOptions `esquery` options for traversing custom nodes.
|
211
212
|
* @returns {NodeEventGenerator} new instance
|
212
213
|
*/
|
213
|
-
constructor(emitter) {
|
214
|
+
constructor(emitter, esqueryOptions) {
|
214
215
|
this.emitter = emitter;
|
216
|
+
this.esqueryOptions = esqueryOptions;
|
215
217
|
this.currentAncestry = [];
|
216
218
|
this.enterSelectorsByNodeType = new Map();
|
217
219
|
this.exitSelectorsByNodeType = new Map();
|
@@ -250,7 +252,7 @@ class NodeEventGenerator {
|
|
250
252
|
* @returns {void}
|
251
253
|
*/
|
252
254
|
applySelector(node, selector) {
|
253
|
-
if (esquery.matches(node, selector.parsedSelector, this.currentAncestry)) {
|
255
|
+
if (esquery.matches(node, selector.parsedSelector, this.currentAncestry, this.esqueryOptions)) {
|
254
256
|
this.emitter.emit(selector.rawSelector, node);
|
255
257
|
}
|
256
258
|
}
|
@@ -191,7 +191,7 @@ module.exports = {
|
|
191
191
|
}
|
192
192
|
|
193
193
|
/*
|
194
|
-
* If the first token of the
|
194
|
+
* If the first token of the return value is `{` or the return value is a sequence expression,
|
195
195
|
* enclose the return value by parentheses to avoid syntax error.
|
196
196
|
*/
|
197
197
|
if (astUtils.isOpeningBraceToken(firstValueToken) || blockBody[0].argument.type === "SequenceExpression" || (funcInfo.hasInOperator && isInsideForLoopInitializer(node))) {
|
@@ -59,9 +59,9 @@ module.exports = {
|
|
59
59
|
}
|
60
60
|
|
61
61
|
/**
|
62
|
-
* Check to see if a node contains only
|
62
|
+
* Check to see if a node contains only identifiers
|
63
63
|
* @param {ASTNode} node The node to check
|
64
|
-
* @returns {boolean} Whether or not the node contains only
|
64
|
+
* @returns {boolean} Whether or not the node contains only identifiers
|
65
65
|
*/
|
66
66
|
function containsOnlyIdentifiers(node) {
|
67
67
|
if (node.type === "Identifier") {
|
package/lib/rules/complexity.js
CHANGED
@@ -153,7 +153,13 @@ module.exports = {
|
|
153
153
|
IfStatement: increaseComplexity,
|
154
154
|
SwitchCase: increaseSwitchComplexity,
|
155
155
|
WhileStatement: increaseComplexity,
|
156
|
-
DoWhileStatement: increaseComplexity
|
156
|
+
DoWhileStatement: increaseComplexity,
|
157
|
+
|
158
|
+
AssignmentExpression(node) {
|
159
|
+
if (astUtils.isLogicalAssignmentOperator(node.operator)) {
|
160
|
+
increaseComplexity();
|
161
|
+
}
|
162
|
+
}
|
157
163
|
};
|
158
164
|
|
159
165
|
}
|
@@ -46,7 +46,7 @@ module.exports = {
|
|
46
46
|
const sourceCode = context.getSourceCode();
|
47
47
|
|
48
48
|
/**
|
49
|
-
* Reports if the dot between object and property is on the correct
|
49
|
+
* Reports if the dot between object and property is on the correct location.
|
50
50
|
* @param {ASTNode} node The `MemberExpression` node.
|
51
51
|
* @returns {void}
|
52
52
|
*/
|
@@ -131,7 +131,7 @@ module.exports = {
|
|
131
131
|
return null;
|
132
132
|
}
|
133
133
|
|
134
|
-
// If `?.`
|
134
|
+
// If `?.` exists, it doesn't hide no-unexpected-multiline errors
|
135
135
|
if (node.optional) {
|
136
136
|
return fixer.replaceTextRange([leftToken.range[1], rightToken.range[0]], "?.");
|
137
137
|
}
|
@@ -177,7 +177,7 @@ module.exports = {
|
|
177
177
|
/*
|
178
178
|
* Only autofix if there is no newline
|
179
179
|
* https://github.com/eslint/eslint/issues/7787
|
180
|
-
* But if `?.`
|
180
|
+
* But if `?.` exists, it doesn't hide no-unexpected-multiline errors
|
181
181
|
*/
|
182
182
|
if (!node.optional) {
|
183
183
|
return null;
|
package/lib/rules/indent.js
CHANGED
@@ -1178,6 +1178,7 @@ module.exports = {
|
|
1178
1178
|
offsets.setDesiredOffset(colonToken, firstToken, 1);
|
1179
1179
|
|
1180
1180
|
offsets.setDesiredOffset(firstConsequentToken, firstToken,
|
1181
|
+
firstConsequentToken.type === "Punctuator" &&
|
1181
1182
|
options.offsetTernaryExpressions ? 2 : 1);
|
1182
1183
|
|
1183
1184
|
/*
|
@@ -27,19 +27,22 @@ module.exports = {
|
|
27
27
|
enum: ["always", "always-multiline", "never"]
|
28
28
|
}
|
29
29
|
],
|
30
|
+
|
30
31
|
messages: {
|
31
32
|
expectedTestCons: "Expected newline between test and consequent of ternary expression.",
|
32
33
|
expectedConsAlt: "Expected newline between consequent and alternate of ternary expression.",
|
33
34
|
unexpectedTestCons: "Unexpected newline between test and consequent of ternary expression.",
|
34
35
|
unexpectedConsAlt: "Unexpected newline between consequent and alternate of ternary expression."
|
35
|
-
}
|
36
|
+
},
|
37
|
+
|
38
|
+
fixable: "whitespace"
|
36
39
|
},
|
37
40
|
|
38
41
|
create(context) {
|
42
|
+
const sourceCode = context.getSourceCode();
|
39
43
|
const option = context.options[0];
|
40
44
|
const multiline = option !== "never";
|
41
45
|
const allowSingleLine = option === "always-multiline";
|
42
|
-
const sourceCode = context.getSourceCode();
|
43
46
|
|
44
47
|
//--------------------------------------------------------------------------
|
45
48
|
// Public
|
@@ -59,6 +62,8 @@ module.exports = {
|
|
59
62
|
const areTestAndConsequentOnSameLine = astUtils.isTokenOnSameLine(lastTokenOfTest, firstTokenOfConsequent);
|
60
63
|
const areConsequentAndAlternateOnSameLine = astUtils.isTokenOnSameLine(lastTokenOfConsequent, firstTokenOfAlternate);
|
61
64
|
|
65
|
+
const hasComments = !!sourceCode.getCommentsInside(node).length;
|
66
|
+
|
62
67
|
if (!multiline) {
|
63
68
|
if (!areTestAndConsequentOnSameLine) {
|
64
69
|
context.report({
|
@@ -67,7 +72,24 @@ module.exports = {
|
|
67
72
|
start: firstTokenOfTest.loc.start,
|
68
73
|
end: lastTokenOfTest.loc.end
|
69
74
|
},
|
70
|
-
messageId: "unexpectedTestCons"
|
75
|
+
messageId: "unexpectedTestCons",
|
76
|
+
fix: fixer => {
|
77
|
+
if (hasComments) {
|
78
|
+
return null;
|
79
|
+
}
|
80
|
+
const fixers = [];
|
81
|
+
const areTestAndQuestionOnSameLine = astUtils.isTokenOnSameLine(lastTokenOfTest, questionToken);
|
82
|
+
const areQuestionAndConsOnSameLine = astUtils.isTokenOnSameLine(questionToken, firstTokenOfConsequent);
|
83
|
+
|
84
|
+
if (!areTestAndQuestionOnSameLine) {
|
85
|
+
fixers.push(fixer.removeRange([lastTokenOfTest.range[1], questionToken.range[0]]));
|
86
|
+
}
|
87
|
+
if (!areQuestionAndConsOnSameLine) {
|
88
|
+
fixers.push(fixer.removeRange([questionToken.range[1], firstTokenOfConsequent.range[0]]));
|
89
|
+
}
|
90
|
+
|
91
|
+
return fixers;
|
92
|
+
}
|
71
93
|
});
|
72
94
|
}
|
73
95
|
|
@@ -78,7 +100,24 @@ module.exports = {
|
|
78
100
|
start: firstTokenOfConsequent.loc.start,
|
79
101
|
end: lastTokenOfConsequent.loc.end
|
80
102
|
},
|
81
|
-
messageId: "unexpectedConsAlt"
|
103
|
+
messageId: "unexpectedConsAlt",
|
104
|
+
fix: fixer => {
|
105
|
+
if (hasComments) {
|
106
|
+
return null;
|
107
|
+
}
|
108
|
+
const fixers = [];
|
109
|
+
const areConsAndColonOnSameLine = astUtils.isTokenOnSameLine(lastTokenOfConsequent, colonToken);
|
110
|
+
const areColonAndAltOnSameLine = astUtils.isTokenOnSameLine(colonToken, firstTokenOfAlternate);
|
111
|
+
|
112
|
+
if (!areConsAndColonOnSameLine) {
|
113
|
+
fixers.push(fixer.removeRange([lastTokenOfConsequent.range[1], colonToken.range[0]]));
|
114
|
+
}
|
115
|
+
if (!areColonAndAltOnSameLine) {
|
116
|
+
fixers.push(fixer.removeRange([colonToken.range[1], firstTokenOfAlternate.range[0]]));
|
117
|
+
}
|
118
|
+
|
119
|
+
return fixers;
|
120
|
+
}
|
82
121
|
});
|
83
122
|
}
|
84
123
|
} else {
|
@@ -93,7 +132,16 @@ module.exports = {
|
|
93
132
|
start: firstTokenOfTest.loc.start,
|
94
133
|
end: lastTokenOfTest.loc.end
|
95
134
|
},
|
96
|
-
messageId: "expectedTestCons"
|
135
|
+
messageId: "expectedTestCons",
|
136
|
+
fix: fixer => (hasComments ? null : (
|
137
|
+
fixer.replaceTextRange(
|
138
|
+
[
|
139
|
+
lastTokenOfTest.range[1],
|
140
|
+
questionToken.range[0]
|
141
|
+
],
|
142
|
+
"\n"
|
143
|
+
)
|
144
|
+
))
|
97
145
|
});
|
98
146
|
}
|
99
147
|
|
@@ -104,7 +152,16 @@ module.exports = {
|
|
104
152
|
start: firstTokenOfConsequent.loc.start,
|
105
153
|
end: lastTokenOfConsequent.loc.end
|
106
154
|
},
|
107
|
-
messageId: "expectedConsAlt"
|
155
|
+
messageId: "expectedConsAlt",
|
156
|
+
fix: (fixer => (hasComments ? null : (
|
157
|
+
fixer.replaceTextRange(
|
158
|
+
[
|
159
|
+
lastTokenOfConsequent.range[1],
|
160
|
+
colonToken.range[0]
|
161
|
+
],
|
162
|
+
"\n"
|
163
|
+
)
|
164
|
+
)))
|
108
165
|
});
|
109
166
|
}
|
110
167
|
}
|
@@ -106,10 +106,15 @@ module.exports = {
|
|
106
106
|
*/
|
107
107
|
return operator === node.operator &&
|
108
108
|
(
|
109
|
-
isLogicalIdentity(node.left,
|
110
|
-
isLogicalIdentity(node.right,
|
109
|
+
isLogicalIdentity(node.left, operator) ||
|
110
|
+
isLogicalIdentity(node.right, operator)
|
111
111
|
);
|
112
112
|
|
113
|
+
case "AssignmentExpression":
|
114
|
+
return ["||=", "&&="].includes(node.operator) &&
|
115
|
+
operator === node.operator.slice(0, -1) &&
|
116
|
+
isLogicalIdentity(node.right, operator);
|
117
|
+
|
113
118
|
// no default
|
114
119
|
}
|
115
120
|
return false;
|
@@ -177,7 +182,15 @@ module.exports = {
|
|
177
182
|
}
|
178
183
|
|
179
184
|
case "AssignmentExpression":
|
180
|
-
|
185
|
+
if (node.operator === "=") {
|
186
|
+
return isConstant(node.right, inBooleanPosition);
|
187
|
+
}
|
188
|
+
|
189
|
+
if (["||=", "&&="].includes(node.operator) && inBooleanPosition) {
|
190
|
+
return isLogicalIdentity(node.right, node.operator.slice(0, -1));
|
191
|
+
}
|
192
|
+
|
193
|
+
return false;
|
181
194
|
|
182
195
|
case "SequenceExpression":
|
183
196
|
return isConstant(node.expressions[node.expressions.length - 1], inBooleanPosition);
|
@@ -138,7 +138,7 @@ module.exports = {
|
|
138
138
|
}
|
139
139
|
|
140
140
|
/*
|
141
|
-
* `identifierNode.parent` is a
|
141
|
+
* `identifierNode.parent` is a MemberExpression `*.prototype`.
|
142
142
|
* If it's an optional member access, it may be wrapped by a `ChainExpression` node.
|
143
143
|
*/
|
144
144
|
const prototypeNode =
|
@@ -844,45 +844,49 @@ module.exports = {
|
|
844
844
|
ExportDefaultDeclaration: node => checkExpressionOrExportStatement(node.declaration),
|
845
845
|
ExpressionStatement: node => checkExpressionOrExportStatement(node.expression),
|
846
846
|
|
847
|
-
|
848
|
-
if (node.left.type !== "
|
847
|
+
ForInStatement(node) {
|
848
|
+
if (node.left.type !== "VariableDeclaration") {
|
849
849
|
const firstLeftToken = sourceCode.getFirstToken(node.left, astUtils.isNotOpeningParenToken);
|
850
850
|
|
851
851
|
if (
|
852
|
-
firstLeftToken.value === "let" &&
|
853
|
-
|
854
|
-
|
855
|
-
* If `let` is the only thing on the left side of the loop, it's the loop variable: `for ((let) of foo);`
|
856
|
-
* Removing it will cause a syntax error, because it will be parsed as the start of a VariableDeclarator.
|
857
|
-
*/
|
858
|
-
(firstLeftToken.range[1] === node.left.range[1] || /*
|
859
|
-
* If `let` is followed by a `[` token, it's a property access on the `let` value: `for ((let[foo]) of bar);`
|
860
|
-
* Removing it will cause the property access to be parsed as a destructuring declaration of `foo` instead.
|
861
|
-
*/
|
862
|
-
astUtils.isOpeningBracketToken(
|
863
|
-
sourceCode.getTokenAfter(firstLeftToken, astUtils.isNotClosingParenToken)
|
864
|
-
))
|
852
|
+
firstLeftToken.value === "let" &&
|
853
|
+
astUtils.isOpeningBracketToken(
|
854
|
+
sourceCode.getTokenAfter(firstLeftToken, astUtils.isNotClosingParenToken)
|
865
855
|
)
|
866
856
|
) {
|
857
|
+
|
858
|
+
// ForInStatement#left expression cannot start with `let[`.
|
867
859
|
tokensToIgnore.add(firstLeftToken);
|
868
860
|
}
|
869
861
|
}
|
870
862
|
|
871
|
-
if (node.
|
872
|
-
|
873
|
-
|
874
|
-
: hasExcessParens(node.right);
|
863
|
+
if (hasExcessParens(node.left)) {
|
864
|
+
report(node.left);
|
865
|
+
}
|
875
866
|
|
876
|
-
|
877
|
-
report(node.right);
|
878
|
-
}
|
879
|
-
} else if (hasExcessParens(node.right)) {
|
867
|
+
if (hasExcessParens(node.right)) {
|
880
868
|
report(node.right);
|
881
869
|
}
|
870
|
+
},
|
871
|
+
|
872
|
+
ForOfStatement(node) {
|
873
|
+
if (node.left.type !== "VariableDeclaration") {
|
874
|
+
const firstLeftToken = sourceCode.getFirstToken(node.left, astUtils.isNotOpeningParenToken);
|
875
|
+
|
876
|
+
if (firstLeftToken.value === "let") {
|
877
|
+
|
878
|
+
// ForOfStatement#left expression cannot start with `let`.
|
879
|
+
tokensToIgnore.add(firstLeftToken);
|
880
|
+
}
|
881
|
+
}
|
882
882
|
|
883
883
|
if (hasExcessParens(node.left)) {
|
884
884
|
report(node.left);
|
885
885
|
}
|
886
|
+
|
887
|
+
if (hasExcessParensWithPrecedence(node.right, PRECEDENCE_OF_ASSIGNMENT_EXPR)) {
|
888
|
+
report(node.right);
|
889
|
+
}
|
886
890
|
},
|
887
891
|
|
888
892
|
ForStatement(node) {
|
@@ -895,6 +899,22 @@ module.exports = {
|
|
895
899
|
}
|
896
900
|
|
897
901
|
if (node.init) {
|
902
|
+
|
903
|
+
if (node.init.type !== "VariableDeclaration") {
|
904
|
+
const firstToken = sourceCode.getFirstToken(node.init, astUtils.isNotOpeningParenToken);
|
905
|
+
|
906
|
+
if (
|
907
|
+
firstToken.value === "let" &&
|
908
|
+
astUtils.isOpeningBracketToken(
|
909
|
+
sourceCode.getTokenAfter(firstToken, astUtils.isNotClosingParenToken)
|
910
|
+
)
|
911
|
+
) {
|
912
|
+
|
913
|
+
// ForStatement#init expression cannot start with `let[`.
|
914
|
+
tokensToIgnore.add(firstToken);
|
915
|
+
}
|
916
|
+
}
|
917
|
+
|
898
918
|
startNewReportsBuffering();
|
899
919
|
|
900
920
|
if (hasExcessParens(node.init)) {
|
@@ -97,10 +97,10 @@ function isIterationVariable(node) {
|
|
97
97
|
* - `Object.defineProperties`
|
98
98
|
* - `Object.freeze`
|
99
99
|
* - `Object.setPrototypeOf`
|
100
|
-
* - `
|
101
|
-
* - `
|
102
|
-
* - `
|
103
|
-
* - `
|
100
|
+
* - `Reflect.defineProperty`
|
101
|
+
* - `Reflect.deleteProperty`
|
102
|
+
* - `Reflect.set`
|
103
|
+
* - `Reflect.setPrototypeOf`
|
104
104
|
* @param {ASTNode} node The node to check.
|
105
105
|
* @param {Scope} scope A `escope.Scope` object to find variable (whichever).
|
106
106
|
* @returns {boolean} `true` if the node is at the first argument of a well-known mutation function.
|
@@ -9,7 +9,7 @@
|
|
9
9
|
//------------------------------------------------------------------------------
|
10
10
|
|
11
11
|
const RegExpValidator = require("regexpp").RegExpValidator;
|
12
|
-
const validator = new RegExpValidator(
|
12
|
+
const validator = new RegExpValidator();
|
13
13
|
const validFlags = /[gimuys]/gu;
|
14
14
|
const undefined1 = void 0;
|
15
15
|
|
@@ -69,6 +69,28 @@ module.exports = {
|
|
69
69
|
return node && node.type === "Literal" && typeof node.value === "string";
|
70
70
|
}
|
71
71
|
|
72
|
+
/**
|
73
|
+
* Gets flags of a regular expression created by the given `RegExp()` or `new RegExp()` call
|
74
|
+
* Examples:
|
75
|
+
* new RegExp(".") // => ""
|
76
|
+
* new RegExp(".", "gu") // => "gu"
|
77
|
+
* new RegExp(".", flags) // => null
|
78
|
+
* @param {ASTNode} node `CallExpression` or `NewExpression` node
|
79
|
+
* @returns {string|null} flags if they can be determined, `null` otherwise
|
80
|
+
* @private
|
81
|
+
*/
|
82
|
+
function getFlags(node) {
|
83
|
+
if (node.arguments.length < 2) {
|
84
|
+
return "";
|
85
|
+
}
|
86
|
+
|
87
|
+
if (isString(node.arguments[1])) {
|
88
|
+
return node.arguments[1].value;
|
89
|
+
}
|
90
|
+
|
91
|
+
return null;
|
92
|
+
}
|
93
|
+
|
72
94
|
/**
|
73
95
|
* Check syntax error in a given pattern.
|
74
96
|
* @param {string} pattern The RegExp pattern to validate.
|
@@ -104,18 +126,23 @@ module.exports = {
|
|
104
126
|
return;
|
105
127
|
}
|
106
128
|
const pattern = node.arguments[0].value;
|
107
|
-
let flags =
|
129
|
+
let flags = getFlags(node);
|
108
130
|
|
109
|
-
if (allowedFlags) {
|
131
|
+
if (flags && allowedFlags) {
|
110
132
|
flags = flags.replace(allowedFlags, "");
|
111
133
|
}
|
112
134
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
135
|
+
const message =
|
136
|
+
(
|
137
|
+
flags && validateRegExpFlags(flags)
|
138
|
+
) ||
|
139
|
+
(
|
140
|
+
|
141
|
+
// If flags are unknown, report the regex only if its pattern is invalid both with and without the "u" flag
|
142
|
+
flags === null
|
143
|
+
? validateRegExpPattern(pattern, true) && validateRegExpPattern(pattern, false)
|
144
|
+
: validateRegExpPattern(pattern, flags.includes("u"))
|
145
|
+
);
|
119
146
|
|
120
147
|
if (message) {
|
121
148
|
context.report({
|
@@ -45,7 +45,7 @@ module.exports = {
|
|
45
45
|
|
46
46
|
/**
|
47
47
|
* Checks and reports given exported identifier.
|
48
|
-
* @param {ASTNode} node exported `
|
48
|
+
* @param {ASTNode} node exported `Identifier` node to check.
|
49
49
|
* @returns {void}
|
50
50
|
*/
|
51
51
|
function checkExportedName(node) {
|
package/lib/rules/no-shadow.js
CHANGED
@@ -44,7 +44,8 @@ module.exports = {
|
|
44
44
|
],
|
45
45
|
|
46
46
|
messages: {
|
47
|
-
noShadow: "'{{name}}' is already declared in the upper scope."
|
47
|
+
noShadow: "'{{name}}' is already declared in the upper scope on line {{shadowedLine}} column {{shadowedColumn}}.",
|
48
|
+
noShadowGlobal: "'{{name}}' is already a global variable."
|
48
49
|
}
|
49
50
|
},
|
50
51
|
|
@@ -117,6 +118,29 @@ module.exports = {
|
|
117
118
|
return def && def.name.range;
|
118
119
|
}
|
119
120
|
|
121
|
+
/**
|
122
|
+
* Get declared line and column of a variable.
|
123
|
+
* @param {eslint-scope.Variable} variable The variable to get.
|
124
|
+
* @returns {Object} The declared line and column of the variable.
|
125
|
+
*/
|
126
|
+
function getDeclaredLocation(variable) {
|
127
|
+
const identifier = variable.identifiers[0];
|
128
|
+
let obj;
|
129
|
+
|
130
|
+
if (identifier) {
|
131
|
+
obj = {
|
132
|
+
global: false,
|
133
|
+
line: identifier.loc.start.line,
|
134
|
+
column: identifier.loc.start.column + 1
|
135
|
+
};
|
136
|
+
} else {
|
137
|
+
obj = {
|
138
|
+
global: true
|
139
|
+
};
|
140
|
+
}
|
141
|
+
return obj;
|
142
|
+
}
|
143
|
+
|
120
144
|
/**
|
121
145
|
* Checks if a variable is in TDZ of scopeVar.
|
122
146
|
* @param {Object} variable The variable to check.
|
@@ -165,10 +189,18 @@ module.exports = {
|
|
165
189
|
!isOnInitializer(variable, shadowed) &&
|
166
190
|
!(options.hoist !== "all" && isInTdz(variable, shadowed))
|
167
191
|
) {
|
192
|
+
const location = getDeclaredLocation(shadowed);
|
193
|
+
const messageId = location.global ? "noShadowGlobal" : "noShadow";
|
194
|
+
const data = { name: variable.name };
|
195
|
+
|
196
|
+
if (!location.global) {
|
197
|
+
data.shadowedLine = location.line;
|
198
|
+
data.shadowedColumn = location.column;
|
199
|
+
}
|
168
200
|
context.report({
|
169
201
|
node: variable.identifiers[0],
|
170
|
-
messageId
|
171
|
-
data
|
202
|
+
messageId,
|
203
|
+
data
|
172
204
|
});
|
173
205
|
}
|
174
206
|
}
|
@@ -171,7 +171,7 @@ module.exports = {
|
|
171
171
|
/**
|
172
172
|
* Removes the top of stack item.
|
173
173
|
*
|
174
|
-
* And this
|
174
|
+
* And this traverses all segments of this code path then reports every
|
175
175
|
* invalid node.
|
176
176
|
* @param {CodePath} codePath A code path which was ended.
|
177
177
|
* @returns {void}
|
@@ -50,6 +50,10 @@ module.exports = {
|
|
50
50
|
allowTaggedTemplates: {
|
51
51
|
type: "boolean",
|
52
52
|
default: false
|
53
|
+
},
|
54
|
+
enforceForJSX: {
|
55
|
+
type: "boolean",
|
56
|
+
default: false
|
53
57
|
}
|
54
58
|
},
|
55
59
|
additionalProperties: false
|
@@ -65,7 +69,8 @@ module.exports = {
|
|
65
69
|
const config = context.options[0] || {},
|
66
70
|
allowShortCircuit = config.allowShortCircuit || false,
|
67
71
|
allowTernary = config.allowTernary || false,
|
68
|
-
allowTaggedTemplates = config.allowTaggedTemplates || false
|
72
|
+
allowTaggedTemplates = config.allowTaggedTemplates || false,
|
73
|
+
enforceForJSX = config.enforceForJSX || false;
|
69
74
|
|
70
75
|
// eslint-disable-next-line jsdoc/require-description
|
71
76
|
/**
|
@@ -140,6 +145,12 @@ module.exports = {
|
|
140
145
|
},
|
141
146
|
FunctionExpression: alwaysTrue,
|
142
147
|
Identifier: alwaysTrue,
|
148
|
+
JSXElement() {
|
149
|
+
return enforceForJSX;
|
150
|
+
},
|
151
|
+
JSXFragment() {
|
152
|
+
return enforceForJSX;
|
153
|
+
},
|
143
154
|
Literal: alwaysTrue,
|
144
155
|
LogicalExpression(node) {
|
145
156
|
if (allowShortCircuit) {
|
@@ -109,9 +109,9 @@ module.exports = {
|
|
109
109
|
* @returns {void}
|
110
110
|
*/
|
111
111
|
function report(node, startOffset, character) {
|
112
|
-
const
|
113
|
-
const rangeStart = sourceCode.getIndexFromLoc(node.loc.start) + startOffset;
|
112
|
+
const rangeStart = node.range[0] + startOffset;
|
114
113
|
const range = [rangeStart, rangeStart + 1];
|
114
|
+
const start = sourceCode.getLocFromIndex(rangeStart);
|
115
115
|
|
116
116
|
context.report({
|
117
117
|
node,
|
@@ -172,7 +172,7 @@ module.exports = {
|
|
172
172
|
}
|
173
173
|
|
174
174
|
if (isUnnecessaryEscape && !isQuoteEscape) {
|
175
|
-
report(node, match.index
|
175
|
+
report(node, match.index, match[0].slice(1));
|
176
176
|
}
|
177
177
|
}
|
178
178
|
|
@@ -206,7 +206,7 @@ module.exports = {
|
|
206
206
|
return;
|
207
207
|
}
|
208
208
|
|
209
|
-
const value = isTemplateElement ? node
|
209
|
+
const value = isTemplateElement ? sourceCode.getText(node) : node.raw;
|
210
210
|
const pattern = /\\[^\d]/gu;
|
211
211
|
let match;
|
212
212
|
|
@@ -5,6 +5,12 @@
|
|
5
5
|
|
6
6
|
"use strict";
|
7
7
|
|
8
|
+
//------------------------------------------------------------------------------
|
9
|
+
// Requirements
|
10
|
+
//------------------------------------------------------------------------------
|
11
|
+
|
12
|
+
const astUtils = require("./utils/ast-utils");
|
13
|
+
|
8
14
|
//------------------------------------------------------------------------------
|
9
15
|
// Rule Definition
|
10
16
|
//------------------------------------------------------------------------------
|
@@ -54,11 +60,10 @@ module.exports = {
|
|
54
60
|
* Reports error for unnecessarily renamed assignments
|
55
61
|
* @param {ASTNode} node node to report
|
56
62
|
* @param {ASTNode} initial node with initial name value
|
57
|
-
* @param {ASTNode} result node with new name value
|
58
63
|
* @param {string} type the type of the offending node
|
59
64
|
* @returns {void}
|
60
65
|
*/
|
61
|
-
function reportError(node, initial,
|
66
|
+
function reportError(node, initial, type) {
|
62
67
|
const name = initial.type === "Identifier" ? initial.name : initial.value;
|
63
68
|
|
64
69
|
return context.report({
|
@@ -69,18 +74,21 @@ module.exports = {
|
|
69
74
|
type
|
70
75
|
},
|
71
76
|
fix(fixer) {
|
72
|
-
|
77
|
+
const replacementNode = node.type === "Property" ? node.value : node.local;
|
78
|
+
|
79
|
+
if (sourceCode.getCommentsInside(node).length > sourceCode.getCommentsInside(replacementNode).length) {
|
73
80
|
return null;
|
74
81
|
}
|
75
82
|
|
76
|
-
|
77
|
-
|
78
|
-
|
83
|
+
// Don't autofix code such as `({foo: (foo) = a} = obj);`, parens are not allowed in shorthand properties.
|
84
|
+
if (
|
85
|
+
replacementNode.type === "AssignmentPattern" &&
|
86
|
+
astUtils.isParenthesised(sourceCode, replacementNode.left)
|
87
|
+
) {
|
88
|
+
return null;
|
89
|
+
}
|
79
90
|
|
80
|
-
return fixer.
|
81
|
-
initial.range[0],
|
82
|
-
result.range[1]
|
83
|
-
], replacementText);
|
91
|
+
return fixer.replaceText(node, sourceCode.getText(replacementNode));
|
84
92
|
}
|
85
93
|
});
|
86
94
|
}
|
@@ -97,19 +105,11 @@ module.exports = {
|
|
97
105
|
|
98
106
|
for (const property of node.properties) {
|
99
107
|
|
100
|
-
/*
|
101
|
-
* TODO: Remove after babel-eslint removes ExperimentalRestProperty
|
102
|
-
* https://github.com/eslint/eslint/issues/12335
|
103
|
-
*/
|
104
|
-
if (property.type === "ExperimentalRestProperty") {
|
105
|
-
continue;
|
106
|
-
}
|
107
|
-
|
108
108
|
/**
|
109
109
|
* Properties using shorthand syntax and rest elements can not be renamed.
|
110
110
|
* If the property is computed, we have no idea if a rename is useless or not.
|
111
111
|
*/
|
112
|
-
if (property.
|
112
|
+
if (property.type !== "Property" || property.shorthand || property.computed) {
|
113
113
|
continue;
|
114
114
|
}
|
115
115
|
|
@@ -117,7 +117,7 @@ module.exports = {
|
|
117
117
|
const renamedKey = property.value.type === "AssignmentPattern" ? property.value.left.name : property.value.name;
|
118
118
|
|
119
119
|
if (key === renamedKey) {
|
120
|
-
reportError(property, property.key,
|
120
|
+
reportError(property, property.key, "Destructuring assignment");
|
121
121
|
}
|
122
122
|
}
|
123
123
|
}
|
@@ -134,7 +134,7 @@ module.exports = {
|
|
134
134
|
|
135
135
|
if (node.imported.name === node.local.name &&
|
136
136
|
node.imported.range[0] !== node.local.range[0]) {
|
137
|
-
reportError(node, node.imported,
|
137
|
+
reportError(node, node.imported, "Import");
|
138
138
|
}
|
139
139
|
}
|
140
140
|
|
@@ -150,7 +150,7 @@ module.exports = {
|
|
150
150
|
|
151
151
|
if (node.local.name === node.exported.name &&
|
152
152
|
node.local.range[0] !== node.exported.range[0]) {
|
153
|
-
reportError(node, node.local,
|
153
|
+
reportError(node, node.local, "Export");
|
154
154
|
}
|
155
155
|
|
156
156
|
}
|
package/lib/rules/one-var.js
CHANGED
@@ -5,6 +5,25 @@
|
|
5
5
|
|
6
6
|
"use strict";
|
7
7
|
|
8
|
+
//------------------------------------------------------------------------------
|
9
|
+
// Requirements
|
10
|
+
//------------------------------------------------------------------------------
|
11
|
+
|
12
|
+
const astUtils = require("./utils/ast-utils");
|
13
|
+
|
14
|
+
//------------------------------------------------------------------------------
|
15
|
+
// Helpers
|
16
|
+
//------------------------------------------------------------------------------
|
17
|
+
|
18
|
+
/**
|
19
|
+
* Determines whether the given node is in a statement list.
|
20
|
+
* @param {ASTNode} node node to check
|
21
|
+
* @returns {boolean} `true` if the given node is in a statement list
|
22
|
+
*/
|
23
|
+
function isInStatementList(node) {
|
24
|
+
return astUtils.STATEMENT_LIST_PARENTS.has(node.parent.type);
|
25
|
+
}
|
26
|
+
|
8
27
|
//------------------------------------------------------------------------------
|
9
28
|
// Rule Definition
|
10
29
|
//------------------------------------------------------------------------------
|
@@ -268,8 +287,8 @@ module.exports = {
|
|
268
287
|
|
269
288
|
/**
|
270
289
|
* Fixer to join VariableDeclaration's into a single declaration
|
271
|
-
* @param
|
272
|
-
* @returns {Function}
|
290
|
+
* @param {VariableDeclarator[]} declarations The `VariableDeclaration` to join
|
291
|
+
* @returns {Function} The fixer function
|
273
292
|
*/
|
274
293
|
function joinDeclarations(declarations) {
|
275
294
|
const declaration = declarations[0];
|
@@ -297,10 +316,17 @@ module.exports = {
|
|
297
316
|
|
298
317
|
/**
|
299
318
|
* Fixer to split a VariableDeclaration into individual declarations
|
300
|
-
* @param
|
301
|
-
* @returns {Function}
|
319
|
+
* @param {VariableDeclaration} declaration The `VariableDeclaration` to split
|
320
|
+
* @returns {Function|null} The fixer function
|
302
321
|
*/
|
303
322
|
function splitDeclarations(declaration) {
|
323
|
+
const { parent } = declaration;
|
324
|
+
|
325
|
+
// don't autofix code such as: if (foo) var x, y;
|
326
|
+
if (!isInStatementList(parent.type === "ExportNamedDeclaration" ? parent : declaration)) {
|
327
|
+
return null;
|
328
|
+
}
|
329
|
+
|
304
330
|
return fixer => declaration.declarations.map(declarator => {
|
305
331
|
const tokenAfterDeclarator = sourceCode.getTokenAfter(declarator);
|
306
332
|
|
@@ -5,6 +5,11 @@
|
|
5
5
|
|
6
6
|
"use strict";
|
7
7
|
|
8
|
+
//------------------------------------------------------------------------------
|
9
|
+
// Requirements
|
10
|
+
//------------------------------------------------------------------------------
|
11
|
+
|
12
|
+
const FixTracker = require("./utils/fix-tracker");
|
8
13
|
const astUtils = require("./utils/ast-utils");
|
9
14
|
|
10
15
|
//------------------------------------------------------------------------------
|
@@ -451,10 +456,18 @@ module.exports = {
|
|
451
456
|
messageId: "useConst",
|
452
457
|
data: node,
|
453
458
|
fix: shouldFix
|
454
|
-
? fixer =>
|
455
|
-
sourceCode.getFirstToken(varDeclParent, t => t.value === varDeclParent.kind)
|
456
|
-
|
457
|
-
|
459
|
+
? fixer => {
|
460
|
+
const letKeywordToken = sourceCode.getFirstToken(varDeclParent, t => t.value === varDeclParent.kind);
|
461
|
+
|
462
|
+
/**
|
463
|
+
* Extend the replacement range to the whole declaration,
|
464
|
+
* in order to prevent other fixes in the same pass
|
465
|
+
* https://github.com/eslint/eslint/issues/13899
|
466
|
+
*/
|
467
|
+
return new FixTracker(fixer, sourceCode)
|
468
|
+
.retainRange(varDeclParent.range)
|
469
|
+
.replaceTextRange(letKeywordToken.range, "const");
|
470
|
+
}
|
458
471
|
: null
|
459
472
|
});
|
460
473
|
});
|
@@ -279,7 +279,7 @@ module.exports = {
|
|
279
279
|
* @param {ASTNode} node the AssignmentExpression node
|
280
280
|
* @returns {void}
|
281
281
|
*/
|
282
|
-
function
|
282
|
+
function checkAssignmentExpression(node) {
|
283
283
|
if (node.operator === "=") {
|
284
284
|
performCheck(node.left, node.right, node);
|
285
285
|
}
|
@@ -291,7 +291,7 @@ module.exports = {
|
|
291
291
|
|
292
292
|
return {
|
293
293
|
VariableDeclarator: checkVariableDeclarator,
|
294
|
-
AssignmentExpression:
|
294
|
+
AssignmentExpression: checkAssignmentExpression
|
295
295
|
};
|
296
296
|
}
|
297
297
|
};
|
@@ -105,10 +105,10 @@ module.exports = {
|
|
105
105
|
CallExpression(node) {
|
106
106
|
const methodName = (node.callee.property || {}).name;
|
107
107
|
const isReflectCall = (node.callee.object || {}).name === "Reflect";
|
108
|
-
const
|
108
|
+
const hasReflectSubstitute = Object.prototype.hasOwnProperty.call(reflectSubstitutes, methodName);
|
109
109
|
const userConfiguredException = exceptions.indexOf(methodName) !== -1;
|
110
110
|
|
111
|
-
if (
|
111
|
+
if (hasReflectSubstitute && !isReflectCall && !userConfiguredException) {
|
112
112
|
report(node, existingNames[methodName], reflectSubstitutes[methodName]);
|
113
113
|
}
|
114
114
|
},
|
@@ -82,7 +82,7 @@ function startsWithUpperCase(s) {
|
|
82
82
|
/**
|
83
83
|
* Checks whether or not a node is a constructor.
|
84
84
|
* @param {ASTNode} node A function node to check.
|
85
|
-
* @returns {boolean}
|
85
|
+
* @returns {boolean} Whether or not a node is a constructor.
|
86
86
|
*/
|
87
87
|
function isES5Constructor(node) {
|
88
88
|
return (node.id && startsWithUpperCase(node.id.name));
|
@@ -1574,7 +1574,7 @@ module.exports = {
|
|
1574
1574
|
},
|
1575
1575
|
|
1576
1576
|
/*
|
1577
|
-
* Determine if a node has a
|
1577
|
+
* Determine if a node has a possibility to be an Error object
|
1578
1578
|
* @param {ASTNode} node ASTNode to check
|
1579
1579
|
* @returns {boolean} True if there is a chance it contains an Error obj
|
1580
1580
|
*/
|
@@ -15,7 +15,7 @@ const lodash = require("lodash");
|
|
15
15
|
// Private
|
16
16
|
//------------------------------------------------------------------------------
|
17
17
|
|
18
|
-
//
|
18
|
+
// Definitions for deprecation warnings.
|
19
19
|
const deprecationWarningMessages = {
|
20
20
|
ESLINT_LEGACY_ECMAFEATURES:
|
21
21
|
"The 'ecmaFeatures' config file property is deprecated and has no effect.",
|
package/lib/shared/types.js
CHANGED
@@ -46,9 +46,9 @@ module.exports = {};
|
|
46
46
|
/**
|
47
47
|
* @typedef {Object} OverrideConfigData
|
48
48
|
* @property {Record<string, boolean>} [env] The environment settings.
|
49
|
-
* @property {string | string[]} [excludedFiles] The glob
|
49
|
+
* @property {string | string[]} [excludedFiles] The glob patterns for excluded files.
|
50
50
|
* @property {string | string[]} [extends] The path to other config files or the package name of shareable configs.
|
51
|
-
* @property {string | string[]} files The glob
|
51
|
+
* @property {string | string[]} files The glob patterns for target files.
|
52
52
|
* @property {Record<string, GlobalConf>} [globals] The global variable settings.
|
53
53
|
* @property {boolean} [noInlineConfig] The flag that disables directive comments.
|
54
54
|
* @property {OverrideConfigData[]} [overrides] The override settings per kind of files.
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "eslint",
|
3
|
-
"version": "7.
|
3
|
+
"version": "7.20.0",
|
4
4
|
"author": "Nicholas C. Zakas <nicholas+npm@nczconsulting.com>",
|
5
5
|
"description": "An AST-based pattern checker for JavaScript.",
|
6
6
|
"bin": {
|
@@ -46,8 +46,8 @@
|
|
46
46
|
"homepage": "https://eslint.org",
|
47
47
|
"bugs": "https://github.com/eslint/eslint/issues/",
|
48
48
|
"dependencies": {
|
49
|
-
"@babel/code-frame": "
|
50
|
-
"@eslint/eslintrc": "^0.
|
49
|
+
"@babel/code-frame": "7.12.11",
|
50
|
+
"@eslint/eslintrc": "^0.3.0",
|
51
51
|
"ajv": "^6.10.0",
|
52
52
|
"chalk": "^4.0.0",
|
53
53
|
"cross-spawn": "^7.0.2",
|
@@ -58,7 +58,7 @@
|
|
58
58
|
"eslint-utils": "^2.1.0",
|
59
59
|
"eslint-visitor-keys": "^2.0.0",
|
60
60
|
"espree": "^7.3.1",
|
61
|
-
"esquery": "^1.
|
61
|
+
"esquery": "^1.4.0",
|
62
62
|
"esutils": "^2.0.2",
|
63
63
|
"file-entry-cache": "^6.0.0",
|
64
64
|
"functional-red-black-tree": "^1.0.1",
|
@@ -71,7 +71,7 @@
|
|
71
71
|
"js-yaml": "^3.13.1",
|
72
72
|
"json-stable-stringify-without-jsonify": "^1.0.1",
|
73
73
|
"levn": "^0.4.1",
|
74
|
-
"lodash": "^4.17.
|
74
|
+
"lodash": "^4.17.20",
|
75
75
|
"minimatch": "^3.0.4",
|
76
76
|
"natural-compare": "^1.4.0",
|
77
77
|
"optionator": "^0.9.1",
|