eslint-plugin-unicorn 67.0.0 → 68.0.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 (157) hide show
  1. package/index.js +4 -0
  2. package/package.json +6 -3
  3. package/readme.md +153 -16
  4. package/rules/ast/is-empty-node.js +1 -5
  5. package/rules/better-dom-traversing.js +17 -8
  6. package/rules/class-reference-in-static-methods.js +14 -2
  7. package/rules/consistent-assert.js +1 -1
  8. package/rules/consistent-boolean-name.js +15 -3
  9. package/rules/consistent-compound-words.js +7 -5
  10. package/rules/consistent-conditional-object-spread.js +354 -0
  11. package/rules/consistent-destructuring.js +5 -0
  12. package/rules/consistent-existence-index-check.js +1 -1
  13. package/rules/consistent-json-file-read.js +4 -16
  14. package/rules/consistent-optional-chaining.js +3 -20
  15. package/rules/default-export-style.js +569 -0
  16. package/rules/expiring-todo-comments.js +1 -1
  17. package/rules/explicit-length-check.js +7 -32
  18. package/rules/import-style.js +8 -6
  19. package/rules/index.js +38 -1
  20. package/rules/logical-assignment-operators.js +17 -4
  21. package/rules/{prevent-abbreviations.js → name-replacements.js} +11 -9
  22. package/rules/new-for-builtins.js +39 -5
  23. package/rules/no-accessor-recursion.js +7 -0
  24. package/rules/no-accidental-bitwise-operator.js +97 -0
  25. package/rules/no-array-callback-reference.js +1 -7
  26. package/rules/no-array-concat-in-loop.js +45 -0
  27. package/rules/no-array-front-mutation.js +64 -0
  28. package/rules/no-array-sort-for-min-max.js +225 -0
  29. package/rules/no-array-splice.js +78 -64
  30. package/rules/no-boolean-sort-comparator.js +215 -0
  31. package/rules/no-break-in-nested-loop.js +33 -0
  32. package/rules/no-chained-comparison.js +116 -0
  33. package/rules/no-collection-bracket-access.js +165 -0
  34. package/rules/no-confusing-array-splice.js +2 -21
  35. package/rules/no-confusing-array-with.js +2 -20
  36. package/rules/no-constant-zero-expression.js +91 -0
  37. package/rules/no-declarations-before-early-exit.js +29 -36
  38. package/rules/no-double-comparison.js +117 -0
  39. package/rules/no-duplicate-if-branches.js +143 -0
  40. package/rules/no-duplicate-logical-operands.js +151 -0
  41. package/rules/no-for-each.js +11 -12
  42. package/rules/no-for-loop.js +3 -15
  43. package/rules/no-impossible-length-comparison.js +166 -0
  44. package/rules/no-incorrect-query-selector.js +8 -4
  45. package/rules/no-incorrect-template-string-interpolation.js +22 -11
  46. package/rules/no-instanceof-builtins.js +14 -1
  47. package/rules/no-invalid-argument-count.js +110 -54
  48. package/rules/no-invalid-character-comparison.js +121 -0
  49. package/rules/no-invalid-fetch-options.js +3 -1
  50. package/rules/no-keyword-prefix.js +14 -4
  51. package/rules/no-late-current-target-access.js +7 -39
  52. package/rules/no-loop-iterable-mutation.js +541 -0
  53. package/rules/no-manually-wrapped-comments.js +10 -2
  54. package/rules/no-misrefactored-assignment.js +102 -0
  55. package/rules/no-named-default.js +35 -2
  56. package/rules/no-nonstandard-builtin-properties.js +1381 -0
  57. package/rules/no-process-exit.js +16 -12
  58. package/rules/no-redundant-comparison.js +5 -12
  59. package/rules/no-selector-as-dom-name.js +150 -0
  60. package/rules/no-thenable.js +27 -11
  61. package/rules/no-uncalled-method.js +2 -8
  62. package/rules/no-undeclared-class-members.js +8 -6
  63. package/rules/no-unnecessary-boolean-comparison.js +131 -0
  64. package/rules/no-unnecessary-splice.js +15 -20
  65. package/rules/no-unreadable-for-of-expression.js +2 -1
  66. package/rules/no-unsafe-property-key.js +10 -15
  67. package/rules/no-unused-properties.js +4 -3
  68. package/rules/no-useless-coercion.js +71 -15
  69. package/rules/no-useless-compound-assignment.js +110 -0
  70. package/rules/no-useless-delete-check.js +353 -0
  71. package/rules/no-useless-else.js +16 -65
  72. package/rules/no-useless-error-capture-stack-trace.js +1 -1
  73. package/rules/no-useless-fallback-in-spread.js +7 -118
  74. package/rules/no-useless-logical-operand.js +248 -0
  75. package/rules/no-useless-undefined.js +11 -28
  76. package/rules/no-xor-as-exponentiation.js +59 -0
  77. package/rules/prefer-array-find.js +95 -5
  78. package/rules/prefer-array-flat-map.js +9 -21
  79. package/rules/prefer-array-flat.js +1 -24
  80. package/rules/prefer-array-from-async.js +273 -0
  81. package/rules/prefer-array-iterable-methods.js +157 -0
  82. package/rules/prefer-array-some.js +56 -31
  83. package/rules/prefer-at.js +1 -24
  84. package/rules/prefer-await.js +29 -0
  85. package/rules/prefer-boolean-return.js +224 -0
  86. package/rules/prefer-continue.js +361 -0
  87. package/rules/prefer-default-parameters.js +10 -6
  88. package/rules/prefer-dispose.js +1 -5
  89. package/rules/prefer-early-return.js +160 -30
  90. package/rules/prefer-else-if.js +50 -53
  91. package/rules/prefer-event-target.js +3 -13
  92. package/rules/prefer-flat-math-min-max.js +103 -0
  93. package/rules/prefer-global-this.js +1 -1
  94. package/rules/prefer-hoisting-branch-code.js +422 -0
  95. package/rules/prefer-identifier-import-export-specifiers.js +6 -11
  96. package/rules/prefer-includes-over-repeated-comparisons.js +5 -1
  97. package/rules/prefer-includes.js +6 -0
  98. package/rules/prefer-logical-operator-over-ternary.js +12 -20
  99. package/rules/prefer-math-constants.js +103 -0
  100. package/rules/prefer-math-min-max.js +1 -5
  101. package/rules/prefer-minimal-ternary.js +26 -2
  102. package/rules/prefer-node-protocol.js +1 -0
  103. package/rules/prefer-number-properties.js +2 -5
  104. package/rules/prefer-object-from-entries.js +6 -1
  105. package/rules/prefer-object-iterable-methods.js +36 -11
  106. package/rules/prefer-optional-catch-binding.js +30 -24
  107. package/rules/prefer-private-class-fields.js +2 -8
  108. package/rules/prefer-promise-with-resolvers.js +248 -0
  109. package/rules/prefer-query-selector.js +79 -17
  110. package/rules/prefer-queue-microtask.js +7 -9
  111. package/rules/prefer-regexp-escape.js +263 -0
  112. package/rules/prefer-set-size.js +10 -2
  113. package/rules/prefer-short-arrow-method.js +3 -3
  114. package/rules/prefer-single-replace.js +218 -0
  115. package/rules/prefer-spread.js +14 -21
  116. package/rules/prefer-string-replace-all.js +5 -0
  117. package/rules/prefer-structured-clone.js +2 -2
  118. package/rules/prefer-switch.js +1 -0
  119. package/rules/prefer-ternary.js +4 -2
  120. package/rules/prefer-type-literal-last.js +22 -54
  121. package/rules/prefer-unary-minus.js +103 -0
  122. package/rules/prefer-url-can-parse.js +308 -0
  123. package/rules/prefer-while-loop-condition.js +252 -0
  124. package/rules/require-passive-events.js +11 -4
  125. package/rules/require-proxy-trap-boolean-return.js +40 -126
  126. package/rules/rule/to-eslint-listener.js +5 -3
  127. package/rules/shared/array-concat-in-loop.js +151 -0
  128. package/rules/shared/identifier-checks.js +4 -16
  129. package/rules/shared/{abbreviations.js → name-replacements.js} +57 -0
  130. package/rules/shared/no-array-mutate-rule.js +19 -2
  131. package/rules/shared/regexp-escape.js +81 -0
  132. package/rules/shared/splice-replacements.js +1 -18
  133. package/rules/string-content.js +11 -4
  134. package/rules/template-indent.js +2 -8
  135. package/rules/throw-new-error.js +7 -0
  136. package/rules/utils/block-scope.js +42 -0
  137. package/rules/utils/builtins.js +50 -1
  138. package/rules/utils/comments.js +16 -0
  139. package/rules/utils/comparison.js +17 -0
  140. package/rules/utils/contains-suspension-point.js +35 -0
  141. package/rules/utils/get-const-variable-initializer.js +31 -0
  142. package/rules/utils/global-reference-tracker.js +14 -1
  143. package/rules/utils/has-optional-chain-element.js +36 -4
  144. package/rules/utils/index.js +32 -2
  145. package/rules/utils/is-boolean.js +23 -0
  146. package/rules/utils/is-function-self-used-inside.js +1 -5
  147. package/rules/utils/is-weak-map.js +21 -0
  148. package/rules/utils/is-weak-set.js +21 -0
  149. package/rules/utils/length-or-size.js +53 -0
  150. package/rules/utils/member-expression.js +18 -0
  151. package/rules/utils/needs-semicolon.js +1 -5
  152. package/rules/utils/numeric.js +20 -0
  153. package/rules/utils/should-add-parentheses-to-logical-expression-child.js +8 -14
  154. package/rules/utils/should-add-parentheses-to-member-expression-object.js +1 -5
  155. package/rules/utils/should-add-parentheses-to-unary-expression.js +8 -2
  156. package/rules/utils/track-branch-exits.js +79 -0
  157. package/rules/utils/types.js +22 -0
