Skip to content

Features ​

Tyda は Ruby / Rails のコードから型を推論し、RBS を出力する CLI、LSP、AI agent 向け MCP server を提供する。 対応状況の正本は capability-matrix.md、設計上の線引きは design.md に置く。

プロダクト ​

  • Ruby source と .rbs を中心にした query 型推論 engine
  • CLI の RBS 出力、JSON Lines diagnostics、型カバレッジ JSON
  • TypeProf VSCode 拡張と接続できる LSP server
  • stdio MCP server による AI agent 向けの位置指定型推論
  • Rails / gem DSL plugin
  • Sorbet sig / .rbi の実験的な補助
  • wasm playground(Playground)

Ruby 推論 ​

主な対応範囲は次のとおり。

  • class / module / method / mixin / constant / local / instance variable(LSP / Playground の定義・参照 hover を含む。宣言済み引数の定義位置も対象)
  • method dispatch、visibility、super、singleton method、refinement(include / prepend / extend の適用順を反映。静的に完全な Module#ancestors は順序付き Tuple)
  • block / Proc / lambda / yield / Enumerable / Enumerator / Lazy(遅延解決された source method return を block dispatch 前に反映し、tuple の要素 union とリテラル演算を block 内へ伝播)
  • Array / Hash / Set / Tuple / Record の要素型と shape
  • if / case / rescue / safe navigation / pattern matching の flow narrowing。標準の Class#=== による postfix の local 代入条件や、pure な no-arg ivar reader の再呼び出しも扱い、分岐で相関したlocalも識別可能な型で絞られた場合に反映
  • 多重代入、operator-write、method 内の instance variable 再代入、文字列・シンボル補間(静的な literal / union の展開を含む)
  • Thread / Fiber / Queue の bounded な値伝播
  • 静的に名前を求められる alias / define_method / attr_* / Struct.new / Data.define(位置引数・キーワード引数の new 呼び出しからmember型を推定) / Forwardable / send / const_get

実行時にしか決まらない名前、object identity、method surface は推測せず untyped にする。 型の深さ・union・collection shape には上限がある。

型情報ソース ​

RBS ​

  • .rbs の自動発見、stdlib の lazy load、generic、overload、interface、alias
  • inline RBS(#: / # @rbs)の単一・複数行宣言、block signature、type alias
  • self / instance を call site の受け手へ解決する factory 型

Sorbet(実験的) ​

sorbet/config がある project で、sig、T.let、T::Struct、T::Enum、.rbi と 対応する comment extension を読み込む。RBS と同じ安定性や網羅性は保証しない。

Diagnostics ​

型推論が主であり、diagnostics は補助である。権威ある宣言に対する確実な不一致だけを報告する。

種類既定の severity方針
argument_type_mismatcherror宣言 param と actual が確実に不一致のときだけ。分岐内のインスタンス変数や File.exist? で確認したパスも、その分岐で絞られた型で判定する。Union receiver は各候補型の権威ある署名で調べ、不一致の候補型を message に含める
return_type_mismatcherrorinline RBS、@rbs、Sorbet sig、外部RBS/RBIの戻り値型と、メソッド本体の到達可能な返却型が確実に不一致のとき。untyped や未解決型を含む不確かな結果は報告しない
arity_mismatcherror / experimentalUnion receiver は候補型と権威ある署名が分かる場合に、引数個数・必須キーワードの不一致を候補型ごとに報告する。ソース定義の initialize を標準の Class#new 経由で呼ぶ場合は必須引数の不一致を error にする。祖先解決では :: による絶対指定を保つ。Struct.new 由来の constructor は member の省略を許し、上限超過だけを報告する。Data.define 由来は、member 名が静的に分かり独自 initialize がない場合に限り、必須 member 数と位置・キーワード引数の規則で判定する。それ以外は TYDA_EXPERIMENTAL_CHECKS=1 のときだけ
missing_record_keywarning形状が分かる非空 record のすべての候補にリテラルキーが存在しないとき。空 record は動的な to_h の推論結果と区別できないため対象外。Hash#merge の引数が untyped や未解決型なら、結果を動的な Hash として扱い対象外。record のキー存在確認後は既知のキーへ絞り、`[]
missing_methodwarningreceiver と祖先の method surface が完全に既知のときだけ。Union receiver は各候補型で欠けている method を報告する。安全 navigation の nil は候補から除く。bare Object / Class / Module、plugin が解決する method、既知の class-body DSL は対象外。ActiveRecord 系ではDBスキーマや宣言RBIから動的なカラム属性を確認できない場合も対象外
unresolved_constantinformationreceiver 文脈で未定義と証明できるときだけ

Unknown、untyped、動的な record key、開いた method_missing 面、未解決の祖先は誤検知を避けて沈黙する。Union の候補型を名前付き class に解決できない場合、引数型チェックはその呼び出し全体を Unknown として扱う。戻り値の判定では return / 末尾式 / 分岐 / loop の到達可能な返却型を使い、到達不能な末尾や bot は不一致に含めない。 詳細は incomplete-code-policy.md を参照する。

診断を一行だけ抑制するには、対象式の行末に # tyda: ignore を置く。特定の種類だけを 抑制する場合は # tyda: ignore[missing_method] のように診断 code を指定できる。現在の code は missing_method、argument_type_mismatch、arity_mismatch、missing_record_key、 unresolved_constant などで、CLI・LSP・Playground で同じ書式を使う。コメントは同じ行の末尾に 置いた場合だけ有効で、単独行のコメントが次の行へ影響することはない。対応する診断がない ignore は unused_ignore warning になり、診断が解消したあとに不要な抑制を見つけられる。

--diagnostics の JSON Lines 出力は実行間で byte-identical になる。ファイルは 辞書順の走査順(CLI に明示的に渡したパスはその順序を保つ)、ファイル内の各行は position 順(line/column 昇順)で並ぶため、複数回実行した出力をそのまま diff できる。

型カバレッジ ​

--coverage は、compact scan が記録した推論サイトを最終 workspace registry で再解決し、 宣言スロットと合わせて決定的な JSON として出力する。通常の RBS 出力ではサイトを保持しない ため、明示的に指定した実行だけがこの追加コストを負う。

宣言と参照は意味の違う単位なので、レポートでは分母を分ける。

  • declarations: Ruby source の method parameter / return / instance variable。外部 RBS だけの宣言と synthetic DSL method は含めない
  • references: 推論中に観測した value / method_call / constant_reference

各グループと種別には次の三段階を出力する。

  • typed: 型が確定し、入れ子の型にも未解決 marker がない
  • untyped: サイトは解析経路に結び付いているが、型が untyped または deferred
  • unknown: receiver や constant の結び付き自体を確立できない

型構造が極端に大きい、または深い場合は、報告処理の上限を超えたサイトを安全側に untyped として扱う。これにより coverage の計測自体が入力によって無制限に膨らまないようにする。

type_coverage_percent は typed / total、tracking_coverage_percent は (typed + untyped) / total である。型が String から Integer に変わるような、両方とも typed の精度差はこのレポートでは扱わない。Performance workflow では既存の全 subject を base/head の同じ release binary で一度ずつ解析し、解析ファイル数の減少、typed / tracked サイトの減少、unknown の増加を失敗として検出する。untyped の増加は警告として結果 JSON と CI log に残す。Perf と同じ matrix 内で実行するため、追加の Rust build や PR comment は発生しない。

Rails / gem DSL ​

Rails の ActiveRecord、ActiveModel、ActiveSupport、ActionController、ActionMailer、ActiveJob、 routes、schema と、主要な gem plugin を扱う。対応 gem の正本は src/inference/plugins/ であり、 個別 gem の一覧をこの文書に重複して持たない。

  • schema / attribute / relation から model の型を補う
  • Concern、association、scope、enum(plural map method を含む)、delegate などの静的な DSL を展開する。structure.sql の外部キー先は明示的な self.table_name も参照する
  • ActiveRecord の find は単一 ID、ID 配列、複数 ID の overload とモデル/配列の戻り値を出力する
  • Rails.application.configure の block では、receiver のない呼び出しを application の self で推論する
  • Grape、GraphQL-Ruby、Devise、Doorkeeper、Sidekiq、Draper、AASM などを plugin で補う
  • GitLab in-tree の Presenter / CurrentSettings / Metrics / EE 拡張を検出する
  • Redmine の acts_as_* など、ライブラリ内部の実行時登録は展開しない。必要なら手書き .rbs / .rbi、または生成済み定義を入力する

LSP / Playground ​

LSP は TypeProf VSCode 拡張が期待する起動・version・request 契約に対応する。

  • incremental text sync(full change も受理)
  • Hover、CodeLens、definition、typeDefinition、completion
  • method hover は呼び出し形に合う RBS overload を選び、推論済みの引数・戻り値から generic と block 型を具体化する
  • Playground は入力中の Ruby とユーザー RBS を debounce 解析し、RBS の変更も同じ hover / diagnostics に反映する
  • diagnostics の publish と workspace refresh
  • CLI と共通の WorkspaceState / query backend
  • Playground の複数行選択を Ctrl+/(Windows/Linux)または Command+/(macOS)で Ruby 行コメントに切り替え

Playground は同じ LSP 表示経路を wasm で実行し、Ruby と手書き RBS の結果をブラウザで確認する。 右上の Examples メニューから、配列・Tuple・mixin・RBS などの短いサンプルに切り替えられる。 サンプルのソースは末尾改行一つで統一する。 Ruby エディタを主領域として PC / 横長画面では左、狭い画面(768px 以下)では上に置き、RBS は補助領域として右または下に配置する。エディタ内の長い行は折り返し、横スクロールは使わない。動的viewportとSafe Area insetにも対応する。

主なコマンド ​

bash
cargo run -- <path>                         # RBS
cargo run -- --diagnostics <path>           # JSON Lines diagnostics
cargo run -- --coverage <path>              # JSON type coverage
cargo run -- --lsp                          # LSP server
cargo run -- mcp                            # MCP server for AI agents
cargo run -- --include-synthetic-dsl-methods <path>
mise run dev                                # playground

MCP の client 設定と infer_type_at_position の入力・出力は mcp.md を参照する。

開発・拡張の手順は development.md、テストの追加方法は testing.md を参照する。