経験は何よりも饒舌

10年後に真価を発揮するかもしれないブログ 

非推奨になったESLintのルールがESLintのコード上でそう記されているか確かめるESLintのテストを書いた

ESLintのレポジトリでは、lib/rulesディレクトリ配下にルールがまとまっている。
以下に記されているように、それらのルールは非推奨になることがあるが、削除されることはない。
Rule Deprecation - ESLint - Pluggable JavaScript Linter

Balancing the trade-offs of improving a tool and the frustration these changes can cause is a difficult task. One key area in which this affects our users is in the removal of rules.
...
Rules will never be removed from ESLint.

非推奨となったルールは、そのコードとドキュメントにその旨が記されている。
例えば、ESLint v7.0.0で非推奨となったcallback-returnというルールでは、lib/rules/callback-return.jsdocs/rules/callback-return.mdでそれぞれ以下のような記述がある。

/**
 * @fileoverview Enforce return after a callback.
 * @author Jamund Ferguson
 * @deprecated in ESLint v7.0.0
 */
...
This rule was **deprecated** in ESLint v7.0.0. Please use the corresponding rule in [`eslint-plugin-node`](https://github.com/mysticatea/eslint-plugin-node).

しかし、コードとドキュメントにこのようにきちんと記されているか確認するフローがなかったため、記述が抜け漏れている箇所があった。
非推奨になっているルールの一覧が Rules - ESLint - Pluggable JavaScript Linter にあるので、それを目視で確認しながら修正していった。
Chore: Update deprecated information by wafuwafu13 · Pull Request #14961 · eslint/eslint · GitHub
このPRで、「非推奨になったルールのコードに@deprecatedタグがあること」、「README.mdThis rule was deprecated...の記述があること」を確かめるテストがあればよいというレビューがあった。

「目的のファイルに目的の記述があること」は、ShellJSのcatと正規表現を使って、すでに同じようなテストをしている箇所があったので書けそうだった。
eslint/Makefile.js at 80cfb8f858888bddfefd7de6b4ecbf5aabe267bc · eslint/eslint · GitHub

function hasIdInTitle(id) {
    const docText = cat(docFilename);
    const idOldAtEndOfTitleRegExp = new RegExp(`^# (.*?) \\(${id}\\)`, "u"); // original format
    const idNewAtBeginningOfTitleRegExp = new RegExp(`^# ${id}: `, "u"); // new format is same as rules index
    
    return idNewAtBeginningOfTitleRegExp.test(docText) || idOldAtEndOfTitleRegExp.test(docText);
}

問題は、「ルールが非推奨になっていること」をどのように定義するかだった。
先ほど述べたように非推奨になっているルールの一覧はRules - ESLint - Pluggable JavaScript Linterにあるのだが、それをfetch等でとってくるのは、コードが煩雑になりそうなのと、ルールの一覧のフォーマットやページが変わることによってテストが落ちるので避けたかった。
非推奨になったルールの一覧を写したjsonファイルを作る手もあったが、そのjsonがきちんと更新されなければ元も子もない。
ESLintのリリースフローはよく知らないが、このルールの一覧もコードから生成されているため、どこかにフラグがあるに違いないと思い探していると、メンテナーのPRが見つかった。
Update: deprecate Node.js & CommonJS rules by kaicataldo · Pull Request #12898 · eslint/eslint · GitHub
そこでは、各ルールのコードで書かれているドキュメントのような箇所でdeprecated: true,が追加されていた。

module.exports = {
    meta: {
        deprecated: true,
        ...

これはおそらくリリースフローに組み込まれているため、非推奨のルールが抜け漏れている心配はない。
よって、以下のようなコードで、非推奨になったESLintのルールがESLintのコード上でそう記されているか確かめるテストがかける。

function hasDeprecatedInfo() {
    return 
        「非推奨になったルールのコードに@deprecatedタグがあること」 && 
        「README.mdにThis rule was deprecated...の記述があること」
}

if (ruleDef.meta.deprecated && !hasDeprecatedInfo()) {
    エラー++
}

今朝approvedされた。
Chore: Add test that deprecated rules display a deprecated notice by wafuwafu13 · Pull Request #14989 · eslint/eslint · GitHub