-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
198 additions
and
72 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,74 +1,224 @@ | ||
#!/usr/bin/env php | ||
<?php declare(strict_types=1); | ||
<?php | ||
|
||
use Composer\XdebugHandler\XdebugHandler; | ||
declare(strict_types=1); | ||
|
||
use PHP_CodeSniffer\Util\Tokens; | ||
use Symfony\Component\Console\Input\ArgvInput; | ||
use Symplify\EasyCodingStandard\ChangedFilesDetector\ChangedFilesDetector; | ||
use Symplify\EasyCodingStandard\Console\EasyCodingStandardConsoleApplication; | ||
use Symplify\EasyCodingStandard\HttpKernel\EasyCodingStandardKernel; | ||
use Symplify\PackageBuilder\Configuration\ConfigFileFinder; | ||
use Symplify\PackageBuilder\Configuration\LevelFileFinder; | ||
use Symplify\EasyCodingStandard\Set\Set; | ||
use Symplify\SetConfigResolver\ConfigResolver; | ||
use Symplify\PackageBuilder\Console\Input\InputDetector; | ||
use Symplify\EasyCodingStandard\Configuration\Configuration; | ||
|
||
// performance boost | ||
gc_disable(); | ||
|
||
# 1. autoload | ||
require_once __DIR__ . '/vendor/autoload.php'; | ||
require_once __DIR__ . '/vendor/squizlabs/php_codesniffer/autoload.php'; | ||
|
||
// performance boost | ||
$xdebug = new XdebugHandler('ecs', '--ansi'); | ||
$xdebug->check(); | ||
unset($xdebug); | ||
$autoloadIncluder = new AutoloadIncluder(); | ||
$autoloadIncluder->includeCwdVendorAutoloadIfExists(); | ||
$autoloadIncluder->autoloadProjectAutoloaderFile('/../../autoload.php'); | ||
$autoloadIncluder->includeDependencyOrRepositoryVendorAutoloadIfExists(); | ||
$autoloadIncluder->includePhpCodeSnifferAutoloadIfNotInPharAndInitliazeTokens(); | ||
|
||
# 2. create container | ||
|
||
// Detect configuration from level option | ||
$configs = []; | ||
$configs[] = (new LevelFileFinder())->detectFromInputAndDirectory(new ArgvInput(), __DIR__ . '/../config/'); | ||
|
||
// Fallback to config option | ||
ConfigFileFinder::detectFromInput('ecs', new ArgvInput()); | ||
$configs[] = ConfigFileFinder::provide( | ||
'ecs', | ||
['easy-coding-standard.yml', 'easy-coding-standard.yaml', 'ecs.yml', 'ecs.yaml'] | ||
// 1. --config CLI option or default | ||
$configResolver = new ConfigResolver(); | ||
|
||
$input = new ArgvInput(); | ||
$inputConfig = $configResolver->resolveFromInputWithFallback($input, | ||
['easy-coding-standard.yml', 'easy-coding-standard.yaml', 'ecs.yml', 'ecs.yaml'] | ||
); | ||
if ($inputConfig) { | ||
$configs[] = $inputConfig; | ||
} | ||
|
||
// 2. --set CLI option | ||
$setInputConfig = $configResolver->resolveSetFromInputAndDirectory($input, Set::SET_DIRECTORY); | ||
if ($setInputConfig) { | ||
$configs[] = $setInputConfig; | ||
} | ||
|
||
// remove empty values | ||
$configs = array_filter($configs); | ||
|
||
if (!$configs) { | ||
if (version_compare(PHP_VERSION, '7.0.0', '<=')) { | ||
$configs[] = __DIR__ . '/coding-standard-php56.yml'; | ||
} elseif (version_compare(PHP_VERSION, '7.1.0', '<=')) { | ||
$configs[] = __DIR__ . '/coding-standard-php70.yml'; | ||
} else { | ||
$configs[] = __DIR__ . '/coding-standard-php71.yml'; | ||
} | ||
// 3. "parameters > set" in provided yaml files | ||
$parameterSetsConfigs = $configResolver->resolveFromParameterSetsFromConfigFiles($configs, Set::SET_DIRECTORY); | ||
if ($parameterSetsConfigs !== []) { | ||
$configs = array_merge($configs, $parameterSetsConfigs); | ||
} | ||
|
||
/** | ||
* @param string[] $configs | ||
*/ | ||
function computeConfigHash(array $configs): string | ||
{ | ||
$hash = ''; | ||
foreach ($configs as $config) { | ||
$hash .= md5_file($config); | ||
} | ||
$hash = ''; | ||
foreach ($configs as $config) { | ||
$hash .= md5_file($config); | ||
} | ||
|
||
return $hash; | ||
} | ||
|
||
$environment = 'prod' . md5(computeConfigHash($configs) . random_int(1, 100000)); | ||
|
||
return $hash; | ||
// shift input config as last, so the parameters override previous rules loaded from sets | ||
$mainConfigShiftedAsLast = []; | ||
foreach ($configs as $config) { | ||
if ($config !== $inputConfig) { | ||
$mainConfigShiftedAsLast[] = $config; | ||
} | ||
} | ||
|
||
if ($inputConfig !== null) { | ||
$mainConfigShiftedAsLast[] = $inputConfig; | ||
} | ||
|
||
$environment = 'prod' . computeConfigHash($configs) . random_int(1, 100000); | ||
$easyCodingStandardKernel = new EasyCodingStandardKernel($environment, InputDetector::isDebug()); | ||
if ($configs !== []) { | ||
$easyCodingStandardKernel->setConfigs($configs); | ||
$easyCodingStandardKernel->setConfigs($mainConfigShiftedAsLast); | ||
} | ||
|
||
$easyCodingStandardKernel->boot(); | ||
$container = $easyCodingStandardKernel->getContainer(); | ||
|
||
// for cache invalidation on config change | ||
/** @var ChangedFilesDetector $changedFilesDetector */ | ||
$changedFilesDetector = $container->get(ChangedFilesDetector::class); | ||
$changedFilesDetector->setUsedConfigs($configs); | ||
|
||
/** @var Configuration $configuration */ | ||
$configuration = $container->get(Configuration::class); | ||
$configuration->setFirstResolverConfig($configResolver->getFirstResolvedConfig()); | ||
|
||
# 3. run | ||
$application = $container->get(EasyCodingStandardConsoleApplication::class); | ||
exit($application->run()); | ||
|
||
|
||
/** | ||
* Inspired by https://github.com/rectorphp/rector/pull/2373/files#diff-0fc04a2bb7928cac4ae339d5a8bf67f3 | ||
*/ | ||
final class AutoloadIncluder | ||
{ | ||
/** | ||
* @var string[] | ||
*/ | ||
private $alreadyLoadedAutoloadFiles = []; | ||
|
||
public function includeCwdVendorAutoloadIfExists(): void | ||
{ | ||
$cwdVendorAutoload = getcwd() . '/vendor/autoload.php'; | ||
if (!is_file($cwdVendorAutoload)) { | ||
return; | ||
} | ||
$this->loadIfNotLoadedYet($cwdVendorAutoload, __METHOD__ . '()" on line ' . __LINE__); | ||
} | ||
|
||
public function includeDependencyOrRepositoryVendorAutoloadIfExists(): void | ||
{ | ||
// ECS' vendor is already loaded | ||
if (class_exists('\Symplify\EasyCodingStandard\HttpKernel\EasyCodingStandardKernel')) { | ||
return; | ||
} | ||
|
||
$devOrPharVendorAutoload = __DIR__ . '/../vendor/autoload.php'; | ||
if (! is_file($devOrPharVendorAutoload)) { | ||
return; | ||
} | ||
|
||
$this->loadIfNotLoadedYet($devOrPharVendorAutoload, __METHOD__ . '()" on line ' . __LINE__); | ||
} | ||
/** | ||
* Inspired by https://github.com/phpstan/phpstan-src/blob/e2308ecaf49a9960510c47f5a992ce7b27f6dba2/bin/phpstan#L19 | ||
*/ | ||
public function autoloadProjectAutoloaderFile(string $file): void | ||
{ | ||
$path = dirname(__DIR__) . $file; | ||
if (!extension_loaded('phar')) { | ||
if (is_file($path)) { | ||
$this->loadIfNotLoadedYet($path, __METHOD__ . '()" on line ' . __LINE__); | ||
} | ||
} else { | ||
$pharPath = Phar::running(false); | ||
if ($pharPath === '') { | ||
if (is_file($path)) { | ||
$this->loadIfNotLoadedYet($path, __METHOD__ . '()" on line ' . __LINE__); | ||
} | ||
} else { | ||
$path = dirname($pharPath) . $file; | ||
if (is_file($path)) { | ||
$this->loadIfNotLoadedYet($path, __METHOD__ . '()" on line ' . __LINE__); | ||
} | ||
} | ||
} | ||
} | ||
|
||
private function isInPhar(): bool | ||
{ | ||
if (!extension_loaded('phar')) { | ||
return false; | ||
} | ||
|
||
if (Phar::running(false) === '') { | ||
return false; | ||
} | ||
|
||
return true; | ||
} | ||
|
||
private function loadIfNotLoadedYet(string $file, string $location): void | ||
{ | ||
if (in_array($file, $this->alreadyLoadedAutoloadFiles, true)) { | ||
return; | ||
} | ||
|
||
if ($this->isDebugOption()) { | ||
echo sprintf(sprintf( | ||
'File "%s" is about to be loaded in "%s"' . PHP_EOL, | ||
$file, | ||
$location | ||
)); | ||
} | ||
|
||
$this->alreadyLoadedAutoloadFiles[] = realpath($file); | ||
require_once $file; | ||
} | ||
|
||
private function isDebugOption(): bool | ||
{ | ||
return in_array('--debug', $_SERVER['argv'], true); | ||
} | ||
|
||
public function includePhpCodeSnifferAutoloadIfNotInPharAndInitliazeTokens() | ||
{ | ||
// file is autoloaded with classmap in PHAR | ||
// without phar, we still need to autoload it | ||
if (! $this->isInPhar()) { | ||
# 1. autoload | ||
$possibleAutoloadPaths = [ | ||
// after split package | ||
__DIR__ . '/../vendor', | ||
// dependency | ||
__DIR__ . '/../../..', | ||
// monorepo | ||
__DIR__ . '/../../../vendor', | ||
]; | ||
|
||
foreach ($possibleAutoloadPaths as $possibleAutoloadPath) { | ||
if (!is_file($possibleAutoloadPath . '/autoload.php')) { | ||
continue; | ||
} | ||
|
||
require_once $possibleAutoloadPath . '/squizlabs/php_codesniffer/autoload.php'; | ||
} | ||
} | ||
|
||
// initalize PHPCS tokens | ||
new Tokens(); | ||
} | ||
} |
This file was deleted.
Oops, something went wrong.