Skip to content

Commit

Permalink
Display parent class name for anonymous class like native php does
Browse files Browse the repository at this point in the history
  • Loading branch information
mvorisek authored and ondrejmirtes committed Sep 19, 2024
1 parent 9a9abe3 commit 8f2307e
Show file tree
Hide file tree
Showing 8 changed files with 90 additions and 9 deletions.
16 changes: 14 additions & 2 deletions src/Reflection/BetterReflection/BetterReflectionProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
use PHPStan\Type\Generic\TemplateTypeMap;
use PHPStan\Type\Type;
use function array_key_exists;
use function array_key_first;
use function array_map;
use function base64_decode;
use function in_array;
Expand Down Expand Up @@ -217,12 +218,23 @@ public function getAnonymousClassReflection(Node\Stmt\Class_ $classNode, Scope $
null,
);

$displayParentName = $reflectionClass->getParentClassName();
if ($displayParentName === null) {
// https://3v4l.org/6FBuP
$classInterfaceNames = $reflectionClass->getInterfaceNames();
if ($classInterfaceNames !== []) {
$displayParentName = $classInterfaceNames[array_key_first($classInterfaceNames)];
} else {
$displayParentName = 'class';
}
}

/** @var int|null $classLineIndex */
$classLineIndex = $classNode->getAttribute(AnonymousClassVisitor::ATTRIBUTE_LINE_INDEX);
if ($classLineIndex === null) {
$displayName = sprintf('class@anonymous/%s:%s', $filename, $classNode->getStartLine());
$displayName = sprintf('%s@anonymous/%s:%s', $displayParentName, $filename, $classNode->getStartLine());
} else {
$displayName = sprintf('class@anonymous/%s:%s:%d', $filename, $classNode->getStartLine(), $classLineIndex);
$displayName = sprintf('%s@anonymous/%s:%s:%d', $displayParentName, $filename, $classNode->getStartLine(), $classLineIndex);
}

self::$anonymousClasses[$className] = new ClassReflection(
Expand Down
4 changes: 2 additions & 2 deletions tests/PHPStan/Analyser/AnalyserIntegrationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -541,9 +541,9 @@ public function testBug6442(): void
{
$errors = $this->runAnalyse(__DIR__ . '/data/bug-6442.php');
$this->assertCount(2, $errors);
$this->assertSame('Dumped type: \'Bug6442\\\A\'', $errors[0]->getMessage());
$this->assertSame('Dumped type: \'Bug6442\\\B\'', $errors[0]->getMessage());
$this->assertSame(9, $errors[0]->getLine());
$this->assertSame('Dumped type: \'Bug6442\\\B\'', $errors[1]->getMessage());
$this->assertSame('Dumped type: \'Bug6442\\\A\'', $errors[1]->getMessage());
$this->assertSame(9, $errors[1]->getLine());
}

Expand Down
4 changes: 2 additions & 2 deletions tests/PHPStan/Levels/data/stubValidator-0.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@
"ignorable": false
},
{
"message": "Method class@anonymous/stubValidator/stubs.php:27::doFoo() has no return type specified.",
"message": "Method ArrayIterator@anonymous/stubValidator/stubs.php:27::doFoo() has no return type specified.",
"line": 30,
"ignorable": false
},
{
"message": "Parameter $foo of method class@anonymous/stubValidator/stubs.php:27::doFoo() has invalid type StubValidator\\Foooooooo.",
"message": "Parameter $foo of method ArrayIterator@anonymous/stubValidator/stubs.php:27::doFoo() has invalid type StubValidator\\Foooooooo.",
"line": 30,
"ignorable": false
}
Expand Down
49 changes: 49 additions & 0 deletions tests/PHPStan/Reflection/AnonymousClassReflectionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,55 @@ public function testReflection(): void
]),
9,
],
[
implode("\n", [
'name: AnonymousClass1d622e3ff3a656e68d55eafbd25eaef1',
'display name: AnonymousClassReflectionTest\A@anonymous/tests/PHPStan/Reflection/data/anonymous-classes.php:17:1',
]),
17,
],
[
implode("\n", [
'name: AnonymousClass6e1acc8e948827c8d0439a2225fdbdd0',
'display name: AnonymousClassReflectionTest\A@anonymous/tests/PHPStan/Reflection/data/anonymous-classes.php:17:2',
]),
17,
],
[
implode("\n", [
'name: AnonymousClass2a49db3d44479dddd8beaea4ea8131fb',
'display name: AnonymousClassReflectionTest\A@anonymous/tests/PHPStan/Reflection/data/anonymous-classes.php:19:1',
]),
19,
],
[
implode("\n", [
'name: AnonymousClass337463cf86ee25e526f445630960b336',
'display name: AnonymousClassReflectionTest\A@anonymous/tests/PHPStan/Reflection/data/anonymous-classes.php:19:2',
]),
19,
],
[
implode("\n", [
'name: AnonymousClassda3e79cc45f826d60295f848abab37e7',
'display name: AnonymousClassReflectionTest\U@anonymous/tests/PHPStan/Reflection/data/anonymous-classes.php:29',
]),
29,
],
[
implode("\n", [
'name: AnonymousClassc06612bf3776bbe5e50870a8c3151186',
'display name: AnonymousClassReflectionTest\U@anonymous/tests/PHPStan/Reflection/data/anonymous-classes.php:31',
]),
31,
],
[
implode("\n", [
'name: AnonymousClassbee6eba8c721d73d649fcc9d361f5902',
'display name: AnonymousClassReflectionTest\V@anonymous/tests/PHPStan/Reflection/data/anonymous-classes.php:33',
]),
33,
],
]);
}

