Fix bin/publish: copy docs.dist from project root

Fix bin/publish: use correct .env path for rspade_system
Fix bin/publish script: prevent grep exit code 1 from terminating script

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
root
2025-10-21 02:08:33 +00:00
commit f6fac6c4bc
79758 changed files with 10547827 additions and 0 deletions

View File

@@ -0,0 +1,76 @@
<?php
declare(strict_types=1);
/*
* This file is part of PHP CS Fixer.
*
* (c) Fabien Potencier <fabien@symfony.com>
* Dariusz Rumiński <dariusz.ruminski@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace PhpCsFixer\Console\Report\FixReport;
use PhpCsFixer\Console\Application;
use Symfony\Component\Console\Formatter\OutputFormatter;
/**
* @author Kévin Gomez <contact@kevingomez.fr>
*
* @readonly
*
* @internal
*/
final class CheckstyleReporter implements ReporterInterface
{
public function getFormat(): string
{
return 'checkstyle';
}
public function generate(ReportSummary $reportSummary): string
{
if (!\extension_loaded('dom')) {
throw new \RuntimeException('Cannot generate report! `ext-dom` is not available!');
}
$dom = new \DOMDocument('1.0', 'UTF-8');
/** @var \DOMElement $checkstyles */
$checkstyles = $dom->appendChild($dom->createElement('checkstyle'));
$checkstyles->setAttribute('version', Application::getAbout());
foreach ($reportSummary->getChanged() as $filePath => $fixResult) {
/** @var \DOMElement $file */
$file = $checkstyles->appendChild($dom->createElement('file'));
$file->setAttribute('name', $filePath);
foreach ($fixResult['appliedFixers'] as $appliedFixer) {
$error = $this->createError($dom, $appliedFixer);
$file->appendChild($error);
}
}
$dom->formatOutput = true;
$result = $dom->saveXML();
if (false === $result) {
throw new \RuntimeException('Failed to generate XML output');
}
return $reportSummary->isDecoratedOutput() ? OutputFormatter::escape($result) : $result;
}
private function createError(\DOMDocument $dom, string $appliedFixer): \DOMElement
{
$error = $dom->createElement('error');
$error->setAttribute('severity', 'warning');
$error->setAttribute('source', 'PHP-CS-Fixer.'.$appliedFixer);
$error->setAttribute('message', 'Found violation(s) of type: '.$appliedFixer);
return $error;
}
}

View File

@@ -0,0 +1,96 @@
<?php
declare(strict_types=1);
/*
* This file is part of PHP CS Fixer.
*
* (c) Fabien Potencier <fabien@symfony.com>
* Dariusz Rumiński <dariusz.ruminski@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace PhpCsFixer\Console\Report\FixReport;
use PhpCsFixer\Console\Application;
use SebastianBergmann\Diff\Chunk;
use SebastianBergmann\Diff\Diff;
use SebastianBergmann\Diff\Parser;
use Symfony\Component\Console\Formatter\OutputFormatter;
/**
* Generates a report according to gitlabs subset of codeclimate json files.
*
* @author Hans-Christian Otto <c.otto@suora.com>
*
* @see https://github.com/codeclimate/platform/blob/master/spec/analyzers/SPEC.md#data-types
*
* @readonly
*
* @internal
*/
final class GitlabReporter implements ReporterInterface
{
private Parser $diffParser;
public function __construct()
{
$this->diffParser = new Parser();
}
public function getFormat(): string
{
return 'gitlab';
}
/**
* Process changed files array. Returns generated report.
*/
public function generate(ReportSummary $reportSummary): string
{
$about = Application::getAbout();
$report = [];
foreach ($reportSummary->getChanged() as $fileName => $change) {
foreach ($change['appliedFixers'] as $fixerName) {
$report[] = [
'check_name' => 'PHP-CS-Fixer.'.$fixerName,
'description' => 'PHP-CS-Fixer.'.$fixerName.' by '.$about,
'categories' => ['Style'],
'fingerprint' => md5($fileName.$fixerName),
'severity' => 'minor',
'location' => [
'path' => $fileName,
'lines' => self::getLines($this->diffParser->parse($change['diff'])),
],
];
}
}
$jsonString = json_encode($report, \JSON_THROW_ON_ERROR);
return $reportSummary->isDecoratedOutput() ? OutputFormatter::escape($jsonString) : $jsonString;
}
/**
* @param list<Diff> $diffs
*
* @return array{begin: int, end: int}
*/
private static function getLines(array $diffs): array
{
if (isset($diffs[0])) {
$firstDiff = $diffs[0];
$firstChunk = \Closure::bind(static fn (Diff $diff) => array_shift($diff->chunks), null, $firstDiff)($firstDiff);
if ($firstChunk instanceof Chunk) {
return \Closure::bind(static fn (Chunk $chunk): array => ['begin' => $chunk->start, 'end' => $chunk->startRange], null, $firstChunk)($firstChunk);
}
}
return ['begin' => 0, 'end' => 0];
}
}

