eslint 7.2.0 → 7.5.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.
Files changed (76) hide show
  1. package/CHANGELOG.md +78 -0
  2. package/README.md +14 -7
  3. package/lib/init/config-initializer.js +89 -68
  4. package/lib/linter/code-path-analysis/code-path-analyzer.js +38 -0
  5. package/lib/linter/code-path-analysis/code-path-segment.js +0 -1
  6. package/lib/linter/code-path-analysis/code-path-state.js +59 -0
  7. package/lib/linter/code-path-analysis/debug-helpers.js +26 -19
  8. package/lib/rule-tester/rule-tester.js +9 -0
  9. package/lib/rules/accessor-pairs.js +1 -14
  10. package/lib/rules/array-callback-return.js +26 -17
  11. package/lib/rules/arrow-body-style.js +43 -8
  12. package/lib/rules/arrow-parens.js +91 -108
  13. package/lib/rules/camelcase.js +47 -0
  14. package/lib/rules/comma-dangle.js +2 -1
  15. package/lib/rules/consistent-return.js +1 -12
  16. package/lib/rules/constructor-super.js +1 -0
  17. package/lib/rules/curly.js +8 -1
  18. package/lib/rules/dot-location.js +20 -14
  19. package/lib/rules/dot-notation.js +36 -33
  20. package/lib/rules/func-call-spacing.js +42 -6
  21. package/lib/rules/func-name-matching.js +1 -4
  22. package/lib/rules/global-require.js +2 -1
  23. package/lib/rules/id-blacklist.js +14 -11
  24. package/lib/rules/id-denylist.js +230 -0
  25. package/lib/rules/id-match.js +2 -1
  26. package/lib/rules/indent.js +19 -0
  27. package/lib/rules/index.js +3 -0
  28. package/lib/rules/key-spacing.js +6 -2
  29. package/lib/rules/keyword-spacing.js +2 -2
  30. package/lib/rules/max-len.js +13 -2
  31. package/lib/rules/max-lines.js +34 -8
  32. package/lib/rules/new-cap.js +10 -14
  33. package/lib/rules/newline-per-chained-call.js +15 -5
  34. package/lib/rules/no-alert.js +10 -3
  35. package/lib/rules/no-eval.js +8 -38
  36. package/lib/rules/no-extend-native.js +37 -40
  37. package/lib/rules/no-extra-bind.js +57 -17
  38. package/lib/rules/no-extra-boolean-cast.js +7 -0
  39. package/lib/rules/no-extra-parens.js +48 -10
  40. package/lib/rules/no-implicit-coercion.js +11 -6
  41. package/lib/rules/no-implied-eval.js +7 -28
  42. package/lib/rules/no-import-assign.js +33 -32
  43. package/lib/rules/no-irregular-whitespace.js +22 -12
  44. package/lib/rules/no-magic-numbers.js +4 -8
  45. package/lib/rules/no-obj-calls.js +7 -4
  46. package/lib/rules/no-promise-executor-return.js +121 -0
  47. package/lib/rules/no-prototype-builtins.js +13 -3
  48. package/lib/rules/no-self-assign.js +3 -53
  49. package/lib/rules/no-setter-return.js +5 -8
  50. package/lib/rules/no-unexpected-multiline.js +2 -2
  51. package/lib/rules/no-unneeded-ternary.js +0 -2
  52. package/lib/rules/no-unreachable-loop.js +150 -0
  53. package/lib/rules/no-unused-expressions.js +55 -23
  54. package/lib/rules/no-unused-vars.js +2 -1
  55. package/lib/rules/no-useless-call.js +10 -7
  56. package/lib/rules/no-whitespace-before-property.js +16 -4
  57. package/lib/rules/object-curly-newline.js +4 -4
  58. package/lib/rules/object-property-newline.js +1 -1
  59. package/lib/rules/operator-assignment.js +3 -42
  60. package/lib/rules/operator-linebreak.js +2 -5
  61. package/lib/rules/padded-blocks.js +2 -1
  62. package/lib/rules/padding-line-between-statements.js +2 -2
  63. package/lib/rules/prefer-arrow-callback.js +90 -25
  64. package/lib/rules/prefer-exponentiation-operator.js +1 -1
  65. package/lib/rules/prefer-numeric-literals.js +4 -13
  66. package/lib/rules/prefer-promise-reject-errors.js +1 -3
  67. package/lib/rules/prefer-regex-literals.js +68 -13
  68. package/lib/rules/prefer-spread.js +2 -6
  69. package/lib/rules/radix.js +5 -2
  70. package/lib/rules/semi-spacing.js +1 -0
  71. package/lib/rules/sort-imports.js +28 -0
  72. package/lib/rules/use-isnan.js +1 -1
  73. package/lib/rules/utils/ast-utils.js +317 -153
  74. package/lib/rules/wrap-iife.js +9 -2
  75. package/lib/rules/yoda.js +2 -55
  76. package/package.json +7 -7
