Skip to content

Instantly share code, notes, and snippets.

@riseshia
Created March 21, 2026 10:14
Show Gist options
  • Select an option

  • Save riseshia/6ba6d1dd6146517c92823b92c2241cdb to your computer and use it in GitHub Desktop.

Select an option

Save riseshia/6ba6d1dd6146517c92823b92c2241cdb to your computer and use it in GitHub Desktop.
軽量型情報 LSP の開発 - 最終報告

TypeGuessr プロジェクト最終報告

https://github.com/riseshia/type-guessr で実装を進めております。

1. プロジェクト現況サマリー

Phase サマリー
Phase 1: 基本機能 TupleType実装やタイプ変数へのサポート、大規模プロジェクトでの安定性向上。
Phase 2: ヒューリスティック推論 メソッド集合パターン改善、duck typing精度向上、変数名ベースは見送り
Phase 3: DSL対応 ActiveRecord DSL型推論を独自実装(検証245件中175件パス、71.4%)

2. 中間報告からの主な進捗

2.1 パフォーマンス改善(高優先度課題の解決)

中間報告時点での最大の課題であった初期インデックシングの性能を大幅に改善しました。

起動速度の変化

ruby-lspはindexing files...が出ている間を計測しています。type-guessrはruby-lspの拡張として実装しているため、ruby-lspのインデックスタイム込みでの計測です。

巨大Railsアプリケーション(LOC > 100k)基準:

構成 起動時間
type-guessrなし(ruby-lsp only) 11秒
type-guessrあり(中間報告時) 41秒
type-guessrあり(現在、キャッシュなし) 30秒
type-guessrあり(現在、キャッシュあり) 24秒

type-guessr自体のリポジトリ基準:

構成 起動時間
type-guessrなし(ruby-lsp only) 5秒
type-guessrあり(中間報告時) 15秒
type-guessrあり(現在、キャッシュなし) 9秒
type-guessrあり(現在、キャッシュあり) 8秒

メモリ使用量の変化

初期インデックシング終了後に測定しています。

巨大Railsアプリケーション(LOC > 100k)基準:

構成 メモリ使用量
type-guessrなし(ruby-lsp only) 1.15 GB
type-guessrあり(中間報告時) 2.84 GB
type-guessrあり(現在) 1.85 GB

type-guessr自体のリポジトリ基準:

構成 メモリ使用量
type-guessrなし(ruby-lsp only) 295.1 MB
type-guessrあり(中間報告時) 832.1 MB
type-guessrあり(現在) 587.1 MB

主な施策:

  1. gemのタイプシグネチャキャッシュの導入 — gem由来の型情報をファイルキャッシュに保存し、2回目以降の起動・推論を高速化
    • これは gem の実装および推論結果は基本変更されない、という前提でやっています
  2. Unguessedタイプの導入により遅延処理 — gem由来のメソッドを即座に型表現を用意せず、実際にhoverされた時点で遅延パース & 推論する仕組み。
    • 起動時のIRオブジェクト生成を削減しGC負荷を軽減
    • トレードオフとしては初期推論速度を犠牲にしていますが、それを上記のキャッシュで抑えていくという方針です
  3. メソッドから定数の逆引き辞書生成 — duck typing候補検索をO(n)からO(1)に改善。大規模プロジェクトでの推論速度に寄与
  4. 推論深度制限(MAX_DEPTH=50) — 大規模gemメソッドの再帰的推論によるスタックオーバーフローを防止

2.2 型システムの拡充

中間報告で未実装だったTupleTypeを実装し、Phase 1の完成度を向上させました。比較的わかりやすい対応だと以下があります。

  • TupleType — 配列リテラルの位置ごとの型を保持(最大8要素)。[1, "hello"][Integer, String]
  • OrNode|| および ||= 演算子の型推論。truthiness判定による型の絞り込み
  • ガード節型ナローイングreturn unless x パターンでfalsyな型を除去
  • MultiWriteNode — 多重代入の型推論対応
  • クラスレベルの型変数のサポート — 今までだとメソッドシグニチャーレベルしか対応してなかったが、 ActiveRecord などのサポートのために必要だったので対応

2.3 Rails DSL型推論の実装

提案書のPhase 3で予定していたDSL対応として、gem_rbs_collectionやrbs_railsが生成する型情報に依存する方式も検討しましたが、それでは type-guessrとしての差別性がなくなるし、単純に楽して型の情報を得たい、というモチベーションにそぐわないため、ActiveRecordのDSLが動的に生成するメソッドに対する型推論を独自対応しました。具体的には ActiveRecord が提供するメソッド一覧に対して type-guessr 側から ActiveRecord::Base を継承しているクラスであれば DSL や継承により発生するクラスメソッド・インスタンスメソッドをインデックスに登録する形です。なおモデルのカラムに関しては ruby-lsp-rails の力を借りて取得する形になっています。

対応済みのものとしては

  • モデルのカラムの型情報の取得
  • ActiveRecord::Base の継承で発生する各種のメソッドの型シグネチャー対応
  • アソシエーションやスコープによるメソッド生成

対応がまだできないものに関しては

  • Delegated Type や Polymorphic
  • Finder メソッドのチェーニング
  • 集計メソッド
  • いくつか登録漏れしたメソッド一覧

