From 51e89c3f32c7f588dfd82b4b914f0ba9518adb0f Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Tue, 12 Apr 2022 10:52:46 +0200 Subject: [PATCH] [docs] Improve first-time contributors docs (#2061) --- CONTRIBUTING.md | 26 ++++++--- build/target-repository/README.md | 13 +++-- .../docs/auto_import_names.md | 11 +++- .../docs/how_to_add_test_for_rector_rule.md | 56 +++++++------------ packages/Config/RectorConfig.php | 11 ++++ .../config/auto_import_names.php | 18 +++--- templates/rector.php.dist | 24 ++++---- 7 files changed, 79 insertions(+), 80 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 770c6285b3d..78e4e248a54 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,28 +1,36 @@ # How to Contribute -Contributions here are more than welcomed! You can contribute to [rector-src](https://github.com/rectorphp/rector-src) repository. +Contributions here are more than welcomed! You can contribute to [rector-src](https://github.com/rectorphp/rector-src) repository or one of [extension packages](https://github.com/rectorphp/). ## Preparing Local Environment -If you have PHP 8 and Composer installed locally you can use it straight away. You can validate your environment with: +1. Fork the [rector/rector-src](https://github.com/rectorphp/rector-src) repository and clone it + +```bash +git clone git@github.com:rectorphp/rector-src.git +cd rector-src +``` + +2. We use PHP 8.1 and composer + +Verify your local environment and update dependencies: ```bash composer check-platform-reqs +composer update ``` -Alternatively you can use Docker runtime. All you need to do is wrap every command with `docker-compose run php`, so commands will be executed inside Docker container. +*Note: using Docker for contributing is strongly discouraged, as it requires [extra knowledge of composer internals](https://github.com/composer/composer/issues/9368#issuecomment-718112361).* -For example, to download PHP dependencies: +Then you can start working with the code :+1: -```bash -docker-compose run php composer install -``` +
-Now you can start using all scripts and work with the code. +Do you want to **contribute a failing test**? [This tutorial will sow you how](https://github.com/rectorphp/rector/blob/main/docs/how_to_add_test_for_rector_rule.md) ## Preparing Pull Request -There 3 rules will highly increase chance to get your PR merged: +There 3 steps will make your pull-request easy to merge: - **1 feature per pull-request** - **new features need tests** diff --git a/build/target-repository/README.md b/build/target-repository/README.md index bb7f7905675..b1f147a193b 100644 --- a/build/target-repository/README.md +++ b/build/target-repository/README.md @@ -8,7 +8,7 @@ Rector instantly upgrades and refactors the PHP code of your application. It ca ### 1. Instant Upgrades -Rector now supports upgrades from PHP 5.3 to 8.0 and major open-source projects like [Symfony](https://github.com/rectorphp/rector-symfony), [PHPUnit](https://github.com/rectorphp/rector-phpunit), [Nette](https://github.com/rectorphp/rector-nette), [Laravel](https://github.com/rectorphp/rector-laravel), [CakePHP](https://github.com/rectorphp/rector-cakephp), [Doctrine](https://github.com/rectorphp/rector-doctrine), [PHPOffice](https://github.com/rectorphp/rector-phpoffice) and [TYPO3](https://github.com/sabbelasichon/typo3-rector) out of the box. Do you want to **be constantly on the latest PHP/framework version without effort**? +Rector now supports upgrades from PHP 5.3 to 8.1 and major open-source projects like [Symfony](https://github.com/rectorphp/rector-symfony), [PHPUnit](https://github.com/rectorphp/rector-phpunit), [Nette](https://github.com/rectorphp/rector-nette), [Laravel](https://github.com/rectorphp/rector-laravel), [CakePHP](https://github.com/rectorphp/rector-cakephp), [Doctrine](https://github.com/rectorphp/rector-doctrine) and [TYPO3](https://github.com/sabbelasichon/typo3-rector) out of the box. Do you want to **be constantly on the latest PHP and Framework without effort**? Use Rector to handle **instant upgrades** for you. @@ -34,21 +34,22 @@ By [buying a book](https://leanpub.com/rector-the-power-of-automated-refactoring ## Documentation -- [Explore 450+ Rector Rules](/docs/rector_rules_overview.md) -- [Auto Import Names](/docs/auto_import_names.md) +- [Explore 500+ 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) -- [Beyond PHP - Entering the realm of FileProcessors](/docs/beyond_php_file_processors.md) +- [Auto Import Names](/docs/auto_import_names.md) ### For Rule Developers and Contributors +- [How to add Test for Rector Rule](/docs/how_to_add_test_for_rector_rule.md) - [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 Generate New 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 create a custom FileProcessor](/docs/how_to_create_custom_fileprocessor.md) + +See [the full documentation](/docs). +
## Install diff --git a/build/target-repository/docs/auto_import_names.md b/build/target-repository/docs/auto_import_names.md index b728a51318c..da37a3b155b 100644 --- a/build/target-repository/docs/auto_import_names.md +++ b/build/target-repository/docs/auto_import_names.md @@ -16,7 +16,7 @@ Rector works with all class names as fully qualified by default, so it knows the To import FQN like these, configure `rector.php` with: ```php -$parameters->set(Option::AUTO_IMPORT_NAMES, true); +$rectorConfig->autoImportNames(); ```
@@ -37,8 +37,9 @@ $parameters->set(Option::IMPORT_SHORT_CLASSES, false);
-If you have set Option::AUTO_IMPORT_NAMES to true, rector is applying this to every analyzed file, even if no real change by a rector was applied to the file. -The reason is that a so-called post rector is responsible for this, namely the NameImportingPostRector. +If you have set `Option::AUTO_IMPORT_NAMES` to `true`, rector is applying this to every analyzed file, even if no real change by a rector was applied to the file. + +The reason is that a so-called post-rector is responsible for this, namely the `NameImportingPostRector`. If you like to apply the Option::AUTO_IMPORT_NAMES only for real changed files, you can configure this. ```php @@ -65,3 +66,7 @@ Run it: ```bash vendor/bin/ecs check src --fix ``` + +
+ +Happy coding! diff --git a/build/target-repository/docs/how_to_add_test_for_rector_rule.md b/build/target-repository/docs/how_to_add_test_for_rector_rule.md index af80ac9b98f..ebf572dbf91 100644 --- a/build/target-repository/docs/how_to_add_test_for_rector_rule.md +++ b/build/target-repository/docs/how_to_add_test_for_rector_rule.md @@ -9,37 +9,11 @@ When using Rector to update your own code, you will typically be using release r - 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 and create a new pull request to https://github.com/rectorphp/rector-src +- 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 -Alternatively, the above may be performed on the CLI - -```bash -# Authenticate -gh auth login - -# Fork and clone the repository -gh repo fork https://github.com/rectorphp/rector-src - -# Install dependencies -cd rector-src -composer install - -# Test installation -composer fix-cs -composer phpstan - -# Create and checkout a branch -git checkout -b your_branch_name - -# Create test as described below - -# Push the branch -git push -u origin your_branch_name - -# create new pull request to https://github.com/rectorphp/rector-src -gh pr create --title "Your title text" --body "Your body text" -``` +
## 2. Detect the Rector Rule @@ -57,6 +31,8 @@ Our rule in this example is: `Rector\Privatization\Rector\Class_\FinalizeClasses 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. +
+ ## 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**. @@ -79,6 +55,8 @@ bin/rector process app/SomeFile.php Do we have the same diff? Great! +
+ ## 4. Find the Rector Test Case Now we need to find the test case. The test case name is rule + `Test` suffix. @@ -89,14 +67,12 @@ Now we need to find the test case. The test case name is rule + `Test` suffix. `FinalizeClassesWithoutChildrenRectorTest` (test class) -↓ - -`FinalizeClassesWithoutChildrenRectorTest.php` (test file) - Right here: ![Rule Test Case](/docs/images/docs_rule_test_case.png) +
+ ## 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. @@ -105,9 +81,11 @@ Do you see *test fixture file* first time? It's a file with real-life PHP code t 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. -There are 2 fixture formats. +
-### 1. The Code Should Change +There are 2 fixture formats: + +### A. The Code Should Change ```bash @@ -115,7 +93,7 @@ There are 2 fixture formats. ``` -### 2. The Code Should Be Skipped +### B. The Code Should Be Skipped ```bash @@ -164,3 +142,7 @@ vendor/bin/phpunit rules-tests/Privatization/Rector/Class_/FinalizeClassesWithou ``` If PHPUnit fails, you've successfully added a test case! :) + +
+ +Thank you diff --git a/packages/Config/RectorConfig.php b/packages/Config/RectorConfig.php index f51d6226ae7..bc70d790ff7 100644 --- a/packages/Config/RectorConfig.php +++ b/packages/Config/RectorConfig.php @@ -88,4 +88,15 @@ final class RectorConfig extends ContainerConfigurator $services->set($rectorClass) ->configure($configuration); } + + /** + * @param class-string $rectorClass + */ + public function rule(string $rectorClass): void + { + Assert::isAOf($rectorClass, RectorInterface::class); + + $services = $this->services(); + $services->set($rectorClass); + } } diff --git a/rules-tests/Renaming/Rector/Name/RenameClassRector/config/auto_import_names.php b/rules-tests/Renaming/Rector/Name/RenameClassRector/config/auto_import_names.php index 2505a22dd4f..8cc75fcae99 100644 --- a/rules-tests/Renaming/Rector/Name/RenameClassRector/config/auto_import_names.php +++ b/rules-tests/Renaming/Rector/Name/RenameClassRector/config/auto_import_names.php @@ -2,22 +2,18 @@ declare(strict_types=1); -use Rector\Core\Configuration\Option; +use Rector\Config\RectorConfig; use Rector\Renaming\Rector\Name\RenameClassRector; use Rector\Tests\Renaming\Rector\Name\RenameClassRector\Source\FirstNamespace\SomeServiceClass as SomeServiceClassFirstNamespace; use Rector\Tests\Renaming\Rector\Name\RenameClassRector\Source\NewClass; use Rector\Tests\Renaming\Rector\Name\RenameClassRector\Source\OldClass; use Rector\Tests\Renaming\Rector\Name\RenameClassRector\Source\SecondNamespace\SomeServiceClass; -use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator; -return static function (ContainerConfigurator $containerConfigurator): void { - $parameters = $containerConfigurator->parameters(); - $parameters->set(Option::AUTO_IMPORT_NAMES, true); +return static function (RectorConfig $rectorConfig): void { + $rectorConfig->autoImportNames(); - $services = $containerConfigurator->services(); - $services->set(RenameClassRector::class) - ->configure([ - OldClass::class => NewClass::class, - SomeServiceClassFirstNamespace::class => SomeServiceClass::class, - ]); + $rectorConfig->ruleWithConfiguration(RenameClassRector::class, [ + OldClass::class => NewClass::class, + SomeServiceClassFirstNamespace::class => SomeServiceClass::class, + ]); }; diff --git a/templates/rector.php.dist b/templates/rector.php.dist index 08a29eebb3d..062b41b93b6 100644 --- a/templates/rector.php.dist +++ b/templates/rector.php.dist @@ -2,24 +2,20 @@ declare(strict_types=1); -use Rector\Core\Configuration\Option; -use Rector\Php74\Rector\Property\TypedPropertyRector; +use Rector\CodeQuality\Rector\Class_\InlineConstructorDefaultToPropertyRector; +use Rector\Config\RectorConfig; use Rector\Set\ValueObject\LevelSetList; -use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator; -return static function (ContainerConfigurator $containerConfigurator): void { - // get parameters - $parameters = $containerConfigurator->parameters(); - $parameters->set(Option::PATHS, [ +return static function (RectorConfig $rectorConfig): void { + $rectorConfig->paths([ __DIR__ . '/src' ]); - // Define what rule sets will be applied - $containerConfigurator->import(LevelSetList::UP_TO_PHP_XY); - - // get services (needed for register a single rule) - // $services = $containerConfigurator->services(); - // register a single rule - // $services->set(TypedPropertyRector::class); + $rectorConfig->rule(InlineConstructorDefaultToPropertyRector::class); + + // define sets of rules + // $rectorConfig->sets([ + // LevelSetList::UP_TO_PHP_XY + // ]); };