1: | <?php |
2: | |
3: | declare(strict_types=1); |
4: | |
5: | namespace PHPStan\BetterReflection\Reflection; |
6: | |
7: | use Attribute; |
8: | use LogicException; |
9: | use PhpParser\Node; |
10: | use PHPStan\BetterReflection\NodeCompiler\CompileNodeToValue; |
11: | use PHPStan\BetterReflection\NodeCompiler\CompilerContext; |
12: | use PHPStan\BetterReflection\Reflection\Adapter\ReflectionAttribute as ReflectionAttributeAdapter; |
13: | use PHPStan\BetterReflection\Reflection\StringCast\ReflectionAttributeStringCast; |
14: | use PHPStan\BetterReflection\Reflector\Reflector; |
15: | |
16: | use function array_map; |
17: | |
18: | |
19: | class ReflectionAttribute |
20: | { |
21: | private Reflector $reflector; |
22: | |
23: | |
24: | |
25: | private $owner; |
26: | private bool $isRepeated; |
27: | |
28: | private string $name; |
29: | |
30: | |
31: | private array $arguments; |
32: | |
33: | |
34: | |
35: | public function __construct(Reflector $reflector, Node\Attribute $node, $owner, bool $isRepeated) |
36: | { |
37: | $this->reflector = $reflector; |
38: | $this->owner = $owner; |
39: | $this->isRepeated = $isRepeated; |
40: | |
41: | $name = $node->name->toString(); |
42: | $this->name = $name; |
43: | $arguments = []; |
44: | foreach ($node->args as $argNo => $arg) { |
45: | $arguments[(($nullsafeVariable1 = $arg->name) ? $nullsafeVariable1->toString() : null) ?? $argNo] = $arg->value; |
46: | } |
47: | $this->arguments = $arguments; |
48: | } |
49: | |
50: | |
51: | |
52: | public function withOwner($owner): self |
53: | { |
54: | $clone = clone $this; |
55: | $clone->owner = $owner; |
56: | |
57: | return $clone; |
58: | } |
59: | |
60: | |
61: | public function getName(): string |
62: | { |
63: | return $this->name; |
64: | } |
65: | |
66: | public function getClass(): ReflectionClass |
67: | { |
68: | return $this->reflector->reflectClass($this->getName()); |
69: | } |
70: | |
71: | |
72: | public function getArgumentsExpressions(): array |
73: | { |
74: | return $this->arguments; |
75: | } |
76: | |
77: | |
78: | |
79: | |
80: | public function getArguments(): array |
81: | { |
82: | $compiler = new CompileNodeToValue(); |
83: | $context = new CompilerContext($this->reflector, $this->owner); |
84: | |
85: | return array_map(static fn (Node\Expr $value) => $compiler->__invoke($value, $context)->value, $this->arguments); |
86: | } |
87: | |
88: | |
89: | public function getTarget(): int |
90: | { |
91: | switch (true) { |
92: | case $this->owner instanceof ReflectionClass: |
93: | return Attribute::TARGET_CLASS; |
94: | case $this->owner instanceof ReflectionFunction: |
95: | return Attribute::TARGET_FUNCTION; |
96: | case $this->owner instanceof ReflectionConstant: |
97: | return ReflectionAttributeAdapter::TARGET_CONSTANT_COMPATIBILITY; |
98: | case $this->owner instanceof ReflectionMethod: |
99: | return Attribute::TARGET_METHOD; |
100: | case $this->owner instanceof ReflectionProperty: |
101: | return Attribute::TARGET_PROPERTY; |
102: | case $this->owner instanceof ReflectionClassConstant: |
103: | return Attribute::TARGET_CLASS_CONSTANT; |
104: | case $this->owner instanceof ReflectionEnumCase: |
105: | return Attribute::TARGET_CLASS_CONSTANT; |
106: | case $this->owner instanceof ReflectionParameter: |
107: | return Attribute::TARGET_PARAMETER; |
108: | default: |
109: | throw new LogicException('unknown owner'); |
110: | } |
111: | } |
112: | |
113: | public function isRepeated(): bool |
114: | { |
115: | return $this->isRepeated; |
116: | } |
117: | |
118: | |
119: | public function __toString(): string |
120: | { |
121: | return ReflectionAttributeStringCast::toString($this); |
122: | } |
123: | } |
124: | |