Skip to content

Commit 24d0e26

Browse files
committed
CleaningParser - clean up property hooks
1 parent 73ea929 commit 24d0e26

File tree

4 files changed

+97
-7
lines changed

4 files changed

+97
-7
lines changed

src/Parser/CleaningVisitor.php

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use PhpParser\NodeVisitorAbstract;
88
use PHPStan\Reflection\ParametersAcceptor;
99
use function in_array;
10+
use function is_array;
1011

1112
final class CleaningVisitor extends NodeVisitorAbstract
1213
{
@@ -21,30 +22,38 @@ public function __construct()
2122
public function enterNode(Node $node): ?Node
2223
{
2324
if ($node instanceof Node\Stmt\Function_) {
24-
$node->stmts = $this->keepVariadicsAndYields($node->stmts);
25+
$node->stmts = $this->keepVariadicsAndYields($node->stmts, null);
2526
return $node;
2627
}
2728

2829
if ($node instanceof Node\Stmt\ClassMethod && $node->stmts !== null) {
29-
$node->stmts = $this->keepVariadicsAndYields($node->stmts);
30+
$node->stmts = $this->keepVariadicsAndYields($node->stmts, null);
3031
return $node;
3132
}
3233

3334
if ($node instanceof Node\Expr\Closure) {
34-
$node->stmts = $this->keepVariadicsAndYields($node->stmts);
35+
$node->stmts = $this->keepVariadicsAndYields($node->stmts, null);
3536
return $node;
3637
}
3738

39+
if ($node instanceof Node\PropertyHook && is_array($node->body)) {
40+
$propertyName = $node->getAttribute(PropertyHookNameVisitor::ATTRIBUTE_NAME);
41+
if ($propertyName !== null) {
42+
$node->body = $this->keepVariadicsAndYields($node->body, $propertyName);
43+
return $node;
44+
}
45+
}
46+
3847
return null;
3948
}
4049

4150
/**
4251
* @param Node\Stmt[] $stmts
4352
* @return Node\Stmt[]
4453
*/
45-
private function keepVariadicsAndYields(array $stmts): array
54+
private function keepVariadicsAndYields(array $stmts, ?string $hookedPropertyName): array
4655
{
47-
$results = $this->nodeFinder->find($stmts, static function (Node $node): bool {
56+
$results = $this->nodeFinder->find($stmts, static function (Node $node) use ($hookedPropertyName): bool {
4857
if ($node instanceof Node\Expr\YieldFrom || $node instanceof Node\Expr\Yield_) {
4958
return true;
5059
}
@@ -56,6 +65,18 @@ private function keepVariadicsAndYields(array $stmts): array
5665
return true;
5766
}
5867

68+
if ($hookedPropertyName !== null) {
69+
if (
70+
$node instanceof Node\Expr\PropertyFetch
71+
&& $node->var instanceof Node\Expr\Variable
72+
&& $node->var->name === 'this'
73+
&& $node->name instanceof Node\Identifier
74+
&& $node->name->toString() === $hookedPropertyName
75+
) {
76+
return true;
77+
}
78+
}
79+
5980
return false;
6081
});
6182
$newStmts = [];
@@ -65,6 +86,7 @@ private function keepVariadicsAndYields(array $stmts): array
6586
|| $result instanceof Node\Expr\YieldFrom
6687
|| $result instanceof Node\Expr\Closure
6788
|| $result instanceof Node\Expr\ArrowFunction
89+
|| $result instanceof Node\Expr\PropertyFetch
6890
) {
6991
$newStmts[] = new Node\Stmt\Expression($result);
7092
continue;

tests/PHPStan/Parser/CleaningParserTest.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
use PhpParser\Lexer\Emulative;
66
use PhpParser\NodeVisitor\NameResolver;
7-
use PhpParser\Parser\Php7;
7+
use PhpParser\Parser\Php8;
88
use PHPStan\File\FileReader;
99
use PHPStan\Node\Printer\Printer;
1010
use PHPStan\Php\PhpVersion;
@@ -52,6 +52,11 @@ public function dataParse(): iterable
5252
__DIR__ . '/data/cleaning-php-version-after-74.php',
5353
70400,
5454
],
55+
[
56+
__DIR__ . '/data/cleaning-property-hooks-before.php',
57+
__DIR__ . '/data/cleaning-property-hooks-after.php',
58+
80400,
59+
],
5560
];
5661
}
5762

@@ -66,7 +71,7 @@ public function testParse(
6671
{
6772
$parser = new CleaningParser(
6873
new SimpleParser(
69-
new Php7(new Emulative()),
74+
new Php8(new Emulative()),
7075
new NameResolver(),
7176
new VariadicMethodsVisitor(),
7277
new VariadicFunctionsVisitor(),
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
namespace CleaningPropertyHooks;
3+
4+
class Foo
5+
{
6+
public int $i {
7+
get {
8+
$this->i;
9+
}
10+
}
11+
}
12+
class FooParam
13+
{
14+
public function __construct(public int $i {
15+
get {
16+
$this->i;
17+
}
18+
})
19+
{
20+
}
21+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
3+
namespace CleaningPropertyHooks;
4+
5+
class Foo
6+
{
7+
8+
public int $i {
9+
get {
10+
echo 'irrelevant';
11+
12+
// other property, clean up
13+
echo $this->j;
14+
15+
// backed property, leave this here
16+
return $this->i;
17+
}
18+
}
19+
20+
}
21+
22+
class FooParam
23+
{
24+
25+
public function __construct(
26+
public int $i {
27+
get {
28+
echo 'irrelevant';
29+
30+
// other property, clean up
31+
echo $this->j;
32+
33+
// backed property, leave this here
34+
return $this->i;
35+
}
36+
}
37+
)
38+
{
39+
40+
}
41+
42+
}

0 commit comments

Comments
 (0)