package/CHANGELOG.md CHANGED
@@ -1,3 +1,78 @@
1
+ v7.5.0 - July 18, 2020
2
+
3
+ * [`6ea3178`](https://github.com/eslint/eslint/commit/6ea3178776eae0e40c3f5498893e8aab0e23686b) Update: optional chaining support (fixes #12642) (#13416) (Toru Nagashima)
4
+ * [`540b1af`](https://github.com/eslint/eslint/commit/540b1af77278ae649b621aa8d4bf8d6de03c3155) Chore: enable consistent-meta-messages internal rule (#13487) (Milos Djermanovic)
5
+ * [`885a145`](https://github.com/eslint/eslint/commit/885a1455691265db88dc0befe9b48a69d69e8b9c) Docs: clarify behavior if `meta.fixable` is omitted (refs #13349) (#13493) (Milos Djermanovic)
6
+ * [`1a01b42`](https://github.com/eslint/eslint/commit/1a01b420eaab0de03dab5cc190a9f2a860c21a84) Docs: Update technology sponsors in README (#13478) (Nicholas C. Zakas)
7
+ * [`6ed9e8e`](https://github.com/eslint/eslint/commit/6ed9e8e4ff038c0259b0e7fe7ab7f4fd4ec55801) Upgrade: lodash@4.17.19 (#13499) (Yohan Siguret)
8
+ * [`45cdf00`](https://github.com/eslint/eslint/commit/45cdf00da6aeff3d584d37b0710fc8d6ad9456d6) Sponsors: Sync README with website (ESLint Jenkins)
9
+ * [`f1cc725`](https://github.com/eslint/eslint/commit/f1cc725ba1b8646dcf06a83716d96ad9bb726172) Docs: fix linebreaks between versions in changelog (#13488) (Milos Djermanovic)
10
+ * [`f4d7b9e`](https://github.com/eslint/eslint/commit/f4d7b9e1a599346b2f21ff9de003b311b51411e6) Update: deprecate id-blacklist rule (#13465) (Dimitri Mitropoulos)
11
+ * [`e14a645`](https://github.com/eslint/eslint/commit/e14a645aa495558081490f990ba221e21aa6b27c) Chore: use espree.latestEcmaVersion in fuzzer (#13484) (Milos Djermanovic)
12
+ * [`61097fe`](https://github.com/eslint/eslint/commit/61097fe5cc275d414a0c8e19b31c6060cb5568b7) Docs: Update int rule level to string (#13483) (Brandon Mills)
13
+ * [`c8f9c82`](https://github.com/eslint/eslint/commit/c8f9c8210cf4b9da8f07922093d7b219abad9f10) Update: Improve report location no-irregular-whitespace (refs #12334) (#13462) (Milos Djermanovic)
14
+ * [`f2e68ec`](https://github.com/eslint/eslint/commit/f2e68ec1d6cee6299e8a5cdf76c522c11d3008dd) Build: update webpack resolve.mainFields to match website config (#13457) (Milos Djermanovic)
15
+ * [`a96bc5e`](https://github.com/eslint/eslint/commit/a96bc5ec06f3a48bfe458bccd68d4d3b2a280ed9) Fix: arrow-body-style fixer for `in` wrap (fixes #11849) (#13228) (Anix)
16
+ * [`748734f`](https://github.com/eslint/eslint/commit/748734fdd497fbf61f3a616ff4a09169135b9396) Upgrade: Updated puppeteer version to v4.0.0 (#13444) (odidev)
17
+ * [`e951457`](https://github.com/eslint/eslint/commit/e951457b7aaa1b12b135588d36e3f4db4d7b8463) Docs: fix wording in configuring.md (#13469) (Piper)
18
+ * [`0af1d28`](https://github.com/eslint/eslint/commit/0af1d2828d27885483737867653ba1659af72005) Update: add allowSeparatedGroups option to sort-imports (fixes #12951) (#13455) (Milos Djermanovic)
19
+ * [`1050ee7`](https://github.com/eslint/eslint/commit/1050ee78a95da9484ff333dc1c74dac64c05da6f) Update: Improve report location for no-unneeded-ternary (refs #12334) (#13456) (Milos Djermanovic)
20
+ * [`b77b420`](https://github.com/eslint/eslint/commit/b77b4202bd1d5d1306f6f645e88d7a41a51715db) Update: Improve report location for max-len (refs #12334) (#13458) (Milos Djermanovic)
21
+ * [`095194c`](https://github.com/eslint/eslint/commit/095194c0fc0eb02aa69fde6b4280696e0e4de214) Fix: add end location to reports in object-curly-newline (refs #12334) (#13460) (Milos Djermanovic)
22
+ * [`10251bb`](https://github.com/eslint/eslint/commit/10251bbaeba80ac15244f385fc42cf2f2a30e5d2) Fix: add end location to reports in keyword-spacing (refs #12334) (#13461) (Milos Djermanovic)
23
+ * [`2ea7ee5`](https://github.com/eslint/eslint/commit/2ea7ee51a4e05ee76a6dae5954c3b6263b0970a3) Sponsors: Sync README with website (ESLint Jenkins)
24
+ * [`b55fd3b`](https://github.com/eslint/eslint/commit/b55fd3b8c05a29a465a794a524b06c1a28cddf0c) Sponsors: Sync README with website (ESLint Jenkins)
25
+
26
+ v7.4.0 - July 3, 2020
27
+
28
+ * [`f21bad2`](https://github.com/eslint/eslint/commit/f21bad2680406a2671b877f8dba47f4475d0cc64) Docs: fix description for `never` in multiline-ternary (fixes #13368) (#13452) (Milos Djermanovic)
29
+ * [`ada2c89`](https://github.com/eslint/eslint/commit/ada2c891298382f82dfabf37cacd59a1057b2bb7) Fix: support typescript generics in arrow-parens (fixes #12570) (#13451) (Milos Djermanovic)
30
+ * [`89ee01e`](https://github.com/eslint/eslint/commit/89ee01e083f1e02293bf8d1447f9b0fdb3cb9384) Fix: Revert config cloning (fixes #13447) (#13449) (薛定谔的猫)
31
+ * [`0a463db`](https://github.com/eslint/eslint/commit/0a463dbf7cc5a77d442879c9117204d4d38db972) Docs: fix no-multiple-empty-lines examples (fixes #13432) (#13433) (Milos Djermanovic)
32
+ * [`ff5317e`](https://github.com/eslint/eslint/commit/ff5317e93425f93cfdf808609551ee67b2032543) Update: Improve array-callback-return report message (#13395) (Philip (flip) Kromer)
33
+ * [`3f51930`](https://github.com/eslint/eslint/commit/3f51930eea7cddc921a9ee3cb0328c7b649c0f83) Fix: false positive new with member in no-extra-parens (fixes #12740) (#13375) (YeonJuan)
34
+ * [`825a5b9`](https://github.com/eslint/eslint/commit/825a5b98d3d84f6eb72b75f7d8519de763cc8898) Fix: Clarify documentation on implicit ignore behavior (fixes #12348) (#12600) (Scott Hardin)
35
+ * [`c139156`](https://github.com/eslint/eslint/commit/c1391566a5f765f25716527de7b5cdee16c0ce36) Sponsors: Sync README with website (ESLint Jenkins)
36
+ * [`0c17e9d`](https://github.com/eslint/eslint/commit/0c17e9d2ac307cc288eea6ed7971bd5a7d33321a) Sponsors: Sync README with website (ESLint Jenkins)
37
+ * [`c680387`](https://github.com/eslint/eslint/commit/c680387ba61f6dccf0390d24a85d871fa83e9fea) Sponsors: Sync README with website (ESLint Jenkins)
38
+ * [`bf3939b`](https://github.com/eslint/eslint/commit/bf3939bbd9a33d0eb96cebe6a53bf61c855f9ba6) Sponsors: Sync README with website (ESLint Jenkins)
39
+ * [`7baf02e`](https://github.com/eslint/eslint/commit/7baf02e983af909800261263f125cca901a5bd0f) Sponsors: Sync README with website (ESLint Jenkins)
40
+ * [`5c4c3fd`](https://github.com/eslint/eslint/commit/5c4c3fdfbda18a13223ad36f44283adbfee8c496) Sponsors: Sync README with website (ESLint Jenkins)
41
+ * [`53912aa`](https://github.com/eslint/eslint/commit/53912aab1856327b399cca26cbb2ba81fd01bfa2) Sponsors: Sync README with website (ESLint Jenkins)
42
+ * [`51e42ec`](https://github.com/eslint/eslint/commit/51e42eca3e87d8259815d736ffe81e604f184057) Update: Add option "ignoreGlobals" to camelcase rule (fixes #11716) (#12782) (David Gasperoni)
43
+ * [`0655f66`](https://github.com/eslint/eslint/commit/0655f66525d167ca1288167b79a77087cfc8fcf6) Update: improve report location in arrow-body-style (refs #12334) (#13424) (YeonJuan)
44
+ * [`d53d69a`](https://github.com/eslint/eslint/commit/d53d69af08cfe55f42e0a0ca725b1014dabccc21) Update: prefer-regex-literal detect regex literals (fixes #12840) (#12842) (Mathias Schreck)
45
+ * [`004adae`](https://github.com/eslint/eslint/commit/004adae3f959414f56e44e5884f6221e9dcda142) Update: rename id-blacklist to id-denylist (fixes #13407) (#13408) (Kai Cataldo)
46
+
47
+ v7.3.1 - June 22, 2020
48
+
49
+ * [`de77c11`](https://github.com/eslint/eslint/commit/de77c11e7515f2097ff355ddc0d7b6db9c83c892) Fix: Replace Infinity with Number.MAX_SAFE_INTEGER (fixes #13427) (#13435) (Nicholas C. Zakas)
50
+
51
+ v7.3.0 - June 19, 2020
52
+
53
+ * [`638a6d6`](https://github.com/eslint/eslint/commit/638a6d6be18b4a37cfdc7223e1f5acd3718694be) Update: add missing `additionalProperties: false` to some rules' schema (#13198) (Milos Djermanovic)
54
+ * [`949a5cd`](https://github.com/eslint/eslint/commit/949a5cd741c2e930cfb43d80a9b6b084f9d677c3) Update: fix operator-linebreak overrides schema (#13199) (Milos Djermanovic)
55
+ * [`9e1414e`](https://github.com/eslint/eslint/commit/9e1414ee16b8caf582920f8fdf3b6ee1eb0b7cd5) New: Add no-promise-executor-return rule (fixes #12640) (#12648) (Milos Djermanovic)
56
+ * [`09cc0a2`](https://github.com/eslint/eslint/commit/09cc0a2bb5bcf3bcb0766a3c989871f268518437) Update: max-lines reporting loc improvement (refs #12334) (#13318) (Anix)
57
+ * [`ee2fc2e`](https://github.com/eslint/eslint/commit/ee2fc2e90d0f9dfcdba852b0609156bee5280b92) Update: object-property-newline end location (refs #12334) (#13399) (Anix)
58
+ * [`d98152a`](https://github.com/eslint/eslint/commit/d98152a3d8c72e4f5ac4c6fa10a615b12090c8f7) Update: added empty error array check for false negative (#13200) (Anix)
59
+ * [`7fb45cf`](https://github.com/eslint/eslint/commit/7fb45cf13e9908d489bd6d5fba3b7243c01508b9) Fix: clone config before validating (fixes #12592) (#13034) (Anix)
60
+ * [`aed46f6`](https://github.com/eslint/eslint/commit/aed46f69d54da167d9838149954ceeb4b02be5fd) Sponsors: Sync README with website (ESLint Jenkins)
61
+ * [`7686d7f`](https://github.com/eslint/eslint/commit/7686d7feaccc7b8fee927eda6602d641d8de1e5c) Update: semi-spacing should check do-while statements (#13358) (Milos Djermanovic)
62
+ * [`cbd0d00`](https://github.com/eslint/eslint/commit/cbd0d00a1ec2824d7e025bbbc084855ed0bf08bb) Update: disallow multiple options in comma-dangle schema (fixes #13165) (#13166) (Milos Djermanovic)
63
+ * [`b550330`](https://github.com/eslint/eslint/commit/b550330d739c73a7a8f887064e7c911d05a95f9a) New: Add no-unreachable-loop rule (fixes #12381) (#12660) (Milos Djermanovic)
64
+ * [`13999d2`](https://github.com/eslint/eslint/commit/13999d292080f814fa4fb266e011d61c184197c4) Update: curly should check consequent `if` statements (#12947) (Milos Djermanovic)
65
+ * [`c42e548`](https://github.com/eslint/eslint/commit/c42e54893b79b470ca7745bd2a626ffd069e017b) Chore: enable exceptRange option in the yoda rule (#12857) (Milos Djermanovic)
66
+ * [`6cfbd03`](https://github.com/eslint/eslint/commit/6cfbd03b3f22edb4d1c9c61c64eea7c129da71aa) Update: Drop @typescript-eslint/eslint-recommended from `eslint --init` (#13340) (Minh Nguyen)
67
+ * [`796f269`](https://github.com/eslint/eslint/commit/796f269e448fdcbf8a5a62edf1990bd857efd1af) Chore: update eslint-config-eslint's required node version (#13379) (薛定谔的猫)
68
+ * [`9d0186e`](https://github.com/eslint/eslint/commit/9d0186e55bee769ea6aa08dc5a62682f58316412) Docs: Fix changelog versions (#13410) (Tony Brix)
69
+ * [`1ee3c42`](https://github.com/eslint/eslint/commit/1ee3c42ceeee56b650bcc4206ed783b795f65643) Docs: On maxEOF with eol-last (fixes #12742) (#13374) (Arthur Dias)
70
+ * [`2a21049`](https://github.com/eslint/eslint/commit/2a210499288ed14ec9a6fd72decabfb77504c197) Update: key-spacing loc changes for extra space (refs #12334) (#13362) (Anix)
71
+ * [`7ce7988`](https://github.com/eslint/eslint/commit/7ce7988f411da64248a64a9d9d2b7884d5ba39e0) Chore: Replace the inquirer dependency with enquirer (#13254) (Selwyn)
72
+ * [`0f1f5ed`](https://github.com/eslint/eslint/commit/0f1f5ed2a20b8fb575d4360316861cf4c2b9b7bc) Docs: Add security policy link to README (#13403) (Nicholas C. Zakas)
73
+ * [`9e9ba89`](https://github.com/eslint/eslint/commit/9e9ba897c566601cfe90522099c635ea316b235f) Sponsors: Sync README with website (ESLint Jenkins)
74
+ * [`ca59fb9`](https://github.com/eslint/eslint/commit/ca59fb95a395c0a02ed23768a70e086480ab1f6d) Sponsors: Sync README with website (ESLint Jenkins)
75
+
1
76
  v7.2.0 - June 5, 2020
2
77
 
3
78
  * [`b735a48`](https://github.com/eslint/eslint/commit/b735a485e77bcc791e4c4c6b8716801d94e98b2c) Update: add enforceForFunctionPrototypeMethods option to no-extra-parens (#12895) (Milos Djermanovic)
@@ -17,6 +92,7 @@ v7.2.0 - June 5, 2020
17
92
  * [`ee30e5d`](https://github.com/eslint/eslint/commit/ee30e5d8bb1a4c82a2a3fbe1b9ee9f979b55c5c4) Sponsors: Sync README with website (ESLint Jenkins)
18
93
  * [`c29bd9f`](https://github.com/eslint/eslint/commit/c29bd9f75582e5b1a403a8ffd0aafd1ffc8c58e1) Chore: Add breaking/core change link to issue templates (#13344) (Kai Cataldo)
19
94
  * [`d55490f`](https://github.com/eslint/eslint/commit/d55490fa73ff69416de375e4c1cd67b6edba531c) Sponsors: Sync README with website (ESLint Jenkins)
95
+
20
96
  v7.1.0 - May 22, 2020
21
97
 
22
98
  * [`a93083a`](https://github.com/eslint/eslint/commit/a93083af89c6f9714dcdd4a7f27c8655a0b0dba6) Fix: astUtils.getNextLocation returns invalid location after CRLF (#13275) (Milos Djermanovic)
@@ -46,6 +122,7 @@ v7.1.0 - May 22, 2020
46
122
  * [`f44a6b4`](https://github.com/eslint/eslint/commit/f44a6b4fd92602af8e2c75d5852f796ec064aa8e) Chore: fix invalid syntax in require-await tests (#13277) (Milos Djermanovic)
47
123
  * [`2c778fb`](https://github.com/eslint/eslint/commit/2c778fb6e31b7943bb27a47a6e15dcbfd8336f39) Fix: remove custom plugins from replacedBy metadata (#13274) (Kai Cataldo)
48
124
  * [`0db3b1d`](https://github.com/eslint/eslint/commit/0db3b1d5cc5e4e1de21462679581b7a4d89ff36e) Sponsors: Sync README with website (ESLint Jenkins)
125
+
49
126
  v7.0.0 - May 8, 2020
50
127
 
51
128
  * [`b98d8bd`](https://github.com/eslint/eslint/commit/b98d8bda4630fe8278c5aa2b6650630770568fe5) Upgrade: eslint-release@2.0.0 (#13271) (Kai Cataldo)
@@ -256,6 +333,7 @@ v7.0.0 - May 8, 2020
256
333
  * [`39f5a45`](https://github.com/eslint/eslint/commit/39f5a453579b2ad732212edeb71f84ecb0991f97) Chore: add test cases for for-direction (#12698) (YeonJuan)
257
334
  * [`b340304`](https://github.com/eslint/eslint/commit/b3403045e535921df6d34785a4ce053e14ba27fd) Chore: Add extra test, improve docs (#12492) (Kevin Partington)
258
335
  * [`827259e`](https://github.com/eslint/eslint/commit/827259ea009f98a0fdf3f7ebf1bfb6cd661ce28d) Build: package.json update for eslint-config-eslint release (ESLint Jenkins)
336
+
259
337
  v7.0.0-rc.0 - April 24, 2020
260
338
 
261
339
  * [`0b1d65a`](https://github.com/eslint/eslint/commit/0b1d65a45aa5dfe08cd596c420490e81b546317e) Update: Improve report location for array-callback-return (refs #12334) (#13109) (Milos Djermanovic)
package/README.md CHANGED
@@ -33,11 +33,12 @@ ESLint is a tool for identifying and reporting on patterns found in ECMAScript/J
33
33
  4. [Filing Issues](#filing-issues)
34
34
  5. [Frequently Asked Questions](#faq)
35
35
  6. [Releases](#releases)
36
- 7. [Semantic Versioning Policy](#semantic-versioning-policy)
37
- 8. [License](#license)
38
- 9. [Team](#team)
39
- 10. [Sponsors](#sponsors)
40
- 11. [Technology Sponsors](#technology-sponsors)
36
+ 7. [Security Policy](#security-policy)
37
+ 8. [Semantic Versioning Policy](#semantic-versioning-policy)
38
+ 9. [License](#license)
39
+ 10. [Team](#team)
40
+ 11. [Sponsors](#sponsors)
41
+ 12. [Technology Sponsors](#technology-sponsors)
41
42
 
42
43
  ## <a name="installation-and-usage"></a>Installation and Usage
43
44
 
@@ -139,6 +140,10 @@ Join our [Mailing List](https://groups.google.com/group/eslint) or [Chatroom](ht
139
140
 
140
141
  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.
141
142
 
143
+ ## <a name="security-policy"></a>Security Policy
144
+
145
+ ESLint takes security seriously. We work hard to ensure that ESLint is safe for everyone and that security issues are addressed quickly and responsibly. Read the full [security policy](https://github.com/eslint/.github/blob/master/SECURITY.md).
146
+
142
147
  ## <a name="semantic-versioning-policy"></a>Semantic Versioning Policy
143
148
 
144
149
  ESLint follows [semantic versioning](https://semver.org). However, due to the nature of ESLint as a code quality tool, it's not always clear when a minor or major version bump occurs. To help clarify this for everyone, we've defined the following semantic versioning policy for ESLint:
@@ -249,11 +254,13 @@ The following companies, organizations, and individuals support ESLint's ongoing
249
254
  <!-- NOTE: This section is autogenerated. Do not manually edit.-->
250
255
  <!--sponsorsstart-->
251
256
  <h3>Gold Sponsors</h3>
252
- <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></p><h3>Silver Sponsors</h3>
257
+ <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>
253
258
  <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>
254
- <p><a href="https://bruce.agency"><img src="https://images.opencollective.com/brucemade/0c70c59/logo.png" alt="Bruce" height="32"></a> <a href="https://edubirdie.com/"><img src="https://images.opencollective.com/edubirdie2/b1d51ab/logo.png" alt="EduBirdie" 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://writersperhour.com/write-my-essay"><img src="https://images.opencollective.com/writersperhour/5787d4b/logo.png" alt="Writers Per Hour" 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://cooltechzone.com/netflix-vpn"><img src="https://images.opencollective.com/vpn-netflix/4850160/logo.png" alt="vpn netflix" 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/bbd887f/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="https://www.bugsnag.com/platforms?utm_source=Open Collective&utm_medium=Website&utm_content=open-source&utm_campaign=2019-community&utm_term="><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/0b37d14/logo.png" alt="Free Icons by Icons8" 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://tekhattan.com"><img src="https://images.opencollective.com/tekhattan/bc73c28/logo.png" alt="TekHattan" 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="http://www.firesticktricks.com"><img src="https://images.opencollective.com/fire-stick-tricks/b8fbe2c/logo.png" alt="Fire Stick Tricks" height="32"></a></p>
259
+ <p><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://bruce.agency"><img src="https://images.opencollective.com/brucemade/0c70c59/logo.png" alt="Bruce" height="32"></a> <a href="https://edubirdie.com/"><img src="https://images.opencollective.com/edubirdie2/b1d51ab/logo.png" alt="EduBirdie" 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://writersperhour.com/write-my-essay"><img src="https://images.opencollective.com/writersperhour/5787d4b/logo.png" alt="Writers Per Hour" 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="https://www.bugsnag.com/platforms?utm_source=Open Collective&utm_medium=Website&utm_content=open-source&utm_campaign=2019-community&utm_term="><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/6e889f6/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://tekhattan.com"><img src="https://images.opencollective.com/tekhattan/bc73c28/logo.png" alt="TekHattan" 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="http://www.firesticktricks.com"><img src="https://images.opencollective.com/fire-stick-tricks/b8fbe2c/logo.png" alt="Fire Stick Tricks" height="32"></a></p>
255
260
  <!--sponsorsend-->
256
261
 
257
262
  ## <a name="technology-sponsors"></a>Technology Sponsors
258
263
 
259
264
  * Site search ([eslint.org](https://eslint.org)) is sponsored by [Algolia](https://www.algolia.com)
265
+ * Hosting for ([eslint.org](https://eslint.org)) is sponsored by [Netlify](https://www.netlify.com)
266
+ * Password management is sponsored by [1Password](https://www.1password.com)
@@ -12,7 +12,7 @@
12
12
 
13
13
  const util = require("util"),
14
14
  path = require("path"),
15
- inquirer = require("inquirer"),
15
+ enquirer = require("enquirer"),
16
16
  ProgressBar = require("progress"),
17
17
  semver = require("semver"),
18
18
  espree = require("espree"),
@@ -146,7 +146,7 @@ function getModulesList(config, installESLint) {
146
146
  *
147
147
  * Note: This clones the config object and returns a new config to avoid mutating
148
148
  * the original config parameter.
149
- * @param {Object} answers answers received from inquirer
149
+ * @param {Object} answers answers received from enquirer
150
150
  * @param {Object} config config object
151
151
  * @returns {Object} config object with configured rules
152
152
  */
@@ -253,7 +253,7 @@ function configureRules(answers, config) {
253
253
 
254
254
  /**
255
255
  * process user's answers and create config object
256
- * @param {Object} answers answers received from inquirer
256
+ * @param {Object} answers answers received from enquirer
257
257
  * @returns {Object} config object
258
258
  */
259
259
  function processAnswers(answers) {
@@ -321,7 +321,6 @@ function processAnswers(answers) {
321
321
  }
322
322
  }
323
323
  if (answers.typescript && config.extends.includes("eslint:recommended")) {
324
- config.extends.push("plugin:@typescript-eslint/eslint-recommended");
325
324
  config.extends.push("plugin:@typescript-eslint/recommended");
326
325
  }
327
326
 
@@ -409,7 +408,7 @@ function installModules(modules) {
409
408
  npmUtils.installSyncSaveDev(modules);
410
409
  }
411
410
 
412
- /* istanbul ignore next: no need to test inquirer */
411
+ /* istanbul ignore next: no need to test enquirer */
413
412
  /**
414
413
  * Ask user to install modules.
415
414
  * @param {string[]} modules Array of modules to be installed.
@@ -425,14 +424,19 @@ function askInstallModules(modules, packageJsonExists) {
425
424
 
426
425
  log.info("The config that you've selected requires the following dependencies:\n");
427
426
  log.info(modules.join(" "));
428
- return inquirer.prompt([
427
+ return enquirer.prompt([
429
428
  {
430
- type: "confirm",
429
+ type: "toggle",
431
430
  name: "executeInstallation",
432
431
  message: "Would you like to install them now with npm?",
433
- default: true,
434
- when() {
435
- return modules.length && packageJsonExists;
432
+ enabled: "Yes",
433
+ disabled: "No",
434
+ initial: 1,
435
+ skip() {
436
+ return !(modules.length && packageJsonExists);
437
+ },
438
+ result(input) {
439
+ return this.skipped ? null : input;
436
440
  }
437
441
  }
438
442
  ]).then(({ executeInstallation }) => {
@@ -442,114 +446,124 @@ function askInstallModules(modules, packageJsonExists) {
442
446
  });
443
447
  }
444
448
 
445
- /* istanbul ignore next: no need to test inquirer */
449
+ /* istanbul ignore next: no need to test enquirer */
446
450
  /**
447
451
  * Ask use a few questions on command prompt
448
452
  * @returns {Promise} The promise with the result of the prompt
449
453
  */
450
454
  function promptUser() {
451
455
 
452
- return inquirer.prompt([
456
+ return enquirer.prompt([
453
457
  {
454
- type: "list",
458
+ type: "select",
455
459
  name: "purpose",
456
460
  message: "How would you like to use ESLint?",
457
- default: "problems",
461
+
462
+ // The returned number matches the name value of nth in the choices array.
463
+ initial: 1,
458
464
  choices: [
459
- { name: "To check syntax only", value: "syntax" },
460
- { name: "To check syntax and find problems", value: "problems" },
461
- { name: "To check syntax, find problems, and enforce code style", value: "style" }
465
+ { message: "To check syntax only", name: "syntax" },
466
+ { message: "To check syntax and find problems", name: "problems" },
467
+ { message: "To check syntax, find problems, and enforce code style", name: "style" }
462
468
  ]
463
469
  },
464
470
  {
465
- type: "list",
471
+ type: "select",
466
472
  name: "moduleType",
467
473
  message: "What type of modules does your project use?",
468
- default: "esm",
474
+ initial: 0,
469
475
  choices: [
470
- { name: "JavaScript modules (import/export)", value: "esm" },
471
- { name: "CommonJS (require/exports)", value: "commonjs" },
472
- { name: "None of these", value: "none" }
476
+ { message: "JavaScript modules (import/export)", name: "esm" },
477
+ { message: "CommonJS (require/exports)", name: "commonjs" },
478
+ { message: "None of these", name: "none" }
473
479
  ]
474
480
  },
475
481
  {
476
- type: "list",
482
+ type: "select",
477
483
  name: "framework",
478
484
  message: "Which framework does your project use?",
479
- default: "react",
485
+ initial: 0,
480
486
  choices: [
481
- { name: "React", value: "react" },
482
- { name: "Vue.js", value: "vue" },
483
- { name: "None of these", value: "none" }
487
+ { message: "React", name: "react" },
488
+ { message: "Vue.js", name: "vue" },
489
+ { message: "None of these", name: "none" }
484
490
  ]
485
491
  },
486
492
  {
487
- type: "confirm",
493
+ type: "toggle",
488
494
  name: "typescript",
489
495
  message: "Does your project use TypeScript?",
490
- default: false
496
+ enabled: "Yes",
497
+ disabled: "No",
498
+ initial: 0
491
499
  },
492
500
  {
493
- type: "checkbox",
501
+ type: "multiselect",
494
502
  name: "env",
495
503
  message: "Where does your code run?",
496
- default: ["browser"],
504
+ hint: "(Press <space> to select, <a> to toggle all, <i> to invert selection)",
505
+ initial: 0,
497
506
  choices: [
498
- { name: "Browser", value: "browser" },
499
- { name: "Node", value: "node" }
507
+ { message: "Browser", name: "browser" },
508
+ { message: "Node", name: "node" }
500
509
  ]
501
510
  },
502
511
  {
503
- type: "list",
512
+ type: "select",
504
513
  name: "source",
505
514
  message: "How would you like to define a style for your project?",
506
- default: "guide",
507
515
  choices: [
508
- { name: "Use a popular style guide", value: "guide" },
509
- { name: "Answer questions about your style", value: "prompt" },
510
- { name: "Inspect your JavaScript file(s)", value: "auto" }
516
+ { message: "Use a popular style guide", name: "guide" },
517
+ { message: "Answer questions about your style", name: "prompt" },
518
+ { message: "Inspect your JavaScript file(s)", name: "auto" }
511
519
  ],
512
- when(answers) {
513
- return answers.purpose === "style";
520
+ skip() {
521
+ return this.state.answers.purpose !== "style";
522
+ },
523
+ result(input) {
524
+ return this.skipped ? null : input;
514
525
  }
515
526
  },
516
527
  {
517
- type: "list",
528
+ type: "select",
518
529
  name: "styleguide",
519
530
  message: "Which style guide do you want to follow?",
520
531
  choices: [
521
- { name: "Airbnb: https://github.com/airbnb/javascript", value: "airbnb" },
522
- { name: "Standard: https://github.com/standard/standard", value: "standard" },
523
- { name: "Google: https://github.com/google/eslint-config-google", value: "google" }
532
+ { message: "Airbnb: https://github.com/airbnb/javascript", name: "airbnb" },
533
+ { message: "Standard: https://github.com/standard/standard", name: "standard" },
534
+ { message: "Google: https://github.com/google/eslint-config-google", name: "google" }
524
535
  ],
525
- when(answers) {
526
- answers.packageJsonExists = npmUtils.checkPackageJson();
527
- return answers.source === "guide" && answers.packageJsonExists;
536
+ skip() {
537
+ this.state.answers.packageJsonExists = npmUtils.checkPackageJson();
538
+ return !(this.state.answers.source === "guide" && this.state.answers.packageJsonExists);
539
+ },
540
+ result(input) {
541
+ return this.skipped ? null : input;
528
542
  }
529
543
  },
530
544
  {
531
545
  type: "input",
532
546
  name: "patterns",
533
547
  message: "Which file(s), path(s), or glob(s) should be examined?",
534
- when(answers) {
535
- return (answers.source === "auto");
548
+ skip() {
549
+ return this.state.answers.source !== "auto";
536
550
  },
537
551
  validate(input) {
538
- if (input.trim().length === 0 && input.trim() !== ",") {
552
+ if (!this.skipped && input.trim().length === 0 && input.trim() !== ",") {
539
553
  return "You must tell us what code to examine. Try again.";
540
554
  }
541
555
  return true;
542
556
  }
543
557
  },
544
558
  {
545
- type: "list",
559
+ type: "select",
546
560
  name: "format",
547
561
  message: "What format do you want your config file to be in?",
548
- default: "JavaScript",
562
+ initial: 0,
549
563
  choices: ["JavaScript", "YAML", "JSON"]
550
564
  },
551
565
  {
552
- type: "confirm",
566
+ type: "toggle",
553
567
  name: "installESLint",
554
568
  message(answers) {
555
569
  const verb = semver.ltr(answers.localESLintVersion, answers.requiredESLintVersionRange)
@@ -558,9 +572,14 @@ function promptUser() {
558
572
 
559
573
  return `The style guide "${answers.styleguide}" requires eslint@${answers.requiredESLintVersionRange}. You are currently using eslint@${answers.localESLintVersion}.\n Do you want to ${verb}?`;
560
574
  },
561
- default: true,
562
- when(answers) {
563
- return answers.source === "guide" && answers.packageJsonExists && hasESLintVersionConflict(answers);
575
+ enabled: "Yes",
576
+ disabled: "No",
577
+ initial: 1,
578
+ skip() {
579
+ return !(this.state.answers.source === "guide" && this.state.answers.packageJsonExists && hasESLintVersionConflict(this.state.answers));
580
+ },
581
+ result(input) {
582
+ return this.skipped ? null : input;
564
583
  }
565
584
  }
566
585
  ]).then(earlyAnswers => {
@@ -613,33 +632,35 @@ function promptUser() {
613
632
  }
614
633
 
615
634
  // continue with the style questions otherwise...
616
- return inquirer.prompt([
635
+ return enquirer.prompt([
617
636
  {
618
- type: "list",
637
+ type: "select",
619
638
  name: "indent",
620
639
  message: "What style of indentation do you use?",
621
- default: "tab",
622
- choices: [{ name: "Tabs", value: "tab" }, { name: "Spaces", value: 4 }]
640
+ initial: 0,
641
+ choices: [{ message: "Tabs", name: "tab" }, { message: "Spaces", name: 4 }]
623
642
  },
624
643
  {
625
- type: "list",
644
+ type: "select",
626
645
  name: "quotes",
627
646
  message: "What quotes do you use for strings?",
628
- default: "double",
629
- choices: [{ name: "Double", value: "double" }, { name: "Single", value: "single" }]
647
+ initial: 0,
648
+ choices: [{ message: "Double", name: "double" }, { message: "Single", name: "single" }]
630
649
  },
631
650
  {
632
- type: "list",
651
+ type: "select",
633
652
  name: "linebreak",
634
653
  message: "What line endings do you use?",
635
- default: "unix",
636
- choices: [{ name: "Unix", value: "unix" }, { name: "Windows", value: "windows" }]
654
+ initial: 0,
655
+ choices: [{ message: "Unix", name: "unix" }, { message: "Windows", name: "windows" }]
637
656
  },
638
657
  {
639
- type: "confirm",
658
+ type: "toggle",
640
659
  name: "semi",
641
660
  message: "Do you require semicolons?",
642
- default: true
661
+ enabled: "Yes",
662
+ disabled: "No",
663
+ initial: 1
643
664
  }
644
665
  ]).then(answers => {
645
666
  const totalAnswers = Object.assign({}, earlyAnswers, answers);
@@ -244,6 +244,19 @@ function preprocess(analyzer, node) {
244
244
  const parent = node.parent;
245
245
 
246
246
  switch (parent.type) {
247
+
248
+ // The `arguments.length == 0` case is in `postprocess` function.
249
+ case "CallExpression":
250
+ if (parent.optional === true && parent.arguments.length >= 1 && parent.arguments[0] === node) {
251
+ state.makeOptionalRight();
252
+ }
253
+ break;
254
+ case "MemberExpression":
255
+ if (parent.optional === true && parent.property === node) {
256
+ state.makeOptionalRight();
257
+ }
258
+ break;
259
+
247
260
  case "LogicalExpression":
248
261
  if (
249
262
  parent.right === node &&
@@ -377,6 +390,20 @@ function processCodePathToEnter(analyzer, node) {
377
390
  analyzer.emitter.emit("onCodePathStart", codePath, node);
378
391
  break;
379
392
 
393
+ case "ChainExpression":
394
+ state.pushChainContext();
395
+ break;
396
+ case "CallExpression":
397
+ if (node.optional === true) {
398
+ state.makeOptionalNode();
399
+ }
400
+ break;
401
+ case "MemberExpression":
402
+ if (node.optional === true) {
403
+ state.makeOptionalNode();
404
+ }
405
+ break;
406
+
380
407
  case "LogicalExpression":
381
408
  if (isHandledLogicalOperator(node.operator)) {
382
409
  state.pushChoiceContext(
@@ -449,6 +476,10 @@ function processCodePathToExit(analyzer, node) {
449
476
  let dontForward = false;
450
477
 
451
478
  switch (node.type) {
479
+ case "ChainExpression":
480
+ state.popChainContext();
481
+ break;
482
+
452
483
  case "IfStatement":
453
484
  case "ConditionalExpression":
454
485
  state.popChoiceContext();
@@ -583,6 +614,13 @@ function postprocess(analyzer, node) {
583
614
  break;
584
615
  }
585
616
 
617
+ // The `arguments.length >= 1` case is in `preprocess` function.
618
+ case "CallExpression":
619
+ if (node.optional === true && node.arguments.length === 0) {
620
+ CodePath.getState(analyzer.codePath).makeOptionalRight();
621
+ }
622
+ break;
623
+
586
624
  default:
587
625
  break;
588
626
  }
@@ -92,7 +92,6 @@ class CodePathSegment {
92
92
  /* istanbul ignore if */
93
93
  if (debug.enabled) {
94
94
  this.internal.nodes = [];
95
- this.internal.exitNodes = [];
96
95
  }
97
96
  }
98
97
 
@@ -234,6 +234,7 @@ class CodePathState {
234
234
  this.tryContext = null;
235
235
  this.loopContext = null;
236
236
  this.breakContext = null;
237
+ this.chainContext = null;
237
238
 
238
239
  this.currentSegments = [];
239
240
  this.initialSegment = this.forkContext.head[0];
@@ -555,6 +556,64 @@ class CodePathState {
555
556
  );
556
557
  }
557
558
 
559
+ //--------------------------------------------------------------------------
560
+ // ChainExpression
561
+ //--------------------------------------------------------------------------
562
+
563
+ /**
564
+ * Push a new `ChainExpression` context to the stack.
565
+ * This method is called on entering to each `ChainExpression` node.
566
+ * This context is used to count forking in the optional chain then merge them on the exiting from the `ChainExpression` node.
567
+ * @returns {void}
568
+ */
569
+ pushChainContext() {
570
+ this.chainContext = {
571
+ upper: this.chainContext,
572
+ countChoiceContexts: 0
573
+ };
574
+ }
575
+
576
+ /**
577
+ * Pop a `ChainExpression` context from the stack.
578
+ * This method is called on exiting from each `ChainExpression` node.
579
+ * This merges all forks of the last optional chaining.
580
+ * @returns {void}
581
+ */
582
+ popChainContext() {
583
+ const context = this.chainContext;
584
+
585
+ this.chainContext = context.upper;
586
+
587
+ // pop all choice contexts of this.
588
+ for (let i = context.countChoiceContexts; i > 0; --i) {
589
+ this.popChoiceContext();
590
+ }
591
+ }
592
+
593
+ /**
594
+ * Create a choice context for optional access.
595
+ * This method is called on entering to each `(Call|Member)Expression[optional=true]` node.
596
+ * This creates a choice context as similar to `LogicalExpression[operator="??"]` node.
597
+ * @returns {void}
598
+ */
599
+ makeOptionalNode() {
600
+ if (this.chainContext) {
601
+ this.chainContext.countChoiceContexts += 1;
602
+ this.pushChoiceContext("??", false);
603
+ }
604
+ }
605
+
606
+ /**
607
+ * Create a fork.
608
+ * This method is called on entering to the `arguments|property` property of each `(Call|Member)Expression` node.
609
+ * @returns {void}
610
+ */
611
+ makeOptionalRight() {
612
+ if (this.chainContext) {
613
+ this.makeLogicalRight();
614
+ }
615
+ }
616
+
558
617
  //--------------------------------------------------------------------------
559
618
  // SwitchStatement
560
619
  //--------------------------------------------------------------------------