Skip to content

Commit 54eb0bc

Browse files
authored
Remove symfony/console, migrate console layer to entropy/entropy (#27)
* Remove symfony/console, migrate console layer to entropy/entropy ECS no longer depends on symfony/console. The console layer runs on entropy/entropy: commands implement Entropy's CommandInterface (run() params are the CLI contract), and a new EasyCodingStandardStyle wraps entropy's OutputPrinter/ProgressBar. - commands (Check/Worker/ListCheckers) implement entropy CommandInterface; delete AbstractCheckCommand and the Symfony console application - replace SymfonyStyle with EasyCodingStandardStyle over entropy output; delete SymfonyStyleFactory - ConfigurationFactory builds Configuration from plain args instead of InputInterface; container resolves config from raw argv - ParallelFileProcessor passes plain option values to the decoupled WorkerCommandLineFactory (symplify/easy-parallel dev-main) - bin/ecs.php parses argv manually (xdebug, --version via Composer InstalledVersions, decoration-flag stripping, -c to --config) - drop dead Option CLI-name constants - composer: drop symfony/console from require, satisfy php-cs-fixer's constraint via replace; require easy-parallel dev-main * Add tests guarding the symfony/console to entropy migration - CommandRegistrationTest: commands are discovered and wired into Entropy's CommandRegistry (check/worker/list-checkers registered, check is default, worker is hidden) - EasyCodingStandardStyleTest: Symfony console tags are translated into Entropy's OutputColorizer vocabulary (comment/info/options/closing)
1 parent 967772b commit 54eb0bc

22 files changed

Lines changed: 535 additions & 497 deletions

bin/ecs.php

Lines changed: 81 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,14 @@
33
declare(strict_types=1);
44

55
// decoupled in own "*.php" file, so ECS, Rector and PHPStan works out of the box here
6+
use Composer\InstalledVersions;
7+
use Composer\XdebugHandler\XdebugHandler;
8+
use Entropy\Console\ConsoleApplication;
9+
use Entropy\Console\Output\OutputColorizer;
10+
use Entropy\Console\Output\OutputPrinter;
611
use PHP_CodeSniffer\Util\Tokens;
7-
use Symfony\Component\Console\Command\Command;
8-
use Symfony\Component\Console\Input\ArgvInput;
9-
use Symplify\EasyCodingStandard\Console\EasyCodingStandardConsoleApplication;
10-
use Symplify\EasyCodingStandard\Console\Style\SymfonyStyleFactory;
12+
use Symplify\EasyCodingStandard\Application\Version\StaticVersionResolver;
13+
use Symplify\EasyCodingStandard\Console\ExitCode;
1114
use Symplify\EasyCodingStandard\DependencyInjection\EasyCodingStandardContainerFactory;
1215
use Symplify\EasyCodingStandard\DependencyInjection\ServiceContainerFactory;
1316

@@ -142,21 +145,85 @@ public function loadIfNotLoadedYet(string $file): void
142145
}
143146
}
144147

148+
$rawArgv = $_SERVER['argv'] ?? [];
149+
150+
// @fixes https://github.com/rectorphp/rector/issues/2205
151+
$isXdebugAllowed = in_array('--xdebug', $rawArgv, true);
152+
if (! $isXdebugAllowed && ! defined('PHPUNIT_COMPOSER_INSTALL')) {
153+
$xdebugHandler = new XdebugHandler('ecs');
154+
$xdebugHandler->check();
155+
unset($xdebugHandler);
156+
}
157+
145158
try {
146-
$input = new ArgvInput();
147159
$ecsContainerFactory = new EasyCodingStandardContainerFactory();
148-
$container = $ecsContainerFactory->createFromFromInput($input);
160+
$container = $ecsContainerFactory->createFromArgv($rawArgv);
149161
} catch (Throwable $throwable) {
150-
$symfonyStyleFactory = new SymfonyStyleFactory();
151-
$symfonyStyle = $symfonyStyleFactory->create();
162+
$outputPrinter = new OutputPrinter(new OutputColorizer());
163+
$outputPrinter->error($throwable->getMessage());
164+
$outputPrinter->writeln($throwable->getTraceAsString());
165+
exit(ExitCode::FAILURE);
166+
}
152167

