-
-
Notifications
You must be signed in to change notification settings - Fork 50
Expand file tree
/
Copy pathFinalPromotedPropertyTest.php
More file actions
124 lines (104 loc) · 4.43 KB
/
Copy pathFinalPromotedPropertyTest.php
File metadata and controls
124 lines (104 loc) · 4.43 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
<?php
declare(strict_types=1);
/**
* Parser Reflection API
*
* @copyright Copyright 2025, Lisachenko Alexander <lisachenko.it@gmail.com>
*
* This source file is subject to the license that is bundled
* with this source code in the file LICENSE.
*/
namespace Go\ParserReflection;
use Go\ParserReflection\Locator\CallableLocator;
use Go\ParserReflection\Locator\ComposerLocator;
use PHPUnit\Framework\TestCase;
/**
* Verifies that the PHP 8.5 `final` modifier on promoted constructor properties is reflected.
*
* The stub file uses PHP 8.5 syntax, therefore it must never be included or required,
* it is only allowed to be parsed by the reflection engine.
*/
class FinalPromotedPropertyTest extends TestCase
{
public const STUB_FILE = '/Stub/FileWithFinalPromoted85.php';
public const STUB_CLASS = 'Go\ParserReflection\Stub\ClassWithFinalPromotedProperty85';
private string $stubFileName;
protected function setUp(): void
{
$resolvedFileName = stream_resolve_include_path(__DIR__ . self::STUB_FILE);
$this->assertIsString($resolvedFileName, 'PHP 8.5 stub file should be available');
$this->stubFileName = $resolvedFileName;
}
protected function tearDown(): void
{
// Restores the default locator for the following tests, because some of them replace it
ReflectionEngine::init(new ComposerLocator());
}
public function testFinalPromotedPropertyIsFinal(): void
{
$parsedClass = $this->getParsedClass();
$parsedProperty = $parsedClass->getProperty('finalPromoted');
$this->assertTrue($parsedProperty->isPromoted(), 'Property should be promoted');
$this->assertTrue($parsedProperty->isFinal(), 'Promoted property should be final');
$this->assertSame(
\ReflectionProperty::IS_FINAL,
$parsedProperty->getModifiers() & \ReflectionProperty::IS_FINAL,
'Modifiers should contain the IS_FINAL bit'
);
$this->assertTrue($parsedProperty->isPublic());
}
public function testPlainPromotedPropertyIsNotFinal(): void
{
$parsedClass = $this->getParsedClass();
$parsedProperty = $parsedClass->getProperty('plainPromoted');
$this->assertTrue($parsedProperty->isPromoted(), 'Property should be promoted');
$this->assertFalse($parsedProperty->isFinal(), 'Plain promoted property should not be final');
$this->assertSame(
0,
$parsedProperty->getModifiers() & \ReflectionProperty::IS_FINAL,
'Modifiers should not contain the IS_FINAL bit'
);
}
public function testFinalReadonlyPromotedPropertyIsFinal(): void
{
$parsedClass = $this->getParsedClass();
$parsedProperty = $parsedClass->getProperty('finalReadonlyPromoted');
$this->assertTrue($parsedProperty->isFinal());
$this->assertTrue($parsedProperty->isReadOnly());
$this->assertTrue($parsedProperty->isProtected());
$this->assertSame(
\ReflectionProperty::IS_FINAL,
$parsedProperty->getModifiers() & \ReflectionProperty::IS_FINAL
);
}
public function testPrivateSetPromotedPropertyRemainsImplicitlyFinal(): void
{
$parsedClass = $this->getParsedClass();
$parsedProperty = $parsedClass->getProperty('privateSetPromoted');
$this->assertTrue($parsedProperty->isPrivateSet(), 'Property should have private(set) visibility');
$this->assertTrue($parsedProperty->isFinal(), 'Property with private(set) is implicitly final');
$this->assertSame(
\ReflectionProperty::IS_FINAL,
$parsedProperty->getModifiers() & \ReflectionProperty::IS_FINAL
);
}
public function testStubClassIsNeverLoaded(): void
{
$parsedClass = $this->getParsedClass();
$this->assertSame(self::STUB_CLASS, $parsedClass->getName());
$this->assertFalse(class_exists(self::STUB_CLASS, false), 'Stub class should not be loaded');
}
/**
* Reflects the stub class without triggering autoloading of the PHP 8.5 source
*/
private function getParsedClass(): ReflectionClass
{
$stubFileName = $this->stubFileName;
$locator = new CallableLocator(
static fn(string $className): false|string
=> $className === self::STUB_CLASS ? $stubFileName : false
);
ReflectionEngine::init($locator);
return new ReflectionClass(self::STUB_CLASS);
}
}