Skip to content

Commit 9a38ef3

Browse files
committed
[+]: check for "readonly" settings
+ use php types + replace deprecated "parts" property from nikic/PHP-Parser
1 parent ba9bec6 commit 9a38ef3

20 files changed

+211
-345
lines changed

src/voku/SimplePhpParser/Model/BasePHPClass.php

Lines changed: 11 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -11,45 +11,29 @@ abstract class BasePHPClass extends BasePHPElement
1111
/**
1212
* @var array<string, PHPMethod>
1313
*/
14-
public $methods = [];
14+
public array $methods = [];
1515

1616
/**
1717
* @var array<string, PHPProperty>
1818
*/
19-
public $properties = [];
19+
public array $properties = [];
2020

2121
/**
2222
* @var array<string, PHPConst>
2323
*/
24-
public $constants = [];
24+
public array $constants = [];
2525

26-
/**
27-
* @var null|bool
28-
*/
29-
public $is_final;
26+
public ?bool $is_final = null;
3027

31-
/**
32-
* @var null|bool
33-
*/
34-
public $is_abstract;
28+
public ?bool $is_abstract = null;
3529

36-
/**
37-
* @var null|bool
38-
*/
39-
public $is_anonymous;
30+
public ?bool $is_readonly = null;
4031

41-
/**
42-
* @var null|bool
43-
*/
44-
public $is_cloneable;
32+
public ?bool $is_anonymous = null;
4533

46-
/**
47-
* @var null|bool
48-
*/
49-
public $is_instantiable;
34+
public ?bool $is_cloneable = null;
5035

51-
/**
52-
* @var null|bool
53-
*/
54-
public $is_iterable;
36+
public ?bool $is_instantiable = null;
37+
38+
public ?bool $is_iterable = null;
5539
}

src/voku/SimplePhpParser/Model/BasePHPElement.php

Lines changed: 27 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -5,46 +5,29 @@
55
namespace voku\SimplePhpParser\Model;
66

77
use PhpParser\Node;
8+
use PhpParser\Node\Name;
89
use PhpParser\Node\Stmt\Namespace_;
910
use PhpParser\NodeAbstract;
1011
use voku\SimplePhpParser\Parsers\Helper\ParserContainer;
1112

1213
abstract class BasePHPElement
1314
{
14-
/**
15-
* @var string
16-
*/
17-
public $name = '';
15+
public string $name = '';
1816

1917
/**
2018
* @var string[]
2119
*/
22-
public $parseError = [];
20+
public array $parseError = [];
2321

24-
/**
25-
* @var int|null
26-
*/
27-
public $line;
22+
public ?int $line = null;
2823

29-
/**
30-
* @var string|null
31-
*/
32-
public $file;
24+
public ?string $file = null;
3325

34-
/**
35-
* @var int|null
36-
*/
37-
public $pos;
26+
public ?int $pos = null;
3827

39-
/**
40-
* @var ParserContainer
41-
*/
42-
public $parserContainer;
28+
public ParserContainer $parserContainer;
4329

44-
/**
45-
* @param ParserContainer $parserContainer
46-
*/
47-
public function __construct($parserContainer)
30+
public function __construct(ParserContainer $parserContainer)
4831
{
4932
$this->parserContainer = $parserContainer;
5033
}
@@ -66,11 +49,15 @@ abstract public function readObjectFromPhpNode($mixed_1, $mixed_2 = null);
6649

6750
protected function getConstantFQN(NodeAbstract $node, string $nodeName): string
6851
{
69-
// init
70-
$namespace = '';
71-
72-
if ($node->getAttribute('parent') instanceof Namespace_ && !empty($node->getAttribute('parent')->name)) {
73-
$namespace = '\\' . \implode('\\', $node->getAttribute('parent')->name->parts) . '\\';
52+
$parent = $node->getAttribute('parent');
53+
if (
54+
$parent instanceof Namespace_
55+
&&
56+
$parent->name instanceof Name
57+
) {
58+
$namespace = '\\' . \implode('\\', $parent->name->getParts()) . '\\';
59+
} else {
60+
$namespace = '';
7461
}
7562

7663
return $namespace . $nodeName;
@@ -93,20 +80,21 @@ protected static function getFQN($node): string
9380
&&
9481
\property_exists($node, 'namespacedName')
9582
) {
96-
/** @psalm-suppress NoInterfaceProperties ? */
97-
$fqn = $node->namespacedName === null
98-
? $node->name->parts[0] ?? ''
99-
: \implode('\\', $node->namespacedName->parts);
83+
if ($node->namespacedName) {
84+
$fqn = \implode('\\', $node->namespacedName->getParts());
85+
} elseif (\property_exists($node, 'name') && $node->name) {
86+
var_dump($node->name);
87+
$fqn = $node->name->name;
88+
}
10089
}
10190

91+
/** @noinspection PhpSillyAssignmentInspection - hack for phpstan */
92+
/** @var class-string $fqn */
93+
$fqn = $fqn;
94+
10295
return $fqn;
10396
}
10497

105-
/**
106-
* @param \PhpParser\Node $node
107-
*
108-
* @return void
109-
*/
11098
protected function prepareNode(Node $node): void
11199
{
112100
$this->line = $node->getLine();

src/voku/SimplePhpParser/Model/PHPClass.php

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -12,25 +12,21 @@
1212
class PHPClass extends BasePHPClass
1313
{
1414
/**
15-
* @var string
16-
*
1715
* @phpstan-var class-string
1816
*/
19-
public $name;
17+
public string $name;
2018

2119
/**
22-
* @var string|null
23-
*
2420
* @phpstan-var class-string|null
2521
*/
26-
public $parentClass;
22+
public ?string $parentClass = null;
2723

2824
/**
2925
* @var string[]
3026
*
3127
* @phpstan-var class-string[]
3228
*/
33-
public $interfaces = [];
29+
public array $interfaces = [];
3430

3531
/**
3632
* @param Class_ $node
@@ -48,6 +44,10 @@ public function readObjectFromPhpNode($node, $dummy = null): self
4844

4945
$this->is_abstract = $node->isAbstract();
5046

47+
if (method_exists($node, 'isReadOnly')) {
48+
$this->is_readonly = $node->isReadOnly();
49+
}
50+
5151
$this->is_anonymous = $node->isAnonymous();
5252

5353
$classExists = false;
@@ -66,13 +66,10 @@ public function readObjectFromPhpNode($node, $dummy = null): self
6666
$this->collectTags($node);
6767

6868
if (!empty($node->extends)) {
69-
$classExtended = '';
70-
foreach ($node->extends->parts as $part) {
71-
$classExtended .= '\\' . $part;
72-
}
69+
$classExtended = implode('\\', $node->extends->getParts());
7370
/** @noinspection PhpSillyAssignmentInspection - hack for phpstan */
7471
/** @var class-string $classExtended */
75-
$classExtended = \ltrim($classExtended, '\\');
72+
$classExtended = $classExtended;
7673
$this->parentClass = $classExtended;
7774
}
7875

@@ -89,6 +86,10 @@ public function readObjectFromPhpNode($node, $dummy = null): self
8986
} else {
9087
$this->properties[$propertyNameTmp] = (new PHPProperty($this->parserContainer))->readObjectFromPhpNode($property, $this->name);
9188
}
89+
90+
if ($this->is_readonly) {
91+
$this->properties[$propertyNameTmp]->is_readonly = true;
92+
}
9293
}
9394

9495
foreach ($node->getMethods() as $method) {
@@ -107,11 +108,7 @@ public function readObjectFromPhpNode($node, $dummy = null): self
107108

108109
if (!empty($node->implements)) {
109110
foreach ($node->implements as $interfaceObject) {
110-
$interfaceFQN = '';
111-
foreach ($interfaceObject->parts as $interface) {
112-
$interfaceFQN .= '\\' . $interface;
113-
}
114-
$interfaceFQN = \ltrim($interfaceFQN, '\\');
111+
$interfaceFQN = implode('\\', $interfaceObject->getParts());
115112
/** @noinspection PhpSillyAssignmentInspection - hack for phpstan */
116113
/** @var class-string $interfaceFQN */
117114
$interfaceFQN = $interfaceFQN;
@@ -147,6 +144,10 @@ public function readObjectFromReflection($clazz): self
147144

148145
$this->is_abstract = $clazz->isAbstract();
149146

147+
if (method_exists($clazz, 'isReadOnly')) {
148+
$this->is_readonly = $clazz->isReadOnly();
149+
}
150+
150151
$this->is_anonymous = $clazz->isAnonymous();
151152

152153
$this->is_cloneable = $clazz->isCloneable();
@@ -181,6 +182,10 @@ public function readObjectFromReflection($clazz): self
181182
foreach ($clazz->getProperties() as $property) {
182183
$propertyPhp = (new PHPProperty($this->parserContainer))->readObjectFromReflection($property);
183184
$this->properties[$propertyPhp->name] = $propertyPhp;
185+
186+
if ($this->is_readonly) {
187+
$this->properties[$propertyPhp->name]->is_readonly = true;
188+
}
184189
}
185190

186191
foreach ($clazz->getInterfaceNames() as $interfaceName) {
@@ -360,8 +365,6 @@ public function getMethodsInfo(
360365

361366
/**
362367
* @param Doc|string $doc
363-
*
364-
* @return void
365368
*/
366369
private function readPhpDocProperties($doc): void
367370
{

src/voku/SimplePhpParser/Model/PHPConst.php

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace voku\SimplePhpParser\Model;
66

77
use PhpParser\Node\Const_;
8+
use PhpParser\Node\Name;
89
use PhpParser\Node\Stmt\ClassConst;
910
use PhpParser\Node\Stmt\Namespace_;
1011
use PhpParser\NodeAbstract;
@@ -15,10 +16,7 @@ class PHPConst extends BasePHPElement
1516
{
1617
use PHPDocElement;
1718

18-
/**
19-
* @var string|null
20-
*/
21-
public $parentName;
19+
public ?string $parentName = null;
2220

2321
/**
2422
* @var array|bool|float|int|string|null
@@ -27,15 +25,9 @@ class PHPConst extends BasePHPElement
2725
*/
2826
public $value;
2927

30-
/**
31-
* @var string|null
32-
*/
33-
public $visibility;
28+
public ?string $visibility = null;
3429

35-
/**
36-
* @var string|null
37-
*/
38-
public $type;
30+
public ?string $type = null;
3931

4032
/**
4133
* @param Const_ $node
@@ -111,8 +103,12 @@ protected function getConstantFQN(NodeAbstract $node, string $nodeName): string
111103
$parent = $node->getAttribute('parent');
112104
$parentParentNode = $parent ? $parent->getAttribute('parent') : null;
113105

114-
if ($parentParentNode instanceof Namespace_ && !empty($parentParentNode->name)) {
115-
$namespace = '\\' . \implode('\\', $parentParentNode->name->parts) . '\\';
106+
if (
107+
$parentParentNode instanceof Namespace_
108+
&&
109+
$parentParentNode->name instanceof Name
110+
) {
111+
$namespace = '\\' . \implode('\\', $parentParentNode->name->getParts()) . '\\';
116112
} else {
117113
$namespace = '';
118114
}

0 commit comments

Comments
 (0)