Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions src/Reflection/BetterReflection/SourceLocator/CachingVisitor.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@ final class CachingVisitor extends NodeVisitorAbstract

private string $contents;

/** @var array<string, array<FetchedNode<Node\Stmt\ClassLike>>> */
/** @var array<string, list<FetchedNode<Node\Stmt\ClassLike>>> */
private array $classNodes;

/** @var array<string, array<FetchedNode<Node\Stmt\Function_>>> */
/** @var array<string, list<FetchedNode<Node\Stmt\Function_>>> */
private array $functionNodes;

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

private ?Node\Stmt\Namespace_ $currentNamespaceNode = null;
Expand Down Expand Up @@ -124,23 +124,23 @@ public function leaveNode(Node $node)
}

/**
* @return array<string, array<FetchedNode<Node\Stmt\ClassLike>>>
* @return array<string, list<FetchedNode<Node\Stmt\ClassLike>>>
*/
public function getClassNodes(): array
{
return $this->classNodes;
}

/**
* @return array<string, array<FetchedNode<Node\Stmt\Function_>>>
* @return array<string, list<FetchedNode<Node\Stmt\Function_>>>
*/
public function getFunctionNodes(): array
{
return $this->functionNodes;
}

/**
* @return array<string, array<FetchedNode<Node\Stmt\Const_|Node\Expr\FuncCall>>>
* @return array<string, list<FetchedNode<Node\Stmt\Const_|Node\Expr\FuncCall>>>
*/
public function getConstantNodes(): array
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ final class FetchedNodesResult
{

/**
* @param array<string, array<FetchedNode<Node\Stmt\ClassLike>>> $classNodes
* @param array<string, array<FetchedNode<Node\Stmt\Function_>>> $functionNodes
* @param array<string, array<FetchedNode<Node\Stmt\Const_|Node\Expr\FuncCall>>> $constantNodes
* @param array<string, list<FetchedNode<Node\Stmt\ClassLike>>> $classNodes
* @param array<string, list<FetchedNode<Node\Stmt\Function_>>> $functionNodes
* @param array<string, list<FetchedNode<Node\Stmt\Const_|Node\Expr\FuncCall>>> $constantNodes
*/
public function __construct(
private array $classNodes,
Expand All @@ -21,23 +21,23 @@ public function __construct(
}

/**
* @return array<string, array<FetchedNode<Node\Stmt\ClassLike>>>
* @return array<string, list<FetchedNode<Node\Stmt\ClassLike>>>
*/
public function getClassNodes(): array
{
return $this->classNodes;
}

/**
* @return array<string, array<FetchedNode<Node\Stmt\Function_>>>
* @return array<string, list<FetchedNode<Node\Stmt\Function_>>>
*/
public function getFunctionNodes(): array
{
return $this->functionNodes;
}

/**
* @return array<string, array<FetchedNode<Node\Stmt\Const_|Node\Expr\FuncCall>>>
* @return array<string, list<FetchedNode<Node\Stmt\Const_|Node\Expr\FuncCall>>>
*/
public function getConstantNodes(): array
{
Expand Down
83 changes: 42 additions & 41 deletions src/Reflection/SignatureMap/Php8SignatureMapProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,10 @@ final class Php8SignatureMapProvider implements SignatureMapProvider

private const DIRECTORY = __DIR__ . '/../../../vendor/phpstan/php-8-stubs';

/** @var array<string, array<string, array{ClassMethod, string}>> */
/** @var array<lowercase-string, array<lowercase-string, array{ClassMethod, string}>> */
private array $methodNodes = [];

/** @var array<string, array<string, Type|null>> */
/** @var array<lowercase-string, array<lowercase-string, Type|null>> */
private array $constantTypes = [];

private Php8StubsMap $map;
Expand Down Expand Up @@ -82,10 +82,26 @@ private function findMethodNode(string $className, string $methodName): ?array
{
$lowerClassName = strtolower($className);
$lowerMethodName = strtolower($methodName);

$this->findClassStubs($className);
if (isset($this->methodNodes[$lowerClassName][$lowerMethodName])) {
return $this->methodNodes[$lowerClassName][$lowerMethodName];
}

return null;
}

private function findClassStubs(string $className): void
{
$lowerClassName = strtolower($className);

if (
isset($this->methodNodes[$lowerClassName])
|| isset($this->constantTypes[$lowerClassName])
) {
return;
}

$stubFile = self::DIRECTORY . '/' . $this->map->classes[$lowerClassName];
$nodes = $this->fileNodesFetcher->fetchNodes($stubFile);
$classes = $nodes->getClassNodes();
Expand All @@ -98,20 +114,37 @@ private function findMethodNode(string $className, string $methodName): ?array
throw new ShouldNotHappenException(sprintf('Class %s stub not found in %s.', $className, $stubFile));
}

$this->methodNodes[$lowerClassName] = [];
$this->constantTypes[$lowerClassName] = [];

// find and remember all methods/constants within the stubFile
foreach ($class[0]->getNode()->stmts as $stmt) {
if (!$stmt instanceof ClassMethod) {
if ($stmt instanceof ClassMethod) {
if (!$this->isForCurrentVersion($stmt->attrGroups)) {
continue;
}

$this->methodNodes[$lowerClassName][$stmt->name->toLowerString()] = [$stmt, $stubFile];

continue;
}

if ($stmt->name->toLowerString() === $lowerMethodName) {
if (!$stmt instanceof ClassConst) {
continue;
}

foreach ($stmt->consts as $const) {
if ($stmt->type === null) {
continue;
}

if (!$this->isForCurrentVersion($stmt->attrGroups)) {
continue;
}
return $this->methodNodes[$lowerClassName][$lowerMethodName] = [$stmt, $stubFile];

$this->constantTypes[$lowerClassName][$const->name->toLowerString()] = ParserNodeTypeToPHPStanType::resolve($stmt->type, null);
}
}

return null;
}

/**
Expand Down Expand Up @@ -481,44 +514,12 @@ private function findConstantType(string $className, string $constantName): ?Typ
{
$lowerClassName = strtolower($className);
$lowerConstantName = strtolower($constantName);

$this->findClassStubs($className);
if (isset($this->constantTypes[$lowerClassName][$lowerConstantName])) {
return $this->constantTypes[$lowerClassName][$lowerConstantName];
}

$stubFile = self::DIRECTORY . '/' . $this->map->classes[$lowerClassName];
$nodes = $this->fileNodesFetcher->fetchNodes($stubFile);
$classes = $nodes->getClassNodes();
if (count($classes) !== 1) {
throw new ShouldNotHappenException(sprintf('Class %s stub not found in %s.', $className, $stubFile));
}

$class = $classes[$lowerClassName];
if (count($class) !== 1) {
throw new ShouldNotHappenException(sprintf('Class %s stub not found in %s.', $className, $stubFile));
}

foreach ($class[0]->getNode()->stmts as $stmt) {
if (!$stmt instanceof ClassConst) {
continue;
}

foreach ($stmt->consts as $const) {
if ($const->name->toString() !== $constantName) {
continue;
}

if (!$this->isForCurrentVersion($stmt->attrGroups)) {
continue;
}

if ($stmt->type === null) {
return null;
}

return $this->constantTypes[$lowerClassName][$lowerConstantName] = ParserNodeTypeToPHPStanType::resolve($stmt->type, null);
}
}

return null;
}

Expand Down
Loading