From e2547337e7162d19fd3bd4cc069b8733bab04809 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Mon, 29 Jan 2024 01:50:10 +0100 Subject: [PATCH] [PSR-4] Add "find-multi-classes" command to check files with multiple classes (#15) --- src/Command/FindMultiClassesCommand.php | 56 ++++++++++++++++++++ src/DependencyInjection/ContainerFactory.php | 3 ++ src/Finder/MultipleClassInOneFileFinder.php | 31 +++++++++++ src/RobotLoader/PhpClassLoader.php | 22 ++++++++ 4 files changed, 112 insertions(+) create mode 100644 src/Command/FindMultiClassesCommand.php create mode 100644 src/Finder/MultipleClassInOneFileFinder.php create mode 100644 src/RobotLoader/PhpClassLoader.php diff --git a/src/Command/FindMultiClassesCommand.php b/src/Command/FindMultiClassesCommand.php new file mode 100644 index 000000000..8b838bf46 --- /dev/null +++ b/src/Command/FindMultiClassesCommand.php @@ -0,0 +1,56 @@ +setName('find-multi-classes'); + + $this->setDescription('Find multiple classes in one file'); + + $this->addArgument( + 'sources', + InputArgument::REQUIRED | InputArgument::IS_ARRAY, + 'Path to source to analyse' + ); + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + /** @var string[] $source */ + $source = $input->getArgument('sources'); + + $multipleClassesByFile = $this->multipleClassInOneFileFinder->findInDirectories($source); + if ($multipleClassesByFile === []) { + $this->symfonyStyle->success('No files with 2+ classes found'); + + return self::SUCCESS; + } + + foreach ($multipleClassesByFile as $file => $classes) { + $message = sprintf('File "%s" has %d classes', $file, count($classes)); + $this->symfonyStyle->section($message); + $this->symfonyStyle->listing($classes); + } + + return self::FAILURE; + } +} diff --git a/src/DependencyInjection/ContainerFactory.php b/src/DependencyInjection/ContainerFactory.php index 9336f8759..1f4dbcf98 100644 --- a/src/DependencyInjection/ContainerFactory.php +++ b/src/DependencyInjection/ContainerFactory.php @@ -11,6 +11,7 @@ use Symfony\Component\Console\Style\SymfonyStyle; use Symplify\EasyCI\Command\CheckCommentedCodeCommand; use Symplify\EasyCI\Command\CheckConflictsCommand; +use Symplify\EasyCI\Command\FindMultiClassesCommand; use Symplify\EasyCI\Command\ValidateFileLengthCommand; use Symplify\EasyCI\Testing\Command\DetectUnitTestsCommand; @@ -37,7 +38,9 @@ public function create(): Container $container->make(CheckConflictsCommand::class), $container->make(ValidateFileLengthCommand::class), $container->make(DetectUnitTestsCommand::class), + $container->make(FindMultiClassesCommand::class), ]; + $application->addCommands($commands); // remove basic command to make output clear diff --git a/src/Finder/MultipleClassInOneFileFinder.php b/src/Finder/MultipleClassInOneFileFinder.php new file mode 100644 index 000000000..79b3c3e1d --- /dev/null +++ b/src/Finder/MultipleClassInOneFileFinder.php @@ -0,0 +1,31 @@ +phpClassLoader->load($directories); + + $classesByFile = []; + foreach ($fileByClasses as $class => $file) { + $classesByFile[$file][] = $class; + } + + return array_filter($classesByFile, static fn(array $classes): bool => count($classes) >= 2); + } +} diff --git a/src/RobotLoader/PhpClassLoader.php b/src/RobotLoader/PhpClassLoader.php new file mode 100644 index 000000000..b5bec2a40 --- /dev/null +++ b/src/RobotLoader/PhpClassLoader.php @@ -0,0 +1,22 @@ + + */ + public function load(array $directories): array + { + $robotLoader = new RobotLoader(); + $robotLoader->addDirectory(...$directories); + $robotLoader->setTempDirectory(sys_get_temp_dir() . '/multiple-classes'); + $robotLoader->rebuild(); + + return $robotLoader->getIndexedClasses(); + } +}