View File

@@ -0,0 +1,65 @@
<?php
declare(strict_types=1);
/*
* This file is part of PHP CS Fixer.
*
* (c) Fabien Potencier <fabien@symfony.com>
* Dariusz Rumiński <dariusz.ruminski@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace PhpCsFixer\Console\Report\FixReport;
use PhpCsFixer\Console\Application;
use Symfony\Component\Console\Formatter\OutputFormatter;
/**
* @author Boris Gorbylev <ekho@ekho.name>
*
* @readonly
*
* @internal
*/
final class JsonReporter implements ReporterInterface
{
public function getFormat(): string
{
return 'json';
}
public function generate(ReportSummary $reportSummary): string
{
$jsonFiles = [];
foreach ($reportSummary->getChanged() as $file => $fixResult) {
$jsonFile = ['name' => $file];
if ($reportSummary->shouldAddAppliedFixers()) {
$jsonFile['appliedFixers'] = $fixResult['appliedFixers'];
}
if ('' !== $fixResult['diff']) {
$jsonFile['diff'] = $fixResult['diff'];
}
$jsonFiles[] = $jsonFile;
}
$json = [
'about' => Application::getAbout(),
'files' => $jsonFiles,
'time' => [
'total' => round($reportSummary->getTime() / 1_000, 3),
],
'memory' => round($reportSummary->getMemory() / 1_024 / 1_024, 3),
];
$json = json_encode($json, \JSON_THROW_ON_ERROR);
return $reportSummary->isDecoratedOutput() ? OutputFormatter::escape($json) : $json;
}
}

View File

