Skip to content

Commit

Permalink
OptimizedSingleFileSourceLocator - fix const handling
Browse files Browse the repository at this point in the history
  • Loading branch information
ondrejmirtes committed May 23, 2020
1 parent 5b4d07d commit 6204ebe
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 51 deletions.
25 changes: 8 additions & 17 deletions src/Reflection/BetterReflection/SourceLocator/CachingVisitor.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class CachingVisitor extends NodeVisitorAbstract
/** @var array<string, FetchedNode<\PhpParser\Node\Stmt\Function_>> */
private array $functionNodes;

/** @var array<string, FetchedNode<\PhpParser\Node\Const_|\PhpParser\Node\Expr\FuncCall>> */
/** @var array<int, FetchedNode<\PhpParser\Node\Stmt\Const_|\PhpParser\Node\Expr\FuncCall>> */
private array $constantNodes;

private ?\PhpParser\Node\Stmt\Namespace_ $currentNamespaceNode = null;
Expand Down Expand Up @@ -53,13 +53,11 @@ public function enterNode(\PhpParser\Node $node): ?int
}

if ($node instanceof \PhpParser\Node\Stmt\Const_) {
foreach ($node->consts as $constNode) {
$this->constantNodes[$constNode->namespacedName->toString()] = new FetchedNode(
$constNode,
$this->currentNamespaceNode,
$this->fileName
);
}
$this->constantNodes[] = new FetchedNode(
$node,
$this->currentNamespaceNode,
$this->fileName
);

return \PhpParser\NodeTraverser::DONT_TRAVERSE_CHILDREN;
}
Expand All @@ -85,14 +83,7 @@ public function enterNode(\PhpParser\Node $node): ?int
$this->currentNamespaceNode,
$this->fileName
);
$this->constantNodes[$constantName] = $constantNode;

if (count($node->args) === 3
&& $node->args[2]->value instanceof \PhpParser\Node\Expr\ConstFetch
&& $node->args[2]->value->name->toLowerString() === 'true'
) {
$this->constantNodes[strtolower($constantName)] = $constantNode;
}
$this->constantNodes[] = $constantNode;

return \PhpParser\NodeTraverser::DONT_TRAVERSE_CHILDREN;
}
Expand Down Expand Up @@ -131,7 +122,7 @@ public function getFunctionNodes(): array
}

/**
* @return array<string, FetchedNode<\PhpParser\Node\Const_|\PhpParser\Node\Expr\FuncCall>>
* @return array<int, FetchedNode<\PhpParser\Node\Stmt\Const_|\PhpParser\Node\Expr\FuncCall>>
*/
public function getConstantNodes(): array
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@ class FetchedNodesResult
/** @var array<string, FetchedNode<\PhpParser\Node\Stmt\Function_>> */
private array $functionNodes;

/** @var array<string, FetchedNode<\PhpParser\Node\Const_|\PhpParser\Node\Expr\FuncCall>> */
/** @var array<int, FetchedNode<\PhpParser\Node\Stmt\Const_|\PhpParser\Node\Expr\FuncCall>> */
private array $constantNodes;

private \Roave\BetterReflection\SourceLocator\Located\LocatedSource $locatedSource;

/**
* @param array<string, FetchedNode<\PhpParser\Node\Stmt\ClassLike>> $classNodes
* @param array<string, FetchedNode<\PhpParser\Node\Stmt\Function_>> $functionNodes
* @param array<string, FetchedNode<\PhpParser\Node\Const_|\PhpParser\Node\Expr\FuncCall>> $constantNodes
* @param array<int, FetchedNode<\PhpParser\Node\Stmt\Const_|\PhpParser\Node\Expr\FuncCall>> $constantNodes
* @param \Roave\BetterReflection\SourceLocator\Located\LocatedSource $locatedSource
*/
public function __construct(
Expand Down Expand Up @@ -54,7 +54,7 @@ public function getFunctionNodes(): array
}

