From 08034e639b0af82aa2701d09b66e9d227881d635 Mon Sep 17 00:00:00 2001 From: Navarr Date: Thu, 21 Dec 2023 11:33:18 -0500 Subject: [PATCH] Update dependencies and fix all phpstan errors --- .env | 2 +- .github/workflows/commit.yml | 11 +++++--- composer.json | 9 ++++-- src/Controller/CliApplication.php | 2 +- src/Controller/Composer/ComposerCommand.php | 24 ++++++++++------ src/Controller/WhyBlockCommandController.php | 26 ++++++++++++----- src/Factory/CollectingFactory.php | 7 ++++- src/Factory/FindingVisitorFactory.php | 7 ++++- src/Factory/NodeTraverserFactory.php | 7 ++++- src/Parser/AstParser.php | 1 + src/Parser/LegacyParser.php | 12 ++++---- .../ComposerScopeDeterminer.php | 28 +++++++++++-------- src/ScopeDeterminer/PhpFileDeterminer.php | 4 +-- 13 files changed, 95 insertions(+), 45 deletions(-) diff --git a/.env b/.env index bd95dd7..658c741 100644 --- a/.env +++ b/.env @@ -6,7 +6,7 @@ TRAEFIK_DOMAIN=depends.test TRAEFIK_SUBDOMAIN=app WARDEN_PHP=1 -PHP_VERSION=8.0 +PHP_VERSION=8.2 PHP_XDEBUG_3=1 COMPOSER_VERSION=2 diff --git a/.github/workflows/commit.yml b/.github/workflows/commit.yml index 05f8ceb..7668f1b 100644 --- a/.github/workflows/commit.yml +++ b/.github/workflows/commit.yml @@ -9,7 +9,7 @@ jobs: - name: Setup PHP uses: shivammathur/setup-php@v2 with: - php-version: 8.0 + php-version: 8.3 coverage: xdebug tools: composer:v2 @@ -32,8 +32,11 @@ jobs: phpstan: name: Static Analysis Check runs-on: ubuntu-latest + strategy: + matrix: + php: [8.0, 8.1, 8.2, 8.3] container: - image: davidalger/php:8.0 + image: davidalger/php:${{ matrix.php }} steps: - name: Checkout Repository uses: actions/checkout@v2 @@ -48,7 +51,7 @@ jobs: name: Code Style (PSR-12) runs-on: ubuntu-latest container: - image: davidalger/php:8.0 + image: davidalger/php:8.3 steps: - name: Checkout Repository uses: actions/checkout@v2 @@ -67,7 +70,7 @@ jobs: - name: Setup PHP uses: shivammathur/setup-php@v2 with: - php-version: 8.0 + php-version: 8.3 coverage: xdebug tools: composer:v2 diff --git a/composer.json b/composer.json index 3b19228..bb86e56 100644 --- a/composer.json +++ b/composer.json @@ -11,7 +11,7 @@ "symfony/console": "^5", "nikic/php-parser": "^4", "navarr/attribute-dependency": "^1.0.1", - "php-di/php-di": "^6" + "php-di/php-di": "^7" }, "suggest": { "ext-fileinfo": "Use MIME types for PHP file detection", @@ -23,7 +23,7 @@ "roave/security-advisories": "dev-master", "phpstan/phpstan": "^1", "phpunit/phpunit": "^9.5", - "infection/infection": "^0.23.0", + "infection/infection": "^0.27.0", "squizlabs/php_codesniffer": "^3.6", "jetbrains/phpstorm-attributes": "^1.0" }, @@ -56,5 +56,10 @@ ".gitattributes", ".env" ] + }, + "config": { + "allow-plugins": { + "infection/extension-installer": true + } } } diff --git a/src/Controller/CliApplication.php b/src/Controller/CliApplication.php index 4a3a73b..ffcdd36 100644 --- a/src/Controller/CliApplication.php +++ b/src/Controller/CliApplication.php @@ -18,7 +18,7 @@ class CliApplication public static function execute(): int { - $application = new Application('DepAnno', static::VERSION); + $application = new Application('DepAnno', self::VERSION); $application->add(new WhyBlockCommandController()); return $application->run(); } diff --git a/src/Controller/Composer/ComposerCommand.php b/src/Controller/Composer/ComposerCommand.php index 4c2bea1..e920605 100644 --- a/src/Controller/Composer/ComposerCommand.php +++ b/src/Controller/Composer/ComposerCommand.php @@ -31,6 +31,7 @@ use Navarr\Depends\ScopeDeterminer\ComposerScopeDeterminer; use Navarr\Depends\ScopeDeterminer\ScopeDeterminerInterface; use Psr\Container\ContainerInterface; +use RuntimeException; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; @@ -128,13 +129,13 @@ protected function execute( } $outputFormat = strtolower($outputFormat); - if (!in_array($outputFormat, static::ACCEPTABLE_FORMATS)) { + if (!in_array($outputFormat, self::ACCEPTABLE_FORMATS)) { $outputFormat = 'text'; } - if ($input->getOption(static::ALL_DEPS)) { + if ($input->getOption(self::ALL_DEPS)) { $composerScope = ComposerScopeDeterminer::SCOPE_ALL_DEPENDENCIES; - } elseif ($input->getOption(static::ROOT_DEPS)) { + } elseif ($input->getOption(self::ROOT_DEPS)) { $composerScope = ComposerScopeDeterminer::SCOPE_ROOT_DEPENDENCIES; } else { $composerScope = ComposerScopeDeterminer::SCOPE_PROJECT_ONLY; @@ -145,14 +146,21 @@ protected function execute( [ InputInterface::class => $input, OutputInterface::class => $output, - IssueHandlerInterface::class => $input->getOption(static::FAIL_ON_ERROR) + IssueHandlerInterface::class => $input->getOption(self::FAIL_ON_ERROR) ? FailOnIssueHandler::class : NotifyOnIssueHandler::class, Composer::class => $this->getComposer(true), ParserInterface::class => static function (ContainerInterface $container) use ($input) { - $parsers = [$container->get(AstParser::class)]; - if ($input->getOption(static::LEGACY_ANNOTATION)) { - $parsers[] = $container->get(LegacyParser::class); + $parser = $container->get(AstParser::class); + if (!$parser instanceof ParserInterface) { + throw new RuntimeException('AstParser not found'); + } + $parsers = [$parser]; + if ($input->getOption(self::LEGACY_ANNOTATION)) { + $legacyParser = $container->get(LegacyParser::class); + if ($legacyParser instanceof ParserInterface) { + $parsers[] = $legacyParser; + } } return new ParserPool($parsers); }, @@ -160,7 +168,7 @@ protected function execute( ComposerScopeDeterminer::class => autowire(ComposerScopeDeterminer::class) ->property('scope', $composerScope), ScopeDeterminerInterface::class => autowire(ComposerScopeDeterminer::class), - OutputHandlerInterface::class => autowire(static::FORMAT_MAPPER[$outputFormat]), + OutputHandlerInterface::class => autowire(self::FORMAT_MAPPER[$outputFormat]), ] ); $container = $containerBuilder->build(); diff --git a/src/Controller/WhyBlockCommandController.php b/src/Controller/WhyBlockCommandController.php index 4421c9e..557d25b 100644 --- a/src/Controller/WhyBlockCommandController.php +++ b/src/Controller/WhyBlockCommandController.php @@ -31,6 +31,7 @@ use Navarr\Depends\ScopeDeterminer\PhpFileFinder; use Navarr\Depends\ScopeDeterminer\ScopeDeterminerInterface; use Psr\Container\ContainerInterface; +use RuntimeException; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; @@ -120,7 +121,7 @@ protected function execute( } $outputFormat = strtolower($outputFormat); - if (!in_array($outputFormat, static::ACCEPTABLE_FORMATS)) { + if (!in_array($outputFormat, self::ACCEPTABLE_FORMATS)) { $outputFormat = 'text'; } @@ -129,24 +130,35 @@ protected function execute( [ InputInterface::class => $input, OutputInterface::class => $output, - IssueHandlerInterface::class => $input->getOption(static::FAIL_ON_ERROR) + IssueHandlerInterface::class => $input->getOption(self::FAIL_ON_ERROR) ? FailOnIssueHandler::class : NotifyOnIssueHandler::class, ParserInterface::class => static function (ContainerInterface $container) use ($input) { - $parsers = [$container->get(AstParser::class)]; - if ($input->getOption(static::LEGACY_ANNOTATION)) { - $parsers[] = $container->get(LegacyParser::class); + $parser = $container->get(AstParser::class); + if (!$parser instanceof ParserInterface) { + throw new RuntimeException('AstParser not found'); + } + $parsers = [$parser]; + if ($input->getOption(self::LEGACY_ANNOTATION)) { + $legacyParser = $container->get(LegacyParser::class); + if ($legacyParser instanceof ParserInterface) { + $parsers[] = $legacyParser; + } } return new ParserPool($parsers); }, WriterInterface::class => autowire(StdOutWriter::class), ScopeDeterminerInterface::class => static function (ContainerInterface $container) use ($directory) { + $phpFileFinder = $container->get(PhpFileFinder::class); + if (!$phpFileFinder instanceof PhpFileFinder) { + throw new RuntimeException('PhpFileFinder not found'); + } return new DirectoryScopeDeterminer( - $container->get(PhpFileFinder::class), + $phpFileFinder, $directory ); }, - OutputHandlerInterface::class => autowire(static::FORMAT_MAPPER[$outputFormat]), + OutputHandlerInterface::class => autowire(self::FORMAT_MAPPER[$outputFormat]), ] ); $container = $containerBuilder->build(); diff --git a/src/Factory/CollectingFactory.php b/src/Factory/CollectingFactory.php index d035324..f912ba8 100644 --- a/src/Factory/CollectingFactory.php +++ b/src/Factory/CollectingFactory.php @@ -13,6 +13,7 @@ use DI\NotFoundException; use Navarr\Attribute\Dependency; use PhpParser\ErrorHandler\Collecting; +use RuntimeException; #[Dependency('php-di/php-di', '^6', 'Container::make')] #[Dependency('nikic/php-parser', '^4', 'Existence of Collecting error handler')] @@ -32,6 +33,10 @@ public function __construct(Container $container) */ public function create(): Collecting { - return $this->container->make(Collecting::class); + $result = $this->container->make(Collecting::class); + if (!$result instanceof Collecting) { + throw new RuntimeException('Container did not return a Collecting'); + } + return $result; } } diff --git a/src/Factory/FindingVisitorFactory.php b/src/Factory/FindingVisitorFactory.php index 663e6c0..4b04172 100644 --- a/src/Factory/FindingVisitorFactory.php +++ b/src/Factory/FindingVisitorFactory.php @@ -13,6 +13,7 @@ use DI\NotFoundException; use Navarr\Attribute\Dependency; use PhpParser\NodeVisitor\FindingVisitor; +use RuntimeException; #[Dependency('php-di/php-di', '^6', 'Container::make')] #[Dependency('nikic/php-parser', '^4', 'Existence of FindingVisitor')] @@ -33,6 +34,10 @@ public function __construct(Container $container) */ public function create(array $args = []): FindingVisitor { - return $this->container->make(FindingVisitor::class, $args); + $result = $this->container->make(FindingVisitor::class, $args); + if (!$result instanceof FindingVisitor) { + throw new RuntimeException('Container did not return a FindingVisitor'); + } + return $result; } } diff --git a/src/Factory/NodeTraverserFactory.php b/src/Factory/NodeTraverserFactory.php index b5f7f0f..5f2d116 100644 --- a/src/Factory/NodeTraverserFactory.php +++ b/src/Factory/NodeTraverserFactory.php @@ -13,6 +13,7 @@ use DI\NotFoundException; use Navarr\Attribute\Dependency; use PhpParser\NodeTraverser; +use RuntimeException; #[Dependency('php-di/php-di', '^6', 'Container::make')] #[Dependency('nikic/php-parser', '^4', 'Existence of NodeTraverser')] @@ -33,6 +34,10 @@ public function __construct(Container $container) */ public function create(array $args = []): NodeTraverser { - return $this->container->make(NodeTraverser::class, $args); + $result = $this->container->make(NodeTraverser::class, $args); + if (!$result instanceof NodeTraverser) { + throw new RuntimeException('Container did not return a NodeTraverser'); + } + return $result; } } diff --git a/src/Parser/AstParser.php b/src/Parser/AstParser.php index fa45d16..3c0b168 100644 --- a/src/Parser/AstParser.php +++ b/src/Parser/AstParser.php @@ -87,6 +87,7 @@ public function parse( $traverser->traverse($ast); + /** @var Attribute[] $attributes Since we have a filter callback, this will always be an Attribute */ $attributes = $finder->getFoundNodes(); $argIndex = [ diff --git a/src/Parser/LegacyParser.php b/src/Parser/LegacyParser.php index f6c5e29..2ef5131 100644 --- a/src/Parser/LegacyParser.php +++ b/src/Parser/LegacyParser.php @@ -51,7 +51,7 @@ public function parse(string $contents): array } /** - * @param string[][] $matches + * @param array>> $matches * @param string $contents * @return DeclaredDependency[] */ @@ -59,15 +59,15 @@ private function processMatches(array $matches, string $contents): array { $results = []; - $matchCount = count($matches[0]) ?? 0; + $matchCount = count($matches[0]) ?: 0; for ($match = 0; $match < $matchCount; ++$match) { - $package = strtolower($matches[static::INLINE_MATCH_PACKAGE][$match][0]); - $version = $matches[static::INLINE_MATCH_VERSION][$match][0]; + $package = strtolower((string)$matches[self::INLINE_MATCH_PACKAGE][$match][0]); + $version = (string)$matches[self::INLINE_MATCH_VERSION][$match][0] ?: null; $line = substr_count(mb_substr($contents, 0, (int)$matches[0][$match][1]), "\n") + 1; - $reason = trim($matches[static::INLINE_MATCH_REASON][$match][0]) ?? 'No reason provided'; - if (substr($reason, -2) === '*/') { + $reason = trim((string)$matches[self::INLINE_MATCH_REASON][$match][0]) ?: 'No reason provided'; + if (str_ends_with($reason, '*/')) { $reason = trim(substr($reason, 0, -2)); } diff --git a/src/ScopeDeterminer/ComposerScopeDeterminer.php b/src/ScopeDeterminer/ComposerScopeDeterminer.php index 507b2f3..e0b5cef 100644 --- a/src/ScopeDeterminer/ComposerScopeDeterminer.php +++ b/src/ScopeDeterminer/ComposerScopeDeterminer.php @@ -112,7 +112,8 @@ private function getRequirementsForPackage(Link $package): array * Retrieve all PHP files out of the directories and files listed in the autoload directive * * @param string $basePath Base directory of the package who's autoload we're processing - * @param array $autoload Result of {@see PackageInterface::getAutoload()} + * @param array|string>> $autoload + * Result of {@see PackageInterface::getAutoload()} * @param string[] $results Array of file paths to merge with * @return string[] File paths */ @@ -123,17 +124,22 @@ private function getAllFilesForAutoload( array $results = [] ): array { foreach ($autoload as $map) { - foreach ($map as $dir) { - $realDir = realpath($basePath . DIRECTORY_SEPARATOR . $dir); - if ($realDir === false) { - continue; + foreach ($map as $dirs) { + if (is_string($dirs)) { + $dirs = [$dirs]; } - if (is_file($realDir)) { - $results[] = $realDir; - continue; - } - if (is_dir($realDir)) { - $results = $this->phpFileFinder->findAll($dir, $results); + foreach ($dirs as $dir) { + $realDir = realpath($basePath . DIRECTORY_SEPARATOR . $dir); + if ($realDir === false) { + continue; + } + if (is_file($realDir)) { + $results[] = $realDir; + continue; + } + if (is_dir($realDir)) { + $results = $this->phpFileFinder->findAll($dir, $results); + } } } } diff --git a/src/ScopeDeterminer/PhpFileDeterminer.php b/src/ScopeDeterminer/PhpFileDeterminer.php index ad8af7b..4f830d1 100644 --- a/src/ScopeDeterminer/PhpFileDeterminer.php +++ b/src/ScopeDeterminer/PhpFileDeterminer.php @@ -45,13 +45,13 @@ public function isPhp( // There are so many approaches we could take here, but we're going with this one: $mimeType = $this->mimeDeterminer->getMimeType($file); - if ($mimeType && in_array($mimeType, static::PHP_MIME_TYPES)) { + if ($mimeType && in_array($mimeType, self::PHP_MIME_TYPES)) { // Mime type is PHP. That's good enough for me return true; } $parts = explode('.', $file); - if (in_array(end($parts), static::PHP_FILE_EXTENSIONS)) { + if (in_array(end($parts), self::PHP_FILE_EXTENSIONS)) { // Extension matches list - so it was probably intended to be PHP return true; }