Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

AST クエリ

パース済みの構文木を直接扱うレシピです。ノード型の検索、そのカウント、ツリーのダンプを行います。

Library-side equivalents. Every recipe below has an in-process Rust counterpart in Walking the AST directly. Use that when shelling out per file is too slow or when you want to compose metrics with custom AST analysis in one parse.

コミット前にパースエラーを検出する

Tree-sitter exposes a synthetic ERROR node anywhere it could not parse. Use find to surface them:

bca find \
    --include "*.rs" \
    --paths "$PWD" \
    -t ERROR

1 回の指定につきグロブ 1 つ。 --include と --exclude は出現ごとにちょうど 1 つの値を取ります。複数のグロブにはフラグを繰り返してください(--include "*.rs" --include "*.py")。後続の位置引数パスが飲み込まれることはありません。= 形式(--include="*.rs")も使えます。

クリーンな実行は何も出力しません。これを pre-commit フックに組み込めば、構文的に壊れたファイルがステージされたときに素早く失敗させられます。

特定の構文要素を数える

count は繰り返し可能な -t/--type フラグで 1 つ以上のノード型を受け取り、合計を報告します。たとえば Rust プロジェクト全体で if、for、while の構文を数えるには:

bca count \
    --include "*.rs" \
    --paths src/ \
    -t if_expression -t for_expression -t while_expression

正確なノード型名は下層の tree-sitter 文法に由来します。見つけるには、小さなサンプルファイルの AST をダンプし(下記参照)、ツリーからノード名を読み取ってください。

Rust クレート内のすべての unsafe ブロックを見つける

bca find \
    --include "*.rs" \
    --paths src/ \
    -t unsafe_block

各マッチはファイルパスとノードの行範囲を出力します。

ファイルの AST をダンプする

メトリクスがなぜその値になったのかを理解したり、find / count に必要な tree-sitter ノード名を発見したりするのに便利です:

bca dump --paths src/lib.rs

ダンプを特定の関数やブロックに絞るには、--line-start と --line-end フラグで行範囲を追加します(dump サブコマンドの後に置く必要があります):

bca dump \
    --paths src/lib.rs \
    --line-start 42 --line-end 88

--line-start / --line-end apply to dump and find, so the same range scopes a search to a single function:

bca find \
    --paths src/lib.rs \
    --line-start 42 --line-end 88 -t return_expression

短縮形の --ls / --le は非推奨エイリアスとして残っていますが、次のメジャーリリースで削除される予定です。

すべての関数・メソッドを一覧する

人間が読むための簡単なインベントリには:

bca functions \
    --include "*.rs" \
    --paths src/

The output is a tree per file: an In file … header followed by an indented row per function with name and line span. It is meant for reading, not parsing.

For tooling that needs a structured inventory (coverage mapping, documentation generation, code-owner reports), use the JSON metrics output instead and walk .spaces[] recursively with jq, taking entries whose kind is function:

bca metrics \
    --include "*.rs" \
    --paths src/ \
    -O json \
  | jq -c '
      . as $root
      | def funcs: if .kind == "function" then [.] else [] end
                   + (.spaces // [] | map(funcs) | add // []);
      funcs[] | {file: $root.name, name, start_line, end_line}
    '

This emits one JSON object per function, ready to pipe into downstream tooling.