forked from phpstan/phpstan-src
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathRicherScopeGetTypeHelper.php
More file actions
95 lines (83 loc) · 2.86 KB
/
RicherScopeGetTypeHelper.php
File metadata and controls
95 lines (83 loc) · 2.86 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
<?php declare(strict_types = 1);
namespace PHPStan\Analyser;
use PhpParser\Node;
use PhpParser\Node\Expr\BinaryOp\Identical;
use PhpParser\Node\Expr\Variable;
use PHPStan\DependencyInjection\AutowiredService;
use PHPStan\Reflection\InitializerExprTypeResolver;
use PHPStan\Rules\Properties\PropertyReflectionFinder;
use PHPStan\Type\BooleanType;
use PHPStan\Type\Constant\ConstantBooleanType;
use PHPStan\Type\TypeResult;
use function is_string;
#[AutowiredService]
final class RicherScopeGetTypeHelper
{
public function __construct(
private InitializerExprTypeResolver $initializerExprTypeResolver,
private PropertyReflectionFinder $propertyReflectionFinder,
)
{
}
/**
* @return TypeResult<BooleanType>
*/
public function getIdenticalResult(Scope $scope, Identical $expr): TypeResult
{
if (
$expr->left instanceof Variable
&& is_string($expr->left->name)
&& $expr->right instanceof Variable
&& is_string($expr->right->name)
&& $expr->left->name === $expr->right->name
) {
$varType = $scope->getType($expr->left);
if (!$this->initializerExprTypeResolver->containsNan($varType)) {
return new TypeResult(new ConstantBooleanType(true), []);
}
}
$leftType = $scope->getType($expr->left);
$rightType = $scope->getType($expr->right);
if (
(
$expr->left instanceof Node\Expr\PropertyFetch
|| $expr->left instanceof Node\Expr\StaticPropertyFetch
)
&& $rightType->isNull()->yes()
) {
$foundPropertyReflections = $this->propertyReflectionFinder->findPropertyReflectionsFromNode($expr->left, $scope);
foreach ($foundPropertyReflections as $foundPropertyReflection) {
if ($foundPropertyReflection->isNative() && !$foundPropertyReflection->hasNativeType()) {
return new TypeResult(new BooleanType(), []);
}
}
}
if (
(
$expr->right instanceof Node\Expr\PropertyFetch
|| $expr->right instanceof Node\Expr\StaticPropertyFetch
)
&& $leftType->isNull()->yes()
) {
$foundPropertyReflections = $this->propertyReflectionFinder->findPropertyReflectionsFromNode($expr->right, $scope);
foreach ($foundPropertyReflections as $foundPropertyReflection) {
if ($foundPropertyReflection->isNative() && !$foundPropertyReflection->hasNativeType()) {
return new TypeResult(new BooleanType(), []);
}
}
}
return $this->initializerExprTypeResolver->resolveIdenticalType($leftType, $rightType);
}
/**
* @return TypeResult<BooleanType>
*/
public function getNotIdenticalResult(Scope $scope, Node\Expr\BinaryOp\NotIdentical $expr): TypeResult
{
$identicalResult = $this->getIdenticalResult($scope, new Identical($expr->left, $expr->right));
$identicalType = $identicalResult->type;
if ($identicalType instanceof ConstantBooleanType) {
return new TypeResult(new ConstantBooleanType(!$identicalType->getValue()), $identicalResult->reasons);
}
return new TypeResult(new BooleanType(), []);
}
}