Skip to content

Commit 01eb32c

Browse files
committed
resolve class constant types when patching return types
1 parent 1d8d1c3 commit 01eb32c

File tree

6 files changed

+91
-1
lines changed

6 files changed

+91
-1
lines changed

src/Symfony/Component/ErrorHandler/DebugClassLoader.php

+25-1
Original file line numberDiff line numberDiff line change
@@ -849,6 +849,30 @@ private function setReturnType(string $types, string $class, string $method, str
849849
$docTypes = [];
850850

851851
foreach ($typesMap as $n => $t) {
852+
if (str_contains($n, '::')) {
853+
[$definingClass, $constantName] = explode('::', $n, 2);
854+
$definingClass = match ($definingClass) {
855+
'self', 'static', 'parent' => $class,
856+
default => $definingClass,
857+
};
858+
859+
if (!\defined($definingClass.'::'.$constantName)) {
860+
return;
861+
}
862+
863+
$constant = new \ReflectionClassConstant($definingClass, $constantName);
864+
865+
if (\PHP_VERSION_ID >= 80300 && $constantType = $constant->getType()) {
866+
if ($constantType instanceof \ReflectionNamedType) {
867+
$n = $constantType->getName();
868+
} else {
869+
return;
870+
}
871+
} else {
872+
$n = \gettype($constant->getValue());
873+
}
874+
}
875+
852876
if ('null' === $n) {
853877
$nullable = true;
854878
continue;
@@ -872,7 +896,7 @@ private function setReturnType(string $types, string $class, string $method, str
872896
continue;
873897
}
874898

875-
if (!isset($phpTypes[''])) {
899+
if (!isset($phpTypes['']) && !\in_array($n, $phpTypes, true)) {
876900
$phpTypes[] = $n;
877901
}
878902
}

src/Symfony/Component/ErrorHandler/Tests/DebugClassLoaderTest.php

+22
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,26 @@ class_exists('Test\\'.ReturnType::class, true);
401401
'Method "Symfony\Component\ErrorHandler\Tests\Fixtures\ReturnTypeParent::true()" might add "true" as a native return type declaration in the future. Do the same in child class "Test\Symfony\Component\ErrorHandler\Tests\ReturnType" now to avoid errors or add an explicit @return annotation to suppress this message.',
402402
'Method "Symfony\Component\ErrorHandler\Tests\Fixtures\ReturnTypeParent::never()" might add "never" as a native return type declaration in the future. Do the same in child class "Test\Symfony\Component\ErrorHandler\Tests\ReturnType" now to avoid errors or add an explicit @return annotation to suppress this message.',
403403
'Method "Symfony\Component\ErrorHandler\Tests\Fixtures\ReturnTypeParent::null()" might add "null" as a native return type declaration in the future. Do the same in child class "Test\Symfony\Component\ErrorHandler\Tests\ReturnType" now to avoid errors or add an explicit @return annotation to suppress this message.',
404+
'Method "Symfony\Component\ErrorHandler\Tests\Fixtures\ReturnTypeParent::classConstant()" might add "string" as a native return type declaration in the future. Do the same in child class "Test\Symfony\Component\ErrorHandler\Tests\ReturnType" now to avoid errors or add an explicit @return annotation to suppress this message.',
405+
], $deprecations);
406+
}
407+
408+
/**
409+
* @requires PHP >= 8.3
410+
*/
411+
public function testReturnTypePhp83()
412+
{
413+
$deprecations = [];
414+
set_error_handler(function ($type, $msg) use (&$deprecations) { $deprecations[] = $msg; });
415+
$e = error_reporting(E_USER_DEPRECATED);
416+
417+
class_exists('Test\\'.ReturnTypePhp83::class, true);
418+
419+
error_reporting($e);
420+
restore_error_handler();
421+
422+
$this->assertSame([
423+
'Method "Symfony\Component\ErrorHandler\Tests\Fixtures\ReturnTypeParentPhp83::classConstantWithType()" might add "string" as a native return type declaration in the future. Do the same in child class "Test\Symfony\Component\ErrorHandler\Tests\ReturnTypePhp83" now to avoid errors or add an explicit @return annotation to suppress this message.',
404424
], $deprecations);
405425
}
406426

@@ -542,6 +562,8 @@ public function ownAbstractBaseMethod() { }
542562
}');
543563
} elseif ('Test\\'.ReturnType::class === $class) {
544564
return $fixtureDir.\DIRECTORY_SEPARATOR.'ReturnType.php';
565+
} elseif ('Test\\'.ReturnTypePhp83::class === $class) {
566+
return $fixtureDir.\DIRECTORY_SEPARATOR.'ReturnTypePhp83.php';
545567
} elseif ('Test\\'.Fixtures\OutsideInterface::class === $class) {
546568
return $fixtureDir.\DIRECTORY_SEPARATOR.'OutsideInterface.php';
547569
} elseif ('Test\\'.OverrideOutsideFinalProperty::class === $class) {

src/Symfony/Component/ErrorHandler/Tests/Fixtures/ReturnType.php

+1
Original file line numberDiff line numberDiff line change
@@ -51,4 +51,5 @@ public function true() { }
5151
public function never() { }
5252
public function null() { }
5353
public function outsideMethod() { }
54+
public function classConstant() { }
5455
}

src/Symfony/Component/ErrorHandler/Tests/Fixtures/ReturnTypeParent.php

+9
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
abstract class ReturnTypeParent extends ReturnTypeGrandParent implements ReturnTypeParentInterface
66
{
7+
const FOO = 'foo';
8+
79
/**
810
* @return void
911
*/
@@ -254,4 +256,11 @@ public function null()
254256
public function notExtended()
255257
{
256258
}
259+
260+
/**
261+
* @return self::FOO
262+
*/
263+
public function classConstant()
264+
{
265+
}
257266
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
namespace Symfony\Component\ErrorHandler\Tests\Fixtures;
4+
5+
abstract class ReturnTypeParentPhp83
6+
{
7+
const string FOO = 'foo';
8+
const string|int BAR = 'bar';
9+
10+
/**
11+
* @return self::FOO
12+
*/
13+
public function classConstantWithType()
14+
{
15+
}
16+
17+
/**
18+
* @return self::BAR
19+
*/
20+
public function classConstantWithUnionType()
21+
{
22+
}
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
3+
namespace Test\Symfony\Component\ErrorHandler\Tests;
4+
5+
use Symfony\Component\ErrorHandler\Tests\Fixtures\ReturnTypeParentPhp83;
6+
7+
class ReturnTypePhp83 extends ReturnTypeParentPhp83
8+
{
9+
public function classConstantWithType() { }
10+
public function classConstantWithUnionType() { }
11+
}

0 commit comments

Comments
 (0)