eslint 7.20.0 → 7.24.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,64 @@
1
+ v7.24.0 - April 9, 2021
2
+
3
+ * [`0c346c8`](https://github.com/eslint/eslint/commit/0c346c87fa83c6d1184fdafb9c0748c2e15a423d) Chore: ignore `pnpm-lock.yaml` (#14303) (Nitin Kumar)
4
+ * [`f06ecdf`](https://github.com/eslint/eslint/commit/f06ecdf78b6d6f366434d73a6acfe7041d575223) Update: Add disallowTemplateShorthand option in no-implicit-coercion (#13579) (Remco Haszing)
5
+ * [`71a80e3`](https://github.com/eslint/eslint/commit/71a80e38aab2dada01b808ed43d9b0e806d863c4) Docs: fix broken links in Node.js API docs toc (#14296) (u-sho (Shouhei Uechi))
6
+ * [`bd46dc4`](https://github.com/eslint/eslint/commit/bd46dc4647faa4c3bbb5f60d4c00616a64081398) Docs: Fix incorrect reference to "braces" in arrow-parens (#14300) (emclain)
7
+ * [`0d6235e`](https://github.com/eslint/eslint/commit/0d6235ea201b8b90761ee69bb4d46ae18899c28d) Docs: update header in max-lines (#14273) (Shinigami)
8
+ * [`70c9216`](https://github.com/eslint/eslint/commit/70c92164017238e329e3a2d1654a0227b8f953f7) Docs: Update issue triage to include blocked column (#14275) (Nicholas C. Zakas)
9
+ * [`abca186`](https://github.com/eslint/eslint/commit/abca186a845200fd7728c4e5f220973e640054f9) Docs: Fix typo in suggestions section (#14293) (Kevin Partington)
10
+ * [`c4d8b0d`](https://github.com/eslint/eslint/commit/c4d8b0db62b859e721105d4bc0f4044ce346995e) Fix: no-unused-vars ignoreRestSiblings check assignments (fixes #14163) (#14264) (YeonJuan)
11
+ * [`b51d077`](https://github.com/eslint/eslint/commit/b51d0778d76c2aa27578caca3ea82c867dced3e4) Update: add ignoreNonDeclaration to no-multi-assign rule (fixes #12545) (#14185) (t-mangoe)
12
+ * [`c981fb1`](https://github.com/eslint/eslint/commit/c981fb1994cd04914042ced1980aa86b68ba7be9) Chore: Upgrade mocha to 8.3.2 (#14278) (Stephen Wade)
13
+ * [`147fc04`](https://github.com/eslint/eslint/commit/147fc045e699811fab33dddf77498324ddf7e9d6) Docs: Fix `repro:needed` label in bug report template (#14285) (Milos Djermanovic)
14
+ * [`e1cfde9`](https://github.com/eslint/eslint/commit/e1cfde93eec71a15c2df1ad660a7a6171204ba80) Docs: Update bug report template (#14276) (Nicholas C. Zakas)
15
+ * [`c85c2f1`](https://github.com/eslint/eslint/commit/c85c2f1138a9e952655f19ee780ab0c8e35431a8) Docs: Add fatal to Node.js API LintMessage type (#14251) (Brandon Mills)
16
+
17
+ v7.23.0 - March 26, 2021
18
+
19
+ * [`687ccae`](https://github.com/eslint/eslint/commit/687ccae517b8b815cf21e948f80d22e2bf118a99) Update: add option "allowInParentheses" to no-sequences (fixes #14197) (#14199) (Daniel Rentz)
20
+ * [`dbf2529`](https://github.com/eslint/eslint/commit/dbf252964d9a2b8957cfe0aed5c87a6d4a5cce24) Sponsors: Sync README with website (ESLint Jenkins)
21
+ * [`4bdf2c1`](https://github.com/eslint/eslint/commit/4bdf2c1dade27625b601080687ce95b8c229e491) Sponsors: Sync README with website (ESLint Jenkins)
22
+ * [`49d1697`](https://github.com/eslint/eslint/commit/49d16977d969070e5240074e76036f56631a90d3) Chore: Upgrade eslint-plugin-jsdoc to v25 and remove --legacy-peer-deps (#14244) (Brandon Mills)
23
+ * [`43f1685`](https://github.com/eslint/eslint/commit/43f1685356b9840e09631843ad9ccf0440a498b0) Update: `--quiet` should not supress `--max-warnings` (fixes #14202) (#14242) (Milos Djermanovic)
24
+ * [`909c727`](https://github.com/eslint/eslint/commit/909c7271b8d294bd884827ad5df02615b6ec5e82) Docs: Add valid example that shows vars in a block scope (#14230) (Ed S)
25
+ * [`28583eb`](https://github.com/eslint/eslint/commit/28583eb8ada20f32579841bec3fbd60a018d5931) Fix: no-mixed-operators false positives with `? :` (fixes #14223) (#14226) (Milos Djermanovic)
26
+ * [`a99eb2d`](https://github.com/eslint/eslint/commit/a99eb2dc2a297d16e40a9feef3956668716c4eb5) Fix: Clarify line breaks in object-curly-newline (fixes #14024) (#14063) (armin yahya)
27
+ * [`8984c91`](https://github.com/eslint/eslint/commit/8984c91372e64d1e8dd2ce21b87b80977d57bff9) Update: eslint --env-info output os info (#14059) (薛定谔的猫)
28
+ * [`2a79306`](https://github.com/eslint/eslint/commit/2a79306f71c4c80f1e3e73be2a140d07cf55c63d) Sponsors: Sync README with website (ESLint Jenkins)
29
+ * [`ebd7026`](https://github.com/eslint/eslint/commit/ebd70263f6e6fe597613d90f4b8de84710c2f3d6) Docs: Fix typo (#14225) (Greg Finley)
30
+ * [`a2013fc`](https://github.com/eslint/eslint/commit/a2013fcf996c8651bc760df21d900442828a6884) Sponsors: Sync README with website (ESLint Jenkins)
31
+
32
+ v7.22.0 - March 12, 2021
33
+
34
+ * [`3a432d8`](https://github.com/eslint/eslint/commit/3a432d82b3a5710aff7da20302fe0b94fedc46c2) Docs: Improve documentation for indent rule (#14168) (Serkan Özel)
35
+ * [`f62ec8d`](https://github.com/eslint/eslint/commit/f62ec8d30d925e70e4d0d40640857c587ac2e116) Update: throw error when fix range is invalid (#14142) (Jacob Bandes-Storch)
36
+ * [`0eecad2`](https://github.com/eslint/eslint/commit/0eecad271358f753730741fcfcb2f7cc915c1fa7) Upgrade: Update lodash in package.json to V 4.17.21 (#14159) (Basem Al-Nabulsi)
37
+ * [`5ad91aa`](https://github.com/eslint/eslint/commit/5ad91aa7df3d6bc185786e6eccd9e055fd951055) Update: report es2021 globals in no-extend-native (refs #13602) (#14177) (Milos Djermanovic)
38
+ * [`c295581`](https://github.com/eslint/eslint/commit/c295581aca4e08ec4ae8e5ee5726a6f454a3ee26) Chore: remove leftover JSDoc from lint-result-cache (#14176) (Milos Djermanovic)
39
+ * [`0d541f9`](https://github.com/eslint/eslint/commit/0d541f9d9d58966372e2055a8f69fb9483d56a4b) Chore: Reduce lodash usage (#14178) (Stephen Wade)
40
+ * [`27a67d7`](https://github.com/eslint/eslint/commit/27a67d71ffa9bbd7af02ae448844e127bcf956dc) Sponsors: Sync README with website (ESLint Jenkins)
41
+ * [`459d821`](https://github.com/eslint/eslint/commit/459d821f4a599501ceb002f9d7a5034fc45ffbb0) Chore: upgrade dependencies of browser test (#14127) (Pig Fang)
42
+ * [`ebfb63a`](https://github.com/eslint/eslint/commit/ebfb63a682004a008f2707dbad616e5ae1630b2c) Sponsors: Sync README with website (ESLint Jenkins)
43
+ * [`3ba029f`](https://github.com/eslint/eslint/commit/3ba029fbffd44068be93254890fc2aec3e92c212) Docs: Remove Extraneous Dash (#14164) (Danny Hurlburt)
44
+ * [`6f4540e`](https://github.com/eslint/eslint/commit/6f4540ea7ea39775906526506fd7abd7ea97610c) Sponsors: Sync README with website (ESLint Jenkins)
45
+ * [`ddf361c`](https://github.com/eslint/eslint/commit/ddf361ca2a2a01a9974f421e5f62270df282d0e8) Docs: Fix Formatting (#14154) (Danny Hurlburt)
46
+ * [`c0d2ac1`](https://github.com/eslint/eslint/commit/c0d2ac16f8f9c75c62c78e9fe6a24a25ba0d7828) Sponsors: Sync README with website (ESLint Jenkins)
47
+ * [`a8df03e`](https://github.com/eslint/eslint/commit/a8df03efe3bc47665d2112c2cdd5bead337d475d) Docs: Clarify triage process (#14117) (Nicholas C. Zakas)
48
+
49
+ v7.21.0 - February 27, 2021
50
+
51
+ * [`3cd5440`](https://github.com/eslint/eslint/commit/3cd5440b94d5fa4f11a09f50b685f6150f0c2d41) Upgrade: @eslint/eslintrc to 0.4.0 (#14147) (Brandon Mills)
52
+ * [`c0b8c71`](https://github.com/eslint/eslint/commit/c0b8c71df4d0b3f54b20587432d9133741985d5c) Upgrade: Puppeteer to 7.1.0 (#14122) (Tim van der Lippe)
53
+ * [`08ae31e`](https://github.com/eslint/eslint/commit/08ae31e539e381cd0eabf6393fa5c20f1d59125f) New: Implement cacheStrategy (refs eslint/rfcs#63) (#14119) (Manu Chambon)
54
+ * [`5e51fd2`](https://github.com/eslint/eslint/commit/5e51fd28dc773c11c924450d24088f97f2824f00) Update: do not ignore symbolic links (fixes #13551, fixes #13615) (#14126) (Pig Fang)
55
+ * [`87c43a5`](https://github.com/eslint/eslint/commit/87c43a5d7ea2018cffd6d9b5c431ecb60caaf0d6) Chore: improve a few comments and fix typos (#14125) (Tobias Nießen)
56
+ * [`e19c51e`](https://github.com/eslint/eslint/commit/e19c51ea2ef2cf666d94218c66f6b223bb2e9dae) Sponsors: Sync README with website (ESLint Jenkins)
57
+ * [`b8aea99`](https://github.com/eslint/eslint/commit/b8aea9988b6451b6a05af4f3ede8d6ed5c1d9926) Fix: pluralize 'line' to 'lines' in max-lines-per-function description (#14115) (Trevin Hofmann)
58
+ * [`f5b53e2`](https://github.com/eslint/eslint/commit/f5b53e285ab5286ea382d73b379b820f649c20d0) Sponsors: Sync README with website (ESLint Jenkins)
59
+ * [`eee1213`](https://github.com/eslint/eslint/commit/eee12134ce0956e9f825c1630776b1731551a948) Sponsors: Sync README with website (ESLint Jenkins)
60
+ * [`5c4d7ea`](https://github.com/eslint/eslint/commit/5c4d7ea8d2e8d137c42b918dc99a84b4a5fed9b3) Sponsors: Sync README with website (ESLint Jenkins)
61
+
1
62
  v7.20.0 - February 12, 2021
2
63
 
3
64
  * [`f4ac3b0`](https://github.com/eslint/eslint/commit/f4ac3b0e7072fbd3c14e9c64ff0c2c255a4eb730) Docs: fix sibling selector descriptions (#14099) (Milos Djermanovic)
package/README.md CHANGED
@@ -281,9 +281,9 @@ The following companies, organizations, and individuals support ESLint's ongoing
281
281
  <!--sponsorsstart-->
282
282
  <h3>Platinum Sponsors</h3>
283
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>
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://opensource.microsoft.com"><img src="https://avatars.githubusercontent.com/u/6154722?v=4" alt="Microsoft" height="96"></a> <a href="https://substack.com/"><img src="https://avatars.githubusercontent.com/u/53023767?v=4" alt="Substack" height="96"></a></p><h3>Silver Sponsors</h3>
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></p><h3>Bronze Sponsors</h3>
286
+ <p><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>
287
287
  <!--sponsorsend-->
288
288
 
289
289
  ## <a name="technology-sponsors"></a>Technology Sponsors
@@ -24,6 +24,7 @@ module.exports = {
24
24
  */
25
25
  cacheLocation: "",
26
26
  cacheFile: ".eslintcache",
27
+ cacheStrategy: "metadata",
27
28
  fix: false,
28
29
  allowInlineConfig: true,
29
30
  reportUnusedDisableDirectives: void 0,
@@ -589,7 +589,7 @@ class CLIEngine {
589
589
  ignore: options.ignore
590
590
  });
591
591
  const lintResultCache =
592
- options.cache ? new LintResultCache(cacheFilePath) : null;
592
+ options.cache ? new LintResultCache(cacheFilePath, options.cacheStrategy) : null;
593
593
  const linter = new Linter({ cwd: options.cwd });
594
594
 
595
595
  /** @type {ConfigArray[]} */
@@ -433,9 +433,14 @@ class FileEnumerator {
433
433
  // Enumerate the files of this directory.
434
434
  for (const entry of readdirSafeSync(directoryPath)) {
435
435
  const filePath = path.join(directoryPath, entry.name);
436
+ const fileInfo = entry.isSymbolicLink() ? statSafeSync(filePath) : entry;
437
+
438
+ if (!fileInfo) {
439
+ continue;
440
+ }
436
441
 
437
442
  // Check if the file is matched.
438
- if (entry.isFile()) {
443
+ if (fileInfo.isFile()) {
439
444
  if (!config) {
440
445
  config = configArrayFactory.getConfigArrayForFile(
441
446
  filePath,
@@ -471,7 +476,7 @@ class FileEnumerator {
471
476
  }
472
477
 
473
478
  // Dive into the sub directory.
474
- } else if (options.recursive && entry.isDirectory()) {
479
+ } else if (options.recursive && fileInfo.isDirectory()) {
475
480
  if (!config) {
476
481
  config = configArrayFactory.getConfigArrayForFile(
477
482
  filePath,
@@ -72,7 +72,7 @@ function renderMessages(messages, parentIndex, rulesMeta) {
72
72
  * @param {Object} message Message.
73
73
  * @returns {string} HTML (table row) describing a message.
74
74
  */
75
- return lodash.map(messages, message => {
75
+ return messages.map(message => {
76
76
  const lineNumber = message.line || 0;
77
77
  const columnNumber = message.column || 0;
78
78
  let ruleUrl;
@@ -103,7 +103,7 @@ function renderMessages(messages, parentIndex, rulesMeta) {
103
103
  * @returns {string} HTML string describing the results.
104
104
  */
105
105
  function renderResults(results, rulesMeta) {
106
- return lodash.map(results, (result, index) => resultTemplate({
106
+ return results.map((result, index) => resultTemplate({
107
107
  index,
108
108
  color: renderColor(result.errorCount, result.warningCount),
109
109
  filePath: result.filePath,
@@ -15,6 +15,8 @@ const stringify = require("json-stable-stringify-without-jsonify");
15
15
  const pkg = require("../../package.json");
16
16
  const hash = require("./hash");
17
17
 
18
+ const debug = require("debug")("eslint:lint-result-cache");
19
+
18
20
  //-----------------------------------------------------------------------------
19
21
  // Helpers
20
22
  //-----------------------------------------------------------------------------
@@ -22,6 +24,22 @@ const hash = require("./hash");
22
24
  const configHashCache = new WeakMap();
23
25
  const nodeVersion = process && process.version;
24
26
 
27
+ const validCacheStrategies = ["metadata", "content"];
28
+ const invalidCacheStrategyErrorMessage = `Cache strategy must be one of: ${validCacheStrategies
29
+ .map(strategy => `"${strategy}"`)
30
+ .join(", ")}`;
31
+
32
+ /**
33
+ * Tests whether a provided cacheStrategy is valid
34
+ * @param {string} cacheStrategy The cache strategy to use
35
+ * @returns {boolean} true if `cacheStrategy` is one of `validCacheStrategies`; false otherwise
36
+ */
37
+ function isValidCacheStrategy(cacheStrategy) {
38
+ return (
39
+ validCacheStrategies.indexOf(cacheStrategy) !== -1
40
+ );
41
+ }
42
+
25
43
  /**
26
44
  * Calculates the hash of the config
27
45
  * @param {ConfigArray} config The config.
@@ -49,12 +67,30 @@ class LintResultCache {
49
67
  /**
50
68
  * Creates a new LintResultCache instance.
51
69
  * @param {string} cacheFileLocation The cache file location.
52
- * configuration lookup by file path).
70
+ * @param {"metadata" | "content"} cacheStrategy The cache strategy to use.
53
71
  */
54
- constructor(cacheFileLocation) {
72
+ constructor(cacheFileLocation, cacheStrategy) {
55
73
  assert(cacheFileLocation, "Cache file location is required");
56
-
57
- this.fileEntryCache = fileEntryCache.create(cacheFileLocation);
74
+ assert(cacheStrategy, "Cache strategy is required");
75
+ assert(
76
+ isValidCacheStrategy(cacheStrategy),
77
+ invalidCacheStrategyErrorMessage
78
+ );
79
+
80
+ debug(`Caching results to ${cacheFileLocation}`);
81
+
82
+ const useChecksum = cacheStrategy === "content";
83
+
84
+ debug(
85
+ `Using "${cacheStrategy}" strategy to detect changes`
86
+ );
87
+
88
+ this.fileEntryCache = fileEntryCache.create(
89
+ cacheFileLocation,
90
+ void 0,
91
+ useChecksum
92
+ );
93
+ this.cacheFileLocation = cacheFileLocation;
58
94
  }
59
95
 
60
96
  /**
@@ -76,17 +112,28 @@ class LintResultCache {
76
112
  * was previously linted
77
113
  * If any of these are not true, we will not reuse the lint results.
78
114
  */
79
-
80
115
  const fileDescriptor = this.fileEntryCache.getFileDescriptor(filePath);
81
116
  const hashOfConfig = hashOfConfigFor(config);
82
- const changed = fileDescriptor.changed || fileDescriptor.meta.hashOfConfig !== hashOfConfig;
117
+ const changed =
118
+ fileDescriptor.changed ||
119
+ fileDescriptor.meta.hashOfConfig !== hashOfConfig;
120
+
121
+ if (fileDescriptor.notFound) {
122
+ debug(`File not found on the file system: ${filePath}`);
123
+ return null;
124
+ }
83
125
 
84
- if (fileDescriptor.notFound || changed) {
126
+ if (changed) {
127
+ debug(`Cache entry not found or no longer valid: ${filePath}`);
85
128
  return null;
86
129
  }
87
130
 
88
131
  // If source is present but null, need to reread the file from the filesystem.
89
- if (fileDescriptor.meta.results && fileDescriptor.meta.results.source === null) {
132
+ if (
133
+ fileDescriptor.meta.results &&
134
+ fileDescriptor.meta.results.source === null
135
+ ) {
136
+ debug(`Rereading cached result source from filesystem: ${filePath}`);
90
137
  fileDescriptor.meta.results.source = fs.readFileSync(filePath, "utf-8");
91
138
  }
92
139
 
@@ -112,6 +159,7 @@ class LintResultCache {
112
159
  const fileDescriptor = this.fileEntryCache.getFileDescriptor(filePath);
113
160
 
114
161
  if (fileDescriptor && !fileDescriptor.notFound) {
162
+ debug(`Updating cached result: ${filePath}`);
115
163
 
116
164
  // Serialize the result, except that we want to remove the file source if present.
117
165
  const resultToSerialize = Object.assign({}, result);
@@ -135,6 +183,7 @@ class LintResultCache {
135
183
  * @returns {void}
136
184
  */
137
185
  reconcile() {
186
+ debug(`Persisting cached results: ${this.cacheFileLocation}`);
138
187
  this.fileEntryCache.reconcile();
139
188
  }
140
189
  }
package/lib/cli.js CHANGED
@@ -32,6 +32,7 @@ const debug = require("debug")("eslint:cli");
32
32
  /** @typedef {import("./eslint/eslint").ESLintOptions} ESLintOptions */
33
33
  /** @typedef {import("./eslint/eslint").LintMessage} LintMessage */
34
34
  /** @typedef {import("./eslint/eslint").LintResult} LintResult */
35
+ /** @typedef {import("./options").ParsedCLIOptions} ParsedCLIOptions */
35
36
 
36
37
  //------------------------------------------------------------------------------
37
38
  // Helpers
@@ -54,7 +55,7 @@ function quietFixPredicate(message) {
54
55
 
55
56
  /**
56
57
  * Translates the CLI options into the options expected by the CLIEngine.
57
- * @param {Object} cliOptions The CLI options to translate.
58
+ * @param {ParsedCLIOptions} cliOptions The CLI options to translate.
58
59
  * @returns {ESLintOptions} The options object for the CLIEngine.
59
60
  * @private
60
61
  */
@@ -62,6 +63,7 @@ function translateOptions({
62
63
  cache,
63
64
  cacheFile,
64
65
  cacheLocation,
66
+ cacheStrategy,
65
67
  config,
66
68
  env,
67
69
  errorOnUnmatchedPattern,
@@ -88,6 +90,7 @@ function translateOptions({
88
90
  allowInlineConfig: inlineConfig,
89
91
  cache,
90
92
  cacheLocation: cacheLocation || cacheFile,
93
+ cacheStrategy,
91
94
  errorOnUnmatchedPattern,
92
95
  extensions: ext,
93
96
  fix: (fix || fixDryRun) && (quiet ? quietFixPredicate : true),
@@ -219,6 +222,8 @@ const cli = {
219
222
  if (Array.isArray(args)) {
220
223
  debug("CLI args: %o", args.slice(2));
221
224
  }
225
+
226
+ /** @type {ParsedCLIOptions} */
222
227
  let options;
223
228
 
224
229
  try {
@@ -299,12 +304,16 @@ const cli = {
299
304
  await ESLint.outputFixes(results);
300
305
  }
301
306
 
307
+ let resultsToPrint = results;
308
+
302
309
  if (options.quiet) {
303
310
  debug("Quiet mode enabled - filtering out warnings");
304
- results = ESLint.getErrorResults(results);
311
+ resultsToPrint = ESLint.getErrorResults(resultsToPrint);
305
312
  }
306
313
 
307
- if (await printResults(engine, results, options.format, options.outputFile)) {
314
+ if (await printResults(engine, resultsToPrint, options.format, options.outputFile)) {
315
+
316
+ // Errors and warnings from the original unfiltered results should determine the exit code
308
317
  const { errorCount, warningCount } = countErrors(results);
309
318
  const tooManyWarnings =
310
319
  options.maxWarnings >= 0 && warningCount > options.maxWarnings;
@@ -43,6 +43,7 @@ const { version } = require("../../package.json");
43
43
  * @property {ConfigData} [baseConfig] Base config object, extended by all configs used with this instance
44
44
  * @property {boolean} [cache] Enable result caching.
45
45
  * @property {string} [cacheLocation] The cache file to use instead of .eslintcache.
46
+ * @property {"metadata" | "content"} [cacheStrategy] The strategy used to detect changed files.
46
47
  * @property {string} [cwd] The value to use for the current working directory.
47
48
  * @property {boolean} [errorOnUnmatchedPattern] If `false` then `ESLint#lintFiles()` doesn't throw even if no target files found. Defaults to `true`.
48
49
  * @property {string[]} [extensions] An array of file extensions to check.
@@ -157,6 +158,7 @@ function processOptions({
157
158
  baseConfig = null,
158
159
  cache = false,
159
160
  cacheLocation = ".eslintcache",
161
+ cacheStrategy = "metadata",
160
162
  cwd = process.cwd(),
161
163
  errorOnUnmatchedPattern = true,
162
164
  extensions = null, // ← should be null by default because if it's an array then it suppresses RFC20 feature.
@@ -216,6 +218,12 @@ function processOptions({
216
218
  if (!isNonEmptyString(cacheLocation)) {
217
219
  errors.push("'cacheLocation' must be a non-empty string.");
218
220
  }
221
+ if (
222
+ cacheStrategy !== "metadata" &&
223
+ cacheStrategy !== "content"
224
+ ) {
225
+ errors.push("'cacheStrategy' must be any of \"metadata\", \"content\".");
226
+ }
219
227
  if (!isNonEmptyString(cwd) || !path.isAbsolute(cwd)) {
220
228
  errors.push("'cwd' must be an absolute path.");
221
229
  }
@@ -284,6 +292,7 @@ function processOptions({
284
292
  baseConfig,
285
293
  cache,
286
294
  cacheLocation,
295
+ cacheStrategy,
287
296
  configFile: overrideConfigFile,
288
297
  cwd,
289
298
  errorOnUnmatchedPattern,
@@ -115,6 +115,17 @@ function normalizeReportLoc(descriptor) {
115
115
  return descriptor.node.loc;
116
116
  }
117
117
 
118
+ /**
119
+ * Check that a fix has a valid range.
120
+ * @param {Fix|null} fix The fix to validate.
121
+ * @returns {void}
122
+ */
123
+ function assertValidFix(fix) {
124
+ if (fix) {
125
+ assert(fix.range && typeof fix.range[0] === "number" && typeof fix.range[1] === "number", `Fix has invalid range: ${JSON.stringify(fix, null, 2)}`);
126
+ }
127
+ }
128
+
118
129
  /**
119
130
  * Compares items in a fixes array by range.
120
131
  * @param {Fix} a The first message.
@@ -133,6 +144,10 @@ function compareFixesByRange(a, b) {
133
144
  * @returns {{text: string, range: number[]}} The merged fixes
134
145
  */
135
146
  function mergeFixes(fixes, sourceCode) {
147
+ for (const fix of fixes) {
148
+ assertValidFix(fix);
149
+ }
150
+
136
151
  if (fixes.length === 0) {
137
152
  return null;
138
153
  }
@@ -181,6 +196,8 @@ function normalizeFixes(descriptor, sourceCode) {
181
196
  if (fix && Symbol.iterator in fix) {
182
197
  return mergeFixes(Array.from(fix), sourceCode);
183
198
  }
199
+
200
+ assertValidFix(fix);
184
201
  return fix;
185
202
  }
186
203
 
package/lib/options.js CHANGED
@@ -11,6 +11,53 @@
11
11
 
12
12
  const optionator = require("optionator");
13
13
 
14
+ //------------------------------------------------------------------------------
15
+ // Typedefs
16
+ //------------------------------------------------------------------------------
17
+
18
+ /**
19
+ * The options object parsed by Optionator.
20
+ * @typedef {Object} ParsedCLIOptions
21
+ * @property {boolean} cache Only check changed files
22
+ * @property {string} cacheFile Path to the cache file. Deprecated: use --cache-location
23
+ * @property {string} [cacheLocation] Path to the cache file or directory
24
+ * @property {"metadata" | "content"} cacheStrategy Strategy to use for detecting changed files in the cache
25
+ * @property {boolean} [color] Force enabling/disabling of color
26
+ * @property {string} [config] Use this configuration, overriding .eslintrc.* config options if present
27
+ * @property {boolean} debug Output debugging information
28
+ * @property {string[]} [env] Specify environments
29
+ * @property {boolean} envInfo Output execution environment information
30
+ * @property {boolean} errorOnUnmatchedPattern Prevent errors when pattern is unmatched
31
+ * @property {boolean} eslintrc Disable use of configuration from .eslintrc.*
32
+ * @property {string[]} [ext] Specify JavaScript file extensions
33
+ * @property {boolean} fix Automatically fix problems
34
+ * @property {boolean} fixDryRun Automatically fix problems without saving the changes to the file system
35
+ * @property {("problem" | "suggestion" | "layout")[]} [fixType] Specify the types of fixes to apply (problem, suggestion, layout)
36
+ * @property {string} format Use a specific output format
37
+ * @property {string[]} [global] Define global variables
38
+ * @property {boolean} [help] Show help
39
+ * @property {boolean} ignore Disable use of ignore files and patterns
40
+ * @property {string} [ignorePath] Specify path of ignore file
41
+ * @property {string[]} [ignorePattern] Pattern of files to ignore (in addition to those in .eslintignore)
42
+ * @property {boolean} init Run config initialization wizard
43
+ * @property {boolean} inlineConfig Prevent comments from changing config or rules
44
+ * @property {number} maxWarnings Number of warnings to trigger nonzero exit code
45
+ * @property {string} [outputFile] Specify file to write report to
46
+ * @property {string} [parser] Specify the parser to be used
47
+ * @property {Object} [parserOptions] Specify parser options
48
+ * @property {string[]} [plugin] Specify plugins
49
+ * @property {string} [printConfig] Print the configuration for the given file
50
+ * @property {boolean | undefined} reportUnusedDisableDirectives Adds reported errors for unused eslint-disable directives
51
+ * @property {string} [resolvePluginsRelativeTo] A folder where plugins should be resolved from, CWD by default
52
+ * @property {Object} [rule] Specify rules
53
+ * @property {string[]} [rulesdir] Use additional rules from this directory
54
+ * @property {boolean} stdin Lint code provided on <STDIN>
55
+ * @property {string} [stdinFilename] Specify filename to process STDIN as
56
+ * @property {boolean} quiet Report errors only
57
+ * @property {boolean} [version] Output the version number
58
+ * @property {string[]} _ Positional filenames or patterns
59
+ */
60
+
14
61
  //------------------------------------------------------------------------------
15
62
  // Initialization and Public Interface
16
63
  //------------------------------------------------------------------------------
@@ -214,6 +261,14 @@ module.exports = optionator({
214
261
  type: "path::String",
215
262
  description: "Path to the cache file or directory"
216
263
  },
264
+ {
265
+ option: "cache-strategy",
266
+ dependsOn: ["cache"],
267
+ type: "String",
268
+ default: "metadata",
269
+ enum: ["metadata", "content"],
270
+ description: "Strategy to use for detecting changed files in the cache"
271
+ },
217
272
  {
218
273
  heading: "Miscellaneous"
219
274
  },
@@ -427,12 +427,12 @@ class RuleTester {
427
427
  scenarioErrors = [],
428
428
  linter = this.linter;
429
429
 
430
- if (lodash.isNil(test) || typeof test !== "object") {
430
+ if (!test || typeof test !== "object") {
431
431
  throw new TypeError(`Test Scenarios for rule ${ruleName} : Could not find test scenario object`);
432
432
  }
433
433
 
434
434
  requiredScenarios.forEach(scenarioType => {
435
- if (lodash.isNil(test[scenarioType])) {
435
+ if (!test[scenarioType]) {
436
436
  scenarioErrors.push(`Could not find any ${scenarioType} test scenarios`);
437
437
  }
438
438
  });
@@ -54,7 +54,7 @@ module.exports = {
54
54
  },
55
55
  LF = "\n",
56
56
  CRLF = `\r${LF}`,
57
- endsWithNewline = lodash.endsWith(src, LF);
57
+ endsWithNewline = src.endsWith(LF);
58
58
 
59
59
  /*
60
60
  * Empty source is always valid: No content in file so we don't
@@ -954,7 +954,7 @@ module.exports = {
954
954
  }
955
955
 
956
956
  /**
957
- * Checks wether a return statement is wrapped in ()
957
+ * Checks whether a return statement is wrapped in ()
958
958
  * @param {ASTNode} node node to examine
959
959
  * @returns {boolean} the result
960
960
  */
@@ -8,8 +8,7 @@
8
8
  // Requirements
9
9
  //------------------------------------------------------------------------------
10
10
 
11
- const lodash = require("lodash"),
12
- astUtils = require("./utils/ast-utils");
11
+ const astUtils = require("./utils/ast-utils");
13
12
 
14
13
  //------------------------------------------------------------------------------
15
14
  // Helpers
@@ -347,7 +346,7 @@ module.exports = {
347
346
  const nextTokenOrComment = sourceCode.getTokenAfter(token, { includeComments: true });
348
347
 
349
348
  // check for newline before
350
- if (!exceptionStartAllowed && before && !lodash.includes(commentAndEmptyLines, prevLineNum) &&
349
+ if (!exceptionStartAllowed && before && !commentAndEmptyLines.includes(prevLineNum) &&
351
350
  !(astUtils.isCommentToken(previousTokenOrComment) && astUtils.isTokenOnSameLine(previousTokenOrComment, token))) {
352
351
  const lineStart = token.range[0] - token.loc.start.column;
353
352
  const range = [lineStart, lineStart];
@@ -362,7 +361,7 @@ module.exports = {
362
361
  }
363
362
 
364
363
  // check for newline after
365
- if (!exceptionEndAllowed && after && !lodash.includes(commentAndEmptyLines, nextLineNum) &&
364
+ if (!exceptionEndAllowed && after && !commentAndEmptyLines.includes(nextLineNum) &&
366
365
  !(astUtils.isCommentToken(nextTokenOrComment) && astUtils.isTokenOnSameLine(token, nextTokenOrComment))) {
367
366
  context.report({
368
367
  node: token,
@@ -71,7 +71,7 @@ module.exports = {
71
71
  type: "suggestion",
72
72
 
73
73
  docs: {
74
- description: "enforce a maximum number of line of code in a function",
74
+ description: "enforce a maximum number of lines of code in a function",
75
75
  category: "Stylistic Issues",
76
76
  recommended: false,
77
77
  url: "https://eslint.org/docs/rules/max-lines-per-function"
@@ -151,7 +151,7 @@ module.exports = {
151
151
  );
152
152
 
153
153
  lines = lines.filter(
154
- l => !lodash.includes(commentLines, l.lineNumber)
154
+ l => !commentLines.includes(l.lineNumber)
155
155
  );
156
156
  }
157
157
 
@@ -24,6 +24,7 @@ function parseOptions(options) {
24
24
  boolean: "boolean" in options ? options.boolean : true,
25
25
  number: "number" in options ? options.number : true,
26
26
  string: "string" in options ? options.string : true,
27
+ disallowTemplateShorthand: "disallowTemplateShorthand" in options ? options.disallowTemplateShorthand : false,
27
28
  allow: options.allow || []
28
29
  };
29
30
  }
@@ -180,6 +181,10 @@ module.exports = {
180
181
  type: "boolean",
181
182
  default: true
182
183
  },
184
+ disallowTemplateShorthand: {
185
+ type: "boolean",
186
+ default: false
187
+ },
183
188
  allow: {
184
189
  type: "array",
185
190
  items: {
@@ -299,6 +304,38 @@ module.exports = {
299
304
 
300
305
  report(node, recommendation, true);
301
306
  }
307
+ },
308
+
309
+ TemplateLiteral(node) {
310
+ if (!options.disallowTemplateShorthand) {
311
+ return;
312
+ }
313
+
314
+ // tag`${foo}`
315
+ if (node.parent.type === "TaggedTemplateExpression") {
316
+ return;
317
+ }
318
+
319
+ // `` or `${foo}${bar}`
320
+ if (node.expressions.length !== 1) {
321
+ return;
322
+ }
323
+
324
+
325
+ // `prefix${foo}`
326
+ if (node.quasis[0].value.cooked !== "") {
327
+ return;
328
+ }
329
+
330
+ // `${foo}postfix`
331
+ if (node.quasis[1].value.cooked !== "") {
332
+ return;
333
+ }
334
+
335
+ const code = sourceCode.getText(node.expressions[0]);
336
+ const recommendation = `String(${code})`;
337
+
338
+ report(node, recommendation, true);
302
339
  }
303
340
  };
304
341
  }
@@ -105,9 +105,9 @@ module.exports = {
105
105
  }
106
106
 
107
107
  /**
108
- * Converts an integer to to an object containing the the integer's coefficient and order of magnitude
108
+ * Converts an integer to to an object containing the integer's coefficient and order of magnitude
109
109
  * @param {string} stringInteger the string representation of the integer being converted
110
- * @returns {Object} the object containing the the integer's coefficient and order of magnitude
110
+ * @returns {Object} the object containing the integer's coefficient and order of magnitude
111
111
  */
112
112
  function normalizeInteger(stringInteger) {
113
113
  const significantDigits = removeTrailingZeros(removeLeadingZeros(stringInteger));
@@ -120,9 +120,9 @@ module.exports = {
120
120
 
121
121
  /**
122
122
  *
123
- * Converts a float to to an object containing the the floats's coefficient and order of magnitude
123
+ * Converts a float to to an object containing the floats's coefficient and order of magnitude
124
124
  * @param {string} stringFloat the string representation of the float being converted
125
- * @returns {Object} the object containing the the integer's coefficient and order of magnitude
125
+ * @returns {Object} the object containing the integer's coefficient and order of magnitude
126
126
  */
127
127
  function normalizeFloat(stringFloat) {
128
128
  const trimmedFloat = removeLeadingZeros(stringFloat);
@@ -161,17 +161,6 @@ module.exports = {
161
161
  );
162
162
  }
163
163
 
164
- /**
165
- * Checks whether the operator of a given node is mixed with a
166
- * conditional expression.
167
- * @param {ASTNode} node A node to check. This is a conditional
168
- * expression node
169
- * @returns {boolean} `true` if the node was mixed.
170
- */
171
- function isMixedWithConditionalParent(node) {
172
- return !astUtils.isParenthesised(sourceCode, node) && !astUtils.isParenthesised(sourceCode, node.test);
173
- }
174
-
175
164
  /**
176
165
  * Gets the operator token of a given node.
177
166
  * @param {ASTNode} node A node to check. This is a BinaryExpression
@@ -220,19 +209,13 @@ module.exports = {
220
209
  * @returns {void}
221
210
  */
222
211
  function check(node) {
223
- if (TARGET_NODE_TYPE.test(node.parent.type)) {
224
- if (node.parent.type === "ConditionalExpression" && !shouldIgnore(node) && isMixedWithConditionalParent(node.parent)) {
225
- reportBothOperators(node);
226
- } else {
227
- if (TARGET_NODE_TYPE.test(node.parent.type) &&
228
- isMixedWithParent(node) &&
229
- !shouldIgnore(node)
230
- ) {
231
- reportBothOperators(node);
232
- }
233
- }
212
+ if (
213
+ TARGET_NODE_TYPE.test(node.parent.type) &&
214
+ isMixedWithParent(node) &&
215
+ !shouldIgnore(node)
216
+ ) {
217
+ reportBothOperators(node);
234
218
  }
235
-
236
219
  }
237
220
 
238
221
  return {
@@ -21,7 +21,16 @@ module.exports = {
21
21
  url: "https://eslint.org/docs/rules/no-multi-assign"
22
22
  },
23
23
 
24
- schema: [],
24
+ schema: [{
25
+ type: "object",
26
+ properties: {
27
+ ignoreNonDeclaration: {
28
+ type: "boolean",
29
+ default: false
30
+ }
31
+ },
32
+ additionalProperties: false
33
+ }],
25
34
 
26
35
  messages: {
27
36
  unexpectedChain: "Unexpected chained assignment."
@@ -33,10 +42,14 @@ module.exports = {
33
42
  //--------------------------------------------------------------------------
34
43
  // Public
35
44
  //--------------------------------------------------------------------------
45
+ const options = context.options[0] || {
46
+ ignoreNonDeclaration: false
47
+ };
48
+ const targetParent = options.ignoreNonDeclaration ? ["VariableDeclarator"] : ["AssignmentExpression", "VariableDeclarator"];
36
49
 
37
50
  return {
38
51
  AssignmentExpression(node) {
39
- if (["AssignmentExpression", "VariableDeclarator"].indexOf(node.parent.type) !== -1) {
52
+ if (targetParent.indexOf(node.parent.type) !== -1) {
40
53
  context.report({
41
54
  node,
42
55
  messageId: "unexpectedChain"
@@ -11,6 +11,14 @@
11
11
 
12
12
  const astUtils = require("./utils/ast-utils");
13
13
 
14
+ //------------------------------------------------------------------------------
15
+ // Helpers
16
+ //------------------------------------------------------------------------------
17
+
18
+ const DEFAULT_OPTIONS = {
19
+ allowInParentheses: true
20
+ };
21
+
14
22
  //------------------------------------------------------------------------------
15
23
  // Rule Definition
16
24
  //------------------------------------------------------------------------------
@@ -26,7 +34,15 @@ module.exports = {
26
34
  url: "https://eslint.org/docs/rules/no-sequences"
27
35
  },
28
36
 
29
- schema: [],
37
+ schema: [{
38
+ properties: {
39
+ allowInParentheses: {
40
+ type: "boolean",
41
+ default: true
42
+ }
43
+ },
44
+ additionalProperties: false
45
+ }],
30
46
 
31
47
  messages: {
32
48
  unexpectedCommaExpression: "Unexpected use of comma operator."
@@ -34,6 +50,7 @@ module.exports = {
34
50
  },
35
51
 
36
52
  create(context) {
53
+ const options = Object.assign({}, DEFAULT_OPTIONS, context.options[0]);
37
54
  const sourceCode = context.getSourceCode();
38
55
 
39
56
  /**
@@ -99,13 +116,15 @@ module.exports = {
99
116
  }
100
117
 
101
118
  // Wrapping a sequence in extra parens indicates intent
102
- if (requiresExtraParens(node)) {
103
- if (isParenthesisedTwice(node)) {
104
- return;
105
- }
106
- } else {
107
- if (isParenthesised(node)) {
108
- return;
119
+ if (options.allowInParentheses) {
120
+ if (requiresExtraParens(node)) {
121
+ if (isParenthesisedTwice(node)) {
122
+ return;
123
+ }
124
+ } else {
125
+ if (isParenthesised(node)) {
126
+ return;
127
+ }
109
128
  }
110
129
  }
111
130
 
@@ -196,6 +196,17 @@ module.exports = {
196
196
 
197
197
  }
198
198
 
199
+ /**
200
+ * Checks whether a node is a sibling of the rest property or not.
201
+ * @param {ASTNode} node a node to check
202
+ * @returns {boolean} True if the node is a sibling of the rest property, otherwise false.
203
+ */
204
+ function hasRestSibling(node) {
205
+ return node.type === "Property" &&
206
+ node.parent.type === "ObjectPattern" &&
207
+ REST_PROPERTY_TYPE.test(node.parent.properties[node.parent.properties.length - 1].type);
208
+ }
209
+
199
210
  /**
200
211
  * Determines if a variable has a sibling rest property
201
212
  * @param {Variable} variable eslint-scope variable object.
@@ -204,16 +215,10 @@ module.exports = {
204
215
  */
205
216
  function hasRestSpreadSibling(variable) {
206
217
  if (config.ignoreRestSiblings) {
207
- return variable.defs.some(def => {
208
- const propertyNode = def.name.parent;
209
- const patternNode = propertyNode.parent;
210
-
211
- return (
212
- propertyNode.type === "Property" &&
213
- patternNode.type === "ObjectPattern" &&
214
- REST_PROPERTY_TYPE.test(patternNode.properties[patternNode.properties.length - 1].type)
215
- );
216
- });
218
+ const hasRestSiblingDefinition = variable.defs.some(def => hasRestSibling(def.name.parent));
219
+ const hasRestSiblingReference = variable.references.some(ref => hasRestSibling(ref.identifier.parent));
220
+
221
+ return hasRestSiblingDefinition || hasRestSiblingReference;
217
222
  }
218
223
 
219
224
  return false;
@@ -82,7 +82,7 @@ function normalizeOptionValue(value) {
82
82
  function normalizeOptions(options) {
83
83
  const isNodeSpecificOption = lodash.overSome([lodash.isPlainObject, lodash.isString]);
84
84
 
85
- if (lodash.isPlainObject(options) && lodash.some(options, isNodeSpecificOption)) {
85
+ if (lodash.isPlainObject(options) && Object.values(options).some(isNodeSpecificOption)) {
86
86
  return {
87
87
  ObjectExpression: normalizeOptionValue(options.ObjectExpression),
88
88
  ObjectPattern: normalizeOptionValue(options.ObjectPattern),
@@ -134,7 +134,7 @@ module.exports = {
134
134
  type: "layout",
135
135
 
136
136
  docs: {
137
- description: "enforce consistent line breaks inside braces",
137
+ description: "enforce consistent line breaks after opening and before closing braces",
138
138
  category: "Stylistic Issues",
139
139
  recommended: false,
140
140
  url: "https://eslint.org/docs/rules/object-curly-newline"
@@ -168,7 +168,7 @@ module.exports = {
168
168
  * Assignment expression is not fixed.
169
169
  * Array destructuring is not fixed.
170
170
  * Renamed property is not fixed.
171
- * @param {ASTNode} node the the node to evaluate
171
+ * @param {ASTNode} node the node to evaluate
172
172
  * @returns {boolean} whether or not the node should be fixed
173
173
  */
174
174
  function shouldFix(node) {
@@ -101,7 +101,7 @@ module.exports = {
101
101
  }
102
102
 
103
103
  /**
104
- * Checks the the given `CallExpression` node for `.indexOf(NaN)` and `.lastIndexOf(NaN)`.
104
+ * Checks the given `CallExpression` node for `.indexOf(NaN)` and `.lastIndexOf(NaN)`.
105
105
  * @param {ASTNode} node The node to check.
106
106
  * @returns {void}
107
107
  */
@@ -11,7 +11,7 @@
11
11
 
12
12
  const path = require("path");
13
13
  const spawn = require("cross-spawn");
14
- const { isEmpty } = require("lodash");
14
+ const os = require("os");
15
15
  const log = require("../shared/logging");
16
16
  const packageJson = require("../../package.json");
17
17
 
@@ -107,7 +107,7 @@ function environment() {
107
107
  * Checking globally returns an empty JSON object, while local checks
108
108
  * include the name and version of the local project.
109
109
  */
110
- if (isEmpty(parsedStdout) || !(parsedStdout.dependencies && parsedStdout.dependencies.eslint)) {
110
+ if (Object.keys(parsedStdout).length === 0 || !(parsedStdout.dependencies && parsedStdout.dependencies.eslint)) {
111
111
  return "Not found";
112
112
  }
113
113
 
@@ -141,7 +141,8 @@ function environment() {
141
141
  `Node version: ${getBinVersion("node")}`,
142
142
  `npm version: ${getBinVersion("npm")}`,
143
143
  `Local ESLint version: ${getNpmPackageVersion("eslint", { global: false })}`,
144
- `Global ESLint version: ${getNpmPackageVersion("eslint", { global: true })}`
144
+ `Global ESLint version: ${getNpmPackageVersion("eslint", { global: true })}`,
145
+ `Operating System: ${os.platform()} ${os.release()}`
145
146
  ].join("\n");
146
147
  }
147
148
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint",
3
- "version": "7.20.0",
3
+ "version": "7.24.0",
4
4
  "author": "Nicholas C. Zakas <nicholas+npm@nczconsulting.com>",
5
5
  "description": "An AST-based pattern checker for JavaScript.",
6
6
  "bin": {
@@ -47,7 +47,7 @@
47
47
  "bugs": "https://github.com/eslint/eslint/issues/",
48
48
  "dependencies": {
49
49
  "@babel/code-frame": "7.12.11",
50
- "@eslint/eslintrc": "^0.3.0",
50
+ "@eslint/eslintrc": "^0.4.0",
51
51
  "ajv": "^6.10.0",
52
52
  "chalk": "^4.0.0",
53
53
  "cross-spawn": "^7.0.2",
@@ -60,10 +60,10 @@
60
60
  "espree": "^7.3.1",
61
61
  "esquery": "^1.4.0",
62
62
  "esutils": "^2.0.2",
63
- "file-entry-cache": "^6.0.0",
63
+ "file-entry-cache": "^6.0.1",
64
64
  "functional-red-black-tree": "^1.0.1",
65
65
  "glob-parent": "^5.0.0",
66
- "globals": "^12.1.0",
66
+ "globals": "^13.6.0",
67
67
  "ignore": "^4.0.6",
68
68
  "import-fresh": "^3.0.0",
69
69
  "imurmurhash": "^0.1.4",
@@ -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.20",
74
+ "lodash": "^4.17.21",
75
75
  "minimatch": "^3.0.4",
76
76
  "natural-compare": "^1.4.0",
77
77
  "optionator": "^0.9.1",
@@ -100,7 +100,7 @@
100
100
  "eslint-config-eslint": "file:packages/eslint-config-eslint",
101
101
  "eslint-plugin-eslint-plugin": "^2.2.1",
102
102
  "eslint-plugin-internal-rules": "file:tools/internal-rules",
103
- "eslint-plugin-jsdoc": "^22.1.0",
103
+ "eslint-plugin-jsdoc": "^25.4.3",
104
104
  "eslint-plugin-node": "^11.1.0",
105
105
  "eslint-release": "^2.0.0",
106
106
  "eslump": "^2.0.0",
@@ -108,29 +108,30 @@
108
108
  "fs-teardown": "^0.1.0",
109
109
  "glob": "^7.1.6",
110
110
  "jsdoc": "^3.5.5",
111
- "karma": "^4.0.1",
111
+ "karma": "^6.1.1",
112
112
  "karma-chrome-launcher": "^3.1.0",
113
- "karma-mocha": "^1.3.0",
114
- "karma-mocha-reporter": "^2.2.3",
115
- "karma-webpack": "^4.0.0-rc.6",
113
+ "karma-mocha": "^2.0.1",
114
+ "karma-mocha-reporter": "^2.2.5",
115
+ "karma-webpack": "^5.0.0",
116
116
  "lint-staged": "^10.1.2",
117
117
  "load-perf": "^0.2.0",
118
118
  "markdownlint": "^0.19.0",
119
119
  "markdownlint-cli": "^0.22.0",
120
120
  "memfs": "^3.0.1",
121
- "mocha": "^7.1.1",
122
- "mocha-junit-reporter": "^1.23.0",
121
+ "mocha": "^8.3.2",
122
+ "mocha-junit-reporter": "^2.0.0",
123
+ "node-polyfill-webpack-plugin": "^1.0.3",
123
124
  "npm-license": "^0.3.3",
124
125
  "nyc": "^15.0.1",
125
126
  "proxyquire": "^2.0.1",
126
- "puppeteer": "^4.0.0",
127
+ "puppeteer": "^7.1.0",
127
128
  "recast": "^0.19.0",
128
129
  "regenerator-runtime": "^0.13.2",
129
130
  "shelljs": "^0.8.2",
130
131
  "sinon": "^9.0.1",
131
132
  "temp": "^0.9.0",
132
- "webpack": "^4.35.0",
133
- "webpack-cli": "^3.3.5",
133
+ "webpack": "^5.23.0",
134
+ "webpack-cli": "^4.5.0",
134
135
  "yorkie": "^2.0.0"
135
136
  },
136
137
  "keywords": [