Skip to content

Commit

Permalink
Fix non-empty-lowercase-string handling with literal non-lowercase st…
Browse files Browse the repository at this point in the history
…rings

* Fix #9782 and related issues
* add explicit handling for non-falsy-string to not fallback non-falsy-string and 0 to string
  • Loading branch information
kkmuffme committed Feb 19, 2024
1 parent d3c1222 commit f035c00
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 1 deletion.
37 changes: 36 additions & 1 deletion src/Psalm/Internal/Type/TypeCombiner.php
Original file line number Diff line number Diff line change
Expand Up @@ -1103,18 +1103,53 @@ private static function scrapeStringProperties(
} else {
$combination->value_types['string'] = $type;
}
} elseif ($type instanceof TNonFalsyString) {
$has_empty_string = false;
$has_falsy_string = false;

foreach ($combination->strings as $string_type) {
if ($string_type->value === '') {
$has_empty_string = true;
$has_falsy_string = true;
break;
}

if ($string_type->value === '0') {
$has_falsy_string = true;
}
}

if ($has_empty_string) {
$combination->value_types['string'] = new TString();
} elseif ($has_falsy_string) {
$combination->value_types['string'] = new TNonEmptyString();
} else {
$combination->value_types['string'] = $type;
}
} elseif ($type instanceof TNonEmptyString) {
$has_empty_string = false;

foreach ($combination->strings as $string_type) {
if (!$string_type->value) {
if ($string_type->value === '') {
$has_empty_string = true;
break;
}
}

$has_non_lowercase_string = false;
if ($type instanceof TNonEmptyLowercaseString) {
foreach ($combination->strings as $string_type) {
if (strtolower($string_type->value) !== $string_type->value) {
$has_non_lowercase_string = true;
break;
}
}
}

if ($has_empty_string) {
$combination->value_types['string'] = new TString();
} elseif ($has_non_lowercase_string && get_class($type) !== TNonEmptyString::class) {
$combination->value_types['string'] = new TNonEmptyString();
} else {
$combination->value_types['string'] = $type;
}
Expand Down
34 changes: 34 additions & 0 deletions tests/TypeCombinationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,40 @@ function takesLiteralString($arg) {}
'$x===' => 'non-falsy-string',
],
],
'loopNonFalsyWithZeroShouldBeNonEmpty' => [
'code' => '<?php
/**
* @psalm-suppress InvalidReturnType
* @return string[]
*/
function getStringArray() {}
$x = array();
foreach (getStringArray() as $id) {
$x[] = "0";
$x[] = "some_" . $id;
}',
'assertions' => [
'$x===' => 'list<non-empty-string>',
],
],
'loopNonLowercaseLiteralWithNonEmptyLowercaseShouldBeNonEmptyAndNotLowercase' => [
'code' => '<?php
/**
* @psalm-suppress InvalidReturnType
* @return int[]
*/
function getIntArray() {}
$x = array();
foreach (getIntArray() as $id) {
$x[] = "TEXT";
$x[] = "some_" . $id;
}',
'assertions' => [
'$x===' => 'list<non-empty-string>',
],
],
];
}

Expand Down

0 comments on commit f035c00

Please sign in to comment.