eslint 10.0.0-alpha.0 → 10.0.0-alpha.1

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/README.md CHANGED
@@ -343,7 +343,7 @@ to get your logo on our READMEs and [website](https://eslint.org/sponsors).
343
343
  <p><a href="https://automattic.com"><img src="https://images.opencollective.com/automattic/d0ef3e1/logo.png" alt="Automattic" height="128"></a> <a href="https://www.airbnb.com/"><img src="https://images.opencollective.com/airbnb/d327d66/logo.png" alt="Airbnb" height="128"></a></p><h3>Gold Sponsors</h3>
344
344
  <p><a href="https://qlty.sh/"><img src="https://images.opencollective.com/qltysh/33d157d/logo.png" alt="Qlty Software" height="96"></a> <a href="https://shopify.engineering/"><img src="https://avatars.githubusercontent.com/u/8085" alt="Shopify" height="96"></a></p><h3>Silver Sponsors</h3>
345
345
  <p><a href="https://vite.dev/"><img src="https://images.opencollective.com/vite/e6d15e1/logo.png" alt="Vite" height="64"></a> <a href="https://liftoff.io/"><img src="https://images.opencollective.com/liftoff/2d6c3b6/logo.png" alt="Liftoff" height="64"></a> <a href="https://americanexpress.io"><img src="https://avatars.githubusercontent.com/u/3853301" alt="American Express" height="64"></a> <a href="https://stackblitz.com"><img src="https://avatars.githubusercontent.com/u/28635252" alt="StackBlitz" height="64"></a></p><h3>Bronze Sponsors</h3>
346
- <p><a href="https://cybozu.co.jp/"><img src="https://images.opencollective.com/cybozu/933e46d/logo.png" alt="Cybozu" height="32"></a> <a href="https://syntax.fm"><img src="https://github.com/syntaxfm.png" alt="Syntax" height="32"></a> <a href="https://icons8.com/"><img src="https://images.opencollective.com/icons8/7fa1641/logo.png" alt="Icons8" height="32"></a> <a href="https://discord.com"><img src="https://images.opencollective.com/discordapp/f9645d9/logo.png" alt="Discord" height="32"></a> <a href="https://www.gitbook.com"><img src="https://avatars.githubusercontent.com/u/7111340" alt="GitBook" height="32"></a> <a href="https://nx.dev"><img src="https://avatars.githubusercontent.com/u/23692104" alt="Nx" height="32"></a> <a href="https://opensource.mercedes-benz.com/"><img src="https://avatars.githubusercontent.com/u/34240465" alt="Mercedes-Benz Group" height="32"></a> <a href="https://herocoders.com"><img src="https://avatars.githubusercontent.com/u/37549774" alt="HeroCoders" height="32"></a> <a href="https://www.lambdatest.com"><img src="https://avatars.githubusercontent.com/u/171592363" alt="LambdaTest" height="32"></a></p>
346
+ <p><a href="https://cybozu.co.jp/"><img src="https://images.opencollective.com/cybozu/933e46d/logo.png" alt="Cybozu" height="32"></a> <a href="https://syntax.fm"><img src="https://github.com/syntaxfm.png" alt="Syntax" height="32"></a> <a href="https://www.n-ix.com/"><img src="https://images.opencollective.com/n-ix-ltd/575a7a5/logo.png" alt="N-iX Ltd" height="32"></a> <a href="https://icons8.com/"><img src="https://images.opencollective.com/icons8/7fa1641/logo.png" alt="Icons8" height="32"></a> <a href="https://discord.com"><img src="https://images.opencollective.com/discordapp/f9645d9/logo.png" alt="Discord" height="32"></a> <a href="https://www.gitbook.com"><img src="https://avatars.githubusercontent.com/u/7111340" alt="GitBook" height="32"></a> <a href="https://nx.dev"><img src="https://avatars.githubusercontent.com/u/23692104" alt="Nx" height="32"></a> <a href="https://opensource.mercedes-benz.com/"><img src="https://avatars.githubusercontent.com/u/34240465" alt="Mercedes-Benz Group" height="32"></a> <a href="https://herocoders.com"><img src="https://avatars.githubusercontent.com/u/37549774" alt="HeroCoders" height="32"></a> <a href="https://www.lambdatest.com"><img src="https://avatars.githubusercontent.com/u/171592363" alt="LambdaTest" height="32"></a></p>
347
347
  <h3>Technology Sponsors</h3>
348
348
  Technology sponsors allow us to use their products and services for free as part of a contribution to the open source ecosystem and our work.
349
349
  <p><a href="https://netlify.com"><img src="https://raw.githubusercontent.com/eslint/eslint.org/main/src/assets/images/techsponsors/netlify-icon.svg" alt="Netlify" height="32"></a> <a href="https://algolia.com"><img src="https://raw.githubusercontent.com/eslint/eslint.org/main/src/assets/images/techsponsors/algolia-icon.svg" alt="Algolia" height="32"></a> <a href="https://1password.com"><img src="https://raw.githubusercontent.com/eslint/eslint.org/main/src/assets/images/techsponsors/1password-icon.svg" alt="1Password" height="32"></a></p>
@@ -8,8 +8,7 @@
8
8
  // Requirements
9
9
  //------------------------------------------------------------------------------
10
10
 
11
- const { isCommentToken } = require("@eslint-community/eslint-utils"),
12
- TokenStore = require("./token-store"),
11
+ const TokenStore = require("./token-store"),
13
12
  astUtils = require("../../../shared/ast-utils"),
14
13
  Traverser = require("../../../shared/traverser"),
15
14
  globals = require("../../../../conf/globals"),
@@ -90,21 +89,6 @@ function getGlobalsForEcmaVersion(ecmaVersion) {
90
89
  }
91
90
  }
