eslint-plugin-unicorn 70.0.0 → 71.1.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 (91) hide show
  1. package/package.json +26 -25
  2. package/readme.md +5 -1
  3. package/rules/ast/call-or-new-expression.js +2 -8
  4. package/rules/ast/is-member-expression.js +2 -8
  5. package/rules/comment-content.js +4 -4
  6. package/rules/consistent-boolean-name.js +275 -29
  7. package/rules/consistent-compound-words.js +1 -2
  8. package/rules/consistent-json-file-read.js +2 -5
  9. package/rules/dom-node-dataset.js +3 -7
  10. package/rules/escape-case.js +4 -4
  11. package/rules/expiring-todo-comments.js +2 -2
  12. package/rules/explicit-length-check.js +3 -3
  13. package/rules/filename-case.js +4 -4
  14. package/rules/fix/remove-argument.js +34 -8
  15. package/rules/fix/remove-statement.js +1 -3
  16. package/rules/id-match.js +2 -2
  17. package/rules/isolated-functions.js +47 -7
  18. package/rules/name-replacements.js +1 -2
  19. package/rules/no-anonymous-default-export.js +1 -3
  20. package/rules/no-array-callback-reference.js +2 -10
  21. package/rules/no-chained-comparison.js +1 -1
  22. package/rules/no-computed-property-existence-check.js +1 -4
  23. package/rules/no-declarations-before-early-exit.js +6 -5
  24. package/rules/no-error-property-assignment.js +3 -3
  25. package/rules/no-for-loop.js +4 -4
  26. package/rules/no-keyword-prefix.js +2 -2
  27. package/rules/no-mismatched-map-key.js +13 -20
  28. package/rules/no-named-default.js +2 -5
  29. package/rules/no-negated-array-predicate.js +4 -11
  30. package/rules/no-negated-comparison.js +7 -10
  31. package/rules/no-negation-in-equality-check.js +2 -5
  32. package/rules/no-process-exit.js +6 -6
  33. package/rules/no-static-only-class.js +2 -8
  34. package/rules/no-thenable.js +9 -15
  35. package/rules/no-undeclared-class-members.js +1 -5
  36. package/rules/no-unnecessary-array-flat-map.js +6 -5
  37. package/rules/no-unnecessary-global-this.js +5 -9
  38. package/rules/no-unused-properties.js +0 -1
  39. package/rules/no-useless-coercion.js +1 -2
  40. package/rules/no-useless-undefined.js +2 -2
  41. package/rules/prefer-array-find.js +2 -5
  42. package/rules/prefer-bigint-literals.js +1 -0
  43. package/rules/prefer-boolean-return.js +20 -3
  44. package/rules/prefer-default-parameters.js +2 -2
  45. package/rules/prefer-else-if.js +5 -9
  46. package/rules/prefer-has-check.js +6 -3
  47. package/rules/prefer-https.js +3 -3
  48. package/rules/prefer-identifier-import-export-specifiers.js +1 -3
  49. package/rules/prefer-minimal-ternary.js +4 -4
  50. package/rules/prefer-object-define-properties.js +1 -3
  51. package/rules/prefer-observer-apis.js +2 -5
  52. package/rules/prefer-private-class-fields.js +1 -3
  53. package/rules/prefer-simple-sort-comparator.js +6 -6
  54. package/rules/prefer-single-object-destructuring.js +2 -5
  55. package/rules/prefer-single-replace.js +2 -2
  56. package/rules/prefer-spread.js +22 -32
  57. package/rules/prefer-string-pad-start-end.js +1 -6
  58. package/rules/prefer-string-repeat.js +16 -9
  59. package/rules/prefer-string-replace-all.js +1 -1
  60. package/rules/prefer-ternary.js +5 -5
  61. package/rules/prefer-toggle-attribute.js +3 -3
  62. package/rules/prefer-top-level-await.js +6 -1
  63. package/rules/prefer-uint8array-base64.js +3 -1
  64. package/rules/require-proxy-trap-boolean-return.js +2 -2
  65. package/rules/rule/to-eslint-create.js +1 -2
  66. package/rules/rule/to-eslint-listener.js +1 -3
  67. package/rules/rule/to-eslint-problem.js +1 -3
  68. package/rules/rule/to-eslint-rule-fixer.js +1 -3
  69. package/rules/rule/to-eslint-rule.js +1 -3
  70. package/rules/rule/to-eslint-rules.js +1 -3
  71. package/rules/rule/unicorn-context.js +1 -3
  72. package/rules/rule/unicorn-listeners.js +1 -3
  73. package/rules/shared/no-array-mutate-rule.js +1 -3
  74. package/rules/shared/regexp-escape.js +4 -4
  75. package/rules/utils/can-tokens-be-adjacent.js +95 -0
  76. package/rules/utils/escape-string.js +2 -8
  77. package/rules/utils/get-available-variable-name.js +2 -13
  78. package/rules/utils/get-precedence.js +112 -0
  79. package/rules/utils/get-token-store.js +1 -3
  80. package/rules/utils/global-reference-tracker.js +3 -6
  81. package/rules/utils/index.js +4 -0
  82. package/rules/utils/is-boolean.js +90 -32
  83. package/rules/utils/is-identifier-name.js +5 -0
  84. package/rules/utils/is-promise-type.js +1 -3
  85. package/rules/utils/is-react-hook-name.js +5 -0
  86. package/rules/utils/parentheses/get-parent-syntax-opening-parenthesis.js +1 -3
  87. package/rules/utils/parentheses/iterate-surrounding-parentheses.js +1 -1
  88. package/rules/utils/should-add-parentheses-to-await-expression-argument.js +4 -9
  89. package/rules/utils/should-add-parentheses-to-call-expression-callee.js +6 -12
  90. package/rules/utils/should-add-parentheses-to-unary-expression.js +7 -14
  91. package/rules/utils/to-location.js +1 -3
@@ -24,13 +24,6 @@ const replacementMethod = new Map([
24
24
  ]);
25
25
  const methods = replacementMethod.keys().toArray();
26
26
 
27
- const predicateBodyTypesRequiringParentheses = new Set([
28
- 'TSAsExpression',
29
- 'TSNonNullExpression',
30
- 'TSSatisfiesExpression',
31
- 'TSTypeAssertion',
32
- ]);
33
-
34
27
  const needsParenthesesInConciseArrowBody = (node, text) =>
35
28
  node.parent.type === 'ArrowFunctionExpression'
36
29
  && node.parent.body === node
@@ -75,7 +68,7 @@ function getReplacementPredicateText(node, context) {
75
68
  }
76
69
 
77
70
  const text = context.sourceCode.getText(node);
78
- const needsParentheses = predicateBodyTypesRequiringParentheses.has(node.type) || shouldAddParenthesesToUnaryExpressionArgument(node, '!');
71
+ const needsParentheses = shouldAddParenthesesToUnaryExpressionArgument(node, '!');
79
72
 
80
73
  return {
81
74
  node,
@@ -158,7 +151,7 @@ const create = context => {
158
151
  replacement,
159
152
  },
160
153
  * fix(fixer) {
161
- const needsReturnOrThrowParentheses = (
154
+ const isNeedsReturnOrThrowParentheses = (
162
155
  (parent.type === 'ReturnStatement' || parent.type === 'ThrowStatement')
163
156
  && parent.argument === unaryExpression
164
157
  && !isOnSameLine(bangToken, tokenAfterBang, context)
@@ -171,12 +164,12 @@ const create = context => {
171
164
 
172
165
  if (
173
166
  tokenStore === sourceCode
174
- && !needsReturnOrThrowParentheses
167
+ && !isNeedsReturnOrThrowParentheses
175
168
  ) {
176
169
  yield fixSpaceAroundKeyword(fixer, unaryExpression, context);
177
170
  }
178
171
 
179
- if (needsReturnOrThrowParentheses) {
172
+ if (isNeedsReturnOrThrowParentheses) {
180
173
  yield addParenthesesToReturnOrThrowExpression(fixer, parent, context);
181
174
  return;
182
175
  }
@@ -98,14 +98,14 @@ function * fix({
98
98
  const tokenAfterBangIncludingComments = sourceCode.getTokenAfter(bangToken, {includeComments: true});
99
99
  const operatorToken = getPunctuatorBinaryExpressionOperatorToken(comparison, context);
100
100
  const {parent} = unaryExpression;
101
- const needsReturnOrThrowParentheses = (
101
+ const isNeedsReturnOrThrowParentheses = (
102
102
  (parent.type === 'ReturnStatement' || parent.type === 'ThrowStatement')
103
103
  && parent.argument === unaryExpression
104
104
  && !isOnSameLine(bangToken, tokenAfterBang, context)
105
105
  && !isParenthesized(unaryExpression, context)
106
106
  );
107
107
 
108
- if (!needsReturnOrThrowParentheses) {
108
+ if (!isNeedsReturnOrThrowParentheses) {
109
109
  yield fixSpaceAroundKeyword(fixer, unaryExpression, context);
110
110
  }
111
111
 
@@ -117,16 +117,13 @@ function * fix({
117
117
  yield fixer.insertTextAfter(tokenAfterBangIncludingComments, ' ');
118
118
  }
119
119
 
120
- if (!(
121
- parentNeedsGroupedComparison(parent)
122
- && !isParenthesized(unaryExpression, context)
123
- )) {
120
+ if (!parentNeedsGroupedComparison(parent) || isParenthesized(unaryExpression, context)) {
124
121
  yield removeParentheses(comparison, fixer, context);
125
122
  }
126
123
 
127
124
  yield fixer.replaceText(operatorToken, replacementOperator);
128
125
 
129
- if (needsReturnOrThrowParentheses) {
126
+ if (isNeedsReturnOrThrowParentheses) {
130
127
  yield addParenthesesToReturnOrThrowExpression(fixer, parent, context);
131
128
  return;
132
129
  }
@@ -178,21 +175,21 @@ function * fixLogical({
178
175
  const bangToken = sourceCode.getFirstToken(unaryExpression);
179
176
  const tokenAfterBang = sourceCode.getTokenAfter(bangToken);
180
177
  const {parent} = unaryExpression;
181
- const needsReturnOrThrowParentheses = (
178
+ const isNeedsReturnOrThrowParentheses = (
182
179
  (parent.type === 'ReturnStatement' || parent.type === 'ThrowStatement')
183
180
  && parent.argument === unaryExpression
184
181
  && !isOnSameLine(bangToken, tokenAfterBang, context)
185
182
  && !isParenthesized(unaryExpression, context)
186
183
  );
187
184
 
188
- if (!needsReturnOrThrowParentheses) {
185
+ if (!isNeedsReturnOrThrowParentheses) {
189
186
  yield fixSpaceAroundKeyword(fixer, unaryExpression, context);
190
187
  }
191
188
 
192
189
  yield fixer.remove(bangToken);
193
190
  yield fixer.replaceText(logicalExpression, getFixedLogicalExpressionText(logicalExpression, context));
194
191
 
195
- if (needsReturnOrThrowParentheses) {
192
+ if (isNeedsReturnOrThrowParentheses) {
196
193
  yield addParenthesesToReturnOrThrowExpression(fixer, parent, context);
197
194
  return;
198
195
  }
@@ -23,11 +23,8 @@ const create = context => {
23
23
  context.on('BinaryExpression', binaryExpression => {
24
24
  const {operator, left} = binaryExpression;
25
25
 
26
- if (!(
27
- isEqualityCheck(binaryExpression)
28
- && isNegatedExpression(left)
29
- && !isNegatedExpression(left.argument)
30
- )) {
26
+ if (!(isEqualityCheck(binaryExpression)
27
+ && isNegatedExpression(left)) || isNegatedExpression(left.argument)) {
31
28
  return;
32
29
  }
33
30
 
@@ -11,9 +11,9 @@ const isWorkerThreads = node =>
11
11
 
12
12
  /** @param {import('eslint').Rule.RuleContext} context */
13
13
  const create = context => {
14
- const startsWithHashBang = context.sourceCode.lines[0].indexOf('#!') === 0;
14
+ const isStartsWithHashBang = context.sourceCode.lines[0].indexOf('#!') === 0;
15
15
 
16
- if (startsWithHashBang) {
16
+ if (isStartsWithHashBang) {
17
17
  return;
18
18
  }
19
19
 
@@ -22,7 +22,7 @@ const create = context => {
22
22
  let processEventHandlerDepth = 0;
23
23
 
24
24
  // Only report if it's outside a worker thread context. See #328.
25
- let requiredWorkerThreadsModule = false;
25
+ let isRequiredWorkerThreadsModule = false;
26
26
  const problemNodes = [];
27
27
 
28
28
  const isProcessEventHandler = node => isMethodCall(node, {
@@ -39,7 +39,7 @@ const create = context => {
39
39
  isStaticRequire(callExpression)
40
40
  && isWorkerThreads(callExpression.arguments[0])
41
41
  ) {
42
- requiredWorkerThreadsModule = true;
42
+ isRequiredWorkerThreadsModule = true;
43
43
  }
44
44
  });
45
45
 
@@ -49,7 +49,7 @@ const create = context => {
49
49
  importDeclaration.source.type === 'Literal'
50
50
  && isWorkerThreads(importDeclaration.source)
51
51
  ) {
52
- requiredWorkerThreadsModule = true;
52
+ isRequiredWorkerThreadsModule = true;
53
53
  }
54
54
  });
55
55
 
@@ -81,7 +81,7 @@ const create = context => {
81
81
  });
82
82
 
83
83
  context.onExit('Program', function * () {
84
- if (requiredWorkerThreadsModule) {
84
+ if (isRequiredWorkerThreadsModule) {
85
85
  return;
86
86
  }
87
87
 
@@ -38,16 +38,10 @@ function isStaticMember(node) {
38
38
  }
39
39
 
40
40
  // TypeScript class
41
- if (
42
- isDeclare
41
+ return !(isDeclare
43
42
  || isReadonly
44
43
  || accessibility !== undefined
45
- || (Array.isArray(decorators) && decorators.length > 0)
46
- ) {
47
- return false;
48
- }
49
-
50
- return true;
44
+ || (Array.isArray(decorators) && decorators.length > 0));
51
45
  }
52
46
 
53
47
  function * switchClassMemberToObjectProperty(node, context, fixer) {
@@ -79,16 +79,13 @@ const cases = [
79
79
  {
80
80
  selector: 'CallExpression',
81
81
  * getNodes(node, context) {
82
- if (!(
83
- isMethodCall(node, {
84
- objects: ['Object', 'Reflect'],
85
- method: 'defineProperty',
86
- minimumArguments: 3,
87
- optionalCall: false,
88
- optionalMember: false,
89
- })
90
- && node.arguments[0].type !== 'SpreadElement'
91
- )) {
82
+ if (!isMethodCall(node, {
83
+ objects: ['Object', 'Reflect'],
84
+ method: 'defineProperty',
85
+ minimumArguments: 3,
86
+ optionalCall: false,
87
+ optionalMember: false,
88
+ }) || node.arguments[0].type === 'SpreadElement') {
92
89
  return;
93
90
  }
94
91
 
@@ -117,11 +114,8 @@ const cases = [
117
114
  }
118
115
 
119
116
  for (const pairs of node.arguments[0].elements) {
120
- if (!(
121
- pairs?.type === 'ArrayExpression'
122
- && pairs.elements[0]
123
- && pairs.elements[0].type !== 'SpreadElement'
124
- )) {
117
+ if (!(pairs?.type === 'ArrayExpression'
118
+ && pairs.elements[0]) || pairs.elements[0].type === 'SpreadElement') {
125
119
  continue;
126
120
  }
127
121
 
@@ -179,11 +179,7 @@ const getDeclaredClassMemberNames = (classBody, sourceCode) => {
179
179
  const names = new Set(['constructor']);
180
180
 
181
181
  for (const member of classBody.body) {
182
- if (!(
183
- classMemberTypes.has(member.type)
184
- && member.static !== true
185
- && member.kind !== 'constructor'
186
- )) {
182
+ if (!classMemberTypes.has(member.type) || member.static === true || member.kind === 'constructor') {
187
183
  continue;
188
184
  }
189
185
 
@@ -1,10 +1,11 @@
1
1
  import {hasSideEffect} from '@eslint-community/eslint-utils';
2
- import {isMethodCall} from './ast/index.js';
2
+ import {isEmptyArrayExpression, isMethodCall} from './ast/index.js';
3
3
  import {
4
4
  getParenthesizedText,
5
5
  isKnownNonArray,
6
6
  isParenthesized,
7
7
  isSameIdentifier,
8
+ isTypeScriptFile,
8
9
  shouldAddParenthesesToMemberExpressionObject,
9
10
  wouldRemoveComments,
10
11
  } from './utils/index.js';
@@ -49,10 +50,6 @@ const isSimpleSingleParameterArrowCallback = node =>
49
50
  && !node.params[0].optional
50
51
  && node.body.type !== 'BlockStatement';
51
52
 
52
- const isEmptyArrayExpression = node =>
53
- node.type === 'ArrayExpression'
54
- && node.elements.length === 0;
55
-
56
53
  const getSingleArrayElement = node => {
57
54
  if (
58
55
  node.type !== 'ArrayExpression'
@@ -195,6 +192,10 @@ function getProblemForFilterFlatMap(flatMapCallExpression, callbackResult, conte
195
192
  }
196
193
 
197
194
  function getProblemForConditionalFlatMap(flatMapCallExpression, callback, callbackResult, context) {
195
+ if (isTypeScriptFile(context.physicalFilename)) {
196
+ return;
197
+ }
198
+
198
199
  const method = isSameIdentifier(callbackResult.element, callback.params[0]) ? 'filter' : 'filter().map';
199
200
  const problem = {
200
201
  node: flatMapCallExpression.callee.property,
@@ -1,9 +1,4 @@
1
- import {
2
- isIdentifierName,
3
- isKeyword,
4
- isReservedWord,
5
- isStrictReservedWord,
6
- } from '@babel/helper-validator-identifier';
1
+ import reservedIdentifiers from 'reserved-identifiers';
7
2
  import {findVariable} from '@eslint-community/eslint-utils';
8
3
  import {isStringLiteral} from './ast/index.js';
9
4
  import {
@@ -12,6 +7,7 @@ import {
12
7
  isLeftHandSide,
13
8
  isControlFlowTest,
14
9
  isBooleanExpression,
10
+ isIdentifierName,
15
11
  } from './utils/index.js';
16
12
 
17
13
  const MESSAGE_ID = 'no-unnecessary-global-this';
@@ -53,11 +49,11 @@ function isActiveGlobal(name, node, context) {
53
49
  && variable.defs.length === 0;
54
50
  }
55
51
 
52
+ const reserved = reservedIdentifiers();
53
+
56
54
  function canUseBareIdentifier(name) {
57
55
  return isIdentifierName(name)
58
- && !isKeyword(name)
59
- && !isReservedWord(name, true)
60
- && !isStrictReservedWord(name, true);
56
+ && (!reserved.has(name) || name === 'eval' || name === 'arguments');
61
57
  }
62
58
 
63
59
  function getStaticPropertyName(node) {
@@ -65,7 +65,6 @@ const getReferenceParent = referenceNode => {
65
65
  return referenceNode.parent;
66
66
  };
67
67
 
68
- // eslint-disable-next-line unicorn/name-replacements
69
68
  const specialProtoPropertyKey = {
70
69
  type: 'Identifier',
71
70
  name: '__proto__',
@@ -1,3 +1,4 @@
1
+ import {isEmptyStringLiteral} from './ast/index.js';
1
2
  import {
2
3
  isBoolean,
3
4
  isString,
@@ -25,8 +26,6 @@ const coercions = new Map([
25
26
  ['Number', {type: 'number', isType: (node, context) => isNumber(node, context.sourceCode.getScope(node))}],
26
27
  ]);
27
28
 
28
- const isEmptyStringLiteral = node => node.type === 'Literal' && node.value === '';
29
-
30
29
  /** @param {ESLint.Rule.RuleContext} context */
31
30
  const create = context => {
32
31
  const {sourceCode} = context;
@@ -410,10 +410,10 @@ const create = context => {
410
410
  return;
411
411
  }
412
412
 
413
- const accessWhenTestPasses = !isConsequentUndefined;
413
+ const isAccessWhenTestPasses = !isConsequentUndefined;
414
414
  const testValidity = getIndexedAccessTestValidity(node.test, indexedAccess);
415
415
 
416
- if (testValidity !== accessWhenTestPasses) {
416
+ if (testValidity !== isAccessWhenTestPasses) {
417
417
  return;
418
418
  }
419
419
 
@@ -204,13 +204,10 @@ const create = context => {
204
204
  // `array.filter()[0]`
205
205
  // `array?.filter()[0]`
206
206
  context.on('MemberExpression', node => {
207
- if (!(
208
- node.computed
207
+ if (!(node.computed
209
208
  && node.property.type === 'Literal'
210
209
  && node.property.raw === '0'
211
- && isArrayFilterCall(node.object, context)
212
- && !isLeftHandSide(node)
213
- )) {
210
+ && isArrayFilterCall(node.object, context)) || isLeftHandSide(node)) {
214
211
  return;
215
212
  }
216
213
 
@@ -75,6 +75,7 @@ function getReplacement(valueNode) {
75
75
  const {value, raw} = valueNode;
76
76
 
77
77
  // Intentionally `Number.isInteger`, not `Number.isSafeInteger`: large integers beyond the safe range are exactly what bigint literals are for.
78
+ // eslint-disable-next-line unicorn/prefer-number-is-safe-integer
78
79
  if (!Number.isInteger(value)) {
79
80
  return;
80
81
  }
@@ -3,6 +3,7 @@ import {
3
3
  getLastTrailingCommentOnSameLine,
4
4
  getNextNode,
5
5
  getParenthesizedText,
6
+ getPreviousNode,
6
7
  isGlobalBooleanCall,
7
8
  shouldAddParenthesesToUnaryExpressionArgument,
8
9
  } from './utils/index.js';
@@ -143,11 +144,11 @@ const create = context => {
143
144
  const hasComments = sourceCode.getCommentsInside(node).length > 0
144
145
  || sourceCode.getCommentsInside(alternate).length > 0
145
146
  || getLastTrailingCommentOnSameLine(context, alternate);
146
- const needsGlobalBoolean = !shouldNegateTest
147
+ const isNeedsGlobalBoolean = !shouldNegateTest
147
148
  && !isRuntimeBooleanExpression(node.test, context)
148
149
  && !canUseGlobalBoolean(node);
149
150
 
150
- if (hasComments || needsGlobalBoolean) {
151
+ if (hasComments || isNeedsGlobalBoolean) {
151
152
  return problem;
152
153
  }
153
154
 
@@ -160,6 +161,13 @@ const create = context => {
160
161
  };
161
162
  }
162
163
 
164
+ function isPrecededByFlatIfReturningSameBoolean(node, returnValue) {
165
+ const previousNode = getPreviousNode(node, context);
166
+ return previousNode?.type === 'IfStatement'
167
+ && !previousNode.alternate
168
+ && getBooleanReturnValue(getNodeBody(previousNode.consequent)) === returnValue;
169
+ }
170
+
163
171
  function getFlatProblem(node) {
164
172
  const alternate = getNextNode(node, context);
165
173
  if (
@@ -169,9 +177,18 @@ const create = context => {
169
177
  return;
170
178
  }
171
179
 
180
+ const consequent = getNodeBody(node.consequent);
181
+ const consequentValue = getBooleanReturnValue(consequent);
182
+ if (
183
+ consequentValue !== undefined
184
+ && isPrecededByFlatIfReturningSameBoolean(node, consequentValue)
185
+ ) {
186
+ return;
187
+ }
188
+
172
189
  const problem = getProblem(
173
190
  node,
174
- getNodeBody(node.consequent),
191
+ consequent,
175
192
  alternate,
176
193
  [
177
194
  sourceCode.getRange(node)[0],
@@ -108,8 +108,8 @@ const fixDefaultExpression = (fixer, sourceCode, node) => {
108
108
  ]);
109
109
  }
110
110
 
111
- const endsWithWhitespace = lineText[column] === ' ';
112
- if (endsWithWhitespace) {
111
+ const isEndsWithWhitespace = lineText[column] === ' ';
112
+ if (isEndsWithWhitespace) {
113
113
  const [start, end] = sourceCode.getRange(node);
114
114
  return fixer.removeRange([start, end + 1]);
115
115
  }
@@ -148,13 +148,13 @@ function getEqualityComparisons(node) {
148
148
  */
149
149
  function getBooleanComparisonInfo(node, context) {
150
150
  node = unwrapExpression(node);
151
- let value = true;
151
+ let isValue = true;
152
152
 
153
153
  while (
154
154
  node.type === 'UnaryExpression'
155
155
  && node.operator === '!'
156
156
  ) {
157
- value = !value;
157
+ isValue = !isValue;
158
158
  node = unwrapExpression(node.argument);
159
159
  }
160
160
 
@@ -178,7 +178,7 @@ function getBooleanComparisonInfo(node, context) {
178
178
 
179
179
  return {
180
180
  discriminant: node,
181
- valueKeys: new Set([getStaticEqualityValueKey(value)]),
181
+ valueKeys: new Set([getStaticEqualityValueKey(isValue)]),
182
182
  };
183
183
  }
184
184
 
@@ -444,13 +444,9 @@ function getProblem(previousIfStatement, ifStatement, context, branchAlwaysExits
444
444
  const previous = getComparisonInfo(previousIfStatement.test, context);
445
445
  const current = getComparisonInfo(ifStatement.test, context);
446
446
 
447
- if (!(
448
- previous
447
+ if (!(previous
449
448
  && current
450
- && isSame(previous.discriminant, current.discriminant)
451
- && !hasOverlappingValues(previous.valueKeys, current.valueKeys)
452
- && !hasDirectDiscriminantMutation(previousIfStatement.consequent, previous.discriminant, context)
453
- )) {
449
+ && isSame(previous.discriminant, current.discriminant)) || hasOverlappingValues(previous.valueKeys, current.valueKeys) || hasDirectDiscriminantMutation(previousIfStatement.consequent, previous.discriminant, context)) {
454
450
  return;
455
451
  }
456
452
 
@@ -1,5 +1,10 @@
1
1
  import {findVariable, getStaticValue} from '@eslint-community/eslint-utils';
2
- import {isMethodCall, isNewExpression, isUndefined} from './ast/index.js';
2
+ import {
3
+ isMethodCall,
4
+ isNewExpression,
5
+ isNullLiteral,
6
+ isUndefined,
7
+ } from './ast/index.js';
3
8
  import {
4
9
  getParenthesizedText,
5
10
  getTypeSymbol,
@@ -823,8 +828,6 @@ const getCallKind = (callExpression, comparison, context) => {
823
828
  }
824
829
  };
825
830
 
826
- const isNullLiteral = node => node.type === 'Literal' && node.value === null;
827
-
828
831
  const getComparison = callExpression => {
829
832
  const comparisonTarget = getTransparentExpressionAncestor(callExpression);
830
833
  const {parent} = comparisonTarget;
@@ -82,14 +82,14 @@ function isWellKnownXmlNamespace(text, matchIndex) {
82
82
 
83
83
  /** @param {import('eslint').Rule.RuleContext} context */
84
84
  const create = context => {
85
- let checked = false;
85
+ let isChecked = false;
86
86
 
87
87
  onRoot(context, node => {
88
- if (checked) {
88
+ if (isChecked) {
89
89
  return;
90
90
  }
91
91
 
92
- checked = true;
92
+ isChecked = true;
93
93
 
94
94
  const {sourceCode} = context;
95
95
  const {text} = sourceCode;
@@ -1,6 +1,4 @@
1
- import helperValidatorIdentifier from '@babel/helper-validator-identifier';
2
-
3
- const {isIdentifierName} = helperValidatorIdentifier;
1
+ import {isIdentifierName} from './utils/index.js';
4
2
 
5
3
  const MESSAGE_ID = 'prefer-identifier-import-export-specifiers';
6
4
  const messages = {
@@ -166,14 +166,14 @@ function isMinimalBinaryExpression(left, right, context) {
166
166
  return false;
167
167
  }
168
168
 
169
- const leftSidesAreSame = isSameSourceText(left.left, right.left, context.sourceCode);
170
- const rightSidesAreSame = isSameSourceText(left.right, right.right, context.sourceCode);
169
+ const isLeftSidesAreSame = isSameSourceText(left.left, right.left, context.sourceCode);
170
+ const isRightSidesAreSame = isSameSourceText(left.right, right.right, context.sourceCode);
171
171
 
172
- if (leftSidesAreSame === rightSidesAreSame) {
172
+ if (isLeftSidesAreSame === isRightSidesAreSame) {
173
173
  return false;
174
174
  }
175
175
 
176
- return rightSidesAreSame || isSafeSharedExpression(left.left);
176
+ return isRightSidesAreSame || isSafeSharedExpression(left.left);
177
177
  }
178
178
 
179
179
  function hasSameObjectWithDifferentDynamicKey(left, right, context) {
@@ -1,15 +1,13 @@
1
1
  import {getStaticValue} from '@eslint-community/eslint-utils';
2
- import helperValidatorIdentifier from '@babel/helper-validator-identifier';
3
2
  import {isMethodCall} from './ast/index.js';
4
3
  import {
5
4
  getIndentString,
6
5
  getNextNode,
7
6
  getPreviousNode,
8
7
  isSameReference,
8
+ isIdentifierName,
9
9
  } from './utils/index.js';
10
10
 
11
- const {isIdentifierName} = helperValidatorIdentifier;
12
-
13
11
  const MESSAGE_ID = 'prefer-object-define-properties';
14
12
  const messages = {
15
13
  [MESSAGE_ID]: 'Prefer `Object.defineProperties()` over multiple `Object.defineProperty()` calls.',
@@ -231,11 +231,8 @@ const isGlobalObject = (node, context) =>
231
231
  const isWriteOnlyLeftHandSide = node =>
232
232
  isLeftHandSide(node)
233
233
  && node.parent.type !== 'UpdateExpression'
234
- && !(
235
- node.parent.type === 'AssignmentExpression'
236
- && node.parent.left === node
237
- && node.parent.operator !== '='
238
- );
234
+ && (!(node.parent.type === 'AssignmentExpression'
235
+ && node.parent.left === node) || node.parent.operator === '=');
239
236
 
240
237
  const isGlobalDocument = (node, context) => {
241
238
  node = unwrapTypeScriptExpression(node);
@@ -1,7 +1,5 @@
1
- import helperValidatorIdentifier from '@babel/helper-validator-identifier';
2
1
  import {getStaticStringValue} from './ast/index.js';
3
-
4
- const {isIdentifierName} = helperValidatorIdentifier;
2
+ import {isIdentifierName} from './utils/index.js';
5
3
 
6
4
  const MESSAGE_ID = 'prefer-private-class-fields';
7
5
  const messages = {
@@ -138,14 +138,14 @@ function trueBranchSign(branch) {
138
138
  }
139
139
 
140
140
  function expectedSignForTest(test, minuend, subtrahend) {
141
- const greaterThan = test.operator === '>' || test.operator === '>=';
141
+ const isGreaterThan = test.operator === '>' || test.operator === '>=';
142
142
  const testLeftIsMinuend = isSameReference(test.left, minuend) && isSameReference(test.right, subtrahend);
143
143
 
144
144
  if (testLeftIsMinuend) {
145
- return greaterThan ? 1 : -1;
145
+ return isGreaterThan ? 1 : -1;
146
146
  }
147
147
 
148
- return greaterThan ? -1 : 1;
148
+ return isGreaterThan ? -1 : 1;
149
149
  }
150
150
 
151
151
  function branchSignsMatchSubtraction(branch, minuend, subtrahend) {
@@ -220,9 +220,9 @@ const create = context => {
220
220
 
221
221
  // Orient the subtraction so it matches the comparator's sort direction.
222
222
  const {test} = tree;
223
- const greaterThan = test.operator === '>' || test.operator === '>=';
224
- const leftIsMinuend = greaterThan ? sign > 0 : sign < 0;
225
- const [minuend, subtrahend] = leftIsMinuend ? [test.left, test.right] : [test.right, test.left];
223
+ const isGreaterThan = test.operator === '>' || test.operator === '>=';
224
+ const isLeftIsMinuend = isGreaterThan ? sign > 0 : sign < 0;
225
+ const [minuend, subtrahend] = isLeftIsMinuend ? [test.left, test.right] : [test.right, test.left];
226
226
 
227
227
  if (!branchSignsMatchSubtraction(tree, minuend, subtrahend)) {
228
228
  return;
@@ -68,15 +68,12 @@ const getProblem = (sourceCode, firstNode, secondNode) => {
68
68
  const first = getSupportedDeclaration(sourceCode, firstNode);
69
69
  const second = getSupportedDeclaration(sourceCode, secondNode);
70
70
 
71
- if (!(
72
- first
71
+ if (!(first
73
72
  && second
74
73
  && first.node.kind === second.node.kind
75
74
  && first.source === second.source
76
75
  && sourceCode.getCommentsInside(first.node).length === 0
77
- && sourceCode.getCommentsInside(second.node).length === 0
78
- && !hasCommentsBetween(sourceCode, first.node, second.node)
79
- )) {
76
+ && sourceCode.getCommentsInside(second.node).length === 0) || hasCommentsBetween(sourceCode, first.node, second.node)) {
80
77
  return;
81
78
  }
82
79
 
@@ -21,8 +21,8 @@ const characterClassEscapes = new Map([
21
21
  ['\t', String.raw`\t`],
22
22
  ['\f', String.raw`\f`],
23
23
  ['\v', String.raw`\v`],
24
- ['\u2028', String.raw`\u2028`],
25
- ['\u2029', String.raw`\u2029`],
24
+ ['\u{2028}', String.raw`\u2028`],
25
+ ['\u{2029}', String.raw`\u2029`],
26
26
  ]);
27
27
 
28
28
  // Escapes a single character for use inside a character class. `^` and `-` are only special depending on position, so they are escaped only when necessary (avoids tripping `no-useless-escape` on the output).