Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit a80fd40

Browse files
VincentLangletondrejmirtes
authored andcommitted
Add VersionCompareFunctionDynamicThrowTypeExtension
1 parent 825367d commit a80fd40

File tree

4 files changed

+86
-1
lines changed

4 files changed

+86
-1
lines changed

‎src/Type/Php/VersionCompareFunctionDynamicReturnTypeExtension.php‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
final class VersionCompareFunctionDynamicReturnTypeExtension implements DynamicFunctionReturnTypeExtension
3030
{
3131

32-
private const VALID_OPERATORS = [
32+
public const VALID_OPERATORS = [
3333
'<',
3434
'lt',
3535
'<=',
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Type\Php;
4+
5+
use PhpParser\Node\Expr\FuncCall;
6+
use PHPStan\Analyser\Scope;
7+
use PHPStan\DependencyInjection\AutowiredService;
8+
use PHPStan\Php\PhpVersion;
9+
use PHPStan\Reflection\FunctionReflection;
10+
use PHPStan\Type\DynamicFunctionThrowTypeExtension;
11+
use PHPStan\Type\Type;
12+
use function count;
13+
use function in_array;
14+
15+
#[AutowiredService]
16+
final class VersionCompareFunctionDynamicThrowTypeExtension implements DynamicFunctionThrowTypeExtension
17+
{
18+
19+
public function __construct(
20+
private PhpVersion $phpVersion,
21+
)
22+
{
23+
}
24+
25+
public function isFunctionSupported(FunctionReflection $functionReflection): bool
26+
{
27+
return $functionReflection->getName() === 'version_compare';
28+
}
29+
30+
public function getThrowTypeFromFunctionCall(
31+
FunctionReflection $functionReflection,
32+
FuncCall $funcCall,
33+
Scope $scope,
34+
): ?Type
35+
{
36+
if (!$this->phpVersion->throwsValueErrorForInternalFunctions()) {
37+
return null;
38+
}
39+
40+
$args = $funcCall->getArgs();
41+
if (!isset($args[2])) {
42+
return null;
43+
}
44+
45+
$operatorStrings = $scope->getType($args[2]->value)->getConstantStrings();
46+
if (count($operatorStrings) === 0) {
47+
return $functionReflection->getThrowType();
48+
}
49+
50+
foreach ($operatorStrings as $operatorString) {
51+
$operatorValue = $operatorString->getValue();
52+
if (!in_array($operatorValue, VersionCompareFunctionDynamicReturnTypeExtension::VALID_OPERATORS, true)) {
53+
return $functionReflection->getThrowType();
54+
}
55+
}
56+
57+
return null;
58+
}
59+
60+
}

‎tests/PHPStan/Rules/Exceptions/ThrowsVoidFunctionWithExplicitThrowPointRuleTest.php‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,4 +97,11 @@ public function testRule(bool $missingCheckedExceptionInThrows, array $checkedEx
9797
$this->analyse([__DIR__ . '/data/throws-void-function.php'], $errors);
9898
}
9999

100+
public function testBug13515(): void
101+
{
102+
$this->missingCheckedExceptionInThrows = false;
103+
$this->checkedExceptionClasses = [];
104+
$this->analyse([__DIR__ . '/data/bug-13515.php'], []);
105+
}
106+
100107
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
namespace Bug13515;
4+
5+
/** @throws void */
6+
function fromArray(string $name, string $versionWithoutMicro) : void
7+
{
8+
if ($name === 'Mac OS X'
9+
&& \version_compare(
10+
$versionWithoutMicro,
11+
'10.12',
12+
'>='
13+
)
14+
) {
15+
$name = 'macOS';
16+
$marketingName = 'macOS';
17+
}
18+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /