AIはどうやってコードを「理解」するのか — LSP・AST・コードグラフの仕組みと実践

# AIはどうやってコードを「理解」するのか — LSP・AST・コードグラフの仕組みと実践
「AIはコードを本当に理解しているのか?」
AI開発ツールを使い始めた頃、こんな疑問を持ったことがある人は多いはずだ。Copilotが補完してくれるとき、Claude Codeがバグを直してくれるとき、あのAIは何を見て、何をもとに判断しているのだろう。
この問いに、近年いくつかの答えが出てきた。LSP(Language Server Protocol)、AST(抽象構文木)、そしてコードグラフ。これらの技術が組み合わさることで、AIのコー ド理解は「テキストのパターンマッチング」から「構造的な意味の把握」へと進化しつつある。
今回はこの変化を、実際のツールや数字を交えながら整理してみる。
AIがコードを「読む」とはどういうことか
まず、AIがコードをどう扱っているかを整理しよう。
旧来のAIコードアシスタントの多くは、本質的にはテキスト検索の延長だった。ファイルを開いて文字列を検索し、パターンにマッチする箇所を返す。それに確率的な補完能力を加えたものが、初期のAIコーディングツールの正体だ。
この方式には限界がある。コードは「文字列」ではなく「構造」だからだ。
例えば、`getUserData` という関数がどこから呼ばれているか調べるとき、テキスト検索では:
- コメントの中の `getUserData` も引っかかる
- 変数名として使われている箇所も拾う
- 実際の呼び出しとそうでないものを区別できない
一方、コードの構造を理解しているツールなら:
- 関数呼び出しと変数宣言を区別できる
- 継承・インターフェース実装の関係も把握できる
- 依存関係のグラフ をたどれる
この差が、AIのコード理解の「深さ」を決める。
テキストから構造へ — ASTとTree-sitterの役割
コードの構造を理解するための基礎技術がAST(Abstract Syntax Tree: 抽象構文木)だ。
ASTは、ソースコードを「木構造」で表現したもの。関数定義、変数宣言、条件分岐、ループ — それぞれがノードとして表現され、親子関係で繋がっている。
例えば、こんなコードがあったとする:
def greet(name):
return f"Hello, {name}"ASTで表現すると:
- `FunctionDef`(関数定義)
- `name: "greet"`
- `args: ["name"]`
- `body: Return`
- `value: JoinedStr(f文字列)`
テキストとしては「文字列の塊」でも、ASTとして見ると「引数を受け取って文字列を返す関数」という意味が明確になる。
このASTを効率的に生成するのがTree-sitterというパーサーライブラリだ。Go、Python、TypeScript、Rust、Javaなど66以上の言語に対応しており、コードを静的に解析してASTを生成できる。
コードグラフ — 依存関係を"地図"にする
ASTが「1つのファイルの構造」を表現するなら、コードグラフは「ファイルをまたいだ依存関係全体の地図」だ。
ノード(点)= 関数・クラス・モジュール・変数
エッジ(線)= 呼び出し関係・インポート関係・継承関係
この地図があると、AIは「ある関数を変更したとき、どこに影響が出るか」を追跡できる。
最近注目を集めたGitNexusは、このコードグラフをWebAssemblyとMCP(Model Context Protocol)で実装したツールだ。サーバー不要でクライアントサイドのみで動作し、GitHubのリポジトリを解析してコードグラフを構築する。GitHubで17,000以上のスターを集めており、開発者コミュニティでの関心の高さを示している。
Tree-sitterベースのコードグラフ(Codebase-Memoryというプロジェクトの研究)では、ファイルを逐次探索するエージェントと比較して:
- 回答精度: 83%の正答率
- トークン効率: 10分の1のトークン数
という結果が報告されている。コードグラフを使うことで、AIは「必要な情報 に最短距離でたどり着ける」ようになる。
LSP — IDEと同じレベルでコードを理解する
ASTとコードグラフが「静的解析」によるコード理解なら、LSP(Language Server Protocol)はさらに動的な、IDE水準の理解を提供する。
LSPは、もともとVS Codeのために設計されたプロトコルで、エディタとLanguage Serverの間でコードに関する情報をやり取りするための仕様だ。定義へのジャンプ、型情報の取得、参照箇所の一覧 — 普段IDEで使っているあの機能が、LSPによって実現されている。
Claude CodeはこのLSPを活用できる。
具体的な差は数字に出る。ある計測では:
- テキスト検索(grepベース)でコードの全呼び出し箇所を探す: 約45秒
- LSP(`find_references`)で同じことをする: 約50ミリ秒
約900倍の速度差だ。そして速いだけでなく、精度も高い。テキスト検索ではコメントやドキュメント内の誤ヒットが混在するが、LSPは「実際のコード参照」だけを返す。
実際の開発現場での使い分け
これらの技術は、それぞれ得意・不得意がある。
| 技術 | 得意なこと | 向かないこと |
|---|---|---|
| テキスト検索 | 素早い全体スキャン、設定ファイルの検索 | 意味的な関係の把握 |
| AST/Tree-sitter | 言語構造の解析、静的コード変換 | 実行時の動的な関係 |
| コードグラフ | 依存関係の可視化、影響範囲の把握 | リアルタイムの動作把握 |
| LSP | 型情報・参照・定義の正確な取得 | LSP非対応言語や設定コスト |
アツメルの開発現場でも、Claude Codeと組み合わせて使っている。コ ードの全体像を把握するときはグラフ的な理解を使い、特定の関数の定義や型を確認するときはLSPを活用する。
なぜ仕様駆動開発(SDD)との相性がいいか
コード構造の理解が深まると、AIは「書かれたコードが仕様と一致しているか」を検証できるようになる。これが、アツメルが推進する仕様駆動開発(SDD)との親和性が高い理由だ。
SDDでは、仕様を構造化されたドキュメントとして管理する。AIがASTやコードグラフでコードを理解し、その仕様ドキュメントと照合することで:
- 「この関数の実装が、仕様で定義された前提条件を満たしているか」
- 「仕様変更の影響が、どのモジュールに波及するか」
といった確認が自動化できるようになる。
AI開発ツールが上流(要件定義・仕様設計)に向かっているのは、単なる機能拡張ではない。コードを「構造として理解する」技術の成熟が、その前提として必要だったからだ。
まとめ
AIのコード理解は、3つの層で進化している。
- テキスト層: grep・検索。速いが意味を理解しない
- 構造層: AST・Tree-sitter・コードグラフ。ファイル間の依存関係を把握
- 意味層: LSP・型システム。IDEと同等の精度でコードの意味を理解
現時点では、この3つを組み合わせることで「AIが本当に役に立つ」レベルのコード理解が実現できる。GitNexusのような新しいツールの登場が示すのは、「AIのコーディング支援」が「テキスト補完」から「コード理解」へと移行しつつあるという事実だ。
開発現場でAIを使い倒している私たちとしては、この変化を単なる技術トレンドとしてではなく「開発プロセス全体の再設計」のチャンスとして捉えている。AIがコードを深く理解するようになればなるほど、仕様と実装の距離は縮まる。それが最終的に、より良いソフトウェア開発につながると考えている。
AIを活用した開発プロセスの見直しに興味がある方は、ぜひアツメルまでご相談ください。仕様駆動開発の実践から、AIエージェント活用まで、一緒に考えます。