package/rules/index.js CHANGED
@@ -8,6 +8,7 @@ export {default as 'consistent-assert'} from './consistent-assert.js';
8
8
  export {default as 'consistent-boolean-name'} from './consistent-boolean-name.js';
9
9
  export {default as 'consistent-class-member-order'} from './consistent-class-member-order.js';
10
10
  export {default as 'consistent-compound-words'} from './consistent-compound-words.js';
11
+ export {default as 'consistent-conditional-object-spread'} from './consistent-conditional-object-spread.js';
11
12
  export {default as 'consistent-date-clone'} from './consistent-date-clone.js';
12
13
  export {default as 'consistent-destructuring'} from './consistent-destructuring.js';
13
14
  export {default as 'consistent-empty-array-spread'} from './consistent-empty-array-spread.js';
@@ -19,6 +20,7 @@ export {default as 'consistent-json-file-read'} from './consistent-json-file-rea
19
20
  export {default as 'consistent-optional-chaining'} from './consistent-optional-chaining.js';
20
21
  export {default as 'consistent-template-literal-escape'} from './consistent-template-literal-escape.js';
21
22
  export {default as 'custom-error-definition'} from './custom-error-definition.js';
23
+ export {default as 'default-export-style'} from './default-export-style.js';
22
24
  export {default as 'dom-node-dataset'} from './dom-node-dataset.js';
23
25
  export {default as 'empty-brace-spaces'} from './empty-brace-spaces.js';
24
26
  export {default as 'error-message'} from './error-message.js';
@@ -32,30 +34,42 @@ export {default as 'import-style'} from './import-style.js';
32
34
  export {default as 'isolated-functions'} from './isolated-functions.js';
33
35
  export {default as 'logical-assignment-operators'} from './logical-assignment-operators.js';
34
36
  export {default as 'max-nested-calls'} from './max-nested-calls.js';
37
+ export {default as 'name-replacements'} from './name-replacements.js';
35
38
  export {default as 'new-for-builtins'} from './new-for-builtins.js';
36
39
  export {default as 'no-abusive-eslint-disable'} from './no-abusive-eslint-disable.js';
