Skip to content

Commit c0bc2f7

Browse files
authored
Merge branch refs/heads/1.11.x into 1.12.x
2 parents aabea4c + aa7989f commit c0bc2f7

20 files changed

+339
-38
lines changed

build/datetime-php-83.neon

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
parameters:
2+
ignoreErrors:
3+
-
4+
message: "#^If condition is always false\\.$#"
5+
count: 1
6+
path: ../src/Type/Php/DateTimeModifyReturnTypeExtension.php
7+
8+
-
9+
message: "#^Strict comparison using \\=\\=\\= between DateTime and false will always evaluate to false\\.$#"
10+
count: 1
11+
path: ../src/Type/Php/DateTimeModifyReturnTypeExtension.php

build/ignore-by-php-version.neon.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@
3434
$includes[] = __DIR__ . '/spl-autoload-functions-php-8.neon';
3535
}
3636

37+
if (PHP_VERSION_ID >= 80300) {
38+
$includes[] = __DIR__ . '/datetime-php-83.neon';
39+
}
40+
3741
$config = [];
3842
$config['includes'] = $includes;
3943

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
"hoa/exception": "^1.0",
1717
"hoa/file": "1.17.07.11",
1818
"hoa/regex": "1.17.01.13",
19-
"jetbrains/phpstorm-stubs": "dev-master#cf7e447ddfa7f0cbab0c1dd38392f0cb05f9881c",
19+
"jetbrains/phpstorm-stubs": "dev-master#d5a839645a65f06c008779f42abfb6081353acc8",
2020
"nette/bootstrap": "^3.0",
2121
"nette/di": "^3.1.4",
2222
"nette/neon": "^3.3.1",

composer.lock

Lines changed: 5 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

conf/config.neon

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1378,6 +1378,11 @@ services:
13781378
tags:
13791379
- phpstan.dynamicStaticMethodThrowTypeExtension
13801380

1381+
-
1382+
class: PHPStan\Type\Php\DateTimeModifyMethodThrowTypeExtension
1383+
tags:
1384+
- phpstan.dynamicMethodThrowTypeExtension
1385+
13811386
-
13821387
class: PHPStan\Type\Php\DateTimeZoneConstructorThrowTypeExtension
13831388
tags:

resources/functionMap_php83delta.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
*/
2222
return [
2323
'new' => [
24+
'DateTime::modify' => ['static', 'modify'=>'string'],
25+
'DateTimeImmutable::modify' => ['static', 'modify'=>'string'],
2426
'str_decrement' => ['non-empty-string', 'string'=>'non-empty-string'],
2527
'str_increment' => ['non-falsy-string', 'string'=>'non-empty-string'],
2628
'gc_status' => ['array{running:bool,protected:bool,full:bool,runs:int,collected:int,threshold:int,buffer_size:int,roots:int,application_time:float,collector_time:float,destructor_time:float,free_time:float}'],

src/Php/PhpVersion.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,4 +309,9 @@ public function supportsNeverReturnTypeInArrowFunction(): bool
309309
return $this->versionId >= 80200;
310310
}
311311

312+
public function hasDateTimeExceptions(): bool
313+
{
314+
return $this->versionId >= 80300;
315+
}
316+
312317
}

src/Type/Php/DateIntervalConstructorThrowTypeExtension.php

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,22 @@
55
use DateInterval;
66
use PhpParser\Node\Expr\StaticCall;
77
use PHPStan\Analyser\Scope;
8+
use PHPStan\Php\PhpVersion;
89
use PHPStan\Reflection\MethodReflection;
910
use PHPStan\Type\DynamicStaticMethodThrowTypeExtension;
1011
use PHPStan\Type\NeverType;
12+
use PHPStan\Type\ObjectType;
1113
use PHPStan\Type\Type;
1214
use PHPStan\Type\TypeCombinator;
1315
use function count;
1416

1517
class DateIntervalConstructorThrowTypeExtension implements DynamicStaticMethodThrowTypeExtension
1618
{
1719

20+
public function __construct(private PhpVersion $phpVersion)
21+
{
22+
}
23+
1824
public function isStaticMethodSupported(MethodReflection $methodReflection): bool
1925
{
2026
return $methodReflection->getName() === '__construct' && $methodReflection->getDeclaringClass()->getName() === DateInterval::class;
@@ -33,17 +39,26 @@ public function getThrowTypeFromStaticMethodCall(MethodReflection $methodReflect
3339
try {
3440
new DateInterval($constantString->getValue());
3541
} catch (\Exception $e) { // phpcs:ignore
36-
return $methodReflection->getThrowType();
42+
return $this->exceptionType();
3743
}
3844

3945
$valueType = TypeCombinator::remove($valueType, $constantString);
4046
}
4147

4248
if (!$valueType instanceof NeverType) {
43-
return $methodReflection->getThrowType();
49+
return $this->exceptionType();
4450
}
4551

4652
return null;
4753
}
4854

55+
private function exceptionType(): Type
56+
{
57+
if ($this->phpVersion->hasDateTimeExceptions()) {
58+
return new ObjectType('DateMalformedIntervalStringException');
59+
}
60+
61+
return new ObjectType('Exception');
62+
}
63+
4964
}

