Phan から PhanUndeclaredTypeProperty やら PhanUndeclaredMethod やら PhanUndeclaredClassMethod やら PhanUndeclaredFunction と叱られる
助っ人メンバーを入れたのに、一部の熱狂的なファンが認めてくれず活動できません。
<?php
declare(strict_types=1);
namespace MYNAME\MYPACKAGE;
use Symfony\Component\Cache\Adapter\FilesystemAdapter; //助っ人。でも Phan からは「こんなやつ、聞いとらん」と怒られる
class MyClass
{
/** @var FilesystemAdapter */ //← Phan から「こんなやつ、しらん」と怒られる
protected $my_property;
public function __construct()
{
$this->my_property = new FilesystemAdapter();
}
public function set(string $key, $value)
{
$cache_item = $this->cache_pool->getItem($key); //← Phan から「そんなん、できん」と叱られる
$cache_item->set($value); //← Phan から「なんやそれ」と叱られる
$this->cache_pool->save($cache_item); //← Phan から「出なおしてこい」と叱られる
}
}
PhanUndeclaredTypeProperty Property \MYNAME\MYPACKAGE\MyClass->my_property has undeclared type \Symfony\Component\Cache\Adapter\FilesystemAdapter
phan PhanUndeclaredClassMethod Call to method __construct from undeclared class ...
FilesystemAdapter
オブジェクトのメソッド、例えば getItem()
を使っても、「そんなメンバー(メソッド)しらんし、聞いとらん」と叱られます。use
で告知したよ?
PhanUndeclaredMethod Call to undeclared method \MYNAME\MYPACKAGE\MyClass->my_property->getItem($key)
TS; DR
Phan が
vendor
ディレクトリなどにある依存パッケージ(ライブラリ)を読み込んでから静的解析をしていないことが原因です。
各メソッドの PHPDoc コメントに @suppress PhanUndeclaredClassMethod
を追加してもいいのですが、Phan の config.php
ファイルを作成して、対象ディレクトリに vendor
を追加しつつ解析対象対象から外すと、パッケージがインポートされるようになります。
<?php
return [
'directory_list' => [
'src',
'vendor/symfony', // use で使うパッケージを追加
],
'exclude_analysis_directory_list' => [
'vendor/' // 解析対象から除外
],
];
$ # --allow-polyfill-parser → php-ast がなくても解析する設定
$ # --config-file ./phan.php → 設定ファイルを指定
$ ./vendor/bin/phan --allow-polyfill-parser --config-file ./phan.php
...
TL; DR
作曲家(composer
)の言うことなんか聞かない Phan
PHP の静的解析ツール「Phan」は静的解析時、composer
などの autoloader
によるダイナミックなインポート先を参照しません。
そのため、use
で宣言しても解析時に必要なパッケージ/ライブラリがインポートされていないため解析エラーが出ます。
suppress
コメント(エラー無視コメント)の「@suppress PhanUndeclaredClassMethod
」を PHPDoc のブロックコメントに入れて黙殺してもいいのですが、やはり Phan の意見は尊重したいものです。
色々ググってみたのですが、Phan の公式 Wiki の FAQ にちゃんと載ってました。
Phan says that a composer dependency of my project(a class, constant, or function) is undeclared
- You must add the directory (or file) of that dependency to
'directory_list'
or'file_list'
in.phan/config.php
. Usually, you will want to add'vendor'
to'exclude_analysis_directory_list'
as well. See https://github.com/phan/phan/wiki/Getting-Started#creating-a-config-file- Make sure that the file exists in vendor/ (e.g. make sure that
composer.phar install
was executed if this is running in CI)- Make sure that there are no typos in the variable name, that the namespace of the class is correct, and that the file containing the class/constant/function exists.
This is a common cause of
PhanUndeclaredClassMethod
,PhanUndeclaredClass
,PhanUndeclaredFunction
, etc.
(Frequently Asked Questions | Phan 公式 Wiki @ GitHub より)(筆者適当訳)
作曲家による(クラス、定数、または関数)の依存関係に対し、熱狂的なファンが「宣言していない」と怒っています。
- 依存関係のディレクトリ(またはファイル)を
.phan/config.php
の'directory_list'
もしくは'file_list'
に追加する必要があります。その場合、一般的に'vendor'
ディレクトリを'exclude_analysis_directory_list'
にも追加します。詳しくは https://github.com/phan/phan/wiki/Getting-Started#creating-a-config-file を参照ください。- ファイルが
vendor/
以下に存在することを確認してください。(たとえば CI で解析を実行する場合に「あらかじめcomposer.phar install
が実行されているか」などです)- 変数名にタイプミスがないこと、クラスの名前空間が正しいこと、およびクラス/定数/関数を含むファイルが存在することを確認してください。
これは
PhanUndeclaredClassMethod
、PhanUndeclaredClass
、PhanUndeclaredFunction
などが発生する「あるある」な原因です。
とほほ。
参考文献
- Creating a Config File | Phan 公式 Wiki @ GitHub
- このPHPがテンプレートエンジンのくせに慎重すぎる (中篇) @ Qiita
- Phanで静的解析 @ Qiita