1: <?php
2:
3: declare(strict_types=1);
4:
5: namespace PHPStan\BetterReflection\Reflection\Adapter;
6:
7: use ReflectionNamedType as CoreReflectionNamedType;
8: use PHPStan\BetterReflection\Reflection\ReflectionNamedType as BetterReflectionNamedType;
9:
10: use function is_string;
11: use function strtolower;
12:
13: /** @psalm-immutable */
14: final class ReflectionNamedType extends CoreReflectionNamedType
15: {
16: /**
17: * @var BetterReflectionNamedType|non-empty-string
18: */
19: private $type;
20: private bool $allowsNull = false;
21: /** @var non-empty-string */
22: private string $nameType;
23:
24: private bool $isBuiltin;
25:
26: /** @var non-empty-string */
27: private string $toString;
28:
29: /** @param BetterReflectionNamedType|non-empty-string $type */
30: public function __construct($type, bool $allowsNull = false)
31: {
32: $this->type = $type;
33: $this->allowsNull = $allowsNull;
34: if ($type instanceof BetterReflectionNamedType) {
35: $nameType = $type->getName();
36: $this->nameType = $nameType;
37: $this->isBuiltin = self::computeIsBuiltin($nameType, $type->isBuiltin());
38: $this->toString = $type->__toString();
39: } else {
40: $this->nameType = $type;
41: $this->isBuiltin = true;
42: $this->toString = $type;
43: }
44: }
45:
46: /** @return non-empty-string */
47: public function getName(): string
48: {
49: return $this->nameType;
50: }
51:
52: /** @return non-empty-string */
53: public function __toString(): string
54: {
55: $normalizedType = strtolower($this->nameType);
56:
57: if (
58: ! $this->allowsNull
59: || $normalizedType === 'mixed'
60: || $normalizedType === 'null'
61: ) {
62: return $this->toString;
63: }
64:
65: return '?' . $this->toString;
66: }
67:
68: public function allowsNull(): bool
69: {
70: return $this->allowsNull;
71: }
72:
73: public function isBuiltin(): bool
74: {
75: return $this->isBuiltin;
76: }
77:
78: private static function computeIsBuiltin(string $namedType, bool $isBuiltin): bool
79: {
80: $normalizedType = strtolower($namedType);
81:
82: if ($normalizedType === 'self' || $normalizedType === 'parent' || $normalizedType === 'static') {
83: return false;
84: }
85:
86: return $isBuiltin;
87: }
88:
89: public function isIdentifier(): bool
90: {
91: if (is_string($this->type)) {
92: return true;
93: }
94:
95: return $this->type->isIdentifier();
96: }
97: }
98: