Skip to content

Commit

Permalink
Merge pull request vimeo#10941 from kkmuffme/cast-int-range-keep-lite…
Browse files Browse the repository at this point in the history
…rals
  • Loading branch information
weirdan committed May 5, 2024
2 parents 10956df + 5bb9ebf commit 0294324
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
use Psalm\Type\Atomic\TFalse;
use Psalm\Type\Atomic\TFloat;
use Psalm\Type\Atomic\TInt;
use Psalm\Type\Atomic\TIntRange;
use Psalm\Type\Atomic\TKeyedArray;
use Psalm\Type\Atomic\TList;
use Psalm\Type\Atomic\TLiteralFloat;
Expand All @@ -53,6 +54,7 @@
use function array_pop;
use function array_values;
use function get_class;
use function range;
use function strtolower;

/**
Expand Down Expand Up @@ -537,6 +539,18 @@ public static function castFloatAttempt(
continue;
}

if ($atomic_type instanceof TIntRange
&& $atomic_type->min_bound !== null
&& $atomic_type->max_bound !== null
&& ($atomic_type->max_bound - $atomic_type->min_bound) < 500
) {
foreach (range($atomic_type->min_bound, $atomic_type->max_bound) as $literal_int_value) {
$valid_floats[] = new TLiteralFloat((float) $literal_int_value);
}

continue;
}

if ($atomic_type instanceof TInt) {
if ($atomic_type instanceof TLiteralInt) {
$valid_floats[] = new TLiteralFloat((float) $atomic_type->value);
Expand Down Expand Up @@ -721,9 +735,17 @@ public static function castStringAttempt(
|| $atomic_type instanceof TNumeric
) {
if ($atomic_type instanceof TLiteralInt || $atomic_type instanceof TLiteralFloat) {
$castable_types[] = Type::getAtomicStringFromLiteral((string) $atomic_type->value);
$valid_strings[] = Type::getAtomicStringFromLiteral((string) $atomic_type->value);
} elseif ($atomic_type instanceof TNonspecificLiteralInt) {
$castable_types[] = new TNonspecificLiteralString();
} elseif ($atomic_type instanceof TIntRange
&& $atomic_type->min_bound !== null
&& $atomic_type->max_bound !== null
&& ($atomic_type->max_bound - $atomic_type->min_bound) < 500
) {
foreach (range($atomic_type->min_bound, $atomic_type->max_bound) as $literal_int_value) {
$valid_strings[] = Type::getAtomicStringFromLiteral((string) $literal_int_value);
}
} else {
$castable_types[] = new TNumericString();
}
Expand Down
10 changes: 10 additions & 0 deletions tests/CastTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,15 @@ public function providerValidCodeParse(): iterable
'$a===' => 'array{a: int, b: string, ...<array-key, mixed>}',
],
];
yield 'castIntRangeToString' => [
'code' => '<?php
/** @var int<-5, 3> */
$int_range = 2;
$string = (string) $int_range;
',
'assertions' => [
'$string===' => "'-1'|'-2'|'-3'|'-4'|'-5'|'0'|'1'|'2'|'3'",
],
];
}
}

0 comments on commit 0294324

Please sign in to comment.