Skip to content

Commit cb21e52

Browse files
committed
Add async visibility support
The async visibility class reflects the async accessors on properties.
1 parent 1f16892 commit cb21e52

File tree

8 files changed

+183
-2
lines changed

8 files changed

+183
-2
lines changed

composer.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@
1212
"autoload-dev": {
1313
"psr-4": {
1414
"phpDocumentor\\": [
15-
"tests/integration/",
1615
"tests/unit/phpDocumentor",
1716
"tests/bench/"
17+
],
18+
"phpDocumentor\\Reflection\\": [
19+
"tests/integration"
1820
]
1921
}
2022
},
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace phpDocumentor\Reflection\Php;
6+
7+
final class AsyncVisibility extends Visibility
8+
{
9+
public function __construct(
10+
private Visibility $readVisibility,
11+
private Visibility $writeVisibility,
12+
) {
13+
parent::__construct((string) $readVisibility);
14+
}
15+
16+
public function getReadVisibility(): Visibility
17+
{
18+
return $this->readVisibility;
19+
}
20+
21+
public function getWriteVisibility(): Visibility
22+
{
23+
return $this->writeVisibility;
24+
}
25+
}

src/phpDocumentor/Reflection/Php/Factory/Property.php

+29
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
use phpDocumentor\Reflection\DocBlockFactoryInterface;
1717
use phpDocumentor\Reflection\Location;
18+
use phpDocumentor\Reflection\Php\AsyncVisibility;
1819
use phpDocumentor\Reflection\Php\Class_;
1920
use phpDocumentor\Reflection\Php\Factory\Reducer\Reducer;
2021
use phpDocumentor\Reflection\Php\Property as PropertyDescriptor;
@@ -107,6 +108,21 @@ protected function doCreate(
107108
* Converts the visibility of the property to a valid Visibility object.
108109
*/
109110
private function buildVisibility(PropertyIterator $node): Visibility
111+
{
112+
if ($node->isAsync() === false) {
113+
return $this->buildReadVisibility($node);
114+
}
115+
116+
$readVisibility = $this->buildReadVisibility($node);
117+
$writeVisibility = $this->buildWriteVisibility($node);
118+
119+
return new AsyncVisibility(
120+
$readVisibility,
121+
$writeVisibility,
122+
);
123+
}
124+
125+
private function buildReadVisibility(PropertyIterator $node): Visibility
110126
{
111127
if ($node->isPrivate()) {
112128
return new Visibility(Visibility::PRIVATE_);
@@ -118,4 +134,17 @@ private function buildVisibility(PropertyIterator $node): Visibility
118134

119135
return new Visibility(Visibility::PUBLIC_);
120136
}
137+
138+
private function buildWriteVisibility(PropertyIterator $node): Visibility
139+
{
140+
if ($node->isPrivateSet()) {
141+
return new Visibility(Visibility::PRIVATE_);
142+
}
143+
144+
if ($node->isProtectedSet()) {
145+
return new Visibility(Visibility::PROTECTED_);
146+
}
147+
148+
return new Visibility(Visibility::PUBLIC_);
149+
}
121150
}

src/phpDocumentor/Reflection/Php/Factory/PropertyIterator.php

+58
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
use PhpParser\Node\Name;
2323
use PhpParser\Node\Stmt\Property as PropertyNode;
2424

25+
use function method_exists;
26+
2527
/**
2628
* This class acts like a combination of a PropertyNode and PropertyProperty to
2729
* be able to create property descriptors using a normal strategy.
@@ -48,6 +50,20 @@ public function isPublic(): bool
4850
return $this->property->isPublic();
4951
}
5052

53+
/**
54+
* Returns async accessor value for current property.
55+
*
56+
* This method will return the same value as {@see self::isPublic()} when your phpparser version is < 5.2
57+
*/
58+
public function isPublicSet(): bool
59+
{
60+
if ($this->isAsync() === false) {
61+
return $this->isPublic();
62+
}
63+
64+
return $this->property->isPublic();
65+
}
66+
5167
/**
5268
* returns true when the current property is protected.
5369
*/
@@ -56,6 +72,20 @@ public function isProtected(): bool
5672
return $this->property->isProtected();
5773
}
5874

75+
/**
76+
* Returns async accessor value for current property.
77+
*
78+
* This method will return the same value as {@see self::isProtected()} when your phpparser version is < 5.2
79+
*/
80+
public function isProtectedSet(): bool
81+
{
82+
if ($this->isAsync() === false) {
83+
return $this->isProtected();
84+
}
85+
86+
return $this->property->isProtectedSet();
87+
}
88+
5989
/**
6090
* returns true when the current property is private.
6191
*/
@@ -64,6 +94,34 @@ public function isPrivate(): bool
6494
return $this->property->isPrivate();
6595
}
6696

97+
/**
98+
* Returns async accessor value for current property.
99+
*
100+
* This method will return the same value as {@see self::isPrivate()} when your phpparser version is < 5.2
101+
*/
102+
public function isPrivateSet(): bool
103+
{
104+
if ($this->isAsync() === false) {
105+
return $this->isPrivate();
106+
}
107+
108+
return $this->property->isPrivateSet();
109+
}
110+
111+
/**
112+
* Returns true when current property has async accessors.
113+
*
114+
* This method will always return false when your phpparser version is < 5.2
115+
*/
116+
public function isAsync(): bool
117+
{
118+
if (method_exists($this->property, 'isPrivateSet') === false) {
119+
return false;
120+
}
121+
122+
return $this->property->isPublicSet() || $this->property->isProtected() || $this->property->isPrivateSet();
123+
}
124+
67125
/**
68126
* returns true when the current property is static.
69127
*/

src/phpDocumentor/Reflection/Php/Visibility.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
/**
2323
* Value object for visibility values of classes, properties, ect.
2424
*/
25-
final class Visibility implements Stringable
25+
class Visibility implements Stringable
2626
{
2727
/**
2828
* constant for protected visibility
+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace phpDocumentor\Reflection;
6+
7+
use phpDocumentor\Reflection\File\LocalFile;
8+
use phpDocumentor\Reflection\Php\ProjectFactory;
9+
use PHPUnit\Framework\TestCase;
10+
11+
/** @coversNothing */
12+
final class AsyncAccessorTest extends TestCase
13+
{
14+
public function testAsyncAccessor(): void
15+
{
16+
$file = __DIR__ . '/data/PHP84/AsyncAccessor.php';
17+
$projectFactory = ProjectFactory::createInstance();
18+
$project = $projectFactory->create('My project', [new LocalFile($file)]);
19+
20+
$class = $project->getFiles()[$file]->getClasses()['\AsyncAccessor'];
21+
22+
self::assertEquals(
23+
'public',
24+
$class->getProperties()['\AsyncAccessor::$pizza']->getVisibility()->getReadVisibility(),
25+
);
26+
self::assertEquals(
27+
'private',
28+
$class->getProperties()['\AsyncAccessor::$pizza']->getVisibility()->getWriteVisibility(),
29+
);
30+
}
31+
32+
public function testAsyncPropertyPromotion(): void
33+
{
34+
$file = __DIR__ . '/data/PHP84/AsyncPropertyPromotion.php';
35+
$projectFactory = ProjectFactory::createInstance();
36+
$project = $projectFactory->create('My project', [new LocalFile($file)]);
37+
38+
$class = $project->getFiles()[$file]->getClasses()['\AsyncPropertyPromotion'];
39+
40+
self::assertEquals(
41+
'public',
42+
$class->getProperties()['\AsyncPropertyPromotion::$pizza']->getVisibility()->getReadVisibility(),
43+
);
44+
self::assertEquals(
45+
'protected',
46+
$class->getProperties()['\AsyncPropertyPromotion::$pizza']->getVisibility()->getWriteVisibility(),
47+
);
48+
}
49+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
class AsyncAccessor
6+
{
7+
private(set) \Pizza $pizza;
8+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
class AsyncPropertyPromotion
6+
{
7+
public function __construct(
8+
protected(set) Pizza $pizza,
9+
) {}
10+
}

0 commit comments

Comments
 (0)