ingenerator/risky-rector-rules

A selection of Rector refactoring rules that should be used with caution

Maintainers

Package info

github.com/ingenerator/risky-rector-rules

pkg:composer/ingenerator/risky-rector-rules

Fund package maintenance!

acoulton

Statistics

Installs: 184

Dependents: 1

Suggesters: 0

Stars: 6

Open Issues: 0

v1.1.1 2026-04-10 09:36 UTC

This package is auto-updated.

Last update: 2026-04-17 21:56:38 UTC


README

This package provides automated refactoring rules for Rector that are likely to produce risky updates.

The Rector project are committed to shipping rules that can be trusted to run safely (see this discussion and this blog.

This library exists for the times where you want to perform unsafe refactorings. You can use these rules to automate the grunt work of modifying files, so you can instead spend your time carefully reviewing the changes.

When would I use these rules?

  • When you are preparing a major breaking release of a library
  • When you are beginning a major modernisation of a project

You should also have:

  • Comprehensive test coverage.
  • A static analyser (e.g. phpstan) and have resolved any issues it identifies.
  • Installed and run Rector with the standard / safe rules so that your code is modernised based on concrete types wherever possible.

We do not recommend using this package in your project long-term. The rules are intended to be for one-time modernisation - you should install it, configure it, run it & then remove it.

Installing and running the rules

Install the package with composer: composer require ingenerator/risky-rector-rules.

Ensure you have a clean working directory, and have already run and committed the changes from your existing Rector configuration.

Choose the rules you wish to use and add them to your rector.php config file:

return RectorConfig::configure()
    // ... your existing Rector config
    ->withRules([
      \Ingenerator\RiskyRectorRules\PhpDocToStrictTypes\AddParamTypeFromPhpDocRector::class,
      \Ingenerator\RiskyRectorRules\PhpDocToStrictTypes\AddPropertyTypeFromPhpDocRector::class,
      \Ingenerator\RiskyRectorRules\PhpDocToStrictTypes\AddReturnTypeFromPhpDocRector::class,
      // We recommend running this rule in a *separate* commit, as it may add void returns to methods
      // where the return type was accidentally undocumented.
      \Ingenerator\RiskyRectorRules\PhpDocToStrictTypes\AddImplicitVoidInterfaceReturnTypeRector::class,
    ]);

Run Rector vendor/bin/rector process, carefully review the result, and commit the changes.

Rules provided

PhpDocToStrictTypes

This group of rules will add strict types throughout your code based on existing phpdoc tags. Any redundant phpdoc will be removed as part of this process.

If your project is a library, these rules are almost guaranteed to produce breaking changes in your public API.

If you have a reasonable level of phpstan coverage proving that the phpdoc types in your codebase are correct, these changes may be relatively safe. Relatively...!

Name Purpose
AddParamTypeFromPhpDocRector Adds strict types to method parameters based on @param tags
AddPropertyTypeFromPhpDocRector Adds strict return types to properties based on @var tags
AddReturnTypeFromPhpDocRector Adds strict return types to methods based on @return tags
AddImplicitVoidInterfaceReturnTypeRector Adds strict void types to interface methods with no documented return

Only add types to interface methods

By default, AddParamTypeFromPhpDocRector and AddReturnTypeFromPhpDocRector will add strict types to methods in all classes and interfaces.

You can configure them to only modify interfaces by setting the interfaces_only option to true:

use Ingenerator\RiskyRectorRules\PhpDocToStrictTypes\AddMethodTypeConfig;

return RectorConfig::configure()
    ->withConfiguredRule(AddParamTypeFromPhpDocRector::class, [AddMethodTypeConfig::INTERFACES_ONLY => true])
    ->withConfiguredRule(AddReturnTypeFromPhpDocRector::class, [AddMethodTypeConfig::INTERFACES_ONLY => true]);

AddStrictTypes

These rules add strict types based on runtime type information.

AddParamTypeBasedOnParentClassMethodRector

This rule adds strict types to method parameters based on the type of the parameter in a parent class or interface method. Types will not be added or changed if the parameter is already typed.

This is similar to Rector's built-in AddReturnTypeDeclarationBasedOnParentClassMethodRector BUT it is risky. This is because classes are allowed to accept a wider type for method parameters than the parent class allows. Only run this rule if you want to enforce that child methods can only accept types that the parent class allows.

For example, this code is both valid and works:

class A {
  public function print(string $a) {
    echo $a;
  }
}

class B extends A {
{
  public function print($a) {
    echo $a ?? '{null}'
  }
}

$b = new B();
$b->print(null);

But this rule will change it to the following, which will break at runtime:

class A {
  public function print(string $a) {
    echo $a;
  }
}

class B extends A {
{
  public function print(string $a) {
    echo $a ?? '{null}'
  }
}

$b = new B();
$b->print(null);

Therefore you should only use this rule if you want to lock down the types that a child class can accept, for example as part of a breaking release of a PHP library.

Support this library

If you find this library useful, please consider sponsoring my Open Source work. One-time and recurring sponsorship helps me to spend time working on Open Source projects.

Credits

The initial implementation of the AddParamTypeFromPhpDocRector was based on a contribution by Michael Strelan to the Drupal project from March 2024.

At the time, that contribution had not been accepted and the implementation was no longer functional against current Rector versions. Additionally, their implementation differed in a number of respects from my desired requirements.

The implementation shipped in this library has therefore diverged quite significantly from the original inspiration, but Michael's work provided a useful starting point and so I'm very happy to credit it.

Contributing

Contributions - whether changes or new rules - are very welcome. However, we strongly recommend opening an issue to discuss your idea before working on any code. This will avoid wasting any time if your proposal does not fit with our vision for the library.

If you do decide to contribute, you should follow our coding style and add tests for every change.

Licence

Licensed under the BSD-3-Clause Licence