Skip to content

Commit 4b35722

Browse files
committed
Add exceptional case for DateInterval::format return type inference
Difference in days might behave differently when the DateInterval is created from scratch or from a diff. Filter returned type information for DateInterval::format. It can only be non-falsy for sure if it's not '%a'.
1 parent 6e498e6 commit 4b35722

File tree

2 files changed

+9
-4
lines changed

2 files changed

+9
-4
lines changed

src/Type/Php/DateIntervalFormatDynamicReturnTypeExtension.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,17 +56,20 @@ public function getTypeFromMethodCall(MethodReflection $methodReflection, Method
5656
}
5757

5858
// The worst case scenario for the non-falsy-string check is that every number is 0.
59+
// `%a` format gives `(unknown)` and removes numeric and uppercase accessory but then
60+
// we'll have to manually check for the non-falsy one.
5961
$dateInterval = new DateInterval('P0D');
6062

6163
$possibleReturnTypes = [];
6264
foreach ($constantStrings as $string) {
63-
$value = $dateInterval->format($string->getValue());
65+
$formatString = $string->getValue();
66+
$value = $dateInterval->format($formatString);
6467

6568
$accessories = [];
6669
if (is_numeric($value)) {
6770
$accessories[] = new AccessoryNumericStringType();
6871
}
69-
if ($value !== '0' && $value !== '') {
72+
if ($value !== '0' && $value !== '' && $formatString !== '%a') {
7073
$accessories[] = new AccessoryNonFalsyStringType();
7174
} elseif ($value !== '') {
7275
$accessories[] = new AccessoryNonEmptyStringType();

tests/PHPStan/Analyser/nsrt/bug-1452.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,7 @@
66

77
$dateInterval = (new \DateTimeImmutable('now -60 minutes'))->diff(new \DateTimeImmutable('now'));
88

9-
// Could be lowercase-string&non-falsy-string&numeric-string&uppercase-string
10-
assertType('lowercase-string&non-falsy-string', $dateInterval->format('%a'));
9+
assertType(
10+
'lowercase-string&non-empty-string',
11+
$dateInterval->format('%a')
12+
);

0 commit comments

Comments
 (0)