eslint-plugin-unicorn 67.0.0 → 69.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.
- package/index.js +4 -0
- package/package.json +8 -3
- package/readme.md +165 -16
- package/rules/ast/is-empty-node.js +1 -5
- package/rules/ast/is-empty-object-expression.js +2 -2
- package/rules/better-dom-traversing.js +17 -8
- package/rules/class-reference-in-static-methods.js +14 -2
- package/rules/comment-content.js +136 -18
- package/rules/consistent-assert.js +1 -1
- package/rules/consistent-boolean-name.js +44 -5
- package/rules/consistent-compound-words.js +7 -5
- package/rules/consistent-conditional-object-spread.js +360 -0
- package/rules/consistent-destructuring.js +5 -0
- package/rules/consistent-existence-index-check.js +1 -1
- package/rules/consistent-json-file-read.js +4 -16
- package/rules/consistent-optional-chaining.js +3 -20
- package/rules/consistent-tuple-labels.js +49 -0
- package/rules/custom-error-definition.js +26 -7
- package/rules/default-export-style.js +569 -0
- package/rules/expiring-todo-comments.js +1 -1
- package/rules/explicit-length-check.js +7 -32
- package/rules/import-style.js +8 -6
- package/rules/index.js +50 -1
- package/rules/logical-assignment-operators.js +17 -4
- package/rules/{prevent-abbreviations.js → name-replacements.js} +11 -9
- package/rules/new-for-builtins.js +39 -5
- package/rules/no-accessor-recursion.js +7 -0
- package/rules/no-accidental-bitwise-operator.js +97 -0
- package/rules/no-array-callback-reference.js +1 -7
- package/rules/no-array-concat-in-loop.js +45 -0
- package/rules/no-array-front-mutation.js +64 -0
- package/rules/no-array-sort-for-min-max.js +225 -0
- package/rules/no-array-splice.js +78 -64
- package/rules/no-boolean-sort-comparator.js +215 -0
- package/rules/no-break-in-nested-loop.js +33 -0
- package/rules/no-chained-comparison.js +116 -0
- package/rules/no-collection-bracket-access.js +165 -0
- package/rules/no-computed-property-existence-check.js +6 -0
- package/rules/no-confusing-array-splice.js +2 -21
- package/rules/no-confusing-array-with.js +2 -20
- package/rules/no-constant-zero-expression.js +91 -0
- package/rules/no-declarations-before-early-exit.js +29 -36
- package/rules/no-double-comparison.js +117 -0
- package/rules/no-duplicate-if-branches.js +143 -0
- package/rules/no-duplicate-logical-operands.js +151 -0
- package/rules/no-for-each.js +11 -12
- package/rules/no-for-loop.js +3 -15
- package/rules/no-impossible-length-comparison.js +166 -0
- package/rules/no-incorrect-query-selector.js +8 -4
- package/rules/no-incorrect-template-string-interpolation.js +106 -43
- package/rules/no-instanceof-builtins.js +73 -14
- package/rules/no-invalid-argument-count.js +110 -54
- package/rules/no-invalid-character-comparison.js +121 -0
- package/rules/no-invalid-fetch-options.js +3 -1
- package/rules/no-invalid-well-known-symbol-methods.js +205 -0
- package/rules/no-keyword-prefix.js +14 -4
- package/rules/no-late-current-target-access.js +13 -107
- package/rules/no-late-event-control.js +127 -0
- package/rules/no-loop-iterable-mutation.js +541 -0
- package/rules/no-manually-wrapped-comments.js +10 -2
- package/rules/no-misrefactored-assignment.js +102 -0
- package/rules/no-named-default.js +35 -2
- package/rules/no-nonstandard-builtin-properties.js +1383 -0
- package/rules/no-object-methods-with-collections.js +4 -289
- package/rules/no-process-exit.js +16 -12
- package/rules/no-redundant-comparison.js +5 -12
- package/rules/no-return-array-push.js +20 -5
- package/rules/no-selector-as-dom-name.js +150 -0
- package/rules/no-thenable.js +27 -11
- package/rules/no-top-level-side-effects.js +8 -1
- package/rules/no-uncalled-method.js +2 -8
- package/rules/no-undeclared-class-members.js +8 -6
- package/rules/no-unnecessary-boolean-comparison.js +131 -0
- package/rules/no-unnecessary-global-this.js +36 -1
- package/rules/no-unnecessary-splice.js +15 -20
- package/rules/no-unreadable-for-of-expression.js +2 -1
- package/rules/no-unreadable-object-destructuring.js +15 -0
- package/rules/no-unsafe-property-key.js +10 -15
- package/rules/no-unsafe-string-replacement.js +31 -0
- package/rules/no-unused-array-method-return.js +11 -2
- package/rules/no-unused-properties.js +4 -3
- package/rules/no-useless-boolean-cast.js +58 -1
- package/rules/no-useless-coercion.js +71 -15
- package/rules/no-useless-compound-assignment.js +110 -0
- package/rules/no-useless-concat.js +27 -3
- package/rules/no-useless-delete-check.js +353 -0
- package/rules/no-useless-else.js +27 -62
- package/rules/no-useless-error-capture-stack-trace.js +1 -1
- package/rules/no-useless-fallback-in-spread.js +7 -118
- package/rules/no-useless-iterator-to-array.js +165 -115
- package/rules/no-useless-logical-operand.js +248 -0
- package/rules/no-useless-undefined.js +11 -28
- package/rules/no-xor-as-exponentiation.js +59 -0
- package/rules/prefer-abort-signal-timeout.js +395 -0
- package/rules/prefer-aggregate-error.js +478 -0
- package/rules/prefer-array-find.js +95 -5
- package/rules/prefer-array-flat-map.js +9 -21
- package/rules/prefer-array-flat.js +1 -24
- package/rules/prefer-array-from-async.js +273 -0
- package/rules/prefer-array-iterable-methods.js +157 -0
- package/rules/prefer-array-some.js +56 -31
- package/rules/prefer-at.js +6 -30
- package/rules/prefer-await.js +29 -0
- package/rules/prefer-boolean-return.js +224 -0
- package/rules/prefer-code-point.js +58 -8
- package/rules/prefer-continue.js +377 -0
- package/rules/prefer-default-parameters.js +10 -6
- package/rules/prefer-dispose.js +1 -5
- package/rules/prefer-dom-node-replace-children.js +353 -0
- package/rules/prefer-early-return.js +160 -30
- package/rules/prefer-else-if.js +50 -53
- package/rules/prefer-error-is-error.js +181 -0
- package/rules/prefer-event-target.js +3 -13
- package/rules/prefer-flat-math-min-max.js +103 -0
- package/rules/prefer-global-this.js +1 -1
- package/rules/prefer-has-check.js +1 -4
- package/rules/prefer-hoisting-branch-code.js +424 -0
- package/rules/prefer-identifier-import-export-specifiers.js +6 -11
- package/rules/prefer-includes-over-repeated-comparisons.js +5 -1
- package/rules/prefer-includes.js +6 -0
- package/rules/prefer-iterator-concat.js +21 -1
- package/rules/prefer-logical-operator-over-ternary.js +12 -20
- package/rules/prefer-math-constants.js +103 -0
- package/rules/prefer-math-min-max.js +1 -5
- package/rules/prefer-minimal-ternary.js +41 -13
- package/rules/prefer-modern-dom-apis.js +1 -45
- package/rules/prefer-node-protocol.js +1 -0
- package/rules/prefer-number-properties.js +2 -5
- package/rules/prefer-object-from-entries.js +6 -1
- package/rules/prefer-object-iterable-methods.js +36 -11
- package/rules/prefer-observer-apis.js +498 -0
- package/rules/prefer-optional-catch-binding.js +30 -24
- package/rules/prefer-private-class-fields.js +2 -8
- package/rules/prefer-promise-try.js +238 -0
- package/rules/prefer-promise-with-resolvers.js +248 -0
- package/rules/prefer-query-selector.js +79 -17
- package/rules/prefer-queue-microtask.js +7 -9
- package/rules/prefer-regexp-escape.js +263 -0
- package/rules/prefer-set-methods.js +337 -0
- package/rules/prefer-set-size.js +10 -2
- package/rules/prefer-short-arrow-method.js +3 -3
- package/rules/prefer-single-replace.js +218 -0
- package/rules/prefer-spread.js +14 -21
- package/rules/prefer-string-replace-all.js +5 -0
- package/rules/prefer-structured-clone.js +2 -2
- package/rules/prefer-switch.js +1 -0
- package/rules/prefer-ternary.js +4 -2
- package/rules/prefer-toggle-attribute.js +293 -0
- package/rules/prefer-type-literal-last.js +22 -54
- package/rules/prefer-unary-minus.js +103 -0
- package/rules/prefer-url-can-parse.js +308 -0
- package/rules/prefer-url-search-parameters.js +411 -0
- package/rules/prefer-while-loop-condition.js +252 -0
- package/rules/require-passive-events.js +11 -4
- package/rules/require-proxy-trap-boolean-return.js +40 -126
- package/rules/rule/to-eslint-listener.js +5 -3
- package/rules/shared/array-concat-in-loop.js +151 -0
- package/rules/shared/identifier-checks.js +4 -16
- package/rules/shared/late-event-handler.js +82 -0
- package/rules/shared/{abbreviations.js → name-replacements.js} +63 -0
- package/rules/shared/no-array-mutate-rule.js +19 -2
- package/rules/shared/regexp-escape.js +81 -0
- package/rules/shared/splice-replacements.js +1 -18
- package/rules/string-content.js +11 -4
- package/rules/template-indent.js +2 -8
- package/rules/throw-new-error.js +7 -0
- package/rules/utils/block-scope.js +42 -0
- package/rules/utils/builtin-collection-type.js +267 -0
- package/rules/utils/builtins.js +50 -1
- package/rules/utils/comments.js +16 -0
- package/rules/utils/comparison.js +17 -0
- package/rules/utils/contains-suspension-point.js +35 -0
- package/rules/utils/get-const-variable-initializer.js +31 -0
- package/rules/utils/global-reference-tracker.js +14 -1
- package/rules/utils/has-optional-chain-element.js +36 -4
- package/rules/utils/index.js +38 -2
- package/rules/utils/is-boolean.js +26 -1
- package/rules/utils/is-event.js +127 -0
- package/rules/utils/is-function-self-used-inside.js +1 -5
- package/rules/utils/is-weak-map.js +21 -0
- package/rules/utils/is-weak-set.js +21 -0
- package/rules/utils/length-or-size.js +53 -0
- package/rules/utils/member-expression.js +18 -0
- package/rules/utils/needs-semicolon.js +1 -5
- package/rules/utils/numeric.js +20 -0
- package/rules/utils/should-add-parentheses-to-logical-expression-child.js +8 -14
- package/rules/utils/should-add-parentheses-to-member-expression-object.js +1 -5
- package/rules/utils/should-add-parentheses-to-unary-expression.js +8 -2
- package/rules/utils/should-report-replace-children-receiver.js +210 -0
- package/rules/utils/track-branch-exits.js +79 -0
- package/rules/utils/type-helpers.js +166 -8
- 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';
|
|
@@ -18,7 +19,9 @@ export {default as 'consistent-function-style'} from './consistent-function-styl
|
|
|
18
19
|
export {default as 'consistent-json-file-read'} from './consistent-json-file-read.js';
|
|
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';
|
|
22
|
+
export {default as 'consistent-tuple-labels'} from './consistent-tuple-labels.js';
|
|
21
23
|
export {default as 'custom-error-definition'} from './custom-error-definition.js';
|
|
24
|
+
export {default as 'default-export-style'} from './default-export-style.js';
|
|
22
25
|
export {default as 'dom-node-dataset'} from './dom-node-dataset.js';
|
|
23
26
|
export {default as 'empty-brace-spaces'} from './empty-brace-spaces.js';
|
|
24
27
|
export {default as 'error-message'} from './error-message.js';
|
|
@@ -32,30 +35,42 @@ export {default as 'import-style'} from './import-style.js';
|
|
|
32
35
|
export {default as 'isolated-functions'} from './isolated-functions.js';
|
|
33
36
|
export {default as 'logical-assignment-operators'} from './logical-assignment-operators.js';
|
|
34
37
|
export {default as 'max-nested-calls'} from './max-nested-calls.js';
|
|
38
|
+
export {default as 'name-replacements'} from './name-replacements.js';
|
|
35
39
|
export {default as 'new-for-builtins'} from './new-for-builtins.js';
|
|
36
40
|
export {default as 'no-abusive-eslint-disable'} from './no-abusive-eslint-disable.js';
|
|
37
41
|
export {default as 'no-accessor-recursion'} from './no-accessor-recursion.js';
|
|
42
|
+
export {default as 'no-accidental-bitwise-operator'} from './no-accidental-bitwise-operator.js';
|
|
38
43
|
export {default as 'no-anonymous-default-export'} from './no-anonymous-default-export.js';
|
|
39
44
|
export {default as 'no-array-callback-reference'} from './no-array-callback-reference.js';
|
|
45
|
+
export {default as 'no-array-concat-in-loop'} from './no-array-concat-in-loop.js';
|
|
40
46
|
export {default as 'no-array-fill-with-reference-type'} from './no-array-fill-with-reference-type.js';
|
|
41
47
|
export {default as 'no-array-from-fill'} from './no-array-from-fill.js';
|
|
48
|
+
export {default as 'no-array-front-mutation'} from './no-array-front-mutation.js';
|
|
42
49
|
export {default as 'no-array-method-this-argument'} from './no-array-method-this-argument.js';
|
|
43
50
|
export {default as 'no-array-reduce'} from './no-array-reduce.js';
|
|
44
51
|
export {default as 'no-array-reverse'} from './no-array-reverse.js';
|
|
52
|
+
export {default as 'no-array-sort-for-min-max'} from './no-array-sort-for-min-max.js';
|
|
45
53
|
export {default as 'no-array-sort'} from './no-array-sort.js';
|
|
46
54
|
export {default as 'no-array-splice'} from './no-array-splice.js';
|
|
47
55
|
export {default as 'no-asterisk-prefix-in-documentation-comments'} from './no-asterisk-prefix-in-documentation-comments.js';
|
|
48
56
|
export {default as 'no-await-expression-member'} from './no-await-expression-member.js';
|
|
49
57
|
export {default as 'no-await-in-promise-methods'} from './no-await-in-promise-methods.js';
|
|
50
58
|
export {default as 'no-blob-to-file'} from './no-blob-to-file.js';
|
|
59
|
+
export {default as 'no-boolean-sort-comparator'} from './no-boolean-sort-comparator.js';
|
|
51
60
|
export {default as 'no-break-in-nested-loop'} from './no-break-in-nested-loop.js';
|
|
52
61
|
export {default as 'no-canvas-to-image'} from './no-canvas-to-image.js';
|
|
62
|
+
export {default as 'no-chained-comparison'} from './no-chained-comparison.js';
|
|
63
|
+
export {default as 'no-collection-bracket-access'} from './no-collection-bracket-access.js';
|
|
53
64
|
export {default as 'no-computed-property-existence-check'} from './no-computed-property-existence-check.js';
|
|
54
65
|
export {default as 'no-confusing-array-splice'} from './no-confusing-array-splice.js';
|
|
55
66
|
export {default as 'no-confusing-array-with'} from './no-confusing-array-with.js';
|
|
56
67
|
export {default as 'no-console-spaces'} from './no-console-spaces.js';
|
|
68
|
+
export {default as 'no-constant-zero-expression'} from './no-constant-zero-expression.js';
|
|
57
69
|
export {default as 'no-declarations-before-early-exit'} from './no-declarations-before-early-exit.js';
|
|
58
70
|
export {default as 'no-document-cookie'} from './no-document-cookie.js';
|
|
71
|
+
export {default as 'no-double-comparison'} from './no-double-comparison.js';
|
|
72
|
+
export {default as 'no-duplicate-if-branches'} from './no-duplicate-if-branches.js';
|
|
73
|
+
export {default as 'no-duplicate-logical-operands'} from './no-duplicate-logical-operands.js';
|
|
59
74
|
export {default as 'no-duplicate-loops'} from './no-duplicate-loops.js';
|
|
60
75
|
export {default as 'no-duplicate-set-values'} from './no-duplicate-set-values.js';
|
|
61
76
|
export {default as 'no-empty-file'} from './no-empty-file.js';
|
|
@@ -65,19 +80,25 @@ export {default as 'no-for-each'} from './no-for-each.js';
|
|
|
65
80
|
export {default as 'no-for-loop'} from './no-for-loop.js';
|
|
66
81
|
export {default as 'no-global-object-property-assignment'} from './no-global-object-property-assignment.js';
|
|
67
82
|
export {default as 'no-immediate-mutation'} from './no-immediate-mutation.js';
|
|
83
|
+
export {default as 'no-impossible-length-comparison'} from './no-impossible-length-comparison.js';
|
|
68
84
|
export {default as 'no-incorrect-query-selector'} from './no-incorrect-query-selector.js';
|
|
69
85
|
export {default as 'no-incorrect-template-string-interpolation'} from './no-incorrect-template-string-interpolation.js';
|
|
70
86
|
export {default as 'no-instanceof-builtins'} from './no-instanceof-builtins.js';
|
|
71
87
|
export {default as 'no-invalid-argument-count'} from './no-invalid-argument-count.js';
|
|
88
|
+
export {default as 'no-invalid-character-comparison'} from './no-invalid-character-comparison.js';
|
|
72
89
|
export {default as 'no-invalid-fetch-options'} from './no-invalid-fetch-options.js';
|
|
73
90
|
export {default as 'no-invalid-file-input-accept'} from './no-invalid-file-input-accept.js';
|
|
74
91
|
export {default as 'no-invalid-remove-event-listener'} from './no-invalid-remove-event-listener.js';
|
|
92
|
+
export {default as 'no-invalid-well-known-symbol-methods'} from './no-invalid-well-known-symbol-methods.js';
|
|
75
93
|
export {default as 'no-keyword-prefix'} from './no-keyword-prefix.js';
|
|
76
94
|
export {default as 'no-late-current-target-access'} from './no-late-current-target-access.js';
|
|
95
|
+
export {default as 'no-late-event-control'} from './no-late-event-control.js';
|
|
77
96
|
export {default as 'no-lonely-if'} from './no-lonely-if.js';
|
|
97
|
+
export {default as 'no-loop-iterable-mutation'} from './no-loop-iterable-mutation.js';
|
|
78
98
|
export {default as 'no-magic-array-flat-depth'} from './no-magic-array-flat-depth.js';
|
|
79
99
|
export {default as 'no-manually-wrapped-comments'} from './no-manually-wrapped-comments.js';
|
|
80
100
|
export {default as 'no-mismatched-map-key'} from './no-mismatched-map-key.js';
|
|
101
|
+
export {default as 'no-misrefactored-assignment'} from './no-misrefactored-assignment.js';
|
|
81
102
|
export {default as 'no-named-default'} from './no-named-default.js';
|
|
82
103
|
export {default as 'no-negated-array-predicate'} from './no-negated-array-predicate.js';
|
|
83
104
|
export {default as 'no-negated-comparison'} from './no-negated-comparison.js';
|
|
@@ -87,6 +108,7 @@ export {default as 'no-nested-ternary'} from './no-nested-ternary.js';
|
|
|
87
108
|
export {default as 'no-new-array'} from './no-new-array.js';
|
|
88
109
|
export {default as 'no-new-buffer'} from './no-new-buffer.js';
|
|
89
110
|
export {default as 'no-non-function-verb-prefix'} from './no-non-function-verb-prefix.js';
|
|
111
|
+
export {default as 'no-nonstandard-builtin-properties'} from './no-nonstandard-builtin-properties.js';
|
|
90
112
|
export {default as 'no-null'} from './no-null.js';
|
|
91
113
|
export {default as 'no-object-as-default-parameter'} from './no-object-as-default-parameter.js';
|
|
92
114
|
export {default as 'no-object-methods-with-collections'} from './no-object-methods-with-collections.js';
|
|
@@ -94,6 +116,7 @@ export {default as 'no-optional-chaining-on-undeclared-variable'} from './no-opt
|
|
|
94
116
|
export {default as 'no-process-exit'} from './no-process-exit.js';
|
|
95
117
|
export {default as 'no-redundant-comparison'} from './no-redundant-comparison.js';
|
|
96
118
|
export {default as 'no-return-array-push'} from './no-return-array-push.js';
|
|
119
|
+
export {default as 'no-selector-as-dom-name'} from './no-selector-as-dom-name.js';
|
|
97
120
|
export {default as 'no-single-promise-in-promise-methods'} from './no-single-promise-in-promise-methods.js';
|
|
98
121
|
export {default as 'no-static-only-class'} from './no-static-only-class.js';
|
|
99
122
|
export {default as 'no-subtraction-comparison'} from './no-subtraction-comparison.js';
|
|
@@ -108,6 +131,7 @@ export {default as 'no-undeclared-class-members'} from './no-undeclared-class-me
|
|
|
108
131
|
export {default as 'no-unnecessary-array-flat-depth'} from './no-unnecessary-array-flat-depth.js';
|
|
109
132
|
export {default as 'no-unnecessary-array-splice-count'} from './no-unnecessary-array-splice-count.js';
|
|
110
133
|
export {default as 'no-unnecessary-await'} from './no-unnecessary-await.js';
|
|
134
|
+
export {default as 'no-unnecessary-boolean-comparison'} from './no-unnecessary-boolean-comparison.js';
|
|
111
135
|
export {default as 'no-unnecessary-global-this'} from './no-unnecessary-global-this.js';
|
|
112
136
|
export {default as 'no-unnecessary-nested-ternary'} from './no-unnecessary-nested-ternary.js';
|
|
113
137
|
export {default as 'no-unnecessary-polyfills'} from './no-unnecessary-polyfills.js';
|
|
@@ -127,13 +151,16 @@ export {default as 'no-unused-properties'} from './no-unused-properties.js';
|
|
|
127
151
|
export {default as 'no-useless-boolean-cast'} from './no-useless-boolean-cast.js';
|
|
128
152
|
export {default as 'no-useless-coercion'} from './no-useless-coercion.js';
|
|
129
153
|
export {default as 'no-useless-collection-argument'} from './no-useless-collection-argument.js';
|
|
154
|
+
export {default as 'no-useless-compound-assignment'} from './no-useless-compound-assignment.js';
|
|
130
155
|
export {default as 'no-useless-concat'} from './no-useless-concat.js';
|
|
131
156
|
export {default as 'no-useless-continue'} from './no-useless-continue.js';
|
|
157
|
+
export {default as 'no-useless-delete-check'} from './no-useless-delete-check.js';
|
|
132
158
|
export {default as 'no-useless-else'} from './no-useless-else.js';
|
|
133
159
|
export {default as 'no-useless-error-capture-stack-trace'} from './no-useless-error-capture-stack-trace.js';
|
|
134
160
|
export {default as 'no-useless-fallback-in-spread'} from './no-useless-fallback-in-spread.js';
|
|
135
161
|
export {default as 'no-useless-iterator-to-array'} from './no-useless-iterator-to-array.js';
|
|
136
162
|
export {default as 'no-useless-length-check'} from './no-useless-length-check.js';
|
|
163
|
+
export {default as 'no-useless-logical-operand'} from './no-useless-logical-operand.js';
|
|
137
164
|
export {default as 'no-useless-override'} from './no-useless-override.js';
|
|
138
165
|
export {default as 'no-useless-promise-resolve-reject'} from './no-useless-promise-resolve-reject.js';
|
|
139
166
|
export {default as 'no-useless-recursion'} from './no-useless-recursion.js';
|
|
@@ -141,17 +168,22 @@ export {default as 'no-useless-spread'} from './no-useless-spread.js';
|
|
|
141
168
|
export {default as 'no-useless-switch-case'} from './no-useless-switch-case.js';
|
|
142
169
|
export {default as 'no-useless-template-literals'} from './no-useless-template-literals.js';
|
|
143
170
|
export {default as 'no-useless-undefined'} from './no-useless-undefined.js';
|
|
171
|
+
export {default as 'no-xor-as-exponentiation'} from './no-xor-as-exponentiation.js';
|
|
144
172
|
export {default as 'no-zero-fractions'} from './no-zero-fractions.js';
|
|
145
173
|
export {default as 'number-literal-case'} from './number-literal-case.js';
|
|
146
174
|
export {default as 'numeric-separators-style'} from './numeric-separators-style.js';
|
|
147
175
|
export {default as 'operator-assignment'} from './operator-assignment.js';
|
|
176
|
+
export {default as 'prefer-abort-signal-timeout'} from './prefer-abort-signal-timeout.js';
|
|
148
177
|
export {default as 'prefer-add-event-listener-options'} from './prefer-add-event-listener-options.js';
|
|
149
178
|
export {default as 'prefer-add-event-listener'} from './prefer-add-event-listener.js';
|
|
179
|
+
export {default as 'prefer-aggregate-error'} from './prefer-aggregate-error.js';
|
|
150
180
|
export {default as 'prefer-array-find'} from './prefer-array-find.js';
|
|
151
181
|
export {default as 'prefer-array-flat-map'} from './prefer-array-flat-map.js';
|
|
152
182
|
export {default as 'prefer-array-flat'} from './prefer-array-flat.js';
|
|
183
|
+
export {default as 'prefer-array-from-async'} from './prefer-array-from-async.js';
|
|
153
184
|
export {default as 'prefer-array-from-map'} from './prefer-array-from-map.js';
|
|
154
185
|
export {default as 'prefer-array-index-of'} from './prefer-array-index-of.js';
|
|
186
|
+
export {default as 'prefer-array-iterable-methods'} from './prefer-array-iterable-methods.js';
|
|
155
187
|
export {default as 'prefer-array-last-methods'} from './prefer-array-last-methods.js';
|
|
156
188
|
export {default as 'prefer-array-slice'} from './prefer-array-slice.js';
|
|
157
189
|
export {default as 'prefer-array-some'} from './prefer-array-some.js';
|
|
@@ -159,9 +191,11 @@ export {default as 'prefer-at'} from './prefer-at.js';
|
|
|
159
191
|
export {default as 'prefer-await'} from './prefer-await.js';
|
|
160
192
|
export {default as 'prefer-bigint-literals'} from './prefer-bigint-literals.js';
|
|
161
193
|
export {default as 'prefer-blob-reading-methods'} from './prefer-blob-reading-methods.js';
|
|
194
|
+
export {default as 'prefer-boolean-return'} from './prefer-boolean-return.js';
|
|
162
195
|
export {default as 'prefer-class-fields'} from './prefer-class-fields.js';
|
|
163
196
|
export {default as 'prefer-classlist-toggle'} from './prefer-classlist-toggle.js';
|
|
164
197
|
export {default as 'prefer-code-point'} from './prefer-code-point.js';
|
|
198
|
+
export {default as 'prefer-continue'} from './prefer-continue.js';
|
|
165
199
|
export {default as 'prefer-date-now'} from './prefer-date-now.js';
|
|
166
200
|
export {default as 'prefer-default-parameters'} from './prefer-default-parameters.js';
|
|
167
201
|
export {default as 'prefer-direct-iteration'} from './prefer-direct-iteration.js';
|
|
@@ -169,15 +203,19 @@ export {default as 'prefer-dispose'} from './prefer-dispose.js';
|
|
|
169
203
|
export {default as 'prefer-dom-node-append'} from './prefer-dom-node-append.js';
|
|
170
204
|
export {default as 'prefer-dom-node-html-methods'} from './prefer-dom-node-html-methods.js';
|
|
171
205
|
export {default as 'prefer-dom-node-remove'} from './prefer-dom-node-remove.js';
|
|
206
|
+
export {default as 'prefer-dom-node-replace-children'} from './prefer-dom-node-replace-children.js';
|
|
172
207
|
export {default as 'prefer-dom-node-text-content'} from './prefer-dom-node-text-content.js';
|
|
173
208
|
export {default as 'prefer-early-return'} from './prefer-early-return.js';
|
|
174
209
|
export {default as 'prefer-else-if'} from './prefer-else-if.js';
|
|
210
|
+
export {default as 'prefer-error-is-error'} from './prefer-error-is-error.js';
|
|
175
211
|
export {default as 'prefer-event-target'} from './prefer-event-target.js';
|
|
176
212
|
export {default as 'prefer-export-from'} from './prefer-export-from.js';
|
|
213
|
+
export {default as 'prefer-flat-math-min-max'} from './prefer-flat-math-min-max.js';
|
|
177
214
|
export {default as 'prefer-get-or-insert-computed'} from './prefer-get-or-insert-computed.js';
|
|
178
215
|
export {default as 'prefer-global-number-constants'} from './prefer-global-number-constants.js';
|
|
179
216
|
export {default as 'prefer-global-this'} from './prefer-global-this.js';
|
|
180
217
|
export {default as 'prefer-has-check'} from './prefer-has-check.js';
|
|
218
|
+
export {default as 'prefer-hoisting-branch-code'} from './prefer-hoisting-branch-code.js';
|
|
181
219
|
export {default as 'prefer-https'} from './prefer-https.js';
|
|
182
220
|
export {default as 'prefer-identifier-import-export-specifiers'} from './prefer-identifier-import-export-specifiers.js';
|
|
183
221
|
export {default as 'prefer-import-meta-properties'} from './prefer-import-meta-properties.js';
|
|
@@ -192,6 +230,7 @@ export {default as 'prefer-location-assign'} from './prefer-location-assign.js';
|
|
|
192
230
|
export {default as 'prefer-logical-operator-over-ternary'} from './prefer-logical-operator-over-ternary.js';
|
|
193
231
|
export {default as 'prefer-map-from-entries'} from './prefer-map-from-entries.js';
|
|
194
232
|
export {default as 'prefer-math-abs'} from './prefer-math-abs.js';
|
|
233
|
+
export {default as 'prefer-math-constants'} from './prefer-math-constants.js';
|
|
195
234
|
export {default as 'prefer-math-min-max'} from './prefer-math-min-max.js';
|
|
196
235
|
export {default as 'prefer-math-trunc'} from './prefer-math-trunc.js';
|
|
197
236
|
export {default as 'prefer-minimal-ternary'} from './prefer-minimal-ternary.js';
|
|
@@ -208,17 +247,22 @@ export {default as 'prefer-object-define-properties'} from './prefer-object-defi
|
|
|
208
247
|
export {default as 'prefer-object-destructuring-defaults'} from './prefer-object-destructuring-defaults.js';
|
|
209
248
|
export {default as 'prefer-object-from-entries'} from './prefer-object-from-entries.js';
|
|
210
249
|
export {default as 'prefer-object-iterable-methods'} from './prefer-object-iterable-methods.js';
|
|
250
|
+
export {default as 'prefer-observer-apis'} from './prefer-observer-apis.js';
|
|
211
251
|
export {default as 'prefer-optional-catch-binding'} from './prefer-optional-catch-binding.js';
|
|
212
252
|
export {default as 'prefer-path2d'} from './prefer-path2d.js';
|
|
213
253
|
export {default as 'prefer-private-class-fields'} from './prefer-private-class-fields.js';
|
|
254
|
+
export {default as 'prefer-promise-try'} from './prefer-promise-try.js';
|
|
255
|
+
export {default as 'prefer-promise-with-resolvers'} from './prefer-promise-with-resolvers.js';
|
|
214
256
|
export {default as 'prefer-prototype-methods'} from './prefer-prototype-methods.js';
|
|
215
257
|
export {default as 'prefer-query-selector'} from './prefer-query-selector.js';
|
|
216
258
|
export {default as 'prefer-queue-microtask'} from './prefer-queue-microtask.js';
|
|
217
259
|
export {default as 'prefer-reflect-apply'} from './prefer-reflect-apply.js';
|
|
260
|
+
export {default as 'prefer-regexp-escape'} from './prefer-regexp-escape.js';
|
|
218
261
|
export {default as 'prefer-regexp-test'} from './prefer-regexp-test.js';
|
|
219
262
|
export {default as 'prefer-response-static-json'} from './prefer-response-static-json.js';
|
|
220
263
|
export {default as 'prefer-scoped-selector'} from './prefer-scoped-selector.js';
|
|
221
264
|
export {default as 'prefer-set-has'} from './prefer-set-has.js';
|
|
265
|
+
export {default as 'prefer-set-methods'} from './prefer-set-methods.js';
|
|
222
266
|
export {default as 'prefer-set-size'} from './prefer-set-size.js';
|
|
223
267
|
export {default as 'prefer-short-arrow-method'} from './prefer-short-arrow-method.js';
|
|
224
268
|
export {default as 'prefer-simple-condition-first'} from './prefer-simple-condition-first.js';
|
|
@@ -226,6 +270,7 @@ export {default as 'prefer-simple-sort-comparator'} from './prefer-simple-sort-c
|
|
|
226
270
|
export {default as 'prefer-single-array-predicate'} from './prefer-single-array-predicate.js';
|
|
227
271
|
export {default as 'prefer-single-call'} from './prefer-single-call.js';
|
|
228
272
|
export {default as 'prefer-single-object-destructuring'} from './prefer-single-object-destructuring.js';
|
|
273
|
+
export {default as 'prefer-single-replace'} from './prefer-single-replace.js';
|
|
229
274
|
export {default as 'prefer-smaller-scope'} from './prefer-smaller-scope.js';
|
|
230
275
|
export {default as 'prefer-split-limit'} from './prefer-split-limit.js';
|
|
231
276
|
export {default as 'prefer-spread'} from './prefer-spread.js';
|
|
@@ -241,13 +286,17 @@ export {default as 'prefer-structured-clone'} from './prefer-structured-clone.js
|
|
|
241
286
|
export {default as 'prefer-switch'} from './prefer-switch.js';
|
|
242
287
|
export {default as 'prefer-temporal'} from './prefer-temporal.js';
|
|
243
288
|
export {default as 'prefer-ternary'} from './prefer-ternary.js';
|
|
289
|
+
export {default as 'prefer-toggle-attribute'} from './prefer-toggle-attribute.js';
|
|
244
290
|
export {default as 'prefer-top-level-await'} from './prefer-top-level-await.js';
|
|
245
291
|
export {default as 'prefer-type-error'} from './prefer-type-error.js';
|
|
246
292
|
export {default as 'prefer-type-literal-last'} from './prefer-type-literal-last.js';
|
|
247
293
|
export {default as 'prefer-uint8array-base64'} from './prefer-uint8array-base64.js';
|
|
294
|
+
export {default as 'prefer-unary-minus'} from './prefer-unary-minus.js';
|
|
248
295
|
export {default as 'prefer-unicode-code-point-escapes'} from './prefer-unicode-code-point-escapes.js';
|
|
296
|
+
export {default as 'prefer-url-can-parse'} from './prefer-url-can-parse.js';
|
|
249
297
|
export {default as 'prefer-url-href'} from './prefer-url-href.js';
|
|
250
|
-
export {default as '
|
|
298
|
+
export {default as 'prefer-url-search-parameters'} from './prefer-url-search-parameters.js';
|
|
299
|
+
export {default as 'prefer-while-loop-condition'} from './prefer-while-loop-condition.js';
|
|
251
300
|
export {default as 'relative-url-style'} from './relative-url-style.js';
|
|
252
301
|
export {default as 'require-array-join-separator'} from './require-array-join-separator.js';
|
|
253
302
|
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
|
|
63
|
+
return problemWithMessage;
|
|
51
64
|
}
|
|
52
65
|
|
|
53
66
|
const fix = getFix(problem);
|
|
54
67
|
|
|
55
68
|
return {
|
|
56
|
-
...
|
|
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
|
|
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/
|
|
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
|
-
|
|
469
|
-
|
|
470
|
-
if (
|
|
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
|
-
|
|
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/
|
|
577
|
-
description: 'Custom
|
|
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
|
-
|
|
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: '
|
|
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
|
|
21
|
-
|
|
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
|
|
69
|
-
const
|
|
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
|
|
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;
|