37
40
  export {default as 'no-accessor-recursion'} from './no-accessor-recursion.js';
41
+ export {default as 'no-accidental-bitwise-operator'} from './no-accidental-bitwise-operator.js';
38
42
  export {default as 'no-anonymous-default-export'} from './no-anonymous-default-export.js';
39
43
  export {default as 'no-array-callback-reference'} from './no-array-callback-reference.js';
44
+ export {default as 'no-array-concat-in-loop'} from './no-array-concat-in-loop.js';
40
45
  export {default as 'no-array-fill-with-reference-type'} from './no-array-fill-with-reference-type.js';
41
46
  export {default as 'no-array-from-fill'} from './no-array-from-fill.js';
47
+ export {default as 'no-array-front-mutation'} from './no-array-front-mutation.js';
42
48
  export {default as 'no-array-method-this-argument'} from './no-array-method-this-argument.js';
43
49
  export {default as 'no-array-reduce'} from './no-array-reduce.js';
44
50
  export {default as 'no-array-reverse'} from './no-array-reverse.js';
51
+ export {default as 'no-array-sort-for-min-max'} from './no-array-sort-for-min-max.js';
45
52
  export {default as 'no-array-sort'} from './no-array-sort.js';
46
53
  export {default as 'no-array-splice'} from './no-array-splice.js';
47
54
  export {default as 'no-asterisk-prefix-in-documentation-comments'} from './no-asterisk-prefix-in-documentation-comments.js';
48
55
  export {default as 'no-await-expression-member'} from './no-await-expression-member.js';
49
56
  export {default as 'no-await-in-promise-methods'} from './no-await-in-promise-methods.js';
50
57
  export {default as 'no-blob-to-file'} from './no-blob-to-file.js';
58
+ export {default as 'no-boolean-sort-comparator'} from './no-boolean-sort-comparator.js';
51
59
  export {default as 'no-break-in-nested-loop'} from './no-break-in-nested-loop.js';
52
60
  export {default as 'no-canvas-to-image'} from './no-canvas-to-image.js';
61
+ export {default as 'no-chained-comparison'} from './no-chained-comparison.js';
62
+ export {default as 'no-collection-bracket-access'} from './no-collection-bracket-access.js';
53
63
  export {default as 'no-computed-property-existence-check'} from './no-computed-property-existence-check.js';
54
64
  export {default as 'no-confusing-array-splice'} from './no-confusing-array-splice.js';
55
65
  export {default as 'no-confusing-array-with'} from './no-confusing-array-with.js';
56
66
  export {default as 'no-console-spaces'} from './no-console-spaces.js';
67
+ export {default as 'no-constant-zero-expression'} from './no-constant-zero-expression.js';
57
68
  export {default as 'no-declarations-before-early-exit'} from './no-declarations-before-early-exit.js';
58
69
  export {default as 'no-document-cookie'} from './no-document-cookie.js';
70
+ export {default as 'no-double-comparison'} from './no-double-comparison.js';
71
+ export {default as 'no-duplicate-if-branches'} from './no-duplicate-if-branches.js';
72
+ export {default as 'no-duplicate-logical-operands'} from './no-duplicate-logical-operands.js';
59
73
  export {default as 'no-duplicate-loops'} from './no-duplicate-loops.js';
60
74
  export {default as 'no-duplicate-set-values'} from './no-duplicate-set-values.js';
61
75
  export {default as 'no-empty-file'} from './no-empty-file.js';
@@ -65,19 +79,23 @@ export {default as 'no-for-each'} from './no-for-each.js';
65
79
  export {default as 'no-for-loop'} from './no-for-loop.js';
66
80
  export {default as 'no-global-object-property-assignment'} from './no-global-object-property-assignment.js';
67
81
  export {default as 'no-immediate-mutation'} from './no-immediate-mutation.js';
82
+ export {default as 'no-impossible-length-comparison'} from './no-impossible-length-comparison.js';
68
83
  export {default as 'no-incorrect-query-selector'} from './no-incorrect-query-selector.js';
69
84
  export {default as 'no-incorrect-template-string-interpolation'} from './no-incorrect-template-string-interpolation.js';
70
85
  export {default as 'no-instanceof-builtins'} from './no-instanceof-builtins.js';
71
86
  export {default as 'no-invalid-argument-count'} from './no-invalid-argument-count.js';
87
+ export {default as 'no-invalid-character-comparison'} from './no-invalid-character-comparison.js';
72
88
  export {default as 'no-invalid-fetch-options'} from './no-invalid-fetch-options.js';
73
89
  export {default as 'no-invalid-file-input-accept'} from './no-invalid-file-input-accept.js';
74
90
  export {default as 'no-invalid-remove-event-listener'} from './no-invalid-remove-event-listener.js';
75
91
  export {default as 'no-keyword-prefix'} from './no-keyword-prefix.js';
76
92
  export {default as 'no-late-current-target-access'} from './no-late-current-target-access.js';
77
93
  export {default as 'no-lonely-if'} from './no-lonely-if.js';
94
+ export {default as 'no-loop-iterable-mutation'} from './no-loop-iterable-mutation.js';
78
95
  export {default as 'no-magic-array-flat-depth'} from './no-magic-array-flat-depth.js';
79
96
  export {default as 'no-manually-wrapped-comments'} from './no-manually-wrapped-comments.js';
80
97
  export {default as 'no-mismatched-map-key'} from './no-mismatched-map-key.js';
98
+ export {default as 'no-misrefactored-assignment'} from './no-misrefactored-assignment.js';
81
99
  export {default as 'no-named-default'} from './no-named-default.js';
82
100
  export {default as 'no-negated-array-predicate'} from './no-negated-array-predicate.js';
83
101
  export {default as 'no-negated-comparison'} from './no-negated-comparison.js';
@@ -87,6 +105,7 @@ export {default as 'no-nested-ternary'} from './no-nested-ternary.js';
87
105
  export {default as 'no-new-array'} from './no-new-array.js';
88
106
  export {default as 'no-new-buffer'} from './no-new-buffer.js';
89
107
  export {default as 'no-non-function-verb-prefix'} from './no-non-function-verb-prefix.js';