@@ -0,0 +1,150 @@
<?php
declare(strict_types=1);
/*
* This file is part of PHP CS Fixer.
*
* (c) Fabien Potencier <fabien@symfony.com>
* Dariusz Rumiński <dariusz.ruminski@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace PhpCsFixer\Console\Report\FixReport;
use PhpCsFixer\Console\Application;
use PhpCsFixer\Preg;
use Symfony\Component\Console\Formatter\OutputFormatter;
/**
* @author Boris Gorbylev <ekho@ekho.name>
*
* @readonly
*
* @internal
*/
final class JunitReporter implements ReporterInterface
{
public function getFormat(): string
{
return 'junit';
}
public function generate(ReportSummary $reportSummary): string
{
if (!\extension_loaded('dom')) {
throw new \RuntimeException('Cannot generate report! `ext-dom` is not available!');
}
$dom = new \DOMDocument('1.0', 'UTF-8');
$testsuites = $dom->appendChild($dom->createElement('testsuites'));
/** @var \DOMElement $testsuite */
$testsuite = $testsuites->appendChild($dom->createElement('testsuite'));
$testsuite->setAttribute('name', 'PHP CS Fixer');
$properties = $dom->createElement('properties');
$property = $dom->createElement('property');
$property->setAttribute('name', 'about');
$property->setAttribute('value', Application::getAbout());
$properties->appendChild($property);
$testsuite->appendChild($properties);
if (\count($reportSummary->getChanged()) > 0) {
$this->createFailedTestCases($dom, $testsuite, $reportSummary);
} else {
$this->createSuccessTestCase($dom, $testsuite);
}
if ($reportSummary->getTime() > 0) {
$testsuite->setAttribute(
'time',
\sprintf(
'%.3f',
$reportSummary->getTime() / 1_000
)
);
}
$dom->formatOutput = true;
$result = $dom->saveXML();
if (false === $result) {
throw new \RuntimeException('Failed to generate XML output');
}
return $reportSummary->isDecoratedOutput() ? OutputFormatter::escape($result) : $result;
}
private function createSuccessTestCase(\DOMDocument $dom, \DOMElement $testsuite): void
{
$testcase = $dom->createElement('testcase');
$testcase->setAttribute('name', 'All OK');
$testcase->setAttribute('assertions', '1');
$testsuite->appendChild($testcase);
$testsuite->setAttribute('tests', '1');
$testsuite->setAttribute('assertions', '1');
$testsuite->setAttribute('failures', '0');
$testsuite->setAttribute('errors', '0');
}
private function createFailedTestCases(\DOMDocument $dom, \DOMElement $testsuite, ReportSummary $reportSummary): void
{
$assertionsCount = 0;
foreach ($reportSummary->getChanged() as $file => $fixResult) {
$testcase = $this->createFailedTestCase(
$dom,
$file,
$fixResult,
$reportSummary->shouldAddAppliedFixers()
);
$testsuite->appendChild($testcase);
$assertionsCount += (int) $testcase->getAttribute('assertions');
}
$testsuite->setAttribute('tests', (string) \count($reportSummary->getChanged()));
$testsuite->setAttribute('assertions', (string) $assertionsCount);
$testsuite->setAttribute('failures', (string) $assertionsCount);
$testsuite->setAttribute('errors', '0');
}
/**
* @param array{appliedFixers: list<string>, diff: string} $fixResult
*/
private function createFailedTestCase(\DOMDocument $dom, string $file, array $fixResult, bool $shouldAddAppliedFixers): \DOMElement
{
$appliedFixersCount = \count($fixResult['appliedFixers']);
$testName = str_replace('.', '_DOT_', Preg::replace('@\.'.pathinfo($file, \PATHINFO_EXTENSION).'$@', '', $file));
$testcase = $dom->createElement('testcase');
$testcase->setAttribute('name', $testName);
$testcase->setAttribute('file', $file);
$testcase->setAttribute('assertions', (string) $appliedFixersCount);
$failure = $dom->createElement('failure');
$failure->setAttribute('type', 'code_style');
$testcase->appendChild($failure);
if ($shouldAddAppliedFixers) {
$failureContent = "applied fixers:\n---------------\n";
foreach ($fixResult['appliedFixers'] as $appliedFixer) {
$failureContent .= "* {$appliedFixer}\n";
}
} else {
$failureContent = "Wrong code style\n";
}
if ('' !== $fixResult['diff']) {
$failureContent .= "\nDiff:\n---------------\n\n".$fixResult['diff'];
}
$failure->appendChild($dom->createCDATASection(trim($failureContent)));
return $testcase;
}
}

View File

