Skip to content

Commit

Permalink
AutoloadSourceLocator - use FileNodesFetcher
Browse files Browse the repository at this point in the history
  • Loading branch information
ondrejmirtes committed May 26, 2020
1 parent 97617f2 commit 423fd9b
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 32 deletions.
3 changes: 3 additions & 0 deletions conf/config.neon
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,9 @@ services:
arguments:
phpParser: @phpParserDecorator

-
class: PHPStan\Reflection\BetterReflection\SourceLocator\AutoloadSourceLocator

-
class: PHPStan\Reflection\BetterReflection\SourceLocator\ComposerJsonAndInstalledJsonSourceLocatorMaker

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ class BetterReflectionSourceLocatorFactory
/** @var ComposerJsonAndInstalledJsonSourceLocatorMaker */
private $composerJsonAndInstalledJsonSourceLocatorMaker;

/** @var AutoloadSourceLocator */
private $autoloadSourceLocator;

/** @var \PHPStan\DependencyInjection\Container */
private $container;

Expand Down Expand Up @@ -71,6 +74,7 @@ public function __construct(
OptimizedSingleFileSourceLocatorRepository $optimizedSingleFileSourceLocatorRepository,
OptimizedDirectorySourceLocatorRepository $optimizedDirectorySourceLocatorRepository,
ComposerJsonAndInstalledJsonSourceLocatorMaker $composerJsonAndInstalledJsonSourceLocatorMaker,
AutoloadSourceLocator $autoloadSourceLocator,
Container $container,
array $autoloadDirectories,
array $autoloadFiles,
Expand All @@ -85,6 +89,7 @@ public function __construct(
$this->optimizedSingleFileSourceLocatorRepository = $optimizedSingleFileSourceLocatorRepository;
$this->optimizedDirectorySourceLocatorRepository = $optimizedDirectorySourceLocatorRepository;
$this->composerJsonAndInstalledJsonSourceLocatorMaker = $composerJsonAndInstalledJsonSourceLocatorMaker;
$this->autoloadSourceLocator = $autoloadSourceLocator;
$this->container = $container;
$this->autoloadDirectories = $autoloadDirectories;
$this->autoloadFiles = $autoloadFiles;
Expand Down Expand Up @@ -135,7 +140,7 @@ public function create(): SourceLocator
return $this->container->getService('betterReflectionFunctionReflector');
});
$locators[] = new PhpInternalSourceLocator($astLocator, $this->phpstormStubsSourceStubber);
$locators[] = new AutoloadSourceLocator($astLocator);
$locators[] = $this->autoloadSourceLocator;
$locators[] = new PhpInternalSourceLocator($astLocator, $this->reflectionSourceStubber);
$locators[] = new EvaledCodeSourceLocator($astLocator, $this->reflectionSourceStubber);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,16 @@
use PhpParser\Node\Expr\FuncCall;
use PhpParser\Node\Name;
use PhpParser\Node\Scalar\String_;
use PHPStan\File\FileReader;
use ReflectionClass;
use ReflectionException;
use ReflectionFunction;
use Roave\BetterReflection\Identifier\Identifier;
use Roave\BetterReflection\Identifier\IdentifierType;
use Roave\BetterReflection\Reflection\Reflection;
use Roave\BetterReflection\Reflection\ReflectionConstant;
use Roave\BetterReflection\Reflector\Exception\IdentifierNotFound;
use Roave\BetterReflection\Reflector\Reflector;
use Roave\BetterReflection\SourceLocator\Ast\Exception\ParseToAstFailure;
use Roave\BetterReflection\SourceLocator\Ast\Locator as AstLocator;
use Roave\BetterReflection\SourceLocator\Ast\Strategy\NodeToReflection;
use Roave\BetterReflection\SourceLocator\Located\LocatedSource;
use Roave\BetterReflection\SourceLocator\Type\SourceLocator;
use function file_exists;
Expand All @@ -36,24 +34,24 @@
class AutoloadSourceLocator implements SourceLocator
{

private AstLocator $astLocator;
private FileNodesFetcher $fileNodesFetcher;

private static ?string $autoloadLocatedFile = null;

private static ?AstLocator $currentAstLocator = null;
private static ?FileNodesFetcher $currentFileNodesFetcher = null;

/**
* Note: the constructor has been made a 0-argument constructor because `\stream_wrapper_register`
* is a piece of trash, and doesn't accept instances, just class names.
*/
public function __construct(?AstLocator $astLocator = null)
public function __construct(?FileNodesFetcher $fileNodesFetcher = null)
{
$validLocator = $astLocator ?? self::$currentAstLocator;
if ($validLocator === null) {
$validFetcher = $fileNodesFetcher ?? self::$currentFileNodesFetcher;
if ($validFetcher === null) {
throw new \PHPStan\ShouldNotHappenException();
}

$this->astLocator = $validLocator;
$this->fileNodesFetcher = $validFetcher;
}

/**
Expand Down Expand Up @@ -115,22 +113,40 @@ public function locateIdentifier(Reflector $reflector, Identifier $identifier):

private function findReflection(Reflector $reflector, string $file, Identifier $identifier): ?Reflection
{
try {
$fileContents = FileReader::read($file);
} catch (\PHPStan\File\CouldNotReadFileException $e) {
return null;
$result = $this->fileNodesFetcher->fetchNodes($file);
$nodeToReflection = new NodeToReflection();
if ($identifier->isClass()) {
foreach ($result->getClassNodes() as $fetchedFunctionNode) {
$reflection = $nodeToReflection->__invoke(
$reflector,
$fetchedFunctionNode->getNode(),
$result->getLocatedSource(),
$fetchedFunctionNode->getNamespace()
);
if ($reflection === null) {
continue;
}

return $reflection;
}
}

$locatedSource = new LocatedSource(
$fileContents,
$file
);

try {
return $this->astLocator->findReflection($reflector, $locatedSource, $identifier);
} catch (IdentifierNotFound $exception) {
return null;
if ($identifier->isFunction()) {
foreach ($result->getFunctionNodes() as $fetchedFunctionNode) {
$reflection = $nodeToReflection->__invoke(
$reflector,
$fetchedFunctionNode->getNode(),
$result->getLocatedSource(),
$fetchedFunctionNode->getNamespace()
);
if ($reflection === null) {
continue;
}

return $reflection;
}
}

return null;
}

public function locateIdentifiersByType(Reflector $reflector, IdentifierType $identifierType): array
Expand Down Expand Up @@ -172,7 +188,7 @@ private function locateClassByName(string $className): ?array
}

self::$autoloadLocatedFile = null;
self::$currentAstLocator = $this->astLocator; // passing the locator on to the implicitly instantiated `self`
self::$currentFileNodesFetcher = $this->fileNodesFetcher; // passing the locator on to the implicitly instantiated `self`
set_error_handler(static function (int $errno, string $errstr): bool {
throw new \PHPStan\Reflection\BetterReflection\SourceLocator\AutoloadSourceLocatorException();
});
Expand Down
6 changes: 5 additions & 1 deletion src/Testing/TestCaseSourceLocatorFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ class TestCaseSourceLocatorFactory

private ComposerJsonAndInstalledJsonSourceLocatorMaker $composerJsonAndInstalledJsonSourceLocatorMaker;

private AutoloadSourceLocator $autoloadSourceLocator;

private \PhpParser\Parser $phpParser;

private PhpStormStubsSourceStubber $phpstormStubsSourceStubber;
Expand All @@ -32,13 +34,15 @@ class TestCaseSourceLocatorFactory
public function __construct(
Container $container,
ComposerJsonAndInstalledJsonSourceLocatorMaker $composerJsonAndInstalledJsonSourceLocatorMaker,
AutoloadSourceLocator $autoloadSourceLocator,
\PhpParser\Parser $phpParser,
PhpStormStubsSourceStubber $phpstormStubsSourceStubber,
ReflectionSourceStubber $reflectionSourceStubber
)
{
$this->container = $container;
$this->composerJsonAndInstalledJsonSourceLocatorMaker = $composerJsonAndInstalledJsonSourceLocatorMaker;
$this->autoloadSourceLocator = $autoloadSourceLocator;
$this->phpParser = $phpParser;
$this->phpstormStubsSourceStubber = $phpstormStubsSourceStubber;
$this->reflectionSourceStubber = $reflectionSourceStubber;
Expand Down Expand Up @@ -69,7 +73,7 @@ public function create(): SourceLocator
});

$locators[] = new PhpInternalSourceLocator($astLocator, $this->phpstormStubsSourceStubber);
$locators[] = new AutoloadSourceLocator($astLocator);
$locators[] = $this->autoloadSourceLocator;
$locators[] = new PhpInternalSourceLocator($astLocator, $this->reflectionSourceStubber);
$locators[] = new EvaledCodeSourceLocator($astLocator, $this->reflectionSourceStubber);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,31 @@

namespace PHPStan\Reflection\BetterReflection\SourceLocator;

use PHPStan\Parser\PhpParserDecorator;
use PHPStan\Testing\TestCase;
use Roave\BetterReflection\Reflector\ClassReflector;
use Roave\BetterReflection\Reflector\FunctionReflector;
use Roave\BetterReflection\SourceLocator\Ast\Locator;
use TestSingleFileSourceLocator\AFoo;

function testFunctionForLocator()
{

}

class AutoloadSourceLocatorTest extends TestCase
{

public function testAutoloadEverythingInFile(): void
{
/** @var FunctionReflector $functionReflector */
$functionReflector = null;
$astLocator = new Locator(new PhpParserDecorator($this->getParser()), function () use (&$functionReflector): FunctionReflector {
return $functionReflector;
});
$locator = new AutoloadSourceLocator($astLocator);
$locator = new AutoloadSourceLocator(self::getContainer()->getByType(FileNodesFetcher::class));
$classReflector = new ClassReflector($locator);
$functionReflector = new FunctionReflector($locator, $classReflector);
$aFoo = $classReflector->reflect(AFoo::class);
$this->assertSame('a.php', basename($aFoo->getFileName()));

$testFunctionReflection = $functionReflector->reflect('PHPStan\\Reflection\\BetterReflection\\SourceLocator\testFunctionForLocator');
$this->assertSame(__FILE__, $testFunctionReflection->getFileName());
}

}

0 comments on commit 423fd9b

Please sign in to comment.