Skip to content

Commit 25d1552

Browse files
committed
Bleeding edge - ParamAttributesRule - promoted property attribute needs to target both parameters and properties
1 parent 154cc40 commit 25d1552

File tree

6 files changed

+73
-11
lines changed

6 files changed

+73
-11
lines changed

conf/bleedingEdge.neon

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ parameters:
2424
missingMagicSerializationRule: true
2525
nullContextForVoidReturningFunctions: true
2626
unescapeStrings: true
27+
promotedPropertyAttribute: true
2728
alwaysCheckTooWideReturnTypeFinalMethods: true
2829
duplicateStubs: true
2930
logicalXor: true

conf/config.level0.neon

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,6 @@ rules:
7575
- PHPStan\Rules\Functions\FunctionAttributesRule
7676
- PHPStan\Rules\Functions\InnerFunctionRule
7777
- PHPStan\Rules\Functions\InvalidLexicalVariablesInClosureUseRule
78-
- PHPStan\Rules\Functions\ParamAttributesRule
7978
- PHPStan\Rules\Functions\PrintfParametersRule
8079
- PHPStan\Rules\Functions\RedefinedParametersRule
8180
- PHPStan\Rules\Functions\ReturnNullsafeByRefRule
@@ -152,6 +151,13 @@ services:
152151
arguments:
153152
checkFunctionNameCase: %checkFunctionNameCase%
154153

154+
-
155+
class: PHPStan\Rules\Functions\ParamAttributesRule
156+
tags:
157+
- phpstan.rules.rule
158+
arguments:
159+
checkPromotedPropertyAttribute: %featureToggles.promotedPropertyAttribute%
160+
155161
-
156162
class: PHPStan\Rules\Constants\OverridingConstantRule
157163
arguments:

conf/config.neon

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ parameters:
5959
missingMagicSerializationRule: false
6060
nullContextForVoidReturningFunctions: false
6161
unescapeStrings: false
62+
promotedPropertyAttribute: false
6263
alwaysCheckTooWideReturnTypeFinalMethods: false
6364
duplicateStubs: false
6465
logicalXor: false

conf/parametersSchema.neon

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ parametersSchema:
5454
missingMagicSerializationRule: bool()
5555
nullContextForVoidReturningFunctions: bool()
5656
unescapeStrings: bool()
57+
promotedPropertyAttribute: bool()
5758
alwaysCheckTooWideReturnTypeFinalMethods: bool()
5859
duplicateStubs: bool()
5960
logicalXor: bool()

src/Rules/Functions/ParamAttributesRule.php

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
class ParamAttributesRule implements Rule
1616
{
1717

18-
public function __construct(private AttributesCheck $attributesCheck)
18+
public function __construct(private AttributesCheck $attributesCheck, private bool $checkPromotedPropertyAttribute)
1919
{
2020
}
2121

@@ -28,17 +28,30 @@ public function processNode(Node $node, Scope $scope): array
2828
{
2929
$targetName = 'parameter';
3030
if ($node->flags !== 0) {
31-
$targetName = 'parameter or property';
31+
if ($this->checkPromotedPropertyAttribute) {
32+
$propertyTargetErrors = $this->attributesCheck->check(
33+
$scope,
34+
$node->attrGroups,
35+
Attribute::TARGET_PROPERTY,
36+
'property',
37+
);
3238

33-
$propertyTargetErrors = $this->attributesCheck->check(
34-
$scope,
35-
$node->attrGroups,
36-
Attribute::TARGET_PROPERTY,
37-
$targetName,
38-
);
39+
if (count($propertyTargetErrors) > 0) {
40+
return $propertyTargetErrors;
41+
}
42+
} else {
43+
$targetName = 'parameter or property';
3944

40-
if (count($propertyTargetErrors) === 0) {
41-
return $propertyTargetErrors;
45+
$propertyTargetErrors = $this->attributesCheck->check(
46+
$scope,
47+
$node->attrGroups,
48+
Attribute::TARGET_PROPERTY,
49+
$targetName,
50+
);
51+
52+
if (count($propertyTargetErrors) === 0) {
53+
return $propertyTargetErrors;
54+
}
4255
}
4356
}
4457

tests/PHPStan/Rules/Functions/ParamAttributesRuleTest.php

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
class ParamAttributesRuleTest extends RuleTestCase
2020
{
2121

22+
private bool $checkPromotedPropertyAttribute;
23+
2224
protected function getRule(): Rule
2325
{
2426
$reflectionProvider = $this->createReflectionProvider();
@@ -40,11 +42,13 @@ protected function getRule(): Rule
4042
new ClassCaseSensitivityCheck($reflectionProvider, false),
4143
true,
4244
),
45+
$this->checkPromotedPropertyAttribute,
4346
);
4447
}
4548

4649
public function testRule(): void
4750
{
51+
$this->checkPromotedPropertyAttribute = false;
4852
$this->analyse([__DIR__ . '/data/param-attributes.php'], [
4953
[
5054
'Attribute class ParamAttributes\Foo does not have the parameter target.',
@@ -61,8 +65,44 @@ public function testRule(): void
6165
]);
6266
}
6367

68+
public function testRuleCheckPromotedPropertyAttribute(): void
69+
{
70+
$this->checkPromotedPropertyAttribute = true;
71+
$this->analyse([__DIR__ . '/data/param-attributes.php'], [
72+
[
73+
'Attribute class ParamAttributes\Foo does not have the parameter target.',
74+
33,
75+
],
76+
[
77+
'Attribute class ParamAttributes\Foo does not have the property target.',
78+
72,
79+
],
80+
[
81+
'Attribute class ParamAttributes\Bar does not have the property target.',
82+
74,
83+
],
84+
[
85+
'Attribute class ParamAttributes\Qux does not have the parameter target.',
86+
76,
87+
],
88+
[
89+
'Attribute class ParamAttributes\Qux does not have the parameter target.',
90+
78,
91+
],
92+
[
93+
'Attribute class ParamAttributes\Qux does not have the parameter target.',
94+
80,
95+
],
96+
[
97+
'Attribute class ParamAttributes\Qux does not have the parameter target.',
98+
82,
99+
],
100+
]);
101+
}
102+
64103
public function testSensitiveParameterAttribute(): void
65104
{
105+
$this->checkPromotedPropertyAttribute = false;
66106
$this->analyse([__DIR__ . '/data/sensitive-parameter.php'], []);
67107
}
68108

0 commit comments

Comments
 (0)