@@ -0,0 +1,103 @@
<?php
declare(strict_types=1);
/*
* This file is part of PHP CS Fixer.
*
* (c) Fabien Potencier <fabien@symfony.com>
* Dariusz Rumiński <dariusz.ruminski@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace PhpCsFixer\Console\Report\FixReport;
/**
* @author Dariusz Rumiński <dariusz.ruminski@gmail.com>
*
* @readonly
*
* @internal
*/
final class ReportSummary
{
/**
* @var array<string, array{appliedFixers: list<string>, diff: string}>
*/
private array $changed;
private int $filesCount;
private int $time;
private int $memory;
private bool $addAppliedFixers;
private bool $isDryRun;
private bool $isDecoratedOutput;
/**
* @param array<string, array{appliedFixers: list<string>, diff: string}> $changed
* @param int $time duration in milliseconds
* @param int $memory memory usage in bytes
*/
public function __construct(
array $changed,
int $filesCount,
int $time,
int $memory,
bool $addAppliedFixers,
bool $isDryRun,
bool $isDecoratedOutput
) {
$this->changed = $changed;
$this->filesCount = $filesCount;
$this->time = $time;
$this->memory = $memory;
$this->addAppliedFixers = $addAppliedFixers;
$this->isDryRun = $isDryRun;
$this->isDecoratedOutput = $isDecoratedOutput;
}
public function isDecoratedOutput(): bool
{
return $this->isDecoratedOutput;
}
public function isDryRun(): bool
{
return $this->isDryRun;
}
/**
* @return array<string, array{appliedFixers: list<string>, diff: string}>
*/
public function getChanged(): array
{
return $this->changed;
}
public function getMemory(): int
{
return $this->memory;
}
public function getTime(): int
{
return $this->time;
}
public function getFilesCount(): int
{
return $this->filesCount;
}
public function shouldAddAppliedFixers(): bool
{
return $this->addAppliedFixers;
}
}

View File

@@ -0,0 +1,90 @@
<?php
declare(strict_types=1);
/*
* This file is part of PHP CS Fixer.
*
* (c) Fabien Potencier <fabien@symfony.com>
* Dariusz Rumiński <dariusz.ruminski@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace PhpCsFixer\Console\Report\FixReport;
use Symfony\Component\Finder\Finder as SymfonyFinder;
/**
* @author Boris Gorbylev <ekho@ekho.name>
*
* @internal
*/
final class ReporterFactory
{
/** @var array<string, ReporterInterface> */
private array $reporters = [];
public function registerBuiltInReporters(): self
{
/** @var null|list<string> $builtInReporters */
static $builtInReporters;
if (null === $builtInReporters) {
$builtInReporters = [];
foreach (SymfonyFinder::create()->files()->name('*Reporter.php')->in(__DIR__) as $file) {
$relativeNamespace = $file->getRelativePath();
$builtInReporters[] = \sprintf(
'%s\%s%s',
__NAMESPACE__,
'' !== $relativeNamespace ? $relativeNamespace.'\\' : '',
$file->getBasename('.php')
);
}
}
foreach ($builtInReporters as $reporterClass) {
$this->registerReporter(new $reporterClass());
}
return $this;
}
/**
* @return $this
*/
public function registerReporter(ReporterInterface $reporter): self
{
$format = $reporter->getFormat();
if (isset($this->reporters[$format])) {
throw new \UnexpectedValueException(\sprintf('Reporter for format "%s" is already registered.', $format));
}
$this->reporters[$format] = $reporter;
return $this;
}
/**
* @return list<string>
*/
public function getFormats(): array
{
$formats = array_keys($this->reporters);
sort($formats);
return $formats;
}
public function getReporter(string $format): ReporterInterface
{
if (!isset($this->reporters[$format])) {
throw new \UnexpectedValueException(\sprintf('Reporter for format "%s" is not registered.', $format));
}
return $this->reporters[$format];
}
}

View File

@@ -0,0 +1,30 @@
<?php
declare(strict_types=1);
/*
* This file is part of PHP CS Fixer.
*
* (c) Fabien Potencier <fabien@symfony.com>
* Dariusz Rumiński <dariusz.ruminski@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace PhpCsFixer\Console\Report\FixReport;
/**
* @author Boris Gorbylev <ekho@ekho.name>
*
* @internal
*/
interface ReporterInterface
{
public function getFormat(): string;
/**
* Process changed files array. Returns generated report.
*/
public function generate(ReportSummary $reportSummary): string;
}

View File

