Mobile Factory Tech Blog

技術好きな方へ!モバイルファクトリーのエンジニアたちが楽しい技術話をお届けします!

PerlのVSCodeの拡張機能を少し便利にした話

この記事はモバイルファクトリー Advent Calendar 2020 14日目の記事です。

はじめまして、20卒エンジニアのthe96です。 今回は業務中に使っているPerlのVSCodeの拡張機能のメソッド呼び出しの際の定義元ジャンプが正しく動作するように修正した話をします。

やったこと

従来のVSCode Perlではメソッド呼び出し(Hoge::Fuga->func())のときに定義元ジャンプを行った場合、別パッケージの同名関数の定義元に移動してしまうことがあります。 ソースコードを読む際に正しい定義元に移動しないと不便なので、この拡張機能に手を入れて改善しました。

この不具合について説明するために、同名の関数helloが定義された二つのパッケージABを用意しました。

修正前の定義元ジャンプ機能では、関数呼び出し(A::hello)のときはA#helloの定義に移動できていますが、メソッド呼び出し(A->hello)のときに定義元ジャンプをするとB#helloの定義に移動してしまっています。

f:id:the630:20201211185700g:plain

修正後の定義元ジャンプ機能では、メソッド呼び出しでも期待通りA#helloへ移動できています。

f:id:the630:20201211190147g:plain

原因

メソッド呼び出しされている関数で定義元ジャンプをする際、その関数の前の文字列を参照し、パッケージ名であればそれを含めて検索してくれます。 しかし、->がパッケージ名をつなぐ区切り文字として認識されていなかったのが原因でした。 https://github.com/vscode-perl/vscode-perl/blob/master/src/utils.ts#L15

export function getPackageBefore(document: vscode.TextDocument, range: vscode.Range): string {
    let separatorRange = getRangeBefore(range, 2);
    let separator = document.getText(separatorRange);
    let pkg = "";

    while (separator === "::") {
        const newRange = document.getWordRangeAtPosition(getPointBefore(separatorRange, 1));
        if (newRange) {
            range = newRange;
            pkg = document.getText(range) + separator + pkg;
            separatorRange = getRangeBefore(range, 2);
            separator = document.getText(separatorRange);
        } else {
            // break loop
            separator = "";
        }
    }

    return pkg.replace(/::$/, "");
}

区切り文字に->を加えた結果、予想通りパッケージ名を考慮して正しい定義元へとジャンプしてくれるようになりました! これで、業務中のコードリーディングが捗りそうです:tada:

改良後の拡張機能

初めてのOSSへのP-Rです https://github.com/vscode-perl/vscode-perl/pull/41

しばらく更新されていなかったので、VSCodeのマーケットプレイスにも公開しておきました。 上記が元リポジトリに反映されるまで、よろしければご利用ください。 https://marketplace.visualstudio.com/items?itemName=the96.vscode-perl


明日の記事は yokoi0803 さんです!