コマンド
bcaは、ソースコードを解析して情報を抽出するためのさまざまなコマンドを提供します。各コマンドは、実行するタスクに固有のパラメーターを持つ場合があります。以下では、bca で利用できる主要なコマンドの種類を説明します。
インストール
bca コマンドラインツールは、pip でインストールできる wheel として提供されています。配布名は big-code-analysis-cliで、インストールされるコマンドは bca です — この 2 つは意図的に異なります(PyPI 上の bca という名前は無関係なプロジェクトのものであり、big-code-analysis は本プロジェクトのインポート可能な ライブラリ バインディングです):
pip install big-code-analysis-cli # PATH に `bca` コマンドをインストールします
bca --version
これにより、pip install ruff が ruff コマンドを提供するのと同じように、コンパイル済みの bca バイナリが PATH に配置されます — Rust ツールチェインは不要です。wheel には完全な all-languages 文法セットが含まれているため、すべての 対応言語 が追加設定なしで動作します。単一の py3-none-<platform> wheel が、そのプラットフォーム上のすべての CPython 3.x(および PyPy)をカバーします。ビルド済み wheel は Linux(manylinux_2_28 x86_64 / aarch64)、macOS(x86_64 / arm64)、Windows(x86_64)向けに提供されます。それ以外のプラットフォームでは pip はソースビルドにフォールバックし、その場合は Rust ツールチェインが必要です。
これはバイナリの CLI であり、インポート可能な Python バインディング(pip install big-code-analysis)とは別物です。その他のインストール方法 — Homebrew、.deb / .rpm / .apk パッケージ、ビルド済みリリースアーカイブ、cargo install big-code-analysis-cli — はリポジトリの README に記載されています。
wheel のビルドと公開のマトリクスは .github/workflows/python-cli-wheels.yml で定義されています。
終了コード
bca はすべてのサブコマンドで単一の終了コード規約に従うため、CI スクリプトは出力を検査せずにプロセスのステータスで分岐できます:
| コード | 意味 |
|---|---|
0 | 成功。 |
1 | ツールエラー — 不正なフラグ / しきい値 / glob 指定、読み取れない入力、またはパース失敗。使用方法エラー(未知のフラグ、不正なサブコマンド、clap に拒否された不正な --threshold 値)も含まれます。決して メトリクスのシグナルではありません。 |
2 | メトリクスゲート: check のしきい値を超過した、vcs commit --fail-above に違反した、または --exit-code 指定時の diff / diff-baseline がフィルター後の空でない差分を検出した場合。 |
3–5 | check --exit-codes=tiered のみ: 段階化された違反の重大度(回帰のみ / 混在 / ハード違反。tiered モードではコード 2 は新規のみを意味します)。 |
コード 2–5 はゲートシグナルであり、check、vcs commit --fail-above、およびオプトインの --exit-code フラグ指定時の diff / diff-baseline だけが発行します。これらはメトリクスの結果を報告するものであって、ツール自体の失敗ではありません。それ以外のすべてのサブコマンド — metrics、ops、report、diff、diff-baseline、exemptions、init など — は、成功時に 0、エラー時に 1 で終了します。1 はツールエラー専用であり — 使用方法エラーも含むため、フラグの打ち間違いがゲート帯域に入ることはありません — CI は常に「ゲートが回帰を検出した」(2–5)と「ツール自体がクラッシュした」(1)を区別できます。
読み取れない入力
ソースファイルを走査するすべてのサブコマンド — metrics、ops、report、functions、find、count、dump、exemptions、preproc、strip-comments、check、init(ベースラインを check 経由で生成します)、および diff --since — は、入力ファイルのいずれかが読み取れなかった場合に 1 で終了します。権限がない場合や、走査から読み取りまでの間にパスが消えた場合です。個々の失敗は error processing <path>: … として stderr に列挙され、続いて 1 行のサマリーが出力されます。
この規則が「出力がまったくない場合」ではなく「読み取り失敗が 1 つでもあった場合」なのは、欠落したファイルが結果からは見えないからです。部分的な metrics --output ドキュメントや report、count は完全なものに見えてしまいます。ファイルを失った diff --since の片側は、それを本来の I/O エラーではなく_追加_または_削除_として報告します。この失敗は終了コードでしか観測できないため、終了コードがそれを担う必要があります。
走査_中にストリーミングされた_出力は、チェックがその後に走るため、そのまま出力されます。したがって混在した実行でも、読み取れたファイルは表示されます — metrics / ops / dump / find / functions の stdout ツリーと、--output-dir のファイル単位のドキュメントです。
走査_後に組み立てられる_出力は完全に抑制されます。部分的なものと完全なものを区別できないからです。これは metrics --output / ops --output の集約ドキュメント、report ドキュメント、count の集計、preproc の JSON、および exemptions レポートに適用されます — いずれも出力も書き込みもされません。
開けないファイルがツリーに正当に含まれている場合は、--exclude で除外してください(あるいは --include でより狭い集合を指定します)。これらのフィルタで除去されたファイルは開かれないため、読み取り失敗にはなりません。
列挙できないディレクトリ
走査が「列挙」できないディレクトリは、同じ失敗が 1 段上で起きたものであり、同じ終了コード 1 を伴います。そのサブツリー全体は、どのファイルかが選択される前に解析対象の集合から脱落するため、下流のすべてのカウント — メトリクスドキュメント、count の集計、diff --since の片側、vcs rank のランキング — は、出力の何を見ても分からない量だけ不足します。bca check は最悪のケースです。読めなかったツリーに対してクリーンと報告するゲートは、合格したゲートと見分けがつきません。
列挙できなかった各エントリは stderr に bca: warning: skipping walk entry in … として警告され、1 つの不良ディレクトリがツリーの残りを巻き込まないよう走査は継続し、実行はサマリー行と終了コード 1 で終わります。
列挙できないと分かっているディレクトリを免除するには、ignore ファイル(.gitignore、.ignore)で名前を挙げるか、走査が到達しないよう --paths を絞ってください。ここでは --exclude は機能しません。読み取れない「ファイル」に対しては正しい答えですが、--exclude は走査が生み出したパスをフィルタリングするものであり、列挙できなかったディレクトリは何も生み出していません — 失敗は、フィルタが適用できるようになる前に起きています。
隣接する 2 つのケースは、設計上、致命的にはなりません。
- 不正な形式の ignore ファイル、またはその中のコンパイルできないパターン。 ウォーカーはこれらを同じチャネルで報告し、警告の形も同一ですが、これらが記述するのは走査が失ったファイルではなく、走査がどう「構成」されたかです。カウントされるのは基盤に I/O エラーを伴うエラーだけなので、
.gitignoreに紛れ込んだタイポがビルドを失敗させることはありません。 - 走査中に発見された壊れたシンボリックリンク。 通常ファイルでないという理由で除外され、エラーとして表面化することは一切ありません — 走査はリンクをたどらないため、意図的にシンボリックリンクを解決せず、報告すべきものが何もないのです。これを致命的として扱うと、ベンダリングされたツリー内の古いシンボリックリンクがハードな CI 失敗になってしまいます。
明示的に「名指しされた」パスは、この最後の点の例外であり、以前から存在する例外です。--paths はシンボリックリンクのシードを一度解決し、存在しないシード — 宙ぶらりんのリンクやタイポ — はそれ自体がエラーで、これも終了コード 1 です。
書き込めない出力
その鏡像も同じ規則であり、すべての出力経路に当てはまります。出力を書き込めなかった実行は 1 で終了します。これは、書き込めない --output-dir 配下のファイル別ドキュメントにも、stdout でのディスクフルにも当てはまります — dump のバナーとツリー、find のマッチ、strip-comments の書き換え済みソース、count の集計、preproc の JSON、そして vcs、vcs commit、vcs trend の単一ドキュメントレポートまで、あらゆるフォーマットで同様です。ファイル単位の失敗は stderr で名指しされ、サマリー行でカウントされます。走査後に組み立てられる出力は、オペレーティングシステムのエラーを直接報告します。
唯一の免除は、閉じられた下流のパイプです。bca dump | head は失敗ではなく日常的な操作であるため、BrokenPipe は握りつぶされ、実行はそれでも 0 で終了します。
フラグの位置と入力パス
ほとんどのサブコマンドは、解析対象の入力を末尾の位置引数パスとして読み取るため、一般的なケースは他のコードツール(tokei、cloc、scc、rg)と同じ書き方になります。例外は次のとおりです: report と vcs は --paths で入力を選択し、diff は 2 つの結果セットを比較し、init は --dir でディレクトリを対象にします。
bca metrics src/ # src/ ツリーを解析する
bca check src/ tests/ # 2 つのサブツリーをゲートする
bca find -t function_item . # 現在のツリー内のすべての関数を検索する
フラグは それを消費するサブコマンドにスコープされ、サブコマンドのトークンの後に 書く必要があります:
bca metrics --exclude '*.generated.rs' src/ # 正しい
bca --exclude '*.generated.rs' metrics src/ # エラー(終了コード 1)
どの位置でも受け付けられる汎用フラグは -w / --warnings と --report-skipped だけです。すべての入力選択フラグ(-p / --paths、-I / --include、-X / --exclude、-l / --language、--paths-from、--exclude-from、--no-ignore、--no-skip-generated、--no-config)、ウォーカー調整フラグ(-j / --jobs、--exclude-tests、--cyclomatic-count-try)、プリプロセッサフラグ(--preproc-data)、および出力フラグ(--color)は、それを読み取るサブコマンドのヘルプ内でグループ化されたセクション(Input selection / Walker tuning / Preprocessor / Output)に属します。あるサブコマンドが消費しないフラグをそのサブコマンドに渡すと、黙って無視されるのではなくハードな使用方法エラー(終了コード 1)になります — そのため bca vcs commit --exclude-tests と bca list-metrics --paths はどちらもエラーになり、bca list-metrics --help はウォーカーフラグを表示しません。
-p / --paths フラグは引き続き機能し、位置引数のパスと 和集合 になります。つまり bca metrics a.rs --paths b.rs は両方を走査します。find と count サブコマンドは、繰り返し指定できる -t / --type フラグでノード種別を受け取ります(そのため位置引数のスロットはパス用に空いています): bca find -t function_item -t struct_item src/。
メトリクス
メトリクスはソースコードに関する定量的な指標を提供し、次のことに役立ちます:
- 異なるプログラミング言語を比較する
- コードの品質に関する情報を提供する
- コードのどこが扱いにくいかを開発者に伝える
- 開発プロセスの早い段階で潜在的な問題を発見する
big-code-analysis は、プログラムのソースコードを起点にメトリクスを計算します。この種のメトリクスは 静的メトリクス と呼ばれます。
ノード
プログラムコードの構造を表現するために、bca は 抽象構文木(AST) を構築します。ノード はこの木の要素であり、言語に存在する任意の構文構造を表します。
ノードは次の用途に使えます:
- ソースファイルの構文構造を作成する
- 解析対象のコードに、ある言語構造が存在するかどうかを調べる
- 特定の種類の構造の数を数える
- ソースコード内のエラーを検出する
REST API
bca-web は REST API を提供するサーバーを実行します。これにより、ユーザーは HTTP 経由でソースコードを送信し、対応するメトリクスを JSON 形式で受け取れます。
生成コードのスキップ
生成されたバインディング(protobuf スタブ、OpenAPI クライアント、lex/yacc の出力、ビルドシステムの補助コード)は、誰もリファクタリングしないコードでメトリクスを水増しします。デフォルトでは、bca は各ファイルの先頭約 50 行 / 5 KiB を走査して生成コードマーカーを探し、一致したファイルをパース 「前に」 スキップします。そのため、スキップされたファイルに tree-sitter のパースコストはかかりません。
認識されるマーカー(大文字小文字を区別しません):
@generated— Facebook / Meta の慣習。buck2、rustfmt、prettier をはじめ、多くのコードジェネレーターも出力します。DO NOT EDIT— Go の// Code generated by … DO NOT EDIT.が標準形です。この語句単体でも広くコピーされています(Bazel、protoc、OpenAPI クライアント)。GENERATED CODE— Lizard のマーカーで、互換性のために認識されます。
マーカー語句がファイル本体の深い位置(走査ウィンドウの外)にのみ現れる場合、スキップは 発動しません — 検出器は意図的にファイルヘッダーだけを見ます。
このスキップは bca metrics、bca report、およびしきい値エンジンに一律に適用されます。
フラグ
--no-skip-generated— 自動スキップを無効にし、以前の動作(すべてのファイルをパースする)に戻します。--report-skipped— 検出器が除外した各ファイルについてskipped (generated): <path>を stderr にログ出力します。これにより除外を監査でき、ファイルが誤って生成コード扱いされていた場合は明示的な include を追加できます。
さらに bca check は、ゲート実行で検出器がファイルを除外した場合に 1 行のサマリーを stderr に出力します(bca: 1 file not checked (1 generated) — pass --report-skipped to list them)。また、--strict プロファイルは検出器そのものを無効にします。マーカーはテスト対象のブランチが管理するコンテンツなので、プルリクエストのゲートでは、それによって検査対象のファイル集合が狭められるべきではありません。
.gitignore の尊重
--paths にディレクトリが渡されると、bca はデフォルトで .gitignore を考慮して走査します。次のいずれかに一致するファイルは、パース前にスキップされます:
- 走査対象ツリー内の
.gitignoreファイル。 .ignoreファイル(ripgrep /fdの慣習)。.git/info/exclude。- グローバル gitignore(
~/.config/git/ignore、またはcore.excludesFileが指す先)。 - 起点の祖先ディレクトリにある
.gitignoreファイル(そのため、プロジェクトルートからbca metrics src/を実行すると、プロジェクト最上位の.gitignoreが反映されます)。
ウォーカーは、チェックインされた git リポジトリの外でも .gitignore を尊重します。そのため、.gitignore ファイルを含む展開済みのソース tarball も、git clone した直後と同じ扱いになります。
隠しファイル(ベース名が . で始まるもの)は走査中に除外され、以前の動作と一致します。
明示的なパスはフィルターを迂回する
名前で渡されたファイル — --paths、--paths-from、または末尾の位置引数のパス経由 — は、プロジェクトの ignore ルールの対象であっても常に解析されます。これにより、git diff --name-only 形式のパイプラインから bca metrics --paths-from - を安全に実行でき、ワイルドカードの ignore ルールにたまたま該当するファイルを失うことがありません。
この上書きは意図的なもので、rg や fd が適用しているのと同じ規則です。あなたが名指ししたパスは直接の要求です。これは走査が参照するすべての拒否セット — .gitignore とその仲間、-X / --exclude、--exclude-from、.bcaignore、マニフェストの exclude リストのいずれにも — 及びます。rg --glob '!x.txt' pattern x.txt が x.txt を検索するのは、まさにこの理由からです。
これには 2 つの境界があります。
-I/--includeは引き続き適用されます。 許可リストは、名指しされたファイルの「どれ」を解析するかを絞り込むため、bca metrics -I '*.rs' notes.mdは何も解析しません。上書きされるのは拒否セットだけです。[check] excludeは引き続き適用されます。 ゲート免除セット(--check-exclude/--check-exclude-from、またはbca.tomlの[check]配下のexclude)は走査フィルタではなく、ファイルではなく「違反」を落とすものなので、明示的なパスでも生き残り、発動時にはbca: skipped N violations via [check.exclude]と報告します。#1164 がオープンな間は注意点が 1 つあります。明示的に名指しされたパスに対しては、これらのグロブがマニフェストルートではなく作業ディレクトリを基準に解決されるため、bcaはbca.tomlのあるディレクトリから実行してください — CI とエージェントフックはすでにそうしています。
頼るべきはこの 2 点目です。ウォーカーの除外は何が解析されるかを形作り、チェックの除外は何がゲートされるかを形作ります。しきい値ゲートから恒久的に外しておきたいもの — 開発ツール、測定はしたい生成コード、活発に書き換え中のサブツリー — は [check] exclude に属します。パスを 1 つずつ名指しする呼び出し側は、設計上ウォーカーの除外をバイパスするからです。ファイル単位の呼び出し側は仮定の話ではありません。エージェントフィードバックフックがすべての編集で使っているのが、まさにこの形です。
明示的に名指しされたパスが実際にウォーカーの除外を上書きした場合、bca は stderr でそのことを伝え、該当するグロブを名指しします。
bca: warning: utils/gate.py matches an exclude pattern (./utils/**) but was named explicitly; analyzing anyway
パス探索フラグ
--no-ignore— ディレクトリシードを展開する際の.gitignore/.ignore/ グローバル gitignore の解釈を無効にします。bca checkは、ignore ルールによってゲート実行から除外された分析可能なファイルを not-checked サマリーで数え、除外された各エントリを--report-skippedで一覧表示し(note: skipped (ignored): <path>、note: skipped (ignored directory): <path>)、--strictプロファイルではこの解釈自体を無効にします。テスト対象のブランチにコミットされた ignore ファイルが、検査対象のファイル集合を黙って狭めてしまうためです。--paths-from <FILE>— 改行区切りの入力パスを<FILE>から読み取ります。<FILE>が-の場合は stdin から読み取ります。--pathsの値があれば和集合として結合されます。-Iの glob は引き続き適用されますが、-Xの glob は、明示的なパスはフィルタを迂回するのとおり、ファイルを直接名指しするエントリには及びません。空行はスキップされ、#は(コメントではなく)パスの文字として扱われます。文字どおり-という名前のファイルを渡すには./-と書きます。--exclude-from <FILE>— 改行区切りの--excludeglob パターンを<FILE>から読み取ります。<FILE>が-の場合は stdin から読み取ります。パターンはインラインの--exclude/-Xの値と和集合として 1 つの拒否セットにまとめられ、順序は関係ありません。.gitignore形式です: 空行と、最初の非空白文字が#の行はスキップされ、先頭の UTF-8 BOM は取り除かれます。慣習としては、.gitignore/.dockerignoreに倣ってリポジトリルートに.bcaignoreを置きます。文字どおり-という名前のファイルを渡すには./-と書きます。