LoginSignup
0
1

More than 3 years have passed since last update.

【PHP】Phan の静的コード解析で use 指定したクラスオブジェクトを認識してくれない

Last updated at Posted at 2020-07-20

Phan から PhanUndeclaredTypeProperty やら PhanUndeclaredMethod やら PhanUndeclaredClassMethod やら PhanUndeclaredFunction と叱られる

助っ人メンバーを入れたのに、一部の熱狂的なファンが認めてくれず活動できません。

sample.php
<?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 を追加しつつ解析対象対象から外すと、パッケージがインポートされるようになります。

phan.php
<?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 が実行されているか」などです)
  • 変数名にタイプミスがないこと、クラスの名前空間が正しいこと、およびクラス/定数/関数を含むファイルが存在することを確認してください。

これは PhanUndeclaredClassMethodPhanUndeclaredClassPhanUndeclaredFunction などが発生する「あるある」な原因です。

とほほ。

参考文献

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1