eslint-plugin-unicorn 67.0.0 → 68.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (157) hide show
  1. package/index.js +4 -0
  2. package/package.json +6 -3
  3. package/readme.md +153 -16
  4. package/rules/ast/is-empty-node.js +1 -5
  5. package/rules/better-dom-traversing.js +17 -8
  6. package/rules/class-reference-in-static-methods.js +14 -2
  7. package/rules/consistent-assert.js +1 -1
  8. package/rules/consistent-boolean-name.js +15 -3
  9. package/rules/consistent-compound-words.js +7 -5
  10. package/rules/consistent-conditional-object-spread.js +354 -0
  11. package/rules/consistent-destructuring.js +5 -0
  12. package/rules/consistent-existence-index-check.js +1 -1
  13. package/rules/consistent-json-file-read.js +4 -16
  14. package/rules/consistent-optional-chaining.js +3 -20
  15. package/rules/default-export-style.js +569 -0
  16. package/rules/expiring-todo-comments.js +1 -1
  17. package/rules/explicit-length-check.js +7 -32
  18. package/rules/import-style.js +8 -6
  19. package/rules/index.js +38 -1
  20. package/rules/logical-assignment-operators.js +17 -4
  21. package/rules/{prevent-abbreviations.js → name-replacements.js} +11 -9
  22. package/rules/new-for-builtins.js +39 -5
  23. package/rules/no-accessor-recursion.js +7 -0
  24. package/rules/no-accidental-bitwise-operator.js +97 -0
  25. package/rules/no-array-callback-reference.js +1 -7
  26. package/rules/no-array-concat-in-loop.js +45 -0
  27. package/rules/no-array-front-mutation.js +64 -0
  28. package/rules/no-array-sort-for-min-max.js +225 -0
  29. package/rules/no-array-splice.js +78 -64
  30. package/rules/no-boolean-sort-comparator.js +215 -0
  31. package/rules/no-break-in-nested-loop.js +33 -0
  32. package/rules/no-chained-comparison.js +116 -0
  33. package/rules/no-collection-bracket-access.js +165 -0
  34. package/rules/no-confusing-array-splice.js +2 -21
  35. package/rules/no-confusing-array-with.js +2 -20
  36. package/rules/no-constant-zero-expression.js +91 -0
  37. package/rules/no-declarations-before-early-exit.js +29 -36
  38. package/rules/no-double-comparison.js +117 -0
  39. package/rules/no-duplicate-if-branches.js +143 -0
  40. package/rules/no-duplicate-logical-operands.js +151 -0
  41. package/rules/no-for-each.js +11 -12
  42. package/rules/no-for-loop.js +3 -15
  43. package/rules/no-impossible-length-comparison.js +166 -0
  44. package/rules/no-incorrect-query-selector.js +8 -4
  45. package/rules/no-incorrect-template-string-interpolation.js +22 -11
  46. package/rules/no-instanceof-builtins.js +14 -1
  47. package/rules/no-invalid-argument-count.js +110 -54
  48. package/rules/no-invalid-character-comparison.js +121 -0
  49. package/rules/no-invalid-fetch-options.js +3 -1
  50. package/rules/no-keyword-prefix.js +14 -4
  51. package/rules/no-late-current-target-access.js +7 -39
  52. package/rules/no-loop-iterable-mutation.js +541 -0
  53. package/rules/no-manually-wrapped-comments.js +10 -2
  54. package/rules/no-misrefactored-assignment.js +102 -0
  55. package/rules/no-named-default.js +35 -2
  56. package/rules/no-nonstandard-builtin-properties.js +1381 -0
  57. package/rules/no-process-exit.js +16 -12
  58. package/rules/no-redundant-comparison.js +5 -12
  59. package/rules/no-selector-as-dom-name.js +150 -0
  60. package/rules/no-thenable.js +27 -11
  61. package/rules/no-uncalled-method.js +2 -8
  62. package/rules/no-undeclared-class-members.js +8 -6
  63. package/rules/no-unnecessary-boolean-comparison.js +131 -0
  64. package/rules/no-unnecessary-splice.js +15 -20
  65. package/rules/no-unreadable-for-of-expression.js +2 -1
  66. package/rules/no-unsafe-property-key.js +10 -15
  67. package/rules/no-unused-properties.js +4 -3
  68. package/rules/no-useless-coercion.js +71 -15
  69. package/rules/no-useless-compound-assignment.js +110 -0
  70. package/rules/no-useless-delete-check.js +353 -0
  71. package/rules/no-useless-else.js +16 -65
  72. package/rules/no-useless-error-capture-stack-trace.js +1 -1
  73. package/rules/no-useless-fallback-in-spread.js +7 -118
  74. package/rules/no-useless-logical-operand.js +248 -0
  75. package/rules/no-useless-undefined.js +11 -28
  76. package/rules/no-xor-as-exponentiation.js +59 -0
  77. package/rules/prefer-array-find.js +95 -5
  78. package/rules/prefer-array-flat-map.js +9 -21
  79. package/rules/prefer-array-flat.js +1 -24
  80. package/rules/prefer-array-from-async.js +273 -0
  81. package/rules/prefer-array-iterable-methods.js +157 -0
  82. package/rules/prefer-array-some.js +56 -31
  83. package/rules/prefer-at.js +1 -24
  84. package/rules/prefer-await.js +29 -0
  85. package/rules/prefer-boolean-return.js +224 -0
  86. package/rules/prefer-continue.js +361 -0
  87. package/rules/prefer-default-parameters.js +10 -6
  88. package/rules/prefer-dispose.js +1 -5
  89. package/rules/prefer-early-return.js +160 -30
  90. package/rules/prefer-else-if.js +50 -53
  91. package/rules/prefer-event-target.js +3 -13
  92. package/rules/prefer-flat-math-min-max.js +103 -0
  93. package/rules/prefer-global-this.js +1 -1
  94. package/rules/prefer-hoisting-branch-code.js +422 -0
  95. package/rules/prefer-identifier-import-export-specifiers.js +6 -11
  96. package/rules/prefer-includes-over-repeated-comparisons.js +5 -1
  97. package/rules/prefer-includes.js +6 -0
  98. package/rules/prefer-logical-operator-over-ternary.js +12 -20
  99. package/rules/prefer-math-constants.js +103 -0
  100. package/rules/prefer-math-min-max.js +1 -5
  101. package/rules/prefer-minimal-ternary.js +26 -2
  102. package/rules/prefer-node-protocol.js +1 -0
  103. package/rules/prefer-number-properties.js +2 -5
  104. package/rules/prefer-object-from-entries.js +6 -1
  105. package/rules/prefer-object-iterable-methods.js +36 -11
  106. package/rules/prefer-optional-catch-binding.js +30 -24
  107. package/rules/prefer-private-class-fields.js +2 -8
  108. package/rules/prefer-promise-with-resolvers.js +248 -0
  109. package/rules/prefer-query-selector.js +79 -17
  110. package/rules/prefer-queue-microtask.js +7 -9
  111. package/rules/prefer-regexp-escape.js +263 -0
  112. package/rules/prefer-set-size.js +10 -2
  113. package/rules/prefer-short-arrow-method.js +3 -3
  114. package/rules/prefer-single-replace.js +218 -0
  115. package/rules/prefer-spread.js +14 -21
  116. package/rules/prefer-string-replace-all.js +5 -0
  117. package/rules/prefer-structured-clone.js +2 -2
  118. package/rules/prefer-switch.js +1 -0
  119. package/rules/prefer-ternary.js +4 -2
  120. package/rules/prefer-type-literal-last.js +22 -54
  121. package/rules/prefer-unary-minus.js +103 -0
  122. package/rules/prefer-url-can-parse.js +308 -0
  123. package/rules/prefer-while-loop-condition.js +252 -0
  124. package/rules/require-passive-events.js +11 -4
  125. package/rules/require-proxy-trap-boolean-return.js +40 -126
  126. package/rules/rule/to-eslint-listener.js +5 -3
  127. package/rules/shared/array-concat-in-loop.js +151 -0
  128. package/rules/shared/identifier-checks.js +4 -16
  129. package/rules/shared/{abbreviations.js → name-replacements.js} +57 -0
  130. package/rules/shared/no-array-mutate-rule.js +19 -2
  131. package/rules/shared/regexp-escape.js +81 -0
  132. package/rules/shared/splice-replacements.js +1 -18
  133. package/rules/string-content.js +11 -4
  134. package/rules/template-indent.js +2 -8
  135. package/rules/throw-new-error.js +7 -0
  136. package/rules/utils/block-scope.js +42 -0
  137. package/rules/utils/builtins.js +50 -1
  138. package/rules/utils/comments.js +16 -0
  139. package/rules/utils/comparison.js +17 -0
  140. package/rules/utils/contains-suspension-point.js +35 -0
  141. package/rules/utils/get-const-variable-initializer.js +31 -0
  142. package/rules/utils/global-reference-tracker.js +14 -1
  143. package/rules/utils/has-optional-chain-element.js +36 -4
  144. package/rules/utils/index.js +32 -2
  145. package/rules/utils/is-boolean.js +23 -0
  146. package/rules/utils/is-function-self-used-inside.js +1 -5
  147. package/rules/utils/is-weak-map.js +21 -0
  148. package/rules/utils/is-weak-set.js +21 -0
  149. package/rules/utils/length-or-size.js +53 -0
  150. package/rules/utils/member-expression.js +18 -0
  151. package/rules/utils/needs-semicolon.js +1 -5
  152. package/rules/utils/numeric.js +20 -0
  153. package/rules/utils/should-add-parentheses-to-logical-expression-child.js +8 -14
  154. package/rules/utils/should-add-parentheses-to-member-expression-object.js +1 -5
  155. package/rules/utils/should-add-parentheses-to-unary-expression.js +8 -2
  156. package/rules/utils/track-branch-exits.js +79 -0
  157. package/rules/utils/types.js +22 -0
