拡張を作ろうとする症候群

VSCode 拡張を作ろうとしたとき,実は最初 Perl のテストを CodeLens からやる,という拡張をつくろうとしていた.

どういうものか

Perl のテスト(Test::Class) で sub some_test_1 : Tests の行の上に CodeLens で Run Test... っていうのつけて,簡単にテスト実行できるようにしよう,というやつだった.

なぜかというと,以前までテストを実行するために iTerm2 から

docker-compose run -e TEST_METHOD=some_test docker_app carton exec -- prove -lr t/Some/Test.t

とかやっていて,超効率が悪かったからだ.

そんなとき JUnit とかだと VSCode の CodeLens から実行できるのを見た:

https://www.publickey1.jp/blog/17/visual_studio_codejunit.html

なので,VSCode からそのままテスト実行できたら,ものすごい楽だろうな,という気持ちになっていた.

CodeLens

CodeLens を任意の行に追加するのは非常に楽で,vscode.languages.registerCodeLensProvider というメソッドで,vscode.TextDocument を受け取って,vscode.CodeLens オブジェクトの配列を返すような関数を登録すればいいのだった.

Perl のパーサーはどうした,という話だが,そのときはスーパー適当で,正規表現でマッチした行でいいでしょう! ってザックリ実装したのだった:

import * as vscode from 'vscode';

export default function findTestMethodRanges(document: vscode.TextDocument): vscode.Range[] {
    const REGEX = /sub\s+(.+?)\s*:\s*Tests?/mg;
    const ranges = [];

    for (let i = 0; i < document.lineCount; ++i) {
        const text = document.lineAt(i).text;
        const matches = REGEX.exec(text);
        if (!matches) {
            continue;
        }
        const range = new vscode.Range(i, 0, i, matches[1].length);
        ranges.push(range);
    }

    return ranges;
}

そして,

それはそれっぽく動いて,sub great_test : Tests のような行の上に Run Test... が出て,クリックしたら VSCode のビルトイン Terminal に config で設定したテストコマンドが流し込まれて,いいんじゃないか,となっていた.

f:id:mangano-ito:20200426001653p:plain
それっぽい

しかしながら,

すこし欲が出て,サイドバーにテストケースのツリービューを表示して,テストの成功・失敗が一覧できると楽しいだろうな,という気持ちになってきた (IntelliJIDE みたいに).

しかも,そこで Rerun All Tests... とか Rerun Failed Tests... とかできたら気分がいいだろう…とも思っていた.

https://blog.jetbrains.com/idea/2013/03/how-to-write-automated-tests-for-plugins/

こういうのです.

PHPStorm ではテストが通った行がマーカーついてカバレッジこれくらいですよ,っていうのが視覚的に見えたりする機能もあった.

そうすると,

テストは入れ子にできるので,subtest のツリーとかをパースする必要が出てくるわけだが,これは正規表現でザックリできるほど生易しいものではない.

というのも,{, } のマッチとかになってくると,コンテキストなしにパースするのは難しいというか,多いに間違ってしまうわけで,簡単にはできないだろうな,と思って諦めた.

最終的に,

でもターミナルから毎回やるのは面倒だな〜と思っていたら,普通に業務のレポジトリでは「カーソル行のテスト実行」と「すべてのテスト実行」がタスクとして .vscode/tasks.json に定義されていて,単に ⌘ + P> Run Task から便利にテスト実行できるようになっていたのだった!:

f:id:mangano-ito:20200427194525p:plain
求めていたものが身近にあった

こんな感じでカーソル行とファイルを指定してタスク定義できるのだった:

{
    "tasks": [
        {
            "label": "My Test",
            "type": "shell",
            "command": "path-to-test-helper ${relativeFile} ${lineNumber}",
            "group": "test"
        }
    ]
}

だとしたら,僕の悩みというのは 9 割解決で,別に CodeLens でポチポチする必要はないな,と思い直した.

しかも Problem Matcher が定義されているので,テストに Fail した行が波線も引かれていて,エラー行を調べるとかもしなくてよかったので,10 割解決して満足したのでこの拡張はボツとなった.

つまり,

頑張らなくても意外と素直に簡単な方法で実現できることは多くて,みんな経験することならなおさらステキな解決案が出ているので,先に探したほうがよかったりするのだった.

今回は CodeLens や VSCode の勉強だったと思うことにして,勉強のために車輪の再発明をしたと認識を改めることで後ろ向きに前進した.