@sarj/eslint-plugin 15.8.0 → 15.8.2

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/dist/index.d.cts CHANGED
@@ -220,7 +220,7 @@ declare const rules: {
220
220
  libraries: readonly RestrictedLibrary[];
221
221
  }], "restrictedLibraryLoad">;
222
222
  readonly "no-repeated-string-literal": DocumentedRule<readonly [], "noRepeatedStringLiteral">;
223
- readonly "no-restated-comment": DocumentedRule<readonly [], "restatesLineBelow">;
223
+ readonly "no-restated-comment": DocumentedRule<readonly [], "deleteComment" | "restatesLineBelow">;
224
224
  readonly "no-restated-jsdoc": DocumentedRule<readonly [], "restatesSignature" | "deleteBlock">;
225
225
  readonly "no-secret-in-log": DocumentedRule<readonly [LoggingOptions?], "noSecretInLog" | "noRawBodyInLog">;
226
226
  readonly "no-select-star": DocumentedRule<readonly [], "noSelectStar">;
@@ -231,7 +231,7 @@ declare const rules: {
231
231
  readonly "no-string-concat-in-loop": DocumentedRule<readonly [], "noStringConcatInLoop" | "noStringReduce">;
232
232
  readonly "no-tautological-expect": DocumentedRule<readonly [], "tautologicalComparison" | "tautologicalMatcher">;
233
233
  readonly "no-typed-doc-sections": DocumentedRule<readonly [], "typedSection">;
234
- readonly "no-trailing-value-narration": DocumentedRule<readonly [], "deleteNarration" | "narratesValue">;
234
+ readonly "no-trailing-value-narration": DocumentedRule<readonly [], "deleteNarration" | "narratesValue" | "removeNarration">;
235
235
  readonly "no-declaration-comment-wall": DocumentedRule<readonly [Partial<WallOptions>?], "commentWall">;
236
236
  readonly "no-union-in-comment": DocumentedRule<readonly [], "unionInComment">;
237
237
  readonly "no-type-member-comment-wall": DocumentedRule<readonly [Partial<WallOptions>?], "commentWall">;
@@ -286,7 +286,7 @@ declare const rules: {
286
286
  /** Rules registered for application-profile configs but intentionally absent from general presets. */
287
287
  declare const applicationOnlyRules: readonly ["no-restricted-library-load", "prefer-native-random-uuid", "prefer-shadcn-primitives"];
288
288
  /** Calibrated rules that intentionally remain warnings until consumer-corpus precision is proven. */
289
- declare const advisoryRules: readonly ["no-bare-return-from-test-catch", "no-vague-suppression-description", "iac-source-coupled-test", "repeated-static-call-cases", "source-coupled-test"];
289
+ declare const advisoryRules: readonly ["no-bare-return-from-test-catch", "iac-source-coupled-test", "repeated-static-call-cases", "source-coupled-test"];
290
290
  declare const recommendedRules: {
291
291
  readonly "@sarj/iac-source-coupled-test": "warn";
292
292
  readonly "@sarj/duplicate-test-body": "error";
@@ -306,7 +306,7 @@ declare const recommendedRules: {
306
306
  readonly "@sarj/no-log-only-catch": "error";
307
307
  readonly "@sarj/no-bare-return-from-test-catch": "warn";
308
308
  readonly "@sarj/no-long-comment": "error";
309
- readonly "@sarj/no-vague-suppression-description": "warn";
309
+ readonly "@sarj/no-vague-suppression-description": "error";
310
310
  readonly "@sarj/no-generic-single-export-module": "error";
311
311
  readonly "@sarj/no-offset-pagination": "error";
312
312
  readonly "@sarj/no-positional-tuple-return": "error";
@@ -375,7 +375,7 @@ declare const strictRules: {
375
375
  readonly "@sarj/no-log-only-catch": "error";
376
376
  readonly "@sarj/no-bare-return-from-test-catch": "warn";
377
377
  readonly "@sarj/no-long-comment": "error";
378
- readonly "@sarj/no-vague-suppression-description": "warn";
378
+ readonly "@sarj/no-vague-suppression-description": "error";
379
379
  readonly "@sarj/no-generic-single-export-module": "error";
380
380
  readonly "@sarj/no-offset-pagination": "error";
381
381
  readonly "@sarj/no-positional-tuple-return": "error";
@@ -435,7 +435,7 @@ type FlatPreset = {
435
435
  declare const plugin: {
436
436
  readonly meta: {
437
437
  readonly name: "@sarj/eslint-plugin";
438
- readonly version: "15.8.0";
438
+ readonly version: "15.8.2";
439
439
  };
440
440
  readonly rules: {
441
441
  readonly "iac-source-coupled-test": DocumentedRule<readonly [], "rawSourceOracle">;
@@ -470,7 +470,7 @@ declare const plugin: {
470
470
  libraries: readonly RestrictedLibrary[];
471
471
  }], "restrictedLibraryLoad">;
472
472
  readonly "no-repeated-string-literal": DocumentedRule<readonly [], "noRepeatedStringLiteral">;
473
- readonly "no-restated-comment": DocumentedRule<readonly [], "restatesLineBelow">;
473
+ readonly "no-restated-comment": DocumentedRule<readonly [], "deleteComment" | "restatesLineBelow">;
474
474
  readonly "no-restated-jsdoc": DocumentedRule<readonly [], "restatesSignature" | "deleteBlock">;
475
475
  readonly "no-secret-in-log": DocumentedRule<readonly [LoggingOptions?], "noSecretInLog" | "noRawBodyInLog">;
476
476
  readonly "no-select-star": DocumentedRule<readonly [], "noSelectStar">;
@@ -481,7 +481,7 @@ declare const plugin: {
481
481
  readonly "no-string-concat-in-loop": DocumentedRule<readonly [], "noStringConcatInLoop" | "noStringReduce">;
482
482
  readonly "no-tautological-expect": DocumentedRule<readonly [], "tautologicalComparison" | "tautologicalMatcher">;
483
483
  readonly "no-typed-doc-sections": DocumentedRule<readonly [], "typedSection">;
484
- readonly "no-trailing-value-narration": DocumentedRule<readonly [], "deleteNarration" | "narratesValue">;
484
+ readonly "no-trailing-value-narration": DocumentedRule<readonly [], "deleteNarration" | "narratesValue" | "removeNarration">;
485
485
  readonly "no-declaration-comment-wall": DocumentedRule<readonly [Partial<WallOptions>?], "commentWall">;
486
486
  readonly "no-union-in-comment": DocumentedRule<readonly [], "unionInComment">;
487
487
  readonly "no-type-member-comment-wall": DocumentedRule<readonly [Partial<WallOptions>?], "commentWall">;
package/dist/index.d.ts CHANGED
@@ -220,7 +220,7 @@ declare const rules: {
220
220
  libraries: readonly RestrictedLibrary[];
221
221
  }], "restrictedLibraryLoad">;
222
222
  readonly "no-repeated-string-literal": DocumentedRule<readonly [], "noRepeatedStringLiteral">;
223
- readonly "no-restated-comment": DocumentedRule<readonly [], "restatesLineBelow">;
223
+ readonly "no-restated-comment": DocumentedRule<readonly [], "deleteComment" | "restatesLineBelow">;
224
224
  readonly "no-restated-jsdoc": DocumentedRule<readonly [], "restatesSignature" | "deleteBlock">;
225
225
  readonly "no-secret-in-log": DocumentedRule<readonly [LoggingOptions?], "noSecretInLog" | "noRawBodyInLog">;
226
226
  readonly "no-select-star": DocumentedRule<readonly [], "noSelectStar">;
@@ -231,7 +231,7 @@ declare const rules: {
231
231
  readonly "no-string-concat-in-loop": DocumentedRule<readonly [], "noStringConcatInLoop" | "noStringReduce">;
232
232
  readonly "no-tautological-expect": DocumentedRule<readonly [], "tautologicalComparison" | "tautologicalMatcher">;
233
233
  readonly "no-typed-doc-sections": DocumentedRule<readonly [], "typedSection">;
234
- readonly "no-trailing-value-narration": DocumentedRule<readonly [], "deleteNarration" | "narratesValue">;
234
+ readonly "no-trailing-value-narration": DocumentedRule<readonly [], "deleteNarration" | "narratesValue" | "removeNarration">;
235
235
  readonly "no-declaration-comment-wall": DocumentedRule<readonly [Partial<WallOptions>?], "commentWall">;
236
236
  readonly "no-union-in-comment": DocumentedRule<readonly [], "unionInComment">;
237
237
  readonly "no-type-member-comment-wall": DocumentedRule<readonly [Partial<WallOptions>?], "commentWall">;
@@ -286,7 +286,7 @@ declare const rules: {
286
286
  /** Rules registered for application-profile configs but intentionally absent from general presets. */
287
287
  declare const applicationOnlyRules: readonly ["no-restricted-library-load", "prefer-native-random-uuid", "prefer-shadcn-primitives"];
288
288
  /** Calibrated rules that intentionally remain warnings until consumer-corpus precision is proven. */
289
- declare const advisoryRules: readonly ["no-bare-return-from-test-catch", "no-vague-suppression-description", "iac-source-coupled-test", "repeated-static-call-cases", "source-coupled-test"];
289
+ declare const advisoryRules: readonly ["no-bare-return-from-test-catch", "iac-source-coupled-test", "repeated-static-call-cases", "source-coupled-test"];
290
290
  declare const recommendedRules: {
291
291
  readonly "@sarj/iac-source-coupled-test": "warn";
292
292
  readonly "@sarj/duplicate-test-body": "error";
@@ -306,7 +306,7 @@ declare const recommendedRules: {
306
306
  readonly "@sarj/no-log-only-catch": "error";
307
307
  readonly "@sarj/no-bare-return-from-test-catch": "warn";
308
308
  readonly "@sarj/no-long-comment": "error";
309
- readonly "@sarj/no-vague-suppression-description": "warn";
309
+ readonly "@sarj/no-vague-suppression-description": "error";
310
310
  readonly "@sarj/no-generic-single-export-module": "error";
311
311
  readonly "@sarj/no-offset-pagination": "error";
312
312
  readonly "@sarj/no-positional-tuple-return": "error";
@@ -375,7 +375,7 @@ declare const strictRules: {
375
375
  readonly "@sarj/no-log-only-catch": "error";
376
376
  readonly "@sarj/no-bare-return-from-test-catch": "warn";
377
377
  readonly "@sarj/no-long-comment": "error";
378
- readonly "@sarj/no-vague-suppression-description": "warn";
378
+ readonly "@sarj/no-vague-suppression-description": "error";
379
379
  readonly "@sarj/no-generic-single-export-module": "error";
380
380
  readonly "@sarj/no-offset-pagination": "error";
381
381
  readonly "@sarj/no-positional-tuple-return": "error";
@@ -435,7 +435,7 @@ type FlatPreset = {
435
435
  declare const plugin: {
436
436
  readonly meta: {
437
437
  readonly name: "@sarj/eslint-plugin";
438
- readonly version: "15.8.0";
438
+ readonly version: "15.8.2";
439
439
  };
440
440
  readonly rules: {
441
441
  readonly "iac-source-coupled-test": DocumentedRule<readonly [], "rawSourceOracle">;
@@ -470,7 +470,7 @@ declare const plugin: {
470
470
  libraries: readonly RestrictedLibrary[];
471
471
  }], "restrictedLibraryLoad">;
472
472
  readonly "no-repeated-string-literal": DocumentedRule<readonly [], "noRepeatedStringLiteral">;
473
- readonly "no-restated-comment": DocumentedRule<readonly [], "restatesLineBelow">;
473
+ readonly "no-restated-comment": DocumentedRule<readonly [], "deleteComment" | "restatesLineBelow">;
474
474
  readonly "no-restated-jsdoc": DocumentedRule<readonly [], "restatesSignature" | "deleteBlock">;
475
475
  readonly "no-secret-in-log": DocumentedRule<readonly [LoggingOptions?], "noSecretInLog" | "noRawBodyInLog">;
476
476
  readonly "no-select-star": DocumentedRule<readonly [], "noSelectStar">;
@@ -481,7 +481,7 @@ declare const plugin: {
481
481
  readonly "no-string-concat-in-loop": DocumentedRule<readonly [], "noStringConcatInLoop" | "noStringReduce">;
482
482
  readonly "no-tautological-expect": DocumentedRule<readonly [], "tautologicalComparison" | "tautologicalMatcher">;
483
483
  readonly "no-typed-doc-sections": DocumentedRule<readonly [], "typedSection">;
484
- readonly "no-trailing-value-narration": DocumentedRule<readonly [], "deleteNarration" | "narratesValue">;
484
+ readonly "no-trailing-value-narration": DocumentedRule<readonly [], "deleteNarration" | "narratesValue" | "removeNarration">;
485
485
  readonly "no-declaration-comment-wall": DocumentedRule<readonly [Partial<WallOptions>?], "commentWall">;
486
486
  readonly "no-union-in-comment": DocumentedRule<readonly [], "unionInComment">;
487
487
  readonly "no-type-member-comment-wall": DocumentedRule<readonly [Partial<WallOptions>?], "commentWall">;
package/dist/index.js CHANGED
@@ -5586,6 +5586,38 @@ var no_repeated_string_literal_default = createRule({
5586
5586
 
5587
5587
  // src/rules/no-restated-comment.ts
5588
5588
  import { AST_NODE_TYPES as AST_NODE_TYPES22 } from "@typescript-eslint/utils";
5589
+
5590
+ // src/rules/_comment-edits.ts
5591
+ import "@typescript-eslint/utils";
5592
+ function physicalLineEnd(text, offset) {
5593
+ const newline = text.indexOf("\n", offset);
5594
+ return newline < 0 ? text.length : newline;
5595
+ }
5596
+ function contentLineEnd(text, offset) {
5597
+ const end = physicalLineEnd(text, offset);
5598
+ return end > offset && text[end - 1] === "\r" ? end - 1 : end;
5599
+ }
5600
+ function wholeLineRemovalRange(text, comment) {
5601
+ if (comment.loc.start.line !== comment.loc.end.line) return null;
5602
+ const lineStart = text.lastIndexOf("\n", Math.max(0, comment.range[0] - 1)) + 1;
5603
+ if (!/^[\t ]*$/u.test(text.slice(lineStart, comment.range[0]))) return null;
5604
+ const contentEnd = contentLineEnd(text, comment.range[1]);
5605
+ if (!/^[\t ]*$/u.test(text.slice(comment.range[1], contentEnd))) return null;
5606
+ const physicalEnd = physicalLineEnd(text, comment.range[1]);
5607
+ return { range: [lineStart, physicalEnd < text.length ? physicalEnd + 1 : physicalEnd] };
5608
+ }
5609
+ function trailingCommentRemovalRange(text, comment) {
5610
+ if (comment.loc.start.line !== comment.loc.end.line) return null;
5611
+ const contentEnd = contentLineEnd(text, comment.range[1]);
5612
+ if (!/^[\t ]*$/u.test(text.slice(comment.range[1], contentEnd))) return null;
5613
+ let start = comment.range[0];
5614
+ while (start > 0 && (text[start - 1] === " " || text[start - 1] === " ")) {
5615
+ start -= 1;
5616
+ }
5617
+ return { range: [start, contentEnd] };
5618
+ }
5619
+
5620
+ // src/rules/no-restated-comment.ts
5589
5621
  var MAX_WORDS = 8;
5590
5622
  var MIN_CONTENT_TOKENS = 2;
5591
5623
  var DIRECTIVE_RE3 = /^(eslint\b|eslint-|sarj-noqa\b|@ts-|prettier-ignore|prettier\b|biome-|c8\b|v8\b|istanbul\b|@type\b|@vite|webpack|<reference|<amd|global\b|noinspection|todo\b|fixme\b|hack\b|xxx\b)/i;
@@ -5605,6 +5637,7 @@ var noRestatedCommentDocumentation = {
5605
5637
  rationale: "A comment that only repeats code adds no context and can become stale independently.",
5606
5638
  remediation: "Delete the comment or replace it with the reason, constraint, or consequence absent from the code.",
5607
5639
  category: "maintainability",
5640
+ autofix: "suggestion",
5608
5641
  limitations: ["Directives, protected references, questions, multi-line prose, comments with novel content, and generated files are excluded."],
5609
5642
  examples: [
5610
5643
  { id: "reason-comment", title: "Keep the reason the code cannot express", outcome: "no-match", files: [{ path: "src/cache.ts", source: "// Serialize because the cache key is stable across deploys.\nconst key = serialize(input);" }], focusPath: "src/cache.ts", expectedCount: 0, public: true },
@@ -5628,11 +5661,13 @@ var no_restated_comment_default = createRule({
5628
5661
  documentation: noRestatedCommentDocumentation,
5629
5662
  meta: {
5630
5663
  type: "suggestion",
5664
+ hasSuggestions: true,
5631
5665
  docs: {
5632
5666
  description: "Flag a single-line comment whose every word already appears on the statement below it."
5633
5667
  },
5634
5668
  schema: [],
5635
5669
  messages: {
5670
+ deleteComment: "Delete the redundant comment.",
5636
5671
  restatesLineBelow: "Comment restates the statement below it \u2014 delete it, or replace it with the *why*; the code already carries the *what*."
5637
5672
  }
5638
5673
  },
@@ -5701,7 +5736,17 @@ var no_restated_comment_default = createRule({
5701
5736
  if (!ACTION_STMT_RE.test(line)) continue;
5702
5737
  if (labelsASiblingRun(comment)) continue;
5703
5738
  if (restates(tokens, codeTokens(line))) {
5704
- context.report({ node: comment, messageId: "restatesLineBelow" });
5739
+ const removal = wholeLineRemovalRange(sourceCode.text, comment);
5740
+ context.report({
5741
+ node: comment,
5742
+ messageId: "restatesLineBelow",
5743
+ suggest: removal === null ? null : [
5744
+ {
5745
+ messageId: "deleteComment",
5746
+ fix: (fixer) => fixer.removeRange(removal.range)
5747
+ }
5748
+ ]
5749
+ });
5705
5750
  }
5706
5751
  }
5707
5752
  }
@@ -7729,6 +7774,7 @@ var noTrailingValueNarrationDocumentation = {
7729
7774
  rationale: "A repeated value can disagree with the expression after either the code or comment changes.",
7730
7775
  remediation: "Put the unit in the identifier and keep comments only when they explain a constraint or non-obvious conversion.",
7731
7776
  category: "maintainability",
7777
+ autofix: "suggestion",
7732
7778
  aliases: ["trailing-value-narration"],
7733
7779
  limitations: ["Only trailing comments with numeric values and recognized unit words are inspected."],
7734
7780
  examples: [
@@ -7845,13 +7891,15 @@ var no_trailing_value_narration_default = createRule({
7845
7891
  documentation: noTrailingValueNarrationDocumentation,
7846
7892
  meta: {
7847
7893
  type: "suggestion",
7894
+ hasSuggestions: true,
7848
7895
  docs: {
7849
7896
  description: "Flag a trailing comment that repeats the line's numeric value only to name its unit."
7850
7897
  },
7851
7898
  schema: [],
7852
7899
  messages: {
7853
7900
  deleteNarration: "Trailing comment restates the literal and the identifier already names its unit \u2014 delete the comment so it cannot drift.",
7854
- narratesValue: "Trailing comment restates the literal on this line \u2014 put the unit in the name (STALE_TIME_MS) so it cannot drift."
7901
+ narratesValue: "Trailing comment restates the literal on this line \u2014 put the unit in the name (STALE_TIME_MS) so it cannot drift.",
7902
+ removeNarration: "Delete the redundant trailing narration."
7855
7903
  }
7856
7904
  },
7857
7905
  defaultOptions: [],
@@ -7883,9 +7931,17 @@ var no_trailing_value_narration_default = createRule({
7883
7931
  const code = line.slice(0, comment.loc.start.column);
7884
7932
  const body2 = comment.value.replace(/^\*+/, "").replace(/\*+$/, "").trim();
7885
7933
  if (narratesValue(body2, code)) {
7934
+ const canDelete = nameAlreadyCarriesUnit(code);
7935
+ const removal = canDelete ? trailingCommentRemovalRange(sourceCode.text, comment) : null;
7886
7936
  context.report({
7887
7937
  node: comment,
7888
- messageId: nameAlreadyCarriesUnit(code) ? "deleteNarration" : "narratesValue"
7938
+ messageId: canDelete ? "deleteNarration" : "narratesValue",
7939
+ suggest: removal === null ? null : [
7940
+ {
7941
+ messageId: "removeNarration",
7942
+ fix: (fixer) => fixer.removeRange(removal.range)
7943
+ }
7944
+ ]
7889
7945
  });
7890
7946
  }
7891
7947
  }
@@ -15768,7 +15824,7 @@ var rules = {
15768
15824
  };
15769
15825
  var meta = {
15770
15826
  name: "@sarj/eslint-plugin",
15771
- version: "15.8.0"
15827
+ version: "15.8.2"
15772
15828
  };
15773
15829
  var applicationOnlyRules = [
15774
15830
  "no-restricted-library-load",
@@ -15777,7 +15833,6 @@ var applicationOnlyRules = [
15777
15833
  ];
15778
15834
  var advisoryRules = [
15779
15835
  "no-bare-return-from-test-catch",
15780
- "no-vague-suppression-description",
15781
15836
  "iac-source-coupled-test",
15782
15837
  "repeated-static-call-cases",
15783
15838
  "source-coupled-test"
@@ -15799,7 +15854,7 @@ var recommendedRules = {
15799
15854
  "@sarj/no-log-only-catch": "error",
15800
15855
  "@sarj/no-bare-return-from-test-catch": "warn",
15801
15856
  "@sarj/no-long-comment": "error",
15802
- "@sarj/no-vague-suppression-description": "warn",
15857
+ "@sarj/no-vague-suppression-description": "error",
15803
15858
  "@sarj/no-generic-single-export-module": "error",
15804
15859
  "@sarj/no-offset-pagination": "error",
15805
15860
  "@sarj/no-positional-tuple-return": "error",
@@ -15864,7 +15919,7 @@ var strictRules = {
15864
15919
  "@sarj/no-log-only-catch": "error",
15865
15920
  "@sarj/no-bare-return-from-test-catch": "warn",
15866
15921
  "@sarj/no-long-comment": "error",
15867
- "@sarj/no-vague-suppression-description": "warn",
15922
+ "@sarj/no-vague-suppression-description": "error",
15868
15923
  "@sarj/no-generic-single-export-module": "error",
15869
15924
  "@sarj/no-offset-pagination": "error",
15870
15925
  "@sarj/no-positional-tuple-return": "error",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sarj/eslint-plugin",
3
- "version": "15.8.0",
3
+ "version": "15.8.2",
4
4
  "packageManager": "npm@12.0.2",
5
5
  "description": "Custom ESLint rules for hypermodern TypeScript / React / Next.js projects",
6
6
  "type": "module",