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
73 changes: 73 additions & 0 deletions src/Parser/UseAliasVisitor.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<?php declare(strict_types = 1);

namespace PHPStan\Parser;

use Override;
use PhpParser\Node;
use PhpParser\Node\Name;
use PhpParser\Node\Stmt\GroupUse;
use PhpParser\Node\Stmt\Use_;
use PhpParser\NodeVisitorAbstract;
use PHPStan\DependencyInjection\AutowiredService;
use function count;
use function strtolower;

#[AutowiredService]
final class UseAliasVisitor extends NodeVisitorAbstract
{

public const ATTRIBUTE_NAME = 'isExplicitUseAlias';

/** @var array<string, string> alias name (original case) keyed by lowercase alias name */
private array $explicitAliases = [];

#[Override]
public function enterNode(Node $node): ?Node
{
if ($node instanceof Node\Stmt\Namespace_) {
$this->explicitAliases = [];
}

if ($node instanceof Use_ && $node->type === Use_::TYPE_NORMAL) {
foreach ($node->uses as $use) {
if ($use->alias === null) {
continue;
}

$this->explicitAliases[strtolower($use->alias->name)] = $use->alias->name;
}
}

if ($node instanceof GroupUse) {
foreach ($node->uses as $use) {
if ($use->type !== Use_::TYPE_NORMAL && $node->type !== Use_::TYPE_NORMAL) {
continue;
}
if ($use->alias === null) {
continue;
}

$this->explicitAliases[strtolower($use->alias->name)] = $use->alias->name;
}
}

if ($node instanceof Name) {
$originalName = $node->getAttribute('originalName');
if ($originalName instanceof Name) {
$originalParts = $originalName->getParts();
if (count($originalParts) === 1) {
$lowerOriginal = strtolower($originalParts[0]);
if (
isset($this->explicitAliases[$lowerOriginal])
&& $this->explicitAliases[$lowerOriginal] === $originalParts[0]
) {
$node->setAttribute(self::ATTRIBUTE_NAME, true);
}
}
}
}

return null;
}

}
10 changes: 5 additions & 5 deletions src/Rules/FunctionDefinitionCheck.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
use PHPStan\DependencyInjection\AutowiredParameter;
use PHPStan\DependencyInjection\AutowiredService;
use PHPStan\Node\Printer\NodeTypePrinter;
use PHPStan\Parser\UseAliasVisitor;
use PHPStan\Php\PhpVersion;
use PHPStan\Reflection\ExtendedParameterReflection;
use PHPStan\Reflection\ExtendedParametersAcceptor;
Expand Down Expand Up @@ -852,6 +853,10 @@ private function getOriginalClassNamePairsFromTypeNode(Identifier|Name|ComplexTy
return [];
}

if ($typeNode->getAttribute(UseAliasVisitor::ATTRIBUTE_NAME) === true) {
return [];
}

$resolvedName = $typeNode->toString();
$originalParts = $originalName->getParts();
$resolvedParts = $typeNode->getParts();
Expand All @@ -866,11 +871,6 @@ private function getOriginalClassNamePairsFromTypeNode(Identifier|Name|ComplexTy
$originalCaseClassName = $originalName->toString();
}

if (strtolower($originalCaseClassName) !== strtolower($resolvedName)) {
// use alias, not just a case difference
return [];
}

if ($originalCaseClassName === $resolvedName) {
return [];
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -662,4 +662,9 @@ public function testBug14205(): void
$this->analyse([__DIR__ . '/data/bug-14205.php'], []);
}

public function testBug14617(): void
{
$this->analyse([__DIR__ . '/data/bug-14617.php'], []);
}

}
19 changes: 19 additions & 0 deletions tests/PHPStan/Rules/Methods/data/bug-14617.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php declare(strict_types = 1);

namespace Bug14617;

class MyClass {}

namespace Bug14617\Consumer;

use Bug14617\MyClass as myclass;

function test(): myclass {
return new myclass();
}

class Foo {
public function bar(myclass $a): myclass {
return $a;
}
}
Loading