Skip to content

Commit

Permalink
Anonymous class node has valid class name
Browse files Browse the repository at this point in the history
  • Loading branch information
ondrejmirtes committed Mar 3, 2019
1 parent f217e5d commit e05ed66
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 7 deletions.
6 changes: 5 additions & 1 deletion src/Analyser/NodeScopeResolver.php
Expand Up @@ -335,7 +335,10 @@ private function processStmtNode(
if (isset($stmt->namespacedName)) {
$classScope = $scope->enterClass($this->broker->getClass((string) $stmt->namespacedName));
} elseif ($stmt instanceof Class_) {
$classScope = $scope->enterAnonymousClass($this->broker->getAnonymousClassReflection($stmt, $scope));
if ($stmt->name === null) {
throw new \PHPStan\ShouldNotHappenException();
}
$classScope = $scope->enterClass($this->broker->getClass($stmt->name->toString()));
} else {
throw new \PHPStan\ShouldNotHappenException();
}
Expand Down Expand Up @@ -1403,6 +1406,7 @@ function (Scope $scope) use ($expr, $nodeCallback, $depth): Scope {
if ($expr->class instanceof Expr) {
$scope = $this->processExprNode($expr->class, $scope, $nodeCallback, $depth + 1);
} elseif ($expr->class instanceof Class_) {
$this->broker->getAnonymousClassReflection($expr->class, $scope); // populates $expr->class->name
$this->processStmtNode($expr->class, $scope, $nodeCallback);
} elseif ($this->broker->hasClass($expr->class->toString())) {
$classReflection = $this->broker->getClass($expr->class->toString());
Expand Down
5 changes: 0 additions & 5 deletions src/Analyser/Scope.php
Expand Up @@ -1972,11 +1972,6 @@ public function isInClosureBind(): bool
return $this->inClosureBindScopeClass !== null;
}

public function enterAnonymousClass(ClassReflection $anonymousClass): self
{
return $this->enterClass($anonymousClass);
}

public function enterAnonymousFunction(
Expr\Closure $closure
): self
Expand Down
2 changes: 1 addition & 1 deletion src/Broker/Broker.php
Expand Up @@ -292,12 +292,12 @@ public function getAnonymousClassReflection(
$classNode,
$filename
);
$classNode->name = new \PhpParser\Node\Identifier($className);

if (isset(self::$anonymousClasses[$className])) {
return self::$anonymousClasses[$className];
}

$classNode->name = new \PhpParser\Node\Identifier($className);
eval($this->printer->prettyPrint([$classNode]));

self::$anonymousClasses[$className] = $this->getClassFromReflection(
Expand Down
45 changes: 45 additions & 0 deletions tests/PHPStan/Analyser/AnonymousClassNameRule.php
@@ -0,0 +1,45 @@
<?php declare(strict_types = 1);

namespace PHPStan\Analyser;

use PhpParser\Node;
use PhpParser\Node\Stmt\Class_;
use PHPStan\Broker\Broker;
use PHPStan\Rules\Rule;

class AnonymousClassNameRule implements Rule
{

/** @var Broker */
private $broker;

public function __construct(Broker $broker)
{
$this->broker = $broker;
}

public function getNodeType(): string
{
return Class_::class;
}

/**
* @param Class_ $node
* @param Scope $scope
* @return string[]
*/
public function processNode(Node $node, Scope $scope): array
{
$className = isset($node->namespacedName)
? (string) $node->namespacedName
: (string) $node->name;
try {
$this->broker->getClass($className);
} catch (\PHPStan\Broker\ClassNotFoundException $e) {
return ['not found'];
}

return ['found'];
}

}
27 changes: 27 additions & 0 deletions tests/PHPStan/Analyser/AnonymousClassNameRuleTest.php
@@ -0,0 +1,27 @@
<?php declare(strict_types = 1);

namespace PHPStan\Analyser;

use PHPStan\Rules\Rule;
use PHPStan\Testing\RuleTestCase;

class AnonymousClassNameRuleTest extends RuleTestCase
{

protected function getRule(): Rule
{
$broker = $this->createBroker();
return new AnonymousClassNameRule($broker);
}

public function testRule(): void
{
$this->analyse([__DIR__ . '/data/anonymous-class-name.php'], [
[
'found',
6,
],
]);
}

}

0 comments on commit e05ed66

Please sign in to comment.