92
91
 
93
- /**
94
- * Check to see if its a ES6 export declaration.
95
- * @param {ASTNode} astNode An AST node.
96
- * @returns {boolean} whether the given node represents an export declaration.
97
- * @private
98
- */
99
- function looksLikeExport(astNode) {
100
- return (
101
- astNode.type === "ExportDefaultDeclaration" ||
102
- astNode.type === "ExportNamedDeclaration" ||
103
- astNode.type === "ExportAllDeclaration" ||
104
- astNode.type === "ExportSpecifier"
105
- );
106
- }
107
-
108
92
  /**
109
93
  * Merges two sorted lists into a larger sorted list in O(n) time.
110
94
  * @param {Token[]} tokens The list of tokens.
@@ -179,56 +163,6 @@ function nodesOrTokensOverlap(first, second) {
179
163
  );
180
164
  }
181
165
 
182
- /**
183
- * Determines if two nodes or tokens have at least one whitespace character
184
- * between them. Order does not matter. Returns false if the given nodes or
185
- * tokens overlap.
186
- * @param {SourceCode} sourceCode The source code object.
187
- * @param {ASTNode|Token} first The first node or token to check between.
188
- * @param {ASTNode|Token} second The second node or token to check between.
189
- * @param {boolean} checkInsideOfJSXText If `true` is present, check inside of JSXText tokens for backward compatibility.
190
- * @returns {boolean} True if there is a whitespace character between
191
- * any of the tokens found between the two given nodes or tokens.
192
- * @public
193
- */
194
- function isSpaceBetween(sourceCode, first, second, checkInsideOfJSXText) {
195
- if (nodesOrTokensOverlap(first, second)) {
196
- return false;
197
- }
198
-
199
- const [startingNodeOrToken, endingNodeOrToken] =
200
- first.range[1] <= second.range[0] ? [first, second] : [second, first];
201
- const firstToken =
202
- sourceCode.getLastToken(startingNodeOrToken) || startingNodeOrToken;
203
- const finalToken =
204
- sourceCode.getFirstToken(endingNodeOrToken) || endingNodeOrToken;
205
- let currentToken = firstToken;
206
-
207
- while (currentToken !== finalToken) {
208
- const nextToken = sourceCode.getTokenAfter(currentToken, {
209
- includeComments: true,
210
- });
211
-
212
- if (
213
- currentToken.range[1] !== nextToken.range[0] ||
214
- /*
215
- * For backward compatibility, check spaces in JSXText.
216
- * https://github.com/eslint/eslint/issues/12614
217
- */
218
- (checkInsideOfJSXText &&
219
- nextToken !== finalToken &&
220
- nextToken.type === "JSXText" &&
221
- /\s/u.test(nextToken.value))
222
- ) {
223
- return true;
224
- }
225
-
226
- currentToken = nextToken;
227
- }
228
-
229
- return false;
230
- }
231
-
232
166
  /**
233
167
  * Performs binary search to find the line number containing a given character index.
234
168
  * Returns the lower bound - the index of the first element greater than the target.
@@ -529,87 +463,6 @@ class SourceCode extends TokenStore {
529
463
  return this.ast.comments;
530
464
  }
531
465
 
532
- /**
533
- * Retrieves the JSDoc comment for a given node.
534
- * @param {ASTNode} node The AST node to get the comment for.
535
- * @returns {Token|null} The Block comment token containing the JSDoc comment
536
- * for the given node or null if not found.
537
- * @public
538
- * @deprecated
539
- */
540
- getJSDocComment(node) {
541
- /**
542
- * Checks for the presence of a JSDoc comment for the given node and returns it.
543
- * @param {ASTNode} astNode The AST node to get the comment for.
544
- * @returns {Token|null} The Block comment token containing the JSDoc comment
545
- * for the given node or null if not found.
546
- * @private
547
- */
548
- const findJSDocComment = astNode => {
549
- const tokenBefore = this.getTokenBefore(astNode, {
550
- includeComments: true,
551
- });
552
-
553
- if (
554
- tokenBefore &&
555
- isCommentToken(tokenBefore) &&
556
- tokenBefore.type === "Block" &&
557
- tokenBefore.value.charAt(0) === "*" &&
558
- astNode.loc.start.line - tokenBefore.loc.end.line <= 1
559
- ) {
560
- return tokenBefore;
561
- }
562
-
563
- return null;
564
- };
565
- let parent = node.parent;
566
-
567
- switch (node.type) {
568
- case "ClassDeclaration":
569
- case "FunctionDeclaration":
570
- return findJSDocComment(
571
- looksLikeExport(parent) ? parent : node,
572
- );
573
-
574
- case "ClassExpression":
575
- return findJSDocComment(parent.parent);
576
-
577
- case "ArrowFunctionExpression":
578
- case "FunctionExpression":
579
- if (
580
- parent.type !== "CallExpression" &&
581
- parent.type !== "NewExpression"
582
- ) {
583
- while (
584
- !this.getCommentsBefore(parent).length &&
585
- !/Function/u.test(parent.type) &&
586
- parent.type !== "MethodDefinition" &&
587
- parent.type !== "Property"
588
- ) {
589
- parent = parent.parent;
590
-
591
- if (!parent) {
592
- break;
593
- }
594
- }
595
-
596
- if (
597
- parent &&
598
- parent.type !== "FunctionDeclaration" &&
599
- parent.type !== "Program"
600
- ) {
601
- return findJSDocComment(parent);
602
- }
603
- }
604
-
605
- return findJSDocComment(node);
606
-
607
- // falls through
608
- default:
609
- return null;
610
- }
611
- }
612
-
613
466
  /**
614
467
  * Gets the deepest node containing a range index.
615
468
  * @param {number} index Range index of the desired node.
@@ -649,24 +502,33 @@ class SourceCode extends TokenStore {
649
502
  * @public
650
503
  */
