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.AnalysisFailure instances, and/or None (the natural shape of bca.analyze_batch's return value). AnalysisFailure and None entries are skipped silently — they represent files for which no record was emitted, not findings.
  • A scalar None, the documented return of bca.analyze for a skipped file; it yields an empty SARIF run.

しきい値

受け付けられるしきい値名は、big-code-analysis-cli/src/thresholds.rs にある CLI の EXTRACTORS テーブルと一致します。

  • cognitive, cyclomatic, cyclomatic.modified
  • halstead.volumehalstead.difficultyhalstead.efforthalstead.timehalstead.bugs
  • loc.slocloc.plocloc.llocloc.clocloc.blank
  • nom, tokens, nexits, nargs
  • mi.originalmi.seimi.visual_studio
  • abc, 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.

関連項目

  • バッチ処理to_sarif への入力イテラブルの自然な供給源です。AnalysisFailure エントリは黙ってスキップされます。
  • メトリクスの選択 — しきい値名は metrics= とは独立した閉じた集合です。メトリクスの組を狭く要求しつつ、外したメトリクスのしきい値でゲートすると、空の SARIF run になります。
  • エラー処理 — 不正な呼び出し側入力に対して to_sarif が送出する型付き例外(TypeError / ValueError)。