文法の更新

各プログラミング言語は、その構文と意味 — いわゆる言語の文法 — を抽出するためにパースされる必要があります。big-code-analysis では、対応プログラミング言語ごとに個別の文法一式を提供している tree-sitter をパースライブラリとして使用しています。しかし文法は静的な一枚岩ではなく、時間とともに変化し、バグの影響を受けることもあるため、折に触れて更新する必要があります。

現時点では、操作の自動化に bash スクリプトを使用しているため、文法をネイティブに更新できるのは LinuxMacOS システムのみですが、これらのスクリプトは WSL を使えば Windows でも実行できます。

big-code-analysis では、サードパーティの文法と内部の文法の両方を使用しています。前者は crates.io で公開され外部の開発者によって保守されているもので、後者は Firefox で使用される一部言語の変種を扱うためにプロジェクト内で考案・定義されたものです。以下のセクションで両方の更新方法を説明します。

サードパーティの文法

Cargo.tomlenums/Cargo.toml の文法バージョンを更新します。以下は tree-sitter-java 文法の例です

tree-sitter-java = "x.xx.x"

ここで x は数字を表します。

./recreate-grammars.sh を実行して、すべての文法の構造とデータを再作成・更新します

./recreate-grammars.sh

上記スクリプトの実行が完了したら、文法の変更によって発生した失敗テストや問題があれば、それらをすべて修正する必要があります。

変更をコミットして、新しいプルリクエストを作成します

内部の文法

内部文法の package.json ファイルにある tree-sitter-cli のバージョンを更新し、同じディレクトリで npm install --package-lock-only --ignore-scripts を実行してコミット済みの package-lock.json を更新し、両方のファイルを一緒にコミットします。再生成スクリプトは npm ci でインストールを行うため、ロックファイルが存在しない場合や package.json と同期していない場合には明示的に失敗します。これにより、すべての再生成がハッシュ検証済みかつバイト単位で再現可能に保たれます(OpenSSF Scorecard の Pinned-Dependencies)。

5 つのベンダリングされた文法は bca-tree-sitter-* 名前空間で公開されます(改名の理由は RELEASING.md を参照)。ただし、利用側の呼び出し箇所は Cargo の package = ... エイリアスを介して引き続き tree-sitter-<lang> として参照します。文法の更新だけではリーフのバージョンは上がりません — このリポジトリのすべてのクレートはワークスペース全体で 1 つのバージョンを共有しており、リーフを親と食い違わせてバージョンを上げることは許可されていません(RELEASING.md の「Lockstep version policy」を参照)。パーサーテーブルを再生成し、生じたテストスナップショットのドリフトを受け入れ、現在のバージョンのまま変更を出荷してください。次のワークスペースリリースが、次のタグが宣言する共有バージョンで新しい文法を取り込みます。

再生成に加えて tree-sitter の「ランタイム」依存関係の更新も必要な場合は、リーフの Cargo.toml 内の dev-dependency 行を更新します。

[dev-dependencies]
tree-sitter = "=x.x.x"

[package] name = "bca-tree-sitter-<lang>"[package] version[lib] name = "tree_sitter_<lang>" はそのままにしてください — [lib] での改名の仕掛けが Rust のインポートパスを安定に保っており、バージョン行はリリース時のロックステップバンプで管理されます。

適切なスクリプトを実行し、すべてのファイルとスクリプトを再作成・更新して文法を更新します。

tree-sitter-ccommenttree-sitter-preproc の場合は、./generate-grammars/generate-grammar.sh に続けて文法名を指定して実行します。以下は引き続き tree-sitter-ccomment 文法を使った例です

./generate-grammars/generate-grammar.sh tree-sitter-ccomment

一方、tree-sitter-mozcpptree-sitter-mozjs には、それぞれ専用のスクリプトを使用します。

tree-sitter-mozcpp の場合は、次を実行します

./generate-grammars/generate-mozcpp.sh

tree-sitter-mozjs の場合は、次を実行します

./generate-grammars/generate-mozjs.sh

5 番目のベンダリング文法である tree-sitter-tcl には再生成スクリプトがありません。事前生成されたパーサーソースのみをベンダリングしている(grammar.js がない)ため、更新する際はローカルで tree-sitter generate を実行するのではなく、アップストリームプロジェクトから生成済みの src/ を再ベンダリングします。

上記スクリプトの実行が完了したら、文法の変更によって発生した失敗テストや問題があれば、それらをすべて修正する必要があります。

変更をコミットして、新しいプルリクエストを作成します