SARIF 出力
bca.to_sarif(result, *, thresholds=None) renders an analysis result (or an iterable of them) into a SARIF 2.1.0 JSON document, ready for upload to GitHub Code Scanning or any other SARIF consumer. The output is produced by the same Rust writer that backs bca check --report-format sarif, so the schema URL, tool driver name / version, and rule descriptions match the CLI byte-for-byte.
Findings match in order as well as in content. Both surfaces sort their findings by path, then start line, then metric name — the order bca check applies after its walk — and findings tying on all three keep the depth-first source order of the space tree. For the same files and thresholds the two results arrays therefore line up entry for entry against bca check --no-suppress. to_sarif compares raw metric values, so it applies none of the in-source suppression markers bca check honours by default (each marked space keeps its suppressed key, for a caller that wants to filter), no baseline, and no [check] exclude globs.
"The same files" means a unique file set. The CLI folds repeated path seeds together, so bca check -p a.py -p a.py analyses a.py once and emits one finding per breach. analyze_batch instead returns one result per input, and to_sarif renders every result it is handed, so to_sarif(analyze_batch([a, a]), ...) emits each finding twice. Deduplicating in the binding would be wrong — two distinct results may legitimately share a name, since analyze_source takes the caller's — so hand to_sarif a unique file set when comparing the two documents positionally.
Examples on this page import the package as bca (import big_code_analysis as bca). A bare bca in a shell command is the CLI binary.
def run(
paths: Iterable[Path],
sarif_path: Path,
thresholds: Mapping[str, float],
) -> str:
"""``paths`` を分析し、SARIF ドキュメントを ``sarif_path`` に書き込む。
レンダリング済みの SARIF JSON を返すため、呼び出し側(やテスト)は
ファイルを読み直さずに内容を検査できる。
"""
batch = bca.analyze_batch(paths)
sarif = bca.to_sarif(batch, thresholds=dict(thresholds))
sarif_path.parent.mkdir(parents=True, exist_ok=True)
sarif_path.write_text(sarif, encoding="utf-8")
print(f"wrote {sarif_path} ({len(sarif.encode('utf-8'))} bytes)")
return sarif
to_sarif は次を受け付けます。
bca.analyzeまたはbca.analyze_sourceが返す単一のdict。- Any iterable yielding such dicts,
bca.AnalysisFailureinstances, and/orNone(the natural shape ofbca.analyze_batch's return value).AnalysisFailureandNoneentries are skipped silently — they represent files for which no record was emitted, not findings. - A scalar
None, the documented return ofbca.analyzefor a skipped file; it yields an empty SARIF run.
しきい値
受け付けられるしきい値名は、big-code-analysis-cli/src/thresholds.rs にある CLI の EXTRACTORS テーブルと一致します。
cognitive,cyclomatic,cyclomatic.modifiedhalstead.volume、halstead.difficulty、halstead.effort、halstead.time、halstead.bugsloc.sloc、loc.ploc、loc.lloc、loc.cloc、loc.blanknom,tokens,nexits,nargsmi.original、mi.sei、mi.visual_studioabc,wmc,npm,npa
未知の名前に対しては、受け付け可能な名前の一覧を含む ValueError が送出されるため、タイポは黙って空の SARIF run を生成するのではなく、即座に失敗します。
thresholds=None (the default) and thresholds={} both produce a well-formed SARIF document with empty results and rules arrays. This matches bca check, which applies no implicit limits: every run supplies its own, from --threshold or a bca.toml (which bca init scaffolds with a starting table).
GitHub Code Scanning へのアップロード
# .github/workflows/code-scanning.yml(抜粋)
- name: Compute metric SARIF
run: |
python - <<'PY'
import big_code_analysis as bca
with open("paths.txt", encoding="utf-8") as paths_fh:
results = bca.analyze_batch(paths_fh.read().splitlines())
with open("metrics.sarif", "w", encoding="utf-8") as fh:
fh.write(bca.to_sarif(results, thresholds={"cyclomatic": 15}))
PY
- name: Upload to Code Scanning
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: metrics.sarif
アップロード用アクションのドキュメントは github/codeql-action/upload-sarif にあります。バインディングは呼び出しごとに 1 つの SARIF run を生成し、リポジトリの Code Scanning アラートへのアップロードはこのアクションが担います。
Which spaces produce findings
to_sarif emits a finding at every space — the file unit, each container, and each leaf function or closure — whose own value breaches its limit, exactly matching bca check --report-format sarif. For most metrics the JSON headline at a space already is that space's own value. The five subtree-aggregate metrics — cyclomatic, cyclomatic.modified, cognitive, abc and nargs — additionally expose a sum / magnitude / total rolled up across child spaces; the binding reads their per-space value field instead, so it reports an interior breach (for example a function whose own complexity breaches even though a nested closure's does not) without being fooled by the larger aggregate. For nargs that means a function is gated on its own parameter list, exactly as bca check has been since #1196; a closure with its own space produces its own finding rather than inflating the enclosing function's.
Unit findings carry logicalLocations: [{"fullyQualifiedName": "<file>"}]. Every other space carries its qualified symbol. Within that symbol, a closure/lambda (the <anonymous> name every grammar emits) and the None-name parse-failure case both collapse to <anon@L{start_line}>, matching the CLI's space_segment.