Webエンジニア向けプログラミング解説動画をYouTubeで配信中!
▶ チャンネル登録はこちら

【ITニュース解説】Title: How I Adapted My Custom Parser for the New nvim-treesitter `main` Branch

2025年09月28日に「Dev.to」が公開したITニュース「Title: How I Adapted My Custom Parser for the New nvim-treesitter `main` Branch」について初心者にもわかりやすく解説しています。

作成日: 更新日:

ITニュース概要

nvim-treesitterの最新版でカスタムC++パーサーのハイライトが動かず、筆者はデバッグを行った。旧版と異なり、新版は大幅な設計変更があり、パーサーのインストールやハイライトの有効化はユーザーが個別に行う必要がある。この変更点を理解し、設定を修正することで問題を解決した。

ITニュース解説

Neovimという高機能なテキストエディタで開発を行う際、コードの構文を解析し、色付け(シンタックスハイライト)やインデントを自動で行うことは非常に重要だ。その基盤となる技術の一つに「Tree-sitter」がある。これは、ソースコードを木構造として解析し、その構造を理解するライブラリで、従来の正規表現による解析よりもはるかに正確で柔軟な構文解析を可能にする。そして、このTree-sitterをNeovimで活用するためのプラグインが「nvim-treesitter」だ。

この記事の著者は、「tree-sitter-unreal-cpp」という、Unreal EngineのC++コード特有の構文を解析するためのカスタムパーサーを作成し、自身のNeovim環境で活用していた。カスタムパーサーとは、特定のプログラミング言語や、その言語の特定の方言(Unreal EngineのC++のように、標準C++に加えて独自のキーワードやマクロが使われる場合など)に対応するために、自分で開発した構文解析器のことだ。これにより、Unreal Engine特有のキーワードも適切にハイライトされるように設定していた。

しかし、著者がnvim-treesitterプラグインを最新の「main」ブランチに更新したところ、問題が発生した。以前は正常に機能していたUnreal Engineのマクロや仕様記述子(UCLASSBlueprintableなど)のカスタムハイライトが、突然すべて表示されなくなったのだ。これは、これまでの設定では最新のnvim-treesitterに対応できなくなったことを意味していた。

この問題の原因を探るデバッグの道のりが始まった。まず、自分のカスタムハイライトルールが記述された「highlights.scm」というファイルがNeovimによって認識されているかを確認した。Neovimの組み込みAPIを直接利用するコマンドを実行した結果、このカスタムクエリファイルは確かにロード対象リストに含まれていることが確認できた。つまり、ファイル自体は見つけられていたのだ。

次に、ハイライトされるべきキーワードにカーソルを合わせ、「:Inspect」コマンドを使って、どのような構文グループが適用されているかを調べた。結果は、Tree-sitter由来のハイライトが何も適用されていないことを示していた。しかし、Tree-sitterパーサー自体が機能しているかを確認する「:InspectTree」コマンドでは、Unreal EngineのC++コードが正しく解析され、木構造が生成されていることが確認できた。これは非常に奇妙な状況だった。パーサーはコードを理解しているのに、その理解に基づいたハイライトルールが適用されていないのだ。

この矛盾に直面し、著者はより根本的な変更があったのではないかと疑い始めた。そして、nvim-treesitterの「main」ブランチのREADME(説明書)を隅々まで読み直すことにした。このREADMEこそが、問題の真相を明らかにした。

実は、nvim-treesitterの「main」ブランチは単なる更新ではなく、これまでのバージョンとは互換性のない、完全に新しい設計思想に基づいた書き換えが行われていたのだ。以前のバージョンでは、プラグインのsetup関数でハイライト、インデント、パーサーの自動インストールなど、多くの機能を一括で設定する大規模なテーブルが使われていた。しかし、新しい「main」ブランチでは、このsetupテーブルが大幅に簡素化されていた。

特に大きな変更点は以下の通りだ。

  1. ensure_installedの廃止: 以前は、自動でインストールしたいパーサーのリストを指定するensure_installedという設定項目があったが、これが削除された。今後は、パーサーのインストールは明示的な関数呼び出しで行う必要がある。
  2. 機能の有効化が手動に: これまでhighlight = { enable = true }のように設定することで、プラグインが自動的にハイライトを有効化していたが、このような機能有効化のスイッチは削除された。新しいnvim-treesitterは、パーサーやクエリファイルを提供する「パーサーマネージャー」としての役割に特化し、ハイライト、インデント、折りたたみなどの各機能を実際に有効化するかどうかは、NeovimのコアAPIを使ってユーザー自身が責任を持って設定するようになったのだ。つまり、ハイライトの「電源スイッチ」は、ユーザーが自分で入れなければならなかったのだ。

この新しい理解に基づき、著者は新しい設定を構築した。まず、プラグインマネージャー(lazy.nvimなど)を使ってnvim-treesitterを「main」ブランチからインストールするように設定する。ここで重要なのは、build = ':TSUpdate'とすることで、プラグインがビルドされる際にパーサーが自動的にインストールまたは更新されるようにすることだ。そして、カスタムパーサーであるtree-sitter-unreal-cppも依存関係として指定する。

設定のコア部分は、Neovimのautocmd(自動コマンド)機能を使って実現される。TSUpdateというイベントが発生したときに実行されるコールバック関数を登録し、その中で、標準の「cpp」パーサーの定義を、自分のカスタムパーサー(https://github.com/taku25/tree-sitter-unreal-cppの特定のコミットリビジョン)で上書きするように設定する。この際、もしカスタムパーサーが標準C++の全構文を完全にカバーしていない場合、デフォルトのC++パーサーもハイライトに利用されるように設定できる(maintainers = {}をコメントアウトしないことで)。これにより、カスタムパーサーが提供するUnreal Engine特有のハイライトと、標準C++のハイライトが適切に共存できるようになる。

次に、実際にハイライトやインデントを有効にする設定だ。特定のファイルタイプ(C、C++、C#など)が開かれたときに発火するFileTypeイベントに対して、別のautocmdグループを作成し、コールバック関数を登録する。このコールバック関数の中で、vim.treesitter.start(args.buf)を呼び出して現在のバッファ(ファイル)でTree-sitterによるハイライトを明示的に開始させ、さらにvim.bo[args.buf].indentexpr = "v:lua.require'nvim-treesitter'.indentexpr()"を設定してTree-sitterベースのインデントを有効にする。

この新しい設定を適用した結果、Unreal Engineのカスタムハイライトはすべて復活し、LSP(Language Server Protocol)によるより高度なセマンティックトークン(コードの意味に基づいたハイライト)とも問題なく共存できるようになった。

今回の経験から得られる教訓は、プラグインが大幅な変更を行った場合、特に「main」ブランチのように最先端の開発ラインでは、古い知識が通用しないことがあるという点だ。重要なのは、プラグインの責任範囲がどのように変化したかを理解することだ。nvim-treesitterは、強力なパーサーとクエリを提供するツールマネージャーとなり、それをどのように、いつ活用するかは、Neovimのコア機能を使ってユーザーが能動的に設定する必要がある。常に最新のドキュメント(特にREADMEファイル)を確認し、新しい変更点を理解しようと努めることが、スムーズな開発環境の維持には不可欠だ。

関連コンテンツ

関連IT用語