Skip to content

Commit 4679c62

Browse files
committed
Support #[Deprecated] attribute in property hooks
1 parent e606f0c commit 4679c62

File tree

6 files changed

+122
-7
lines changed

6 files changed

+122
-7
lines changed

src/Analyser/MutatingScope.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3004,6 +3004,8 @@ public function enterPropertyHook(
30043004
?Type $phpDocPropertyType,
30053005
array $phpDocParameterTypes,
30063006
?Type $throwType,
3007+
?string $deprecatedDescription,
3008+
bool $isDeprecated,
30073009
?string $phpDocComment,
30083010
): self
30093011
{
@@ -3059,8 +3061,8 @@ public function enterPropertyHook(
30593061
$realReturnType,
30603062
$phpDocReturnType,
30613063
$throwType,
3062-
null,
3063-
false,
3064+
$deprecatedDescription,
3065+
$isDeprecated,
30643066
false,
30653067
false,
30663068
false,

src/Analyser/NodeScopeResolver.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1985,7 +1985,7 @@ static function (Node $node, Scope $scope) use ($nodeCallback): void {
19851985
/**
19861986
* @return array{bool, string|null}
19871987
*/
1988-
private function getDeprecatedAttribute(Scope $scope, Node\Stmt\Function_|Node\Stmt\ClassMethod $stmt): array
1988+
private function getDeprecatedAttribute(Scope $scope, Node\Stmt\Function_|Node\Stmt\ClassMethod|Node\PropertyHook $stmt): array
19891989
{
19901990
$initializerExprContext = InitializerExprContext::fromStubParameter(
19911991
null,
@@ -4684,13 +4684,17 @@ private function processPropertyHooks(
46844684
$this->processParamNode($stmt, $param, $scope, $nodeCallback);
46854685
}
46864686

4687+
[$isDeprecated, $deprecatedDescription] = $this->getDeprecatedAttribute($scope, $hook);
4688+
46874689
$hookScope = $scope->enterPropertyHook(
46884690
$hook,
46894691
$propertyName,
46904692
$nativeTypeNode,
46914693
$phpDocType,
46924694
$phpDocParameterTypes,
46934695
$phpDocThrowType,
4696+
$deprecatedDescription,
4697+
$isDeprecated,
46944698
$phpDocComment,
46954699
);
46964700
$hookReflection = $hookScope->getFunction();

src/Reflection/InitializerExprContext.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace PHPStan\Reflection;
44

5+
use PhpParser\Node\PropertyHook;
56
use PhpParser\Node\Stmt\ClassMethod;
67
use PhpParser\Node\Stmt\Function_;
78
use PHPStan\Analyser\Scope;
@@ -115,7 +116,7 @@ public static function fromReflectionParameter(ReflectionParameter $parameter):
115116
public static function fromStubParameter(
116117
?string $className,
117118
string $stubFile,
118-
ClassMethod|Function_ $function,
119+
ClassMethod|Function_|PropertyHook $function,
119120
): self
120121
{
121122
$namespace = null;

tests/PHPStan/Reflection/Annotations/DeprecatedAnnotationsTest.php

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,4 +339,50 @@ public function testDeprecatedAttributeAboveEnumCase(string $className, string $
339339
$this->assertSame($deprecatedDescription, $case->getDeprecatedDescription());
340340
}
341341

342+
public function dataDeprecatedAttributeAbovePropertyHook(): iterable
343+
{
344+
yield [
345+
\DeprecatedAttributePropertyHooks\Foo::class,
346+
'i',
347+
'get',
348+
TrinaryLogic::createNo(),
349+
null,
350+
];
351+
yield [
352+
\DeprecatedAttributePropertyHooks\Foo::class,
353+
'j',
354+
'get',
355+
TrinaryLogic::createYes(),
356+
null,
357+
];
358+
yield [
359+
\DeprecatedAttributePropertyHooks\Foo::class,
360+
'k',
361+
'get',
362+
TrinaryLogic::createYes(),
363+
'msg',
364+
];
365+
yield [
366+
\DeprecatedAttributePropertyHooks\Foo::class,
367+
'l',
368+
'get',
369+
TrinaryLogic::createYes(),
370+
'msg2',
371+
];
372+
}
373+
374+
/**
375+
* @dataProvider dataDeprecatedAttributeAbovePropertyHook
376+
* @param 'get'|'set' $hookName
377+
*/
378+
public function testDeprecatedAttributeAbovePropertyHook(string $className, string $propertyName, string $hookName, TrinaryLogic $isDeprecated, ?string $deprecatedDescription): void
379+
{
380+
$reflectionProvider = $this->createReflectionProvider();
381+
$class = $reflectionProvider->getClass($className);
382+
$property = $class->getNativeProperty($propertyName);
383+
$hook = $property->getHook($hookName);
384+
$this->assertSame($isDeprecated->describe(), $hook->isDeprecated()->describe());
385+
$this->assertSame($deprecatedDescription, $hook->getDeprecatedDescription());
386+
}
387+
342388
}

tests/PHPStan/Reflection/Annotations/DeprecatedAttributePhpFunctionFromParserReflectionRuleTest.php

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use PHPStan\Analyser\Scope;
77
use PHPStan\Node\InClassMethodNode;
88
use PHPStan\Node\InFunctionNode;
9+
use PHPStan\Node\InPropertyHookNode;
910
use PHPStan\Rules\Rule;
1011
use PHPStan\Rules\RuleErrorBuilder;
1112
use PHPStan\Testing\RuleTestCase;
@@ -18,15 +19,15 @@ class DeprecatedAttributePhpFunctionFromParserReflectionRuleTest extends RuleTes
1819
{
1920

2021
/**
21-
* @return Rule<Node\Stmt>
22+
* @return Rule<Node>
2223
*/
2324
protected function getRule(): Rule
2425
{
25-
return new /** @implements Rule<Node\Stmt> */ class implements Rule {
26+
return new /** @implements Rule<Node> */ class implements Rule {
2627

2728
public function getNodeType(): string
2829
{
29-
return Node\Stmt::class;
30+
return Node::class;
3031
}
3132

3233
public function processNode(Node $node, Scope $scope): array
@@ -35,6 +36,8 @@ public function processNode(Node $node, Scope $scope): array
3536
$reflection = $node->getFunctionReflection();
3637
} elseif ($node instanceof InClassMethodNode) {
3738
$reflection = $node->getMethodReflection();
39+
} elseif ($node instanceof InPropertyHookNode) {
40+
$reflection = $node->getHookReflection();
3841
} else {
3942
return [];
4043
}
@@ -108,4 +111,26 @@ public function testMethodRule(): void
108111
]);
109112
}
110113

114+
public function testPropertyHookRule(): void
115+
{
116+
$this->analyse([__DIR__ . '/data/deprecated-attribute-property-hooks.php'], [
117+
[
118+
'Not deprecated',
119+
11,
120+
],
121+
[
122+
'Deprecated',
123+
17,
124+
],
125+
[
126+
'Deprecated: msg',
127+
24,
128+
],
129+
[
130+
'Deprecated: msg2',
131+
31,
132+
],
133+
]);
134+
}
135+
111136
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php // lint >= 8.4
2+
3+
namespace DeprecatedAttributePropertyHooks;
4+
5+
use Deprecated;
6+
7+
class Foo
8+
{
9+
10+
public int $i {
11+
get {
12+
return 1;
13+
}
14+
}
15+
16+
public int $j {
17+
#[Deprecated]
18+
get {
19+
return 1;
20+
}
21+
}
22+
23+
public int $k {
24+
#[Deprecated('msg')]
25+
get {
26+
return 1;
27+
}
28+
}
29+
30+
public int $l {
31+
#[Deprecated(since: '1.0', message: 'msg2')]
32+
get {
33+
return 1;
34+
}
35+
}
36+
37+
}

0 commit comments

Comments
 (0)