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