Skip to content

Commit bbdfcb4

Browse files
committed
Implement SocketCreateReturnTypeExtension
1 parent 2d637da commit bbdfcb4

File tree

4 files changed

+71
-0
lines changed

4 files changed

+71
-0
lines changed

conf/config.neon

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1820,6 +1820,11 @@ services:
18201820
tags:
18211821
- phpstan.broker.dynamicMethodReturnTypeExtension
18221822

1823+
-
1824+
class: PHPStan\Type\Php\SocketCreateReturnTypeExtension
1825+
tags:
1826+
- phpstan.broker.dynamicFunctionReturnTypeExtension
1827+
18231828
-
18241829
class: PHPStan\Type\Php\StrSplitFunctionReturnTypeExtension
18251830
tags:

src/Php/PhpVersions.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,9 @@ public function producesWarningForFinalPrivateMethods(): TrinaryLogic
2323
return IntegerRangeType::fromInterval(80000, null)->isSuperTypeOf($this->phpVersions)->result;
2424
}
2525

26+
public function socketCreateUsesResource(): TrinaryLogic
27+
{
28+
return IntegerRangeType::fromInterval(null, 80000)->isSuperTypeOf($this->phpVersions)->result;
29+
}
30+
2631
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
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\Reflection\FunctionReflection;
8+
use PHPStan\Type\Constant\ConstantBooleanType;
9+
use PHPStan\Type\DynamicFunctionReturnTypeExtension;
10+
use PHPStan\Type\ObjectType;
11+
use PHPStan\Type\ResourceType;
12+
use PHPStan\Type\Type;
13+
use PHPStan\Type\UnionType;
14+
use Socket;
15+
use function count;
16+
17+
final class SocketCreateReturnTypeExtension implements DynamicFunctionReturnTypeExtension
18+
{
19+
20+
public function isFunctionSupported(FunctionReflection $functionReflection): bool
21+
{
22+
return $functionReflection->getName() === 'socket_create';
23+
}
24+
25+
public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope): ?Type
26+
{
27+
if (count($functionCall->getArgs()) < 3) {
28+
return null;
29+
}
30+
31+
if ($scope->getPhpVersion()->socketCreateUsesResource()->no()) {
32+
return new UnionType([new ConstantBooleanType(false), new ObjectType(Socket::class)]);
33+
}
34+
35+
if ($scope->getPhpVersion()->socketCreateUsesResource()->yes()) {
36+
return new UnionType([new ConstantBooleanType(false), new ResourceType()]);
37+
}
38+
39+
return null;
40+
}
41+
42+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php // lint >= 7.4
2+
3+
declare(strict_types=1);
4+
5+
namespace SocketCreate;
6+
7+
use function PHPStan\Testing\assertType;
8+
9+
class HelloWorld
10+
{
11+
public function sayHello(): void
12+
{
13+
if (PHP_VERSION_ID < 80000) {
14+
assertType('resource|false', socket_create(AF_INET, SOCK_DGRAM, SOL_UDP));
15+
return;
16+
}
17+
assertType('Socket|false', socket_create(AF_INET, SOCK_DGRAM, SOL_UDP));
18+
}
19+
}

0 commit comments

Comments
 (0)