eslint-linter-browserify 10.2.1 → 10.3.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/linter.cjs CHANGED
@@ -4216,7 +4216,7 @@ function requireEslintVisitorKeys$2 () {
4216
4216
  return eslintVisitorKeys$2;
4217
4217
  }
4218
4218
 
4219
- var version = "10.2.1";
4219
+ var version = "10.3.0";
4220
4220
  var require$$3$1 = {
4221
4221
  version: version};
4222
4222
 
@@ -13380,10 +13380,9 @@ function requireIdGenerator () {
13380
13380
  next() {
13381
13381
  this.n = (1 + this.n) | 0;
13382
13382
 
13383
- /* c8 ignore start */
13384
13383
  if (this.n < 0) {
13385
13384
  this.n = 1;
13386
- } /* c8 ignore stop */
13385
+ }
13387
13386
 
13388
13387
  return this.prefix + this.n;
13389
13388
  }
@@ -13819,8 +13818,8 @@ function requireCodePathAnalyzer () {
13819
13818
  }
13820
13819
 
13821
13820
  /**
13822
- * Checks whether or not a given logical expression node goes different path
13823
- * between the `true` case and the `false` case.
13821
+ * Checks whether a given logical expression node takes different paths for the
13822
+ * `true` and `false` cases.
13824
13823
  * @param {ASTNode} node A node to check.
13825
13824
  * @returns {boolean} `true` if the node is a test of a choice statement.
13826
13825
  */