/**
* @return array<string, FetchedNode<\PhpParser\Node\Const_|\PhpParser\Node\Expr\FuncCall>>
* @return array<int, FetchedNode<\PhpParser\Node\Stmt\Const_|\PhpParser\Node\Expr\FuncCall>>
*/
public function getConstantNodes(): array
{
Expand Down
21 changes: 3 additions & 18 deletions src/Reflection/BetterReflection/SourceLocator/FileNodesFetcher.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,25 +40,10 @@ public function fetchNodes(string $fileName): FetchedNodesResult
$this->cachingVisitor->reset($fileName);
$nodeTraverser->traverse($ast);

$classNodes = [];
foreach ($this->cachingVisitor->getClassNodes() as $className => $fetchedClassNode) {
$classNodes[$className] = $fetchedClassNode;
}

$functionNodes = [];
foreach ($this->cachingVisitor->getFunctionNodes() as $functionName => $fetchedFunctionNode) {
$functionNodes[$functionName] = $fetchedFunctionNode;
}

$constantNodes = [];
foreach ($this->cachingVisitor->getConstantNodes() as $constantName => $fetchedConstantNode) {
$constantNodes[$constantName] = $fetchedConstantNode;
}

return new FetchedNodesResult(
$classNodes,
$functionNodes,
$constantNodes,
$this->cachingVisitor->getClassNodes(),
$this->cachingVisitor->getFunctionNodes(),
$this->cachingVisitor->getConstantNodes(),
$locatedSource
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace PHPStan\Reflection\BetterReflection\SourceLocator;

use PhpParser\Node\Expr\FuncCall;
use Roave\BetterReflection\Identifier\Identifier;
use Roave\BetterReflection\Identifier\IdentifierType;
use Roave\BetterReflection\Reflection\Reflection;
Expand Down Expand Up @@ -76,21 +77,50 @@ public function locateIdentifier(Reflector $reflector, Identifier $identifier):

if ($identifier->isConstant()) {
$constantNodes = $this->fetchedNodesResult->getConstantNodes();
if (!array_key_exists($identifier->getName(), $constantNodes)) {
return null;
}

$constantReflection = $nodeToReflection->__invoke(
$reflector,
$constantNodes[$identifier->getName()]->getNode(),
$this->fetchedNodesResult->getLocatedSource(),
$constantNodes[$identifier->getName()]->getNamespace()
);
if (!$constantReflection instanceof ReflectionConstant) {
throw new \PHPStan\ShouldNotHappenException();
foreach ($constantNodes as $stmtConst) {
if ($stmtConst->getNode() instanceof FuncCall) {
$constantReflection = $nodeToReflection->__invoke(
$reflector,
$stmtConst->getNode(),
$this->fetchedNodesResult->getLocatedSource(),
$stmtConst->getNamespace()
);
if ($constantReflection === null) {
continue;
}
if (!$constantReflection instanceof ReflectionConstant) {
throw new \PHPStan\ShouldNotHappenException();
}
if ($constantReflection->getName() !== $identifier->getName()) {
continue;
}

return $constantReflection;
}

foreach (array_keys($stmtConst->getNode()->consts) as $i) {
$constantReflection = $nodeToReflection->__invoke(
$reflector,
$stmtConst->getNode(),
$this->fetchedNodesResult->getLocatedSource(),
$stmtConst->getNamespace(),
$i
);
if ($constantReflection === null) {
continue;
}
if (!$constantReflection instanceof ReflectionConstant) {
throw new \PHPStan\ShouldNotHappenException();
}
if ($constantReflection->getName() !== $identifier->getName()) {
continue;
}

return $constantReflection;
}
}

return $constantReflection;
return null;
}

throw new \PHPStan\ShouldNotHappenException();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php declare(strict_types = 1);

namespace PHPStan\Reflection\BetterReflection\SourceLocator;

use PHPStan\Testing\TestCase;
use Roave\BetterReflection\Reflector\ClassReflector;
use Roave\BetterReflection\Reflector\ConstantReflector;

class OptimizedSingleFileSourceLocatorTest extends TestCase
{

public function dataConst(): array
{
return [
[
'ConstFile\\TABLE_NAME',
'resized_images',
],
[
'ANOTHER_NAME',
'foo_images',
],
[
'ConstFile\\ANOTHER_NAME',
'bar_images',
],
];
}

/**
* @dataProvider dataConst
* @param string $constantName
* @param mixed $value
*/
public function testConst(string $constantName, $value): void
{
$factory = self::getContainer()->getByType(OptimizedSingleFileSourceLocatorFactory::class);
$locator = $factory->create(__DIR__ . '/data/const.php');
$classReflector = new ClassReflector($locator);
$constantReflector = new ConstantReflector($locator, $classReflector);
$constant = $constantReflector->reflect($constantName);
$this->assertSame($constantName, $constant->getName());
$this->assertSame($value, $constant->getValue());
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php declare(strict_types = 1);

namespace ConstFile;

const TABLE_NAME = 'resized_images';

define('ANOTHER_NAME', 'foo_images');
define('ConstFile\\ANOTHER_NAME', 'bar_images');

0 comments on commit 6204ebe

Please sign in to comment.