From a78abe927843869361dd6f382f6d5b30fb7878bd Mon Sep 17 00:00:00 2001 From: Cees-Jan Kiewiet Date: Wed, 7 Aug 2019 21:35:53 +0200 Subject: [PATCH] Round two! --- bin/composer-require-checker.php | 4 +- composer.json | 3 +- .../Cli/Application.php | 4 +- .../Cli/CheckCommand.php | 94 +++++++++---------- .../Cli/CheckCommandTest.php | 2 +- 5 files changed, 49 insertions(+), 58 deletions(-) diff --git a/bin/composer-require-checker.php b/bin/composer-require-checker.php index cc57a58e..89507265 100644 --- a/bin/composer-require-checker.php +++ b/bin/composer-require-checker.php @@ -17,7 +17,7 @@ } $foundAutoloadFile = true; - $autoloader = require $autoloadFileLocation; + require $autoloadFileLocation; break; } @@ -28,5 +28,5 @@ use ComposerRequireChecker\Cli\Application; -$application = new Application($autoloader); +$application = new Application(); $application->run(); diff --git a/composer.json b/composer.json index 581d0161..95c752e9 100644 --- a/composer.json +++ b/composer.json @@ -31,7 +31,8 @@ "ext-phar": "*", "nikic/php-parser": "^4.0", "symfony/console": "^3.4.17 | ^4.1.6", - "webmozart/glob": "^4.1" + "webmozart/glob": "^4.1", + "roave/better-reflection": "^3.5" }, "require-dev": { "phpunit/phpunit": "^6.0", diff --git a/src/ComposerRequireChecker/Cli/Application.php b/src/ComposerRequireChecker/Cli/Application.php index 6fe05452..e0847375 100644 --- a/src/ComposerRequireChecker/Cli/Application.php +++ b/src/ComposerRequireChecker/Cli/Application.php @@ -13,11 +13,11 @@ class Application extends AbstractApplication { - public function __construct(ClassLoader $autoloader) + public function __construct() { parent::__construct('ComposerRequireChecker', $this->getPackageVersion()); - $check = new CheckCommand($autoloader); + $check = new CheckCommand(); $this->add($check); $this->setDefaultCommand($check->getName()); } diff --git a/src/ComposerRequireChecker/Cli/CheckCommand.php b/src/ComposerRequireChecker/Cli/CheckCommand.php index 4979f696..697c6dcf 100644 --- a/src/ComposerRequireChecker/Cli/CheckCommand.php +++ b/src/ComposerRequireChecker/Cli/CheckCommand.php @@ -2,13 +2,10 @@ namespace ComposerRequireChecker\Cli; -use Composer\Autoload\ClassLoader; use ComposerRequireChecker\ASTLocator\LocateASTFromFiles; use ComposerRequireChecker\DefinedExtensionsResolver\DefinedExtensionsResolver; -use ComposerRequireChecker\DefinedSymbolsLocator\LocateDefinedSymbolsFromASTRoots; use ComposerRequireChecker\DefinedSymbolsLocator\LocateDefinedSymbolsFromExtensions; use ComposerRequireChecker\DependencyGuesser\DependencyGuesser; -use ComposerRequireChecker\FileLocator\LocateComposerPackageDirectDependenciesSourceFiles; use ComposerRequireChecker\FileLocator\LocateComposerPackageSourceFiles; use ComposerRequireChecker\FileLocator\LocateFilesByGlobPattern; use ComposerRequireChecker\GeneratorUtil\ComposeGenerators; @@ -16,6 +13,12 @@ use ComposerRequireChecker\UsedSymbolsLocator\LocateUsedSymbolsFromASTRoots; use PhpParser\ErrorHandler\Collecting as CollectingErrorHandler; use PhpParser\ParserFactory; +use Roave\BetterReflection\BetterReflection; +use Roave\BetterReflection\Reflector\ClassReflector; +use Roave\BetterReflection\Reflector\ConstantReflector; +use Roave\BetterReflection\Reflector\Exception\IdentifierNotFound; +use Roave\BetterReflection\Reflector\FunctionReflector; +use Roave\BetterReflection\SourceLocator\Type\Composer\Factory\MakeLocatorForComposerJsonAndInstalledJson; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Helper\Table; use Symfony\Component\Console\Input\InputArgument; @@ -26,16 +29,6 @@ class CheckCommand extends Command { - /** @var ClassLoader */ - private $classLoader; - - public function __construct(ClassLoader $autoloader) - { - $this->classLoader = $autoloader; - - parent::__construct(); - } - protected function configure() { $this @@ -91,59 +84,56 @@ protected function execute(InputInterface $input, OutputInterface $output): int )); $this->verbose("found " . count($usedSymbols) . " symbols.", $output, true); + $this->verbose("Collecting defined extension symbols... ", $output); $definedExtensionSymbols = (new LocateDefinedSymbolsFromExtensions())->__invoke( (new DefinedExtensionsResolver())->__invoke($composerJson, $options->getPhpCoreExtensions()) ); $this->verbose("found " . count($definedExtensionSymbols) . " symbols.", $output, true); - $this->verbose("Collecting defined vendor symbols phase 1... ", $output); + $locator = new MakeLocatorForComposerJsonAndInstalledJson(); + $astLocator = (new BetterReflection())->astLocator(); + $composerLocator = $locator(dirname($composerJson), $astLocator); + $classReflector = new ClassReflector($composerLocator); + $functionReflector = new FunctionReflector($composerLocator, $classReflector); + $constantReflector = new ConstantReflector($composerLocator, $classReflector); + $whiteList = $options->getSymbolWhitelist(); + $unknownSymbols = []; + foreach ($usedSymbols as $usedSymbol) { + if (in_array($usedSymbol, $whiteList)) { + continue; + } - $definedVendorSymbols = (new LocateDefinedSymbolsFromASTRoots())->__invoke($sourcesASTs( - $getAdditionalSourceFiles(iterator_to_array((function ($usedSymbols): iterable{ - foreach ($usedSymbols as $usedSymbol) { - $file = $this->classLoader->findFile($usedSymbol); + if (in_array($usedSymbol, $definedExtensionSymbols)) { + continue; + } - if ($file !== false) { - yield $file; - } - } - })($usedSymbols)), ''), - )); + try { + $classReflector->reflect($usedSymbol); - $this->verbose("found " . count($definedVendorSymbols) . " symbols.", $output, true); + continue; + } catch (IdentifierNotFound $ignore) { + // void + } - $unknownSymbols = array_diff( - $usedSymbols, - $definedVendorSymbols, - $definedExtensionSymbols, - $options->getSymbolWhitelist() - ); + try { + $functionReflector->reflect($usedSymbol); - if (count($unknownSymbols) > 0) { - $this->verbose("Collecting defined vendor symbols phase 2... ", $output); + continue; + } catch (IdentifierNotFound $ignore) { + // void + } - $definedVendorSymbols = (new LocateDefinedSymbolsFromASTRoots())->__invoke($sourcesASTs( - (new ComposeGenerators())->__invoke( - $getAdditionalSourceFiles($options->getScanFiles(), dirname($composerJson)), - $getPackageSourceFiles($composerData, dirname($composerJson)), - (new LocateComposerPackageDirectDependenciesSourceFiles())->__invoke($composerJson) - ) - )); + try { + $constantReflector->reflect($usedSymbol); - $this->verbose("found " . count($definedVendorSymbols) . " symbols.", $output, true); - } - if (!count($usedSymbols)) { - throw new \LogicException('There were no symbols found, please check your configuration.'); - } + continue; + } catch (IdentifierNotFound $ignore) { + // void + } - $this->verbose("Checking for unknown symbols... ", $output, true); - $unknownSymbols = array_diff( - $usedSymbols, - $definedVendorSymbols, - $definedExtensionSymbols, - $options->getSymbolWhitelist() - ); + $unknownSymbols[] = $usedSymbol; + } if (!$unknownSymbols) { $output->writeln("There were no unknown symbols found."); diff --git a/test/ComposerRequireCheckerTest/Cli/CheckCommandTest.php b/test/ComposerRequireCheckerTest/Cli/CheckCommandTest.php index 3ca5dc1e..64829cfc 100644 --- a/test/ComposerRequireCheckerTest/Cli/CheckCommandTest.php +++ b/test/ComposerRequireCheckerTest/Cli/CheckCommandTest.php @@ -57,7 +57,7 @@ public function testVerboseSelfCheckShowsCounts() 'verbosity' => OutputInterface::VERBOSITY_VERBOSE, ]); - $this->assertRegExp('/Collecting defined vendor symbols... found \d+ symbols./', $this->commandTester->getDisplay()); +// $this->assertRegExp('/Collecting defined vendor symbols... found \d+ symbols./', $this->commandTester->getDisplay()); $this->assertRegExp('/Collecting defined extension symbols... found \d+ symbols./', $this->commandTester->getDisplay()); $this->assertRegExp('/Collecting used symbols... found \d+ symbols./', $this->commandTester->getDisplay()); }