Skip to content

Commit

Permalink
Guess dependency of class symbols using installed packages.
Browse files Browse the repository at this point in the history
Use BetterReflection.
Do not work with functions nor constants.
Do not support https://getcomposer.org/doc/06-config.md#vendor-dir
  • Loading branch information
guillaume-perreal committed Nov 17, 2019
1 parent 832281d commit c889607
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 0 deletions.
2 changes: 2 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
"ext-phar": "*",
"nikic/php-parser": "^4.2",
"ocramius/package-versions": "^1.4.0",
"phpdocumentor/type-resolver": "^0.4",
"roave/better-reflection": "^3.5.0",
"symfony/console": "^4.3.6",
"webmozart/glob": "^4.1"
},
Expand Down
2 changes: 2 additions & 0 deletions src/ComposerRequireChecker/Cli/CheckCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use ComposerRequireChecker\DefinedSymbolsLocator\LocateDefinedSymbolsFromASTRoots;
use ComposerRequireChecker\DefinedSymbolsLocator\LocateDefinedSymbolsFromExtensions;
use ComposerRequireChecker\DependencyGuesser\DependencyGuesser;
use ComposerRequireChecker\DependencyGuesser\GuessFromComposerInstalledJson;
use ComposerRequireChecker\FileLocator\LocateComposerPackageDirectDependenciesSourceFiles;
use ComposerRequireChecker\FileLocator\LocateComposerPackageSourceFiles;
use ComposerRequireChecker\FileLocator\LocateFilesByGlobPattern;
Expand Down Expand Up @@ -116,6 +117,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$table = new Table($output);
$table->setHeaders(['unknown symbol', 'guessed dependency']);
$guesser = new DependencyGuesser($options);
$guesser->addGuesser(new GuessFromComposerInstalledJson(dirname($composerJson)));
foreach ($unknownSymbols as $unknownSymbol) {
$guessedDependencies = [];
foreach ($guesser($unknownSymbol) as $guessedDependency) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ public function __construct(?Options $options = null)
$this->guessers[] = new GuessFromLoadedExtensions($options);
}

public function addGuesser(GuesserInterface $guesser): void
{
$this->guessers[] = $guesser;
}

public function __invoke($symbolName): \Generator
{
foreach ($this->guessers as $guesser) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<?php declare(strict_types=1);


namespace ComposerRequireChecker\DependencyGuesser;

use Roave\BetterReflection\BetterReflection;
use Roave\BetterReflection\Identifier\Identifier;
use Roave\BetterReflection\Identifier\IdentifierType;
use Roave\BetterReflection\Reflection\ReflectionClass;
use Roave\BetterReflection\Reflector\ClassReflector;
use Roave\BetterReflection\SourceLocator\Type\Composer\Factory\MakeLocatorForInstalledJson;
use Roave\BetterReflection\SourceLocator\Type\MemoizingSourceLocator;
use Roave\BetterReflection\SourceLocator\Type\SourceLocator;

final class GuessFromComposerInstalledJson implements GuesserInterface
{
/**
* @var SourceLocator
*/
private $sourceLocator;

/**
* @var ClassReflector
*/
private $reflector;

/**
* @var string
*/
private $pathRegex;

public function __construct(string $projectPath)
{
$this->sourceLocator = new MemoizingSourceLocator(
(new MakeLocatorForInstalledJson())(
$projectPath,
(new BetterReflection())->astLocator()
)
);

$this->reflector = new ClassReflector($this->sourceLocator);

// @todo: support https://getcomposer.org/doc/06-config.md#vendor-dir; useless as BetterReflection does not, at this moment.
$cleanPath = preg_quote(str_replace(DIRECTORY_SEPARATOR, '/', $projectPath) . '/' . 'vendor', '@');

$this->pathRegex = '@^' . $cleanPath . '/(?:composer/\.\./)?([^/]+/[^/]+)/@';
}

public function __invoke(string $symbolName): \Generator
{
$reflection = $this->sourceLocator->locateIdentifier($this->reflector, new Identifier($symbolName, new IdentifierType(IdentifierType::IDENTIFIER_CLASS)));

if (!($reflection instanceof ReflectionClass)) {
return;
}

$path = $reflection->getFileName();

if (preg_match($this->pathRegex, $path, $captures)) {
yield $captures[1];
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php declare(strict_types=1);

namespace ComposerRequireCheckerTest\DependencyGuesser;

use ComposerRequireChecker\DependencyGuesser\GuessFromComposerInstalledJson;
use PHPUnit\Framework\TestCase;

class GuessFromComposerInstalledJsonTest extends TestCase
{
/**
* @var GuessFromComposerInstalledJson
*/
private $guesser;

protected function setUp(): void
{
$this->guesser = new GuessFromComposerInstalledJson(dirname(__DIR__, 3));
}

public function testGuessVendorClass(): void
{
$result = ($this->guesser)(TestCase::class);

self::assertNotEmpty($result);
self::assertContains('phpunit/phpunit', $result);
}

public function testDoNotGuessVendorFunction(): void
{
$result = iterator_to_array(($this->guesser)('DeepCopy\deep_copy'));

self::assertEmpty($result);
}


public function testDoNotGuessClassFromProject(): void
{
$result = iterator_to_array(($this->guesser)(GuessFromComposerInstalledJson::class));

self::assertEmpty($result);
}
}

0 comments on commit c889607

Please sign in to comment.