2019-10-13 05:59:52 +00:00
|
|
|
<?php
|
|
|
|
|
|
|
|
declare(strict_types=1);
|
2017-10-22 14:31:29 +00:00
|
|
|
|
2020-03-19 00:07:07 +00:00
|
|
|
namespace Rector\ChangesReporting\Output;
|
2017-10-22 14:31:29 +00:00
|
|
|
|
2019-08-10 07:28:27 +00:00
|
|
|
use Nette\Utils\Strings;
|
2021-04-10 16:22:25 +00:00
|
|
|
use Rector\ChangesReporting\Annotation\RectorsChangelogResolver;
|
2020-03-19 00:07:07 +00:00
|
|
|
use Rector\ChangesReporting\Application\ErrorAndDiffCollector;
|
|
|
|
use Rector\ChangesReporting\Contract\Output\OutputFormatterInterface;
|
2020-02-06 21:48:18 +00:00
|
|
|
use Rector\Core\Configuration\Configuration;
|
|
|
|
use Rector\Core\Configuration\Option;
|
2020-05-03 19:17:42 +00:00
|
|
|
use Rector\Core\ValueObject\Application\RectorError;
|
2020-02-06 21:48:18 +00:00
|
|
|
use Rector\Core\ValueObject\Reporting\FileDiff;
|
2019-01-02 13:22:25 +00:00
|
|
|
use Symfony\Component\Console\Style\SymfonyStyle;
|
2017-10-22 14:31:29 +00:00
|
|
|
|
2019-05-25 16:36:53 +00:00
|
|
|
final class ConsoleOutputFormatter implements OutputFormatterInterface
|
2017-10-22 14:31:29 +00:00
|
|
|
{
|
2019-05-25 16:36:53 +00:00
|
|
|
/**
|
|
|
|
* @var string
|
|
|
|
*/
|
|
|
|
public const NAME = 'console';
|
|
|
|
|
2020-09-23 09:16:40 +00:00
|
|
|
/**
|
|
|
|
* @var string
|
2020-10-29 18:04:33 +00:00
|
|
|
* @see https://regex101.com/r/q8I66g/1
|
2020-09-23 09:16:40 +00:00
|
|
|
*/
|
|
|
|
private const ON_LINE_REGEX = '# on line #';
|
|
|
|
|
2017-10-22 14:31:29 +00:00
|
|
|
/**
|
2018-11-02 17:27:00 +00:00
|
|
|
* @var SymfonyStyle
|
2017-10-22 14:31:29 +00:00
|
|
|
*/
|
2018-11-02 17:27:00 +00:00
|
|
|
private $symfonyStyle;
|
2017-10-22 14:31:29 +00:00
|
|
|
|
2019-08-10 07:28:27 +00:00
|
|
|
/**
|
2021-02-19 12:01:23 +00:00
|
|
|
* @var Configuration
|
2019-08-10 07:28:27 +00:00
|
|
|
*/
|
2021-02-19 12:01:23 +00:00
|
|
|
private $configuration;
|
2019-08-10 07:28:27 +00:00
|
|
|
|
2021-04-10 14:54:24 +00:00
|
|
|
/**
|
2021-04-10 16:22:25 +00:00
|
|
|
* @var RectorsChangelogResolver
|
2021-04-10 14:54:24 +00:00
|
|
|
*/
|
2021-04-10 16:22:25 +00:00
|
|
|
private $rectorsChangelogResolver;
|
2021-04-10 14:54:24 +00:00
|
|
|
|
2020-01-08 20:05:12 +00:00
|
|
|
public function __construct(
|
2020-07-26 07:49:22 +00:00
|
|
|
Configuration $configuration,
|
2021-04-10 14:54:24 +00:00
|
|
|
SymfonyStyle $symfonyStyle,
|
2021-04-10 16:22:25 +00:00
|
|
|
RectorsChangelogResolver $rectorsChangelogResolver
|
2020-01-08 20:05:12 +00:00
|
|
|
) {
|
2018-11-02 17:27:00 +00:00
|
|
|
$this->symfonyStyle = $symfonyStyle;
|
2020-01-08 20:05:12 +00:00
|
|
|
$this->configuration = $configuration;
|
2021-04-10 16:22:25 +00:00
|
|
|
$this->rectorsChangelogResolver = $rectorsChangelogResolver;
|
2017-10-22 14:31:29 +00:00
|
|
|
}
|
|
|
|
|
2020-01-08 20:05:12 +00:00
|
|
|
public function report(ErrorAndDiffCollector $errorAndDiffCollector): void
|
2019-05-28 14:28:46 +00:00
|
|
|
{
|
2020-01-17 13:54:37 +00:00
|
|
|
if ($this->configuration->getOutputFile()) {
|
2020-07-05 23:57:19 +00:00
|
|
|
$message = sprintf(
|
2020-01-17 09:02:46 +00:00
|
|
|
'Option "--%s" can be used only with "--%s %s"',
|
|
|
|
Option::OPTION_OUTPUT_FILE,
|
|
|
|
Option::OPTION_OUTPUT_FORMAT,
|
|
|
|
'json'
|
2020-07-05 23:57:19 +00:00
|
|
|
);
|
|
|
|
$this->symfonyStyle->error($message);
|
2020-01-17 09:02:46 +00:00
|
|
|
}
|
|
|
|
|
2021-01-29 20:12:09 +00:00
|
|
|
if ($this->configuration->shouldShowDiffs()) {
|
|
|
|
$this->reportFileDiffs($errorAndDiffCollector->getFileDiffs());
|
|
|
|
}
|
|
|
|
|
2019-05-28 14:28:46 +00:00
|
|
|
$this->reportErrors($errorAndDiffCollector->getErrors());
|
2019-08-06 07:37:31 +00:00
|
|
|
$this->reportRemovedFilesAndNodes($errorAndDiffCollector);
|
2019-05-28 14:47:55 +00:00
|
|
|
|
|
|
|
if ($errorAndDiffCollector->getErrors() !== []) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-01-29 20:12:09 +00:00
|
|
|
$message = $this->createSuccessMessage($errorAndDiffCollector);
|
2020-01-08 14:55:19 +00:00
|
|
|
$this->symfonyStyle->success($message);
|
2019-05-28 14:28:46 +00:00
|
|
|
}
|
|
|
|
|
2019-05-25 16:36:53 +00:00
|
|
|
public function getName(): string
|
|
|
|
{
|
|
|
|
return self::NAME;
|
|
|
|
}
|
|
|
|
|
2018-01-02 06:03:11 +00:00
|
|
|
/**
|
2018-02-08 15:51:16 +00:00
|
|
|
* @param FileDiff[] $fileDiffs
|
2018-01-02 06:03:11 +00:00
|
|
|
*/
|
2019-05-28 14:28:46 +00:00
|
|
|
private function reportFileDiffs(array $fileDiffs): void
|
2018-01-02 06:03:11 +00:00
|
|
|
{
|
2018-02-08 15:51:16 +00:00
|
|
|
if (count($fileDiffs) <= 0) {
|
2018-01-06 23:09:22 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-12-07 17:54:24 +00:00
|
|
|
// normalize
|
|
|
|
ksort($fileDiffs);
|
2020-07-05 23:57:19 +00:00
|
|
|
$message = sprintf('%d file%s with changes', count($fileDiffs), count($fileDiffs) === 1 ? '' : 's');
|
2018-12-07 17:54:24 +00:00
|
|
|
|
2020-07-05 23:57:19 +00:00
|
|
|
$this->symfonyStyle->title($message);
|
2018-01-02 06:03:11 +00:00
|
|
|
|
2018-01-06 20:10:35 +00:00
|
|
|
$i = 0;
|
2018-02-08 15:51:16 +00:00
|
|
|
foreach ($fileDiffs as $fileDiff) {
|
2019-05-28 20:38:21 +00:00
|
|
|
$relativeFilePath = $fileDiff->getRelativeFilePath();
|
2020-07-05 23:57:19 +00:00
|
|
|
$message = sprintf('<options=bold>%d) %s</>', ++$i, $relativeFilePath);
|
2019-05-28 16:28:20 +00:00
|
|
|
|
2020-07-05 23:57:19 +00:00
|
|
|
$this->symfonyStyle->writeln($message);
|
2018-11-02 17:27:00 +00:00
|
|
|
$this->symfonyStyle->newLine();
|
2019-05-28 14:18:05 +00:00
|
|
|
$this->symfonyStyle->writeln($fileDiff->getDiffConsoleFormatted());
|
2018-11-02 17:27:00 +00:00
|
|
|
$this->symfonyStyle->newLine();
|
2018-11-05 01:27:48 +00:00
|
|
|
|
2021-04-10 16:22:25 +00:00
|
|
|
$rectorsChangelogsLines = $this->createRectorChangelogLines($fileDiff);
|
|
|
|
|
2020-03-19 00:07:07 +00:00
|
|
|
if ($fileDiff->getRectorChanges() !== []) {
|
2020-10-10 17:42:43 +00:00
|
|
|
$this->symfonyStyle->writeln('<options=underscore>Applied rules:</>');
|
2018-11-05 01:27:48 +00:00
|
|
|
$this->symfonyStyle->newLine();
|
2021-04-10 16:22:25 +00:00
|
|
|
$this->symfonyStyle->listing($rectorsChangelogsLines);
|
2018-11-05 01:27:48 +00:00
|
|
|
$this->symfonyStyle->newLine();
|
|
|
|
}
|
2018-01-02 06:03:11 +00:00
|
|
|
}
|
|
|
|
}
|
2018-09-17 10:38:11 +00:00
|
|
|
|
|
|
|
/**
|
2020-05-03 19:17:42 +00:00
|
|
|
* @param RectorError[] $errors
|
2018-09-17 10:38:11 +00:00
|
|
|
*/
|
2019-05-28 14:28:46 +00:00
|
|
|
private function reportErrors(array $errors): void
|
2018-09-17 10:38:11 +00:00
|
|
|
{
|
|
|
|
foreach ($errors as $error) {
|
2020-08-11 10:59:04 +00:00
|
|
|
$errorMessage = $error->getMessage();
|
|
|
|
$errorMessage = $this->normalizePathsToRelativeWithLine($errorMessage);
|
|
|
|
|
2018-09-17 10:38:11 +00:00
|
|
|
$message = sprintf(
|
2018-11-04 23:36:12 +00:00
|
|
|
'Could not process "%s" file%s, due to: %s"%s".',
|
2020-11-16 17:50:38 +00:00
|
|
|
$error->getRelativeFilePath(),
|
2018-11-04 23:36:12 +00:00
|
|
|
$error->getRectorClass() ? ' by "' . $error->getRectorClass() . '"' : '',
|
2018-09-17 10:38:11 +00:00
|
|
|
PHP_EOL,
|
2020-08-11 10:59:04 +00:00
|
|
|
$errorMessage
|
2018-09-17 10:38:11 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
if ($error->getLine()) {
|
|
|
|
$message .= ' On line: ' . $error->getLine();
|
|
|
|
}
|
|
|
|
|
2018-11-02 17:27:00 +00:00
|
|
|
$this->symfonyStyle->error($message);
|
2018-09-17 10:38:11 +00:00
|
|
|
}
|
|
|
|
}
|
2019-08-06 07:37:31 +00:00
|
|
|
|
|
|
|
private function reportRemovedFilesAndNodes(ErrorAndDiffCollector $errorAndDiffCollector): void
|
|
|
|
{
|
2020-10-31 12:59:40 +00:00
|
|
|
if ($errorAndDiffCollector->getAddFilesCount() !== 0) {
|
|
|
|
$message = sprintf('%d files were added', $errorAndDiffCollector->getAddFilesCount());
|
|
|
|
$this->symfonyStyle->note($message);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($errorAndDiffCollector->getRemovedFilesCount() !== 0) {
|
|
|
|
$message = sprintf('%d files were removed', $errorAndDiffCollector->getRemovedFilesCount());
|
2020-07-05 23:57:19 +00:00
|
|
|
$this->symfonyStyle->note($message);
|
2019-08-06 07:37:31 +00:00
|
|
|
}
|
|
|
|
|
2019-08-10 07:28:27 +00:00
|
|
|
$this->reportRemovedNodes($errorAndDiffCollector);
|
|
|
|
}
|
|
|
|
|
2020-08-11 10:59:04 +00:00
|
|
|
private function normalizePathsToRelativeWithLine(string $errorMessage): string
|
|
|
|
{
|
2021-01-24 20:12:02 +00:00
|
|
|
$regex = '#' . preg_quote(getcwd(), '#') . '/#';
|
|
|
|
$errorMessage = Strings::replace($errorMessage, $regex, '');
|
2021-04-11 11:14:46 +00:00
|
|
|
return Strings::replace($errorMessage, self::ON_LINE_REGEX, ':');
|
2020-08-11 10:59:04 +00:00
|
|
|
}
|
|
|
|
|
2019-08-10 07:28:27 +00:00
|
|
|
private function reportRemovedNodes(ErrorAndDiffCollector $errorAndDiffCollector): void
|
|
|
|
{
|
|
|
|
if ($errorAndDiffCollector->getRemovedNodeCount() === 0) {
|
|
|
|
return;
|
|
|
|
}
|
2020-10-31 12:59:40 +00:00
|
|
|
|
2020-07-05 23:57:19 +00:00
|
|
|
$message = sprintf('%d nodes were removed', $errorAndDiffCollector->getRemovedNodeCount());
|
|
|
|
$this->symfonyStyle->warning($message);
|
2019-08-10 07:28:27 +00:00
|
|
|
}
|
2021-01-29 20:12:09 +00:00
|
|
|
|
|
|
|
private function createSuccessMessage(ErrorAndDiffCollector $errorAndDiffCollector): string
|
|
|
|
{
|
|
|
|
$changeCount = $errorAndDiffCollector->getFileDiffsCount()
|
|
|
|
+ $errorAndDiffCollector->getRemovedAndAddedFilesCount();
|
|
|
|
|
|
|
|
if ($changeCount === 0) {
|
|
|
|
return 'Rector is done!';
|
|
|
|
}
|
|
|
|
|
|
|
|
return sprintf(
|
2021-04-11 11:14:46 +00:00
|
|
|
'%d file%s %s by Rector',
|
2021-01-29 20:12:09 +00:00
|
|
|
$changeCount,
|
|
|
|
$changeCount > 1 ? 's' : '',
|
|
|
|
$this->configuration->isDryRun() ? 'would have changed (dry-run)' : ($changeCount === 1 ? 'has' : 'have') . ' been changed'
|
|
|
|
);
|
|
|
|
}
|
2021-04-10 16:22:25 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @return string[]
|
|
|
|
*/
|
|
|
|
private function createRectorChangelogLines(FileDiff $fileDiff): array
|
|
|
|
{
|
|
|
|
$rectorsChangelogs = $this->rectorsChangelogResolver->resolveIncludingMissing($fileDiff->getRectorClasses());
|
|
|
|
|
|
|
|
$rectorsChangelogsLines = [];
|
|
|
|
foreach ($rectorsChangelogs as $rectorClass => $changelog) {
|
|
|
|
$rectorsChangelogsLines[] = $changelog === null ? $rectorClass : $rectorClass . ' ' . $changelog;
|
|
|
|
}
|
|
|
|
|
|
|
|
return $rectorsChangelogsLines;
|
|
|
|
}
|
2017-10-22 14:31:29 +00:00
|
|
|
}
|