rector/README.md

528 lines
15 KiB
Markdown
Raw Normal View History

# Rector - Upgrade Your Legacy App to a Modern Codebase
2017-07-15 17:20:20 +00:00
Rector is a **rec**onstruc**tor** tool - it does **instant upgrades** and **instant refactoring** of your code.
2020-03-21 10:41:11 +00:00
Why refactor manually if Rector can handle 80% of the task for you?
2018-02-02 16:51:41 +00:00
2018-11-09 13:45:14 +00:00
[![Coverage Status](https://img.shields.io/coveralls/rectorphp/rector/master.svg?style=flat-square)](https://coveralls.io/github/rectorphp/rector?branch=master)
2018-07-02 13:02:27 +00:00
[![Downloads](https://img.shields.io/packagist/dt/rector/rector.svg?style=flat-square)](https://packagist.org/packages/rector/rector)
2020-07-30 22:30:25 +00:00
[![SonarCube](https://img.shields.io/badge/SonarCube_Debt-%3C27-brightgreen.svg?style=flat-square)](https://sonarcloud.io/dashboard?id=rectorphp_rector)
2017-07-15 17:20:20 +00:00
2020-02-21 14:26:02 +00:00
<br>
2020-04-14 19:52:27 +00:00
- **[Online DEMO](https://getrector.org/demo)**
2020-06-17 10:12:34 +00:00
- [Explore 500+ Rector Rules](/docs/rector_rules_overview.md)
2020-02-21 14:26:02 +00:00
2020-05-03 12:32:03 +00:00
---
2020-02-13 16:13:49 +00:00
![Rector-showcase](docs/images/rector-showcase-var.gif)
2018-01-13 15:01:31 +00:00
2019-04-29 21:42:11 +00:00
<br>
## Sponsors
Rector grows faster with your help, the more you help the more work it saves you.
2020-03-21 10:41:11 +00:00
Check out [Rector's Patreon](https://www.patreon.com/rectorphp). One-time donations are welcome [through PayPal](https://www.paypal.me/rectorphp).
2019-04-29 21:42:11 +00:00
2019-08-19 13:49:41 +00:00
Thank you:
2020-06-18 10:38:01 +00:00
<p>
2020-06-18 10:43:11 +00:00
<a href="https://www.startupjobs.cz/en/startup/scrumworks-s-r-o"><img src="/docs/images/amateri.png"></a>
<img src="/docs/images/space.png" width=40>
2020-06-17 12:16:17 +00:00
<a href="https://zenika.ca/en/en"><img src="/docs/images/zenika.png"></a>
<img src="/docs/images/space.png" width=40>
<a href="https://spaceflow.io/en"><img src="/docs/images/spaceflow.png"></a>
</p>
2019-08-19 13:49:41 +00:00
2019-04-29 21:42:11 +00:00
<br>
## Open-Source First
2020-05-03 12:32:37 +00:00
Rector **instantly upgrades and instantly refactors the PHP code of your application**.
It supports all versions of PHP from 5.2 and many open-source projects:
2017-07-15 17:20:20 +00:00
2018-10-21 09:00:39 +00:00
<br>
2017-10-30 15:00:28 +00:00
<p align="center">
2019-06-08 20:41:52 +00:00
<a href="/config/set/php"><img src="/docs/images/php.png"></a>
2019-10-20 14:46:52 +00:00
<img src="/docs/images/space.png" width=40>
2019-06-08 20:41:52 +00:00
<a href="/config/set/symfony"><img src="/docs/images/symfony.png"></a>
2019-10-20 14:46:52 +00:00
<img src="/docs/images/space.png" width=40>
2019-10-20 14:47:40 +00:00
<a href="/config/set/laravel"><img src="/docs/images/laravel.png"></a>
<img src="/docs/images/space.png" width=40>
<a href="/config/set/twig"><img src="/docs/images/twig.png"></a>
2019-10-20 14:47:40 +00:00
<br>
2020-05-25 00:29:13 +00:00
<a href="https://github.com/palantirnet/drupal-rector/tree/master/config/drupal-8"><img src="/docs/images/drupal.png" alt="Drupal Rector rules"></a>
<img src="/docs/images/space.png" width=40>
2019-10-20 14:47:40 +00:00
<a href="/config/set/cakephp"><img src="/docs/images/cakephp.png"></a>
<img src="/docs/images/space.png" width=40>
<a href="/config/set/phpunit"><img src="/docs/images/phpunit.png"></a>
2017-10-30 15:00:28 +00:00
</p>
2017-08-20 15:40:19 +00:00
2018-10-21 09:00:39 +00:00
<br>
## What Can Rector Do for You?
2018-08-01 20:29:01 +00:00
2020-06-17 10:12:34 +00:00
- [Upgrade 30 000 unit tests from PHPUnit 6 to 9 in 2 weeks](https://twitter.com/LBajsarowicz/status/1272947900016967683)
- Complete [@var annotations or parameter/return type declarations](https://www.tomasvotruba.com/blog/2019/01/03/how-to-complete-type-declarations-without-docblocks-with-rector/)
2020-01-14 21:20:38 +00:00
- [Complete PHP 7.4 property type declarations](https://www.tomasvotruba.com/blog/2018/11/15/how-to-get-php-74-typed-properties-to-your-code-in-few-seconds/)
2020-06-17 10:12:34 +00:00
- Upgrade your code from **PHP 5.3 to 8.0**
- [Migrate your project from Nette to Symfony](https://www.tomasvotruba.com/blog/2019/02/21/how-we-migrated-from-nette-to-symfony-in-3-weeks-part-1/)
2020-01-14 21:20:38 +00:00
- [Refactor Laravel facades to dependency injection](https://www.tomasvotruba.com/blog/2019/03/04/how-to-turn-laravel-from-static-to-dependency-injection-in-one-day/)
2017-12-28 19:58:35 +00:00
- And much more...
2017-07-15 17:20:20 +00:00
## How to Apply Coding Standards?
Rector uses [nikic/php-parser](https://github.com/nikic/PHP-Parser/), that build on technology called *abstract syntax tree* (AST). AST doesn't care about spaces and produces mall-formatted code. That's why your project needs to have coding standard tool and set of rules, so it can make refactored nice and shiny again.
Don't have any coding standard tool? Add [EasyCodingStandard](https://github.com/Symplify/EasyCodingStandard) and use prepared [`ecs-after-rector.php`](/ecs-after-rector.php) set.
2019-11-08 17:02:29 +00:00
2017-07-15 17:20:20 +00:00
## Install
```bash
composer require rector/rector --dev
2017-07-15 17:20:20 +00:00
```
2020-05-03 12:32:03 +00:00
- Having conflicts during `composer require`? → Use the [Rector Prefixed](https://github.com/rectorphp/rector-prefixed)
- Using a different PHP version than Rector supports? → Use the [Docker image](#run-rector-in-docker)
2019-11-08 16:49:03 +00:00
## Running Rector
### A. Prepared Sets
2019-11-08 16:49:03 +00:00
2020-07-20 12:18:15 +00:00
Featured open-source projects have **prepared sets**. You can find them in [`/config/set`](/config/set) or by autocomplete of [`Rector\Set\ValueObject\SetList`](/packages/set/src/ValueObject/SetList.php) constants in `rector.php` config.
2019-11-08 16:49:03 +00:00
2020-07-20 12:18:15 +00:00
Let's say you pick the [`symfony40`](/config/set/symfony40.php) set and you want to upgrade your `/src` directory:
2019-11-08 16:49:03 +00:00
```bash
vendor/bin/rector process src --set symfony40 --dry-run
```
2020-07-20 12:18:15 +00:00
Rector will show you diff of files that it *would* change. To *make* the changes, drop `--dry-run`:
2019-11-08 16:49:03 +00:00
```bash
# apply upgrades to your code
vendor/bin/rector process src --set symfony40
```
Some sets, such as [`code-quality`](/config/set/code-quality.php) can be used on a regular basis. **The best practice is to use config over command line**:
2020-07-18 18:26:57 +00:00
```php
<?php
2020-07-20 12:18:15 +00:00
// rector.php
2020-07-18 18:26:57 +00:00
declare(strict_types=1);
use Rector\Core\Configuration\Option;
2020-07-20 12:18:15 +00:00
use Rector\Set\ValueObject\SetList;
2020-07-18 18:26:57 +00:00
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
return static function (ContainerConfigurator $containerConfigurator): void {
$parameters = $containerConfigurator->parameters();
2020-07-20 12:18:15 +00:00
$parameters->set(Option::SETS, [SetList::CODE_QUALITY]);
2020-07-18 18:26:57 +00:00
};
```
2020-07-20 12:18:15 +00:00
PHP config format is a new [Symfony best practice](https://twitter.com/symfony_en/status/1284538366147678208).
### B. Standalone Rules
2019-11-08 16:49:03 +00:00
In the end, it's best to combine few of basic sets and drop [particular rules](/docs/rector_rules_overview.md) that you want to try:
2019-11-08 16:49:03 +00:00
```php
<?php
// rector.php
declare(strict_types=1);
2019-11-08 16:49:03 +00:00
use Rector\Core\Configuration\Option;
use Rector\Set\ValueObject\SetList;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Rector\Php74\Rector\Property\TypedPropertyRector;
return static function (ContainerConfigurator $containerConfigurator): void {
$parameters = $containerConfigurator->parameters();
$services = $containerConfigurator->services();
$services->set(TypedPropertyRector::class);
$parameters->set(Option::SETS, [SetList::CODE_QUALITY]);
};
```
2019-11-08 16:49:03 +00:00
2020-05-03 12:30:47 +00:00
Then let Rector refactor your code:
2019-11-08 16:49:03 +00:00
```bash
vendor/bin/rector process src
```
:+1:
<br>
*Note: `rector.php` is loaded by default. For different location, use `--config` option.*
2019-11-08 16:49:03 +00:00
## Features
2020-05-13 16:17:21 +00:00
### Paths
If you're annoyed by repeating paths in arguments, you can move them to config instead:
```php
<?php
// rector.php
declare(strict_types=1);
use Rector\Core\Configuration\Option;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
return static function (ContainerConfigurator $containerConfigurator): void {
$parameters = $containerConfigurator->parameters();
$parameters->set(Option::PATHS, [
__DIR__ . '/src',
__DIR__ . '/tests',
]);
};
2020-05-13 16:17:21 +00:00
```
### Extra Autoloading
2020-03-21 10:41:11 +00:00
Rector relies on whatever autoload setup the project it is fixing is using by using the Composer autoloader as default. To specify your own autoload file, use `--autoload-file` option:
2018-02-09 00:16:54 +00:00
```bash
2018-02-08 14:27:14 +00:00
vendor/bin/rector process ../project --autoload-file ../project/vendor/autoload.php
```
Or use a `rector.php` configuration file:
```php
<?php
// rector.php
declare(strict_types=1);
use Rector\Core\Configuration\Option;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
return static function (ContainerConfigurator $containerConfigurator): void {
$parameters = $containerConfigurator->parameters();
$parameters->set(Option::AUTOLOAD_PATHS, [
__DIR__ . '/vendor/squizlabs/php_codesniffer/autoload.php',
__DIR__ . '/vendor/project-without-composer',
]);
};
```
2019-11-08 12:08:42 +00:00
### Exclude Paths and Rectors
2019-01-18 11:41:07 +00:00
2018-11-09 13:58:49 +00:00
You can also **exclude files or directories** (with regex or [fnmatch](http://php.net/manual/en/function.fnmatch.php)):
```php
<?php
// rector.php
declare(strict_types=1);
use Rector\Core\Configuration\Option;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
return static function (ContainerConfigurator $containerConfigurator): void {
$parameters = $containerConfigurator->parameters();
$parameters->set(Option::EXCLUDE_PATHS, [
__DIR__ . '/src/*/Tests/*',
]);
};
```
2020-05-13 16:17:21 +00:00
You can use a whole set, except 1 rule:
2019-01-18 11:41:07 +00:00
```php
<?php
// rector.php
declare(strict_types=1);
use Rector\CodeQuality\Rector\If_\SimplifyIfReturnBoolRector;
use Rector\Core\Configuration\Option;
use Rector\Set\ValueObject\SetList;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
return static function (ContainerConfigurator $containerConfigurator): void {
$parameters = $containerConfigurator->parameters();
$parameters->set(Option::SETS, [
SetList::CODE_QUALITY,
]);
$parameters->set(Option::EXCLUDE_RECTORS, [
SimplifyIfReturnBoolRector::class,
]);
};
2019-01-18 11:41:07 +00:00
```
2020-05-13 16:17:21 +00:00
For in-file exclusion, use `@noRector \FQN name` annotation:
2019-12-29 12:00:38 +00:00
```php
class SomeClass
{
/**
* @noRector \Rector\DeadCode\Rector\ClassMethod\RemoveEmptyClassMethodRector
*/
public function foo()
{
/** @noRector \Rector\DeadCode\Rector\Plus\RemoveDeadZeroAndOneOperationRector */
round(1 + 0);
}
}
```
### Run Just 1 Rector Rule
2020-06-17 12:33:58 +00:00
Do you have config that includes many sets and Rectors? You might want to run only a single Rector. The `--only` argument allows that, e.g.:
2020-06-17 12:33:58 +00:00
```bash
vendor/bin/rector process src --set solid --only Rector\SOLID\Rector\Class_\FinalizeClassesWithoutChildrenRector
2020-06-17 12:33:58 +00:00
```
Or just short name:
2020-06-17 12:33:58 +00:00
```bash
vendor/bin/rector process src --set solid --only FinalizeClassesWithoutChildrenRector
```
Both will run only `Rector\SOLID\Rector\Class_\FinalizeClassesWithoutChildrenRector`.
2020-06-17 12:33:58 +00:00
2019-11-08 12:08:42 +00:00
### Provide PHP Version
By default Rector uses the language features matching your system version of PHP. You can configure it for a different PHP version:
2019-02-23 13:03:07 +00:00
```php
<?php
// rector.php
declare(strict_types=1);
use Rector\Core\Configuration\Option;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
return static function (ContainerConfigurator $containerConfigurator): void {
$parameters = $containerConfigurator->parameters();
$parameters->set(Option::PHP_VERSION_FEATURES, '7.2'); # your version is 7.3
};
2019-02-23 13:03:07 +00:00
```
2020-06-16 19:43:45 +00:00
### Safe Types
2020-06-19 16:03:37 +00:00
In default setting:
2020-06-16 19:43:45 +00:00
```php
<?php
// rector.php
declare(strict_types=1);
use Rector\Core\Configuration\Option;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
return static function (ContainerConfigurator $containerConfigurator): void {
$parameters = $containerConfigurator->parameters();
$parameters->set(Option::SAFE_TYPES, false);
};
2020-06-16 19:43:45 +00:00
```
All docblocks are taken seriously, e.g. with [typed properties](https://github.com/rectorphp/rector/blob/master/docs/rector_rules_overview.md#typedpropertyrector) rule:
```diff
<?php
class ValueObject
{
- public $value;
+ public string $value;
/**
* @param string $value
*/
public function __construct($value)
{
$this->value = $value;
}
}
```
Do you want to use only explicit PHP type declaration? Enable `safe_types`:
```php
<?php
// rector.php
declare(strict_types=1);
use Rector\Core\Configuration\Option;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
return static function (ContainerConfigurator $containerConfigurator): void {
$parameters = $containerConfigurator->parameters();
$parameters->set(Option::SAFE_TYPES, true);
};
2020-06-16 19:43:45 +00:00
```
Then, docblocks are skipped:
```diff
<?php
class ValueObject
{
public $value;
- public $count;
+ public int $count;
/**
* @param string $value
*/
2020-06-16 21:06:16 +00:00
public function __construct($value, int $count)
2020-06-16 19:43:45 +00:00
{
$this->value = $value;
$this->count = $count
}
}
```
2019-11-08 12:08:42 +00:00
### Import Use Statements
2020-04-04 20:59:33 +00:00
FQN classes are not imported by default. If you don't want to do it manually after every Rector run, enable it by:
2019-10-12 15:51:07 +00:00
```php
<?php
// rector.php
declare(strict_types=1);
use Rector\Core\Configuration\Option;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
return static function (ContainerConfigurator $containerConfigurator): void {
$parameters = $containerConfigurator->parameters();
$parameters->set(Option::AUTO_IMPORT_NAMES, true);
};
2019-10-12 15:51:07 +00:00
```
2019-12-20 06:40:36 +00:00
You can also fine-tune how these imports are processed:
```php
<?php
// rector.php
declare(strict_types=1);
use Rector\Core\Configuration\Option;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
return static function (ContainerConfigurator $containerConfigurator): void {
$parameters = $containerConfigurator->parameters();
2019-12-20 06:40:36 +00:00
// this will not import root namespace classes, like \DateTime or \Exception
$parameters->set(Option::IMPORT_SHORT_CLASSES, false);
// this will not import classes used in PHP DocBlocks, like in /** @var \Some\Class */
$parameters->set(Option::IMPORT_DOC_BLOCKS, false);
};
```
### Limit Execution to Changed Files
Execution can be limited to changed files using the `process` option `--match-git-diff`.
This option will filter the files included by the configuration, creating an intersection with the files listed in `git diff`.
```bash
vendor/bin/rector process src --match-git-diff
```
This option is useful in CI with pull-requests that only change few files.
2019-12-16 14:45:37 +00:00
### Symfony Container
To work with some Symfony rules, you now need to link your container XML file
```php
<?php
// rector.php
declare(strict_types=1);
use Rector\Core\Configuration\Option;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
return static function (ContainerConfigurator $containerConfigurator): void {
$parameters = $containerConfigurator->parameters();
$parameters->set(Option::SYMFONY_CONTAINER_XML_PATH_PARAMETER, __DIR__ . '/var/cache/dev/AppKernelDevDebugContainer.xml');
};
2019-12-16 14:45:37 +00:00
```
2020-05-13 16:17:21 +00:00
<br>
2017-12-28 19:58:35 +00:00
## More Detailed Documentation
2017-10-15 09:07:53 +00:00
- **[All Rectors Overview](/docs/rector_rules_overview.md)**
- [Create own Rule](/docs/create_own_rule.md)
- [Generate Rector from Recipe](/docs/rector_recipe.md)
- [How Does Rector Work?](/docs/how_it_works.md)
- [PHP Parser Nodes Overview](/docs/nodes_overview.md)
- [Add Checkstyle with your CI](/docs/checkstyle.md)
2017-10-15 09:07:53 +00:00
2020-05-13 16:17:21 +00:00
<br>
2017-12-28 19:58:35 +00:00
## How to Contribute
2017-07-15 17:20:20 +00:00
See [the contribution guide](/CONTRIBUTING.md).
2018-12-12 09:02:10 +00:00
2020-05-13 16:17:21 +00:00
<br>
## Run Rector in Docker
You can run Rector on your project using Docker:
2018-12-12 09:02:10 +00:00
```bash
docker run --rm -v $(pwd):/project rector/rector:latest process /project/src --set symfony40 --dry-run
2019-03-11 14:12:27 +00:00
2019-10-26 01:11:11 +00:00
# Note that a volume is mounted from `pwd` (the current directory) into `/project` which can be accessed later.
2018-12-11 17:22:54 +00:00
```
Using `rector.php`:
```bash
docker run --rm -v $(pwd):/project rector/rector:latest process /project/app \
--config /project/rector.php \
--autoload-file /project/vendor/autoload.php \
--dry-run
```
2020-05-13 16:17:21 +00:00
<br>
2020-07-07 15:58:55 +00:00
### Debugging
2020-07-07 15:59:41 +00:00
1. Make sure XDebug is installed and configured
2. Add `--xdebug` option when running Rector
2020-07-07 15:58:55 +00:00
2020-07-07 15:59:41 +00:00
Without XDebug, you can use `--debug` option, that will print nested exceptions output.
2020-07-07 15:58:55 +00:00
<br>
2020-05-13 16:17:21 +00:00
## Community Packages
Do you use Rector to upgrade your code? Add it here:
- [palantirnet/drupal-rector](https://github.com/palantirnet/drupal-rector) by [Palantir.net](https://github.com/palantirnet) for [Drupal](https://www.drupal.org/)
2019-10-25 01:04:18 +00:00
- [sabbelasichon/typo3-rector](https://github.com/sabbelasichon/typo3-rector) for [TYPO3](https://typo3.org/)