651
504
  isSpaceBetween(first, second) {
652
- return isSpaceBetween(this, first, second, false);
653
- }
505
+ if (nodesOrTokensOverlap(first, second)) {
506
+ return false;
507
+ }
654
508
 
655
- /**
656
- * Determines if two nodes or tokens have at least one whitespace character
657
- * between them. Order does not matter. Returns false if the given nodes or
658
- * tokens overlap.
659
- * For backward compatibility, this method returns true if there are
660
- * `JSXText` tokens that contain whitespaces between the two.
661
- * @param {ASTNode|Token} first The first node or token to check between.
662
- * @param {ASTNode|Token} second The second node or token to check between.
663
- * @returns {boolean} True if there is a whitespace character between
664
- * any of the tokens found between the two given nodes or tokens.
665
- * @deprecated in favor of isSpaceBetween().
666
- * @public
667
- */
668
- isSpaceBetweenTokens(first, second) {
669
- return isSpaceBetween(this, first, second, true);
509
+ const [startingNodeOrToken, endingNodeOrToken] =
510
+ first.range[1] <= second.range[0]
511
+ ? [first, second]
512
+ : [second, first];
513
+ const firstToken =
514
+ this.getLastToken(startingNodeOrToken) || startingNodeOrToken;
515
+ const finalToken =
516
+ this.getFirstToken(endingNodeOrToken) || endingNodeOrToken;
517
+ let currentToken = firstToken;
518
+
519
+ while (currentToken !== finalToken) {
520
+ const nextToken = this.getTokenAfter(currentToken, {
521
+ includeComments: true,
522
+ });
523
+
524
+ if (currentToken.range[1] !== nextToken.range[0]) {
525
+ return true;
526
+ }
527
+
528
+ currentToken = nextToken;
529
+ }
530
+
531
+ return false;
670
532
  }
671
533
 
672
534
  /**
@@ -444,32 +444,6 @@ module.exports = class TokenStore {
444
444
  ).getOneToken();
445
445
  }
446
446
 
447
- /**
448
- * Gets the token that precedes a given node or token in the token stream.
449
- * This is defined for backward compatibility. Use `includeComments` option instead.
450
- * TODO: We have a plan to remove this in a future major version.
451
- * @param {ASTNode|Token|Comment} node The AST node or token.
452
- * @param {number} [skip=0] A number of tokens to skip.
453
- * @returns {Token|null} An object representing the token.
454
- * @deprecated
455
- */
456
- getTokenOrCommentBefore(node, skip) {
457
- return this.getTokenBefore(node, { includeComments: true, skip });
458
- }
459
-
460
- /**
461
- * Gets the token that follows a given node or token in the token stream.
462
- * This is defined for backward compatibility. Use `includeComments` option instead.
463
- * TODO: We have a plan to remove this in a future major version.
464
- * @param {ASTNode|Token|Comment} node The AST node or token.
465
- * @param {number} [skip=0] A number of tokens to skip.
466
- * @returns {Token|null} An object representing the token.
467
- * @deprecated
468
- */
469
- getTokenOrCommentAfter(node, skip) {
470
- return this.getTokenAfter(node, { includeComments: true, skip });
471
- }
472
-
473
447
  //--------------------------------------------------------------------------
474
448
  // Gets multiple tokens.
475
449
  //--------------------------------------------------------------------------
