Skip to content
Open
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
1 change: 1 addition & 0 deletions e2e/rules-summary-option/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/vendor
1 change: 1 addition & 0 deletions e2e/rules-summary-option/cli-options.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
--rules-summary
7 changes: 7 additions & 0 deletions e2e/rules-summary-option/composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"require": {
"php": "^8.1"
},
"minimum-stability": "dev",
"prefer-stable": true
}
68 changes: 68 additions & 0 deletions e2e/rules-summary-option/expected-output.diff
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
3 files with changes
====================

1) src/AlwaysTrue.php:4

---------- begin diff ----------
@@ @@
{
public function run()
{
- if (1 === 1) {
- }
-
- if (2 === 2) {
- }
-
return 'no';
}
}
----------- end diff -----------

Applied rules:
* RemoveAlwaysTrueIfConditionRector


2) src/AnotherAlwaysTrue.php:4

---------- begin diff ----------
@@ @@
{
public function run()
{
- if (3 === 3) {
- }
-
return 'yes';
}
}
----------- end diff -----------

Applied rules:
* RemoveAlwaysTrueIfConditionRector


3) src/DeadConstructor.php:2

---------- begin diff ----------
@@ @@

final class DeadConstructor
{
- public function __construct()
- {
- }
}
----------- end diff -----------

Applied rules:
* RemoveEmptyClassMethodRector


Rules Summary
-------------

* RemoveAlwaysTrueIfConditionRector would have been applied 2 times
* RemoveEmptyClassMethodRector would have been applied 1 time

[OK] 3 files would have been changed (dry-run) by Rector
16 changes: 16 additions & 0 deletions e2e/rules-summary-option/rector.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

declare(strict_types=1);

use Rector\Config\RectorConfig;
use Rector\DeadCode\Rector\ClassMethod\RemoveEmptyClassMethodRector;
use Rector\DeadCode\Rector\If_\RemoveAlwaysTrueIfConditionRector;

return static function (RectorConfig $rectorConfig): void {
$rectorConfig->paths([
__DIR__ . '/src',
]);

$rectorConfig->rule(RemoveEmptyClassMethodRector::class);
$rectorConfig->rule(RemoveAlwaysTrueIfConditionRector::class);
};
15 changes: 15 additions & 0 deletions e2e/rules-summary-option/src/AlwaysTrue.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

final class AlwaysTrue
{
public function run()
{
if (1 === 1) {
}

if (2 === 2) {
}

return 'no';
}
}
12 changes: 12 additions & 0 deletions e2e/rules-summary-option/src/AnotherAlwaysTrue.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

final class AnotherAlwaysTrue
{
public function run()
{
if (3 === 3) {
}

return 'yes';
}
}
8 changes: 8 additions & 0 deletions e2e/rules-summary-option/src/DeadConstructor.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

final class DeadConstructor
{
public function __construct()
{
}
}
29 changes: 29 additions & 0 deletions src/ChangesReporting/Output/ConsoleOutputFormatter.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ public function report(ProcessResult $processResult, Configuration $configuratio
$this->symfonyStyle->newLine();
}

if ($configuration->shouldShowRulesSummary()) {
$this->reportRulesSummary($processResult, $configuration);
}

$message = $this->createSuccessMessage($processResult, $configuration);
$this->symfonyStyle->success($message);
}
Expand Down Expand Up @@ -131,6 +135,31 @@ private function reportErrors(array $errors, bool $absoluteFilePath): void
}
}

private function reportRulesSummary(ProcessResult $processResult, Configuration $configuration): void
{
$ruleApplicationCounts = $processResult->getRuleApplicationCounts();
if ($ruleApplicationCounts === []) {
return;
}

$verb = $configuration->isDryRun() ? 'would have been applied' : 'was applied';

$this->symfonyStyle->section('Rules Summary');

foreach ($ruleApplicationCounts as $ruleClass => $count) {
$ruleShortClass = (string) Strings::after($ruleClass, '\\', -1);
$this->symfonyStyle->writeln(sprintf(
' * <info>%s</info> %s <comment>%d</comment> time%s',
$ruleShortClass,
$verb,
$count,
$count > 1 ? 's' : ''
));
}

$this->symfonyStyle->newLine();
}

private function normalizePathsToRelativeWithLine(string $errorMessage): string
{
$regex = '#' . preg_quote(getcwd(), '#') . '/#';
Expand Down
3 changes: 3 additions & 0 deletions src/Configuration/ConfigurationFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ public function createFromInput(InputInterface $input): Configuration

$levelOverflows = SimpleParameterProvider::provideArrayParameter(Option::LEVEL_OVERFLOWS);

$showRulesSummary = (bool) $input->getOption(Option::RULES_SUMMARY);

return new Configuration(
$isDryRun,
$showProgressBar,
Expand All @@ -104,6 +106,7 @@ public function createFromInput(InputInterface $input): Configuration
$onlyRule,
$onlySuffix,
$levelOverflows,
$showRulesSummary,
);
}

Expand Down
2 changes: 2 additions & 0 deletions src/Configuration/Option.php
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,8 @@ final class Option

public const string XDEBUG = 'xdebug';

public const string RULES_SUMMARY = 'rules-summary';

public const string CONFIG = 'config';

/**
Expand Down
7 changes: 7 additions & 0 deletions src/Console/ProcessConfigureDecorator.php
Original file line number Diff line number Diff line change
Expand Up @@ -74,5 +74,12 @@ public static function decorate(Command $command): void
$command->addOption(Option::PARALLEL_IDENTIFIER, null, InputOption::VALUE_REQUIRED);

$command->addOption(Option::XDEBUG, null, InputOption::VALUE_NONE, 'Display xdebug output.');

$command->addOption(
Option::RULES_SUMMARY,
null,
InputOption::VALUE_NONE,
'Show summary of rules applied during the run.'
);
}
}
6 changes: 6 additions & 0 deletions src/ValueObject/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ public function __construct(
private ?string $onlyRule = null,
private ?string $onlySuffix = null,
private array $levelOverflows = [],
private bool $showRulesSummary = false,
) {
}

Expand Down Expand Up @@ -141,4 +142,9 @@ public function getBothSetAndRulesDuplicatedRegistrations(): array

return array_unique($ruleDuplicatedRegistrations);
}

public function shouldShowRulesSummary(): bool
{
return $this->showRulesSummary;
}
}
22 changes: 22 additions & 0 deletions src/ValueObject/ProcessResult.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Rector\ValueObject;

use Rector\Contract\Rector\RectorInterface;
use Rector\ValueObject\Error\SystemError;
use Rector\ValueObject\Reporting\FileDiff;
use Webmozart\Assert\Assert;
Expand Down Expand Up @@ -57,4 +58,25 @@ public function getTotalChanged(): int
{
return $this->totalChanged;
}

/**
* @return array<class-string<RectorInterface>, int>
*/
public function getRuleApplicationCounts(): array
{
$ruleCounts = [];

foreach ($this->fileDiffs as $fileDiff) {
foreach ($fileDiff->getRectorClasses() as $rectorClass) {
if (! isset($ruleCounts[$rectorClass])) {
$ruleCounts[$rectorClass] = 0;
}

++$ruleCounts[$rectorClass];
}
}

arsort($ruleCounts);
return $ruleCounts;
}
}