@@ -0,0 +1,104 @@
<?php
declare(strict_types=1);
/*
* This file is part of PHP CS Fixer.
*
* (c) Fabien Potencier <fabien@symfony.com>
* Dariusz Rumiński <dariusz.ruminski@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace PhpCsFixer\Console\Report\FixReport;
use PhpCsFixer\Differ\DiffConsoleFormatter;
/**
* @author Boris Gorbylev <ekho@ekho.name>
*
* @readonly
*
* @internal
*/
final class TextReporter implements ReporterInterface
{
public function getFormat(): string
{
return 'txt';
}
public function generate(ReportSummary $reportSummary): string
{
$output = '';
$identifiedFiles = 0;
foreach ($reportSummary->getChanged() as $file => $fixResult) {
++$identifiedFiles;
$output .= \sprintf('%4d) %s', $identifiedFiles, $file);
if ($reportSummary->shouldAddAppliedFixers()) {
$output .= $this->getAppliedFixers(
$reportSummary->isDecoratedOutput(),
$fixResult['appliedFixers'],
);
}
$output .= $this->getDiff($reportSummary->isDecoratedOutput(), $fixResult['diff']);
$output .= \PHP_EOL;
}
return $output.$this->getFooter(
$reportSummary->getTime(),
$identifiedFiles,
$reportSummary->getFilesCount(),
$reportSummary->getMemory(),
$reportSummary->isDryRun()
);
}
/**
* @param list<string> $appliedFixers
*/
private function getAppliedFixers(bool $isDecoratedOutput, array $appliedFixers): string
{
return \sprintf(
$isDecoratedOutput ? ' (<comment>%s</comment>)' : ' (%s)',
implode(', ', $appliedFixers)
);
}
private function getDiff(bool $isDecoratedOutput, string $diff): string
{
if ('' === $diff) {
return '';
}
$diffFormatter = new DiffConsoleFormatter($isDecoratedOutput, \sprintf(
'<comment> ---------- begin diff ----------</comment>%s%%s%s<comment> ----------- end diff -----------</comment>',
\PHP_EOL,
\PHP_EOL
));
return \PHP_EOL.$diffFormatter->format($diff).\PHP_EOL;
}
private function getFooter(int $time, int $identifiedFiles, int $files, int $memory, bool $isDryRun): string
{
if (0 === $time || 0 === $memory) {
return '';
}
return \PHP_EOL.\sprintf(
'%s %d of %d %s in %.3f seconds, %.2f MB memory used'.\PHP_EOL,
$isDryRun ? 'Found' : 'Fixed',
$identifiedFiles,
$files,
$isDryRun ? 'files that can be fixed' : 'files',
$time / 1_000,
$memory / 1_024 / 1_024
);
}
}

View File

