AST queries
Recipes that work with the parsed syntax tree directly: searching for node types, counting them, or dumping the tree.
Library-side equivalents. Every recipe below has an in-process Rust counterpart in Walking the AST directly — useful when shelling out per file is too slow or when you want to compose metrics with custom AST analysis in one parse.
Detect parse errors before committing
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
One glob per occurrence.
--includeand--excludetake exactly one value each time they appear; repeat the flag for multiple globs (--include "*.rs" --include "*.py"). A positional path that follows is never swallowed. The=form (--include="*.rs") also works.
A clean run prints nothing. Wire this into a pre-commit hook to fail fast when a syntactically broken file is staged.
Count specific syntactic constructs
count takes one or more node types via the repeatable -t/--type
flag and reports the totals. For example, to count if, for, and
while constructs across a Rust project:
bca count \
--include "*.rs" \
--paths src/ \
-t if_expression -t for_expression -t while_expression
The exact node-type names come from the underlying tree-sitter grammar. To discover them, dump the AST of a small sample file (see below) and read the node names off the tree.
Find all unsafe blocks in a Rust crate
bca find \
--include "*.rs" \
--paths src/ \
-t unsafe_block
Each match prints the file path and the line range of the node.
Dump the AST of a file
Useful for understanding why a metric came out the way it did, or for
discovering the tree-sitter node names you need for find / count:
bca dump --paths src/lib.rs
To narrow the dump to a specific function or block, add line bounds
with the --line-start and --line-end flags (they must follow the
dump subcommand):
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 can be used to scope a search to a single function:
bca find \
--paths src/lib.rs \
--line-start 42 --line-end 88 -t return_expression
The short --ls / --le spellings remain as deprecated aliases and
are slated for removal in the next major.
List every function or method
For a quick human-readable inventory:
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 intended 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, 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 and is safe to pipe into downstream tooling.