153-
$symfonyStyle->error($throwable->getMessage());
154-
$symfonyStyle->writeln($throwable->getTraceAsString());
155-
exit(Command::FAILURE);
168+
// print version and exit
169+
if (in_array('--version', $rawArgv, true) || in_array('-V', $rawArgv, true)) {
170+
echo sprintf('EasyCodingStandard %s', StaticVersionResolver::PACKAGE_VERSION) . PHP_EOL;
171+
echo sprintf('+ PHP_CodeSniffer %s', InstalledVersions::getPrettyVersion('squizlabs/php_codesniffer')) . PHP_EOL;
172+
echo sprintf('+ PHP-CS-Fixer %s', InstalledVersions::getPrettyVersion('friendsofphp/php-cs-fixer')) . PHP_EOL;
173+
exit(ExitCode::SUCCESS);
156174
}
157175

158-
/** @var EasyCodingStandardConsoleApplication $application */
159-
$application = $container->make(EasyCodingStandardConsoleApplication::class);
176+
/** @var ConsoleApplication $application */
177+
$application = $container->make(ConsoleApplication::class);
160178

161-
$statusCode = $application->run();
179+
$statusCode = $application->run(ecs_normalize_argv($rawArgv));
162180
exit($statusCode);
181+
182+
/**
183+
* Strip global/decoration flags Symfony Console handled implicitly, and normalize
184+
* the "-c" config shortcut to "--config", so the Entropy input parser does not
185+
* treat them as unknown command options.
186+
*
187+
* @param string[] $argv
188+
* @return string[]
189+
*/
190+
function ecs_normalize_argv(array $argv): array
191+
{
192+
$decorationFlags = [
193+
'--ansi',
194+
'--no-ansi',
195+
'--quiet',
196+
'-q',
197+
'--no-interaction',
198+
'-n',
199+
'-v',
200+
'-vv',
201+
'-vvv',
202+
'--xdebug',
203+
];
204+
205+
if (in_array('--no-ansi', $argv, true)) {
206+
putenv('NO_COLOR=1');
207+
}
208+
209+
$normalized = [];
210+
foreach ($argv as $arg) {
211+
if (in_array($arg, $decorationFlags, true)) {
212+
continue;
213+
}
214+
215+
if ($arg === '-c') {
216+
$normalized[] = '--config';
217+
continue;
218+
}
219+
220+
if (str_starts_with($arg, '-c=')) {
221+
$normalized[] = '--config=' . substr($arg, 3);
222+
continue;
223+
}
224+
225+
$normalized[] = $arg;
226+
}
227+
228+
return $normalized;
229+
}

