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