Expand Down
20 changes: 20 additions & 0 deletions tests/PHPStan/Reflection/data/anonymous-classes.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,23 @@ public function __construct(object $object)
{
}
};

class A {}

new class extends A {}; new class extends A {};

new class (new class extends A {}) extends A {
public function __construct(object $object)
{
}
};

interface U {}

interface V {}

new class implements U {};

new class implements U, V {};

new class implements V, U {};
2 changes: 1 addition & 1 deletion tests/PHPStan/Rules/Classes/RequireImplementsRuleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public function testRule(): void
137,
],
[
'Trait IncompatibleRequireImplements\ValidPsalmTrait requires using class to implement IncompatibleRequireImplements\RequiredInterface2, but class@anonymous/tests/PHPStan/Rules/PhpDoc/data/incompatible-require-implements.php:164 does not.',
'Trait IncompatibleRequireImplements\ValidPsalmTrait requires using class to implement IncompatibleRequireImplements\RequiredInterface2, but IncompatibleRequireImplements\RequiredInterface@anonymous/tests/PHPStan/Rules/PhpDoc/data/incompatible-require-implements.php:164 does not.',
164,
],
[
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public function testRule(): void
24,
],
[
'Non-abstract class class@anonymous/tests/PHPStan/Rules/Methods/data/missing-method-impl.php:41 contains abstract method doFoo() from interface MissingMethodImpl\Foo.',
'Non-abstract class MissingMethodImpl\Foo@anonymous/tests/PHPStan/Rules/Methods/data/missing-method-impl.php:41 contains abstract method doFoo() from interface MissingMethodImpl\Foo.',
41,
],
]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ public function testRedeclaredReadonlyProperties(): void
70,
],
[
'Readonly property class@anonymous/tests/PHPStan/Rules/Properties/data/redeclare-readonly-property.php:117::$myProp is already assigned.',
'Readonly property RedeclareReadonlyProperty\A@anonymous/tests/PHPStan/Rules/Properties/data/redeclare-readonly-property.php:117::$myProp is already assigned.',
121,
],
[
Expand Down

0 comments on commit 8f2307e

Please sign in to comment.