@@ -198,6 +198,16 @@ const isBooleanVariable = (variable, context) => {
198
198
  return false;
199
199
  }
200
200
 
201
+ // Destructuring patterns (`const {completed} = task`, `const [enabled] = list`) are intentionally not checked, since renaming a destructured binding is more involved than renaming a plain identifier.
202
+ if (definition.type === 'Variable' && definition.node.id.type !== 'Identifier') {
203
+ return false;
204
+ }
205
+
206
+ // A setter parameter's name is positional and dictated by the accessor, not chosen freely.
207
+ if (definition.type === 'Parameter' && definition.node.parent?.kind === 'set') {
208
+ return false;
209
+ }
210
+
201
211
  const scope = sourceCode.getScope(name);
202
212
 
203
213
  if (name.typeAnnotation) {
@@ -384,9 +394,11 @@ const create = context => {
384
394
  }
385
395
 
386
396
  const checkVariable = variable => {
397
+ // `hasBooleanPrefix` is a cheap string check, so run it before the expensive
398
+ // `isBooleanVariable` analysis.
387
399
  if (
388
- !isBooleanVariable(variable, context)
389
- || hasBooleanPrefix(variable.name, prefixes)
400
+ hasBooleanPrefix(variable.name, prefixes)
401
+ || !isBooleanVariable(variable, context)
390
402
  ) {
391
403
  return;
392
404
  }
@@ -423,8 +435,8 @@ const create = context => {
423
435
 
424
436
  if (
425
437
  !name
426
- || !isBooleanProperty(node, context)
427
438
  || hasBooleanPrefix(name, prefixes)
439
+ || !isBooleanProperty(node, context)
428
440
  ) {
429
441
  return;
430
442
  }
@@ -218,6 +218,13 @@ const create = context => {
218
218
  return;
219
219
  }
220
220
 
221
+ // The combined-regex gate is cheap and rejects most names, so run it before the
222
+ // import/shorthand checks.
223
+ const replacement = getNameReplacement(variable.name, options);
224
+ if (!replacement) {
225
+ return;
226
+ }
227
+
221
228
  const [definition] = variable.defs;
222
229
 
223
230
  if (!shouldCheckDefaultOrNamespaceImportName(definition, options)) {
@@ -235,11 +242,6 @@ const create = context => {
235
242
  return;
236
243
  }
237
244
 
238
- const replacement = getNameReplacement(variable.name, options);
239
- if (!replacement) {
240
- return;
241
- }
242
-
243
245
  const scopes = [
244
246
  ...variable.references.map(reference => reference.from),
245
247
  variable.scope,
@@ -0,0 +1,354 @@
1
+ import {
2
+ isEmptyObjectExpression,
3
+ isNullLiteral,
4
+ isUndefined,
5
+ } from './ast/index.js';
6
+ import {
7
+ getParenthesizedText,
8
+ isParenthesized,
9
+ isSameReference,
10
+ shouldAddParenthesesToConditionalExpressionChild,
11
+ shouldAddParenthesesToLogicalExpressionChild,
12
+ shouldAddParenthesesToUnaryExpressionArgument,
13
+ } from './utils/index.js';
14
+
15
+ const STYLE_LOGICAL = 'logical';
16
+ const STYLE_TERNARY = 'ternary';
17
+
18
+ const MESSAGE_ID = 'consistent-conditional-object-spread';
19
+ const messages = {
20
+ [MESSAGE_ID]: 'Prefer {{expectedStyle}} conditional object spreads.',
21
+ };
22
+ const nullishOperators = new Set(['==', '===']);
23
+ const nonNullishOperators = new Set(['!=', '!==']);
24
+
25
+ const isObjectSpreadArgument = node => (
26
+ node.parent.type === 'SpreadElement'
27
+ && node.parent.argument === node
28
+ && node.parent.parent.type === 'ObjectExpression'
29
+ && node.parent.parent.properties.includes(node.parent)
30
+ );
31
+
32
+ function isSameNode(left, right, sourceCode) {
33
+ if (isSameReference(left, right)) {
34
+ return true;
35
+ }
36
+
37
+ if (left.type !== right.type) {
38
+ return false;
39
+ }
40
+
41
+ switch (left.type) {
42
+ case 'AwaitExpression': {
43
+ return isSameNode(left.argument, right.argument, sourceCode);
44
+ }
45
+
46
+ case 'LogicalExpression': {
47
+ return (
48
+ left.operator === right.operator
49
+ && isSameNode(left.left, right.left, sourceCode)
50
+ && isSameNode(left.right, right.right, sourceCode)
51
+ );
52
+ }
53
+
54
+ case 'UnaryExpression': {
55
+ return (
56
+ left.operator === right.operator
57
+ && left.prefix === right.prefix
58
+ && isSameNode(left.argument, right.argument, sourceCode)
59
+ );
60
+ }
61
+
62
+ case 'UpdateExpression': {
63
+ return false;
64
+ }
65
+
66
+ // No default
67
+ }
68
+
69
+ return sourceCode.getText(left) === sourceCode.getText(right);
70
+ }
71
+
72
+ function getNullishKind(node) {
73
+ if (isNullLiteral(node)) {
74
+ return 'null';
75
+ }
76
+
77
+ if (isUndefined(node)) {
78
+ return 'undefined';
79
+ }
80
+ }
81
+
82
+ function getNullishBinaryCheck(node) {
83
+ if (
84
+ node.type !== 'BinaryExpression'
85
+ || (!nullishOperators.has(node.operator) && !nonNullishOperators.has(node.operator))
86
+ ) {
87
+ return;
88
+ }
89
+
90
+ const leftKind = getNullishKind(node.left);
91
+ const rightKind = getNullishKind(node.right);
92
+
93
+ if (Boolean(leftKind) === Boolean(rightKind)) {
94
+ return;
95
+ }
96
+
97
+ return {
98
+ reference: leftKind ? node.right : node.left,
99
+ kind: node.operator.length === 2 ? 'nullish' : (leftKind ?? rightKind),
100
+ isTrueWhenNullish: nullishOperators.has(node.operator),
101
+ };
102
+ }
103
+
104
+ const checksNullAndUndefined = (left, right) =>
105
+ (left.kind === 'null' && right.kind === 'undefined')
106
+ || (left.kind === 'undefined' && right.kind === 'null');
107
+
108
+ function getNullishTest(node, sourceCode) {
109
+ const binaryCheck = getNullishBinaryCheck(node);
110
+
111
+ if (binaryCheck?.kind === 'nullish') {
112
+ return binaryCheck;
113
+ }
114
+
115
+ if (node.type !== 'LogicalExpression') {
116
+ return;
117
+ }
118
+
119
+ const left = getNullishBinaryCheck(node.left);
120
+ const right = getNullishBinaryCheck(node.right);
121
+
122
+ if (
123
+ !left
124
+ || !right
125
+ || !isSameNode(left.reference, right.reference, sourceCode)
126
+ ) {
127
+ return;
128
+ }
129
+
130
+ if (
131
+ node.operator === '||'
132
+ && left.isTrueWhenNullish
133
+ && right.isTrueWhenNullish
134
+ && checksNullAndUndefined(left, right)
135
+ ) {
136
+ return {
137
+ reference: left.reference,
138
+ isTrueWhenNullish: true,
139
+ };
140
+ }
141
+
142
+ if (
143
+ node.operator === '&&'
144
+ && !left.isTrueWhenNullish
145
+ && !right.isTrueWhenNullish
146
+ && checksNullAndUndefined(left, right)
147
+ ) {
148
+ return {
149
+ reference: left.reference,
150
+ isTrueWhenNullish: false,
151
+ };
152
+ }
153
+ }
154
+
155
+ // Render `node` as an operand of a `&&` expression, adding parentheses when precedence requires it.
156
+ function getLogicalOperandText(node, property, context) {
157
+ let text = getParenthesizedText(node, context);
158
+
159
+ if (
160
+ !isParenthesized(node, context)
161
+ && shouldAddParenthesesToLogicalExpressionChild(node, {operator: '&&', property})
162
+ ) {
163
+ text = `(${text})`;
164
+ }
165
+
166
+ return text;
167
+ }
168
+
169
+ // Render `!test` as the left operand of a `&&` expression, stripping a leading `!` when present.
170
+ function getNegatedTestText(test, context) {
171
+ if (
172
+ test.type === 'UnaryExpression'
173
+ && test.operator === '!'
174
+ && test.prefix
175
+ ) {
176
+ return getLogicalOperandText(test.argument, 'left', context);
177
+ }
178
+
179
+ let text = getParenthesizedText(test, context);
180
+
181
+ if (
182
+ !isParenthesized(test, context)
183
+ && shouldAddParenthesesToUnaryExpressionArgument(test, '!')
184
+ ) {
185
+ text = `(${text})`;
186
+ }
187
+
188
+ return `!${text}`;
189
+ }
190
+
191
+ function getConditionalExpressionChildText(node, context) {
192
+ let text = getParenthesizedText(node, context);
193
+
194
+ if (
195
+ !isParenthesized(node, context)
196
+ && shouldAddParenthesesToConditionalExpressionChild(node)
197
+ ) {
198
+ text = `(${text})`;
199
+ }
200
+
201
+ return text;
202
+ }
203
+
204
+ function getConditionalExpressionProblem(conditionalExpression, context) {
205
+ const {test, consequent, alternate} = conditionalExpression;
206
+ const isAlternateEmpty = isEmptyObjectExpression(alternate);
207
+ const isConsequentEmpty = isEmptyObjectExpression(consequent);
208
+
209
+ if (isAlternateEmpty === isConsequentEmpty) {
210
+ return;
211
+ }
212
+
213
+ const keptBranch = isAlternateEmpty ? consequent : alternate;
214
+ const nullishTest = getNullishTest(test, context.sourceCode);
215
+ const hasCommentsInside = context.sourceCode.getCommentsInside(conditionalExpression).length > 0;
216
+
217
+ if (
218
+ (
219
+ isAlternateEmpty
220
+ ? isSameNode(test, keptBranch, context.sourceCode)
221
+ : (
222
+ test.type === 'UnaryExpression'
223
+ && test.operator === '!'
224
+ && test.prefix
225
+ && isSameNode(test.argument, keptBranch, context.sourceCode)
226
+ )
227
+ )
228
+ || (
229
+ nullishTest
230
+ && !hasCommentsInside
231
+ && (nullishTest.isTrueWhenNullish ? !isAlternateEmpty : isAlternateEmpty)
232
+ && isSameNode(nullishTest.reference, keptBranch, context.sourceCode)
233
+ )
234
+ ) {
235
+ return;
236
+ }
237
+
238
+ const testText = isAlternateEmpty
239
+ ? getLogicalOperandText(test, 'left', context)
240
+ : getNegatedTestText(test, context);
241
+ const keptBranchText = getLogicalOperandText(keptBranch, 'right', context);
242
+
243
+ return {
244
+ node: conditionalExpression,
245
+ messageId: MESSAGE_ID,
246
+ data: {
247
+ expectedStyle: 'logical',
248
+ },
249
+ /** @param {import('eslint').Rule.RuleFixer} fixer */
250
+ * fix(fixer, {abort}) {
251
+ if (hasCommentsInside) {
252
+ return abort();
253
+ }
254
+
255
+ yield fixer.replaceText(conditionalExpression, `${testText} && ${keptBranchText}`);
256
+ },
257
+ };
258
+ }
259
+
260
+ function getLogicalExpressionProblem(logicalExpression, context) {
261
+ if (
262
+ logicalExpression.operator !== '&&'
263
+ || isEmptyObjectExpression(logicalExpression.right)
264
+ ) {
265
+ return;
266
+ }
267
+
268
+ if (isSameNode(logicalExpression.left, logicalExpression.right, context.sourceCode)) {
269
+ return;
270
+ }
271
+
272
+ const nullishTest = getNullishTest(logicalExpression.left, context.sourceCode);
273
+
274
+ if (
275
+ nullishTest
276
+ && !nullishTest.isTrueWhenNullish
277
+ && isSameNode(nullishTest.reference, logicalExpression.right, context.sourceCode)
278
+ ) {
279
+ return;
280
+ }
281
+
282
+ const testText = getConditionalExpressionChildText(logicalExpression.left, context);
283
+ const consequentText = getConditionalExpressionChildText(logicalExpression.right, context);
284
+
285
+ return {
286
+ node: logicalExpression,
287
+ messageId: MESSAGE_ID,
288
+ data: {
289
+ expectedStyle: 'ternary',
290
+ },
291
+ /** @param {import('eslint').Rule.RuleFixer} fixer */
292
+ * fix(fixer, {abort}) {
293
+ if (context.sourceCode.getCommentsInside(logicalExpression).length > 0) {
294
+ return abort();
295
+ }
296
+
297
+ yield fixer.replaceText(logicalExpression, `${testText} ? ${consequentText} : {}`);
298
+ },
299
+ };
300
+ }
301
+
302
+ /** @param {import('eslint').Rule.RuleContext} context */
303
+ const create = context => {
304
+ const style = context.options[0];
305
+
306
+ if (style === STYLE_TERNARY) {
307
+ context.on('LogicalExpression', logicalExpression => {
308
+ if (!isObjectSpreadArgument(logicalExpression)) {
309
+ return;
310
+ }
311
+
312
+ return getLogicalExpressionProblem(logicalExpression, context);
313
+ });
314
+
315
+ return;
316
+ }
317
+
318
+ context.on('ConditionalExpression', conditionalExpression => {
319
+ if (!isObjectSpreadArgument(conditionalExpression)) {
320
+ return;
321
+ }
322
+
323
+ return getConditionalExpressionProblem(conditionalExpression, context);
324
+ });
325
+ };
326
+
327
+ /** @type {import('eslint').Rule.RuleModule} */
328
+ const config = {
329
+ create,
330
+ meta: {
331
+ type: 'suggestion',
332
+ docs: {
333
+ description: 'Enforce consistent conditional object spread style.',
334
+ recommended: true,
335
+ },
336
+ fixable: 'code',
337
+ schema: [
338
+ {
339
+ description: 'The conditional object spread style to enforce.',
340
+ enum: [
341
+ STYLE_LOGICAL,
342
+ STYLE_TERNARY,
343
+ ],
344
+ },
345
+ ],
346
+ defaultOptions: [STYLE_LOGICAL],
347
+ messages,
348
+ languages: [
349
+ 'js/js',
350
+ ],
351
+ },
352
+ };
353
+
354
+ export default config;
@@ -66,6 +66,11 @@ const shouldIgnoreMemberExpression = node =>
66
66
  isCallOrNewExpression(node.parent)
67
67
  && node.parent.callee === node
68
68
  )
69
+ // Replacing the tag would change the `this` binding, like a method call.
70
+ || (
71
+ node.parent.type === 'TaggedTemplateExpression'
72
+ && node.parent.tag === node
73
+ )
69
74
  || isLeftHandSide(node);
70
75
 
71
76
  const isRootVariableReassigned = (declaration, memberExpressionNode, memberScope, sourceCode) => {
@@ -84,7 +84,7 @@ const create = context => {
84
84
  const replacement = getReplacement(binaryExpression);
85
85
 
86
86
  if (!replacement) {
87
- return;
87
+ continue;
88
88
  }
89
89
 
90
90
  const {left, operator, right} = binaryExpression;
@@ -92,14 +92,8 @@ function isUtf8Encoding(node, scope) {
92
92
  }
93
93
 
94
94
  const {value} = staticValue;
95
- if (
96
- isSingleEncodingOptionObject(value)
97
- && isUtf8EncodingString(value.encoding)
98
- ) {
99
- return true;
100
- }
101
-
102
- return false;
95
+ return Boolean(isSingleEncodingOptionObject(value)
96
+ && isUtf8EncodingString(value.encoding));
103
97
  }
104
98
 
105
99
  function isBufferEncoding(node, scope) {
@@ -113,14 +107,8 @@ function isBufferEncoding(node, scope) {
113
107
  return true;
114
108
  }
115
109
 
116
- if (
117
- isSingleEncodingOptionObject(value)
118
- && (value.encoding === undefined || value.encoding === null)
119
- ) {
120
- return true;
121
- }
122
-
123
- return false;
110
+ return Boolean(isSingleEncodingOptionObject(value)
111
+ && (value.encoding === undefined || value.encoding === null));
124
112
  }
125
113
 
126
114
  function isJsonReadFileCall(node, scope) {
@@ -1,5 +1,6 @@
1
1
  import {
2
- getParenthesizedRange,
2
+ getMemberAccessOperatorRange,
3
+ hasCommentInRange,
3
4
  isSameReference,
4
5
  unwrapTypeScriptExpression,
5
6
  } from './utils/index.js';
@@ -60,28 +61,10 @@ function isSupportedMemberBase(node) {
60
61
  return false;
61
62
  }
62
63
 
63
- function getMemberAccessOperatorRange(memberExpression, context) {
64
- const {sourceCode} = context;
65
- const [, start] = getParenthesizedRange(memberExpression.object, context);
66
- const end = memberExpression.computed
67
- ? sourceCode.getRange(sourceCode.getTokenBefore(memberExpression.property, token => token.value === '['))[1]
68
- : sourceCode.getRange(memberExpression.property)[0];
69
-
70
- return [start, end];
71
- }
72
-
73
- function hasCommentInRange(sourceCode, [start, end]) {
74
- return sourceCode.getAllComments().some(comment => {
75
- const [commentStart, commentEnd] = sourceCode.getRange(comment);
76
-
77
- return commentStart >= start && commentEnd <= end;
78
- });
79
- }
80
-
81
64
  function canReplaceMemberAccessOperator(memberExpression, context) {
82
65
  const range = getMemberAccessOperatorRange(memberExpression, context);
83
66
 
84
- return !hasCommentInRange(context.sourceCode, range);
67
+ return !hasCommentInRange(context, range);
85
68
  }
86
69
 
87
70
  function replaceMemberAccessOperator({memberExpression, context, fixer, replacement}) {