TeamSpirit Advent Calendar 2021 Day11:Visual Studio CodeのBracket Pair Colorizer拡張機能が、ネイティブ実装されました

この記事は チームスピリット Advent Calendar 2021 の11日目の記事です。

adventar.org

こんにちは、開発チームの里石です!

今年もアドベントカレンダーでは、vscodeネタを語らせていただこうかと思います。

もはや普通のエディタとして、一日中使用しているため、毎月の機能アップデートには興味津々です。

今回はその中でも、最近実装されたBracket Pair Colorizerについてのご紹介です。

拡張機能時代

vscodeでは、ソース内の「対」になるブラケット同士を認識しています。そのブラケット同士を同じ色でカラーハイライトし、視認性を大きく高めてくれる拡張機能がありました。

f:id:satoishi_ts:20211205174422p:plain

Bracket Pair Colorizer拡張機能

以降、「BPC1」と略記します。

690万回もインストールされており、恐らく、ほとんどのvscodeユーザがこの拡張機能をインストールしているのではないかと思います。

BPC1では、カラーハイライト以外に、ブラケットが示すブロックスコープにガイド線を引いたり、水平線を引いたりするなど、視認性をより向上してくれるキメ細かい機能が実装されていました。 特に水平線は、ちょうどif文の下に引かれるため、ブロックスコープに入る条件に目が行きやすく、些細ながらとても便利な機能でした。

拡張機能からvscodeネイティブ実装へ

そんなBPC1でしたが、作者の環境の変化により、開発が止まっていました。 特に、BPC1の後継だった「Bracket Pair Colorizer 2拡張機能(以降「BPC2」略記し、BPC1とBPC2を総称して「BPC」と略記)」は、十分な機能実装を前に止まってしまい、かつプチフリーズが発生するパフォーマンス問題が解消されないままとなっていました。

BPC2では、ブラケット認識アルゴリズムが刷新され、vscode本体に実装されている字句解析ライブラリ「vscode-textmate(以降、「textmate」と略記)」と同じライブラリを利用して、ブラケット認識を行っています。これが仇となって、textmateトークン情報の更新に時間がかかるようになり、パフォーマンス問題が発生するようになってしまったようです。なおBPC1では、Prism.jsを使ってブラケット認識を行っています。

こちらで、BPC1とBPC2のパフォーマンス問題解決法を議論するissueが起票されています。Issue #128465 | Investigate into the performance issues of the bracket pair colorizer extension(BPCのパフォーマンスの問題を調査します)

拡張機能向けAPIには、vscode本体のtextmateが生成するトークン情報へのアクセス手段が用意されていません。このため、拡張機能トークン情報を利用するには、vscode本体に実装されているの同じ「vscode-textmateライブラリ」を拡張機能側で読み込んで実装してトークン情報を生成し、さらにそこから自前でブロックスコープ情報を構築して、カラーハイライトするしかありませんでした(BPC2はこの手法を取っています)。

また、大きなファイルになると、textmateトークン情報が正確ではなくなるといった問題も発生していたようです。

そこで、この拡張機能の機能をvscodeに取り込んでしまおうというプロジェクトが始まりました。

f:id:satoishi_ts:20211205174419p:plain

まず、Issue #96899 | Include a bracket pair colorizing feature(BPC機能を取り込みます)チケットとPull Request #129231 | Performant Bracket Pair Colorization(BPC処理の効率化)プルリクエストで、vscodeのブラケット認識アルゴリズムの実装と、カラーハイライトができるようになりました。

これは大きなアップデートでしたが、ブロックスコープの水平線表示など、BPCにあったキメ細かい機能はまだ実装されておらず、それを望む声が多くありました。BPCの作者自身も望んでいました。

その後、Issue #131001 | Feature Request: Colored line scopes(色付きガイド線によるスコープ)チケットと、Pull Request #134259 | Implements horizontal guides for bracket guides(ブラケットの水平線の実装)プルリクエストで、いよいよ水平線も実装され、BPCの持つ機能の大部分が移植され、BPCから移行しても概ね問題のない状況が整いました。

