2017-10-31 00:08:32 +01:00
2017-10-30 14:26:44 +01:00
2017-10-30 16:00:28 +01:00
2017-10-29 21:20:25 +01:00
2017-10-30 14:26:44 +01:00
2017-07-15 19:12:04 +02:00
2017-09-29 12:25:56 +02:00
2017-07-15 19:12:04 +02:00
2017-10-29 23:40:29 +01:00
2017-10-26 10:25:14 +02:00
2017-07-15 19:12:04 +02:00
2017-10-31 00:08:32 +01:00
2017-09-28 17:28:49 +02:00

Rector - Reconstruct your Legacy Code to Modern Codebase

Build Status Coverage Status

Rector upgrades your application for you, with focus on open-source projects:


Install

Add to your composer.json:

{
    "require-dev": {
        "rector/rector": "@dev",
        "nikic/php-parser": "dev-master#5900d78 as v3.1.1"
    }
}

And download packages:

composer update

How To Reconstruct your Code?

A. Prepared Sets

Fetaured open-source projects have prepared sets. You'll find them in /src/config/level.

E.g. Do you need to upgrade to Nette 2.4?

  1. Run rector on your /src directory
vendor/bin/rector process src --config vendor/bin/rector/src/config/level/nette/nette24.yml

Too long? Try --level shortcut:

vendor/bin/rector process src --level nette24
  1. Check the Git
git diff

B. Custom Sets

  1. Create rector.yml with desired Rectors
rectors:
    - Rector\Rector\Contrib\Nette\Application\InjectPropertyRector
  1. Run rector on your /src directory
vendor/bin/rector process src
  1. Check the Git
git diff

6 Steps to Add New Rector

Just extend Rector\Rector\AbstractRector. It will prepare 2 methods processing the node.

public function isCandidate(Node $node): bool
{
}

public function refactor(Node $node): ?Node
{
}
  1. Put it under namespace Rector\Contrib\<set>; namespace
<?php declare(strict_types=1);

namespace Rector\Contrib\Symfony;

use Rector\Rector\AbstractRector;

final class MyRector extends AbstractRector
{
    // ...
}
  1. Add a Test Case

  2. Add to specific level, e.g. /src/config/level/nette/nette24.yml

  3. Submit PR

  4. 👍

Simpler setup with Dynamic Rectors

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

    # phpunit60.yml
    rectors:
        Rector\Rector\Dynamic\ClassReplacerRector:
            # old class: new class
            'PHPUnit_Framework_TestCase': 'PHPUnit\Framework\TestCase'
    
  • replace part of namespace

    # better-reflection20.yml
    rectors:
        Rector\Rector\Dynamic\NamespaceReplacerRector:
            'BetterReflection': 'Roave\BetterReflection'
    
  • change method name

    # nette24.yml
    rectors:
        Rector\Rector\Dynamic\MethodNameReplacerRector:
            # class:
            #   old method: new method
            'Nette\Utils\Html':
                'add': 'addHtml'
    
            # or in case of static methods calls
    
            # class:
            #   old method: [new class, new method]
            'Nette\Bridges\FormsLatte\FormMacros':
                'renderFormBegin': ['Nette\Bridges\FormsLatte\Runtime', 'renderFormBegin']
    
  • change property name

    # php-parser40.yml
    rectors:
        Rector\Rector\Dynamic\PropertyNameReplacerRector:
            # class:
            #   old property: new property
            'PhpParser\Node\Param':
                'name': 'var'
    
  • change class constant name

    # symfony30.yml
    rectors:
        Rector\Rector\Dynamic\ClassConstantReplacerRector:
            # class:
            #   OLD_CONSTANT: NEW_CONSTANT
            'Symfony\Component\Form\FormEvents':
                'PRE_BIND': 'PRE_SUBMIT'
                'BIND': 'SUBMIT'
                'POST_BIND': 'POST_SUBMIT'
    
  • change parameters typehint according to parent type

    # php-parser40.yml
    rectors:
        Rector\Rector\Dynamic\ParentTypehintedArgumentRector:
            # class:
            #   method:
            #       parameter: typehting
            'PhpParser\Parser':
                'parse':
                    'code': 'string'
    
  • remove unused argument

    Rector\Rector\Dynamic\ArgumentRemoverRector:
        # class
            # method
                # arguments to remove
        'Doctrine\ORM\Persisters\Entity\AbstractEntityInheritancePersister':
            'getSelectJoinColumnSQL':
                - 'className'
    
  • or replace underscore naming _ with namespaces \

    rectors:
        Rector\Roector\Dynamic\PseudoNamespaceToNamespaceRector:
            # old namespace prefix
            - 'PHPUnit_'
    

Advanced Operations

How to Contribute

Just follow 3 rules:

  • 1 feature per pull-request

  • New feature needs tests

  • Tests, coding standard and PHPStan checks must pass

    composer all
    

    Don you need to fix coding standards? Run:

    composer fix-cs
    

We would be happy to merge your feature then.

How to use on PHP < 7.1

You must have separated environment with PHP 7.1 (for example in Docker container). When you have it then run following command:

composer create-project rector/rector path-to-rector

When do you have it then you can run all commands like

path-to-rector/bin/rector process /var/www/old-project --config path-to-rector/src/config/level/nette/nette24.yml
# or for short
path-to-rector/bin/rector process /var/www/old-project --level nette24
Description
Languages
PHP 99.9%