From a957eba2eb6e81e8ba079021da9040261b724054 Mon Sep 17 00:00:00 2001 From: TomasVotruba Date: Sun, 29 Mar 2020 16:09:49 +0200 Subject: [PATCH] move check_services_in_yaml_configs to ValidateServicesInSetsCommand --- ci/check_services_in_yaml_configs.php | 139 ------------------ .../Command/ValidateServicesInSetsCommand.php | 98 ++++++++++++ .../ServiceConfigurationValidator.php | 71 +++++++++ .../src/Yaml/YamlConfigFileProvider.php | 35 +++++ 4 files changed, 204 insertions(+), 139 deletions(-) create mode 100644 utils/set-runner/src/Command/ValidateServicesInSetsCommand.php create mode 100644 utils/set-runner/src/Validation/ServiceConfigurationValidator.php create mode 100644 utils/set-runner/src/Yaml/YamlConfigFileProvider.php diff --git a/ci/check_services_in_yaml_configs.php b/ci/check_services_in_yaml_configs.php index a4faf45a216..06fdcb4532a 100644 --- a/ci/check_services_in_yaml_configs.php +++ b/ci/check_services_in_yaml_configs.php @@ -2,143 +2,4 @@ declare(strict_types=1); -use Nette\Utils\Strings; -use Rector\Core\Exception\ShouldNotHappenException; -use Rector\NodeTypeResolver\ClassExistenceStaticHelper; -use Symfony\Component\Finder\Finder; -use Symfony\Component\Finder\SplFileInfo; -use Symfony\Component\Yaml\Yaml; - require __DIR__ . '/../vendor/autoload.php'; - -$serviceExistenceConfigChecker = new ServiceExistenceConfigChecker(); -$serviceExistenceConfigChecker->check(); - -final class ServiceExistenceConfigChecker -{ - /** - * @var YamlConfigFileProvider - */ - private $yamlConfigFileProvider; - - /** - * @var ServiceConfigurationValidator - */ - private $serviceConfigurationValidator; - - public function __construct() - { - $this->yamlConfigFileProvider = new YamlConfigFileProvider(); - $this->serviceConfigurationValidator = new ServiceConfigurationValidator(); - } - - public function check(): void - { - foreach ($this->yamlConfigFileProvider->provider() as $configFileInfo) { - $yamlContent = Yaml::parseFile($configFileInfo->getRealPath()); - if (! isset($yamlContent['services'])) { - continue; - } - - foreach ($yamlContent['services'] as $service => $serviceConfiguration) { - // configuration → skip - if (Strings::startsWith($service, '_')) { - continue; - } - - // autodiscovery → skip - if (Strings::endsWith($service, '\\')) { - continue; - } - - if (! ClassExistenceStaticHelper::doesClassLikeExist($service)) { - throw new ShouldNotHappenException(sprintf( - 'Service "%s" from config "%s" was not found. Check if it really exists or is even autoload, please', - $service, - $configFileInfo->getRealPath() - )); - } - - $this->serviceConfigurationValidator->validate($service, $serviceConfiguration, $configFileInfo); - } - } - - echo 'All configs have existing services - good job!' . PHP_EOL; - } -} - -final class YamlConfigFileProvider -{ - /** - * @return SplFileInfo[] - */ - public function provider(): array - { - $finder = (new Finder())->name('*.yaml') - ->in(__DIR__ . '/../config') - ->files(); - - return iterator_to_array($finder->getIterator()); - } -} - -final class ServiceConfigurationValidator -{ - public function validate(string $serviceClass, $configuration, SplFileInfo $configFileInfo): void - { - if (! is_array($configuration)) { - return; - } - - foreach (array_keys($configuration) as $key) { - if (! $this->isArgumentName($key)) { - continue; - } - - $constructorParameterNames = $this->resolveClassConstructorArgumentNames($serviceClass); - if (in_array($key, $constructorParameterNames, true)) { - continue; - } - - throw new ShouldNotHappenException(sprintf( - 'Service "%s" has unused argument "%s" in config "%s".%sCorrect it to one of existing arguments "%s".', - $serviceClass, - $key, - $configFileInfo->getRealPath(), - PHP_EOL, - implode('", "', $constructorParameterNames) - )); - } - } - - private function isArgumentName($key): bool - { - if (! is_string($key)) { - return false; - } - - return Strings::startsWith($key, '$'); - } - - /** - * @return string[] - */ - private function resolveClassConstructorArgumentNames(string $class): array - { - $reflectionClass = new ReflectionClass($class); - $constructorReflection = $reflectionClass->getConstructor(); - - if ($constructorReflection === null) { - return []; - } - - $constructorParameterNames = []; - foreach ($constructorReflection->getParameters() as $parameterReflection) { - $constructorParameterNames[] = '$' . $parameterReflection->getName(); - } - - sort($constructorParameterNames); - - return $constructorParameterNames; - } -} diff --git a/utils/set-runner/src/Command/ValidateServicesInSetsCommand.php b/utils/set-runner/src/Command/ValidateServicesInSetsCommand.php new file mode 100644 index 00000000000..ebe83618eb0 --- /dev/null +++ b/utils/set-runner/src/Command/ValidateServicesInSetsCommand.php @@ -0,0 +1,98 @@ +symfonyStyle = $symfonyStyle; + $this->serviceConfigurationValidator = $serviceConfigurationValidator; + $this->yamlConfigFileProvider = $yamlConfigFileProvider; + + parent::__construct(); + } + + protected function configure(): void + { + $this->setName(CommandNaming::classToName(self::class)); + $this->setDescription('[CI] Validate services in sets'); + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + foreach ($this->yamlConfigFileProvider->provider() as $configFileInfo) { + $this->symfonyStyle->note(sprintf('Validating config "%s"', $configFileInfo->getRelativeFilePathFromCwd())); + + $yamlContent = Yaml::parseFile($configFileInfo->getRealPath()); + if (! isset($yamlContent['services'])) { + continue; + } + + foreach ($yamlContent['services'] as $service => $serviceConfiguration) { + $this->validateService($service, $serviceConfiguration, $configFileInfo); + } + } + + $this->symfonyStyle->success('All configs have existing services'); + + return ShellCode::SUCCESS; + } + + private function validateService($service, $serviceConfiguration, SmartFileInfo $configFileInfo): void + { + // configuration → skip + if (Strings::startsWith($service, '_')) { + return; + } + + // autodiscovery → skip + if (Strings::endsWith($service, '\\')) { + return; + } + + if (! ClassExistenceStaticHelper::doesClassLikeExist($service)) { + throw new ShouldNotHappenException(sprintf( + 'Service "%s" from config "%s" was not found. Check if it really exists or is even autoload, please', + $service, + $configFileInfo->getRealPath() + )); + } + + $this->serviceConfigurationValidator->validate($service, $serviceConfiguration, $configFileInfo); + } +} diff --git a/utils/set-runner/src/Validation/ServiceConfigurationValidator.php b/utils/set-runner/src/Validation/ServiceConfigurationValidator.php new file mode 100644 index 00000000000..c7aea7e6a41 --- /dev/null +++ b/utils/set-runner/src/Validation/ServiceConfigurationValidator.php @@ -0,0 +1,71 @@ +isArgumentName($key)) { + continue; + } + + $constructorParameterNames = $this->resolveClassConstructorArgumentNames($serviceClass); + if (in_array($key, $constructorParameterNames, true)) { + continue; + } + + throw new ShouldNotHappenException(sprintf( + 'Service "%s" has unused argument "%s" in config "%s".%sCorrect it to one of existing arguments "%s".', + $serviceClass, + $key, + $configFileInfo->getRealPath(), + PHP_EOL, + implode('", "', $constructorParameterNames) + )); + } + } + + private function isArgumentName($key): bool + { + if (! is_string($key)) { + return false; + } + + return Strings::startsWith($key, '$'); + } + + /** + * @return string[] + */ + private function resolveClassConstructorArgumentNames(string $class): array + { + $reflectionClass = new ReflectionClass($class); + $constructorReflection = $reflectionClass->getConstructor(); + + if ($constructorReflection === null) { + return []; + } + + $constructorParameterNames = []; + foreach ($constructorReflection->getParameters() as $parameterReflection) { + $constructorParameterNames[] = '$' . $parameterReflection->getName(); + } + + sort($constructorParameterNames); + + return $constructorParameterNames; + } +} diff --git a/utils/set-runner/src/Yaml/YamlConfigFileProvider.php b/utils/set-runner/src/Yaml/YamlConfigFileProvider.php new file mode 100644 index 00000000000..d328c07bd27 --- /dev/null +++ b/utils/set-runner/src/Yaml/YamlConfigFileProvider.php @@ -0,0 +1,35 @@ +finderSanitizer = $finderSanitizer; + } + + /** + * @return SmartFileInfo[] + */ + public function provider(): array + { + $finder = (new Finder())->name('*.yaml') + ->in(__DIR__ . '/../../../../config') + ->sortByName() + ->files(); + + return $this->finderSanitizer->sanitize($finder); + } +}