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