108
+ export {default as 'no-nonstandard-builtin-properties'} from './no-nonstandard-builtin-properties.js';
90
109
  export {default as 'no-null'} from './no-null.js';
91
110
  export {default as 'no-object-as-default-parameter'} from './no-object-as-default-parameter.js';
92
111
  export {default as 'no-object-methods-with-collections'} from './no-object-methods-with-collections.js';
@@ -94,6 +113,7 @@ export {default as 'no-optional-chaining-on-undeclared-variable'} from './no-opt
94
113
  export {default as 'no-process-exit'} from './no-process-exit.js';
95
114
  export {default as 'no-redundant-comparison'} from './no-redundant-comparison.js';
96
115
  export {default as 'no-return-array-push'} from './no-return-array-push.js';
116
+ export {default as 'no-selector-as-dom-name'} from './no-selector-as-dom-name.js';
97
117
  export {default as 'no-single-promise-in-promise-methods'} from './no-single-promise-in-promise-methods.js';
98
118
  export {default as 'no-static-only-class'} from './no-static-only-class.js';
99
119
  export {default as 'no-subtraction-comparison'} from './no-subtraction-comparison.js';
@@ -108,6 +128,7 @@ export {default as 'no-undeclared-class-members'} from './no-undeclared-class-me
108
128
  export {default as 'no-unnecessary-array-flat-depth'} from './no-unnecessary-array-flat-depth.js';
109
129
  export {default as 'no-unnecessary-array-splice-count'} from './no-unnecessary-array-splice-count.js';
110
130
  export {default as 'no-unnecessary-await'} from './no-unnecessary-await.js';
131
+ export {default as 'no-unnecessary-boolean-comparison'} from './no-unnecessary-boolean-comparison.js';
111
132
  export {default as 'no-unnecessary-global-this'} from './no-unnecessary-global-this.js';
112
133
  export {default as 'no-unnecessary-nested-ternary'} from './no-unnecessary-nested-ternary.js';
113
134
  export {default as 'no-unnecessary-polyfills'} from './no-unnecessary-polyfills.js';
@@ -127,13 +148,16 @@ export {default as 'no-unused-properties'} from './no-unused-properties.js';
127
148
  export {default as 'no-useless-boolean-cast'} from './no-useless-boolean-cast.js';
128
149
  export {default as 'no-useless-coercion'} from './no-useless-coercion.js';
129
150
  export {default as 'no-useless-collection-argument'} from './no-useless-collection-argument.js';
151
+ export {default as 'no-useless-compound-assignment'} from './no-useless-compound-assignment.js';
130
152
  export {default as 'no-useless-concat'} from './no-useless-concat.js';
131
153
  export {default as 'no-useless-continue'} from './no-useless-continue.js';
154
+ export {default as 'no-useless-delete-check'} from './no-useless-delete-check.js';
132
155
  export {default as 'no-useless-else'} from './no-useless-else.js';
133
156
  export {default as 'no-useless-error-capture-stack-trace'} from './no-useless-error-capture-stack-trace.js';
134
157
  export {default as 'no-useless-fallback-in-spread'} from './no-useless-fallback-in-spread.js';
135
158
  export {default as 'no-useless-iterator-to-array'} from './no-useless-iterator-to-array.js';
136
159
  export {default as 'no-useless-length-check'} from './no-useless-length-check.js';
160
+ export {default as 'no-useless-logical-operand'} from './no-useless-logical-operand.js';
137
161
  export {default as 'no-useless-override'} from './no-useless-override.js';
138
162
  export {default as 'no-useless-promise-resolve-reject'} from './no-useless-promise-resolve-reject.js';
139
163
  export {default as 'no-useless-recursion'} from './no-useless-recursion.js';
@@ -141,6 +165,7 @@ export {default as 'no-useless-spread'} from './no-useless-spread.js';
141
165
  export {default as 'no-useless-switch-case'} from './no-useless-switch-case.js';
142
166
  export {default as 'no-useless-template-literals'} from './no-useless-template-literals.js';
143
167
  export {default as 'no-useless-undefined'} from './no-useless-undefined.js';
168
+ export {default as 'no-xor-as-exponentiation'} from './no-xor-as-exponentiation.js';
144
169
  export {default as 'no-zero-fractions'} from './no-zero-fractions.js';
145
170
  export {default as 'number-literal-case'} from './number-literal-case.js';
146
171
  export {default as 'numeric-separators-style'} from './numeric-separators-style.js';
@@ -150,8 +175,10 @@ export {default as 'prefer-add-event-listener'} from './prefer-add-event-listene
150
175
  export {default as 'prefer-array-find'} from './prefer-array-find.js';
151
176
  export {default as 'prefer-array-flat-map'} from './prefer-array-flat-map.js';
152
177
  export {default as 'prefer-array-flat'} from './prefer-array-flat.js';
178
+ export {default as 'prefer-array-from-async'} from './prefer-array-from-async.js';
153
179
  export {default as 'prefer-array-from-map'} from './prefer-array-from-map.js';
154
180
  export {default as 'prefer-array-index-of'} from './prefer-array-index-of.js';
181
+ export {default as 'prefer-array-iterable-methods'} from './prefer-array-iterable-methods.js';
155
182
  export {default as 'prefer-array-last-methods'} from './prefer-array-last-methods.js';
156
183
  export {default as 'prefer-array-slice'} from './prefer-array-slice.js';
157
184
  export {default as 'prefer-array-some'} from './prefer-array-some.js';
@@ -159,9 +186,11 @@ export {default as 'prefer-at'} from './prefer-at.js';
159
186
  export {default as 'prefer-await'} from './prefer-await.js';
160
187
  export {default as 'prefer-bigint-literals'} from './prefer-bigint-literals.js';
161
188
  export {default as 'prefer-blob-reading-methods'} from './prefer-blob-reading-methods.js';
189
+ export {default as 'prefer-boolean-return'} from './prefer-boolean-return.js';
162
190
  export {default as 'prefer-class-fields'} from './prefer-class-fields.js';