@@ -0,0 +1,141 @@
<?php
declare(strict_types=1);
/*
* This file is part of PHP CS Fixer.
*
* (c) Fabien Potencier <fabien@symfony.com>
* Dariusz Rumiński <dariusz.ruminski@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace PhpCsFixer\Console\Report\FixReport;
use PhpCsFixer\Console\Application;
use Symfony\Component\Console\Formatter\OutputFormatter;
/**
* @author Boris Gorbylev <ekho@ekho.name>
*
* @readonly
*
* @internal
*/
final class XmlReporter implements ReporterInterface
{
public function getFormat(): string
{
return 'xml';
}
public function generate(ReportSummary $reportSummary): string
{
if (!\extension_loaded('dom')) {
throw new \RuntimeException('Cannot generate report! `ext-dom` is not available!');
}
$dom = new \DOMDocument('1.0', 'UTF-8');
// new nodes should be added to this or existing children
$root = $dom->createElement('report');
$dom->appendChild($root);
$root->appendChild($this->createAboutElement($dom, Application::getAbout()));
$filesXML = $dom->createElement('files');
$root->appendChild($filesXML);
$i = 1;
foreach ($reportSummary->getChanged() as $file => $fixResult) {
$fileXML = $dom->createElement('file');
$fileXML->setAttribute('id', (string) $i++);
$fileXML->setAttribute('name', $file);
$filesXML->appendChild($fileXML);
if ($reportSummary->shouldAddAppliedFixers()) {
$fileXML->appendChild(
$this->createAppliedFixersElement($dom, $fixResult['appliedFixers']),
);
}
if ('' !== $fixResult['diff']) {
$fileXML->appendChild($this->createDiffElement($dom, $fixResult['diff']));
}
}
if (0 !== $reportSummary->getTime()) {
$root->appendChild($this->createTimeElement($reportSummary->getTime(), $dom));
}
if (0 !== $reportSummary->getMemory()) {
$root->appendChild($this->createMemoryElement($reportSummary->getMemory(), $dom));
}
$dom->formatOutput = true;
$result = $dom->saveXML();
if (false === $result) {
throw new \RuntimeException('Failed to generate XML output');
}
return $reportSummary->isDecoratedOutput() ? OutputFormatter::escape($result) : $result;
}
/**
* @param list<string> $appliedFixers
*/
private function createAppliedFixersElement(\DOMDocument $dom, array $appliedFixers): \DOMElement
{
$appliedFixersXML = $dom->createElement('applied_fixers');
foreach ($appliedFixers as $appliedFixer) {
$appliedFixerXML = $dom->createElement('applied_fixer');
$appliedFixerXML->setAttribute('name', $appliedFixer);
$appliedFixersXML->appendChild($appliedFixerXML);
}
return $appliedFixersXML;
}
private function createDiffElement(\DOMDocument $dom, string $diff): \DOMElement
{
$diffXML = $dom->createElement('diff');
$diffXML->appendChild($dom->createCDATASection($diff));
return $diffXML;
}
private function createTimeElement(float $time, \DOMDocument $dom): \DOMElement
{
$time = round($time / 1_000, 3);
$timeXML = $dom->createElement('time');
$timeXML->setAttribute('unit', 's');
$timeTotalXML = $dom->createElement('total');
$timeTotalXML->setAttribute('value', (string) $time);
$timeXML->appendChild($timeTotalXML);
return $timeXML;
}
private function createMemoryElement(float $memory, \DOMDocument $dom): \DOMElement
{
$memory = round($memory / 1_024 / 1_024, 3);
$memoryXML = $dom->createElement('memory');
$memoryXML->setAttribute('value', (string) $memory);
$memoryXML->setAttribute('unit', 'MB');
return $memoryXML;
}
private function createAboutElement(\DOMDocument $dom, string $about): \DOMElement
{
$xml = $dom->createElement('about');
$xml->setAttribute('value', $about);
return $xml;
}
}

View File

@@ -0,0 +1,52 @@
<?php
declare(strict_types=1);
/*
* This file is part of PHP CS Fixer.
*
* (c) Fabien Potencier <fabien@symfony.com>
* Dariusz Rumiński <dariusz.ruminski@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace PhpCsFixer\Console\Report\ListSetsReport;
use PhpCsFixer\RuleSet\RuleSetDescriptionInterface;
/**
* @author Dariusz Rumiński <dariusz.ruminski@gmail.com>
*
* @readonly
*
* @internal
*/
final class JsonReporter implements ReporterInterface
{
public function getFormat(): string
{
return 'json';
}
public function generate(ReportSummary $reportSummary): string
{
$sets = $reportSummary->getSets();
usort($sets, static fn (RuleSetDescriptionInterface $a, RuleSetDescriptionInterface $b): int => $a->getName() <=> $b->getName());
$json = ['sets' => []];
foreach ($sets as $set) {
$setName = $set->getName();
$json['sets'][$setName] = [
'description' => $set->getDescription(),
'isRisky' => $set->isRisky(),
'name' => $setName,
];
}
return json_encode($json, \JSON_THROW_ON_ERROR | \JSON_PRETTY_PRINT);
}
}

View File

@@ -0,0 +1,48 @@
<?php
declare(strict_types=1);
/*
* This file is part of PHP CS Fixer.
*
* (c) Fabien Potencier <fabien@symfony.com>
* Dariusz Rumiński <dariusz.ruminski@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace PhpCsFixer\Console\Report\ListSetsReport;
use PhpCsFixer\RuleSet\RuleSetDescriptionInterface;
/**
* @author Dariusz Rumiński <dariusz.ruminski@gmail.com>
*
* @readonly
*
* @internal
*/
final class ReportSummary
{
/**
* @var list<RuleSetDescriptionInterface>
*/
private array $sets;
/**
* @param list<RuleSetDescriptionInterface> $sets
*/
public function __construct(array $sets)
{
$this->sets = $sets;
}
/**
* @return list<RuleSetDescriptionInterface>
*/
public function getSets(): array
{
return $this->sets;
}
}