などがあります。限界はありますが、これらのいくつかはhover表示経路の改善やシグネチャ登録範囲の拡大で対応可能である見込みです。

実際どのようなサンプルで試しているかは https://github.com/riseshia/type-guessr/blob/main/sample/activerecord/test_inference.rb こちらからご確認できます。

2.4 MCPサーバの実装(新規)

提案書にはなかった成果物として、type-guessrをClaude Code等のAIコーディングツールから利用するためのMCPサーバを実装しました。

bundle exec ruby exe/type-guessr mcp [project_path]

近年のAIコーディングツールの発展に伴い、type-guessrの活用場面が「人間のIDE利用」だけでなく「AIによるコード理解支援」にも広がると考え、実際 LLM にこのツールをもたせると役に立つ可能性があるかどうかの探索目的で MCPインターフェースを追加しました。 AIツールが大規模コードベースを探索する際に、Grep+Readよりも構造化された型情報を提供できる点に価値があることを期待しながら評価を進めています。

2.5 発表活動

本プロジェクトに関して以下の発表を行いました、または予定しています:

3. 提案書対比 最終実装状況

Phase 1: 基本機能実装

まだ細かいバグがありますが、把握している範囲内ではほぼ完成していると考えています。

Phase 2: ヒューリスティック型推論

コアとなる duck typing のヒューリスティックは問題なく動作しており、なおパフォーマンス上の課題も一定解消しているので完了していると判断しています。

初期予定していた変数名ベース推測・複数形推測は、現状 duck typing ビューリスティックの上に加えたところで大きくメリットにならない、という判断で対応を完全に止めています。

Phase 3: DSL対応

まだ探りの段階ですが、DSL 対応の代表例として ActiveRecord 対応を試して一定の成果を得ていますが、まだ内部実装であり、拡張できるインタフェースにまでは成熟しきっていません。 とはいえ、一定パターンに従うのであれば利用者側が自由に処理を増やせるような構造として作りつつありますので、順調に進むのであれば実現できるかなと考えています。

4. 残課題と今後の展望

継続改善

  1. 推論カバレッジの向上
  2. DSL型推論の精度向上
    1. ActiveRecord検証の残り70件への対応。hover経路でのRBS/DSL優先度の整理、CollectionProxy[T]の型パラメータ活用等
  3. カスタム型シグネチャの外部インターフェース — 内部的にはカスタム型シグネチャを扱うための仕組みが用意されており、これを外部に公開する拡張インターフェースの設計を検討する。ユーザーやgemが独自のDSLに対して型情報を提供できるようにすることが目標
  4. AIツール連携の評価と改善 — MCPサーバを実装したが、AIコーディングツールとの統合における効果測定と改善が必要。バッチAPI対応等、AI時代における型情報ツールの在り方を模索していく

Diagnostic対応

型エラーがあれば開発者にそれを案内したい、ということを考えていたのですが、 Duck typing によるクラス推定においては正確なメソッド一覧を把握できてない場合と型変数の中身が適切に変換できてない場合などにより発生する false positive が多く発生することが予想されている点、そして推論に参考した情報と判定に使う情報の境界線が曖昧に感じており、そこをもう少し極めたほうがよいという判断でまだ対応しておりませんが、今後方針が固まったら実装していきたいと考えています。

リリース予定

現在はそれなりに激しく仕様を変化させたり壊したりしているので積極的にリリースしておらず、福岡Rubyist会議の発表前に出した 0.0.2 が最新になっています。DSL対応の安定化と既知のバグの修正を進め、RubyKaigi 2026(4/22-24)までには安定しているバージョンのリリースを行うことを目標としています。

今後の方向性

今後はRuby LSP addonとしての人間向けの体験と、MCPサーバとしてのAI向けの体験の両面から改善を進めていく予定です。

5. まとめ

本プロジェクトは「型を書かなくても十分に役立つ型情報を得られる」開発環境の実現を目指して開発を進めてきました。

  • Phase 1(基本機能) はTupleType、ガード節型ナローイング、クラスレベル型変数等の実装により実用性が大幅に改善
  • Phase 2(ヒューリスティック推論) は duck typingの精度改善とブロックパラメータ対応を実施。変数名ベース推測は効果が限定的と判断し見送り
  • Phase 3(DSL対応) は ActiveRecord DSLの型推論を独自実装し、検証245件中175件パス(71.4%)を達成
  • パフォーマンス はインデックス時間を41.6秒→14.2秒に短縮(66%改善、目標20秒以下を達成)。起動速度は巨大Railsアプリ基準で41秒→24秒(キャッシュあり)に改善。メモリ使用量は2.84 GB→1.85 GBに削減(35%改善)
  • 新たな成果 としてMCPサーバを実装し、AIコーディングツールとの統合という新しい活用方法を開拓
  • 発表活動 として福岡Rubyist会議05で発表済、RubyKaigi 2026での発表も採択済
  • リリース はDSL対応の安定化後、RubyKaigi 2026(4/22-24)までに安定版リリースを予定

引き続き開発を進め、Rubyコミュニティに貢献できるツールに育てていきたいと考えております。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment