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