composer.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,8 @@
2020
"nette/utils": "^4.1",
2121
"sebastian/diff": "^9.0",
2222
"squizlabs/php_codesniffer": "^4.0.1",
23-
"symfony/console": "^6.4.24",
2423
"symfony/finder": "^7.4",
25-
"symplify/easy-parallel": "^12.0",
24+
"symplify/easy-parallel": "dev-main",
2625
"webmozart/assert": "^2.4"
2726
},
2827
"require-dev": {
@@ -82,6 +81,7 @@
8281
"fix-cs": "bin/ecs check --fix --ansi"
8382
},
8483
"replace": {
84+
"symfony/console": "*",
8585
"symfony/event-dispatcher": "7.*",
8686
"symfony/process": "7.*",
8787
"symfony/stopwatch": "7.*"

src/Application/EasyCodingStandardApplication.php

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@
55
namespace Symplify\EasyCodingStandard\Application;
66

77
use ParseError;
8-
use Symfony\Component\Console\Input\InputInterface;
9-
use Symfony\Component\Console\Style\SymfonyStyle;
108
use Symplify\EasyCodingStandard\Caching\ChangedFilesDetector;
119
use Symplify\EasyCodingStandard\Console\Style\EasyCodingStandardStyle;
1210
use Symplify\EasyCodingStandard\DependencyInjection\SimpleParameterProvider;
@@ -38,15 +36,14 @@ public function __construct(
3836
private ScheduleFactory $scheduleFactory,
3937
private ParallelFileProcessor $parallelFileProcessor,
4038
private CpuCoreCountProvider $cpuCoreCountProvider,
41-
private SymfonyStyle $symfonyStyle,
4239
private ParametersMerger $parametersMerger
4340
) {
4441
}
4542

4643
/**
4744
* @return array{coding_standard_errors?: CodingStandardError[], file_diffs?: FileDiff[], system_errors?: SystemError[]|string[], system_errors_count?: int}
4845
*/
49-
public function run(Configuration $configuration, InputInterface $input): array
46+
public function run(Configuration $configuration): array
5047
{
5148
// 1. find files in sources
5249
$filePaths = $this->sourceFinder->find($configuration->getSources());
@@ -87,11 +84,11 @@ public function run(Configuration $configuration, InputInterface $input): array
8784

8885
if (! $isProgressBarStarted) {
8986
$fileCount = count($filePaths);
90-
$this->symfonyStyle->progressStart($fileCount);
87+
$this->easyCodingStandardStyle->progressStart($fileCount);
9188
$isProgressBarStarted = true;
9289
}
9390

94-
$this->symfonyStyle->progressAdvance($stepCount);
91+
$this->easyCodingStandardStyle->progressAdvance($stepCount);
9592
// running in parallel here → nothing else to do
9693
};
9794

@@ -106,7 +103,7 @@ public function run(Configuration $configuration, InputInterface $input): array
106103
$mainScript,
107104
$postFileCallback,
108105
$configuration->getConfig(),
109-
$input
106+
$configuration
110107
);
111108
}
112109

src/Configuration/ConfigInitializer.php

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@
55
namespace Symplify\EasyCodingStandard\Configuration;
66

77
use Nette\Utils\FileSystem;
8-
use Symfony\Component\Console\Style\SymfonyStyle;
98
use Symplify\EasyCodingStandard\Application\FileProcessorCollector;
9+
use Symplify\EasyCodingStandard\Console\Style\EasyCodingStandardStyle;
1010

