SARIF 出力

bca.to_sarif(result, *, thresholds=None) は、分析結果(またはそのイテラブル)を SARIF 2.1.0 JSON ドキュメントとしてレンダリングし、GitHub Code Scanning をはじめとする任意の SARIF コンシューマへそのままアップロードできる形にします。出力は bca check --report-format sarif を支えるのと同じ Rust ライターが生成するため、スキーマ URL、ツールドライバの名前とバージョン、ルール記述は CLI とバイト単位で一致します。

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
  • そのような dict や bca.AnalysisFailure インスタンスを生成する任意のイテラブル(bca.analyze_batch の戻り値そのままの形)。AnalysisFailure エントリは黙ってスキップされます。これは分析できなかったファイルを表すものであり、検出結果ではないためです。

しきい値

受け付けられるしきい値名は、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(デフォルト)と thresholds={} はどちらも、空の results 配列と rules 配列を持つ整形式の SARIF ドキュメントを生成します。これは CLI の方針と一致します。すなわち組み込みのデフォルトしきい値は存在せず、各 check 実行が自前の上限を指定します。

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 アラートへのアップロードはこのアクションが担います。

「Unit」の検出結果の意味

to_sarif は、自身の値が上限を超えているすべてのスペース — ファイル単位(Unit)、各コンテナ、各リーフ関数・クロージャ — で検出結果を出力し、bca check --report-format sarif と正確に一致します。ほとんどのメトリクスでは、スペースの JSON 見出し値がそのままそのスペース自身の値です。サブツリー集約型の 4 つのメトリクス — cyclomaticcyclomatic.modifiedcognitiveabc — はこれに加えて、子スペースを合算した sum / magnitude を公開しますが、バインディングは代わりにスペースごとの value フィールドを読むため、より大きな集約値に惑わされることなく、内部スペースでの超過(たとえば、ネストしたクロージャは超過していないのに関数自身の複雑度が超過している場合)を報告できます。value フィールドが存在する以前は、バインディングは集約値しか読めなかったため、この 4 メトリクスをリーフスペースでしか出力できず、CLI が報告する真の内部超過を見逃していました(#958)。

Unit の検出結果には logicalLocations: [{"fullyQualifiedName": "<file>"}] が付きます。名前のない非 Unit スペース(まれなパース失敗のケース)には "<unnamed>" が付きます。いずれも CLI の function_token プレースホルダーと一致します。

関連項目

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