163
191
  export {default as 'prefer-classlist-toggle'} from './prefer-classlist-toggle.js';
164
192
  export {default as 'prefer-code-point'} from './prefer-code-point.js';
193
+ export {default as 'prefer-continue'} from './prefer-continue.js';
165
194
  export {default as 'prefer-date-now'} from './prefer-date-now.js';
166
195
  export {default as 'prefer-default-parameters'} from './prefer-default-parameters.js';
167
196
  export {default as 'prefer-direct-iteration'} from './prefer-direct-iteration.js';
@@ -174,10 +203,12 @@ export {default as 'prefer-early-return'} from './prefer-early-return.js';
174
203
  export {default as 'prefer-else-if'} from './prefer-else-if.js';
175
204
  export {default as 'prefer-event-target'} from './prefer-event-target.js';
176
205
  export {default as 'prefer-export-from'} from './prefer-export-from.js';
206
+ export {default as 'prefer-flat-math-min-max'} from './prefer-flat-math-min-max.js';
177
207
  export {default as 'prefer-get-or-insert-computed'} from './prefer-get-or-insert-computed.js';
178
208
  export {default as 'prefer-global-number-constants'} from './prefer-global-number-constants.js';
179
209
  export {default as 'prefer-global-this'} from './prefer-global-this.js';
180
210
  export {default as 'prefer-has-check'} from './prefer-has-check.js';
211
+ export {default as 'prefer-hoisting-branch-code'} from './prefer-hoisting-branch-code.js';
181
212
  export {default as 'prefer-https'} from './prefer-https.js';
182
213
  export {default as 'prefer-identifier-import-export-specifiers'} from './prefer-identifier-import-export-specifiers.js';
183
214
  export {default as 'prefer-import-meta-properties'} from './prefer-import-meta-properties.js';
@@ -192,6 +223,7 @@ export {default as 'prefer-location-assign'} from './prefer-location-assign.js';
192
223
  export {default as 'prefer-logical-operator-over-ternary'} from './prefer-logical-operator-over-ternary.js';
193
224
  export {default as 'prefer-map-from-entries'} from './prefer-map-from-entries.js';
194
225
  export {default as 'prefer-math-abs'} from './prefer-math-abs.js';
226
+ export {default as 'prefer-math-constants'} from './prefer-math-constants.js';
195
227
  export {default as 'prefer-math-min-max'} from './prefer-math-min-max.js';
196
228
  export {default as 'prefer-math-trunc'} from './prefer-math-trunc.js';
197
229
  export {default as 'prefer-minimal-ternary'} from './prefer-minimal-ternary.js';
@@ -211,10 +243,12 @@ export {default as 'prefer-object-iterable-methods'} from './prefer-object-itera
211
243
  export {default as 'prefer-optional-catch-binding'} from './prefer-optional-catch-binding.js';
212
244
  export {default as 'prefer-path2d'} from './prefer-path2d.js';
213
245
  export {default as 'prefer-private-class-fields'} from './prefer-private-class-fields.js';
246
+ export {default as 'prefer-promise-with-resolvers'} from './prefer-promise-with-resolvers.js';
214
247
  export {default as 'prefer-prototype-methods'} from './prefer-prototype-methods.js';
215
248
  export {default as 'prefer-query-selector'} from './prefer-query-selector.js';
216
249
  export {default as 'prefer-queue-microtask'} from './prefer-queue-microtask.js';
217
250
  export {default as 'prefer-reflect-apply'} from './prefer-reflect-apply.js';
251
+ export {default as 'prefer-regexp-escape'} from './prefer-regexp-escape.js';
218
252
  export {default as 'prefer-regexp-test'} from './prefer-regexp-test.js';
219
253
  export {default as 'prefer-response-static-json'} from './prefer-response-static-json.js';
220
254
  export {default as 'prefer-scoped-selector'} from './prefer-scoped-selector.js';
@@ -226,6 +260,7 @@ export {default as 'prefer-simple-sort-comparator'} from './prefer-simple-sort-c
226
260
  export {default as 'prefer-single-array-predicate'} from './prefer-single-array-predicate.js';
227
261
  export {default as 'prefer-single-call'} from './prefer-single-call.js';
228
262
  export {default as 'prefer-single-object-destructuring'} from './prefer-single-object-destructuring.js';
263
+ export {default as 'prefer-single-replace'} from './prefer-single-replace.js';
229
264
  export {default as 'prefer-smaller-scope'} from './prefer-smaller-scope.js';
230
265
  export {default as 'prefer-split-limit'} from './prefer-split-limit.js';
231
266
  export {default as 'prefer-spread'} from './prefer-spread.js';
@@ -245,9 +280,11 @@ export {default as 'prefer-top-level-await'} from './prefer-top-level-await.js';
245
280
  export {default as 'prefer-type-error'} from './prefer-type-error.js';
246
281
  export {default as 'prefer-type-literal-last'} from './prefer-type-literal-last.js';
247
282
  export {default as 'prefer-uint8array-base64'} from './prefer-uint8array-base64.js';
283
+ export {default as 'prefer-unary-minus'} from './prefer-unary-minus.js';
248
284
  export {default as 'prefer-unicode-code-point-escapes'} from './prefer-unicode-code-point-escapes.js';
285
+ export {default as 'prefer-url-can-parse'} from './prefer-url-can-parse.js';
249
286
  export {default as 'prefer-url-href'} from './prefer-url-href.js';
250
- export {default as 'prevent-abbreviations'} from './prevent-abbreviations.js';
287
+ export {default as 'prefer-while-loop-condition'} from './prefer-while-loop-condition.js';
251
288
  export {default as 'relative-url-style'} from './relative-url-style.js';
252
289
  export {default as 'require-array-join-separator'} from './require-array-join-separator.js';
253
290
  export {default as 'require-array-sort-compare'} from './require-array-sort-compare.js';
@@ -3,12 +3,19 @@ import {getBuiltinRule} from './utils/index.js';
3
3
  const baseRule = getBuiltinRule('logical-assignment-operators');
4
4
 
5
5
  const MESSAGE_ID_IF = 'if';
