Skip to content

Commit 8a684e4

Browse files
authored
Merge pull request #663 from phpDocumentor/feature/async-accessors
Add async visibility support
2 parents 1f16892 + df4b1b5 commit 8a684e4

File tree

20 files changed

+316
-13
lines changed

20 files changed

+316
-13
lines changed

composer.json

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,27 @@
55
"homepage": "http://www.phpdoc.org",
66
"license": "MIT",
77
"autoload": {
8+
"files": [
9+
"src/php-parser/Modifiers.php"
10+
],
811
"psr-4": {
912
"phpDocumentor\\": "src/phpDocumentor"
1013
}
1114
},
1215
"autoload-dev": {
1316
"psr-4": {
1417
"phpDocumentor\\": [
15-
"tests/integration/",
1618
"tests/unit/phpDocumentor",
1719
"tests/bench/"
20+
],
21+
"phpDocumentor\\Reflection\\": [
22+
"tests/integration"
1823
]
1924
}
2025
},
2126
"require": {
2227
"php": "8.1.*|8.2.*|8.3.*|8.4.*",
28+
"composer-runtime-api": "^2",
2329
"nikic/php-parser": "~4.18 || ^5.0",
2430
"phpdocumentor/reflection-common": "^2.1",
2531
"phpdocumentor/reflection-docblock": "^5",
@@ -30,6 +36,7 @@
3036
"require-dev": {
3137
"dealerdirect/phpcodesniffer-composer-installer": "^1.0",
3238
"doctrine/coding-standard": "^13.0",
39+
"eliashaeussler/phpunit-attributes": "^1.7",
3340
"mikey179/vfsstream": "~1.2",
3441
"mockery/mockery": "~1.6.0",
3542
"phpspec/prophecy-phpunit": "^2.0",

composer.lock

Lines changed: 58 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

phpstan.neon

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ parameters:
22
paths:
33
- src
44

5-
checkGenericClassInNonGenericObjectType: false
65
level: max
76
ignoreErrors:
87

phpunit.xml.dist

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.5/phpunit.xsd" colors="true" bootstrap="vendor/autoload.php" beStrictAboutOutputDuringTests="true" beStrictAboutChangesToGlobalState="true" cacheDirectory=".phpunit.cache" requireCoverageMetadata="true" beStrictAboutCoverageMetadata="false">
3+
<extensions>
4+
<bootstrap class="EliasHaeussler\PHPUnitAttributes\PHPUnitAttributesExtension" />
5+
</extensions>
36
<coverage>
47
<report>
58
<clover outputFile="build/logs/clover.xml"/>

src/php-parser/Modifiers.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpParser;
6+
7+
use Composer\InstalledVersions;
8+
9+
use function strpos;
10+
11+
if (strpos(InstalledVersions::getVersion('nikic/php-parser') ?? '', '4') === 0) {
12+
/**
13+
* Modifiers used (as a bit mask) by various flags subnodes, for example on classes, functions,
14+
* properties and constants.
15+
*/
16+
final class Modifiers
17+
{
18+
public const PUBLIC = 1;
19+
public const PROTECTED = 2;
20+
public const PRIVATE = 4;
21+
public const STATIC = 8;
22+
public const ABSTRACT = 16;
23+
public const FINAL = 32;
24+
public const READONLY = 64;
25+
public const PUBLIC_SET = 128;
26+
public const PROTECTED_SET = 256;
27+
public const PRIVATE_SET = 512;
28+
29+
public const VISIBILITY_SET_MASK = self::PUBLIC_SET | self::PROTECTED_SET | self::PRIVATE_SET;
30+
}
31+
}

src/phpDocumentor/Reflection/NodeVisitor/ElementNameResolver.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434

3535
final class ElementNameResolver extends NodeVisitorAbstract
3636
{
37+
/** @var SplDoublyLinkedList<Node\Identifier|string|null> */
3738
private SplDoublyLinkedList $parts;
3839

3940
public function __construct()
Lines changed: 25 additions & 0 deletions
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/ConstructorPromotion.php

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,16 @@
88
use phpDocumentor\Reflection\DocBlockFactoryInterface;
99
use phpDocumentor\Reflection\Fqsen;
1010
use phpDocumentor\Reflection\Location;
11+
use phpDocumentor\Reflection\Php\AsyncVisibility;
1112
use phpDocumentor\Reflection\Php\Class_ as ClassElement;
1213
use phpDocumentor\Reflection\Php\Factory\Reducer\Reducer;
1314
use phpDocumentor\Reflection\Php\ProjectFactoryStrategy;
1415
use phpDocumentor\Reflection\Php\Property;
1516
use phpDocumentor\Reflection\Php\StrategyContainer;
1617
use phpDocumentor\Reflection\Php\Visibility;
18+
use PhpParser\Modifiers;
1719
use PhpParser\Node\Expr\Variable;
1820
use PhpParser\Node\Param;
19-
use PhpParser\Node\Stmt\Class_;
2021
use PhpParser\Node\Stmt\ClassMethod;
2122
use PhpParser\PrettyPrinter\Standard as PrettyPrinter;
2223
use Webmozart\Assert\Assert;
@@ -91,11 +92,36 @@ private function promoteParameterToProperty(ContextStack $context, StrategyConta
9192

9293
private function buildPropertyVisibilty(int $flags): Visibility
9394
{
94-
if ((bool) ($flags & Class_::MODIFIER_PRIVATE) === true) {
95+
if ((bool) ($flags & Modifiers::VISIBILITY_SET_MASK) !== false) {
96+
return new AsyncVisibility(
97+
$this->buildReadVisibility($flags),
98+
$this->buildWriteVisibility($flags),
99+
);
100+
}
101+
102+
return $this->buildReadVisibility($flags);
103+
}
104+
105+
private function buildReadVisibility(int $flags): Visibility
106+
{
107+
if ((bool) ($flags & Modifiers::PRIVATE) === true) {
108+
return new Visibility(Visibility::PRIVATE_);
109+
}
110+
111+
if ((bool) ($flags & Modifiers::PROTECTED) === true) {
112+
return new Visibility(Visibility::PROTECTED_);
113+
}
114+
115+
return new Visibility(Visibility::PUBLIC_);
116+
}
117+
118+
private function buildWriteVisibility(int $flags): Visibility
119+
{
120+
if ((bool) ($flags & Modifiers::PRIVATE_SET) === true) {
95121
return new Visibility(Visibility::PRIVATE_);
96122
}
97123

98-
if ((bool) ($flags & Class_::MODIFIER_PROTECTED) === true) {
124+
if ((bool) ($flags & Modifiers::PROTECTED_SET) === true) {
99125
return new Visibility(Visibility::PROTECTED_);
100126
}
101127

@@ -104,6 +130,6 @@ private function buildPropertyVisibilty(int $flags): Visibility
104130

105131
private function readOnly(int $flags): bool
106132
{
107-
return (bool) ($flags & Class_::MODIFIER_READONLY) === true;
133+
return (bool) ($flags & Modifiers::READONLY) === true;
108134
}
109135
}

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

Lines changed: 29 additions & 0 deletions
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
}

0 commit comments

Comments
 (0)