mirror of
https://github.com/rectorphp/rector.git
synced 2025-04-22 16:32:27 +02:00
Updated Rector to commit d670b4e50deb738f15d77c6a4f7fe773791c871f
d670b4e50d
[docs] cleanup, add links to the official docs
This commit is contained in:
parent
670f9998e8
commit
82eda1fecd
72
README.md
72
README.md
@ -18,45 +18,12 @@ Do you have code quality you need, but struggle to keep it with new developers i
|
||||
|
||||
Add Rector to your CI and let it **continuously refactor your code** and keep the code quality high.
|
||||
|
||||
<br>
|
||||
|
||||
## Documentation
|
||||
|
||||
- [Explore Rector Rules](/docs/rector_rules_overview.md)
|
||||
- [How to Ignore Rule or Paths](/docs/how_to_ignore_rule_or_paths.md)
|
||||
- [Static Reflection and Autoload](/docs/static_reflection_and_autoload.md)
|
||||
- [How to Configure Rule](/docs/how_to_configure_rules.md)
|
||||
- [Auto Import Names](/docs/auto_import_names.md)
|
||||
- [How to Troubleshoot Parallel Issues](/docs/how_to_troubleshoot_parallel_issues.md)
|
||||
|
||||
### For Rule Developers and Contributors
|
||||
|
||||
- [How Does Rector Work?](/docs/how_it_works.md)
|
||||
- [PHP Parser Nodes](https://github.com/rectorphp/php-parser-nodes-docs/)
|
||||
- [How to Work with Doc Block and Comments](/docs/how_to_work_with_doc_block_and_comments.md)
|
||||
- [How to Create Own Rector Rule](/docs/create_own_rule.md)
|
||||
- [How to add Test for Rector Rule](/docs/how_to_add_test_for_rector_rule.md)
|
||||
- [How to Persist Cache Between CI Runs](/docs/how_to_persist_cache_between_ci_runs.md)
|
||||
|
||||
See [the full documentation](/docs).
|
||||
|
||||
<br>
|
||||
|
||||
## Learn Faster with a Book
|
||||
|
||||
Are you curious, how Rector works internally, how to create your own rules and test them and why Rector was born?
|
||||
Read [Rector - The Power of Automated Refactoring](https://leanpub.com/rector-the-power-of-automated-refactoring) that will take you step by step through the Rector setup and how to create your own rules.
|
||||
|
||||
<br>
|
||||
|
||||
## Install
|
||||
|
||||
```bash
|
||||
composer require rector/rector --dev
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
## Running Rector
|
||||
|
||||
There are 2 main ways to use Rector:
|
||||
@ -73,19 +40,19 @@ vendor/bin/rector init
|
||||
And modify it:
|
||||
|
||||
```php
|
||||
use Rector\Php74\Rector\Property\TypedPropertyRector;
|
||||
use Rector\Set\ValueObject\SetList;
|
||||
use Rector\Config\RectorConfig;
|
||||
use Rector\Set\ValueObject\SetList;
|
||||
use Rector\TypeDeclaration\Rector\Property\TypedPropertyFromStrictConstructorRector;
|
||||
|
||||
return static function (RectorConfig $rectorConfig): void {
|
||||
// register single rule
|
||||
$rectorConfig->rule(TypedPropertyFromStrictConstructorRector::class);
|
||||
|
||||
// here we can define, what sets of rules will be applied
|
||||
// tip: use "SetList" class to autocomplete sets
|
||||
// tip: use "SetList" class to autocomplete sets with your IDE
|
||||
$rectorConfig->sets([
|
||||
SetList::CODE_QUALITY
|
||||
]);
|
||||
|
||||
// register single rule
|
||||
$rectorConfig->rule(TypedPropertyRector::class);
|
||||
};
|
||||
```
|
||||
|
||||
@ -101,34 +68,21 @@ Rector will show you diff of files that it *would* change. To *make* the changes
|
||||
vendor/bin/rector process src
|
||||
```
|
||||
|
||||
*Note: `rector.php` is loaded by default. For different location, use `--config` option.*
|
||||
## Documentation
|
||||
|
||||
*Note: Rector will only update legacy code to utilize new features which are supported by the PHP version defined in your `composer.json` file. For instance, if require.php is `>=7.2.5`, Rector will not make changes which are only available for PHP versions after 7.2.5.*
|
||||
* Find [full documentation here](https://getrector.org/documentation/).
|
||||
* [Explore Rector Rules](/docs/rector_rules_overview.md)
|
||||
|
||||
<br>
|
||||
|
||||
## Configuration
|
||||
## Learn Faster with a Book
|
||||
|
||||
```php
|
||||
// rector.php
|
||||
use Rector\Core\ValueObject\PhpVersion;
|
||||
use Rector\Config\RectorConfig;
|
||||
|
||||
return static function (RectorConfig $rectorConfig): void {
|
||||
// paths to refactor; solid alternative to CLI arguments
|
||||
$rectorConfig->paths([__DIR__ . '/src', __DIR__ . '/tests']);
|
||||
|
||||
// is your PHP version different from the one you refactor to? [default: your PHP version], uses PHP_VERSION_ID format
|
||||
$rectorConfig->phpVersion(PhpVersion::PHP_72);
|
||||
|
||||
// Path to PHPStan with extensions, that PHPStan in Rector uses to determine types
|
||||
$rectorConfig->phpstanConfig(__DIR__ . '/phpstan-for-config.neon');
|
||||
};
|
||||
```
|
||||
Are you curious, how Rector works internally, how to create your own rules and test them and why Rector was born?
|
||||
Read [Rector - The Power of Automated Refactoring](https://leanpub.com/rector-the-power-of-automated-refactoring) that will take you step by step through the Rector setup and how to create your own rules.
|
||||
|
||||
<br>
|
||||
|
||||
## Empowered by Rector Community :heart:
|
||||
## Empowered by Community :heart:
|
||||
|
||||
The Rector community is powerful thanks to active maintainers who take care of Rector sets for particular projects.
|
||||
|
||||
|
@ -1,60 +1,5 @@
|
||||
# Auto Import Names
|
||||
|
||||
Rector works with all class names as fully qualified by default, so it knows the exact types. In most coding standard, that's not desired behavior, because short version with `use` statement is preferred:
|
||||
This page was moved to new documentation.
|
||||
|
||||
```diff
|
||||
+use App\Some\Namespace\SomeClass;
|
||||
|
||||
-/** @var \App\Some\Namespace\SomeClass $object */
|
||||
+/** @var SomeClass $object */
|
||||
|
||||
-$object = new \App\Some\Namespace\SomeClass();
|
||||
+$object = new SomeClass();
|
||||
```
|
||||
|
||||
|
||||
To import FQN like these, configure `rector.php` with:
|
||||
|
||||
```php
|
||||
$rectorConfig->importNames();
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
Single short classes are imported too:
|
||||
|
||||
```diff
|
||||
+use DateTime;
|
||||
-$someClass = \DateTime();
|
||||
+$someClass = DateTime();
|
||||
```
|
||||
|
||||
Do you want to keep those?
|
||||
|
||||
```php
|
||||
$rectorConfig->importShortClasses(false);
|
||||
```
|
||||
|
||||
## How to Remove Unused Imports?
|
||||
|
||||
To remove imports, use [ECS](https://github.com/symplify/easy-coding-standard) with [`NoUnusedImportsFixer`](https://github.com/FriendsOfPHP/PHP-CS-Fixer/blob/2.18/doc/rules/import/no_unused_imports.rst) rule:
|
||||
|
||||
```php
|
||||
// ecs.php
|
||||
use PhpCsFixer\Fixer\Import\NoUnusedImportsFixer;
|
||||
use Symplify\EasyCodingStandard\Config\ECSConfig;
|
||||
|
||||
return static function (ECSConfig $ecsConfig): void {
|
||||
$ecsConfig->rule(NoUnusedImportsFixer::class);
|
||||
};
|
||||
```
|
||||
|
||||
Run it:
|
||||
|
||||
```bash
|
||||
vendor/bin/ecs check src --fix
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
Happy coding!
|
||||
You can find it here: https://getrector.org/documentation/
|
||||
|
@ -1,101 +1,6 @@
|
||||
# How Does Rector Work?
|
||||
|
||||
(Inspired by [*How it works* in BetterReflection](https://github.com/Roave/BetterReflection/blob/master/docs/how-it-works.md))
|
||||
|
||||
## 1. Finds all files and Load Configured Rectors
|
||||
This page was moved to new documentation.
|
||||
|
||||
- The application finds files in the source code you provide and registered Rectors - from `--config` or local `rector.php`
|
||||
- Then it iterates all found files and applies relevant Rectors to them.
|
||||
- A *Rector* in this context is 1 single class that modifies 1 thing, e.g. changes the class name
|
||||
|
||||
## 2. Parse and Reconstruct 1 File
|
||||
|
||||
The iteration of files, nodes and Rectors respects this lifecycle:
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Rector\Contract\Rector\PhpRectorInterface;
|
||||
use PhpParser\Parser;
|
||||
|
||||
/** @var SplFileInfo[] $fileInfos */
|
||||
foreach ($fileInfos as $fileInfo) {
|
||||
// 1 file => nodes
|
||||
/** @var Parser $phpParser */
|
||||
$nodes = $phpParser->parse(file_get_contents($fileInfo->getRealPath()));
|
||||
|
||||
// nodes => 1 node
|
||||
foreach ($nodes as $node) { // rather traverse all of them
|
||||
/** @var PhpRectorInterface[] $rectors */
|
||||
foreach ($rectors as $rector) {
|
||||
foreach ($rector->getNodeTypes() as $nodeType) {
|
||||
if (is_a($node, $nodeType, true)) {
|
||||
$rector->refactor($node);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2.1 Prepare Phase
|
||||
|
||||
- Files are parsed by [`nikic/php-parser`](https://github.com/nikic/PHP-Parser), 4.0 that supports writing modified tree back to a file
|
||||
- Then nodes (array of objects by parser) are traversed by `StandaloneTraverseNodeTraverser` to prepare their metadata, e.g. the class name, the method node the node is in, the namespace name etc. added by `$node->setAttribute('key', 'value')`.
|
||||
|
||||
### 2.2 Rectify Phase
|
||||
|
||||
- When all nodes are ready, the application iterates on all active Rectors
|
||||
- Each node is compared with `$rector->getNodeTypes()` method to see if this Rector should do some work on it, e.g. is this class name called `OldClassName`?
|
||||
- If it doesn't match, it goes to next node.
|
||||
- If it matches, the `$rector->reconstruct($node)` method is called
|
||||
- Active Rector change everything they have to and return changed nodes
|
||||
|
||||
### 2.2.1 Order of Rectors
|
||||
|
||||
- Nodes to run rectors are iterated in the node traversal order.
|
||||
|
||||
E.g. rectors for `Class_` node always run before rectors for `ClassMethod` in one class.
|
||||
|
||||
- Rectors are run by the natural order in the configuration, meaning the first
|
||||
in the configuration will be run first.
|
||||
|
||||
E.g. in this case, first the `@expectedException` annotation will be changed to a method,
|
||||
then the `setExpectedException` method will be changed to `expectedException`.
|
||||
|
||||
```php
|
||||
use Rector\PHPUnit\Rector\ClassMethod\ExceptionAnnotationRector;
|
||||
use Rector\Renaming\Rector\MethodCall\RenameMethodRector;
|
||||
use Rector\Config\RectorConfig
|
||||
use Rector\Renaming\ValueObject\MethodCallRename;
|
||||
|
||||
return static function (RectorConfig $rectorConfig): void {
|
||||
$rectorConfig->rule(ExceptionAnnotationRector::class);
|
||||
|
||||
$rectorConfig->ruleWithConfiguration(Rector\Renaming\Rector\MethodCall\RenameMethodRector::class, [
|
||||
new MethodCallRename('PHPUnit\Framework\TestClass', 'setExpectedException', 'expectedException'),
|
||||
new MethodCallRename('PHPUnit\Framework\TestClass', 'setExpectedExceptionRegExp', 'expectedException'),
|
||||
]);
|
||||
};
|
||||
```
|
||||
|
||||
### 2.3 Save File/Diff Phase
|
||||
|
||||
- When work on all nodes of 1 file is done, the file will be saved if it has some changes
|
||||
- Or if the `--dry-run` option is on, it will store the *git-like* diff thanks to [GeckoPackages/GeckoDiffOutputBuilder](https://github.com/GeckoPackages/GeckoDiffOutputBuilder)
|
||||
- Then Rector will go to the next file
|
||||
|
||||
## 3 Reporting
|
||||
|
||||
- After this, Rector displays the list of changed files
|
||||
- Or with `--dry-run` option the diff of these files
|
||||
|
||||
### Similar Projects
|
||||
|
||||
- [ClangMR](https://static.googleusercontent.com/media/research.google.com/en//pubs/archive/41342.pdf) for C++ by Google (closed source) - almost identical workflow, developed independently though
|
||||
- [hhast](https://github.com/hhvm/hhast) - HHVM AST + format preserving + migrations
|
||||
- [facebook/jscodeshift](https://github.com/facebook/jscodeshift) for Javascript
|
||||
- [silverstripe/silverstripe-upgrader](https://github.com/silverstripe/silverstripe-upgrader) for PHP CMS, Silverstripe
|
||||
- [dereuromark/upgrade](https://github.com/dereuromark/upgrade) for PHP Framework, CakePHP
|
||||
You can find it here: https://getrector.org/documentation/
|
||||
|
@ -1,148 +1,6 @@
|
||||
# How to Add Test for Rector Rule
|
||||
|
||||
## 1. Create an environment for testing
|
||||
|
||||
When using Rector to update your own code, you will typically be using release repository installed by composer, however, when adding tests, you will need to use the development repository as shown:
|
||||
This page was moved to new documentation.
|
||||
|
||||
- Fork https://github.com/rectorphp/rector-src
|
||||
- Clone it locally
|
||||
- Install dependencies by executing `composer install`
|
||||
- Tests your installation by executing `composer fix-cs` and `composer phpstan`
|
||||
- Create a new branch for your test
|
||||
- Add your test as described below. Note that the rector binary is located at `bin/rector` instead of the typical `vendor/bin/rector`
|
||||
- Push the branch
|
||||
- Create a new pull request to https://github.com/rectorphp/rector-src
|
||||
|
||||
<br>
|
||||
|
||||
## 2. Detect the Rector Rule
|
||||
|
||||
Run Rector only on 1 directory, or better 1 file.
|
||||
|
||||
```bash
|
||||
bin/rector process /some-file.php
|
||||
```
|
||||
|
||||
See "Applied rules" under the diff:
|
||||
|
||||

|
||||
|
||||
Our rule in this example is: `Rector\Privatization\Rector\Class_\FinalizeClassesWithoutChildrenRector`
|
||||
|
||||
This rule's job is to add `final` to every class that has no children and is not a Doctrine entity = everywhere it can without breaking our code.
|
||||
|
||||
<br>
|
||||
|
||||
## 3. Detect the Minimal File
|
||||
|
||||
Usually, the Rector diff output is long and contains many other errors related to other rules. It's a mess; we can't use that for a test fixture. We need to find **1 responsible line**.
|
||||
|
||||
The best way is to copy the file to local code, e.g. `app/SomeFile.php` and put only the broken line there.
|
||||
|
||||
In our case, all we need is:
|
||||
|
||||
```php
|
||||
class StaticEasyPrefixer
|
||||
{
|
||||
}
|
||||
```
|
||||
|
||||
Then rerun Rector to confirm:
|
||||
|
||||
```bash
|
||||
bin/rector process app/SomeFile.php
|
||||
```
|
||||
|
||||
Do we have the same diff? Great!
|
||||
|
||||
<br>
|
||||
|
||||
## 4. Find the Rector Test Case
|
||||
|
||||
Now we need to find the test case. The test case name is rule + `Test` suffix.
|
||||
|
||||
`FinalizeClassesWithoutChildrenRector`
|
||||
|
||||
↓
|
||||
|
||||
`FinalizeClassesWithoutChildrenRectorTest` (test class)
|
||||
|
||||
Right here:
|
||||
|
||||

|
||||
|
||||
<br>
|
||||
|
||||
## 5. Add Change or No-Change Test Fixture File
|
||||
|
||||
Next to the test case, there is `/Fixture` directory. It contains many test fixture files that verified the Rector rule work correctly in all possible cases.
|
||||
|
||||
Do you see *test fixture file* first time? It's a file with real-life PHP code that test 1 specific case that rule should cover or avoid. E.g., one test fixture file can contain a Doctrine entity that cannot be final and should be skipped by this rule. By convention, the first fixture file has the name `fixture.php.inc`.
|
||||
|
||||
In the `/Fixture` directory, we create our test fixture file, e.g., `add_final.php.inc`. The `.php.inc` is there on purpose, so the file is hidden from coding standard tools and static analysis.
|
||||
|
||||
<br>
|
||||
|
||||
There are 2 fixture formats:
|
||||
|
||||
### A. The Code Should Change
|
||||
|
||||
```bash
|
||||
<code before>
|
||||
-----
|
||||
<code after>
|
||||
```
|
||||
|
||||
### B. The Code Should Be Skipped
|
||||
|
||||
```bash
|
||||
<code before>
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
In this particular case, the code should change - `final` should be added so that the test fixture would look like this:
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\Privatization\Rector\Class_\FinalizeClassesWithoutChildrenRector\Fixture;
|
||||
|
||||
class AddFinal
|
||||
{
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\Privatization\Rector\Class_\FinalizeClassesWithoutChildrenRector\Fixture;
|
||||
|
||||
final class AddFinal
|
||||
{
|
||||
}
|
||||
|
||||
?>
|
||||
```
|
||||
|
||||
- The closing `?>` is there for slightly better PHPStorm.
|
||||
- The PSR-4 namespace is there to make each class unique because the test classes are loaded to an analysis by reflection and must be unique
|
||||
- The file name conventions => class is `add_final.php.inc` => `AddFinal` class
|
||||
|
||||
Run PHPUnit with the test file to confirm:
|
||||
|
||||
```bash
|
||||
vendor/bin/phpunit rules-tests/Privatization/Rector/Class_/FinalizeClassesWithoutChildrenRector/FinalizeClassesWithoutChildrenRectorTest.php
|
||||
```
|
||||
|
||||
To run only the single test fixture, add `--filter test#X`, where X is the fixture's order number.
|
||||
|
||||
```bash
|
||||
vendor/bin/phpunit rules-tests/Privatization/Rector/Class_/FinalizeClassesWithoutChildrenRector/FinalizeClassesWithoutChildrenRectorTest.php --filter test#4
|
||||
```
|
||||
|
||||
If PHPUnit fails, you've successfully added a test case! :)
|
||||
|
||||
<br>
|
||||
|
||||
Thank you
|
||||
You can find it here: https://getrector.org/documentation/
|
||||
|
@ -1,16 +1,6 @@
|
||||
# How To Configure Rules
|
||||
|
||||
Rector rules that implement `Rector\Core\Contract\Rector\ConfigurableRectorInterface` can be configured.
|
||||
|
||||
Typical example is `Rector\Renaming\Rector\Name\RenameClassRector`:
|
||||
This page was moved to new documentation.
|
||||
|
||||
```php
|
||||
use Rector\Renaming\Rector\Name\RenameClassRector;
|
||||
use Rector\Config\RectorConfig;
|
||||
|
||||
return static function (RectorConfig $rectorConfig): void {
|
||||
$rectorConfig->ruleWithConfiguration(RenameClassRector::class, [
|
||||
'App\SomeOldClass' => 'App\SomeNewClass',
|
||||
]);
|
||||
};
|
||||
```
|
||||
You can find it here: https://getrector.org/documentation/
|
||||
|
@ -1,60 +1,5 @@
|
||||
# How To Ignore Rule or Paths
|
||||
|
||||
## Preferred Way: Config
|
||||
This page was moved to new documentation.
|
||||
|
||||
```php
|
||||
use Rector\CodeQuality\Rector\If_\SimplifyIfReturnBoolRector;
|
||||
use Rector\Config\RectorConfig;
|
||||
|
||||
return static function (RectorConfig $rectorConfig): void {
|
||||
// is there a file you need to skip?
|
||||
$rectorConfig->skip([
|
||||
// single file
|
||||
__DIR__ . '/src/ComplicatedFile.php',
|
||||
// or directory
|
||||
__DIR__ . '/src',
|
||||
// or fnmatch
|
||||
__DIR__ . '/src/*/Tests/*',
|
||||
|
||||
// is there single rule you don't like from a set you use?
|
||||
SimplifyIfReturnBoolRector::class,
|
||||
|
||||
// or just skip rule in specific directory
|
||||
SimplifyIfReturnBoolRector::class => [
|
||||
// single file
|
||||
__DIR__ . '/src/ComplicatedFile.php',
|
||||
// or directory
|
||||
__DIR__ . '/src',
|
||||
// or fnmatch
|
||||
__DIR__ . '/src/*/Tests/*',
|
||||
],
|
||||
]);
|
||||
};
|
||||
```
|
||||
|
||||
## In a File
|
||||
|
||||
For in-file exclusion, use `@noRector \Rector\SomeClass\NameRector` annotation:
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
class SomeClass
|
||||
{
|
||||
/**
|
||||
* @noRector
|
||||
*/
|
||||
public const NAME = '102';
|
||||
|
||||
/**
|
||||
* @noRector
|
||||
*/
|
||||
public function foo(): void
|
||||
{
|
||||
/** @noRector \Rector\DeadCode\Rector\Plus\RemoveDeadZeroAndOneOperationRector */
|
||||
round(1 + 0);
|
||||
}
|
||||
}
|
||||
```
|
||||
You can find it here: https://getrector.org/documentation/
|
||||
|
@ -1,45 +1,5 @@
|
||||
# How to Persist Cache Between CI Runs
|
||||
While parsing your application code, Rector generates objects representing that code. It caches these objects for later reuse, so it doesn't have to parse the entire application again, by detecting which files have changed since the last Rector run.
|
||||
|
||||
When running Rector in a Continuous Integration (CI) system such as [GitHub Actions](https://github.com/features/actions), the default implementation [uses an in-memory cache](https://github.com/rectorphp/rector/blob/1d28ca109ca536e8034c3c756ee61c65e6e63c8a/config/config.php#L89-L94). This means the next job that runs, will have to parse all code from scratch.
|
||||
This page was moved to new documentation.
|
||||
|
||||
```php
|
||||
use Rector\Caching\ValueObject\Storage\FileCacheStorage;
|
||||
|
||||
return static function (RectorConfig $rectorConfig): void {
|
||||
// ... your config
|
||||
|
||||
// Ensure file system caching is used instead of in-memory.
|
||||
$rectorConfig->cacheClass(FileCacheStorage::class);
|
||||
|
||||
// Specify a path that works locally as well as on CI job runners.
|
||||
$rectorConfig->cacheDirectory('./var/cache/rector');
|
||||
};
|
||||
```
|
||||
|
||||
Note that this caches relative to the repository directory, so it's the same directory on build as on development (and other environments). The actual path, when not specified, may vary per (runner) OS.
|
||||
|
||||
## Debugging the Cache Locally
|
||||
Generate the cache on your development machine, by running the command:
|
||||
```bash
|
||||
vendor/bin/rector process --dry-run --config=rector.php
|
||||
```
|
||||
You can find it in your repository directory under `./var/cache/rector/`, containing folders like `0a`, `0b`, `0c`, ... containing the cache objects representing the latest run.
|
||||
|
||||
This, preferably prepended with `php `, command is also what your CI action should run, after mapping the cache directory from an earlier run.
|
||||
|
||||
## GitHub Actions
|
||||
On GitHub Actions, you can use the [built-in cache action](https://github.com/actions/cache) as a step to point to a path that you want cached between jobs:
|
||||
|
||||
```yaml
|
||||
- name: Rector Cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ./var/cache/rector
|
||||
key: ${{ runner.os }}-rector-${{ hashFiles('**/composer.lock') }}
|
||||
restore-keys: ${{ runner.os }}-rector-
|
||||
|
||||
- name: Rector Dry Run
|
||||
run: php vendor/bin/rector process --dry-run --config=rector.php
|
||||
```
|
||||
In this key configuration, runs on branches inherit the cache from their parent, if any.
|
||||
You can find it here: https://getrector.org/documentation/
|
||||
|
@ -1,42 +1,5 @@
|
||||
# How To Register Custom SetList Constant
|
||||
|
||||
You can have custom `SetList` class that has constants that pointed to your own config, for example:
|
||||
This page was moved to new documentation.
|
||||
|
||||
|
||||
```php
|
||||
namespace App\Set\ValueObject;
|
||||
|
||||
use Rector\Set\Contract\SetListInterface;
|
||||
|
||||
final class SetList implements SetListInterface
|
||||
{
|
||||
public const MY_FRAMEWORK_20 = __DIR__ . '/../../../config/set/my-framework-20.php';
|
||||
}
|
||||
```
|
||||
|
||||
Now, you can register your custom `SetList`'s constant via import from `$containerConfigurator`, for example:
|
||||
|
||||
|
||||
```php
|
||||
use App\Set\ValueObject\SetList;
|
||||
use Rector\Config\RectorConfig;
|
||||
|
||||
return static function (RectorConfig $rectorConfig): void {
|
||||
$rectorConfig->sets([SetList::MY_FRAMEWORK_20]);
|
||||
|
||||
$rectorConfig->paths([__DIR__ . '/src']);
|
||||
};
|
||||
```
|
||||
|
||||
Note that if you are looking for the downgrade categories, there is already the `DowngradeSetList`:
|
||||
|
||||
```php
|
||||
use Rector\Set\ValueObject\DowngradeSetList;
|
||||
use Rector\Config\RectorConfig;
|
||||
|
||||
return static function (RectorConfig $rectorConfig): void {
|
||||
$rectorConfig->sets([DowngradeSetList::PHP_70])
|
||||
|
||||
$rectorConfig->paths([__DIR__ . '/src']);
|
||||
};
|
||||
```
|
||||
You can find it here: https://getrector.org/documentation/
|
||||
|
@ -1,32 +1,5 @@
|
||||
# How to Troubleshoot Parallel Issues
|
||||
|
||||
You may get some parallel errors and ask how you can identify if there is something in your code or a real parallel issue than can be fixed by configuration. They may be displayed as:
|
||||
This page was moved to new documentation.
|
||||
|
||||
```bash
|
||||
$ ./vendor/bin/rector process
|
||||
...
|
||||
[ERROR] Could not process "/app/vendor/rector/rector/vendor/symplify/easy-parallel/src/ValueObject/ParallelProcess.php" file, due to: "Child process timed out after 120 seconds". On line: 103
|
||||
[ERROR] Could not process some files, due to: "Reached system errors count limit of 50, exiting...".
|
||||
```
|
||||
|
||||
When that happens, the first good approach is to disable parallel processing. The output of parallel failures can hide some fatal errors from the source codebase. You can do so by:
|
||||
|
||||
```php
|
||||
$rectorConfig->disableParallel();
|
||||
```
|
||||
|
||||
After that, if rector processing works fine, that is an indication that you might need to adjust your parallel process to some balanced load, depending on the resources you have to process rector.
|
||||
|
||||
|
||||
If we check [parallel() method defaults](https://github.com/rectorphp/rector-src/blob/main/packages/Config/RectorConfig.php#L53):
|
||||
```php
|
||||
public function parallel(int $seconds = 120, int $maxNumberOfProcess = 16, int $jobSize = 20) : void
|
||||
```
|
||||
|
||||
You might find it helpful to keep it aligned with what you have at your disposal:
|
||||
|
||||
- timeout `$seconds` can be increased if you find your codebase has a job size with classes that require more time to process, and then you need more time to process
|
||||
- `$maxNumberOfProcess` may be decreased not to overload your system, and keeping some processes free and avoid side impacts of busy systems not being able to process files properly. For example: if you have four processes, you can use `$maxNumberOfProcess = 2` to keep two processes free and limit the system load.
|
||||
- `$jobSize` might be decreased if your files have too many lines of code, which would cause more time needed to process, which also will load the processes, etc
|
||||
|
||||
Happy coding!
|
||||
You can find it here: https://getrector.org/documentation/
|
||||
|
@ -1,105 +1,5 @@
|
||||
# Static Reflection and Autoload
|
||||
|
||||
This page was moved to new documentation.
|
||||
|
||||
Rector is using static reflection to load code without running it since version 0.10. That means your classes are found **without composer autoload and without running them**. Rector will find them and work with them as you have PSR-4 autoload properly setup. This comes very useful in legacy projects or projects with custom autoload.
|
||||
|
||||
Do you want to know more about it? Continue here:
|
||||
|
||||
- [From Doctrine Annotations Parser to Static Reflection](https://getrector.org/blog/from-doctrine-annotations-parser-to-static-reflection)
|
||||
- [Legacy Refactoring made Easy with Static Reflection](https://getrector.org/blog/2021/03/15/legacy-refactoring-made-easy-with-static-reflection)
|
||||
- [Zero Config Analysis with Static Reflection](https://phpstan.org/blog/zero-config-analysis-with-static-reflection) - from PHPStan
|
||||
|
||||
```php
|
||||
use Rector\Config\RectorConfig;
|
||||
|
||||
return static function (RectorConfig $rectorConfig): void {
|
||||
// Rector is using static reflection to load code without running it - see https://phpstan.org/blog/zero-config-analysis-with-static-reflection
|
||||
$rectorConfig->autoloadPaths([
|
||||
// discover specific file
|
||||
__DIR__ . '/file-with-functions.php',
|
||||
// or full directory
|
||||
__DIR__ . '/project-without-composer',
|
||||
]);
|
||||
```
|
||||
|
||||
## Include Files
|
||||
|
||||
Do you need to include constants, class aliases or custom autoloader? Use bootstrap files:
|
||||
|
||||
```php
|
||||
use Rector\Config\RectorConfig;
|
||||
|
||||
return static function (RectorConfig $rectorConfig): void {
|
||||
$rectorConfig->bootstrapFiles([
|
||||
__DIR__ . '/constants.php',
|
||||
__DIR__ . '/project/special/autoload.php',
|
||||
]);
|
||||
};
|
||||
```
|
||||
|
||||
Listed files will be executed like:
|
||||
|
||||
```php
|
||||
include $filePath;
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
Sometime, when we run Rector to class that detect children class, like `\Rector\Privatization\Rector\Class_\FinalizeClassesWithoutChildrenRector`, we may experience that parent class changed to final while it has children class, it because of the `PHPStan\Reflection\ReflectionProvider` cannot get all classes on scanning it on usage via `FamilyRelationsAnalyzer` service.
|
||||
|
||||
To avoid this issue, you may dump all classes via composer:
|
||||
|
||||
```bash
|
||||
composer dump-autoload -o
|
||||
```
|
||||
|
||||
before run the rector.
|
||||
|
||||
If the false positive still happen, you can skip the rule applied as last resort to do:
|
||||
|
||||
```php
|
||||
use Rector\Privatization\Rector\Class_\FinalizeClassesWithoutChildrenRector;
|
||||
|
||||
$rectorConfig->skip([
|
||||
FinalizeClassesWithoutChildrenRector::class => [
|
||||
// classes that has children, and not detected even with composer dump-autoload -o
|
||||
__DIR__ . '/src/HasChildClass.php',
|
||||
],
|
||||
]);
|
||||
```
|
||||
|
||||
## Dealing with "Class ... was not found while trying to analyse it..."
|
||||
Sometimes you may encounter this error ([see here for an example](https://github.com/rectorphp/rector/issues/6688)) even if the class is there and it seems to work properly with other tools (e.g. PHPStan).
|
||||
|
||||
In this case you may want to try one of the following solutions:
|
||||
|
||||
### Register
|
||||
|
||||
```php
|
||||
$rectorConfig->autoloadPaths([
|
||||
// the path to the exact class file
|
||||
__DIR__ . '/vendor/acme/my-custom-dependency/src/Your/Own/Namespace/TheAffectedClass.php',
|
||||
// or you can specify a wider scope
|
||||
__DIR__ . '/vendor/acme/my-custom-dependency/src',
|
||||
// WARNING: beware of performances, try to narrow down the path
|
||||
// as much as you can or you will slow down each run
|
||||
]);
|
||||
```
|
||||
|
||||
### Register the path of the class to composer.json's `"files"` config, eg:
|
||||
|
||||
```javascript
|
||||
"autoload-dev": {
|
||||
"files": [
|
||||
"vendor/acme/my-custom-dependency/src/Your/Own/Namespace/TheAffectedClass.php"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
After that, run:
|
||||
|
||||
```bash
|
||||
composer dump-autoload
|
||||
```
|
||||
|
||||
and re-run the rector.
|
||||
You can find it here: https://getrector.org/documentation/
|
||||
|
@ -17,12 +17,12 @@ final class VersionResolver
|
||||
* @api
|
||||
* @var string
|
||||
*/
|
||||
public const PACKAGE_VERSION = '1f46de3de704155da47e3b8d87312224cb5550d6';
|
||||
public const PACKAGE_VERSION = 'd670b4e50deb738f15d77c6a4f7fe773791c871f';
|
||||
/**
|
||||
* @api
|
||||
* @var string
|
||||
*/
|
||||
public const RELEASE_DATE = '2022-12-03 11:47:50';
|
||||
public const RELEASE_DATE = '2022-12-03 12:05:16';
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
|
2
vendor/autoload.php
vendored
2
vendor/autoload.php
vendored
@ -22,4 +22,4 @@ if (PHP_VERSION_ID < 50600) {
|
||||
|
||||
require_once __DIR__ . '/composer/autoload_real.php';
|
||||
|
||||
return ComposerAutoloaderInit7b8ec49fbbe9ed9cebfaf25cfae289ae::getLoader();
|
||||
return ComposerAutoloaderInitddaf13b049008d6f65af9a1cac74ef8b::getLoader();
|
||||
|
14
vendor/composer/autoload_real.php
vendored
14
vendor/composer/autoload_real.php
vendored
@ -2,7 +2,7 @@
|
||||
|
||||
// autoload_real.php @generated by Composer
|
||||
|
||||
class ComposerAutoloaderInit7b8ec49fbbe9ed9cebfaf25cfae289ae
|
||||
class ComposerAutoloaderInitddaf13b049008d6f65af9a1cac74ef8b
|
||||
{
|
||||
private static $loader;
|
||||
|
||||
@ -22,19 +22,19 @@ class ComposerAutoloaderInit7b8ec49fbbe9ed9cebfaf25cfae289ae
|
||||
return self::$loader;
|
||||
}
|
||||
|
||||
spl_autoload_register(array('ComposerAutoloaderInit7b8ec49fbbe9ed9cebfaf25cfae289ae', 'loadClassLoader'), true, true);
|
||||
spl_autoload_register(array('ComposerAutoloaderInitddaf13b049008d6f65af9a1cac74ef8b', 'loadClassLoader'), true, true);
|
||||
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
|
||||
spl_autoload_unregister(array('ComposerAutoloaderInit7b8ec49fbbe9ed9cebfaf25cfae289ae', 'loadClassLoader'));
|
||||
spl_autoload_unregister(array('ComposerAutoloaderInitddaf13b049008d6f65af9a1cac74ef8b', 'loadClassLoader'));
|
||||
|
||||
require __DIR__ . '/autoload_static.php';
|
||||
call_user_func(\Composer\Autoload\ComposerStaticInit7b8ec49fbbe9ed9cebfaf25cfae289ae::getInitializer($loader));
|
||||
call_user_func(\Composer\Autoload\ComposerStaticInitddaf13b049008d6f65af9a1cac74ef8b::getInitializer($loader));
|
||||
|
||||
$loader->setClassMapAuthoritative(true);
|
||||
$loader->register(true);
|
||||
|
||||
$includeFiles = \Composer\Autoload\ComposerStaticInit7b8ec49fbbe9ed9cebfaf25cfae289ae::$files;
|
||||
$includeFiles = \Composer\Autoload\ComposerStaticInitddaf13b049008d6f65af9a1cac74ef8b::$files;
|
||||
foreach ($includeFiles as $fileIdentifier => $file) {
|
||||
composerRequire7b8ec49fbbe9ed9cebfaf25cfae289ae($fileIdentifier, $file);
|
||||
composerRequireddaf13b049008d6f65af9a1cac74ef8b($fileIdentifier, $file);
|
||||
}
|
||||
|
||||
return $loader;
|
||||
@ -46,7 +46,7 @@ class ComposerAutoloaderInit7b8ec49fbbe9ed9cebfaf25cfae289ae
|
||||
* @param string $file
|
||||
* @return void
|
||||
*/
|
||||
function composerRequire7b8ec49fbbe9ed9cebfaf25cfae289ae($fileIdentifier, $file)
|
||||
function composerRequireddaf13b049008d6f65af9a1cac74ef8b($fileIdentifier, $file)
|
||||
{
|
||||
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
|
||||
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
|
||||
|
8
vendor/composer/autoload_static.php
vendored
8
vendor/composer/autoload_static.php
vendored
@ -4,7 +4,7 @@
|
||||
|
||||
namespace Composer\Autoload;
|
||||
|
||||
class ComposerStaticInit7b8ec49fbbe9ed9cebfaf25cfae289ae
|
||||
class ComposerStaticInitddaf13b049008d6f65af9a1cac74ef8b
|
||||
{
|
||||
public static $files = array (
|
||||
'ad155f8f1cf0d418fe49e248db8c661b' => __DIR__ . '/..' . '/react/promise/src/functions_include.php',
|
||||
@ -3023,9 +3023,9 @@ class ComposerStaticInit7b8ec49fbbe9ed9cebfaf25cfae289ae
|
||||
public static function getInitializer(ClassLoader $loader)
|
||||
{
|
||||
return \Closure::bind(function () use ($loader) {
|
||||
$loader->prefixLengthsPsr4 = ComposerStaticInit7b8ec49fbbe9ed9cebfaf25cfae289ae::$prefixLengthsPsr4;
|
||||
$loader->prefixDirsPsr4 = ComposerStaticInit7b8ec49fbbe9ed9cebfaf25cfae289ae::$prefixDirsPsr4;
|
||||
$loader->classMap = ComposerStaticInit7b8ec49fbbe9ed9cebfaf25cfae289ae::$classMap;
|
||||
$loader->prefixLengthsPsr4 = ComposerStaticInitddaf13b049008d6f65af9a1cac74ef8b::$prefixLengthsPsr4;
|
||||
$loader->prefixDirsPsr4 = ComposerStaticInitddaf13b049008d6f65af9a1cac74ef8b::$prefixDirsPsr4;
|
||||
$loader->classMap = ComposerStaticInitddaf13b049008d6f65af9a1cac74ef8b::$classMap;
|
||||
|
||||
}, null, ClassLoader::class);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user