Skip to content

Commit b1cebc2

Browse files
committed
Use InTraitNode instead
Some attribute arguments actually depend on using class instead of the trait So we have to analyse the attributes in context of each class that uses the trait
1 parent ff83891 commit b1cebc2

File tree

4 files changed

+22
-30
lines changed

4 files changed

+22
-30
lines changed

Diff for: src/Rules/Traits/TraitAttributesRule.php

+6-27
Original file line numberDiff line numberDiff line change
@@ -4,62 +4,41 @@
44

55
use Attribute;
66
use PhpParser\Node;
7-
use PhpParser\Node\Stmt\Class_;
8-
use PHPStan\Analyser\MutatingScope;
97
use PHPStan\Analyser\Scope;
10-
use PHPStan\Reflection\ReflectionProvider;
8+
use PHPStan\Node\InTraitNode;
119
use PHPStan\Rules\AttributesCheck;
1210
use PHPStan\Rules\Rule;
1311
use PHPStan\Rules\RuleErrorBuilder;
14-
use PHPStan\ShouldNotHappenException;
1512
use function count;
1613

1714
/**
18-
* @implements Rule<Node\Stmt\Trait_>
15+
* @implements Rule<InTraitNode>
1916
*/
2017
final class TraitAttributesRule implements Rule
2118
{
2219

2320
public function __construct(
2421
private AttributesCheck $attributesCheck,
25-
private ReflectionProvider $reflectionProvider,
2622
)
2723
{
2824
}
2925

3026
public function getNodeType(): string
3127
{
32-
return Node\Stmt\Trait_::class;
28+
return InTraitNode::class;
3329
}
3430

3531
public function processNode(Node $node, Scope $scope): array
3632
{
37-
$traitName = $node->namespacedName;
38-
if ($traitName === null) {
39-
return [];
40-
}
41-
42-
if (!$this->reflectionProvider->hasClass($traitName->toString())) {
43-
return [];
44-
}
45-
$traitClassReflection = $this->reflectionProvider->getClass($traitName->toString());
46-
47-
if (!$scope instanceof MutatingScope) {
48-
throw new ShouldNotHappenException();
49-
}
50-
$fakeClass = new Class_(null, [new Node\Stmt\TraitUse([$traitName])], ['startLine' => 1, 'endLine' => 1]);
51-
$fakeClassReflection = $this->reflectionProvider->getAnonymousClassReflection($fakeClass, $scope);
52-
$scope = $scope->enterClass($fakeClassReflection);
53-
$scope = $scope->enterTrait($traitClassReflection);
54-
33+
$originalNode = $node->getOriginalNode();
5534
$errors = $this->attributesCheck->check(
5635
$scope,
57-
$node->attrGroups,
36+
$originalNode->attrGroups,
5837
Attribute::TARGET_CLASS,
5938
'class',
6039
);
6140

62-
if (count($traitClassReflection->getNativeReflection()->getAttributes('AllowDynamicProperties')) > 0) {
41+
if (count($node->getTraitReflection()->getNativeReflection()->getAttributes('AllowDynamicProperties')) > 0) {
6342
$errors[] = RuleErrorBuilder::message('Attribute class AllowDynamicProperties cannot be used with trait.')
6443
->identifier('trait.allowDynamicProperties')
6544
->nonIgnorable()

Diff for: tests/PHPStan/Rules/Traits/TraitAttributesRuleTest.php

-3
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
use PHPStan\Php\PhpVersion;
66
use PHPStan\Rules\AttributesCheck;
77
use PHPStan\Rules\ClassCaseSensitivityCheck;
8-
use PHPStan\Rules\Classes\ClassAttributesRule;
98
use PHPStan\Rules\ClassForbiddenNameCheck;
109
use PHPStan\Rules\ClassNameCheck;
1110
use PHPStan\Rules\FunctionCallParametersCheck;
@@ -14,7 +13,6 @@
1413
use PHPStan\Rules\Properties\PropertyReflectionFinder;
1514
use PHPStan\Rules\Rule;
1615
use PHPStan\Rules\RuleLevelHelper;
17-
use PHPStan\Rules\Traits\TraitAttributesRule;
1816
use PHPStan\Testing\RuleTestCase;
1917
use const PHP_VERSION_ID;
2018

@@ -51,7 +49,6 @@ protected function getRule(): Rule
5149
),
5250
true,
5351
),
54-
$reflectionProvider,
5552
);
5653
}
5754

Diff for: tests/PHPStan/Rules/Traits/data/bug-12281.php

+7
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,10 @@ interface BlogDataInterface { /* … */ } // reported by ClassAttributesRule
1010

1111
#[\AllowDynamicProperties]
1212
trait BlogDataTrait { /* … */ }
13+
14+
class Uses
15+
{
16+
17+
use BlogDataTrait;
18+
19+
}

Diff for: tests/PHPStan/Rules/Traits/data/trait-attributes.php

+9
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,12 @@ class MyTargettedAttribute {}
1919

2020
#[MyTargettedAttribute]
2121
trait MyTrait3 {}
22+
23+
class Uses
24+
{
25+
26+
use MyTrait;
27+
use MyTrait2;
28+
use MyTrait3;
29+
30+
}

0 commit comments

Comments
 (0)