View File

@@ -0,0 +1,89 @@
<?php
declare(strict_types=1);
/*
* This file is part of PHP CS Fixer.
*
* (c) Fabien Potencier <fabien@symfony.com>
* Dariusz Rumiński <dariusz.ruminski@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace PhpCsFixer\Console\Report\ListSetsReport;
use Symfony\Component\Finder\Finder as SymfonyFinder;
/**
* @author Boris Gorbylev <ekho@ekho.name>
*
* @internal
*/
final class ReporterFactory
{
/**
* @var array<string, ReporterInterface>
*/
private array $reporters = [];
public function registerBuiltInReporters(): self
{
/** @var null|list<string> $builtInReporters */
static $builtInReporters;
if (null === $builtInReporters) {
$builtInReporters = [];
foreach (SymfonyFinder::create()->files()->name('*Reporter.php')->in(__DIR__) as $file) {
$relativeNamespace = $file->getRelativePath();
$builtInReporters[] = \sprintf(
'%s\%s%s',
__NAMESPACE__,
'' !== $relativeNamespace ? $relativeNamespace.'\\' : '',
$file->getBasename('.php')
);
}
}
foreach ($builtInReporters as $reporterClass) {
$this->registerReporter(new $reporterClass());
}
return $this;
}
public function registerReporter(ReporterInterface $reporter): self
{
$format = $reporter->getFormat();
if (isset($this->reporters[$format])) {
throw new \UnexpectedValueException(\sprintf('Reporter for format "%s" is already registered.', $format));
}
$this->reporters[$format] = $reporter;
return $this;
}
/**
* @return list<string>
*/
public function getFormats(): array
{
$formats = array_keys($this->reporters);
sort($formats);
return $formats;
}
public function getReporter(string $format): ReporterInterface
{
if (!isset($this->reporters[$format])) {
throw new \UnexpectedValueException(\sprintf('Reporter for format "%s" is not registered.', $format));
}
return $this->reporters[$format];
}
}

View File

@@ -0,0 +1,30 @@
<?php
declare(strict_types=1);
/*
* This file is part of PHP CS Fixer.
*
* (c) Fabien Potencier <fabien@symfony.com>
* Dariusz Rumiński <dariusz.ruminski@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace PhpCsFixer\Console\Report\ListSetsReport;
/**
* @author Dariusz Rumiński <dariusz.ruminski@gmail.com>
*
* @internal
*/
interface ReporterInterface
{
public function getFormat(): string;
/**
* Process changed files array. Returns generated report.
*/
public function generate(ReportSummary $reportSummary): string;
}

View File

@@ -0,0 +1,51 @@
<?php
declare(strict_types=1);
/*
* This file is part of PHP CS Fixer.
*
* (c) Fabien Potencier <fabien@symfony.com>
* Dariusz Rumiński <dariusz.ruminski@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace PhpCsFixer\Console\Report\ListSetsReport;
use PhpCsFixer\RuleSet\RuleSetDescriptionInterface;
/**
* @author Dariusz Rumiński <dariusz.ruminski@gmail.com>
*
* @readonly
*
* @internal
*/
final class TextReporter implements ReporterInterface
{
public function getFormat(): string
{
return 'txt';
}
public function generate(ReportSummary $reportSummary): string
{
$sets = $reportSummary->getSets();
usort($sets, static fn (RuleSetDescriptionInterface $a, RuleSetDescriptionInterface $b): int => $a->getName() <=> $b->getName());
$output = '';
foreach ($sets as $i => $set) {
$output .= \sprintf('%2d) %s', $i + 1, $set->getName()).\PHP_EOL.' '.$set->getDescription().\PHP_EOL;
if ($set->isRisky()) {
$output .= ' Set contains risky rules.'.\PHP_EOL;
}
}
return $output;
}
}