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.
- package/index.js +4 -0
- package/package.json +6 -3
- package/readme.md +153 -16
- package/rules/ast/is-empty-node.js +1 -5
- package/rules/better-dom-traversing.js +17 -8
- package/rules/class-reference-in-static-methods.js +14 -2
- package/rules/consistent-assert.js +1 -1
- package/rules/consistent-boolean-name.js +15 -3
- package/rules/consistent-compound-words.js +7 -5
- package/rules/consistent-conditional-object-spread.js +354 -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/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 +38 -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-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 +22 -11
- package/rules/no-instanceof-builtins.js +14 -1
- 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-keyword-prefix.js +14 -4
- package/rules/no-late-current-target-access.js +7 -39
- 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 +1381 -0
- package/rules/no-process-exit.js +16 -12
- package/rules/no-redundant-comparison.js +5 -12
- package/rules/no-selector-as-dom-name.js +150 -0
- package/rules/no-thenable.js +27 -11
- 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-splice.js +15 -20
- package/rules/no-unreadable-for-of-expression.js +2 -1
- package/rules/no-unsafe-property-key.js +10 -15
- package/rules/no-unused-properties.js +4 -3
- package/rules/no-useless-coercion.js +71 -15
- package/rules/no-useless-compound-assignment.js +110 -0
- package/rules/no-useless-delete-check.js +353 -0
- package/rules/no-useless-else.js +16 -65
- 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-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-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 +1 -24
- package/rules/prefer-await.js +29 -0
- package/rules/prefer-boolean-return.js +224 -0
- package/rules/prefer-continue.js +361 -0
- package/rules/prefer-default-parameters.js +10 -6
- package/rules/prefer-dispose.js +1 -5
- package/rules/prefer-early-return.js +160 -30
- package/rules/prefer-else-if.js +50 -53
- 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-hoisting-branch-code.js +422 -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-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 +26 -2
- 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-optional-catch-binding.js +30 -24
- package/rules/prefer-private-class-fields.js +2 -8
- 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-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-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-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/{abbreviations.js → name-replacements.js} +57 -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/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 +32 -2
- package/rules/utils/is-boolean.js +23 -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/track-branch-exits.js +79 -0
- 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 '
|
|
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
|
|
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;
|
|
@@ -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;
|