1: <?php declare(strict_types = 1);
2:
3: namespace PHPStan\Type\Constant;
4:
5: use PHPStan\PhpDocParser\Ast\ConstExpr\ConstExprIntegerNode;
6: use PHPStan\PhpDocParser\Ast\Type\ConstTypeNode;
7: use PHPStan\PhpDocParser\Ast\Type\TypeNode;
8: use PHPStan\Type\CompoundType;
9: use PHPStan\Type\ConstantScalarType;
10: use PHPStan\Type\GeneralizePrecision;
11: use PHPStan\Type\IntegerRangeType;
12: use PHPStan\Type\IntegerType;
13: use PHPStan\Type\IsSuperTypeOfResult;
14: use PHPStan\Type\Traits\ConstantNumericComparisonTypeTrait;
15: use PHPStan\Type\Traits\ConstantScalarTypeTrait;
16: use PHPStan\Type\Type;
17: use PHPStan\Type\VerbosityLevel;
18: use function abs;
19: use function sprintf;
20:
21: /** @api */
22: class ConstantIntegerType extends IntegerType implements ConstantScalarType
23: {
24:
25: use ConstantScalarTypeTrait;
26: use ConstantScalarToBooleanTrait;
27: use ConstantNumericComparisonTypeTrait;
28:
29: /** @api */
30: public function __construct(private int $value)
31: {
32: parent::__construct();
33: }
34:
35: public function getValue(): int
36: {
37: return $this->value;
38: }
39:
40: public function isSuperTypeOf(Type $type): IsSuperTypeOfResult
41: {
42: if ($type instanceof self) {
43: return $this->value === $type->value ? IsSuperTypeOfResult::createYes() : IsSuperTypeOfResult::createNo();
44: }
45:
46: if ($type instanceof IntegerRangeType) {
47: $min = $type->getMin();
48: $max = $type->getMax();
49: if (($min === null || $min <= $this->value) && ($max === null || $this->value <= $max)) {
50: return IsSuperTypeOfResult::createMaybe();
51: }
52:
53: return IsSuperTypeOfResult::createNo();
54: }
55:
56: if ($type instanceof parent) {
57: return IsSuperTypeOfResult::createMaybe();
58: }
59:
60: if ($type instanceof CompoundType) {
61: return $type->isSubTypeOf($this);
62: }
63:
64: return IsSuperTypeOfResult::createNo();
65: }
66:
67: public function describe(VerbosityLevel $level): string
68: {
69: return $level->handle(
70: static fn (): string => 'int',
71: fn (): string => sprintf('%s', $this->value),
72: );
73: }
74:
75: public function toFloat(): Type
76: {
77: return new ConstantFloatType($this->value);
78: }
79:
80: public function toAbsoluteNumber(): Type
81: {
82: return new self(abs($this->value));
83: }
84:
85: public function toString(): Type
86: {
87: return new ConstantStringType((string) $this->value);
88: }
89:
90: public function toArrayKey(): Type
91: {
92: return $this;
93: }
94:
95: public function generalize(GeneralizePrecision $precision): Type
96: {
97: return new IntegerType();
98: }
99:
100: /**
101: * @return ConstTypeNode
102: */
103: public function toPhpDocNode(): TypeNode
104: {
105: return new ConstTypeNode(new ConstExprIntegerNode((string) $this->value));
106: }
107:
108: }
109: