Skip to content

Commit ab3c679

Browse files
committed
EnforceReadonlyPublicPropertyRule: add support for Nette Inject phpdoc and attribute.
1 parent 879bcdc commit ab3c679

File tree

3 files changed

+50
-0
lines changed

3 files changed

+50
-0
lines changed

src/Rule/EnforceReadonlyPublicPropertyRule.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,16 @@
22

33
namespace ShipMonk\PHPStan\Rule;
44

5+
use LogicException;
56
use PhpParser\Node;
67
use PHPStan\Analyser\Scope;
78
use PHPStan\Node\ClassPropertyNode;
89
use PHPStan\Php\PhpVersion;
910
use PHPStan\Rules\IdentifierRuleError;
1011
use PHPStan\Rules\Rule;
1112
use PHPStan\Rules\RuleErrorBuilder;
13+
use ReflectionException;
14+
use function strpos;
1215

1316
/**
1417
* @implements Rule<ClassPropertyNode>
@@ -48,6 +51,24 @@ public function processNode(Node $node, Scope $scope): array
4851
return [];
4952
}
5053

54+
try {
55+
$propertyReflection = $node->getClassReflection()->getNativeReflection()->getProperty($node->getName());
56+
} catch (ReflectionException $e) {
57+
throw new LogicException('Property isn\'t found in class reflection.', 0, $e);
58+
}
59+
60+
$attributeName = 'Nette\\DI\\Attributes\\Inject';
61+
62+
if ($propertyReflection->getAttributes($attributeName) !== []) { // @phpstan-ignore argument.type
63+
return [];
64+
}
65+
66+
$phpdoc = $propertyReflection->getDocComment();
67+
68+
if ($phpdoc !== false && strpos($phpdoc, '@inject') !== false) {
69+
return [];
70+
}
71+
5172
$error = RuleErrorBuilder::message("Public property `{$node->getName()}` not marked as readonly.")
5273
->identifier('shipmonk.publicPropertyNotReadonly')
5374
->build();

tests/Rule/EnforceReadonlyPublicPropertyRuleTest.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,12 @@ public function testPhp80(): void
4343
$this->analyseFile(__DIR__ . '/data/EnforceReadonlyPublicPropertyRule/code-80.php');
4444
}
4545

46+
public function testNetteInject(): void
47+
{
48+
$this->phpVersion = $this->createPhpVersion(80_100);
49+
$this->analyseFile(__DIR__ . '/data/EnforceReadonlyPublicPropertyRule/code-nette-inject.php');
50+
}
51+
4652
private function createPhpVersion(int $version): PhpVersion
4753
{
4854
return new PhpVersion($version); // @phpstan-ignore phpstanApi.constructor
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
namespace EnforceReadonlyPublicPropertyRule84;
4+
5+
use Nette\DI\Attributes\Inject;
6+
7+
class MyPresenterClass {
8+
9+
#[Inject]
10+
public int $foo;
11+
12+
/** @inject */
13+
public int $foo2;
14+
15+
public int $foo3; // error: Public property `foo3` not marked as readonly.
16+
17+
/**
18+
* @int
19+
* @inject with comment
20+
* @deprecated
21+
*/
22+
public int $foo4;
23+
}

0 commit comments

Comments
 (0)