rector/README.md

373 lines
11 KiB
Markdown
Raw Normal View History

# Rector - Upgrade Your Legacy App to a Modern Codebase
2017-07-15 19:20:20 +02:00
Rector is a **rec**onstruc**tor** tool - it does **instant upgrades** and **instant refactoring** of your code.
2020-03-21 11:41:11 +01:00
Why refactor manually if Rector can handle 80% of the task for you?
2018-02-02 17:51:41 +01:00
2018-11-09 14:45:14 +01: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 15:02:27 +02:00
[![Downloads](https://img.shields.io/packagist/dt/rector/rector.svg?style=flat-square)](https://packagist.org/packages/rector/rector)
2020-07-31 00:30:25 +02: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 19:20:20 +02:00
2020-02-21 15:26:02 +01:00
<br>
2020-04-14 21:52:27 +02:00
- **[Online DEMO](https://getrector.org/demo)**
2020-06-17 12:12:34 +02:00
- [Explore 500+ Rector Rules](/docs/rector_rules_overview.md)
2020-02-21 15:26:02 +01:00
2020-05-03 14:32:03 +02:00
---
2020-02-13 17:13:49 +01:00
![Rector-showcase](docs/images/rector-showcase-var.gif)
2018-01-13 16:01:31 +01:00
2019-04-29 23:42:11 +02:00
<br>
## Sponsors
Rector grows faster with your help, the more you help the more work it saves you.
2020-03-21 11:41:11 +01: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 23:42:11 +02:00
2019-08-19 15:49:41 +02:00
Thank you:
2020-06-18 12:38:01 +02:00
<p>
2020-06-18 12:43:11 +02: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 14:16:17 +02: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 15:49:41 +02:00
2019-04-29 23:42:11 +02:00
<br>
## Open-Source First
2020-05-03 14:32:37 +02: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 19:20:20 +02:00
2018-10-21 11:00:39 +02:00
<br>
2017-10-30 16:00:28 +01:00
<p align="center">
2019-06-08 22:41:52 +02:00
<a href="/config/set/php"><img src="/docs/images/php.png"></a>
2019-10-20 16:46:52 +02:00
<img src="/docs/images/space.png" width=40>
2019-06-08 22:41:52 +02:00
<a href="/config/set/symfony"><img src="/docs/images/symfony.png"></a>
2019-10-20 16:46:52 +02:00
<img src="/docs/images/space.png" width=40>
2019-10-20 16:47:40 +02: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 16:47:40 +02:00
<br>
2020-05-24 20:29:13 -04: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 16:47:40 +02: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 16:00:28 +01:00
</p>
2017-08-20 17:40:19 +02:00
2018-10-21 11:00:39 +02:00
<br>
## What Can Rector Do for You?
2018-08-01 22:29:01 +02:00
2020-06-17 12:12:34 +02: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://tomasvotruba.com/blog/2019/01/03/how-to-complete-type-declarations-without-docblocks-with-rector/)
- [Complete PHP 7.4 property type declarations](https://tomasvotruba.com/blog/2018/11/15/how-to-get-php-74-typed-properties-to-your-code-in-few-seconds/)
2020-06-17 12:12:34 +02:00
- Upgrade your code from **PHP 5.3 to 8.0**
- [Migrate your project from Nette to Symfony](https://tomasvotruba.com/blog/2019/02/21/how-we-migrated-from-nette-to-symfony-in-3-weeks-part-1/)
- [Refactor Laravel facades to dependency injection](https://tomasvotruba.com/blog/2019/03/04/how-to-turn-laravel-from-static-to-dependency-injection-in-one-day/)
2017-12-28 17:58:35 -02:00
- And much more...
2017-07-15 19:20:20 +02:00
<br>
2019-11-08 18:02:29 +01:00
2017-07-15 19:20:20 +02:00
## Install
```bash
composer require rector/rector --dev
2017-07-15 19:20:20 +02:00
```
2020-05-03 14:32:03 +02: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)
<br>
2019-11-08 17:49:03 +01:00
## Running Rector
2019-11-08 17:49:03 +01:00
There a 2 main ways to use Rector:
2019-11-08 17:49:03 +01:00
- a *single rule*, to have the change under control - pick [from over 550 rules](/docs/rector_rules_overview.md)
- or group of rules called *sets* - pick from [sets](/config/set)
Sets are suitable for open-source projects and design patterns, like .
2019-11-08 17:49:03 +01:00
To use them, create a `rector.php` in your root directory:
2020-07-18 20:26:57 +02:00
```php
<?php
2020-07-20 14:18:15 +02:00
// rector.php
2020-07-18 20:26:57 +02:00
declare(strict_types=1);
use Rector\Core\Configuration\Option;
use Rector\Php74\Rector\Property\TypedPropertyRector;
2020-07-20 14:18:15 +02:00
use Rector\Set\ValueObject\SetList;
2020-07-18 20:26:57 +02:00
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
return static function (ContainerConfigurator $containerConfigurator): void {
// get parameters
2020-07-18 20:26:57 +02:00
$parameters = $containerConfigurator->parameters();
// here we can define, what sets of rules will be applied
$parameters->set(Option::SETS, [
SetList::CODE_QUALITY
]);
// get services
$services = $containerConfigurator->services();
2019-11-08 17:49:03 +01:00
// register single rule
$services->set(TypedPropertyRector::class);
};
```
<br>
Then dry run Rector:
```bash
vendor/bin/rector process src --dry-run
```
2019-11-08 17:49:03 +01:00
Rector will show you diff of files that it *would* change. To *make* the changes, drop `--dry-run`:
2019-11-08 17:49:03 +01:00
```bash
vendor/bin/rector process src
```
<br>
*Note: `rector.php` is loaded by default. For different location, use `--config` option.*
2019-11-08 17:49:03 +01:00
<br>
2020-05-13 18:17:21 +02:00
## Configuration
2020-05-13 18:17:21 +02:00
```php
<?php
// rector.php
declare(strict_types=1);
use Rector\CodeQuality\Rector\If_\SimplifyIfReturnBoolRector;
use Rector\Core\Configuration\Option;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
return static function (ContainerConfigurator $containerConfigurator): void {
$parameters = $containerConfigurator->parameters();
// paths to refactor; solid alternative to CLI arguments
$parameters->set(Option::PATHS, [
__DIR__ . '/src',
__DIR__ . '/tests',
]);
// is there a file you need to skip?
$parameters->set(Option::EXCLUDE_PATHS, [
// single file
__DIR__ . '/src/ComplicatedFile.php',
// or directory
__DIR__ . '/src/ComplicatedFile.php',
// or fnmatch
__DIR__ . '/src/*/Tests/*',
]);
// Rector relies on autoload setup of your project; Composer autoload is included by default; to add more:
$parameters->set(Option::AUTOLOAD_PATHS, [
// autoload specific file
__DIR__ . '/vendor/squizlabs/php_codesniffer/autoload.php',
// or full directory
__DIR__ . '/vendor/project-without-composer',
]);
// is there single rule you don't like from a set you use?
$parameters->set(Option::EXCLUDE_RECTORS, [
SimplifyIfReturnBoolRector::class,
]);
// is your PHP version different from the one your refactor to? [default: your PHP version]
$parameters->set(Option::PHP_VERSION_FEATURES, '7.2');
// auto import fully qualified class names? [default: false]
$parameters->set(Option::AUTO_IMPORT_NAMES, true);
// skip root namespace classes, like \DateTime or \Exception [default: true]
$parameters->set(Option::IMPORT_SHORT_CLASSES, false);
// skip classes used in PHP DocBlocks, like in /** @var \Some\Class */ [default: true]
$parameters->set(Option::IMPORT_DOC_BLOCKS, false);
};
2019-01-18 12:41:07 +01:00
```
### Ignore Rector Rule in File
2020-05-13 18:17:21 +02:00
For in-file exclusion, use `@noRector \FQN name` annotation:
2019-12-29 13:00:38 +01:00
```php
class SomeClass
{
/**
* @noRector
*/
const NAME = '102';
/**
* @noRector
2019-12-29 13:00:38 +01:00
*/
public function foo()
{
/** @noRector \Rector\DeadCode\Rector\Plus\RemoveDeadZeroAndOneOperationRector */
round(1 + 0);
}
}
```
### Run Just 1 Rector Rule
2020-06-17 14:33:58 +02: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 14:33:58 +02:00
```bash
vendor/bin/rector process src --set solid --only Rector\SOLID\Rector\Class_\FinalizeClassesWithoutChildrenRector
2020-06-17 14:33:58 +02:00
# or just a short class name
vendor/bin/rector process src --set solid --only FinalizeClassesWithoutChildrenRector
```
2020-06-16 21:43:45 +02:00
### Safe Types
**Experimental** feature
2020-06-16 21:43:45 +02:00
In default type resolving settings, all docblocks are taken seriously.
2020-06-16 21:43:45 +02: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();
// [default: false]
$parameters->set(Option::SAFE_TYPES, true);
};
2020-06-16 21:43:45 +02:00
```
E.g. the `TypedPropertyRector` rule will skip this case, as `string` is defined only in docblock:
2020-06-16 21:43:45 +02:00
```php
<?php
2020-06-16 21:43:45 +02:00
class ValueObject
{
public $value;
2020-06-16 21:43:45 +02:00
/**
* @param string $value
*/
public function __construct($value)
2020-06-16 21:43:45 +02:00
{
$this->value = $value;
}
}
```
### 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 15:45:37 +01: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 15:45:37 +01:00
```
2020-05-13 18:17:21 +02:00
<br>
2017-12-28 17:58:35 -02:00
## More Detailed Documentation
2017-10-15 11:07:53 +02: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 11:07:53 +02:00
2020-05-13 18:17:21 +02:00
<br>
2017-12-28 17:58:35 -02:00
## How to Contribute
2017-07-15 19:20:20 +02:00
See [the contribution guide](/CONTRIBUTING.md).
2018-12-12 10:02:10 +01:00
2020-05-13 18:17:21 +02:00
<br>
## Run Rector in Docker
You can run Rector on your project using Docker:
2018-12-12 10:02:10 +01:00
```bash
docker run --rm -v $(pwd):/project rector/rector:latest process /project/src --set symfony40 --dry-run
2019-03-11 16:12:27 +02:00
2019-10-25 18:11:11 -07:00
# Note that a volume is mounted from `pwd` (the current directory) into `/project` which can be accessed later.
2018-12-11 18:22:54 +01: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 18:17:21 +02:00
<br>
2020-07-07 17:58:55 +02:00
### Debugging
2020-07-07 17:59:41 +02:00
1. Make sure XDebug is installed and configured
2. Add `--xdebug` option when running Rector
2020-07-07 17:58:55 +02:00
2020-07-07 17:59:41 +02:00
Without XDebug, you can use `--debug` option, that will print nested exceptions output.
2020-07-07 17:58:55 +02:00
<br>
2020-05-13 18:17:21 +02: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-24 18:04:18 -07:00
- [sabbelasichon/typo3-rector](https://github.com/sabbelasichon/typo3-rector) for [TYPO3](https://typo3.org/)
## Known Drawbacks
### 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 in both PHP and docblock annotations. **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 [ECS](https://github.com/Symplify/EasyCodingStandard) and use prepared [`ecs-after-rector.php`](/ecs-after-rector.php) set.