1111
final readonly class ConfigInitializer
1212
{
1313
public function __construct(
1414
private FileProcessorCollector $fileProcessorCollector,
15-
private SymfonyStyle $symfonyStyle,
15+
private EasyCodingStandardStyle $easyCodingStandardStyle,
1616
private InitPathsResolver $initPathsResolver,
1717
private \Symfony\Component\Filesystem\Filesystem $filesystem,
1818
) {
@@ -30,13 +30,16 @@ public function createConfig(string $projectDirectory): void
3030

3131
// config already exists, nothing to add
3232
if ($doesConfigExist) {
33-
$this->symfonyStyle->warning(
33+
$this->easyCodingStandardStyle->warning(
3434
'We found ecs.php config, but no rules in it. Register some rules or sets there first'
3535
);
3636
return;
3737
}
3838

39-
$response = $this->symfonyStyle->ask('No "ecs.php" config found. Should we generate it for you?', 'yes');
39+
$response = $this->easyCodingStandardStyle->ask(
40+
'No "ecs.php" config found. Should we generate it for you?',
41+
'yes'
42+
);
4043

4144
// be tolerant about input
4245
if (! in_array($response, ['yes', 'YES', 'y', 'Y'], true)) {
@@ -52,7 +55,9 @@ public function createConfig(string $projectDirectory): void
5255
// create the ecs.php file
5356
FileSystem::write(getcwd() . '/ecs.php', $templateFileContents, null);
5457

55-
$this->symfonyStyle->success('The ecs.php config was generated! Re-run the command to tidy your code');
58+
$this->easyCodingStandardStyle->success(
59+
'The ecs.php config was generated! Re-run the command to tidy your code'
60+
);
5661
}
5762

5863
private function fillPaths(string $projectDirectory, string $templateFileContents): string

src/Configuration/ConfigurationFactory.php

Lines changed: 25 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
namespace Symplify\EasyCodingStandard\Configuration;
66

7-
use Symfony\Component\Console\Input\InputInterface;
87
use Symplify\EasyCodingStandard\Console\Output\OutputFormatterCollector;
98
use Symplify\EasyCodingStandard\DependencyInjection\SimpleParameterProvider;
109
use Symplify\EasyCodingStandard\Exception\Configuration\SourceNotFoundException;
@@ -20,33 +19,32 @@ public function __construct(
2019

2120
/**
2221
* Needs to run in the start of the life cycle, since the rest of workflow uses it.
22+
*
23+
* @param string[] $paths
2324
*/
24-
public function createFromInput(InputInterface $input): Configuration
25-
{
26-
$paths = $this->resolvePaths($input);
27-
28-
$isFixer = (bool) $input->getOption(Option::FIX);
29-
$shouldClearCache = (bool) $input->getOption(Option::CLEAR_CACHE);
30-
$showProgressBar = $this->canShowProgressBar($input);
31-
$showErrorTable = ! (bool) $input->getOption(Option::NO_ERROR_TABLE);
32-
$showDiffs = ! (bool) $input->getOption(Option::NO_DIFFS);
33-
$parallelPort = (string) $input->getOption(Option::PARALLEL_PORT);
34-
$parallelIdentifier = (string) $input->getOption(Option::PARALLEL_IDENTIFIER);
35-
36-
$outputFormat = (string) $input->getOption(Option::OUTPUT_FORMAT);
37-
38-
/** @var string|null $memoryLimit */
39-
$memoryLimit = $input->getOption(Option::MEMORY_LIMIT);
25+
public function create(
26+
array $paths,
27+
bool $isFixer,
28+
bool $shouldClearCache,
29+
bool $noProgressBar,
30+
bool $noErrorTable,
31+
bool $noDiffs,
32+
string $outputFormat,
33+
?string $config,
34+
string $parallelPort,
35+
string $parallelIdentifier,
36+
?string $memoryLimit,
37+
bool $debug,
38+
): Configuration {
39+
$paths = $this->resolvePaths($paths);
40+
41+
$showProgressBar = $this->canShowProgressBar($debug, $outputFormat, $noProgressBar);
42+
$showErrorTable = ! $noErrorTable;
43+
$showDiffs = ! $noDiffs;
4044

4145
$isParallel = SimpleParameterProvider::getBoolParameter(Option::PARALLEL);
42-
4346
$isReportingWithRealPath = SimpleParameterProvider::getBoolParameter(Option::REPORTING_REALPATH);
4447

45-
$config = $input->getOption(Option::CONFIG);
46-
if ($config !== null) {
47-
$config = (string) $config;
48-
}
49-
5048
return new Configuration(
5149
$isFixer,
5250
$shouldClearCache,
@@ -64,22 +62,19 @@ public function createFromInput(InputInterface $input): Configuration
6462
);
6563
}
6664

67-
private function canShowProgressBar(InputInterface $input): bool
65+
private function canShowProgressBar(bool $debug, string $outputFormat, bool $noProgressBar): bool
6866
{
6967
// --debug option shows more
70-
$debug = (bool) $input->getOption(Option::DEBUG);
7168
if ($debug) {
7269
return false;
7370
}
7471

75-
$outputFormat = $input->getOption(Option::OUTPUT_FORMAT);
7672
$outputFormatter = $this->outputFormatterCollector->getByName($outputFormat);
77-
7873
if (! $outputFormatter->hasSupportForProgressBars()) {
7974
return false;
8075
}
8176

82-
return ! (bool) $input->getOption(Option::NO_PROGRESS_BAR);
77+
return ! $noProgressBar;
8378
}
8479

8580
/**
@@ -97,12 +92,11 @@ private function ensurePathsExists(array $paths): void
9792
}
9893

9994
/**
95+
* @param string[] $paths
10096
* @return string[]
10197
*/
102-
private function resolvePaths(InputInterface $input): array
98+
private function resolvePaths(array $paths): array
10399
{
104-
/** @var string[] $paths */
105-
$paths = (array) $input->getArgument(Option::PATHS);
106100
if ($paths === []) {
107101
// if not paths are provided from CLI, use the config ones
108102
$paths = SimpleParameterProvider::getArrayParameter(Option::PATHS);

src/Console/Command/AbstractCheckCommand.php

Lines changed: 0 additions & 64 deletions
This file was deleted.

0 commit comments

Comments
 (0)