背景
Be Framework では以下の2種類のエラーが実行時まで検出できない。いずれも Psalm プラグインで静的解析時に検出可能。
ルール1: Being コンストラクタのパラメータ属性チェック
問題
#[Be(...)] の変換先クラスのコンストラクタパラメータに #[Input] も #[Inject] もない場合、実行時に MissingParameterAttribute 例外が発生する。
// NG: $storage に属性がない → 実行時クラッシュ
final readonly class WeightLogged
{
public function __construct(
#[Input] string $recordedAt,
WeightStorageInterface $storage, // ← 実行するまでわからない
) {}
}
期待する挙動
Psalm が静的解析時にエラーを報告する。
ERROR: MissingBeingParameterAttribute
Parameter $storage in WeightLogged::__construct() must have #[Input] or #[Inject]
検出ロジック案
- コンストラクタに
#[Input] を持つパラメータが1つでも存在する → Being クラスと判定
- 同コンストラクタの全パラメータに
#[Input] または #[Inject] がなければエラー
ルール2: #[Validate] メソッドの例外型チェック
問題
#[Validate] メソッドが DomainException 以外の例外を throw しても、SemanticValidator の catch 節で捕捉されず素通りする。
// NG: RuntimeException は catch (DomainException) で捕捉されない
final class WeightKg
{
#[Validate]
public function validate(float $weightKg): void
{
throw new InvalidWeightException($weightKg); // RuntimeException を継承 → 素通り
}
}
期待する挙動
ERROR: InvalidValidateException
Exception InvalidWeightException thrown in #[Validate] method must extend DomainException
検出ロジック案
#[Validate] 属性を持つメソッドのボディを走査
throw 文の例外型が DomainException を継承していなければエラー
実装方針
- Psalm Plugin として実装(
vimeo/psalm ^6)
AfterClassLikeVisitInterface を使い AST から属性を検出
- カスタム Issue 型:
MissingBeingParameterAttribute, InvalidValidateException
composer require --dev be-framework/psalm-plugin で導入できる形が理想
参考
- 発見の経緯: be-semantic スキル を使った実装中に両エラーに遭遇
SemanticValidator::validateWithAttributes が catch (DomainException $exception) のみ捕捉している箇所が起点
背景
Be Framework では以下の2種類のエラーが実行時まで検出できない。いずれも Psalm プラグインで静的解析時に検出可能。
ルール1: Being コンストラクタのパラメータ属性チェック
問題
#[Be(...)]の変換先クラスのコンストラクタパラメータに#[Input]も#[Inject]もない場合、実行時にMissingParameterAttribute例外が発生する。期待する挙動
Psalm が静的解析時にエラーを報告する。
検出ロジック案
#[Input]を持つパラメータが1つでも存在する → Being クラスと判定#[Input]または#[Inject]がなければエラールール2:
#[Validate]メソッドの例外型チェック問題
#[Validate]メソッドがDomainException以外の例外を throw しても、SemanticValidatorの catch 節で捕捉されず素通りする。期待する挙動
検出ロジック案
#[Validate]属性を持つメソッドのボディを走査throw文の例外型がDomainExceptionを継承していなければエラー実装方針
vimeo/psalm^6)AfterClassLikeVisitInterfaceを使い AST から属性を検出MissingBeingParameterAttribute,InvalidValidateExceptioncomposer require --dev be-framework/psalm-pluginで導入できる形が理想参考
SemanticValidator::validateWithAttributesがcatch (DomainException $exception)のみ捕捉している箇所が起点