@@ -13849,8 +13848,8 @@ function requireCodePathAnalyzer () {
13849
13848
  /**
13850
13849
  * Gets the boolean value of a given literal node.
13851
13850
  *
13852
- * This is used to detect infinity loops (e.g. `while (true) {}`).
13853
- * Statements preceded by an infinity loop are unreachable if the loop didn't
13851
+ * This is used to detect infinite loops (e.g. `while (true) {}`).
13852
+ * Statements preceded by an infinite loop are unreachable if the loop didn't
13854
13853
  * have any `break` statement.
13855
13854
  * @param {ASTNode} node A node to get.
13856
13855
  * @returns {boolean|undefined} a boolean value if the node is a Literal node,
@@ -13963,8 +13962,8 @@ function requireCodePathAnalyzer () {
13963
13962
  }
13964
13963
 
13965
13964
  /**
13966
- * Updates the current segment with empty.
13967
- * This is called at the last of functions or the program.
13965
+ * Updates the current segment with an empty array.
13966
+ * This is called when a code path ends.
13968
13967
  * @param {CodePathAnalyzer} analyzer The instance.
13969
13968
  * @param {ASTNode} node The current AST node.
13970
13969
  * @returns {void}
@@ -14457,7 +14456,7 @@ function requireCodePathAnalyzer () {
14457
14456
  * a = () => {}
14458
14457
  * }
14459
14458
  *
14460
- * In this case, The ArrowFunctionExpression code path is closed first
14459
+ * In this case, the ArrowFunctionExpression code path is closed first,
14461
14460
  * and then we need to close the code path for the PropertyDefinition
14462
14461
  * value.
14463
14462
  */
@@ -47426,12 +47425,31 @@ function requireAstUtils () {
47426
47425
  }
47427
47426
 
47428
47427
  /**
47429
- * Determines whether an opening parenthesis `(`, bracket `[` or backtick ``` ` ``` needs to be preceded by a semicolon.
47430
- * This opening parenthesis or bracket should be at the start of an `ExpressionStatement`, a `MethodDefinition` or at
47431
- * the start of the body of an `ArrowFunctionExpression`.
47428
+ * Checks whether a token can cause continuation of a preceding expression
47429
+ * (for example, of a class field initializer expression) in a class body.
47430
+ * This function checks specifically for tokens that can appear at the start
47431
+ * of a class member: `[` (computed key), `*` (generator method), `in` or `instanceof` (valid keys)
47432
+ * Without a preceding semicolon, these tokens would be parsed as index access or operators.
47433
+ * @param {Token} token The token to check.
47434
+ * @returns {boolean} Whether the token can cause continuation of a preceding expression.
47435
+ */
47436
+ function canContinueExpressionInClassBody(token) {
47437
+ return (
47438
+ (token.type === "Punctuator" &&
47439
+ (token.value === "[" || token.value === "*")) ||
47440
+ // Different parsers may return these tokens as either "Identifier" or "Keyword"
47441
+ ((token.type === "Identifier" || token.type === "Keyword") &&
47442
+ (token.value === "in" || token.value === "instanceof"))
47443
+ );
47444
+ }
47445
+
47446
+ /**
47447
+ * Determines whether an opening parenthesis `(`, bracket `[`, asterisk `*`, or backtick ``` ` ``` needs to be preceded by a semicolon.
47448
+ * This opening parenthesis or bracket should be at the start of an `ExpressionStatement`, a `MethodDefinition`, a `PropertyDefinition`,
47449
+ * or at the start of the body of an `ArrowFunctionExpression`.
47432
47450
  * @type {(sourceCode: SourceCode, node: ASTNode) => boolean}
47433
47451
  * @param {SourceCode} sourceCode The source code object.
47434
- * @param {ASTNode} node A node at the position where an opening parenthesis or bracket will be inserted.
47452
+ * @param {ASTNode} node A node at the position where an opening parenthesis, bracket, or asterisk will be inserted.
47435
47453
  * @returns {boolean} Whether a semicolon is required before the opening parenthesis or bracket.
47436
47454
  */
47437
47455
  let needsPrecedingSemicolon;
@@ -47522,6 +47540,18 @@ function requireAstUtils () {
47522
47540
 
47523
47541
  const prevNode = sourceCode.getNodeByRangeIndex(prevToken.range[0]);
47524
47542
 
47543
+ // Uninitialized class fields don't need a semicolon
47544
+ if (
47545
+ // Key
47546
+ (prevNode.parent.type === "PropertyDefinition" &&
47547
+ prevNode.parent.key === prevNode) ||
47548
+ // Closing bracket of a computed key
47549
+ (prevNode.type === "PropertyDefinition" &&
47550
+ isClosingBracketToken(prevToken))
47551
+ ) {
47552
+ return false;
47553
+ }
47554
+
47525
47555
  if (
47526
47556
  prevNode.type === "TSDeclareFunction" ||
47527
47557
  prevNode.parent.type === "TSImportEqualsDeclaration" ||
@@ -49010,6 +49040,7 @@ function requireAstUtils () {
49010
49040
  isTopLevelExpressionStatement,
49011
49041
  isDirective,
49012
49042
  isStartOfExpressionStatement,
49043
+ canContinueExpressionInClassBody,
49013
49044
  needsPrecedingSemicolon,
49014
49045
  isImportAttributeKey,
49015
49046
  getOpeningParenOfParams,
@@ -103350,6 +103381,12 @@ function requireNoUnusedPrivateClassMembers () {
103350
103381
  if (hasRequiredNoUnusedPrivateClassMembers) return noUnusedPrivateClassMembers;
103351
103382
  hasRequiredNoUnusedPrivateClassMembers = 1;
103352
103383
 
103384
+ //------------------------------------------------------------------------------
103385
+ // Requirements
103386
+ //------------------------------------------------------------------------------
103387
+
103388
+ const astUtils = requireAstUtils();
103389
+
103353
103390
  //------------------------------------------------------------------------------
103354
103391
  // Rule Definition
103355
103392
  //------------------------------------------------------------------------------
@@ -103358,6 +103395,7 @@ function requireNoUnusedPrivateClassMembers () {
103358
103395
  noUnusedPrivateClassMembers = {
103359
103396
  meta: {
103360
103397
  type: "problem",
103398
+ hasSuggestions: true,
103361
103399
 
103362
103400
  docs: {
103363
103401
  description: "Disallow unused private class members",
@@ -103370,12 +103408,168 @@ function requireNoUnusedPrivateClassMembers () {
103370
103408
  messages: {
103371
103409
  unusedPrivateClassMember:
103372
103410
  "'{{classMemberName}}' is defined but never used.",
103411
+ removeUnusedPrivateClassMember:
103412
+ "Remove unused private class member '{{classMemberName}}'.",
103373
103413
  },
103374
103414
  },
103375
103415
 
103376
103416
  create(context) {
103417
+ const sourceCode = context.sourceCode;
103377
103418
  const trackedClasses = [];
103378
103419
 
103420
+ /**
103421
+ * Gets the start index of the line that contains a given token or node.
103422
+ * @param {ASTNode|Token|Comment} nodeOrToken The token or node to check
103423
+ * @returns {number} The line start index
103424
+ */
103425
+ function getLineStartIndex(nodeOrToken) {
103426
+ return nodeOrToken.range[0] - nodeOrToken.loc.start.column;
103427
+ }
103428
+
103429
+ /**
103430
+ * Checks whether a token or node starts on its own line, preceded only by whitespace.
103431
+ * @param {ASTNode|Token|Comment} nodeOrToken The token or node to check
103432
+ * @returns {boolean} Whether the token or node starts on its own line
103433
+ */
103434
+ function startsOnOwnLine(nodeOrToken) {
103435
+ return (
103436
+ sourceCode.getTokenBefore(nodeOrToken, {
103437
+ includeComments: true,
103438
+ }).loc.end.line !== nodeOrToken.loc.start.line
103439
+ );
103440
+ }
103441
+
103442
+ /**
103443
+ * Gets leading comments that are directly attached to a class member.
103444
+ * @param {ASTNode} classMemberNode The class member node
103445
+ * @returns {Comment[]} Leading comments to remove with the member
103446
+ */
103447
+ function getLeadingComments(classMemberNode) {
103448
+ const commentsBefore =
103449
+ sourceCode.getCommentsBefore(classMemberNode);
103450
+ const lastNonLeadingCommentIndex = commentsBefore.findLastIndex(
103451
+ (comment, index, self) => {
103452
+ const next =
103453
+ index < self.length - 1
103454
+ ? self[index + 1]
103455
+ : classMemberNode;
103456
+
103457
+ return (
103458
+ !startsOnOwnLine(comment) ||
103459
+ next.loc.start.line - comment.loc.end.line > 1
103460
+ );
103461
+ },
103462
+ );
103463
+
103464
+ return commentsBefore.slice(lastNonLeadingCommentIndex + 1);
103465
+ }
103466
+
103467
+ /**
103468
+ * Checks whether a class member shares its line with another token.
103469
+ * @param {ASTNode} classMemberNode The class member node
103470
+ * @returns {boolean} Whether the member shares its line with another token
103471
+ */
103472
+ function sharesLineWithAnotherToken(classMemberNode) {
103473
+ const previousToken = sourceCode.getTokenBefore(classMemberNode);
103474
+ const nextToken = sourceCode.getTokenAfter(classMemberNode);
103475
+
103476
+ return (
103477
+ previousToken.loc.end.line === classMemberNode.loc.start.line ||
103478
+ nextToken.loc.start.line === classMemberNode.loc.end.line
103479
+ );
103480
+ }
103481
+
103482
+ /**
103483
+ * Gets trailing comments that are directly attached to a class member.
103484
+ * Same-line trailing comments are preserved when another token shares
103485
+ * the line, because the comment might describe the remaining code rather
103486
+ * than the unused member alone.
103487
+ * @param {ASTNode} classMemberNode The class member node
103488
+ * @returns {Comment[]} Trailing comments to remove with the member
103489
+ */
103490
+ function getTrailingComments(classMemberNode) {
103491
+ if (sharesLineWithAnotherToken(classMemberNode)) {
103492
+ return [];
103493
+ }
103494
+
103495
+ return sourceCode
103496
+ .getCommentsAfter(classMemberNode)
103497
+ .filter(
103498
+ comment =>
103499
+ comment.loc.start.line === classMemberNode.loc.end.line,
103500
+ );
103501
+ }
103502
+
103503
+ /**
103504
+ * Gets the token after which a semicolon should be inserted when removing a class member.
103505
+ * @param {ASTNode} classMemberNode The member that would be removed
103506
+ * @returns {Token|null} The token after which a semicolon should be inserted, or null if no semicolon is needed
103507
+ */
103508
+ function getSemicolonInsertionToken(classMemberNode) {
103509
+ const nextToken = sourceCode.getTokenAfter(classMemberNode);
103510
+
103511
+ if (
103512
+ astUtils.canContinueExpressionInClassBody(nextToken) &&
103513
+ astUtils.needsPrecedingSemicolon(sourceCode, classMemberNode)
103514
+ ) {
103515
+ return sourceCode.getTokenBefore(classMemberNode);
103516
+ }
103517
+
103518
+ return null;
103519
+ }
103520
+
103521
+ /**
103522
+ * Gets the replacement range for removing an unused class member.
103523
+ * @param {ASTNode} classMemberNode The member that would be removed
103524
+ * @returns {number[]} The text range to remove
103525
+ */
103526
+ function getMemberRemovalRange(classMemberNode) {
103527
+ const leadingComments = getLeadingComments(classMemberNode);
103528
+ const trailingComments = getTrailingComments(classMemberNode);
103529
+ const shouldRemoveLeadingComments =
103530
+ leadingComments.length > 0 &&
103531
+ !sharesLineWithAnotherToken(classMemberNode);
103532
+ const lastItemToRemove =
103533
+ trailingComments.length > 0
103534
+ ? trailingComments.at(-1)
103535
+ : classMemberNode;
103536
+
103537
+ const previousToken = sourceCode.getTokenBefore(classMemberNode);
103538
+ const nextToken = sourceCode.getTokenAfter(lastItemToRemove, {
103539
+ includeComments: true,
103540
+ });
103541
+ const nextTokenStartsOnNewLine =
103542
+ nextToken.loc.start.line > lastItemToRemove.loc.end.line;
103543
+ const shouldRemoveOwnLine =
103544
+ !shouldRemoveLeadingComments &&
103545
+ startsOnOwnLine(classMemberNode) &&
103546
+ nextTokenStartsOnNewLine;
103547
+ let start = classMemberNode.range[0];
103548
+ let end = lastItemToRemove.range[1];
103549
+
103550
+ if (shouldRemoveLeadingComments) {
103551
+ start = nextTokenStartsOnNewLine
103552
+ ? getLineStartIndex(leadingComments[0])
103553
+ : leadingComments[0].range[0];
103554
+ end = nextTokenStartsOnNewLine
103555
+ ? getLineStartIndex(nextToken)
103556
+ : nextToken.range[0];
103557
+ } else if (shouldRemoveOwnLine) {
103558
+ start = getLineStartIndex(classMemberNode);
103559
+ end = getLineStartIndex(nextToken);
103560
+ } else if (
103561
+ previousToken.loc.end.line === classMemberNode.loc.start.line
103562
+ ) {
103563
+ start = previousToken.range[1];
103564
+ } else if (
103565
+ nextToken.loc.start.line === lastItemToRemove.loc.end.line
103566
+ ) {
103567
+ end = nextToken.range[0];
103568
+ }
103569
+
103570
+ return [start, end];
103571
+ }
103572
+
103379
103573
  /**
103380
103574
  * Check whether the current node is in a write only assignment.
103381
103575
  * @param {ASTNode} privateIdentifierNode Node referring to a private identifier
@@ -103431,6 +103625,7 @@ function requireNoUnusedPrivateClassMembers () {
103431
103625
  if (bodyMember.key.type === "PrivateIdentifier") {
103432
103626
  privateMembers.set(bodyMember.key.name, {
103433
103627
  declaredNode: bodyMember,
103628
+ hasReference: false,
103434
103629
  isAccessor:
103435
103630
  bodyMember.type === "MethodDefinition" &&
103436
103631
  (bodyMember.kind === "set" ||
@@ -103473,6 +103668,8 @@ function requireNoUnusedPrivateClassMembers () {
103473
103668
  return;
103474
103669
  }
103475
103670
 
103671
+ memberDefinition.hasReference = true;
103672
+
103476
103673
  /*
103477
103674
  * Any usage of an accessor is considered a read, as the getter/setter can have
103478
103675
  * side-effects in its definition.
@@ -103544,11 +103741,12 @@ function requireNoUnusedPrivateClassMembers () {
103544
103741
 
103545
103742
  for (const [
103546
103743
  classMemberName,
103547
- { declaredNode, isUsed },
103744
+ { declaredNode, hasReference, isUsed },
103548
103745
  ] of unusedPrivateMembers.entries()) {
103549
103746
  if (isUsed) {
103550
103747
  continue;
103551
103748
  }
103749
+
103552
103750
  context.report({
103553
103751
  node: declaredNode,
103554
103752
  loc: declaredNode.key.loc,
@@ -103556,6 +103754,39 @@ function requireNoUnusedPrivateClassMembers () {
103556
103754
  data: {
103557
103755
  classMemberName: `#${classMemberName}`,
103558
103756
  },
103757
+ suggest: [
103758
+ {
103759
+ messageId: "removeUnusedPrivateClassMember",
103760
+ data: {
103761
+ classMemberName: `#${classMemberName}`,
103762
+ },
103763
+ *fix(fixer) {
103764
+ if (hasReference) {
103765
+ return;
103766
+ }
103767
+
103768
+ const removalRange =
103769
+ getMemberRemovalRange(declaredNode);
103770
+ const semicolonInsertionToken =
103771
+ getSemicolonInsertionToken(
103772
+ declaredNode,
103773
+ );
103774
+ const removalFix = fixer.replaceTextRange(
103775
+ removalRange,
103776
+ "",
103777
+ );
103778
+
103779
+ yield removalFix;
103780
+
103781
+ if (semicolonInsertionToken) {
103782
+ yield fixer.insertTextAfter(
103783
+ semicolonInsertionToken,
103784
+ ";",
103785
+ );
103786
+ }
103787
+ },
103788
+ },
103789
+ ],
103559
103790
  });
103560
103791
  }
103561
103792
  },
@@ -107139,7 +107370,7 @@ function requireNoUselessConcat () {
107139
107370
  }
107140
107371
 
107141
107372
  /**
107142
- * Get's the right most node on the left side of a BinaryExpression with + operator.
107373
+ * Gets the right most node on the left side of a BinaryExpression with + operator.
107143
107374
  * @param {ASTNode} node A BinaryExpression node to check.
107144
107375
  * @returns {ASTNode} node
107145
107376
  */
@@ -107153,7 +107384,7 @@ function requireNoUselessConcat () {
107153
107384
  }
107154
107385
 
107155
107386
  /**
107156
- * Get's the left most node on the right side of a BinaryExpression with + operator.
107387
+ * Gets the left most node on the right side of a BinaryExpression with + operator.
107157
107388
  * @param {ASTNode} node A BinaryExpression node to check.
107158
107389
  * @returns {ASTNode} node
107159
107390
  */
@@ -107473,8 +107704,9 @@ function requireNoUselessConstructor () {
107473
107704
  const nextToken =
107474
107705
  sourceCode.getTokenAfter(node);
107475
107706
  const addSemiColon =
107476
- nextToken.type === "Punctuator" &&
107477
- nextToken.value === "[" &&
107707
+ astUtils.canContinueExpressionInClassBody(
107708
+ nextToken,
107709
+ ) &&
107478
107710
  astUtils.needsPrecedingSemicolon(
107479
107711
  sourceCode,
107480
107712
  node,
@@ -119691,12 +119923,14 @@ function requireRequireAwait () {
119691
119923
  */
119692
119924
  const nextToken = sourceCode.getTokenAfter(asyncToken);
119693
119925
  const addSemiColon =
119694
- nextToken.type === "Punctuator" &&
119695
- (nextToken.value === "[" || nextToken.value === "(") &&
119696
- (nodeWithAsyncKeyword.type === "MethodDefinition" ||
119926
+ ((astUtils.isOpeningParenToken(nextToken) &&
119697
119927
  astUtils.isStartOfExpressionStatement(
119698
119928
  nodeWithAsyncKeyword,
119699
- )) &&
119929
+ )) ||
119930
+ (nodeWithAsyncKeyword.type === "MethodDefinition" &&
119931
+ astUtils.canContinueExpressionInClassBody(
119932
+ nextToken,
119933
+ ))) &&
119700
119934
  astUtils.needsPrecedingSemicolon(
119701
119935
  sourceCode,
119702
119936
  nodeWithAsyncKeyword,