vscodeネイティブのブロックスコープ構造解析アルゴリズムの改良

今回のBPC機能取り込みプロジェクトにより、不完全だったvscodeネイティブのブロックスコープ構造解析アルゴリズムにも改良が加えられました。詳しくは、下記の記事で解説してくれています。

How We Made Bracket Pair Colorization 10,000x Faster In Visual Studio Code

なお、こちらの記事でも言及されているように、vscode内のtextmateで生成したトークン情報へアクセスする拡張機能APIは、パフォーマンスの問題から提供されることは無さそうです。残念・・・。

How We Made Bracket Pair Colorization 10,000x Faster In Visual Studio Code | tokens-to-the-rescue

We thought long about how we could efficiently and reliably expose token information to extensions, but came to the conclusion that we cannot do this without a lot of implementation details leaking into the extension API. Because the extension still has to send over a list of color decorations for each bracket in the document, such an API alone would not even solve the performance problem.

トークン情報を拡張機能に効率的かつ確実に公開する方法について、長い間考えていましたが、実装の詳細が大量にリークでもしない限り、拡張機能APIに含めることはできないという結論に達しました。拡張機能は、ドキュメント内の各ブラケットに色付けのリストを送信する必要があるため、パフォーマンス問題が発生し、APIだけでは解決することができません。

また、今回のプロジェクトでvscode内部ではブロックスコープ構造情報を持つようになったわけですが、こちらもまだ拡張機能向けAPIは用意されておらず、アクセスすることはできません。しかしすでに、そのAPIの要望は上がっており、issueも起票されています。将来実装されることを期待しましょう。

実際に使ってみる

それでは、実際にvscodeネイティブBPCを使ってみます。vscodeのsetting.jsonを開き、下記の設定項目を追加します。

今回実装されたvscodeネイティブBPCを有効にします。(デフォルトがfalseなのでtrueにしてください)

//角かっこのペアの彩色を有効にするかどうかを制御します。角かっこの強調表示の色をオーバーライドするには、'workbench.colorCustomizations' を使用します。
"editor.bracketPairColorization.enabled": true,   

ブラケット間のブロックスコープに、水平線または垂直線のガイド線を表示するかどうかを制御できます。現在カーソルのあるブロックスコープだけ表示したいときは、activeにします。

// ブラケット ペアのガイドを有効にするかどうかを制御します。
// active: アクティブなブラケット ペアに対してのみブラケット ペア ガイドを有効にします。
"editor.guides.bracketPairs": "active",

ブラケット間のブロックスコープに、水平線を表示するかを制御します。これも、現在カーソルのあるブロックスコープだけ表示させることができます。

//水平方向のブラケット ペアのガイドを有効にするかどうかを制御します。
// active: アクティブなブラケット ペアに対してのみ、水平のガイドを有効にします。
"editor.guides.bracketPairsHorizontal": "active",

ブラケット間のブロックスコープの垂直線を表示するかどうかを制御できます。

//ブラケット ペアのガイドを有効にするかどうかを制御します。
"editor.guides.highlightActiveBracketPair": true,

ちなみに、こちらは名前は似ていますが、インデントのガイド線についての設定です。vscodeネイティブBPCを表示するときは、インデントの垂直ガイド線は上書きされます。

//エディターでインデント ガイドを表示するかどうかを制御します。
"editor.guides.indentation": true,

//エディターでアクティブなインデントのガイドを強調表示するかどうかを制御します。
"editor.guides.highlightActiveIndentation": true,

設定変更のデモを下記に示しますので、どのような効果が現れるか確認してみてください。

f:id:satoishi_ts:20211205175547g:plain

終わりに

役割をおえたBCP拡張機能は、今後非推奨となっていくことでしょう。しかし、vscodeのほぼ全ユーザに使われたであろう、なくてはならない素晴らしい拡張機能でした!vscode黎明期から、お疲れさまでした!