Skip to content

Commit 4ba8fcb

Browse files
committed
PropertyHookAttributesRule - level 0
1 parent ea47edf commit 4ba8fcb

File tree

4 files changed

+157
-0
lines changed

4 files changed

+157
-0
lines changed

conf/config.level0.neon

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ rules:
9797
- PHPStan\Rules\Properties\MissingReadOnlyByPhpDocPropertyAssignRule
9898
- PHPStan\Rules\Properties\PropertiesInInterfaceRule
9999
- PHPStan\Rules\Properties\PropertyAttributesRule
100+
- PHPStan\Rules\Properties\PropertyHookAttributesRule
100101
- PHPStan\Rules\Properties\PropertyInClassRule
101102
- PHPStan\Rules\Properties\ReadOnlyPropertyRule
102103
- PHPStan\Rules\Properties\ReadOnlyByPhpDocPropertyRule
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Rules\Properties;
4+
5+
use Attribute;
6+
use PhpParser\Node;
7+
use PHPStan\Analyser\Scope;
8+
use PHPStan\Node\InPropertyHookNode;
9+
use PHPStan\Rules\AttributesCheck;
10+
use PHPStan\Rules\Rule;
11+
12+
/**
13+
* @implements Rule<InPropertyHookNode>
14+
*/
15+
final class PropertyHookAttributesRule implements Rule
16+
{
17+
18+
public function __construct(private AttributesCheck $attributesCheck)
19+
{
20+
}
21+
22+
public function getNodeType(): string
23+
{
24+
return InPropertyHookNode::class;
25+
}
26+
27+
public function processNode(Node $node, Scope $scope): array
28+
{
29+
return $this->attributesCheck->check(
30+
$scope,
31+
$node->getOriginalNode()->attrGroups,
32+
Attribute::TARGET_METHOD,
33+
'method',
34+
);
35+
}
36+
37+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Rules\Properties;
4+
5+
use PHPStan\Rules\AttributesCheck;
6+
use PHPStan\Rules\ClassCaseSensitivityCheck;
7+
use PHPStan\Rules\ClassForbiddenNameCheck;
8+
use PHPStan\Rules\ClassNameCheck;
9+
use PHPStan\Rules\FunctionCallParametersCheck;
10+
use PHPStan\Rules\NullsafeCheck;
11+
use PHPStan\Rules\PhpDoc\UnresolvableTypeHelper;
12+
use PHPStan\Rules\Rule;
13+
use PHPStan\Rules\RuleLevelHelper;
14+
use PHPStan\Testing\RuleTestCase;
15+
use const PHP_VERSION_ID;
16+
17+
/**
18+
* @extends RuleTestCase<PropertyHookAttributesRule>
19+
*/
20+
class PropertyHookAttributesRuleTest extends RuleTestCase
21+
{
22+
23+
protected function getRule(): Rule
24+
{
25+
$reflectionProvider = $this->createReflectionProvider();
26+
return new PropertyHookAttributesRule(
27+
new AttributesCheck(
28+
$reflectionProvider,
29+
new FunctionCallParametersCheck(
30+
new RuleLevelHelper($reflectionProvider, true, false, true, false, false, false),
31+
new NullsafeCheck(),
32+
new UnresolvableTypeHelper(),
33+
new PropertyReflectionFinder(),
34+
true,
35+
true,
36+
true,
37+
true,
38+
),
39+
new ClassNameCheck(
40+
new ClassCaseSensitivityCheck($reflectionProvider, false),
41+
new ClassForbiddenNameCheck(self::getContainer()),
42+
),
43+
true,
44+
),
45+
);
46+
}
47+
48+
public function testRule(): void
49+
{
50+
if (PHP_VERSION_ID < 80400) {
51+
$this->markTestSkipped('Test requires PHP 8.4.');
52+
}
53+
54+
$this->analyse([__DIR__ . '/data/property-hook-attributes.php'], [
55+
[
56+
'Attribute class PropertyHookAttributes\Foo does not have the method target.',
57+
27,
58+
],
59+
]);
60+
}
61+
62+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<?php // lint >= 8.4
2+
3+
namespace PropertyHookAttributes;
4+
5+
#[\Attribute(\Attribute::TARGET_CLASS)]
6+
class Foo
7+
{
8+
9+
}
10+
11+
#[\Attribute(\Attribute::TARGET_METHOD)]
12+
class Bar
13+
{
14+
15+
}
16+
17+
#[\Attribute(\Attribute::TARGET_ALL)]
18+
class Baz
19+
{
20+
21+
}
22+
23+
class Lorem
24+
{
25+
26+
public int $i {
27+
#[Foo]
28+
get {
29+
30+
}
31+
}
32+
33+
}
34+
35+
class Ipsum
36+
{
37+
38+
public int $i {
39+
#[Bar]
40+
get {
41+
42+
}
43+
}
44+
45+
}
46+
47+
class Dolor
48+
{
49+
50+
public int $i {
51+
#[Baz]
52+
get {
53+
54+
}
55+
}
56+
57+
}

0 commit comments

Comments
 (0)