Skip to content
Open
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@
"dependencies": {
"@babel/helper-validator-identifier": "^7.28.5",
"@eslint-community/eslint-utils": "^4.9.0",
"@eslint/plugin-kit": "^0.4.0",
"change-case": "^5.4.4",
"ci-info": "^4.3.1",
"clean-regexp": "^1.0.0",
Expand Down
7 changes: 5 additions & 2 deletions rules/expiring-todo-comments.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ import path from 'node:path';
import {isRegExp} from 'node:util/types';
import semver from 'semver';
import * as ci from 'ci-info';
import getBuiltinRule from './utils/get-builtin-rule.js';
import {
isEslintDisableOrEnableDirective,
getBuiltinRule,
} from './utils/index.js';
import {readPackageJson} from './shared/package-json.js';

const baseRule = getBuiltinRule('no-warning-comments');
Expand Down Expand Up @@ -285,7 +288,7 @@ const create = context => {
const {sourceCode} = context;
const comments = sourceCode.getAllComments();
const unusedComments = comments
.filter(token => token.type !== 'Shebang')
.filter(comment => comment.type !== 'Shebang' && !isEslintDisableOrEnableDirective(context, comment))
// Block comments come as one.
// Split for situations like this:
// /*
Expand Down
27 changes: 7 additions & 20 deletions rules/no-abusive-eslint-disable.js
Original file line number Diff line number Diff line change
@@ -1,34 +1,21 @@
import {ConfigCommentParser} from '@eslint/plugin-kit';
import {
getEslintDisableDirectives,
} from './utils/index.js';

const MESSAGE_ID = 'no-abusive-eslint-disable';
const messages = {
[MESSAGE_ID]: 'Specify the rules you want to disable.',
};

// https://github.com/eslint/eslint/blob/ecd0ede7fd2ccbb4c0daf0e4732e97ea0f49db1b/lib/linter/linter.js#L509-L512
const eslintDisableDirectives = new Set([
'eslint-disable',
'eslint-disable-line',
'eslint-disable-next-line',
]);

let commentParser;
/** @param {import('eslint').Rule.RuleContext} context */
const create = context => {
context.on('Program', function * (node) {
for (const comment of node.comments) {
commentParser ??= new ConfigCommentParser();
const result = commentParser.parseDirective(comment.value);

if (!(
// It's a eslint-disable comment
eslintDisableDirectives.has(result?.label)
// But it did not specify any rules
&& !result?.value
)) {
context.on('Program', function * () {
for (const directive of getEslintDisableDirectives(context)) {
if (directive.value) {
return;
}

const comment = directive.node;
const {sourceCode} = context;

yield {
Expand Down
21 changes: 21 additions & 0 deletions rules/utils/eslint-directive.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// https://github.com/eslint/eslint/blob/df5566f826d9f5740546e473aa6876b1f7d2f12c/lib/languages/js/source-code/source-code.js#L914-L917
const ESLINT_DISABLE_DIRECTIVE_TYPES = new Set([
'disable',
'disable-next-line',
'disable-line',
]);

function getEslintDisableDirectives(context) {
const {directives} = context.sourceCode.getDisableDirectives();
return directives.filter(({type}) => ESLINT_DISABLE_DIRECTIVE_TYPES.has(type));
}

function isEslintDisableOrEnableDirective(context, comment) {
const {directives} = context.sourceCode.getDisableDirectives();
return directives.some(directive => directive.node === comment);
}

export {
getEslintDisableDirectives,
isEslintDisableOrEnableDirective,
};
5 changes: 5 additions & 0 deletions rules/utils/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ export {default as isShorthandImportLocal} from './is-shorthand-import-local.js'
export {default as isShorthandPropertyValue} from './is-shorthand-property-value.js';
export {default as isValueNotUsable} from './is-value-not-usable.js';
export {default as needsSemicolon} from './needs-semicolon.js';
export {
getEslintDisableDirectives,
isEslintDisableOrEnableDirective,
} from './eslint-directive.js';
export {checkVueTemplate} from './rule.js';
export {default as shouldAddParenthesesToAwaitExpressionArgument} from './should-add-parentheses-to-await-expression-argument.js';
export {default as shouldAddParenthesesToCallExpressionCallee} from './should-add-parentheses-to-call-expression-callee.js';
Expand All @@ -64,3 +68,4 @@ export {default as getAncestor} from './get-ancestor.js';
export {getPreviousNode, getNextNode} from './get-sibling-node.js';
export * from './string-cases.js';
export * from './numeric.js';
export {default as getBuiltinRule} from './get-builtin-rule.js';
12 changes: 12 additions & 0 deletions test/expiring-todo-comments.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,18 @@ test({
code: '// TODO [2001-01-01]: quite old',
options: [{date: '2000-01-01'}],
},
{
code: `// eslint-disable-next-line rule-to-test/expiring-todo-comments
// TODO without a date`,
options: [{allowWarningComments: false}],
},
{
code: `/* eslint-disable rule-to-test/expiring-todo-comments */
// TODO without a date
// fixme [2000-01-01]: too old'
/* eslint-enable rule-to-test/expiring-todo-comments */`,
options: [{allowWarningComments: false}],
},
],
invalid: [
{
Expand Down
Loading