1
0
mirror of https://github.com/danog/psalm.git synced 2024-11-27 04:45:20 +01:00

Merge pull request #8585 from gphargreaves/#8315/concat-non-empty-strings

Add additional checks for concat of non-empty strings to return non-falsy
This commit is contained in:
orklah 2022-10-15 14:37:11 +02:00 committed by GitHub
commit dbb8815813
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 53 additions and 3 deletions

View File

@ -199,6 +199,14 @@ class ConcatAnalyzer
$numeric_type
);
$right_is_numeric = UnionTypeComparator::isContainedBy(
$codebase,
$right_type,
$numeric_type
);
$has_numeric_type = $left_is_numeric || $right_is_numeric;
if ($left_is_numeric) {
$right_uint = Type::getPositiveInt();
$right_uint->addType(new TLiteralInt(0));
@ -230,16 +238,23 @@ class ConcatAnalyzer
$non_empty_string = clone $numeric_type;
$non_empty_string->addType(new TNonEmptyString());
$has_non_empty = UnionTypeComparator::isContainedBy(
$left_non_empty = UnionTypeComparator::isContainedBy(
$codebase,
$left_type,
$non_empty_string
) || UnionTypeComparator::isContainedBy(
);
$right_non_empty = UnionTypeComparator::isContainedBy(
$codebase,
$right_type,
$non_empty_string
);
$has_non_empty = $left_non_empty || $right_non_empty;
$all_non_empty = $left_non_empty && $right_non_empty;
$has_numeric_and_non_empty = $has_numeric_type && $has_non_empty;
$all_literals = $left_type->allLiterals() && $right_type->allLiterals();
if ($has_non_empty) {
@ -248,7 +263,8 @@ class ConcatAnalyzer
} elseif ($all_lowercase) {
$result_type = Type::getNonEmptyLowercaseString();
} else {
$result_type = Type::getNonEmptyString();
$result_type = $all_non_empty || $has_numeric_and_non_empty ?
Type::getNonFalsyString() : Type::getNonEmptyString();
}
} else {
if ($all_literals) {

View File

@ -34,6 +34,7 @@ use Psalm\Type\Atomic\TNever;
use Psalm\Type\Atomic\TNonEmptyList;
use Psalm\Type\Atomic\TNonEmptyLowercaseString;
use Psalm\Type\Atomic\TNonEmptyString;
use Psalm\Type\Atomic\TNonFalsyString;
use Psalm\Type\Atomic\TNull;
use Psalm\Type\Atomic\TNumeric;
use Psalm\Type\Atomic\TNumericString;
@ -219,6 +220,13 @@ abstract class Type
return new Union([$type]);
}
public static function getNonFalsyString(): Union
{
$type = new TNonFalsyString();
return new Union([$type]);
}
public static function getNumeric(): Union
{
$type = new TNumeric;

View File

@ -830,6 +830,32 @@ class BinaryOperationTest extends TestCase
return ($foo instanceof FooInterface ? $foo->toString() : null) ?? "Not a stringable foo";
}',
],
'concatNonEmptyReturnNonFalsyString' => [
'<?php
/** @var non-empty-string $s1 */
$s1 = "0";
/** @var non-empty-string $s1 */
$s2 = "0";
$a = $s1.$s2;',
'assertions' => [
'$a===' => 'non-falsy-string',
],
],
'concatNumericWithNonEmptyReturnNonFalsyString' => [
'<?php
/** @var numeric-string $s1 */
$s1 = "1";
/** @var non-empty-string $s2 */
$s2 = "0";
$a = $s1.$s2;
$b = $s2.$s1;',
'assertions' => [
'$a===' => 'non-falsy-string',
'$b===' => 'non-falsy-string',
],
],
];
}