ADR-2: 拡張API戦略
ステータス: Accepted;実装・出荷済み。
v0.1.0実装スライス(slice)(4 — 内部ナローイング(narrowing)を通じたFlowContributionの配線、5 — プラグイン診断エミッションプロトコル、6 — プラグイン側キャッシュプロデューサー、作業決定はADR-7に固定)はすべてランディングした。拡張APIはその後、ADR-9(クロスプラグインファクト)、ADR-13(TypeNodeリゾルバ)、ADR-16(マクロ基板)、ADR-25(signature_paths:)、ADR-26(open_receivers:)、ADR-28(protocol_contracts:)、ADR-32(source_rbs_synthesizer:)で記録されたサーフェスを成長させてきた。何を解析器がするかについては型モデルと仕様コーパスが権威を持ち続ける;本ADRはなぜを記録する。
コンテキスト
Section titled “コンテキスト”Rigorはコア解析器を小さく保ちながら、Rubyフレームワーク、生成されたAPI、DSL、メタプログラミングを処理できる必要があります。PHPStanはこの設計部分の最も強力な参照ポイントです。なぜなら、その拡張APIはフレームワーク著者が解析されたアプリケーションコードを変更せずに型ファクト(fact)、リフレクションファクト、ルール、インフラストラクチャ動作を精密に提供する方法を与えるからです。
このADRのPHPStan参照資料はreferences/phpstan/website/src/developing-extensions/、特に:
dynamic-return-type-extensions.mdtype-specifying-extensions.mdtype-system.mdscope.mdreflection.mdextension-types.mddependency-injection-configuration.mdtesting.md
Rigorはアーキテクチャをモデル化すべきであり、PHPの名前、PHPDocの構文、またはPHPのランタイムの前提ではありません。
RigorのExtension APIはPHPStanのようにすべきです: 設定またはプラグインマニフェストによって登録された小さく型付けされた拡張プロトコルのセット。各拡張はASTノード、Scope、リフレクションオブジェクト、Type値などの不変の解析コンテキストオブジェクトを受け取り、精密な貢献またはnil/空の結果を返してコア解析器がデフォルト動作を続けられるようにします。
プラグインはアプリケーションコードを実行してはなりません(MUST NOT)。解析されたRuby、RBS、生成されたシグネチャ、設定、依存関係メタデータ、キャッシュされたプラグインメタデータを検査できます(MAY)。(ADR-39がこの境界を明確化します。プラグインは宣言した純粋で許可リストに載ったターゲットライブラリのメソッドを呼び出してよく(MAY)——これは信頼されたgem依存であり、エンジンの定数畳み込み層がすでにコア/標準ライブラリのメソッドを呼び出しているのと同じであり、PHPStan拡張が実際のフレームワークを呼び出すのと同じです——、それでも解析対象であるアプリケーション自身のコードは依然として一切実行されません。)
コアAPIは型推論とメタプログラミングサポートを改善する拡張ポイントから始まるべきです:
- 動的戻り値型拡張。
- フローナローイングのための型指定拡張。
- メソッド、属性、定数、オブジェクトシェイプ(shape)の動的メンバーリフレクション。
- カスタムルールと制限された使用チェック。
- 結果キャッシュメタデータと診断。
PHPStan拡張サーフェス
Section titled “PHPStan拡張サーフェス”| カテゴリー | PHPStan機能 | Rigorへの含意 |
|---|---|---|
| 基盤 | AST、Scope、型システム、3値ロジック、リフレクション、DIと設定。 | Rigorはイミュータブルなスコープスナップショット、型クエリ、解析器リフレクション、3値の確実性、サービス構築、プラグイン設定のために安定したオブジェクトモデルが必要です。 |
| カスタムルール | Rule<TNode>は選択されたASTまたは仮想ノードで実行され診断を返します。コレクターはルールがCollectedDataNodeで実行される前にクロスファイルファクトを集約します。 | Rigorはまずノードスコープのルールをサポートし、並列解析とキャッシングが成熟したらクロスファイルコレクターをサポートすべきです。 |
| 制限された使用 | 専門化されたフックは、フルASTルールを書かずにメソッド、プロパティ、関数、クラス名、定数などを制限します。 | Rigorは内部API、生成されたクラス、Rails専用エントリーポイント、テスト専用ヘルパーなどのアクセスポリシーチェックのためにシンプルなシンボル使用フックを提供すべきです。 |
| 型推論 | 動的戻り値型、動的スロー型、型指定、クロージャ、パラメータアウト、式リゾルバ、演算子型、カスタムPHPDoc型拡張。 | Rigorは戻り値推論、フローファクト、ブロック/プロックコンテキスト、式フォールバック、カスタムRBS拡張型解析を優先すべきです。 |
| メタデータ | クラスリフレクション拡張、カスタム非推奨、許可された部分型(subtype)、追加コンストラクタ、例外分類、条件付きスタブファイル。 | Rigorはプラグインが動的Rubyメンバー、部分型ファクト、初期化メソッド、非推奨/内部メタデータ、例外ポリシー、生成されたまたは条件付きRBSを提供できるようにすべきです。 |
| デッドコードサポート | 常に読み取られる/書き込まれるプロパティ、常に使用される定数、常に使用されるメソッド。 | Rigorはほとんどのデッドコード拡張ポイントを延期すべきですが、そのモデルはRails、シリアライザ、ORMフィールド、コールバック、リフレクション重いコードに有用です。 |
| 出力とインフラ | エラーフォーマッタ、エラー無視拡張、診断拡張、結果キャッシュメタデータ拡張、拡張テスト。 | Rigorはキャッシュ無効化メタデータとプラグイン診断を早期にサポートすべきです。カスタムフォーマッタと無視フックはCLI出力モデルが安定するまで待てます。 |
重要な設計パターンはPHPStan APIを通じて一貫しています: 狭い拡張は何をサポートするかを宣言し、現在のScopeとリフレクション/型オブジェクトを受け取り、ドメインオブジェクトを返します。
Scopeオブジェクト
Section titled “Scopeオブジェクト”PHPStanのScopeは現在のAST位置での解析器の状態を表します。式の型クエリに答え、現在のファイル、名前空間、クラス、トレイト、関数、メソッド、またはクロージャを識別し、selfなどのコンテキスト依存の名前を解決できます。
Rigorは同様の不変Scopeオブジェクトを提供すべきです。以下を公開すべきです:
- 式型クエリのための
type_of(node)。 analyze_condition(node)またはtruthy、falsey、normal、exceptional、unreachableな出力スコープを生成できる同等の解析器所有の操作。- 現在のファイル、字句ネスト、クラス/モジュールシングルトンコンテキスト、メソッド、ブロック、可視性コンテキスト。
- 現在のレシーバー型と既知のローカル、インスタンス変数、クラス変数、グローバル、定数、シェイプファクト。
- 値ファクト、否定的ファクト、関係ファクト、メンバー存在ファクト、シェイプファクト、動的起源provenance、ファクト安定性メタデータ。
- Ruby字句ルックアップの名前と定数解決ヘルパー。
- truthy分岐、falsy分岐、アサーションコンテキスト、rescueコンテキスト、unreachableコンテキストなどのフローエッジコンテキスト。
拡張はScopeを直接変更してはなりません(SHOULD NOT)。ファクト、診断、合成ノード、またはメタデータを解析器に返すべきであり、解析器は通常の制御フロー機構を通じてそれらを適用します。
スコープモデルは短絡条件に対して十分精密でなければなりません。プラグイン定義の述語が&&の左側に現れる場合、そのtrue-edgeファクトは右側を解析する間に見えなければなりません。||の左側に現れる場合、そのfalse-edgeファクトは右側を解析する間に見えなければなりません。
Scopeの最小の最初の実装サーフェス(surface)は意図的に狭いです:
- 型クエリ:
type_of(target)はサポートされるターゲットの現在のナローイングされた型を返します。 - 3値の結果を持つ関係クエリ:
has_member?(target, name)、has_key?(target, key)、equals?(target, value)はプラグインが型に強制せずに関係ファクトを尋ねられるようにyes、maybe、またはnoを返します。 - エッジ認識ナローイング: プラグインは参加する条件のtruthy edgeとfalsey edgeのスコープを別々に受け取ります。
小さなContextInfoコンパニオンオブジェクトはScope自体には属さない字句コンテキストを公開します: 現在のファイル、囲むクラスまたはモジュール、現在のメソッド、現在の可視性スコープ、呼び出しがprivate、protected、またはアサーションコンテキストの中で解析されているかどうか。
型システムオブジェクトモデル
Section titled “型システムオブジェクトモデル”PHPStanはすべての型を共通のTypeインターフェースを実装するオブジェクトとして表現します。型はisSuperTypeOf、accepts、hasMethod、getMethod、hasProperty、describeなどのケイパビリティ(capability)と関係クエリに答えます。これらの回答はしばしばブール値ではなく3値ロジックを使用します。
Rigorは同じスタイルを採用すべきです:
- 型オブジェクトは通常の不変値オブジェクトです。
- 関係クエリは不確実性が意味を持つ場合に
yes、maybe、またはnoを返します。 - 拡張は具体的な実装クラスをチェックするのではなく、
StringType.supertype_of?(type)などのセマンティックな質問をすべきです。 - 型コンストラクタはコンビネータ(ユニオン(union、合併型とも)、積、差、消去ヘルパーなど)を通じて正規化すべきです。
- カスタム型のようなリファインメント(refinement、篩型とも)は関係、正規化、表示、RBS消去動作を実装すべきです。
yesとnoは現在のソース、受け付けられたシグネチャ、プラグインファクト、および解析器の仮定の下で証明された結果のために予約されています。maybeは解析器がどちら側も証明できないことを意味します。
non-empty-stringのような型はアクセサリーリファインメントとして表現でき、文字列リテラルのユニオンは依然として文字列として答えるべきです。拡張著者はすべての具体的な内部表現を知る必要がありません。
リフレクションオブジェクト
Section titled “リフレクションオブジェクト”PHPStanは関数、クラス、プロパティ、メソッド、定数、PHPDocのための解析器所有のリフレクション層を持ちます。リフレクションはソース、ネイティブシンボル、スタブ、または拡張提供のマジックメンバーから来る可能性があります。
RigorはRubyランタイムリフレクションとは別の解析器リフレクション層を公開すべきです。以下を組み合わせるべきです:
- Rubyソース宣言。
- RBS宣言。
- 生成されたRBSまたはプラグイン提供のシグネチャ。
- コアと標準ライブラリのシグネチャ。
- プラグインによって貢献された動的メンバー。
リフレクションオブジェクトはクラス、モジュール、シングルトンクラスオブジェクト、メソッド、属性、定数、エイリアス、インターフェース、オブジェクトシェイプをカバーすべきです。診断がその説明を必要とする場合、ネイティブ/ソースメンバーとプラグイン提供の動的メンバーを区別すべきです。
動的戻り値型拡張
Section titled “動的戻り値型拡張”PHPStanの動的戻り値型拡張は、関数またはメソッドの戻り値型が呼び出し側の引数に依存する場合に使用されます。拡張はターゲットクラス/関数を宣言し、メソッドがサポートされているかチェックし、メソッドリフレクション、呼び出しASTノード、スコープを受け取ります。
RigorはRubyメソッド呼び出しに同じ形状を使用すべきです:
- 動的戻り値拡張はサポートするレシーバーファミリーを宣言します。
- メソッドリフレクション、呼び出しノード、レシーバー型、引数ノード、ブロック情報、スコープを受け取ります。
scope.type_ofで引数の型またはリテラルを検査できます(MAY)。- 型、型付きエフェクトバンドル、またはデフォルト動作のための
nilを返します。
このフックはコンテナ、ORM、ファクトリー、スキーマバックされたアクセサ、Hash#fetchのようなラッパー、フレームワーククエリビルダーなどのAPIに適切です。
型付きエフェクトバンドルには通常の戻り値型、レシーバーまたは引数の変異ファクト、導入された動的メンバー、スローまたは非戻り値制御フローファクト、ファクト無効化を含めることができます(MAY)。
PHPStanの型指定拡張は型チェック関数またはメソッドへの呼び出しに基づくフローファクトを提供します。
Rigorはこれを一流の拡張ファミリーにすべきです。なぜなら、Rubyコードはしばしば述語とアサーションAPIを通じてナローイングするからです:
nil?、is_a?、kind_of?、instance_of?、respond_to?、カスタムfoo?メソッド、フレームワークガードなどの述語。assert、raise unless、テストフレームワークアサーション、契約(contract)ヘルパー、検証ライブラリなどのアサーションメソッド。- レシーバーメンバー、ハッシュキー、またはメソッド結果に関するファクトを証明するパターンスタイルまたは関係スタイルのAPI。
拡張結果はポジティブとネガティブのファクトを別々に記述すべきです。またfalse分岐が補集合を意味しない場合のtrue-onlyフォームもサポートすべきです。
RigorはRuby固有のガードのための関係認識ファクトも必要とします。
動的リフレクションとマジックメンバー
Section titled “動的リフレクションとマジックメンバー”PHPStanのクラスリフレクション拡張は__get、__set、__callなどのメカニズムを通じて公開されるマジックプロパティとメソッドを記述します。
RigorはRubyのmethod_missing、respond_to_missing?、define_method、Rails生成メソッド、ActiveRecord属性、enumヘルパー、アソシエーション、シリアライザ、デリゲートメソッド、DSL生成定数に対して同じケイパビリティが必要です。
動的リフレクションは構造的インターフェースチェックをサポートしなければなりません(MUST)。プラグイン提供のメンバーは、Rigorが名前的型(nominal type、公称型とも)またはオブジェクトシェイプがRBSインターフェースを満たすかどうか決定するのに十分なシグネチャと確実性情報を公開すべきです。
Rigorは一般的な標準ライブラリのケイパビリティロール(読み取り可能ストリーム、書き込み可能ストリーム、巻き戻し可能ストリーム、シーク可能ストリーム、クローズ可能、列挙可能、呼び出し可能、ファイル記述子バック)の意見を持つコアカタログを出荷すべきです。
リフレクション層の再ビルド
Section titled “リフレクション層の再ビルド”リフレクション層は1つのモノリシックテーブルとして再ビルドするのではなく、入力ソースによって層化されるべきです。最初の層は: コアと標準ライブラリのシグネチャ、プロジェクトソース宣言、受け付けられたRBSとインラインシグネチャ、生成されたシグネチャ、プラグイン提供の動的メンバー。
各リフレクション貢献は、最も狭い実用的なスライス(クラスまたはモジュール宣言、シングルトンオブジェクト、メンバーエントリーなど)で安定したidentityとキャッシュキーを持つべきです。
プラグイン提供の動的メンバーはprovenanceと依存関係記述子を持たなければなりません(MUST)。安定した動的メンバーはファイルと実行をまたいで再利用できます(MAY)。
広い式と演算子フック
Section titled “広い式と演算子フック”PHPStanにはキャッチオール式型リゾルバ拡張と演算子型指定拡張があります。そのドキュメントは可能な場合は狭いフックを推奨します。
Rigorはそれらが解析順序とパフォーマンスの推論を難しくできるため、広い式フックを高いハードルの後ろに置くべきです。最初の公開プラグインマイルストーンは、具体的なフレームワークのユースケースが狭いフックで表現できない場合を除いて、広い式と演算子フックを延期すべきです。
フロー貢献バンドル
Section titled “フロー貢献バンドル”プラグイン、RBS::Extendedアノテーション、組み込みナローイングルールはすべて同じ種類のオブジェクトを解析器に渡します: 単一の呼び出しエッジで生成されたファクトとエフェクトのバンドル。
最小の最初の実装の公開バンドルはオプションスロットを持つ単一のstructです:
return_type: 通常エッジの戻り値型。truthy_facts、falsey_facts: 対応する制御フローエッジでのみ保持するファクト。post_return_facts: アサーションに使用される、呼び出しが任意のエッジで正常に戻った後に保持するファクト。mutations: レシーバーと引数の変異エフェクト。invalidations: 変異が意味する以上のターゲットファクト無効化。exceptional: 非戻り値、例外、またはunreachableエフェクト。role_conformance: 貢献がそれらを提供する場合のケイパビリティロール適合ファクト。provenance: ソースファミリー、プラグインid、アノテーションノード、インクリメンタル再ビルドに必要なキャッシュ記述子。
プラグイン貢献のマージ
Section titled “プラグイン貢献のマージ”複数のフロー貢献が同じ呼び出しをターゲットにできます。Rigorはあるソースが別のソースを静かに上書きするのではなく、これらの貢献を決定論的にマージします。
権限ティアは明示的です:
- コアRubyのセマンティクスと受け付けられた通常のRBS、rbs-inline、Steep互換の契約は権威があります。
RBS::Extendedアノテーションと生成されたメタデータはそれらの契約を精製できます(MAY)。- プラグインは互換性のある解析器ファクトを精製できます(MAY)。
- 下位ティアは上位ティアを弱めたり矛盾させてはなりません(MUST NOT)。
同じティア内のプラグイン順序は決定論的です: プロジェクト設定順序(依存関係制約が満たされた後)、タイブレーカーとしてプラグイン識別子順序。最初の公開APIはアドホックな優先フィールドを公開しません。
互換性のある貢献はターゲット、フローエッジ、エフェクト種類によって合成します:
- 同じターゲットとエッジのポジティブ型ファクトは交差します。
- 否定的と関係ファクトはADR-1で定義された通常のファクト予算の下で蓄積します。
- 動的戻り値拡張からの戻り値型は選択されたシグネチャに対してチェックされます。
- 変異、エスケープ、無効化エフェクトは保守的にユニオンされます。
矛盾は診断であり、first-winsまたはlast-wins動作ではありません。
プラグイン診断Provenance
Section titled “プラグイン診断Provenance”プラグイン、生成された、またはRBS::Extendedの貢献に依存する診断はPHPStanエラー識別子と同様に安定した識別子を公開すべきです。公開識別子はソースファミリープレフィックスを使用すべきです(plugin.<plugin-id>.<name>、rbs_extended.<name>、generated.<provider>.<name>など)。
内部的には、ファクト、エフェクト、診断はソースティア、プラグイン識別子、バージョン、設定ソース、依存関係記述子、ターゲットパス、エフェクト種類、貢献するリフレクションまたはシグネチャオブジェクトを保持すべきです。
登録、設定、キャッシング
Section titled “登録、設定、キャッシング”PHPStanはタグ付きサービスとして拡張を登録します。
Rigorはプラグインマニフェストとプロジェクト設定を使用して拡張サービスを登録すべきです。最初の設計は以下を含むべきです:
- アドホックなメソッド名ディスカバリーではなく拡張プロトコル識別子。
- リフレクションプロバイダ、型ファクトリー、ロガー、設定リーダーなどの解析器サービスのコンストラクタインジェクション。
- タイポが診断になるように明示的なプラグイン設定スキーマ。
- 決定論的な拡張順序。
- 外部スキーマ、生成されたファイル、gemバージョン、プラグインバージョン、設定が変更されたときにプラグインが結果を無効化できる宣言的なキャッシュ依存関係記述子。
キャッシュ依存関係は型付きスロットスキーマを使用すべきです:
files: プロジェクトまたは外部ファイル入力。gems: gem名とバージョン制約またはピン留めされたバージョン。plugins: プラグイン識別子とピン留めされたプラグインgemバージョン。configs: 設定キーとそれらの受け付けられた値のハッシュ。
プラグインの信頼とI/Oポリシー
Section titled “プラグインの信頼とI/Oポリシー”プラグインはアプリケーションコードを実行してはなりません(MUST NOT)。解析されたRuby、RBS、生成されたシグネチャ、プロジェクト設定、依存関係メタデータ、キャッシュされたプラグインメタデータを検査できます(MAY)。
最初の実装はプラグインをユーザー、Gemfile、またはプロジェクト設定によって選択された信頼されたRuby gemsとして扱うべきです。解析中は決定論のためにデフォルトでネットワークアクセスを無効にすべきです。ファイル読み取りは通常プロジェクトルート、設定された生成ファイル、依存関係メタデータ、インストールされたgemメタデータにスコープされるべきです。
プラグインの失敗は解析器の境界で分離されるべきです(SHOULD)。プラグインの例外はprovenanceを持つプラグイン診断になるべきであり、可能な場合は影響を受けた貢献のみを劣化させ、rigor checkをクラッシュさせるべきではありません。
テストと互換性
Section titled “テストと互換性”PHPStanはルールと型推論拡張のためのテストベースを提供します。
Rigorは同じ2つのテストスタイルを提供すべきです:
- フィクスチャファイルを解析し、行番号と識別子を持つ診断をアサートするルールテスト。
- フィクスチャコードとヘルパーアサーションを使用して推論された型、ナローイングされた型、動的戻り値型、プラグイン提供のメンバーをチェックする型推論テスト。
型推論アサーション構文はフィクスチャハーネス構文であり、アプリケーションRuby構文ではありません。
拡張の互換性は最初はRuby gem版の依存関係とRigor提供の拡張テストスイートを通じて管理されるべきです。
結果の型仕様からのフィードバック
Section titled “結果の型仕様からのフィードバック”docs/types.mdを理想的な型モデルとして再構築することで、いくつかの拡張API要件が明らかになりました:
- 拡張は型だけでなくフロー貢献を返す必要があります。
Scopeはエッジ認識でなければなりません(MUST)。- ターゲットパスはステージングされた設計が必要です。
- APIは型ファクトに加えて関係ファクトが必要です。
- 拡張と標準ライブラリファクトプロバイダはケイパビリティロール適合を宣言する方法が必要です。
- 動的リフレクションはメンバーの確実性、provenance、可視性、呼び出しシグネチャ、変異動作、安定性を公開すべきです。
- 型とリフレクションAPIは
yes、maybe、noに対して3値の確実性が必要です。 - 拡張テストはステートメント境界だけでなく、複合条件内のプログラムポイントで推論された型とファクトをアサートできる必要があります。
- キャッシュメタデータには外部スキーマ、生成されたシグネチャ、gemバージョン、プラグイン設定、動的メンバーまたはフローファクトの生成に使用されたファイルが含まれなければなりません(MUST)。
クリティカルレビューの作業回答
Section titled “クリティカルレビューの作業回答”拡張APIドラフトのクリティカルレビューで以下のリスクが浮上しました。以下の作業回答は現在の決定または明示的な延期を記録します。
キャッシュ無効化には宣言的APIが必要
Section titled “キャッシュ無効化には宣言的APIが必要”プラグインキャッシュメタデータは重要な入力を命名しましたが、プラグインがファクトをファイル、生成されたシグネチャ、gemバージョン、プラグインバージョン、設定キーに結び付ける方法を定義しませんでした。
作業回答:プラグインのファクトとリフレクション貢献は、それらが生成したキャッシュスライスに付加された宣言的依存関係記述子を持つべきです。
型推論アサーションはフィクスチャのみに留まらなければならない
Section titled “型推論アサーションはフィクスチャのみに留まらなければならない”作業回答:アサーションマーカーはフィクスチャハーネス構文です。Prismが通常のRubyとして解析するコメントまたは外部期待ファイルを使用すべきであり、本番解析は明示的なテストハーネスが有効にしない限りそれらを無視します。
プラグインサンドボックスとI/Oは信頼されたgemモデルから始まる
Section titled “プラグインサンドボックスとI/Oは信頼されたgemモデルから始まる”作業回答:最初の実装はプラグインを信頼されたRuby gemsとして扱います。解析中はデフォルトでネットワークアクセスを無効にし、通常の読み取りはプロジェクトと依存関係の入力にスコープされ、それらの外の読み取りには明示的な設定とキャッシュ依存関係記述子が必要です。
3値のmaybeはポリシー認識の不確実性
Section titled “3値のmaybeはポリシー認識の不確実性”作業回答: yesとnoは現在の受け付けられた契約と解析器の仮定の下で証明された回答です。maybeはそれ以外のすべてです。maybeはポジティブ証明としてナローイングせず、補完的なfalse-edge証明を作成せず、繰り返されたmaybe証拠はmaybeのまま残ります。
ケイパビリティロールはコアによって提供される
Section titled “ケイパビリティロールはコアによって提供される”作業回答: Rigorは一般的な標準ライブラリのケイパビリティロールの意見を持つコアカタログを出荷します。プラグインはフレームワークロール、追加の適合ファクト、ロール固有の除外、不確かな適合を追加できますが(MAY)、コアロール定義を静かに置き換えてはなりません(SHOULD NOT)。
ADR-1はフローエフェクトセマンティクスを所有する
Section titled “ADR-1はフローエフェクトセマンティクスを所有する”作業回答: ADR-1はセマンティックスキーマを所有します。ADR-2はプラグインパッケージング、登録、サービスライフタイム、provenanceを所有します。docs/types.mdは両方のADRが参照する詳細な規範的製品仕様を持ちます。
リフレクション再ビルドはスライスベース
Section titled “リフレクション再ビルドはスライスベース”作業回答:リフレクション入力はソースによって層化され、宣言、メンバーエントリー、シングルトンオブジェクト、シェイププロバイダ、生成されたシグネチャ単位、プラグイン動的メンバープロバイダなどの安定したスライスによってキャッシュされます。
診断Provenanceは公開プレフィックスと内部詳細を使用する
Section titled “診断Provenanceは公開プレフィックスと内部詳細を使用する”作業回答:公開診断識別子はPHPStanエラー識別子と同様のソースファミリープレフィックスを使用すべきです。内部的には、診断は説明、キャッシュキー、将来の抑制ポリシーのためにより豊富なprovenanceを保持します。
互換性はgemバージョンとテストスイートを最初に使用する
Section titled “互換性はgemバージョンとテストスイートを最初に使用する”作業回答:最初の公開契約はRuby gem版の依存関係、文書化された公開名前空間、明示的な内部名前空間、Rigor提供の適合テストスイートに依存すべきです。
広い式と演算子フックは延期される
Section titled “広い式と演算子フックは延期される”作業回答:最初の公開プラグインマイルストーンは、具体的なフレームワークのユースケースが狭いフックで表現できない場合を除いて、広い式と演算子フックを延期すべきです。
却下および延期された候補決定
Section titled “却下および延期された候補決定”| 候補 | ステータス | 理由 |
|---|---|---|
| すべてを検査して上書きできる1つの汎用プラグインフック | 却下 | PHPStanの狭い拡張タイプは推論、キャッシュ、テスト、文書化が容易です。 |
| プラグインが現在のスコープを直接変更することを許可する | 却下 | スコープの変異はCFAを順序依存にします。 |
| フレームワーク動作を発見するためにアプリケーションコードを実行する | 却下 | Rigorはゼロランタイム依存の静的解析器であり続けます。 |
| PHPDocまたはRigor固有のインラインRubyコメントを主な拡張インターフェースにする | 却下 | Rigorは新しいアプリケーションコードアノテーションDSLを発明すべきではありません。 |
| 型推論アサーションヘルパーをアプリケーションRubyの一部にする | 却下 | アサーションマーカーはフィクスチャハーネス構文のみです。 |
| gem互換性が不十分と証明される前に別の拡張プロトコルバージョンを導入する | 延期 | Ruby gem版の依存関係、文書化された公開名前空間、明示的な内部名前空間、Rigor提供の適合テストが最初の公開互換性契約を担うべきです。 |
| MVPですべてのPHPStanスタイルの拡張ポイントを出荷する | 延期 | 動的戻り値型、型指定拡張、動的リフレクションが最も即時の価値を提供します。 |
オープンクエスチョン
Section titled “オープンクエスチョン”- Ractor分離下のプラグイン契約(ADR-15フェーズ3)。
Analysis::RunnerRactorワーカープールが着地するとき(フェーズ4)、プラグインインスタンスはRactorごとである必要があります: 各ワーカーは共有レジストリの凍結されたファクトリー + マニフェストメタデータから自身のプラグインを実体化します。flow_contribution_for/diagnostics_for_fileフックで実行ごとの可変状態を蓄積するプラグイン(rigor-sorbetの@reachable_absurd_nodes/@reveal_type_calls/@assert_type_mismatchescompare_by_identityHashesが正典の例)は、その状態をPlugin::FactStore(すでにクロスRactor調整済み)経由でルーティングするか、Ractorごとの分離を受け入れる必要があります(MUST)。フェーズ3のADR-2修正案が選ばれた形状を固定します;現在テーブル上の3つの候補はADR-15 § OQ2に記録されています。 - 動的戻り値拡張は最初に名前的レシーバー型のみで一致すべきか、それとも構造的インターフェースとオブジェクトシェイプでも一致すべきか?
- 最初のプラグインマニフェスト形式と設定スキーマ言語は何か?
- Rigorは最初のカスタムルールマイルストーンでルールに合成または仮想ASTノードを公開すべきか?
&&または||の右側を解析中にのみ存在するファクトを含む、Rubyフィクスチャで推論された型とブランチローカルファクトをアサートするための正確なフィクスチャマーカースペルは何か?- プラグインが完全、部分的、除外、または
maybeのケイパビリティロール適合を宣言するために使用する正確なペイロードは何か? - 衝突するプラグイン、生成された、および
RBS::Extendedの貢献にRigorが使用する正確な診断識別子分類体系と表示形式は何か? - ソース、RBS、生成、プラグイン提供のスライスを表す正確なリフレクションキャッシュキースキーマと永続形式は何か?
- 広い式または演算子フックが後で有効になる場合、どの具体的な呼び出し予算、タイムアウト動作、走査順序保証、トレース出力を使用すべきか?
ポジティブ:
- Rigorはフレームワーク固有のRuby動作をコアにハードコードせずにサポートできます。
- 拡張著者は安定したコンテキストオブジェクトを持つ集中したプロトコルを得ます。
- コア解析器はフロー適用、正規化、診断、キャッシングの所有権を維持します。
- PHPStanのScope、Type、Reflection、拡張サービス間の分離はRigorにプラグインAPIの実証済みの形状を与えます。
ネガティブ:
- 公開拡張プロトコルは互換性の義務を作成します。
- 有用なプラグインAPIはコアのみのMVPよりも早く慎重な型、スコープ、リフレクションオブジェクトの設計を必要とします。
- 広いフックは規律なしに導入されると、パフォーマンスや予測可能性を損なう可能性があります。
- プラグインテストハーネスはサポートされた開発者体験の一部になります。
© 2026 TypedDuck. Licensed under CC BY-SA 4.0.