@@ -543,6 +543,16 @@ function assertTestCommonProperties(item) {
543
543
  * @throws {AssertionError} If the test case is not valid.
544
544
  */
545
545
  function assertValidTestCase(item, seenTestCases) {
546
+ // must not have properties of invalid test cases
547
+ assert.ok(
548
+ item.errors === void 0,
549
+ "Valid test case must not have 'errors' property",
550
+ );
551
+ assert.ok(
552
+ item.output === void 0,
553
+ "Valid test case must not have 'output' property",
554
+ );
555
+
546
556
  assertTestCommonProperties(item);
547
557
  checkDuplicateTestCase(item, seenTestCases);
548
558
  }
@@ -258,13 +258,13 @@ module.exports = {
258
258
  if (astUtils.isTokenOnSameLine(first, second)) {
259
259
  if (
260
260
  openingBracketMustBeSpaced &&
261
- !sourceCode.isSpaceBetweenTokens(first, second)
261
+ !sourceCode.isSpaceBetween(first, second)
262
262
  ) {
263
263
  reportRequiredBeginningSpace(node, first);
264
264
  }
265
265
  if (
266
266
  !openingBracketMustBeSpaced &&
267
- sourceCode.isSpaceBetweenTokens(first, second)
267
+ sourceCode.isSpaceBetween(first, second)
268
268
  ) {
269
269
  reportNoBeginningSpace(node, first);
270
270
  }
@@ -276,13 +276,13 @@ module.exports = {
276
276
  ) {
277
277
  if (
278
278
  closingBracketMustBeSpaced &&
279
- !sourceCode.isSpaceBetweenTokens(penultimate, last)
279
+ !sourceCode.isSpaceBetween(penultimate, last)
280
280
  ) {
281
281
  reportRequiredEndingSpace(node, last);
282
282
  }
283
283
  if (
284
284
  !closingBracketMustBeSpaced &&
285
- sourceCode.isSpaceBetweenTokens(penultimate, last)
285
+ sourceCode.isSpaceBetween(penultimate, last)
286
286
  ) {
287
287
  reportNoEndingSpace(node, last);
288
288
  }
@@ -95,7 +95,7 @@ module.exports = {
95
95
  function isValid(left, right) {
96
96
  return (
97
97
  !util.isTokenOnSameLine(left, right) ||
98
- sourceCode.isSpaceBetweenTokens(left, right) === always
98
+ sourceCode.isSpaceBetween(left, right) === always
99
99
  );
100
100
  }
101
101
 
@@ -178,10 +178,7 @@ module.exports = {
178
178
  !commaTokensToIgnore.includes(token) &&
179
179
  astUtils.isTokenOnSameLine(previousToken, token) &&
180
180
  options.before !==
181
- sourceCode.isSpaceBetweenTokens(
182
- previousToken,
183
- token,
184
- )
181
+ sourceCode.isSpaceBetween(previousToken, token)
185
182
  ) {
186
183
  report(token, "before", previousToken);
187
184
  }
@@ -195,7 +192,7 @@ module.exports = {
195
192
  !(!options.after && nextToken.type === "Line") && // special case, allow space before line comment
196
193
  astUtils.isTokenOnSameLine(token, nextToken) &&
197
194
  options.after !==
198
- sourceCode.isSpaceBetweenTokens(token, nextToken)
195
+ sourceCode.isSpaceBetween(token, nextToken)
199
196
  ) {
200
197
  report(token, "after", nextToken);
201
198
  }
@@ -203,13 +203,13 @@ module.exports = {
203
203
  if (astUtils.isTokenOnSameLine(before, first)) {
204
204
  if (propertyNameMustBeSpaced) {
205
205
  if (
206
- !sourceCode.isSpaceBetweenTokens(before, first) &&
206
+ !sourceCode.isSpaceBetween(before, first) &&
207
207
  astUtils.isTokenOnSameLine(before, first)
208
208
  ) {
209
209
  reportRequiredBeginningSpace(node, before);
210
210
  }
211
211
  } else {
212
- if (sourceCode.isSpaceBetweenTokens(before, first)) {
212
+ if (sourceCode.isSpaceBetween(before, first)) {
213
213
  reportNoBeginningSpace(node, before, first);
214
214
  }
215
215
  }
@@ -218,13 +218,13 @@ module.exports = {
218
218
  if (astUtils.isTokenOnSameLine(last, after)) {
219
219
  if (propertyNameMustBeSpaced) {
220
220
  if (
221
- !sourceCode.isSpaceBetweenTokens(last, after) &&
221
+ !sourceCode.isSpaceBetween(last, after) &&
222
222
  astUtils.isTokenOnSameLine(last, after)
223
223
  ) {
224
224
  reportRequiredEndingSpace(node, after);
225
225
  }
226
226
  } else {
227
- if (sourceCode.isSpaceBetweenTokens(last, after)) {
227
+ if (sourceCode.isSpaceBetween(last, after)) {
228
228
  reportNoEndingSpace(node, after, last);
229
229
  }
230
230
  }
@@ -163,7 +163,7 @@ module.exports = {
163
163
  !isOpenParenOfTemplate(prevToken) &&
164
164
  !tokensToIgnore.has(prevToken) &&
165
165
  astUtils.isTokenOnSameLine(prevToken, token) &&
166
- !sourceCode.isSpaceBetweenTokens(prevToken, token)
166
+ !sourceCode.isSpaceBetween(prevToken, token)
167
167
  ) {
168
168
  context.report({
169
169
  loc: token.loc,
@@ -192,7 +192,7 @@ module.exports = {
192
192
  !isOpenParenOfTemplate(prevToken) &&
193
193
  !tokensToIgnore.has(prevToken) &&
194
194
  astUtils.isTokenOnSameLine(prevToken, token) &&
195
- sourceCode.isSpaceBetweenTokens(prevToken, token)
195
+ sourceCode.isSpaceBetween(prevToken, token)
196
196
  ) {
197
197
  context.report({
198
198
  loc: { start: prevToken.loc.end, end: token.loc.start },
@@ -224,7 +224,7 @@ module.exports = {
224
224
  !isCloseParenOfTemplate(nextToken) &&
225
225
  !tokensToIgnore.has(nextToken) &&
226
226
  astUtils.isTokenOnSameLine(token, nextToken) &&
227
- !sourceCode.isSpaceBetweenTokens(token, nextToken)
227
+ !sourceCode.isSpaceBetween(token, nextToken)
228
228
  ) {
229
229
  context.report({
230
230
  loc: token.loc,
@@ -253,7 +253,7 @@ module.exports = {
253
253
  !isCloseParenOfTemplate(nextToken) &&
254
254
  !tokensToIgnore.has(nextToken) &&
255
255
  astUtils.isTokenOnSameLine(token, nextToken) &&
256
- sourceCode.isSpaceBetweenTokens(token, nextToken)
256
+ sourceCode.isSpaceBetween(token, nextToken)
257
257
  ) {
258
258
  context.report({
259
259
  loc: { start: token.loc.end, end: nextToken.loc.start },
@@ -470,7 +470,7 @@ module.exports = {
470
470
  return (
471
471
  rightParenToken &&
472
472
  tokenAfterRightParen &&
473
- !sourceCode.isSpaceBetweenTokens(
473
+ !sourceCode.isSpaceBetween(
474
474
  rightParenToken,
475
475
  tokenAfterRightParen,
476
476
  ) &&
@@ -81,7 +81,7 @@ module.exports = {
81
81
  if (
82
82
  parenToken &&
83
83
  parenToken.range[1] < node.range[1] &&
84
- sourceCode.isSpaceBetweenTokens(prevToken, parenToken)
84
+ sourceCode.isSpaceBetween(prevToken, parenToken)
85
85
  ) {
86
86
  context.report({
87
87
  node,
@@ -185,6 +185,8 @@ module.exports = {
185
185
  },
186
186
 
187
187
  create(context) {
188
+ const { sourceCode } = context;
189
+
188
190
  /**
189
191
  * Checks whether a node is a redundant constructor
190
192
  * @param {ASTNode} node node to check
@@ -211,6 +213,14 @@ module.exports = {
211
213
  const body = node.value.body.body;
212
214
  const ctorParams = node.value.params;
213
215
  const superClass = node.parent.parent.superClass;
216
+ const parenToken = sourceCode.getFirstToken(
217
+ node,
218
+ astUtils.isOpeningParenToken,
219
+ );
220
+ const loc = {
221
+ start: node.loc.start,
222
+ end: sourceCode.getTokenBefore(parenToken).loc.end,
223
+ };
214
224
 
215
225
  if (
216
226
  superClass
@@ -218,19 +228,19 @@ module.exports = {
218
228
  : body.length === 0
219
229
  ) {
220
230
  context.report({
221
- node,
231
+ loc,
222
232
  messageId: "noUselessConstructor",
223
233
  suggest: [
224
234
  {
225
235
  messageId: "removeConstructor",
226
236
  *fix(fixer) {
227
237
  const nextToken =
228
- context.sourceCode.getTokenAfter(node);
238
+ sourceCode.getTokenAfter(node);
229
239
  const addSemiColon =
230
240
  nextToken.type === "Punctuator" &&
231
241
  nextToken.value === "[" &&
232
242
  astUtils.needsPrecedingSemicolon(
233
- context.sourceCode,
243
+ sourceCode,
234
244
  node,
235
245
  );
236
246
 
@@ -141,7 +141,7 @@ module.exports = {
141
141
  leftToken = sourceCode.getTokenBefore(rightToken, 1);
142
142
  }
143
143
 
144
- if (sourceCode.isSpaceBetweenTokens(leftToken, rightToken)) {
144
+ if (sourceCode.isSpaceBetween(leftToken, rightToken)) {
145
145
  reportError(node, leftToken, rightToken);
146
146
  }
147
147
  },
@@ -204,10 +204,7 @@ module.exports = {
204
204
  */
205
205
  function validateBraceSpacing(node, first, second, penultimate, last) {
206
206
  if (astUtils.isTokenOnSameLine(first, second)) {
207
- const firstSpaced = sourceCode.isSpaceBetweenTokens(
208
- first,
209
- second,
210
- );
207
+ const firstSpaced = sourceCode.isSpaceBetween(first, second);
211
208
 
212
209
  if (options.spaced && !firstSpaced) {
213
210
  reportRequiredBeginningSpace(node, first);
@@ -236,10 +233,7 @@ module.exports = {
236
233
  ? !options.spaced
237
234
  : options.spaced;
238
235
 
239
- const lastSpaced = sourceCode.isSpaceBetweenTokens(
240
- penultimate,
241
- last,
242
- );
236
+ const lastSpaced = sourceCode.isSpaceBetween(penultimate, last);
243
237
 
244
238
  if (closingCurlyBraceMustBeSpaced && !lastSpaced) {
245
239
  reportRequiredEndingSpace(node, last);
@@ -5,6 +5,12 @@
5
5
 
6
6
  "use strict";
7
7
 
8
+ //------------------------------------------------------------------------------
9
+ // Requirements
10
+ //------------------------------------------------------------------------------
11
+
12
+ const astUtils = require("./utils/ast-utils");
13
+
8
14
  //------------------------------------------------------------------------------
9
15
  // Rule Definition
10
16
  //------------------------------------------------------------------------------
@@ -29,6 +35,7 @@ module.exports = {
29
35
 
30
36
  create(context) {
31
37
  const stack = [];
38
+ const sourceCode = context.sourceCode;
32
39
 
33
40
  /**
34
41
  * If the node is a generator function, start counting `yield` keywords.
@@ -55,7 +62,10 @@ module.exports = {
55
62
  const countYield = stack.pop();
56
63
 
57
64
  if (countYield === 0 && node.body.body.length > 0) {
58
- context.report({ node, messageId: "missingYield" });
65
+ context.report({
66
+ loc: astUtils.getFunctionHeadLoc(node, sourceCode),
67
+ messageId: "missingYield",
68
+ });
59
69
  }
60
70
  }
61
71
 
@@ -74,10 +74,7 @@ module.exports = {
74
74
  function checkWhiteSpace(node) {
75
75
  const operator = sourceCode.getFirstToken(node),
76
76
  nextToken = sourceCode.getTokenAfter(operator),
77
- hasWhitespace = sourceCode.isSpaceBetweenTokens(
78
- operator,
79
- nextToken,
80
- );
77
+ hasWhitespace = sourceCode.isSpaceBetween(operator, nextToken);
81
78
  let type;
82
79
 
83
80
  switch (node.type) {
@@ -95,7 +95,7 @@ module.exports = {
95
95
  return (
96
96
  tokenBefore &&
97
97
  astUtils.isTokenOnSameLine(tokenBefore, token) &&
98
- sourceCode.isSpaceBetweenTokens(tokenBefore, token)
98
+ sourceCode.isSpaceBetween(tokenBefore, token)
99
99
  );
100
100
  }
101
101
 
@@ -110,7 +110,7 @@ module.exports = {
110
110
  return (
111
111
  tokenAfter &&
112
112
  astUtils.isTokenOnSameLine(token, tokenAfter) &&
113
- sourceCode.isSpaceBetweenTokens(token, tokenAfter)
113
+ sourceCode.isSpaceBetween(token, tokenAfter)
114
114
  );
115
115
  }
116
116
 
@@ -164,7 +164,7 @@ module.exports = {
164
164
  !isConflicted(precedingToken, node) &&
165
165
  astUtils.isTokenOnSameLine(precedingToken, node)
166
166
  ) {
167
- const hasSpace = sourceCode.isSpaceBetweenTokens(
167
+ const hasSpace = sourceCode.isSpaceBetween(
168
168
  precedingToken,
169
169
  node,
170
170
  );
@@ -155,10 +155,7 @@ module.exports = {
155
155
  astUtils.isOpeningParenToken,
156
156
  );
157
157
  const leftToken = sourceCode.getTokenBefore(rightToken);
158
- const hasSpacing = sourceCode.isSpaceBetweenTokens(
159
- leftToken,
160
- rightToken,
161
- );
158
+ const hasSpacing = sourceCode.isSpaceBetween(leftToken, rightToken);
162
159
 
163
160
  if (hasSpacing && functionConfig === "never") {
164
161
  context.report({
@@ -153,7 +153,7 @@ module.exports = {
153
153
  */
154
154
  function openerMissingSpace(openingParenToken, tokenAfterOpeningParen) {
155
155
  if (
156
- sourceCode.isSpaceBetweenTokens(
156
+ sourceCode.isSpaceBetween(
157
157
  openingParenToken,
158
158
  tokenAfterOpeningParen,
159
159
  )
@@ -195,7 +195,7 @@ module.exports = {
195
195
  }
196
196
 
197
197
  if (
198
- !sourceCode.isSpaceBetweenTokens(
198
+ !sourceCode.isSpaceBetween(
199
199
  openingParenToken,
200
200
  tokenAfterOpeningParen,
201
201
  )
@@ -220,7 +220,7 @@ module.exports = {
220
220
  closingParenToken,
221
221
  ) {
222
222
  if (
223
- sourceCode.isSpaceBetweenTokens(
223
+ sourceCode.isSpaceBetween(
224
224
  tokenBeforeClosingParen,
225
225
  closingParenToken,
226
226
  )
@@ -261,7 +261,7 @@ module.exports = {
261
261
  }
262
262
 
263
263
  if (
264
- !sourceCode.isSpaceBetweenTokens(
264
+ !sourceCode.isSpaceBetween(
265
265
  tokenBeforeClosingParen,
266
266
  closingParenToken,
267
267
  )
@@ -87,8 +87,8 @@ module.exports = {
87
87
  const next = sourceCode.getTokenAfter(operator);
88
88
 
89
89
  if (
90
- !sourceCode.isSpaceBetweenTokens(prev, operator) ||
91
- !sourceCode.isSpaceBetweenTokens(operator, next)
90
+ !sourceCode.isSpaceBetween(prev, operator) ||
91
+ !sourceCode.isSpaceBetween(operator, next)
92
92
  ) {
93
93
  return operator;
94
94
  }
@@ -238,11 +238,8 @@ module.exports = {
238
238
  const rightToken = sourceCode.getTokenAfter(operatorToken);
239
239
 
240
240
  if (
241
- !sourceCode.isSpaceBetweenTokens(
242
- leftToken,
243
- operatorToken,
244
- ) ||
245
- !sourceCode.isSpaceBetweenTokens(operatorToken, rightToken)
241
+ !sourceCode.isSpaceBetween(leftToken, operatorToken) ||
242
+ !sourceCode.isSpaceBetween(operatorToken, rightToken)
246
243
  ) {
247
244
  report(node, operatorToken);
248
245
  }
@@ -84,7 +84,7 @@ module.exports = {
84
84
  return (
85
85
  astUtils.isClosingBraceToken(right) ||
86
86
  !astUtils.isTokenOnSameLine(left, right) ||
87
- sourceCode.isSpaceBetweenTokens(left, right) === expected
87
+ sourceCode.isSpaceBetween(left, right) === expected
88
88
  );
89
89
  }
90
90
 
@@ -66,7 +66,7 @@ module.exports = {
66
66
  function checkSpacing(node) {
67
67
  const tagToken = sourceCode.getTokenBefore(node.quasi);
68
68
  const literalToken = sourceCode.getFirstToken(node.quasi);
69
- const hasWhitespace = sourceCode.isSpaceBetweenTokens(
69
+ const hasWhitespace = sourceCode.isSpaceBetween(
70
70
  tagToken,
71
71
  literalToken,
72
72
  );
@@ -544,28 +544,6 @@ function negate(f) {
544
544
  return token => !f(token);
545
545
  }
546
546
 
547
- /**
548
- * Checks whether or not a node has a `@this` tag in its comments.
549
- * @param {ASTNode} node A node to check.
550
- * @param {SourceCode} sourceCode A SourceCode instance to get comments.
551
- * @returns {boolean} Whether or not the node has a `@this` tag in its comments.
552
- */
553
- function hasJSDocThisTag(node, sourceCode) {
554
- const jsdocComment = sourceCode.getJSDocComment(node);
555
-
556
- if (jsdocComment && thisTagPattern.test(jsdocComment.value)) {
557
- return true;
558
- }
559
-
560
- // Checks `@this` in its leading comments for callbacks,
561
- // because callbacks don't have its JSDoc comment.
562
- // e.g.
563
- // sinon.test(/* @this sinon.Sandbox */function() { this.spy(); });
564
- return sourceCode
565
- .getCommentsBefore(node)
566
- .some(comment => thisTagPattern.test(comment.value));
567
- }
568
-
569
547
  /**
570
548
  * Determines if a node is surrounded by parentheses.
571
549
  * @param {SourceCode} sourceCode The ESLint source code object
@@ -725,6 +703,120 @@ function isKeywordToken(token) {
725
703
  return token.type === "Keyword";
726
704
  }
727
705
 
706
+ /**
707
+ * Check to see if its a ES6 export declaration.
708
+ * @param {ASTNode} astNode An AST node.
709
+ * @returns {boolean} whether the given node represents an export declaration.
710
+ * @private
711
+ */
712
+ function looksLikeExport(astNode) {
713
+ return (
714
+ astNode.type === "ExportDefaultDeclaration" ||
715
+ astNode.type === "ExportNamedDeclaration" ||
716
+ astNode.type === "ExportAllDeclaration" ||
717
+ astNode.type === "ExportSpecifier"
718
+ );
719
+ }
720
+
721
+ /**
722
+ * Retrieves the JSDoc comment for a given node.
723
+ * @param {ASTNode} node The AST node to get the comment for.
724
+ * @param {SourceCode} sourceCode A SourceCode instance to get comments.
725
+ * @returns {Token|null} The Block comment token containing the JSDoc comment for the given node or null if not found.
726
+ * @private
727
+ */
728
+ function getJSDocComment(node, sourceCode) {
729
+ /**
730
+ * Checks for the presence of a JSDoc comment for the given node and returns it.
731
+ * @param {ASTNode} astNode The AST node to get the comment for.
732
+ * @returns {Token|null} The Block comment token containing the JSDoc comment for the given node or null if not found.
733
+ * @private
734
+ */
735
+ function findJSDocComment(astNode) {
736
+ const tokenBefore = sourceCode.getTokenBefore(astNode, {
737
+ includeComments: true,
738
+ });
739
+
740
+ if (
741
+ tokenBefore &&
742
+ isCommentToken(tokenBefore) &&
743
+ tokenBefore.type === "Block" &&
744
+ tokenBefore.value.charAt(0) === "*" &&
745
+ astNode.loc.start.line - tokenBefore.loc.end.line <= 1
746
+ ) {
747
+ return tokenBefore;
748
+ }
749
+
750
+ return null;
751
+ }
752
+ let parent = node.parent;
753
+
754
+ switch (node.type) {
755
+ case "ClassDeclaration":
756
+ case "FunctionDeclaration":
757
+ return findJSDocComment(looksLikeExport(parent) ? parent : node);
758
+
759
+ case "ClassExpression":
760
+ return findJSDocComment(parent.parent);
761
+
762
+ case "ArrowFunctionExpression":
763
+ case "FunctionExpression":
764
+ if (
765
+ parent.type !== "CallExpression" &&
766
+ parent.type !== "NewExpression"
767
+ ) {
768
+ while (
769
+ !sourceCode.getCommentsBefore(parent).length &&
770
+ !/Function/u.test(parent.type) &&
771
+ parent.type !== "MethodDefinition" &&
772
+ parent.type !== "Property"
773
+ ) {
774
+ parent = parent.parent;
775
+
776
+ if (!parent) {
777
+ break;
778
+ }
779
+ }
780
+
781
+ if (
782
+ parent &&
783
+ parent.type !== "FunctionDeclaration" &&
784
+ parent.type !== "Program"
785
+ ) {
786
+ return findJSDocComment(parent);
787
+ }
788
+ }
789
+
790
+ return findJSDocComment(node);
791
+
792
+ // falls through
793
+ default:
794
+ return null;
795
+ }
796
+ }
797
+
798
+ /**
799
+ * Checks whether or not a node has a `@this` tag in its comments.
800
+ * @param {ASTNode} node A node to check.
801
+ * @param {SourceCode} sourceCode A SourceCode instance to get comments.
802
+ * @returns {boolean} Whether or not the node has a `@this` tag in its comments.
803
+ */
804
+ function hasJSDocThisTag(node, sourceCode) {
805
+ const jsdocComment = getJSDocComment(node, sourceCode);
806
+
807
+ if (jsdocComment && thisTagPattern.test(jsdocComment.value)) {
808
+ return true;
809
+ }
810
+
811
+ // Checks `@this` in its leading comments for callbacks,
812
+ // because callbacks don't have its JSDoc comment.
813
+ // e.g.
814
+ // sinon.test(/* @this sinon.Sandbox */function() { this.spy(); });
815
+ return sourceCode
816
+ .getCommentsBefore(node)
817
+ .some(comment => thisTagPattern.test(comment.value));
818
+ }
819
+
728
820
  /**
729
821
  * Gets the `(` token of the given function node.
730
822
  * @param {ASTNode} node The function node to get.
@@ -96,8 +96,7 @@ module.exports = {
96
96
  */
97
97
  function checkSpacing(side, leftToken, rightToken) {
98
98
  if (
99
- sourceCode.isSpaceBetweenTokens(leftToken, rightToken) !==
100
- mode[side]
99
+ sourceCode.isSpaceBetween(leftToken, rightToken) !== mode[side]
101
100
  ) {
102
101
  const after = leftToken.value === "*";
103
102
  const spaceRequired = mode[side];
@@ -281,17 +281,8 @@ export class SourceCode
281
281
 
282
282
  getDeclaredVariables(node: ESTree.Node): Scope.Variable[];
283
283
 
284
- /** @deprecated */
285
- getJSDocComment(node: ESTree.Node): ESTree.Comment | null;
286
-
287
284
  getNodeByRangeIndex(index: number): ESTree.Node | null;
288
285
 
289
- /** @deprecated Use `isSpaceBetween()` instead. */
290
- isSpaceBetweenTokens(
291
- first: ESTree.Node | AST.Token,
292
- second: ESTree.Node | AST.Token,
293
- ): boolean;
294
-
295
286
  getLocFromIndex(index: number): ESTree.Position;
296
287
 
297
288
  getIndexFromLoc(location: ESTree.Position): number;
@@ -324,18 +315,6 @@ export class SourceCode
324
315
 
325
316
  getTokensAfter: SourceCode.UnaryCursorWithCountOptions;
326
317
 
327
- /** @deprecated Use `getTokenBefore()` instead. */
328
- getTokenOrCommentBefore(
329
- node: ESTree.Node | AST.Token | ESTree.Comment,
330
- skip?: number | undefined,
331
- ): AST.Token | ESTree.Comment | null;
332
-
333
- /** @deprecated Use `getTokenAfter()` instead. */
334
- getTokenOrCommentAfter(
335
- node: ESTree.Node | AST.Token | ESTree.Comment,
336
- skip?: number | undefined,
337
- ): AST.Token | ESTree.Comment | null;
338
-
339
318
  getFirstTokenBetween: SourceCode.BinaryCursorWithSkipOptions;
340
319
 
341
320
  getFirstTokensBetween: SourceCode.BinaryCursorWithCountOptions;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint",
3
- "version": "10.0.0-alpha.0",
3
+ "version": "10.0.0-alpha.1",
4
4
  "author": "Nicholas C. Zakas <nicholas+npm@nczconsulting.com>",
5
5
  "description": "An AST-based pattern checker for JavaScript.",
6
6
  "type": "commonjs",
@@ -108,7 +108,7 @@
108
108
  "dependencies": {
109
109
  "@eslint-community/eslint-utils": "^4.8.0",
110
110
  "@eslint-community/regexpp": "^4.12.1",
111
- "@eslint/config-array": "^0.22.0",
111
+ "@eslint/config-array": "^0.23.0",
112
112
  "@eslint/config-helpers": "^0.5.0",
113
113
  "@eslint/core": "^1.0.0",
114
114
  "@eslint/plugin-kit": "^0.5.0",
@@ -134,7 +134,7 @@
134
134
  "imurmurhash": "^0.1.4",
135
135
  "is-glob": "^4.0.0",
136
136
  "json-stable-stringify-without-jsonify": "^1.0.1",
137
- "minimatch": "^3.1.2",
137
+ "minimatch": "^10.1.1",
138
138
  "natural-compare": "^1.4.0",
139
139
  "optionator": "^0.9.3"
140
140
  },