6
+ const MESSAGE_ID_IF_NULLISH = 'ifNullish';
6
7
  const MESSAGE_ID_CONVERT_IF = 'convertIf';
7
8
  const LOGICAL_OR_ASSIGNMENT_OPERATOR = '||=';
8
9
  const LOGICAL_OR_OPERATOR = '||';
9
10
  const NULLISH_COALESCING_ASSIGNMENT_OPERATOR = '??=';
10
11
  const NULLISH_COALESCING_OPERATOR = '??';
11
12
 
13
+ const messages = {
14
+ ...baseRule.meta.messages,
15
+ // A falsy `if` assignment is offered as both `||=` and `??=`, so name both operators. The phrasing matches the base rule's `if` message, which renders the operator without backticks.
16
+ [MESSAGE_ID_IF_NULLISH]: '\'if\' statement can be replaced with a logical operator assignment with operator ||= or ??=.',
17
+ };
18
+
12
19
  const getFix = problem => problem.fix ?? problem.suggest?.[0]?.fix;
13
20
 
14
21
  const shouldAddNullishSuggestion = problem =>
@@ -46,14 +53,20 @@ function getProblem(problem, sourceCode) {
46
53
  return problem;
47
54
  }
48
55
 
56
+ // Both `||=` and `??=` apply here, so the message names both operators.
57
+ const problemWithMessage = {
58
+ ...withoutFixes(problem),
59
+ messageId: MESSAGE_ID_IF_NULLISH,
60
+ };
61
+
49
62
  if (sourceCode.getCommentsInside(problem.node).length > 0) {
50
- return withoutFixes(problem);
63
+ return problemWithMessage;
51
64
  }
52
65
 
53
66
  const fix = getFix(problem);
54
67
 
