@sarj/eslint-plugin 15.6.8 → 15.6.9
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.cjs +92 -8
- package/dist/index.d.cts +6 -2
- package/dist/index.d.ts +6 -2
- package/dist/index.js +92 -8
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -4292,6 +4292,87 @@ var no_long_comment_default = createRule({
|
|
|
4292
4292
|
}
|
|
4293
4293
|
});
|
|
4294
4294
|
|
|
4295
|
+
// src/rules/no-vague-suppression-description.ts
|
|
4296
|
+
var DIRECTIVE_RE3 = /(?:eslint-(?:disable|disable-next-line|disable-line)|@ts-(?:expect-error|ignore))\b/iu;
|
|
4297
|
+
var DESCRIPTION_RE = /(?::|--)\s*(.+?)\s*$/u;
|
|
4298
|
+
var VAGUE_RE = /^(?:needed|required|intentional(?:ly)?|ignore(?:d)?|false positive|type error|typescript|to satisfy (?:the )?(?:linter|typescript|type checker))\.?$/iu;
|
|
4299
|
+
var noVagueSuppressionDescriptionDocumentation = {
|
|
4300
|
+
summary: "Require suppression descriptions to name the concrete mismatch or invariant instead of a generic non-reason.",
|
|
4301
|
+
rationale: "Generic phrases satisfy require-description mechanically while leaving reviewers unable to audit the risk or remove stale debt.",
|
|
4302
|
+
remediation: "Name the exact type/runtime mismatch, external contract, or safety invariant that makes this suppression acceptable.",
|
|
4303
|
+
category: "maintainability",
|
|
4304
|
+
limitations: [
|
|
4305
|
+
"Only ESLint disable comments and TypeScript expect-error/ignore directives are checked.",
|
|
4306
|
+
"The rule uses a small anchored vocabulary and does not score prose quality generally.",
|
|
4307
|
+
"Generated files and descriptions containing any concrete context are excluded."
|
|
4308
|
+
],
|
|
4309
|
+
examples: [
|
|
4310
|
+
{
|
|
4311
|
+
id: "concrete-runtime-mismatch",
|
|
4312
|
+
title: "Explain the concrete runtime contract",
|
|
4313
|
+
outcome: "no-match",
|
|
4314
|
+
files: [
|
|
4315
|
+
{
|
|
4316
|
+
path: "src/adapter.ts",
|
|
4317
|
+
source: "// @ts-expect-error -- vendor types omit the runtime requestId field\nreturn response.requestId;"
|
|
4318
|
+
}
|
|
4319
|
+
],
|
|
4320
|
+
focusPath: "src/adapter.ts",
|
|
4321
|
+
expectedCount: 0,
|
|
4322
|
+
public: true
|
|
4323
|
+
},
|
|
4324
|
+
{
|
|
4325
|
+
id: "generic-suppression-reason",
|
|
4326
|
+
title: "Reject a suppression with no auditable reason",
|
|
4327
|
+
outcome: "match",
|
|
4328
|
+
files: [
|
|
4329
|
+
{
|
|
4330
|
+
path: "src/adapter.ts",
|
|
4331
|
+
source: "// @ts-expect-error -- false positive\nreturn response.requestId;"
|
|
4332
|
+
}
|
|
4333
|
+
],
|
|
4334
|
+
focusPath: "src/adapter.ts",
|
|
4335
|
+
expectedCount: 1,
|
|
4336
|
+
public: true
|
|
4337
|
+
}
|
|
4338
|
+
]
|
|
4339
|
+
};
|
|
4340
|
+
var no_vague_suppression_description_default = createRule({
|
|
4341
|
+
name: "no-vague-suppression-description",
|
|
4342
|
+
documentation: noVagueSuppressionDescriptionDocumentation,
|
|
4343
|
+
meta: {
|
|
4344
|
+
type: "suggestion",
|
|
4345
|
+
docs: {
|
|
4346
|
+
description: "Require suppression descriptions to name the concrete mismatch or invariant instead of a generic non-reason."
|
|
4347
|
+
},
|
|
4348
|
+
schema: [],
|
|
4349
|
+
messages: {
|
|
4350
|
+
vagueDescription: "Suppression description `{{description}}` does not explain why the suppressed diagnostic is safe here. Name the concrete type/runtime mismatch, external contract, or invariant."
|
|
4351
|
+
}
|
|
4352
|
+
},
|
|
4353
|
+
defaultOptions: [],
|
|
4354
|
+
create(context) {
|
|
4355
|
+
if (isGeneratedFile(context.filename, context.sourceCode.text)) {
|
|
4356
|
+
return {};
|
|
4357
|
+
}
|
|
4358
|
+
return {
|
|
4359
|
+
Program() {
|
|
4360
|
+
for (const comment of context.sourceCode.getAllComments()) {
|
|
4361
|
+
const text = comment.value.trim();
|
|
4362
|
+
if (!DIRECTIVE_RE3.test(text)) continue;
|
|
4363
|
+
const description = DESCRIPTION_RE.exec(text)?.[1]?.trim();
|
|
4364
|
+
if (description === void 0 || !VAGUE_RE.test(description)) continue;
|
|
4365
|
+
context.report({
|
|
4366
|
+
loc: comment.loc,
|
|
4367
|
+
messageId: "vagueDescription",
|
|
4368
|
+
data: { description }
|
|
4369
|
+
});
|
|
4370
|
+
}
|
|
4371
|
+
}
|
|
4372
|
+
};
|
|
4373
|
+
}
|
|
4374
|
+
});
|
|
4375
|
+
|
|
4295
4376
|
// src/rules/no-generic-single-export-module.ts
|
|
4296
4377
|
var import_utils21 = require("@typescript-eslint/utils");
|
|
4297
4378
|
var noGenericSingleExportModuleDocumentation = {
|
|
@@ -5431,7 +5512,7 @@ var no_repeated_string_literal_default = createRule({
|
|
|
5431
5512
|
var import_utils28 = require("@typescript-eslint/utils");
|
|
5432
5513
|
var MAX_WORDS = 8;
|
|
5433
5514
|
var MIN_CONTENT_TOKENS = 2;
|
|
5434
|
-
var
|
|
5515
|
+
var DIRECTIVE_RE4 = /^(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;
|
|
5435
5516
|
var CODEY_RE = /^[\w.$[\]'"]+\s*[:=]\s*\S|^[\w.$]+\s*\(|^(?:return|throw|await|import|export|const|let|var)\b.*[=()[\]{}]/;
|
|
5436
5517
|
var BANNERISH_RE = /[=\-─-╿*#~_.]{3,}|^[A-Z0-9 _:-]+$/;
|
|
5437
5518
|
var MODALITY_RE = /\b(?:can|could|should|shall|may|might|must|will|would|cannot)\b/i;
|
|
@@ -5530,7 +5611,7 @@ var no_restated_comment_default = createRule({
|
|
|
5530
5611
|
}
|
|
5531
5612
|
const body2 = comment.value.replace(/^\/*/, "").trim();
|
|
5532
5613
|
if (body2.length === 0 || body2.endsWith("?")) continue;
|
|
5533
|
-
if (
|
|
5614
|
+
if (DIRECTIVE_RE4.test(body2) || CODEY_RE.test(body2) || BANNERISH_RE.test(body2)) continue;
|
|
5534
5615
|
if (NON_ASCII_LETTER_RE.test(body2) || isProtected(body2)) continue;
|
|
5535
5616
|
if (MODALITY_RE.test(body2) || LEAD_IN_RE.test(body2) || EMPHASIS_RE.test(body2)) continue;
|
|
5536
5617
|
if (NEGATION_WORD_RE.test(body2)) continue;
|
|
@@ -5578,7 +5659,7 @@ var MODELLED_TAGS = /* @__PURE__ */ new Set([
|
|
|
5578
5659
|
]);
|
|
5579
5660
|
var PARAM_TAGS = /* @__PURE__ */ new Set(["arg", "argument", "param"]);
|
|
5580
5661
|
var RETURN_TAGS = /* @__PURE__ */ new Set(["return", "returns"]);
|
|
5581
|
-
var
|
|
5662
|
+
var DIRECTIVE_RE5 = /^\s*(?:eslint\b|eslint-|@ts-|prettier|biome-|c8\b|v8\b|istanbul\b|@vite|webpack|@jsx|@jest-environment|@vitest-environment|#__)/i;
|
|
5582
5663
|
var STOPWORDS2 = new Set(
|
|
5583
5664
|
`the a an of to for in on with and or as at by is are was be been being
|
|
5584
5665
|
this that it its if whether when where which what will would can could should
|
|
@@ -5694,7 +5775,7 @@ var no_restated_jsdoc_default = createRule({
|
|
|
5694
5775
|
description,
|
|
5695
5776
|
...tags.filter((tag) => tag.name === "description").map((tag) => tag.text)
|
|
5696
5777
|
].filter((text) => text.length > 0).join("\n");
|
|
5697
|
-
if (
|
|
5778
|
+
if (DIRECTIVE_RE5.test(describedText)) continue;
|
|
5698
5779
|
const tagNames = new Set(tags.map((tag) => tag.name));
|
|
5699
5780
|
if ([...tagNames].some((name) => !MODELLED_TAGS.has(name))) continue;
|
|
5700
5781
|
if (isProtected(describedText)) continue;
|
|
@@ -7656,10 +7737,10 @@ var STOPWORDS3 = /* @__PURE__ */ new Set([
|
|
|
7656
7737
|
"we",
|
|
7657
7738
|
"with"
|
|
7658
7739
|
]);
|
|
7659
|
-
var
|
|
7740
|
+
var DIRECTIVE_RE6 = /^\s*(?:eslint\b|eslint-|sarj-noqa\b|@ts-|prettier|biome-|c8\b|v8\b|istanbul\b|todo\b|fixme\b|hack\b|xxx\b)/i;
|
|
7660
7741
|
var UNIT_NAME_SUFFIX_RE = /(?:_(?:NS|US|MS|S|SEC|SECS|SECOND|SECONDS|MIN|MINS|MINUTE|MINUTES|HOUR|HOURS|DAY|DAYS|BYTE|BYTES|KB|MB|GB|HZ|KHZ|MHZ|PX)|(?:Ns|Us|Ms|Sec|Secs|Second|Seconds|Min|Mins|Minute|Minutes|Hour|Hours|Day|Days|Byte|Bytes|Kb|Mb|Gb|Hz|Khz|Mhz|Px))$/u;
|
|
7661
7742
|
function narratesValue(body2, code) {
|
|
7662
|
-
if (body2.length === 0 ||
|
|
7743
|
+
if (body2.length === 0 || DIRECTIVE_RE6.test(body2) || hasExternalReference(body2)) return false;
|
|
7663
7744
|
const codeNumbers = numbersIn(code);
|
|
7664
7745
|
if (codeNumbers.size === 0) return false;
|
|
7665
7746
|
const words2 = (body2.match(WORD_RE3) ?? []).map((word) => word.toLowerCase());
|
|
@@ -15305,6 +15386,7 @@ var rules = {
|
|
|
15305
15386
|
"no-impossible-zod-literal-bounds": no_impossible_zod_literal_bounds_default,
|
|
15306
15387
|
"no-log-only-catch": no_log_only_catch_default,
|
|
15307
15388
|
"no-long-comment": no_long_comment_default,
|
|
15389
|
+
"no-vague-suppression-description": no_vague_suppression_description_default,
|
|
15308
15390
|
"no-generic-single-export-module": no_generic_single_export_module_default,
|
|
15309
15391
|
"no-offset-pagination": no_offset_pagination_default,
|
|
15310
15392
|
"no-positional-tuple-return": no_positional_tuple_return_default,
|
|
@@ -15358,14 +15440,14 @@ var rules = {
|
|
|
15358
15440
|
};
|
|
15359
15441
|
var meta = {
|
|
15360
15442
|
name: "@sarj/eslint-plugin",
|
|
15361
|
-
version: "15.6.
|
|
15443
|
+
version: "15.6.9"
|
|
15362
15444
|
};
|
|
15363
15445
|
var applicationOnlyRules = [
|
|
15364
15446
|
"no-restricted-library-load",
|
|
15365
15447
|
"prefer-native-random-uuid",
|
|
15366
15448
|
"prefer-shadcn-primitives"
|
|
15367
15449
|
];
|
|
15368
|
-
var advisoryRules = ["source-coupled-test"];
|
|
15450
|
+
var advisoryRules = ["no-vague-suppression-description", "source-coupled-test"];
|
|
15369
15451
|
var recommendedRules = {
|
|
15370
15452
|
"@sarj/duplicate-test-body": "error",
|
|
15371
15453
|
"@sarj/enforce-file-structure": "error",
|
|
@@ -15381,6 +15463,7 @@ var recommendedRules = {
|
|
|
15381
15463
|
"@sarj/no-impossible-zod-literal-bounds": "error",
|
|
15382
15464
|
"@sarj/no-log-only-catch": "error",
|
|
15383
15465
|
"@sarj/no-long-comment": "error",
|
|
15466
|
+
"@sarj/no-vague-suppression-description": "warn",
|
|
15384
15467
|
"@sarj/no-generic-single-export-module": "error",
|
|
15385
15468
|
"@sarj/no-offset-pagination": "error",
|
|
15386
15469
|
"@sarj/no-positional-tuple-return": "error",
|
|
@@ -15442,6 +15525,7 @@ var strictRules = {
|
|
|
15442
15525
|
"@sarj/no-impossible-zod-literal-bounds": "error",
|
|
15443
15526
|
"@sarj/no-log-only-catch": "error",
|
|
15444
15527
|
"@sarj/no-long-comment": "error",
|
|
15528
|
+
"@sarj/no-vague-suppression-description": "warn",
|
|
15445
15529
|
"@sarj/no-generic-single-export-module": "error",
|
|
15446
15530
|
"@sarj/no-offset-pagination": "error",
|
|
15447
15531
|
"@sarj/no-positional-tuple-return": "error",
|
package/dist/index.d.cts
CHANGED
|
@@ -208,6 +208,7 @@ declare const rules: {
|
|
|
208
208
|
readonly "no-impossible-zod-literal-bounds": DocumentedRule<readonly [], "impossibleBounds">;
|
|
209
209
|
readonly "no-log-only-catch": DocumentedRule<readonly [LoggingOptions?], "noLogOnlyCatch" | "emptyCatch">;
|
|
210
210
|
readonly "no-long-comment": DocumentedRule<readonly [], "tooLong">;
|
|
211
|
+
readonly "no-vague-suppression-description": DocumentedRule<readonly [], "vagueDescription">;
|
|
211
212
|
readonly "no-generic-single-export-module": DocumentedRule<[], "genericSingleExport">;
|
|
212
213
|
readonly "no-offset-pagination": DocumentedRule<readonly [], "noOffsetPagination">;
|
|
213
214
|
readonly "no-positional-tuple-return": DocumentedRule<readonly [], "noPositionalTupleReturn">;
|
|
@@ -282,7 +283,7 @@ declare const rules: {
|
|
|
282
283
|
/** Rules registered for application-profile configs but intentionally absent from general presets. */
|
|
283
284
|
declare const applicationOnlyRules: readonly ["no-restricted-library-load", "prefer-native-random-uuid", "prefer-shadcn-primitives"];
|
|
284
285
|
/** Calibrated rules that intentionally remain warnings until consumer-corpus precision is proven. */
|
|
285
|
-
declare const advisoryRules: readonly ["source-coupled-test"];
|
|
286
|
+
declare const advisoryRules: readonly ["no-vague-suppression-description", "source-coupled-test"];
|
|
286
287
|
declare const recommendedRules: {
|
|
287
288
|
readonly "@sarj/duplicate-test-body": "error";
|
|
288
289
|
readonly "@sarj/enforce-file-structure": "error";
|
|
@@ -300,6 +301,7 @@ declare const recommendedRules: {
|
|
|
300
301
|
readonly "@sarj/no-impossible-zod-literal-bounds": "error";
|
|
301
302
|
readonly "@sarj/no-log-only-catch": "error";
|
|
302
303
|
readonly "@sarj/no-long-comment": "error";
|
|
304
|
+
readonly "@sarj/no-vague-suppression-description": "warn";
|
|
303
305
|
readonly "@sarj/no-generic-single-export-module": "error";
|
|
304
306
|
readonly "@sarj/no-offset-pagination": "error";
|
|
305
307
|
readonly "@sarj/no-positional-tuple-return": "error";
|
|
@@ -365,6 +367,7 @@ declare const strictRules: {
|
|
|
365
367
|
readonly "@sarj/no-impossible-zod-literal-bounds": "error";
|
|
366
368
|
readonly "@sarj/no-log-only-catch": "error";
|
|
367
369
|
readonly "@sarj/no-long-comment": "error";
|
|
370
|
+
readonly "@sarj/no-vague-suppression-description": "warn";
|
|
368
371
|
readonly "@sarj/no-generic-single-export-module": "error";
|
|
369
372
|
readonly "@sarj/no-offset-pagination": "error";
|
|
370
373
|
readonly "@sarj/no-positional-tuple-return": "error";
|
|
@@ -423,7 +426,7 @@ type FlatPreset = {
|
|
|
423
426
|
declare const plugin: {
|
|
424
427
|
readonly meta: {
|
|
425
428
|
readonly name: "@sarj/eslint-plugin";
|
|
426
|
-
readonly version: "15.6.
|
|
429
|
+
readonly version: "15.6.9";
|
|
427
430
|
};
|
|
428
431
|
readonly rules: {
|
|
429
432
|
readonly "duplicate-test-body": DocumentedRule<readonly [], "duplicateTestBody">;
|
|
@@ -446,6 +449,7 @@ declare const plugin: {
|
|
|
446
449
|
readonly "no-impossible-zod-literal-bounds": DocumentedRule<readonly [], "impossibleBounds">;
|
|
447
450
|
readonly "no-log-only-catch": DocumentedRule<readonly [LoggingOptions?], "noLogOnlyCatch" | "emptyCatch">;
|
|
448
451
|
readonly "no-long-comment": DocumentedRule<readonly [], "tooLong">;
|
|
452
|
+
readonly "no-vague-suppression-description": DocumentedRule<readonly [], "vagueDescription">;
|
|
449
453
|
readonly "no-generic-single-export-module": DocumentedRule<[], "genericSingleExport">;
|
|
450
454
|
readonly "no-offset-pagination": DocumentedRule<readonly [], "noOffsetPagination">;
|
|
451
455
|
readonly "no-positional-tuple-return": DocumentedRule<readonly [], "noPositionalTupleReturn">;
|
package/dist/index.d.ts
CHANGED
|
@@ -208,6 +208,7 @@ declare const rules: {
|
|
|
208
208
|
readonly "no-impossible-zod-literal-bounds": DocumentedRule<readonly [], "impossibleBounds">;
|
|
209
209
|
readonly "no-log-only-catch": DocumentedRule<readonly [LoggingOptions?], "noLogOnlyCatch" | "emptyCatch">;
|
|
210
210
|
readonly "no-long-comment": DocumentedRule<readonly [], "tooLong">;
|
|
211
|
+
readonly "no-vague-suppression-description": DocumentedRule<readonly [], "vagueDescription">;
|
|
211
212
|
readonly "no-generic-single-export-module": DocumentedRule<[], "genericSingleExport">;
|
|
212
213
|
readonly "no-offset-pagination": DocumentedRule<readonly [], "noOffsetPagination">;
|
|
213
214
|
readonly "no-positional-tuple-return": DocumentedRule<readonly [], "noPositionalTupleReturn">;
|
|
@@ -282,7 +283,7 @@ declare const rules: {
|
|
|
282
283
|
/** Rules registered for application-profile configs but intentionally absent from general presets. */
|
|
283
284
|
declare const applicationOnlyRules: readonly ["no-restricted-library-load", "prefer-native-random-uuid", "prefer-shadcn-primitives"];
|
|
284
285
|
/** Calibrated rules that intentionally remain warnings until consumer-corpus precision is proven. */
|
|
285
|
-
declare const advisoryRules: readonly ["source-coupled-test"];
|
|
286
|
+
declare const advisoryRules: readonly ["no-vague-suppression-description", "source-coupled-test"];
|
|
286
287
|
declare const recommendedRules: {
|
|
287
288
|
readonly "@sarj/duplicate-test-body": "error";
|
|
288
289
|
readonly "@sarj/enforce-file-structure": "error";
|
|
@@ -300,6 +301,7 @@ declare const recommendedRules: {
|
|
|
300
301
|
readonly "@sarj/no-impossible-zod-literal-bounds": "error";
|
|
301
302
|
readonly "@sarj/no-log-only-catch": "error";
|
|
302
303
|
readonly "@sarj/no-long-comment": "error";
|
|
304
|
+
readonly "@sarj/no-vague-suppression-description": "warn";
|
|
303
305
|
readonly "@sarj/no-generic-single-export-module": "error";
|
|
304
306
|
readonly "@sarj/no-offset-pagination": "error";
|
|
305
307
|
readonly "@sarj/no-positional-tuple-return": "error";
|
|
@@ -365,6 +367,7 @@ declare const strictRules: {
|
|
|
365
367
|
readonly "@sarj/no-impossible-zod-literal-bounds": "error";
|
|
366
368
|
readonly "@sarj/no-log-only-catch": "error";
|
|
367
369
|
readonly "@sarj/no-long-comment": "error";
|
|
370
|
+
readonly "@sarj/no-vague-suppression-description": "warn";
|
|
368
371
|
readonly "@sarj/no-generic-single-export-module": "error";
|
|
369
372
|
readonly "@sarj/no-offset-pagination": "error";
|
|
370
373
|
readonly "@sarj/no-positional-tuple-return": "error";
|
|
@@ -423,7 +426,7 @@ type FlatPreset = {
|
|
|
423
426
|
declare const plugin: {
|
|
424
427
|
readonly meta: {
|
|
425
428
|
readonly name: "@sarj/eslint-plugin";
|
|
426
|
-
readonly version: "15.6.
|
|
429
|
+
readonly version: "15.6.9";
|
|
427
430
|
};
|
|
428
431
|
readonly rules: {
|
|
429
432
|
readonly "duplicate-test-body": DocumentedRule<readonly [], "duplicateTestBody">;
|
|
@@ -446,6 +449,7 @@ declare const plugin: {
|
|
|
446
449
|
readonly "no-impossible-zod-literal-bounds": DocumentedRule<readonly [], "impossibleBounds">;
|
|
447
450
|
readonly "no-log-only-catch": DocumentedRule<readonly [LoggingOptions?], "noLogOnlyCatch" | "emptyCatch">;
|
|
448
451
|
readonly "no-long-comment": DocumentedRule<readonly [], "tooLong">;
|
|
452
|
+
readonly "no-vague-suppression-description": DocumentedRule<readonly [], "vagueDescription">;
|
|
449
453
|
readonly "no-generic-single-export-module": DocumentedRule<[], "genericSingleExport">;
|
|
450
454
|
readonly "no-offset-pagination": DocumentedRule<readonly [], "noOffsetPagination">;
|
|
451
455
|
readonly "no-positional-tuple-return": DocumentedRule<readonly [], "noPositionalTupleReturn">;
|
package/dist/index.js
CHANGED
|
@@ -4253,6 +4253,87 @@ var no_long_comment_default = createRule({
|
|
|
4253
4253
|
}
|
|
4254
4254
|
});
|
|
4255
4255
|
|
|
4256
|
+
// src/rules/no-vague-suppression-description.ts
|
|
4257
|
+
var DIRECTIVE_RE3 = /(?:eslint-(?:disable|disable-next-line|disable-line)|@ts-(?:expect-error|ignore))\b/iu;
|
|
4258
|
+
var DESCRIPTION_RE = /(?::|--)\s*(.+?)\s*$/u;
|
|
4259
|
+
var VAGUE_RE = /^(?:needed|required|intentional(?:ly)?|ignore(?:d)?|false positive|type error|typescript|to satisfy (?:the )?(?:linter|typescript|type checker))\.?$/iu;
|
|
4260
|
+
var noVagueSuppressionDescriptionDocumentation = {
|
|
4261
|
+
summary: "Require suppression descriptions to name the concrete mismatch or invariant instead of a generic non-reason.",
|
|
4262
|
+
rationale: "Generic phrases satisfy require-description mechanically while leaving reviewers unable to audit the risk or remove stale debt.",
|
|
4263
|
+
remediation: "Name the exact type/runtime mismatch, external contract, or safety invariant that makes this suppression acceptable.",
|
|
4264
|
+
category: "maintainability",
|
|
4265
|
+
limitations: [
|
|
4266
|
+
"Only ESLint disable comments and TypeScript expect-error/ignore directives are checked.",
|
|
4267
|
+
"The rule uses a small anchored vocabulary and does not score prose quality generally.",
|
|
4268
|
+
"Generated files and descriptions containing any concrete context are excluded."
|
|
4269
|
+
],
|
|
4270
|
+
examples: [
|
|
4271
|
+
{
|
|
4272
|
+
id: "concrete-runtime-mismatch",
|
|
4273
|
+
title: "Explain the concrete runtime contract",
|
|
4274
|
+
outcome: "no-match",
|
|
4275
|
+
files: [
|
|
4276
|
+
{
|
|
4277
|
+
path: "src/adapter.ts",
|
|
4278
|
+
source: "// @ts-expect-error -- vendor types omit the runtime requestId field\nreturn response.requestId;"
|
|
4279
|
+
}
|
|
4280
|
+
],
|
|
4281
|
+
focusPath: "src/adapter.ts",
|
|
4282
|
+
expectedCount: 0,
|
|
4283
|
+
public: true
|
|
4284
|
+
},
|
|
4285
|
+
{
|
|
4286
|
+
id: "generic-suppression-reason",
|
|
4287
|
+
title: "Reject a suppression with no auditable reason",
|
|
4288
|
+
outcome: "match",
|
|
4289
|
+
files: [
|
|
4290
|
+
{
|
|
4291
|
+
path: "src/adapter.ts",
|
|
4292
|
+
source: "// @ts-expect-error -- false positive\nreturn response.requestId;"
|
|
4293
|
+
}
|
|
4294
|
+
],
|
|
4295
|
+
focusPath: "src/adapter.ts",
|
|
4296
|
+
expectedCount: 1,
|
|
4297
|
+
public: true
|
|
4298
|
+
}
|
|
4299
|
+
]
|
|
4300
|
+
};
|
|
4301
|
+
var no_vague_suppression_description_default = createRule({
|
|
4302
|
+
name: "no-vague-suppression-description",
|
|
4303
|
+
documentation: noVagueSuppressionDescriptionDocumentation,
|
|
4304
|
+
meta: {
|
|
4305
|
+
type: "suggestion",
|
|
4306
|
+
docs: {
|
|
4307
|
+
description: "Require suppression descriptions to name the concrete mismatch or invariant instead of a generic non-reason."
|
|
4308
|
+
},
|
|
4309
|
+
schema: [],
|
|
4310
|
+
messages: {
|
|
4311
|
+
vagueDescription: "Suppression description `{{description}}` does not explain why the suppressed diagnostic is safe here. Name the concrete type/runtime mismatch, external contract, or invariant."
|
|
4312
|
+
}
|
|
4313
|
+
},
|
|
4314
|
+
defaultOptions: [],
|
|
4315
|
+
create(context) {
|
|
4316
|
+
if (isGeneratedFile(context.filename, context.sourceCode.text)) {
|
|
4317
|
+
return {};
|
|
4318
|
+
}
|
|
4319
|
+
return {
|
|
4320
|
+
Program() {
|
|
4321
|
+
for (const comment of context.sourceCode.getAllComments()) {
|
|
4322
|
+
const text = comment.value.trim();
|
|
4323
|
+
if (!DIRECTIVE_RE3.test(text)) continue;
|
|
4324
|
+
const description = DESCRIPTION_RE.exec(text)?.[1]?.trim();
|
|
4325
|
+
if (description === void 0 || !VAGUE_RE.test(description)) continue;
|
|
4326
|
+
context.report({
|
|
4327
|
+
loc: comment.loc,
|
|
4328
|
+
messageId: "vagueDescription",
|
|
4329
|
+
data: { description }
|
|
4330
|
+
});
|
|
4331
|
+
}
|
|
4332
|
+
}
|
|
4333
|
+
};
|
|
4334
|
+
}
|
|
4335
|
+
});
|
|
4336
|
+
|
|
4256
4337
|
// src/rules/no-generic-single-export-module.ts
|
|
4257
4338
|
import { AST_NODE_TYPES as AST_NODE_TYPES16, ASTUtils as ASTUtils4 } from "@typescript-eslint/utils";
|
|
4258
4339
|
var noGenericSingleExportModuleDocumentation = {
|
|
@@ -5392,7 +5473,7 @@ var no_repeated_string_literal_default = createRule({
|
|
|
5392
5473
|
import { AST_NODE_TYPES as AST_NODE_TYPES21 } from "@typescript-eslint/utils";
|
|
5393
5474
|
var MAX_WORDS = 8;
|
|
5394
5475
|
var MIN_CONTENT_TOKENS = 2;
|
|
5395
|
-
var
|
|
5476
|
+
var DIRECTIVE_RE4 = /^(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;
|
|
5396
5477
|
var CODEY_RE = /^[\w.$[\]'"]+\s*[:=]\s*\S|^[\w.$]+\s*\(|^(?:return|throw|await|import|export|const|let|var)\b.*[=()[\]{}]/;
|
|
5397
5478
|
var BANNERISH_RE = /[=\-─-╿*#~_.]{3,}|^[A-Z0-9 _:-]+$/;
|
|
5398
5479
|
var MODALITY_RE = /\b(?:can|could|should|shall|may|might|must|will|would|cannot)\b/i;
|
|
@@ -5491,7 +5572,7 @@ var no_restated_comment_default = createRule({
|
|
|
5491
5572
|
}
|
|
5492
5573
|
const body2 = comment.value.replace(/^\/*/, "").trim();
|
|
5493
5574
|
if (body2.length === 0 || body2.endsWith("?")) continue;
|
|
5494
|
-
if (
|
|
5575
|
+
if (DIRECTIVE_RE4.test(body2) || CODEY_RE.test(body2) || BANNERISH_RE.test(body2)) continue;
|
|
5495
5576
|
if (NON_ASCII_LETTER_RE.test(body2) || isProtected(body2)) continue;
|
|
5496
5577
|
if (MODALITY_RE.test(body2) || LEAD_IN_RE.test(body2) || EMPHASIS_RE.test(body2)) continue;
|
|
5497
5578
|
if (NEGATION_WORD_RE.test(body2)) continue;
|
|
@@ -5539,7 +5620,7 @@ var MODELLED_TAGS = /* @__PURE__ */ new Set([
|
|
|
5539
5620
|
]);
|
|
5540
5621
|
var PARAM_TAGS = /* @__PURE__ */ new Set(["arg", "argument", "param"]);
|
|
5541
5622
|
var RETURN_TAGS = /* @__PURE__ */ new Set(["return", "returns"]);
|
|
5542
|
-
var
|
|
5623
|
+
var DIRECTIVE_RE5 = /^\s*(?:eslint\b|eslint-|@ts-|prettier|biome-|c8\b|v8\b|istanbul\b|@vite|webpack|@jsx|@jest-environment|@vitest-environment|#__)/i;
|
|
5543
5624
|
var STOPWORDS2 = new Set(
|
|
5544
5625
|
`the a an of to for in on with and or as at by is are was be been being
|
|
5545
5626
|
this that it its if whether when where which what will would can could should
|
|
@@ -5655,7 +5736,7 @@ var no_restated_jsdoc_default = createRule({
|
|
|
5655
5736
|
description,
|
|
5656
5737
|
...tags.filter((tag) => tag.name === "description").map((tag) => tag.text)
|
|
5657
5738
|
].filter((text) => text.length > 0).join("\n");
|
|
5658
|
-
if (
|
|
5739
|
+
if (DIRECTIVE_RE5.test(describedText)) continue;
|
|
5659
5740
|
const tagNames = new Set(tags.map((tag) => tag.name));
|
|
5660
5741
|
if ([...tagNames].some((name) => !MODELLED_TAGS.has(name))) continue;
|
|
5661
5742
|
if (isProtected(describedText)) continue;
|
|
@@ -7617,10 +7698,10 @@ var STOPWORDS3 = /* @__PURE__ */ new Set([
|
|
|
7617
7698
|
"we",
|
|
7618
7699
|
"with"
|
|
7619
7700
|
]);
|
|
7620
|
-
var
|
|
7701
|
+
var DIRECTIVE_RE6 = /^\s*(?:eslint\b|eslint-|sarj-noqa\b|@ts-|prettier|biome-|c8\b|v8\b|istanbul\b|todo\b|fixme\b|hack\b|xxx\b)/i;
|
|
7621
7702
|
var UNIT_NAME_SUFFIX_RE = /(?:_(?:NS|US|MS|S|SEC|SECS|SECOND|SECONDS|MIN|MINS|MINUTE|MINUTES|HOUR|HOURS|DAY|DAYS|BYTE|BYTES|KB|MB|GB|HZ|KHZ|MHZ|PX)|(?:Ns|Us|Ms|Sec|Secs|Second|Seconds|Min|Mins|Minute|Minutes|Hour|Hours|Day|Days|Byte|Bytes|Kb|Mb|Gb|Hz|Khz|Mhz|Px))$/u;
|
|
7622
7703
|
function narratesValue(body2, code) {
|
|
7623
|
-
if (body2.length === 0 ||
|
|
7704
|
+
if (body2.length === 0 || DIRECTIVE_RE6.test(body2) || hasExternalReference(body2)) return false;
|
|
7624
7705
|
const codeNumbers = numbersIn(code);
|
|
7625
7706
|
if (codeNumbers.size === 0) return false;
|
|
7626
7707
|
const words2 = (body2.match(WORD_RE3) ?? []).map((word) => word.toLowerCase());
|
|
@@ -15285,6 +15366,7 @@ var rules = {
|
|
|
15285
15366
|
"no-impossible-zod-literal-bounds": no_impossible_zod_literal_bounds_default,
|
|
15286
15367
|
"no-log-only-catch": no_log_only_catch_default,
|
|
15287
15368
|
"no-long-comment": no_long_comment_default,
|
|
15369
|
+
"no-vague-suppression-description": no_vague_suppression_description_default,
|
|
15288
15370
|
"no-generic-single-export-module": no_generic_single_export_module_default,
|
|
15289
15371
|
"no-offset-pagination": no_offset_pagination_default,
|
|
15290
15372
|
"no-positional-tuple-return": no_positional_tuple_return_default,
|
|
@@ -15338,14 +15420,14 @@ var rules = {
|
|
|
15338
15420
|
};
|
|
15339
15421
|
var meta = {
|
|
15340
15422
|
name: "@sarj/eslint-plugin",
|
|
15341
|
-
version: "15.6.
|
|
15423
|
+
version: "15.6.9"
|
|
15342
15424
|
};
|
|
15343
15425
|
var applicationOnlyRules = [
|
|
15344
15426
|
"no-restricted-library-load",
|
|
15345
15427
|
"prefer-native-random-uuid",
|
|
15346
15428
|
"prefer-shadcn-primitives"
|
|
15347
15429
|
];
|
|
15348
|
-
var advisoryRules = ["source-coupled-test"];
|
|
15430
|
+
var advisoryRules = ["no-vague-suppression-description", "source-coupled-test"];
|
|
15349
15431
|
var recommendedRules = {
|
|
15350
15432
|
"@sarj/duplicate-test-body": "error",
|
|
15351
15433
|
"@sarj/enforce-file-structure": "error",
|
|
@@ -15361,6 +15443,7 @@ var recommendedRules = {
|
|
|
15361
15443
|
"@sarj/no-impossible-zod-literal-bounds": "error",
|
|
15362
15444
|
"@sarj/no-log-only-catch": "error",
|
|
15363
15445
|
"@sarj/no-long-comment": "error",
|
|
15446
|
+
"@sarj/no-vague-suppression-description": "warn",
|
|
15364
15447
|
"@sarj/no-generic-single-export-module": "error",
|
|
15365
15448
|
"@sarj/no-offset-pagination": "error",
|
|
15366
15449
|
"@sarj/no-positional-tuple-return": "error",
|
|
@@ -15422,6 +15505,7 @@ var strictRules = {
|
|
|
15422
15505
|
"@sarj/no-impossible-zod-literal-bounds": "error",
|
|
15423
15506
|
"@sarj/no-log-only-catch": "error",
|
|
15424
15507
|
"@sarj/no-long-comment": "error",
|
|
15508
|
+
"@sarj/no-vague-suppression-description": "warn",
|
|
15425
15509
|
"@sarj/no-generic-single-export-module": "error",
|
|
15426
15510
|
"@sarj/no-offset-pagination": "error",
|
|
15427
15511
|
"@sarj/no-positional-tuple-return": "error",
|