今回は、Rector使ってみた話です。

PHP8にupdateすると、↓のようなエラーめちゃくちゃでてきませんか :thinking:

1x: Return type of HogeClass::jsonSerialize() should either be compatible with JsonSerializable::jsonSerialize(): mixed, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice

Rectorを使って#[ReturnTypeWillChangeRector]を付与すると、大量のDeprecation noticesをなくすことができターミナルをすっきりさせることができました✨

Rector とは

公式サイト:https://getrector.org/

PHP Coding Standards Fixer のように自動リファクタリングを行ってくるCLIツールです。

様々なリファクタリングルールが定義されており、それを使用することもできたり、独自のルールを定義して使用することも可能です。

https://getrector.org/demo でデモ実行することもできます。

使い方

GitHub: https://github.com/rectorphp/rector

  • PHPのバージョンやフレームワークのルール、独自作成したルールをsetしたrector.phpを作成
  • $ vendor/bin/rector process [target-dir] --dry-runでdiffを確認
  • 確認後、$ vendor/bin/rector process [target-dir]で実行

使用例: ReturnTypeWillChangeRectorを使い#[ReturnTypeWillChangeRector]を付与する

  • ルール: ReturnTypeWillChangeRectorをsetする
  • ArrayAccess::offsetGetはデフォルトで#[ReturnTypeWillChangeRector]が付与される
  • カスタムで他のメソッドにも付与することもできる(configure部分)
  $services = $containerConfigurator->services();
  $services
      ->set(ReturnTypeWillChangeRector::class)
      ->configure([ //ArrayAccess::offsetGet以外のメソッドにも追加したいので追記
          JsonSerializable::class => ['jsonSerialize'], 
          ArrayAccess::class => ['offsetExists', 'offsetSet', 'offsetUnset'],
      ])
  ;

:warning: mixedの扱い :warning:

当初は、ルール: ReturnTypeDeclarationRectorを使ってreturn typeを付与しようとしていました。

しかし、return type mixedに対応しておらず#[ReturnTypeWillChangeRector]を付与する対応にしました。

ルールReturnTypeDeclarationRectorを使いdry-runした際のRFCのリンクにもある通り、

$ vendor/bin/rector process lib --dry-run
...

Applied rules:
 * ReturnTypeDeclarationRector (https://wiki.php.net/rfc/scalar_type_hints_v5)

すべての関数にreturn typeを付与する義務は今のところないのでmixedはサポートしていないとのことです。

https://wiki.php.net/rfc/scalar_type_hints_v5 より

Why Not Add Support For MIXED? Some people would like adding mixed support in addition to other primitives.

Current Position Currently, there’s no mandate for fully typing all functions (even in strict mode). Therefore, there’s no functional difference between mixed and a non-type-declared paramter. For that reason, addition of a mixed type is outside of the scope for this proposal.

ちなみに、rector.phpの定義を以下のようにすると、関数指定であればreturn type mixedを付与することが可能でした。

  $services = $containerConfigurator->services();
  $services->set(ReturnTypeDeclarationRector::class);
  $services->set(AddReturnTypeDeclarationRector::class)->configure([//return type mixed付与したい関数を定義
      new AddReturnTypeDeclaration(JsonSerializable::class, 'jsonSerialize', new \PHPStan\Type\MixedType(true)),
      new AddReturnTypeDeclaration(ArrayAccess::class, 'offsetGet', new \PHPStan\Type\MixedType(true)),
  ]);

使ってみた感想

全体的に使いやすかったです🙆‍

ただ、自分が求めているルールを探すのが少し大変でした。