55
68
  return {
56
- ...withoutFixes(problem),
69
+ ...problemWithMessage,
57
70
  suggest: [
58
71
  {
59
72
  messageId: MESSAGE_ID_CONVERT_IF,
@@ -100,9 +113,9 @@ const config = {
100
113
  hasSuggestions: baseRule.meta.hasSuggestions,
101
114
  schema: baseRule.meta.schema,
102
115
  defaultOptions: [
103
- baseRule.meta.defaultOptions[0],
116
+ baseRule.meta.defaultOptions?.[0],
104
117
  ],
105
- messages: baseRule.meta.messages,
118
+ messages,
106
119
  languages: [
107
120
  'js/js',
108
121
  ],
@@ -10,7 +10,7 @@ import {
10
10
  lowerFirst,
11
11
  isVirtualFilename,
12
12
  } from './utils/index.js';
13
- import {defaultReplacements, defaultAllowList, defaultIgnore} from './shared/abbreviations.js';
13
+ import {defaultReplacements, defaultAllowList, defaultIgnore} from './shared/name-replacements.js';
14
14
  import {
15
15
  isClassVariable,
16
16
  shouldCheckDefaultOrNamespaceImportName,
@@ -465,13 +465,15 @@ const create = context => {
465
465
  return;
466
466
  }
467
467
 
468
- const identifierReplacements = getNameReplacements(node.name, options);
469
-
470
- if (identifierReplacements.total === 0) {
468
+ // The cheap AST check filters out non-property identifiers before the more
469
+ // expensive name analysis in `getNameReplacements`.
470
+ if (!shouldReportIdentifierAsProperty(node)) {
471
471
  return;
472
472
  }
473
473
 
474
- if (!shouldReportIdentifierAsProperty(node)) {
474
+ const identifierReplacements = getNameReplacements(node.name, options);
475
+
476
+ if (identifierReplacements.total === 0) {
475
477
  return;
476
478
  }
477
479
 
@@ -573,8 +575,8 @@ const schema = {
573
575
  description: 'Whether to extend the default replacements.',
574
576
  },
575
577
  replacements: {
576
- $ref: '#/definitions/abbreviations',
577
- description: 'Custom abbreviation replacements.',
578
+ $ref: '#/definitions/nameReplacements',
579
+ description: 'Custom name replacements.',
578
580
  },
579
581
  extendDefaultAllowList: {
580
582
  type: 'boolean',
@@ -593,7 +595,7 @@ const schema = {
593
595
  },
594
596
  ],
595
597
  definitions: {
596
- abbreviations: {
598
+ nameReplacements: {
597
599
  type: 'object',
598
600
  additionalProperties: {
599
601
  $ref: '#/definitions/replacements',
@@ -626,7 +628,7 @@ const config = {
626
628
  meta: {
627
629
  type: 'suggestion',
628
630
  docs: {
629
- description: 'Prevent abbreviations.',
631
+ description: 'Enforce replacements for variable, property, and filenames.',
630
632
  recommended: true,
631
633
  },
632
634
  fixable: 'code',
@@ -1,5 +1,6 @@
1
1
  import {GlobalReferenceTracker} from './utils/global-reference-tracker.js';
2
2
  import * as builtins from './utils/builtins.js';
3
+ import {hasOptionalChainElement} from './utils/index.js';
3
4
  import {
4
5
  switchCallExpressionToNewExpression,
5
6
  switchNewExpressionToCallExpression,
@@ -12,13 +13,23 @@ const MESSAGE_ID_SUGGESTION_DATE = 'suggestion-date';
12
13
  const messages = {
13
14
  enforce: 'Use `new {{name}}()` instead of `{{name}}()`.',
14
15
  disallow: 'Use `{{name}}()` instead of `new {{name}}()`.',
16
+ disallowCallOrNew: '`{{name}}` is not a function or constructor.',
15
17
  [MESSAGE_ID_ERROR_DATE]: 'Use `String(new Date())` instead of `Date()`.',
16
18
  [MESSAGE_ID_SUGGESTION_DATE]: 'Switch to `String(new Date())`.',
17
19
  };
18
20
 
21
+ const getName = reference => reference.path.join('.');
22
+ const hasOptionalChain = node => node.optional || hasOptionalChainElement(node.callee);
23
+
19
24
  function enforceNewExpression(reference, context) {
20
- const {node, path} = reference;
21
- const [name] = path;
25
+ const {node} = reference;
26
+
27
+ // An optional chain (`Array?.()` or `Intl?.DateTimeFormat()`) can't be rewritten to a `new` expression, which can't be optional.
28
+ if (hasOptionalChain(node)) {
29
+ return;
30
+ }
31
+
32
+ const name = getName(reference);
22
33
 
23
34
  if (name === 'Object') {
24
35
  const {parent} = node;
@@ -65,8 +76,8 @@ function enforceNewExpression(reference, context) {
65
76
  }
66
77
 
67
78
  function enforceCallExpression(reference, context) {
68
- const {node, path} = reference;
69
- const [name] = path;
79
+ const {node} = reference;
80
+ const name = getName(reference);
70
81
 
71
82
  const problem = {
72
83
  node,
@@ -81,6 +92,17 @@ function enforceCallExpression(reference, context) {
81
92
  return problem;
82
93
  }
83
94
 
95
+ function disallowCallOrNewExpression(reference) {
96
+ const {node} = reference;
97
+ const name = getName(reference);
98
+
99
+ return {
100
+ node,
101
+ messageId: 'disallowCallOrNew',
102
+ data: {name},
103
+ };
104
+ }
105
+
84
106
  const newExpressionTracker = new GlobalReferenceTracker({
85
107
  objects: builtins.disallowNew,
86
108
  type: GlobalReferenceTracker.CONSTRUCT,
@@ -91,11 +113,23 @@ const callExpressionTracker = new GlobalReferenceTracker({
91
113
  type: GlobalReferenceTracker.CALL,
92
114
  handle: enforceNewExpression,
93
115
  });
116
+ const callExpressionDisallowTracker = new GlobalReferenceTracker({
117
+ objects: builtins.disallowCallOrNew,
118
+ type: GlobalReferenceTracker.CALL,
119
+ handle: disallowCallOrNewExpression,
120
+ });
121
+ const newExpressionDisallowTracker = new GlobalReferenceTracker({
122
+ objects: builtins.disallowCallOrNew,
123
+ type: GlobalReferenceTracker.CONSTRUCT,
124
+ handle: disallowCallOrNewExpression,
125
+ });
94
126
 
95
127
  /** @param {import('eslint').Rule.RuleContext} context */
96
128
  const create = context => {
97
129
  newExpressionTracker.listen({context});
98
130
  callExpressionTracker.listen({context});
131
+ callExpressionDisallowTracker.listen({context});
132
+ newExpressionDisallowTracker.listen({context});
99
133
  };
100
134
 
101
135
  /** @type {import('eslint').Rule.RuleModule} */
@@ -104,7 +138,7 @@ const config = {
104
138
  meta: {
105
139
  type: 'suggestion',
106
140
  docs: {
107
- description: 'Enforce the use of `new` for all builtins, except `String`, `Number`, `Boolean`, `Symbol` and `BigInt`.',
141
+ description: 'Enforce correct use of `new` for builtin constructors.',
108
142
  recommended: 'unopinionated',
109
143
  },
110
144
  fixable: 'code',
@@ -101,6 +101,13 @@ const isPropertyWrite = (thisExpression, property) => {
101
101
  || (parent.type === 'UpdateExpression' && parent.argument === memberExpression)
102
102
  // `[this.foo] = …`
103
103
  || (parent.type === 'ArrayPattern' && parent.elements.includes(memberExpression))
104
+ // `[...this.foo] = …`
105
+ || (parent.type === 'RestElement' && parent.argument === memberExpression)
106
+ // `for (this.foo of …) {}` / `for (this.foo in …) {}`
107
+ || (
108
+ (parent.type === 'ForOfStatement' || parent.type === 'ForInStatement')
109
+ && parent.left === memberExpression
110
+ )
104
111
  // `({property: this.foo} = …)`
105
112
  || (
106
113
  parent.type === 'Property'
@@ -0,0 +1,97 @@
1
+ import {isStringLiteral, isBooleanLiteral, isFunction} from './ast/index.js';
2
+
3
+ /**
4
+ @import {TSESTree as ESTree} from '@typescript-eslint/types';
5
+ @import * as ESLint from 'eslint';
6
+ */
7
+
8
+ const MESSAGE_ID_ERROR = 'no-accidental-bitwise-operator/error';
9
+ const MESSAGE_ID_SUGGESTION = 'no-accidental-bitwise-operator/suggestion';
10
+ const messages = {
11
+ [MESSAGE_ID_ERROR]: 'Unexpected bitwise operator `{{bitwiseOperator}}`. Did you mean the logical operator `{{logicalOperator}}`?',
12
+ [MESSAGE_ID_SUGGESTION]: 'Replace `{{bitwiseOperator}}` with `{{logicalOperator}}`.',
13
+ };
14
+
15
+ const logicalOperators = new Map([
16
+ ['&', '&&'],
17
+ ['|', '||'],
18
+ ['|=', '||='],
19
+ ]);
20
+
21
+ // Value forms that make no sense as a bitwise operand, so the operator is almost
22
+ // certainly a mistyped logical operator. Intentionally excludes `null`, numeric
23
+ // literals, identifiers, and arithmetic expressions, which may be valid numbers.
24
+ const isDefinitelyNonNumeric = node =>
25
+ node.type === 'ObjectExpression'
26
+ || node.type === 'ArrayExpression'
27
+ || node.type === 'ClassExpression'
28
+ || node.type === 'TemplateLiteral'
29
+ || isFunction(node)
30
+ || isStringLiteral(node)
31
+ || isBooleanLiteral(node);
32
+
33
+ // `obj & obj.prop` is a mistyped short-circuit guard (`obj && obj.prop`).
34
+ const isShortCircuitGuard = node =>
35
+ node.operator === '&'
36
+ && node.left.type === 'Identifier'
37
+ && node.right.type === 'MemberExpression'
38
+ && node.right.object.type === 'Identifier'
39
+ && node.right.object.name === node.left.name;
40
+
41
+ // Either a mistyped short-circuit guard (`&`) or a mistyped logical fallback
42
+ // (`options | {}`, `input |= ''`), where the operator was almost certainly meant
43
+ // to be the logical counterpart.
44
+ const isSuspiciousBitwise = node =>
45
+ isShortCircuitGuard(node)
46
+ || ((node.operator === '|' || node.operator === '|=') && isDefinitelyNonNumeric(node.right));
47
+
48
+ /** @param {ESLint.Rule.RuleContext} context */
49
+ const create = context => {
50
+ const {sourceCode} = context;
51
+
52
+ context.on(['BinaryExpression', 'AssignmentExpression'], node => {
53
+ if (!isSuspiciousBitwise(node)) {
54
+ return;
55
+ }
56
+
57
+ const {operator} = node;
58
+ const logicalOperator = logicalOperators.get(operator);
59
+ const operatorToken = sourceCode.getTokenAfter(
60
+ node.left,
61
+ token => token.type === 'Punctuator' && token.value === operator,
62
+ );
63
+
64
+ return {
65
+ node: operatorToken,
66
+ messageId: MESSAGE_ID_ERROR,
67
+ data: {bitwiseOperator: operator, logicalOperator},
68
+ suggest: [
69
+ {
70
+ messageId: MESSAGE_ID_SUGGESTION,
71
+ data: {bitwiseOperator: operator, logicalOperator},
72
+ /** @param {ESLint.Rule.RuleFixer} fixer */
73
+ fix: fixer => fixer.replaceText(operatorToken, logicalOperator),
74
+ },
75
+ ],
76
+ };
77
+ });
78
+ };
79
+
80
+ /** @type {ESLint.Rule.RuleModule} */
81
+ const config = {
82
+ create,
83
+ meta: {
84
+ type: 'problem',
85
+ docs: {
86
+ description: 'Disallow bitwise operators where a logical operator was likely intended.',
87
+ recommended: 'unopinionated',
88
+ },
89
+ hasSuggestions: true,
90
+ messages,
91
+ languages: [
92
+ 'js/js',
93
+ ],
94
+ },
95
+ };
96
+
97
+ export default config;
@@ -151,13 +151,7 @@ const iteratorMethods = new Map([
151
151
 
152
152
  return shouldIgnoreCallExpression?.(callExpression) ?? false;
153
153
  },
154
- shouldIgnoreCallback(callback) {
155
- if (callback.type === 'Identifier' && ignore.includes(callback.name)) {
156
- return true;
157
- }
158
-
159
- return false;
160
- },
154
+ shouldIgnoreCallback: callback => Boolean(callback.type === 'Identifier' && ignore.includes(callback.name)),
161
155
  }]));
162
156
 
163
157
  const defaultIgnoredCallees = [
@@ -0,0 +1,45 @@
1
+ import {getArrayConcatInLoop} from './shared/array-concat-in-loop.js';
2
+
3
+ /**
4
+ @import * as ESLint from 'eslint';
5
+ */
6
+
7
+ const MESSAGE_ID = 'no-array-concat-in-loop';
8
+ const messages = {
9
+ [MESSAGE_ID]: 'Do not use `Array#concat()` to accumulate an array in a loop.',
10
+ };
11
+
12
+ /** @param {ESLint.Rule.RuleContext} context */
13
+ const create = context => {
14
+ context.on('AssignmentExpression', node => {
15
+ const problem = getArrayConcatInLoop(node, context);
16
+
17
+ if (!problem) {
18
+ return;
19
+ }
20
+
21
+ return {
22
+ node: problem.property,
23
+ messageId: MESSAGE_ID,
24
+ };
25
+ });
26
+ };
27
+
28
+ /** @type {ESLint.Rule.RuleModule} */
29
+ const config = {
30
+ create,
31
+ meta: {
32
+ type: 'suggestion',
33
+ docs: {
34
+ description: 'Disallow array accumulation with `Array#concat()` in loops.',
35
+ recommended: true,
36
+ },
37
+ schema: [],
38
+ messages,
39
+ languages: [
40
+ 'js/js',
41
+ ],
42
+ },
43
+ };
44
+
45
+ export default config;
@@ -0,0 +1,64 @@
1
+ import {isMethodCall} from './ast/index.js';
2
+ import {isNodeMatches, shouldSkipKnownNonArrayReceiver} from './utils/index.js';
3
+
4
+ const MESSAGE_ID = 'no-array-front-mutation';
5
+ const messages = {
6
+ [MESSAGE_ID]: 'Avoid front-of-array mutation with `Array#{{method}}()`.',
7
+ };
8
+
9
+ const ignoredUnshiftCallees = [
10
+ 'stream.unshift',
11
+ 'this.unshift',
12
+ 'this.stream.unshift',
13
+ 'process.stdin.unshift',
14
+ 'process.stdout.unshift',
15
+ 'process.stderr.unshift',
16
+ ];
17
+
18
+ /** @param {import('eslint').Rule.RuleContext} context */
19
+ const create = context => {
20
+ context.on('CallExpression', callExpression => {
21
+ if (!isMethodCall(callExpression, {
22
+ methods: ['shift', 'unshift'],
23
+ optionalCall: false,
24
+ computed: false,
25
+ })) {
26
+ return;
27
+ }
28
+
29
+ const {object, property} = callExpression.callee;
30
+ const {name: method} = property;
31
+
32
+ if (
33
+ (method === 'unshift' && isNodeMatches(callExpression.callee, ignoredUnshiftCallees))
34
+ || shouldSkipKnownNonArrayReceiver(object, context)
35
+ ) {
36
+ return;
37
+ }
38
+
39
+ return {
40
+ node: property,
41
+ messageId: MESSAGE_ID,
42
+ data: {method},
43
+ };
44
+ });
45
+ };
46
+
47
+ /** @type {import('eslint').Rule.RuleModule} */
48
+ const config = {
49
+ create,
50
+ meta: {
51
+ type: 'suggestion',
52
+ docs: {
53
+ description: 'Disallow front-of-array mutation.',
54
+ recommended: false,
55
+ },
56
+ schema: [],
57
+ messages,
58
+ languages: [
59
+ 'js/js',
60
+ ],
61
+ },
62
+ };
63
+
64
+ export default config;