Skip to content

Add Rector #2

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Nov 20, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ locally they will need to be installed. All of them are available via [Phive](ht
* [Infection](https://infection.github.io/)
* [PHP Coveralls](https://php-coveralls.github.io/php-coveralls/)
* [PHP CS Fixer](https://cs.symfony.com/)
* [Rector](https://github.com/rectorphp/rector/)

## Source Files

Expand Down Expand Up @@ -120,6 +121,18 @@ running unit tests. This workflow also configures PHPUnit to report on code cove
upload the results to [Coveralls.io](https://coveralls.io) (you will need a free account,
but it is also fine to use this workflow without Coveralls).

#### Rector

*Requires **rector.php***

Rector provides automated refactoring of code, allowing you to make sweeping updates based on
predefined rulesets. Rector can be highly opinionated based on its configuration file (**rector.php**)
so be sure to read the documentation and figure out the best fit for you. This workflow performs
a "dry run" to check for any changes that Rector would have made and fail if there are matches.

> Note: Rector updates rules all the time so you may want to lock your repo to the latest known working version of Rector to prevent unexpected failures
> E.g. in **.github/workflows/rector.yml** supply the specific minor patch: `composer global require --dev rector/rector:0.12.4`

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

#### Unused

Composer Unused does one thing: checks that your code actually uses the dependencies you
Expand Down
68 changes: 68 additions & 0 deletions src/.github/workflows/rector.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
name: Rector

on:
pull_request:
branches:
- develop
paths:
- '**.php'
- 'composer.**'
- 'rector.php'
- '.github/workflows/rector.yml'
push:
branches:
- develop
paths:
- '**.php'
- 'composer.**'
- 'rector.php'
- '.github/workflows/rector.yml'

jobs:
build:
name: PHP ${{ matrix.php-versions }} Rector Analysis
runs-on: ubuntu-latest
if: "!contains(github.event.head_commit.message, '[ci skip]')"
strategy:
fail-fast: false
matrix:
php-versions: ['7.3', '7.4', '8.0']

steps:
- name: Checkout
uses: actions/checkout@v2

- name: Set up PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-versions }}
tools: phpstan
extensions: intl, json, mbstring, xml
coverage: none
env:
COMPOSER_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Get composer cache directory
id: composer-cache
run: echo "::set-output name=dir::$(composer config cache-files-dir)"

- name: Cache composer dependencies
uses: actions/cache@v2
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}-${{ hashFiles('**/composer.lock') }}
restore-keys: ${{ runner.os }}-composer-

- name: Install dependencies
run: |
composer -q config -g github-oauth.github.com "${{ secrets.GITHUB_TOKEN }}"
if [ -f composer.lock ]; then
composer install --no-progress --no-interaction --prefer-dist --optimize-autoloader
else
composer update --no-progress --no-interaction --prefer-dist --optimize-autoloader
fi

- name: Analyze for refactoring
run: |
composer global require --dev rector/rector
rector process --dry-run --no-progress-bar
108 changes: 108 additions & 0 deletions src/rector.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
<?php

use Rector\CodeQuality\Rector\BooleanAnd\SimplifyEmptyArrayCheckRector;
use Rector\CodeQuality\Rector\Expression\InlineIfToExplicitIfRector;
use Rector\CodeQuality\Rector\For_\ForToForeachRector;
use Rector\CodeQuality\Rector\Foreach_\UnusedForeachValueToArrayKeysRector;
use Rector\CodeQuality\Rector\FuncCall\AddPregQuoteDelimiterRector;
use Rector\CodeQuality\Rector\FuncCall\ChangeArrayPushToArrayAssignRector;
use Rector\CodeQuality\Rector\FuncCall\SimplifyRegexPatternRector;
use Rector\CodeQuality\Rector\FuncCall\SimplifyStrposLowerRector;
use Rector\CodeQuality\Rector\If_\CombineIfRector;
use Rector\CodeQuality\Rector\If_\ShortenElseIfRector;
use Rector\CodeQuality\Rector\If_\SimplifyIfElseToTernaryRector;
use Rector\CodeQuality\Rector\If_\SimplifyIfReturnBoolRector;
use Rector\CodeQuality\Rector\Return_\SimplifyUselessVariableRector;
use Rector\CodeQuality\Rector\Ternary\UnnecessaryTernaryExpressionRector;
use Rector\CodingStyle\Rector\ClassMethod\FuncGetArgsToVariadicParamRector;
use Rector\CodingStyle\Rector\ClassMethod\MakeInheritedMethodVisibilitySameAsParentRector;
use Rector\CodingStyle\Rector\FuncCall\CountArrayToEmptyArrayComparisonRector;
use Rector\Core\Configuration\Option;
use Rector\Core\ValueObject\PhpVersion;
use Rector\DeadCode\Rector\ClassMethod\RemoveUnusedPromotedPropertyRector;
use Rector\DeadCode\Rector\MethodCall\RemoveEmptyMethodCallRector;
use Rector\EarlyReturn\Rector\Foreach_\ChangeNestedForeachIfsToEarlyContinueRector;
use Rector\EarlyReturn\Rector\If_\ChangeIfElseValueAssignToEarlyReturnRector;
use Rector\EarlyReturn\Rector\If_\RemoveAlwaysElseRector;
use Rector\EarlyReturn\Rector\Return_\PreparedValueToEarlyReturnRector;
use Rector\Php55\Rector\String_\StringClassNameToClassConstantRector;
use Rector\Php56\Rector\FunctionLike\AddDefaultValueForUndefinedVariableRector;
use Rector\Php73\Rector\FuncCall\JsonThrowOnErrorRector;
use Rector\Php73\Rector\FuncCall\StringifyStrNeedlesRector;
use Rector\PHPUnit\Set\PHPUnitSetList;
use Rector\Set\ValueObject\LevelSetList;
use Rector\Set\ValueObject\SetList;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;

return static function (ContainerConfigurator $containerConfigurator): void {
// Rule sets to apply
$containerConfigurator->import(SetList::DEAD_CODE);
$containerConfigurator->import(LevelSetList::UP_TO_PHP_73);
$containerConfigurator->import(PHPUnitSetList::PHPUNIT_SPECIFIC_METHOD);
$containerConfigurator->import(PHPUnitSetList::PHPUNIT_80);

$parameters = $containerConfigurator->parameters();

// The paths to refactor (can also be supplied with CLI arguments)
$parameters->set(Option::PATHS, [
__DIR__ . '/app',
__DIR__ . '/tests',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this not used in CodeIgniter4 project as not check system dir?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The intent is not for this to be used in the framework repo but distributable to developer's projects and libraries. Libraries will need to adjust the path from app/ to src/ (or whatever they use), but that is the case for all the files in this repo and I hope to make a scripted solution down the road.

]);

// Do you need to include constants, class aliases, or a custom autoloader?
$parameters->set(Option::BOOTSTRAP_FILES, [
realpath(getcwd()) . '/vendor/codeigniter4/framework/system/Test/bootstrap.php',
]);

// Set the target version for refactoring
$parameters->set(Option::PHP_VERSION_FEATURES, PhpVersion::PHP_73);

// Auto-import fully qualified class names
$parameters->set(Option::AUTO_IMPORT_NAMES, true);

// Are there files or rules you need to skip?
$parameters->set(Option::SKIP, [
__DIR__ . '/app/Views',

JsonThrowOnErrorRector::class,
StringifyStrNeedlesRector::class,

// Note: requires php 8
RemoveUnusedPromotedPropertyRector::class,

// Ignore tests that might make calls without a result
RemoveEmptyMethodCallRector::class => [
__DIR__ . '/tests',
],

// May load view files directly when detecting classes
StringClassNameToClassConstantRector::class,

// May be uninitialized on purpose
AddDefaultValueForUndefinedVariableRector::class,
]);

// Additional rules to apply
$services = $containerConfigurator->services();
$services->set(SimplifyUselessVariableRector::class);
$services->set(RemoveAlwaysElseRector::class);
$services->set(CountArrayToEmptyArrayComparisonRector::class);
$services->set(ForToForeachRector::class);
$services->set(ChangeNestedForeachIfsToEarlyContinueRector::class);
$services->set(ChangeIfElseValueAssignToEarlyReturnRector::class);
$services->set(SimplifyStrposLowerRector::class);
$services->set(CombineIfRector::class);
$services->set(SimplifyIfReturnBoolRector::class);
$services->set(InlineIfToExplicitIfRector::class);
$services->set(PreparedValueToEarlyReturnRector::class);
$services->set(ShortenElseIfRector::class);
$services->set(SimplifyIfElseToTernaryRector::class);
$services->set(UnusedForeachValueToArrayKeysRector::class);
$services->set(ChangeArrayPushToArrayAssignRector::class);
$services->set(UnnecessaryTernaryExpressionRector::class);
$services->set(AddPregQuoteDelimiterRector::class);
$services->set(SimplifyRegexPatternRector::class);
$services->set(FuncGetArgsToVariadicParamRector::class);
$services->set(MakeInheritedMethodVisibilitySameAsParentRector::class);
$services->set(SimplifyEmptyArrayCheckRector::class);
};