Skip to content
Source
Sign inSign up

require-suppression-reason.ts

62 lines2.3 KB

1import { defineRule, type ESTree } from "@oxlint/plugins";
2​
3const DIRECTIVE_PATTERN =
4 /^\s*\*?\s*(?:(?:oxlint|eslint)-(?:disable|enable)|@ts-(?:expect-error|ignore|nocheck)|@effect-diagnostics)/u;
5const TS_DIRECTIVE_PATTERN = /^\s*\*?\s*@ts-(?:expect-error|ignore|nocheck)(?![\w-])(.*)$/su;
6const EMPTY_COMMENT_PATTERN = /^[\s*]*$/u;
7​
8export default defineRule({
9 meta: {
10 type: "suggestion",
11 docs: {
12 description: "Require every lint or type-checker suppression to say why.",
13 },
14 },
15 create(context) {
16 const { sourceCode } = context;
17 return {
18 Program() {
19 const comments = sourceCode.getAllComments();
20 const ownLineCommentsByEndLine = new Map<number, ESTree.Comment>();
21 for (const comment of comments) {
22 const { line, column } = comment.loc.start;
23 if ((sourceCode.lines[line - 1] ?? "").slice(0, column).trim() === "") {
24 ownLineCommentsByEndLine.set(comment.loc.end.line, comment);
25 }
26 }
27​
28 const explainedAbove = (directive: ESTree.Comment) => {
29 let above = ownLineCommentsByEndLine.get(directive.loc.start.line - 1);
30 while (
31 above &&
32 (DIRECTIVE_PATTERN.test(above.value) || EMPTY_COMMENT_PATTERN.test(above.value))
33 ) {
34 above = ownLineCommentsByEndLine.get(above.loc.start.line - 1);
35 }
36 return above !== undefined;
37 };
38​
39 for (const directive of sourceCode.getDisableDirectives().directives) {
40 if (directive.type === "enable" || directive.justification?.trim()) continue;
41 if (explainedAbove(directive.node)) continue;
42 context.report({
43 loc: directive.node.loc,
44 message:
45 "Say why: end the directive with `-- reason` or put a comment on the line above.",
46 });
47 }
48​
49 for (const comment of comments) {
50 const after = TS_DIRECTIVE_PATTERN.exec(comment.value)?.[1];
51 if (after === undefined || after.replace(/^[\s:-]+/u, "").trim()) continue;
52 if (explainedAbove(comment)) continue;
53 context.report({
54 loc: comment.loc,
55 message:
56 "Say why: write the reason after the directive or in a comment on the line above.",
57 });
58 }
59 },
60 };
61 },
62});