以下の内容はhttps://malsan.hatenablog.com/entry/2024/11/15/224610より取得しました。


【PHPStan】Internal error: Argument 1 passed to PHPStan\Analyser\RuleErrorTransformer::transform() must implement interface PHPStan\Rules\RuleError, string given

PHPStanを2.0にしただけなのに

PHPStan2.0出ましたね!早速自分も試してみました!

そして早速内部エラー!どうやらRuleErrorTransformerクラスのtransformメソッドが受け取っている引数の型がRuleErrorである必要があるのにstringが渡されている。とのこと。 スタックトレースを見た感じ、どうやらカスタムルールに対するテストが書いてあるファイルを解析している所でエラーが発生している様子。

./vendor/bin/phpstan -vvv analyze
-- ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
     Error                                                                                                                                                                                
-- ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
     Internal error: PHPStan\Analyser\RuleErrorTransformer::transform(): Argument #1 ($ruleError) must be of type PHPStan\Rules\RuleError, string given, called in                        
     phar:///Users/xyz/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/FileAnalyser.php on line 119 while analysing file                            
     /Users/xyz/tests/CustomRule.php                                                                                                
     Post the following stack trace to https://github.com/phpstan/phpstan/issues/new?template=Bug_report.yaml:                                                                            
     ## phar:///Users/xyz/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/RuleErrorTransformer.php(19)                                              
     #0 phar:///Users/xyz/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/FileAnalyser.php(119):                                                    
     PHPStan\Analyser\RuleErrorTransformer->transform('Sql::execute()\xE3...', Object(PHPStan\Analyser\MutatingScope), 'PhpParser\\Node\\...', 21)                                        

TL;DR

公式のUPGRADING.mdに書いてありました!ちゃんと読んでなくてすみません! github.com

カスタムルールで、メッセージを書く部分を以下のようにRuleErrorBuilderを使った書き方に変更することで直ります。

/**
 * @implements Rule<StaticCall>
 */
class SqlRule implements Rule
{
    public function getNodeType(): string
    {
        return StaticCall::class;
    }

    public function processNode(Node $node, Scope $scope): array
    {
        if (!$node->getArgs()[1]->value instanceof Node\Scalar\String_) {
-           return ['第二引数は文字列である必要があります。'];
+           return [RuleErrorBuilder::message('第二引数は文字列である必要があります。')->identifier('error')->build()];
        }

(identifierメソッドはあってもなくても良さそうでした)

詳細: processNodeの返り値の型が制限された

変更はこれですね。

github.com

実際に確認してみましょう。 2.0未満のPHPStanでは@return (string|RuleError)[] errorsとなっており、string[]が許容されています。

// phpstan-src/src/Rules/Rule.php

/**
 * @phpstan-param TNodeType $node
 * @return (string|RuleError)[] errors
 */

public function processNode(Node $node, Scope $scope): array;

一方2.0.xのブランチを確認するとlist<IdentifierRuleError>になっています。そしてこのIdentifierRuleErrorRuleErrorを継承しています。

/**
 * @phpstan-param TNodeType $node
 * @return list<IdentifierRuleError>
 */
public function processNode(Node $node, Scope $scope): array;

// IdentifierRuleErrorはRuleErrorを継承している。
// interface IdentifierRuleError extends RuleError

仮にstring[]の状態でカスタムルールが呼び出されるとFileAnalyser.phptranformメソッドにて、RuleError型を必要としている第一引数にstringが渡されることになり、TypeErrorを引き起こす。 という訳です。

// phpstan-src/src/Analyser/FileAnalyser.php line 144 ~ 146
foreach ($ruleErrors as $ruleError) {
  $temporaryFileErrors[] = $this->ruleErrorTransformer->transform($ruleError, $scope, $nodeType, $node->getStartLine());
}

まとめ

ちゃんと移行用のマニュアル読まなきゃね




以上の内容はhttps://malsan.hatenablog.com/entry/2024/11/15/224610より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14