2017-11-12 20:13:59 +01:00
|
|
|
# Rector Reconstructs your Legacy Code to Modern Codebase
|
2017-07-15 19:20:20 +02:00
|
|
|
|
2017-11-13 02:58:21 +01:00
|
|
|
[![Build Status](https://img.shields.io/travis/rectorphp/rector/master.svg?style=flat-square)](https://travis-ci.org/rectorphp/rector)
|
2017-11-13 15:31:35 +01:00
|
|
|
[![Coverage Status](https://img.shields.io/coveralls/RectorPHP/Rector/master.svg?style=flat-square)](https://coveralls.io/github/rectorphp/rector?branch=master)
|
2017-07-15 19:20:20 +02:00
|
|
|
|
2017-10-30 16:08:28 +01:00
|
|
|
Rector **upgrades your application** for you, with focus on open-source projects:
|
2017-07-15 19:20:20 +02:00
|
|
|
|
2017-10-30 16:00:28 +01:00
|
|
|
<p align="center">
|
2017-11-21 11:48:32 +01:00
|
|
|
<a href="/src/config/level/symfony"><img src="/docs/images/symfony.png"></a>
|
|
|
|
<img src="/docs/images/space.png">
|
|
|
|
<a href="/src/config/level/nette"><img src="/docs/images/nette.png" height="50"></a>
|
|
|
|
<img src="/docs/images/space.png">
|
|
|
|
<a href="/src/config/level/phpunit"><img src="/docs/images/phpunit.jpg"></a>
|
|
|
|
<img src="/docs/images/space.png">
|
|
|
|
<a href="/src/config/level/roave"><img src="/docs/images/roave.png"></a>
|
2017-10-30 16:00:28 +01:00
|
|
|
</p>
|
2017-08-20 17:40:19 +02:00
|
|
|
|
2017-10-30 16:08:28 +01:00
|
|
|
<br>
|
2017-07-15 19:20:20 +02:00
|
|
|
|
|
|
|
## Install
|
|
|
|
|
|
|
|
```bash
|
2017-11-18 16:55:00 +01:00
|
|
|
composer require --dev rector/rector @dev nikic/php-parser 'dev-master as v4.0.0alpha1'
|
2017-07-15 19:20:20 +02:00
|
|
|
```
|
|
|
|
|
2017-11-14 09:16:31 +01:00
|
|
|
Do you have old PHP or dependencies in conflict? Ok, [it is not problem](/docs/HowUseWithOldPhp.md).
|
|
|
|
|
2017-10-30 14:33:09 +01:00
|
|
|
## How To Reconstruct your Code?
|
|
|
|
|
|
|
|
### A. Prepared Sets
|
|
|
|
|
2017-10-30 15:44:00 +01:00
|
|
|
Fetaured open-source projects have **prepared sets**. You'll find them in [`/src/config/level`](/src/config/level).
|
2017-10-30 14:33:09 +01:00
|
|
|
|
2017-11-09 15:01:32 +01:00
|
|
|
E.g. Do you need to upgrade to Symfony 3.3?
|
2017-09-23 23:51:04 +02:00
|
|
|
|
2017-10-30 14:33:09 +01:00
|
|
|
1. Run rector on your `/src` directory
|
2017-09-23 23:51:04 +02:00
|
|
|
|
2017-10-30 14:33:09 +01:00
|
|
|
```bash
|
2017-11-09 15:01:32 +01:00
|
|
|
vendor/bin/rector process src --level symfony33
|
2017-09-23 23:51:04 +02:00
|
|
|
```
|
2017-10-30 14:33:09 +01:00
|
|
|
|
2017-11-09 12:17:31 +01:00
|
|
|
Which is just a shortcut for using complete path with `--config` option:
|
|
|
|
```bash
|
2017-11-09 15:01:32 +01:00
|
|
|
vendor/bin/rector process src --config vendor/rector/rector/src/config/level/symfony/symfony33.yml
|
2017-11-09 12:17:31 +01:00
|
|
|
```
|
|
|
|
|
|
|
|
You can also use your own config file:
|
2017-10-30 14:33:09 +01:00
|
|
|
|
|
|
|
```bash
|
2017-11-09 12:17:31 +01:00
|
|
|
vendor/bin/rector process src --config your-own-config.yml
|
2017-09-23 23:51:04 +02:00
|
|
|
```
|
|
|
|
|
2017-10-30 14:33:09 +01:00
|
|
|
2. Check the Git
|
2017-09-23 23:51:04 +02:00
|
|
|
|
|
|
|
```
|
2017-10-30 14:33:09 +01:00
|
|
|
git diff
|
2017-09-23 23:51:04 +02:00
|
|
|
```
|
|
|
|
|
2017-10-30 14:33:09 +01:00
|
|
|
|
|
|
|
### B. Custom Sets
|
2017-09-27 23:58:14 +02:00
|
|
|
|
|
|
|
1. Create `rector.yml` with desired Rectors
|
|
|
|
|
|
|
|
```yml
|
|
|
|
rectors:
|
2017-09-28 16:21:20 +02:00
|
|
|
- Rector\Rector\Contrib\Nette\Application\InjectPropertyRector
|
2017-09-27 23:58:14 +02:00
|
|
|
```
|
|
|
|
|
|
|
|
2. Run rector on your `/src` directory
|
2017-07-15 19:20:20 +02:00
|
|
|
|
|
|
|
```bash
|
2017-09-27 23:58:14 +02:00
|
|
|
vendor/bin/rector process src
|
|
|
|
```
|
|
|
|
|
|
|
|
3. Check the Git
|
|
|
|
|
|
|
|
```
|
|
|
|
git diff
|
2017-07-15 19:20:20 +02:00
|
|
|
```
|
|
|
|
|
2017-08-21 12:12:51 +02:00
|
|
|
|
2017-11-02 18:21:25 +01:00
|
|
|
### Simple setup with Dynamic Rectors
|
2017-10-07 10:58:54 +02:00
|
|
|
|
|
|
|
You don't have to always write PHP code. Many projects change only classes or method names, so it would be too much work for a simple task.
|
|
|
|
|
|
|
|
Instead you can use prepared **Dynamic Rectors** directly in `*.yml` config:
|
|
|
|
|
|
|
|
You can:
|
|
|
|
|
|
|
|
- **replace class name**
|
|
|
|
|
|
|
|
```yml
|
|
|
|
# phpunit60.yml
|
|
|
|
rectors:
|
|
|
|
Rector\Rector\Dynamic\ClassReplacerRector:
|
|
|
|
# old class: new class
|
|
|
|
'PHPUnit_Framework_TestCase': 'PHPUnit\Framework\TestCase'
|
|
|
|
```
|
|
|
|
|
2017-10-07 22:34:30 +02:00
|
|
|
- **replace part of namespace**
|
|
|
|
|
|
|
|
```yml
|
|
|
|
# better-reflection20.yml
|
|
|
|
rectors:
|
|
|
|
Rector\Rector\Dynamic\NamespaceReplacerRector:
|
2017-11-01 17:41:13 +01:00
|
|
|
# old namespace: new namespace
|
2017-10-07 22:34:30 +02:00
|
|
|
'BetterReflection': 'Roave\BetterReflection'
|
|
|
|
```
|
|
|
|
|
2017-10-16 22:06:59 +02:00
|
|
|
- **change method name**
|
2017-10-07 10:58:54 +02:00
|
|
|
|
|
|
|
```yml
|
|
|
|
rectors:
|
|
|
|
Rector\Rector\Dynamic\MethodNameReplacerRector:
|
2017-11-01 17:41:13 +01:00
|
|
|
# class
|
2017-10-07 10:58:54 +02:00
|
|
|
'Nette\Utils\Html':
|
2017-11-01 17:41:13 +01:00
|
|
|
# old method: new method
|
2017-10-07 10:58:54 +02:00
|
|
|
'add': 'addHtml'
|
2017-10-30 14:33:09 +01:00
|
|
|
|
2017-10-20 18:04:52 +02:00
|
|
|
# or in case of static methods calls
|
2017-10-30 14:33:09 +01:00
|
|
|
|
2017-11-01 17:41:13 +01:00
|
|
|
# class
|
2017-10-20 18:04:52 +02:00
|
|
|
'Nette\Bridges\FormsLatte\FormMacros':
|
2017-11-01 17:41:13 +01:00
|
|
|
# old method: [new class, new method]
|
2017-10-20 18:04:52 +02:00
|
|
|
'renderFormBegin': ['Nette\Bridges\FormsLatte\Runtime', 'renderFormBegin']
|
2017-10-07 10:58:54 +02:00
|
|
|
```
|
|
|
|
|
2017-10-22 00:04:15 +02:00
|
|
|
- **change property name**
|
|
|
|
|
|
|
|
```yml
|
|
|
|
rectors:
|
|
|
|
Rector\Rector\Dynamic\PropertyNameReplacerRector:
|
|
|
|
# class:
|
|
|
|
'PhpParser\Node\Param':
|
2017-11-18 16:19:47 +01:00
|
|
|
# old property: new property
|
2017-10-22 00:04:15 +02:00
|
|
|
'name': 'var'
|
|
|
|
```
|
|
|
|
|
2017-10-20 20:35:04 +02:00
|
|
|
- **change class constant name**
|
|
|
|
|
|
|
|
```yml
|
|
|
|
rectors:
|
|
|
|
Rector\Rector\Dynamic\ClassConstantReplacerRector:
|
2017-11-01 17:41:13 +01:00
|
|
|
# class
|
2017-10-20 20:35:04 +02:00
|
|
|
'Symfony\Component\Form\FormEvents':
|
2017-11-01 17:41:13 +01:00
|
|
|
# old constant: new constant
|
2017-10-20 20:35:04 +02:00
|
|
|
'PRE_BIND': 'PRE_SUBMIT'
|
|
|
|
'BIND': 'SUBMIT'
|
|
|
|
'POST_BIND': 'POST_SUBMIT'
|
|
|
|
```
|
|
|
|
|
2017-10-22 16:51:13 +02:00
|
|
|
- **change parameters typehint according to parent type**
|
2017-10-21 18:30:45 +02:00
|
|
|
|
|
|
|
```yml
|
|
|
|
rectors:
|
|
|
|
Rector\Rector\Dynamic\ParentTypehintedArgumentRector:
|
2017-11-01 17:41:13 +01:00
|
|
|
# class
|
2017-10-21 18:30:45 +02:00
|
|
|
'PhpParser\Parser':
|
2017-11-01 17:41:13 +01:00
|
|
|
# method
|
2017-10-21 18:30:45 +02:00
|
|
|
'parse':
|
2017-11-01 17:41:13 +01:00
|
|
|
# parameter: typehint
|
2017-10-21 18:30:45 +02:00
|
|
|
'code': 'string'
|
|
|
|
```
|
|
|
|
|
2017-11-01 17:42:08 +01:00
|
|
|
- **change argument value**
|
2017-11-01 13:07:59 +01:00
|
|
|
|
|
|
|
```yml
|
2017-11-01 17:41:13 +01:00
|
|
|
rectors:
|
|
|
|
Rector\Rector\Dynamic\ArgumentReplacerRector:
|
|
|
|
# class
|
|
|
|
'Symfony\Component\DependencyInjection\ContainerBuilder':
|
|
|
|
# method
|
|
|
|
'compile':
|
|
|
|
# argument position
|
|
|
|
0:
|
|
|
|
# added default value
|
2017-11-25 00:52:55 +01:00
|
|
|
'~': false
|
2017-11-01 18:42:47 +01:00
|
|
|
# or remove completely
|
2017-11-25 00:52:55 +01:00
|
|
|
'~': ~
|
2017-11-01 18:42:47 +01:00
|
|
|
# or replace by new value
|
|
|
|
'Symfony\Component\DependencyInjection\ContainerBuilder\ContainerBuilder::SCOPE_PROTOTYPE': false
|
2017-11-01 13:07:59 +01:00
|
|
|
```
|
2017-10-30 14:33:09 +01:00
|
|
|
|
2017-10-16 22:06:59 +02:00
|
|
|
- or **replace underscore naming `_` with namespaces `\`**
|
|
|
|
|
|
|
|
```yml
|
|
|
|
rectors:
|
2017-12-02 20:23:55 +01:00
|
|
|
Rector\Rector\Dynamic\PseudoNamespaceToNamespaceRector:
|
2017-10-16 22:06:59 +02:00
|
|
|
# old namespace prefix
|
|
|
|
- 'PHPUnit_'
|
2017-11-18 03:50:17 +01:00
|
|
|
# exclude classes
|
|
|
|
- '!PHPUnit_Framework_MockObject_MockObject'
|
2017-10-16 22:06:59 +02:00
|
|
|
```
|
2017-10-07 10:58:54 +02:00
|
|
|
|
2017-11-18 16:51:57 +01:00
|
|
|
- or **change property to method**
|
|
|
|
|
|
|
|
```yml
|
|
|
|
rectors:
|
|
|
|
Rector\Rector\Dynamic\PropertyToMethodRector:
|
|
|
|
# type
|
|
|
|
'Symfony\Component\Translation\Translator':
|
|
|
|
# property to replace
|
|
|
|
'locale':
|
|
|
|
# (prepared key): get method name
|
|
|
|
'get': 'getLocale'
|
|
|
|
# (prepared key): set method name
|
|
|
|
'set': 'setLocale'
|
|
|
|
```
|
|
|
|
|
2017-11-23 17:04:36 +01:00
|
|
|
- or **remove value object and use simple types**
|
2017-11-21 04:04:01 +01:00
|
|
|
|
|
|
|
```yml
|
|
|
|
rectors:
|
|
|
|
Rector\Rector\Dynamic\ValueObjectRemoverRector:
|
2017-11-23 17:04:36 +01:00
|
|
|
# type: new simple type
|
|
|
|
'ValueObjects\Name': 'string'
|
2017-11-21 04:04:01 +01:00
|
|
|
```
|
|
|
|
|
|
|
|
For example:
|
|
|
|
|
|
|
|
```php
|
2017-11-23 17:04:36 +01:00
|
|
|
$value = new ValueObjects\Name('Tomas');
|
|
|
|
|
2017-11-21 04:04:01 +01:00
|
|
|
# to
|
2017-11-23 17:04:36 +01:00
|
|
|
|
2017-11-21 04:04:01 +01:00
|
|
|
$value = 'Tomas';
|
|
|
|
```
|
2017-11-23 17:04:36 +01:00
|
|
|
|
|
|
|
```php
|
|
|
|
/**
|
|
|
|
* @var ValueObjects\Name
|
|
|
|
*/
|
|
|
|
private $name;
|
|
|
|
|
|
|
|
# to
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @var string
|
|
|
|
*/
|
|
|
|
private $name;
|
|
|
|
```
|
|
|
|
|
|
|
|
```php
|
|
|
|
public function someMethod(ValueObjects\Name $name) { ...
|
|
|
|
|
|
|
|
# to
|
|
|
|
|
|
|
|
public function someMethod(string $name) { ...
|
|
|
|
```
|
2017-11-18 16:51:57 +01:00
|
|
|
|
2017-11-18 15:01:12 +01:00
|
|
|
### Turn Magic to Methods
|
|
|
|
|
|
|
|
- **replace get/set magic methods with real ones**
|
|
|
|
|
|
|
|
```yml
|
|
|
|
rectors:
|
|
|
|
Rector\Rector\MagicDisclosure\GetAndSetToMethodCallRector:
|
|
|
|
# class
|
|
|
|
'Nette\DI\Container':
|
|
|
|
# magic method (prepared keys): new real method
|
|
|
|
'get': 'getService'
|
|
|
|
'set': 'addService'
|
|
|
|
```
|
|
|
|
|
2017-11-18 15:03:38 +01:00
|
|
|
For example:
|
|
|
|
|
2017-11-18 15:01:12 +01:00
|
|
|
```php
|
|
|
|
$result = $container['key'];
|
2017-11-23 17:04:36 +01:00
|
|
|
|
2017-11-18 15:03:38 +01:00
|
|
|
# to
|
2017-11-23 17:04:36 +01:00
|
|
|
|
2017-11-18 15:03:38 +01:00
|
|
|
$result = $container->getService('key');
|
2017-11-23 17:04:36 +01:00
|
|
|
```
|
2017-11-18 15:01:12 +01:00
|
|
|
|
2017-11-23 17:04:36 +01:00
|
|
|
```php
|
2017-11-18 15:01:12 +01:00
|
|
|
$container['key'] = $value;
|
2017-11-23 17:04:36 +01:00
|
|
|
|
2017-11-18 15:03:38 +01:00
|
|
|
# to
|
2017-11-23 17:04:36 +01:00
|
|
|
|
2017-11-18 15:01:12 +01:00
|
|
|
$container->addService('key', $value);
|
|
|
|
```
|
|
|
|
|
|
|
|
- or **replaces isset/unset magic methods with real ones**
|
|
|
|
|
|
|
|
```yml
|
|
|
|
rectors:
|
|
|
|
Rector\Rector\MagicDisclosure\UnsetAndIssetToMethodCallRector:
|
|
|
|
# class
|
|
|
|
'Nette\DI\Container':
|
|
|
|
# magic method (prepared keys): new real method
|
|
|
|
'isset': 'hasService'
|
|
|
|
'unset': 'removeService'
|
|
|
|
```
|
|
|
|
|
2017-11-18 15:03:38 +01:00
|
|
|
For example:
|
|
|
|
|
2017-11-18 15:01:12 +01:00
|
|
|
```php
|
|
|
|
isset($container['key']);
|
2017-11-23 17:04:36 +01:00
|
|
|
|
2017-11-18 15:03:38 +01:00
|
|
|
# to
|
|
|
|
|
2017-11-23 17:04:36 +01:00
|
|
|
$container->hasService('key');
|
|
|
|
```
|
|
|
|
|
|
|
|
```php
|
2017-11-18 15:03:38 +01:00
|
|
|
unset($container['key']);
|
2017-11-23 17:04:36 +01:00
|
|
|
|
2017-11-18 15:03:38 +01:00
|
|
|
# to
|
2017-11-23 17:04:36 +01:00
|
|
|
|
2017-11-18 15:01:12 +01:00
|
|
|
$container->removeService('key');
|
|
|
|
```
|
2017-10-07 10:58:54 +02:00
|
|
|
|
2017-11-18 15:42:15 +01:00
|
|
|
- or **replaces toString magic methods with real ones**
|
|
|
|
|
|
|
|
```yml
|
|
|
|
rectors:
|
|
|
|
Rector\Rector\MagicDisclosure\ToStringToMethodCallRector:
|
|
|
|
# class
|
|
|
|
'Symfony\Component\Config\ConfigCache':
|
|
|
|
# magic method (prepared key): new real method
|
|
|
|
'toString': 'getPath'
|
|
|
|
```
|
|
|
|
|
|
|
|
For example:
|
|
|
|
|
|
|
|
```php
|
|
|
|
$result = (string) $someValue;
|
2017-11-23 17:04:36 +01:00
|
|
|
|
2017-11-18 15:42:15 +01:00
|
|
|
# to
|
2017-11-23 17:04:36 +01:00
|
|
|
|
2017-11-18 15:42:15 +01:00
|
|
|
$result = $someValue->someMethod();
|
2017-11-23 17:04:36 +01:00
|
|
|
```
|
|
|
|
|
|
|
|
```php
|
2017-11-18 15:42:15 +01:00
|
|
|
$result = $someValue->__toString();
|
2017-11-23 17:04:36 +01:00
|
|
|
|
2017-11-18 15:42:15 +01:00
|
|
|
# to
|
2017-11-23 17:04:36 +01:00
|
|
|
|
2017-11-18 15:42:15 +01:00
|
|
|
$result = $someValue->someMethod();
|
|
|
|
```
|
|
|
|
|
|
|
|
|
2017-11-02 18:31:57 +01:00
|
|
|
### Coding Standards are Outsourced
|
|
|
|
|
2017-11-05 23:07:32 +01:00
|
|
|
This package has no intention in formatting your code, as **coding standard tools handle this much better**.
|
2017-11-02 18:31:57 +01:00
|
|
|
|
2017-11-18 16:19:47 +01:00
|
|
|
We prefer [EasyCodingStandard](https://github.com/Symplify/EasyCodingStandard) that is already available:
|
2017-11-02 18:31:57 +01:00
|
|
|
|
2017-11-18 16:19:47 +01:00
|
|
|
```bash
|
2017-11-02 18:31:57 +01:00
|
|
|
# check
|
|
|
|
vendor/bin/ecs check --config vendor/rector/rector/ecs-after-rector.neon
|
2017-11-18 16:19:47 +01:00
|
|
|
|
2017-11-02 18:31:57 +01:00
|
|
|
# fix
|
|
|
|
vendor/bin/ecs check --config vendor/rector/rector/ecs-after-rector.neon --fix
|
|
|
|
```
|
|
|
|
|
2017-11-18 16:19:47 +01:00
|
|
|
### More Detailed Documentation
|
2017-10-15 11:07:53 +02:00
|
|
|
|
2017-11-18 16:19:47 +01:00
|
|
|
- [How to Create Own Rector](/docs/HowToCreateOwnRector.md)
|
2017-10-15 11:07:53 +02:00
|
|
|
- [Service Name to Type Provider](/docs/ServiceNameToTypeProvider.md)
|
|
|
|
|
|
|
|
|
2017-07-15 19:20:20 +02:00
|
|
|
### How to Contribute
|
|
|
|
|
|
|
|
Just follow 3 rules:
|
|
|
|
|
|
|
|
- **1 feature per pull-request**
|
2017-08-21 12:12:51 +02:00
|
|
|
- **New feature needs tests**
|
2017-07-15 19:20:20 +02:00
|
|
|
- Tests, coding standard and PHPStan **checks must pass**
|
|
|
|
|
|
|
|
```bash
|
|
|
|
composer all
|
|
|
|
```
|
|
|
|
|
2017-08-21 12:12:51 +02:00
|
|
|
Don you need to fix coding standards? Run:
|
2017-07-15 19:20:20 +02:00
|
|
|
|
|
|
|
```bash
|
2017-08-21 12:12:51 +02:00
|
|
|
composer fix-cs
|
2017-07-15 19:20:20 +02:00
|
|
|
```
|
|
|
|
|
|
|
|
We would be happy to merge your feature then.
|