eslint 7.10.0 → 7.13.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 CHANGED
@@ -1,3 +1,60 @@
1
+ v7.13.0 - November 6, 2020
2
+
3
+ * [`254e00f`](https://github.com/eslint/eslint/commit/254e00fea8745ff5a8bcc8cb874fcfd02996d81b) New: Configurable List Size For Per-Rule Performance Metrics (#13812) (Bryan Mishkin)
4
+ * [`6c3c710`](https://github.com/eslint/eslint/commit/6c3c710ade7cd8654990f1adb55b58f038eab92d) Docs: fix broken url in docs (#13815) (SaintMalik)
5
+ * [`4a09149`](https://github.com/eslint/eslint/commit/4a091495a236d231a5065ece972719a0c4dd1b77) Sponsors: Sync README with website (ESLint Jenkins)
6
+ * [`fb6fcbf`](https://github.com/eslint/eslint/commit/fb6fcbfe0a8c41b92f0a33ab90f159037bd195e2) Docs: Fix reference to Code of Conduct (#13797) (Tobias Nießen)
7
+ * [`1b89ebe`](https://github.com/eslint/eslint/commit/1b89ebe1bdbef7de6001100945b8f71429df302c) Sponsors: Sync README with website (ESLint Jenkins)
8
+
9
+ v7.12.1 - October 26, 2020
10
+
11
+ * [`08f33e8`](https://github.com/eslint/eslint/commit/08f33e8b9a353c3183be6f937785db7a30fb90eb) Upgrade: @eslint/eslintrc to fix rule schema validation (fixes #13793) (#13794) (Brandon Mills)
12
+ * [`aeef485`](https://github.com/eslint/eslint/commit/aeef485dc790571b1a82ac09904329e0226b66a9) Fix: Pass internal config paths in FileEnumerator default (fixes #13789) (#13792) (Brandon Mills)
13
+ * [`631ae8b`](https://github.com/eslint/eslint/commit/631ae8b50e5f7975f10860e9e763b70b4f25182e) Sponsors: Sync README with website (ESLint Jenkins)
14
+
15
+ v7.12.0 - October 23, 2020
16
+
17
+ * [`cbf3585`](https://github.com/eslint/eslint/commit/cbf3585f1d6c60414c07380367a8b4505ee3538d) Update: skip keyword check for fns in space-before-blocks (fixes #13553) (#13712) (Milos Djermanovic)
18
+ * [`256f656`](https://github.com/eslint/eslint/commit/256f656455b47bcf9ed3fc30fbf72532678f97da) Fix: autofix shouldn't produce template literals with `\8` or `\9` (#13737) (Milos Djermanovic)
19
+ * [`b165aa5`](https://github.com/eslint/eslint/commit/b165aa5f4d4d19328f13ab80e5f058cbce94c3a6) Fix: yoda rule autofix produces syntax errors with adjacent tokens (#13760) (Milos Djermanovic)
20
+ * [`3175316`](https://github.com/eslint/eslint/commit/3175316db26aebef4b19e269aca90c8ce3955363) Fix: prefer-destructuring invalid autofix with comma operator (#13761) (Milos Djermanovic)
21
+ * [`1a9f171`](https://github.com/eslint/eslint/commit/1a9f17151a4e93eb17c8a2bf4f0a5320cce616de) Chore: Remove more ESLintRC-related files (refs #13481) (#13762) (Nicholas C. Zakas)
22
+ * [`bfddced`](https://github.com/eslint/eslint/commit/bfddcedace5587d662c840c2edf33062b54a178e) Update: remove suggestion if it didn't provide a fix (fixes #13723) (#13772) (Milos Djermanovic)
23
+ * [`5183b14`](https://github.com/eslint/eslint/commit/5183b14a2420b42b4089fb134a61ae57142f31fd) Update: check template literal in no-script-url (#13775) (YeonJuan)
24
+ * [`bfe97d2`](https://github.com/eslint/eslint/commit/bfe97d2332e711ca76b1fd2e7f8548b0cc84cb1c) Sponsors: Sync README with website (ESLint Jenkins)
25
+ * [`6c51ade`](https://github.com/eslint/eslint/commit/6c51adeb86f1de292cd02d2ee19f7b56182e358b) Sponsors: Sync README with website (ESLint Jenkins)
26
+ * [`603de04`](https://github.com/eslint/eslint/commit/603de04cab5e700df12999af2918decd4da9d11b) Update: treat all literals like boolean literal in no-constant-condition (#13245) (Zen)
27
+ * [`289aa6f`](https://github.com/eslint/eslint/commit/289aa6fcef3874ba5f86455f9302dc4209ea83e5) Sponsors: Sync README with website (ESLint Jenkins)
28
+ * [`9a1f669`](https://github.com/eslint/eslint/commit/9a1f6694e59eb3e584d4c5a98b98675c895a9783) Sponsors: Sync README with website (ESLint Jenkins)
29
+ * [`637f818`](https://github.com/eslint/eslint/commit/637f8187404ded600fb3d4013b3cd495d5ae675b) Docs: add more examples for no-func-assign (fixes #13705) (#13777) (Nitin Kumar)
30
+ * [`17cc0dd`](https://github.com/eslint/eslint/commit/17cc0dd9b5d2d500359c36881cd3e5637443c133) Chore: add test case for no-func-assign (refs #13705) (#13783) (Nitin Kumar)
31
+ * [`dee0f77`](https://github.com/eslint/eslint/commit/dee0f7764a1d5a323c89b22c4db94acee2b3c718) Docs: add TOC to user-guide/configuring.md (#13727) (metasean)
32
+ * [`0510621`](https://github.com/eslint/eslint/commit/05106212985cb1ffa1e6fa996a57f6fd2fc3c970) Update: Fix && vs || short-circuiting false negatives (fixes #13634) (#13769) (Brandon Mills)
33
+ * [`8b6ed69`](https://github.com/eslint/eslint/commit/8b6ed691c48189b7d096339441a78cb5874d4137) Sponsors: Sync README with website (ESLint Jenkins)
34
+ * [`1457509`](https://github.com/eslint/eslint/commit/145750991b04fd4cfb3fff3c5d4211a4428e011c) Docs: fix broken links in Node.js API docs (#13771) (Laura Barluzzi)
35
+ * [`7c813d4`](https://github.com/eslint/eslint/commit/7c813d458f9aedf7a94351d137728a4647542879) Docs: Fix typo in v7 migration page (#13778) (Yusuke Sasaki)
36
+ * [`b025795`](https://github.com/eslint/eslint/commit/b0257953be704d0bb387fc15afd7859fd6f19ba5) Docs: Fix the format option name in the document (#13770) (Hideki Igarashi)
37
+ * [`84fd591`](https://github.com/eslint/eslint/commit/84fd591c234accc41bb5af555f178825012fd35d) Chore: Increase Mocha timeout for copying fixtures (#13768) (Brandon Mills)
38
+ * [`1faeb84`](https://github.com/eslint/eslint/commit/1faeb84e663d88c5d85a3cb3f15cd224cc552c2d) Docs: clarify that space-unary-ops doesn't apply when space is required (#13767) (Taylor Morgan)
39
+ * [`67c0605`](https://github.com/eslint/eslint/commit/67c06059dd1ddcee6f369c650ce71220da1510c3) Update: check computed keys in no-prototype-builtins (fixes #13088) (#13755) (Milos Djermanovic)
40
+ * [`b5e011c`](https://github.com/eslint/eslint/commit/b5e011c865e95d700d29cb9a4ba71c671d99e423) Sponsors: Sync README with website (ESLint Jenkins)
41
+
42
+ v7.11.0 - October 9, 2020
43
+
44
+ * [`23e966f`](https://github.com/eslint/eslint/commit/23e966f6cf2a6c6b699dff5d6950ece3cc396498) Chore: Refactor CLIEngine tests (refs #13481) (#13709) (Nicholas C. Zakas)
45
+ * [`fa9429a`](https://github.com/eslint/eslint/commit/fa9429aac0ffed505f3f02e8fc75f646c69f5c61) Fix: don't count line after EOF in max-lines (#13735) (Milos Djermanovic)
46
+ * [`d973675`](https://github.com/eslint/eslint/commit/d973675a5c06a2bd4f8ce640c78b67842cfebfd4) Docs: Update anchor links to use existing linkrefs (refs #13715) (#13741) (Brandon Mills)
47
+ * [`2c6d774`](https://github.com/eslint/eslint/commit/2c6d774c89dcd14f386bd9d73d451fa2a892c3ef) Docs: Fix typos (#13730) (Frieder Bluemle)
48
+ * [`cc468c0`](https://github.com/eslint/eslint/commit/cc468c01021385a028de727eefcd442e7f34875c) Upgrade: eslint-visitor-keys@2.0.0 (#13732) (Milos Djermanovic)
49
+ * [`ab0ac6c`](https://github.com/eslint/eslint/commit/ab0ac6c532fb7b7d49779c8913146244d680743b) Docs: Fix anchor links (#13715) (Gary Moore)
50
+ * [`27f0de6`](https://github.com/eslint/eslint/commit/27f0de62e6281c28043be38ef051818c9edc15cd) Fix: account for linebreaks before postfix `++`/`--` in no-extra-parens (#13731) (Milos Djermanovic)
51
+ * [`da78fa1`](https://github.com/eslint/eslint/commit/da78fa11632a2908db4ac494012a16f5d5a88a64) Update: support async arrow fn in function-paren-newline (fixes #13728) (#13729) (Michal Dziekonski)
52
+ * [`fe301b8`](https://github.com/eslint/eslint/commit/fe301b8cc0762d7f4edd59603ca51ed0ec0c2a43) Docs: Add configuration comments in examples (#13738) (YeonJuan)
53
+ * [`504408c`](https://github.com/eslint/eslint/commit/504408cd65e9d8827b2b8bbeb8f589df90eee523) Sponsors: Sync README with website (ESLint Jenkins)
54
+ * [`3900659`](https://github.com/eslint/eslint/commit/390065985b2289ad4412a83598e3e833c382d27e) Sponsors: Sync README with website (ESLint Jenkins)
55
+ * [`c1974b3`](https://github.com/eslint/eslint/commit/c1974b3f7169a8e5fab7007df92d02d8c1a8d5a3) Sponsors: Sync README with website (ESLint Jenkins)
56
+ * [`6f4abe5`](https://github.com/eslint/eslint/commit/6f4abe5d5ade2711cc4c21bc8485af952763c2d3) Sponsors: Sync README with website (ESLint Jenkins)
57
+
1
58
  v7.10.0 - September 26, 2020
2
59
 
3
60
  * [`6919fbb`](https://github.com/eslint/eslint/commit/6919fbb83f86552b0f49ae749da866e4edc7c46a) Docs: Clarify that ignorePattern should be a string (refs #13029) (#13718) (Brandon Mills)
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- [![NPM version](https://img.shields.io/npm/v/eslint.svg)](https://www.npmjs.com/package/eslint)
1
+ [![npm version](https://img.shields.io/npm/v/eslint.svg)](https://www.npmjs.com/package/eslint)
2
2
  [![Downloads](https://img.shields.io/npm/dm/eslint.svg)](https://www.npmjs.com/package/eslint)
3
3
  [![Build Status](https://github.com/eslint/eslint/workflows/CI/badge.svg)](https://github.com/eslint/eslint/actions)
4
4
  [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Feslint%2Feslint.svg?type=shield)](https://app.fossa.io/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Feslint%2Feslint?ref=badge_shield)
@@ -14,7 +14,7 @@
14
14
  [Rules](https://eslint.org/docs/rules/) |
15
15
  [Contributing](https://eslint.org/docs/developer-guide/contributing) |
16
16
  [Reporting Bugs](https://eslint.org/docs/developer-guide/contributing/reporting-bugs) |
17
- [Code of Conduct](https://js.foundation/community/code-of-conduct) |
17
+ [Code of Conduct](https://eslint.org/conduct) |
18
18
  [Twitter](https://twitter.com/geteslint) |
19
19
  [Mailing List](https://groups.google.com/group/eslint) |
20
20
  [Chat Room](https://eslint.org/chat)
@@ -85,7 +85,7 @@ The three error levels allow you fine-grained control over how ESLint applies ru
85
85
 
86
86
  ## <a name="code-of-conduct"></a>Code of Conduct
87
87
 
88
- ESLint adheres to the [JS Foundation Code of Conduct](https://js.foundation/community/code-of-conduct).
88
+ ESLint adheres to the [JS Foundation Code of Conduct](https://eslint.org/conduct).
89
89
 
90
90
  ## <a name="filing-issues"></a>Filing Issues
91
91
 
@@ -263,10 +263,11 @@ The following companies, organizations, and individuals support ESLint's ongoing
263
263
 
264
264
  <!-- NOTE: This section is autogenerated. Do not manually edit.-->
265
265
  <!--sponsorsstart-->
266
- <h3>Gold Sponsors</h3>
267
- <p><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://avatars1.githubusercontent.com/u/67931232?u=7fddc652a464d7151b97e8f108392af7d54fa3e8&v=4" alt="Microsoft FOSS Fund Sponsorships" height="96"></a></p><h3>Silver Sponsors</h3>
266
+ <h3>Platinum Sponsors</h3>
267
+ <p><a href="https://automattic.com"><img src="https://images.opencollective.com/photomatt/ff91f0b/logo.png" alt="Automattic" height="undefined"></a></p><h3>Gold Sponsors</h3>
268
+ <p><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://avatars1.githubusercontent.com/u/67931232?u=7fddc652a464d7151b97e8f108392af7d54fa3e8&v=4" alt="Microsoft FOSS Fund Sponsorships" height="96"></a></p><h3>Silver Sponsors</h3>
268
269
  <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>
269
- <p><a href="https://www.betacalendars.com/printable-calendar"><img src="https://images.opencollective.com/betacalendars/9334b33/logo.png" alt="2021 calendar" height="32"></a> <a href="https://buy.fineproxy.org/eng/"><img src="https://images.opencollective.com/buy-fineproxy-org/2002c40/logo.png" alt="Buy.Fineproxy.Org" height="32"></a> <a href="https://www.veikkaajat.com"><img src="https://images.opencollective.com/veikkaajat/b92b427/logo.png" alt="Veikkaajat.com" height="32"></a> <a href="https://www.nettikasinot.media/"><img src="https://images.opencollective.com/nettikasinot-media/2dba7da/logo.png" alt="Nettikasinot.media" height="32"></a> <a href="https://mytruemedia.com/"><img src="https://images.opencollective.com/my-true-media/03e2168/logo.png" alt="My True Media" height="32"></a> <a href="https://www.norgekasino.com"><img src="https://images.opencollective.com/norgekasino/ecfd57a/logo.png" alt="Norgekasino" height="32"></a> <a href="https://www.japanesecasino.com/"><img src="https://images.opencollective.com/japanesecasino/b0ffe3c/logo.png" alt="Japanesecasino" height="32"></a> <a href="https://www.casinotop.com/"><img src="https://images.opencollective.com/casinotop-com/10fd95b/logo.png" alt="CasinoTop.com" height="32"></a> <a href="https://www.casinotopp.net/"><img src="https://images.opencollective.com/casino-topp/1dd399a/logo.png" alt="Casino Topp" 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.kasinot.fi"><img src="https://images.opencollective.com/kasinot-fi/e09aa2e/logo.png" alt="Kasinot.fi" height="32"></a> <a href="https://www.pelisivut.com"><img src="https://images.opencollective.com/pelisivut/04f08f2/logo.png" alt="Pelisivut" height="32"></a> <a href="https://www.nettikasinot.org"><img src="https://images.opencollective.com/nettikasinot-org/53a4b44/logo.png" alt="Nettikasinot.org" height="32"></a> <a href="https://www.bonus.com.de/freispiele"><img src="https://images.opencollective.com/bonusfinder-deutschland/646169e/logo.png" alt="BonusFinder Deutschland" 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.marfeel.com/"><img src="https://images.opencollective.com/marfeel/4b88e30/logo.png" alt="Marfeel" 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>
270
+ <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/printable-calendar"><img src="https://images.opencollective.com/betacalendars/9334b33/logo.png" alt="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.veikkaajat.com"><img src="https://images.opencollective.com/veikkaajat/b92b427/logo.png" alt="Veikkaajat.com" 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>
270
271
  <!--sponsorsend-->
271
272
 
272
273
  ## <a name="technology-sponsors"></a>Technology Sponsors
@@ -19,14 +19,29 @@ const fs = require("fs");
19
19
  const path = require("path");
20
20
  const defaultOptions = require("../../conf/default-cli-options");
21
21
  const pkg = require("../../package.json");
22
- const ConfigOps = require("@eslint/eslintrc/lib/shared/config-ops");
23
- const naming = require("@eslint/eslintrc/lib/shared/naming");
24
- const ModuleResolver = require("../shared/relative-module-resolver");
22
+
23
+
24
+ const {
25
+ Legacy: {
26
+ ConfigOps,
27
+ naming,
28
+ CascadingConfigArrayFactory,
29
+ IgnorePattern,
30
+ getUsedExtractedConfigs
31
+ }
32
+ } = require("@eslint/eslintrc");
33
+
34
+ /*
35
+ * For some reason, ModuleResolver must be included via filepath instead of by
36
+ * API exports in order to work properly. That's why this is separated out onto
37
+ * its own require() statement.
38
+ */
39
+ const ModuleResolver = require("@eslint/eslintrc/lib/shared/relative-module-resolver");
40
+ const { FileEnumerator } = require("./file-enumerator");
41
+
25
42
  const { Linter } = require("../linter");
26
43
  const builtInRules = require("../rules");
27
- const { CascadingConfigArrayFactory } = require("./cascading-config-array-factory");
28
- const { IgnorePattern, getUsedExtractedConfigs } = require("./config-array");
29
- const { FileEnumerator } = require("./file-enumerator");
44
+ const loadRules = require("./load-rules");
30
45
  const hash = require("./hash");
31
46
  const LintResultCache = require("./lint-result-cache");
32
47
 
@@ -559,7 +574,11 @@ class CLIEngine {
559
574
  resolvePluginsRelativeTo: options.resolvePluginsRelativeTo,
560
575
  rulePaths: options.rulePaths,
561
576
  specificConfigPath: options.configFile,
562
- useEslintrc: options.useEslintrc
577
+ useEslintrc: options.useEslintrc,
578
+ builtInRules,
579
+ loadRules,
580
+ eslintRecommendedPath: path.resolve(__dirname, "../../conf/eslint-recommended.js"),
581
+ eslintAllPath: path.resolve(__dirname, "../../conf/eslint-all.js")
563
582
  });
564
583
  const fileEnumerator = new FileEnumerator({
565
584
  configArrayFactory,
@@ -40,8 +40,13 @@ const getGlobParent = require("glob-parent");
40
40
  const isGlob = require("is-glob");
41
41
  const { escapeRegExp } = require("lodash");
42
42
  const { Minimatch } = require("minimatch");
43
- const { IgnorePattern } = require("./config-array");
44
- const { CascadingConfigArrayFactory } = require("./cascading-config-array-factory");
43
+
44
+ const {
45
+ Legacy: {
46
+ IgnorePattern,
47
+ CascadingConfigArrayFactory
48
+ }
49
+ } = require("@eslint/eslintrc");
45
50
  const debug = require("debug")("eslint:file-enumerator");
46
51
 
47
52
  //------------------------------------------------------------------------------
@@ -208,7 +213,11 @@ class FileEnumerator {
208
213
  */
209
214
  constructor({
210
215
  cwd = process.cwd(),
211
- configArrayFactory = new CascadingConfigArrayFactory({ cwd }),
216
+ configArrayFactory = new CascadingConfigArrayFactory({
217
+ cwd,
218
+ eslintRecommendedPath: path.resolve(__dirname, "../../conf/eslint-recommended.js"),
219
+ eslintAllPath: path.resolve(__dirname, "../../conf/eslint-all.js")
220
+ }),
212
221
  extensions = null,
213
222
  globInputPaths = true,
214
223
  errorOnUnmatchedPattern = true,
@@ -196,15 +196,19 @@ function mapSuggestions(descriptor, sourceCode, messages) {
196
196
  return [];
197
197
  }
198
198
 
199
- return descriptor.suggest.map(suggestInfo => {
200
- const computedDesc = suggestInfo.desc || messages[suggestInfo.messageId];
201
-
202
- return {
203
- ...suggestInfo,
204
- desc: interpolate(computedDesc, suggestInfo.data),
205
- fix: normalizeFixes(suggestInfo, sourceCode)
206
- };
207
- });
199
+ return descriptor.suggest
200
+ .map(suggestInfo => {
201
+ const computedDesc = suggestInfo.desc || messages[suggestInfo.messageId];
202
+
203
+ return {
204
+ ...suggestInfo,
205
+ desc: interpolate(computedDesc, suggestInfo.data),
206
+ fix: normalizeFixes(suggestInfo, sourceCode)
207
+ };
208
+ })
209
+
210
+ // Remove suggestions that didn't provide a fix
211
+ .filter(({ fix }) => fix);
208
212
  }
209
213
 
210
214
  /**
@@ -44,6 +44,26 @@ const enabled = !!process.env.TIMING;
44
44
  const HEADERS = ["Rule", "Time (ms)", "Relative"];
45
45
  const ALIGN = [alignLeft, alignRight, alignRight];
46
46
 
47
+ /**
48
+ * Decide how many rules to show in the output list.
49
+ * @returns {number} the number of rules to show
50
+ */
51
+ function getListSize() {
52
+ const MINIMUM_SIZE = 10;
53
+
54
+ if (typeof process.env.TIMING !== "string") {
55
+ return MINIMUM_SIZE;
56
+ }
57
+
58
+ if (process.env.TIMING.toLowerCase() === "all") {
59
+ return Number.POSITIVE_INFINITY;
60
+ }
61
+
62
+ const TIMING_ENV_VAR_AS_INTEGER = Number.parseInt(process.env.TIMING, 10);
63
+
64
+ return TIMING_ENV_VAR_AS_INTEGER > 10 ? TIMING_ENV_VAR_AS_INTEGER : MINIMUM_SIZE;
65
+ }
66
+
47
67
  /* istanbul ignore next */
48
68
  /**
49
69
  * display the data
@@ -61,7 +81,7 @@ function display(data) {
61
81
  return [key, time];
62
82
  })
63
83
  .sort((a, b) => b[1] - a[1])
64
- .slice(0, 10);
84
+ .slice(0, getListSize());
65
85
 
66
86
  rows.forEach(row => {
67
87
  row.push(`${(row[1] * 100 / total).toFixed(1)}%`);
@@ -133,7 +153,8 @@ module.exports = (function() {
133
153
 
134
154
  return {
135
155
  time,
136
- enabled
156
+ enabled,
157
+ getListSize
137
158
  };
138
159
 
139
160
  }());
@@ -79,6 +79,17 @@ function isPossibleConstructor(node) {
79
79
  return false;
80
80
 
81
81
  case "LogicalExpression":
82
+
83
+ /*
84
+ * If the && operator short-circuits, the left side was falsy and therefore not a constructor, and if
85
+ * it doesn't short-circuit, it takes the value from the right side, so the right side must always be a
86
+ * possible constructor. A future improvement could verify that the left side could be truthy by
87
+ * excluding falsy literals.
88
+ */
89
+ if (node.operator === "&&") {
90
+ return isPossibleConstructor(node.right);
91
+ }
92
+
82
93
  return (
83
94
  isPossibleConstructor(node.left) ||
84
95
  isPossibleConstructor(node.right)
@@ -218,7 +218,7 @@ module.exports = {
218
218
  }
219
219
 
220
220
  case "ArrowFunctionExpression": {
221
- const firstToken = sourceCode.getFirstToken(node);
221
+ const firstToken = sourceCode.getFirstToken(node, { skip: (node.async ? 1 : 0) });
222
222
 
223
223
  if (!astUtils.isOpeningParenToken(firstToken)) {
224
224
 
@@ -131,6 +131,14 @@ module.exports = {
131
131
  text
132
132
  }));
133
133
 
134
+ /*
135
+ * If file ends with a linebreak, `sourceCode.lines` will have one extra empty line at the end.
136
+ * That isn't a real line, so we shouldn't count it.
137
+ */
138
+ if (lines.length > 1 && lodash.last(lines).text === "") {
139
+ lines.pop();
140
+ }
141
+
134
142
  if (skipBlankLines) {
135
143
  lines = lines.filter(l => l.text.trim() !== "");
136
144
  }
@@ -9,9 +9,6 @@
9
9
  // Helpers
10
10
  //------------------------------------------------------------------------------
11
11
 
12
- const EQUALITY_OPERATORS = ["===", "!==", "==", "!="];
13
- const RELATIONAL_OPERATORS = [">", "<", ">=", "<=", "in", "instanceof"];
14
-
15
12
  //------------------------------------------------------------------------------
16
13
  // Rule Definition
17
14
  //------------------------------------------------------------------------------
@@ -56,6 +53,35 @@ module.exports = {
56
53
  // Helpers
57
54
  //--------------------------------------------------------------------------
58
55
 
56
+ /**
57
+ * Returns literal's value converted to the Boolean type
58
+ * @param {ASTNode} node any `Literal` node
59
+ * @returns {boolean | null} `true` when node is truthy, `false` when node is falsy,
60
+ * `null` when it cannot be determined.
61
+ */
62
+ function getBooleanValue(node) {
63
+ if (node.value === null) {
64
+
65
+ /*
66
+ * it might be a null literal or bigint/regex literal in unsupported environments .
67
+ * https://github.com/estree/estree/blob/14df8a024956ea289bd55b9c2226a1d5b8a473ee/es5.md#regexpliteral
68
+ * https://github.com/estree/estree/blob/14df8a024956ea289bd55b9c2226a1d5b8a473ee/es2020.md#bigintliteral
69
+ */
70
+
71
+ if (node.raw === "null") {
72
+ return false;
73
+ }
74
+
75
+ // regex is always truthy
76
+ if (typeof node.regex === "object") {
77
+ return true;
78
+ }
79
+
80
+ return null;
81
+ }
82
+
83
+ return !!node.value;
84
+ }
59
85
 
60
86
  /**
61
87
  * Checks if a branch node of LogicalExpression short circuits the whole condition
@@ -66,15 +92,23 @@ module.exports = {
66
92
  function isLogicalIdentity(node, operator) {
67
93
  switch (node.type) {
68
94
  case "Literal":
69
- return (operator === "||" && node.value === true) ||
70
- (operator === "&&" && node.value === false);
95
+ return (operator === "||" && getBooleanValue(node) === true) ||
96
+ (operator === "&&" && getBooleanValue(node) === false);
71
97
 
72
98
  case "UnaryExpression":
73
99
  return (operator === "&&" && node.operator === "void");
74
100
 
75
101
  case "LogicalExpression":
76
- return isLogicalIdentity(node.left, node.operator) ||
77
- isLogicalIdentity(node.right, node.operator);
102
+
103
+ /*
104
+ * handles `a && false || b`
105
+ * `false` is an identity element of `&&` but not `||`
106
+ */
107
+ return operator === node.operator &&
108
+ (
109
+ isLogicalIdentity(node.left, node.operator) ||
110
+ isLogicalIdentity(node.right, node.operator)
111
+ );
78
112
 
79
113
  // no default
80
114
  }
@@ -129,21 +163,9 @@ module.exports = {
129
163
  const isLeftConstant = isConstant(node.left, inBooleanPosition);
130
164
  const isRightConstant = isConstant(node.right, inBooleanPosition);
131
165
  const isLeftShortCircuit = (isLeftConstant && isLogicalIdentity(node.left, node.operator));
132
- const isRightShortCircuit = (isRightConstant && isLogicalIdentity(node.right, node.operator));
166
+ const isRightShortCircuit = (inBooleanPosition && isRightConstant && isLogicalIdentity(node.right, node.operator));
133
167
 
134
168
  return (isLeftConstant && isRightConstant) ||
135
- (
136
-
137
- // in the case of an "OR", we need to know if the right constant value is truthy
138
- node.operator === "||" &&
139
- isRightConstant &&
140
- node.right.value &&
141
- (
142
- !node.parent ||
143
- node.parent.type !== "BinaryExpression" ||
144
- !(EQUALITY_OPERATORS.includes(node.parent.operator) || RELATIONAL_OPERATORS.includes(node.parent.operator))
145
- )
146
- ) ||
147
169
  isLeftShortCircuit ||
148
170
  isRightShortCircuit;
149
171
  }
@@ -1109,7 +1109,22 @@ module.exports = {
1109
1109
  },
1110
1110
 
1111
1111
  UnaryExpression: checkArgumentWithPrecedence,
1112
- UpdateExpression: checkArgumentWithPrecedence,
1112
+ UpdateExpression(node) {
1113
+ if (node.prefix) {
1114
+ checkArgumentWithPrecedence(node);
1115
+ } else {
1116
+ const { argument } = node;
1117
+ const operatorToken = sourceCode.getLastToken(node);
1118
+
1119
+ if (argument.loc.end.line === operatorToken.loc.start.line) {
1120
+ checkArgumentWithPrecedence(node);
1121
+ } else {
1122
+ if (hasDoubleExcessParens(argument)) {
1123
+ report(argument);
1124
+ }
1125
+ }
1126
+ }
1127
+ },
1113
1128
  AwaitExpression: checkArgumentWithPrecedence,
1114
1129
 
1115
1130
  VariableDeclarator(node) {
@@ -46,15 +46,15 @@ module.exports = {
46
46
  */
47
47
  function disallowBuiltIns(node) {
48
48
 
49
- // TODO: just use `astUtils.getStaticPropertyName(node.callee)`
50
49
  const callee = astUtils.skipChainExpression(node.callee);
51
50
 
52
- if (callee.type !== "MemberExpression" || callee.computed) {
51
+ if (callee.type !== "MemberExpression") {
53
52
  return;
54
53
  }
55
- const propName = callee.property.name;
56
54
 
57
- if (DISALLOWED_PROPS.indexOf(propName) > -1) {
55
+ const propName = astUtils.getStaticPropertyName(callee);
56
+
57
+ if (propName !== null && DISALLOWED_PROPS.indexOf(propName) > -1) {
58
58
  context.report({
59
59
  messageId: "prototypeBuildIn",
60
60
  loc: callee.property.loc,
@@ -7,6 +7,8 @@
7
7
 
8
8
  "use strict";
9
9
 
10
+ const astUtils = require("./utils/ast-utils");
11
+
10
12
  //------------------------------------------------------------------------------
11
13
  // Rule Definition
12
14
  //------------------------------------------------------------------------------
@@ -31,18 +33,30 @@ module.exports = {
31
33
 
32
34
  create(context) {
33
35
 
36
+ /**
37
+ * Check whether a node's static value starts with "javascript:" or not.
38
+ * And report an error for unexpected script URL.
39
+ * @param {ASTNode} node node to check
40
+ * @returns {void}
41
+ */
42
+ function check(node) {
43
+ const value = astUtils.getStaticStringValue(node);
44
+
45
+ if (typeof value === "string" && value.toLowerCase().indexOf("javascript:") === 0) {
46
+ context.report({ node, messageId: "unexpectedScriptURL" });
47
+ }
48
+ }
34
49
  return {
35
-
36
50
  Literal(node) {
37
51
  if (node.value && typeof node.value === "string") {
38
- const value = node.value.toLowerCase();
39
-
40
- if (value.indexOf("javascript:") === 0) {
41
- context.report({ node, messageId: "unexpectedScriptURL" });
42
- }
52
+ check(node);
53
+ }
54
+ },
55
+ TemplateLiteral(node) {
56
+ if (!(node.parent && node.parent.type === "TaggedTemplateExpression")) {
57
+ check(node);
43
58
  }
44
59
  }
45
60
  };
46
-
47
61
  }
48
62
  };
@@ -4,6 +4,18 @@
4
4
  */
5
5
  "use strict";
6
6
 
7
+ //------------------------------------------------------------------------------
8
+ // Requirements
9
+ //------------------------------------------------------------------------------
10
+
11
+ const astUtils = require("./utils/ast-utils");
12
+
13
+ //------------------------------------------------------------------------------
14
+ // Helpers
15
+ //------------------------------------------------------------------------------
16
+
17
+ const PRECEDENCE_OF_ASSIGNMENT_EXPR = astUtils.getPrecedence({ type: "AssignmentExpression" });
18
+
7
19
  //------------------------------------------------------------------------------
8
20
  // Rule Definition
9
21
  //------------------------------------------------------------------------------
@@ -185,9 +197,15 @@ module.exports = {
185
197
  return null;
186
198
  }
187
199
 
200
+ let objectText = sourceCode.getText(rightNode.object);
201
+
202
+ if (astUtils.getPrecedence(rightNode.object) < PRECEDENCE_OF_ASSIGNMENT_EXPR) {
203
+ objectText = `(${objectText})`;
204
+ }
205
+
188
206
  return fixer.replaceText(
189
207
  node,
190
- `{${rightNode.property.name}} = ${sourceCode.getText(rightNode.object)}`
208
+ `{${rightNode.property.name}} = ${objectText}`
191
209
  );
192
210
  }
193
211
 
@@ -39,33 +39,25 @@ function getTopConcatBinaryExpression(node) {
39
39
  }
40
40
 
41
41
  /**
42
- * Determines whether a given node is a octal escape sequence
42
+ * Checks whether or not a node contains a string literal with an octal or non-octal decimal escape sequence
43
43
  * @param {ASTNode} node A node to check
44
- * @returns {boolean} `true` if the node is an octal escape sequence
44
+ * @returns {boolean} `true` if at least one string literal within the node contains
45
+ * an octal or non-octal decimal escape sequence
45
46
  */
46
- function isOctalEscapeSequence(node) {
47
-
48
- // No need to check TemplateLiterals – would throw error with octal escape
49
- const isStringLiteral = node.type === "Literal" && typeof node.value === "string";
50
-
51
- if (!isStringLiteral) {
52
- return false;
47
+ function hasOctalOrNonOctalDecimalEscapeSequence(node) {
48
+ if (isConcatenation(node)) {
49
+ return (
50
+ hasOctalOrNonOctalDecimalEscapeSequence(node.left) ||
51
+ hasOctalOrNonOctalDecimalEscapeSequence(node.right)
52
+ );
53
53
  }
54
54
 
55
- return astUtils.hasOctalEscapeSequence(node.raw);
56
- }
57
-
58
- /**
59
- * Checks whether or not a node contains a octal escape sequence
60
- * @param {ASTNode} node A node to check
61
- * @returns {boolean} `true` if the node contains an octal escape sequence
62
- */
63
- function hasOctalEscapeSequence(node) {
64
- if (isConcatenation(node)) {
65
- return hasOctalEscapeSequence(node.left) || hasOctalEscapeSequence(node.right);
55
+ // No need to check TemplateLiterals – would throw parsing error
56
+ if (node.type === "Literal" && typeof node.value === "string") {
57
+ return astUtils.hasOctalOrNonOctalDecimalEscapeSequence(node.raw);
66
58
  }
67
59
 
68
- return isOctalEscapeSequence(node);
60
+ return false;
69
61
  }
70
62
 
71
63
  /**
@@ -237,7 +229,7 @@ module.exports = {
237
229
  function fixNonStringBinaryExpression(fixer, node) {
238
230
  const topBinaryExpr = getTopConcatBinaryExpression(node.parent);
239
231
 
240
- if (hasOctalEscapeSequence(topBinaryExpr)) {
232
+ if (hasOctalOrNonOctalDecimalEscapeSequence(topBinaryExpr)) {
241
233
  return null;
242
234
  }
243
235
 
@@ -282,9 +282,12 @@ module.exports = {
282
282
  description: settings.description
283
283
  },
284
284
  fix(fixer) {
285
- if (quoteOption === "backtick" && astUtils.hasOctalEscapeSequence(rawVal)) {
285
+ if (quoteOption === "backtick" && astUtils.hasOctalOrNonOctalDecimalEscapeSequence(rawVal)) {
286
286
 
287
- // An octal escape sequence in a template literal would produce syntax error, even in non-strict mode.
287
+ /*
288
+ * An octal or non-octal decimal escape sequence in a template literal would
289
+ * produce syntax error, even in non-strict mode.
290
+ */
288
291
  return null;
289
292
  }
290
293