src/Type/Php/DateTimeConstructorThrowTypeExtension.php

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@
66
use DateTimeImmutable;
77
use PhpParser\Node\Expr\StaticCall;
88
use PHPStan\Analyser\Scope;
9+
use PHPStan\Php\PhpVersion;
910
use PHPStan\Reflection\MethodReflection;
1011
use PHPStan\Type\DynamicStaticMethodThrowTypeExtension;
1112
use PHPStan\Type\NeverType;
13+
use PHPStan\Type\ObjectType;
1214
use PHPStan\Type\Type;
1315
use PHPStan\Type\TypeCombinator;
1416
use function count;
@@ -17,6 +19,10 @@
1719
class DateTimeConstructorThrowTypeExtension implements DynamicStaticMethodThrowTypeExtension
1820
{
1921

22+
public function __construct(private PhpVersion $phpVersion)
23+
{
24+
}
25+
2026
public function isStaticMethodSupported(MethodReflection $methodReflection): bool
2127
{
2228
return $methodReflection->getName() === '__construct' && in_array($methodReflection->getDeclaringClass()->getName(), [DateTime::class, DateTimeImmutable::class], true);
@@ -35,17 +41,26 @@ public function getThrowTypeFromStaticMethodCall(MethodReflection $methodReflect
3541
try {
3642
new DateTime($constantString->getValue());
3743
} catch (\Exception $e) { // phpcs:ignore
38-
return $methodReflection->getThrowType();
44+
return $this->exceptionType();
3945
}
4046

4147
$valueType = TypeCombinator::remove($valueType, $constantString);
4248
}
4349

4450
if (!$valueType instanceof NeverType) {
45-
return $methodReflection->getThrowType();
51+
return $this->exceptionType();
4652
}
4753

4854
return null;
4955
}
5056

57+
private function exceptionType(): Type
58+
{
59+
if ($this->phpVersion->hasDateTimeExceptions()) {
60+
return new ObjectType('DateMalformedStringException');
61+
}
62+
63+
return new ObjectType('Exception');
64+
}
65+
5166
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Type\Php;
4+
5+
use DateTime;
6+
use DateTimeImmutable;
7+
use PhpParser\Node\Expr\MethodCall;
8+
use PHPStan\Analyser\Scope;
9+
use PHPStan\Php\PhpVersion;
10+
use PHPStan\Reflection\MethodReflection;
11+
use PHPStan\Type\DynamicMethodThrowTypeExtension;
12+
use PHPStan\Type\NeverType;
13+
use PHPStan\Type\ObjectType;
14+
use PHPStan\Type\Type;
15+
use PHPStan\Type\TypeCombinator;
16+
use function count;
17+
use function in_array;
18+
19+
final class DateTimeModifyMethodThrowTypeExtension implements DynamicMethodThrowTypeExtension
20+
{
21+
22+
public function __construct(private PhpVersion $phpVersion)
23+
{
24+
}
25+
26+
public function isMethodSupported(MethodReflection $methodReflection): bool
27+
{
28+
return $methodReflection->getName() === 'modify' && in_array($methodReflection->getDeclaringClass()->getName(), [DateTime::class, DateTimeImmutable::class], true);
29+
}
30+
31+
public function getThrowTypeFromMethodCall(MethodReflection $methodReflection, MethodCall $methodCall, Scope $scope): ?Type
32+
{
33+
if (count($methodCall->getArgs()) === 0) {
34+
return null;
35+
}
36+
37+
if (!$this->phpVersion->hasDateTimeExceptions()) {
38+
return null;
39+
}
40+
41+
$valueType = $scope->getType($methodCall->getArgs()[0]->value);
42+
$constantStrings = $valueType->getConstantStrings();
43+
44+
foreach ($constantStrings as $constantString) {
45+
try {
46+
$dateTime = new DateTime();
47+
$dateTime->modify($constantString->getValue());
48+
} catch (\Exception $e) { // phpcs:ignore
49+
return $this->exceptionType();
50+
}
51+
52+
$valueType = TypeCombinator::remove($valueType, $constantString);
53+
}
54+
55+
if (!$valueType instanceof NeverType) {
56+
return $this->exceptionType();
57+
}
58+
59+
return null;
60+
}
61+
62+
private function exceptionType(): Type
63+
{
64+
if ($this->phpVersion->hasDateTimeExceptions()) {
65+
return new ObjectType('DateMalformedStringException');
66+
}
67+
68+
return new ObjectType('Exception');
69+
}
70+
71+
}

0 commit comments

Comments
 (0)