Skip to content

Commit 5f49473

Browse files
committed
PropertyHandler
1 parent 7ed992a commit 5f49473

File tree

1 file changed

+127
-0
lines changed

1 file changed

+127
-0
lines changed
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Analyser\Generator\StmtHandler;
4+
5+
use Generator;
6+
use PhpParser\Node\Stmt;
7+
use PhpParser\Node\Stmt\Property;
8+
use PHPStan\Analyser\ExpressionContext;
9+
use PHPStan\Analyser\Generator\AttrGroupsAnalysisRequest;
10+
use PHPStan\Analyser\Generator\ExprAnalysisRequest;
11+
use PHPStan\Analyser\Generator\GeneratorScope;
12+
use PHPStan\Analyser\Generator\NodeCallbackRequest;
13+
use PHPStan\Analyser\Generator\NodeHandler\PropertyHooksHandler;
14+
use PHPStan\Analyser\Generator\NodeHandler\StatementPhpDocsHelper;
15+
use PHPStan\Analyser\Generator\StmtAnalysisResult;
16+
use PHPStan\Analyser\Generator\StmtHandler;
17+
use PHPStan\Analyser\StatementContext;
18+
use PHPStan\DependencyInjection\AutowiredService;
19+
use PHPStan\Node\ClassPropertyNode;
20+
use PHPStan\ShouldNotHappenException;
21+
use PHPStan\Type\ParserNodeTypeToPHPStanType;
22+
use function count;
23+
24+
/**
25+
* @implements StmtHandler<Property>
26+
*/
27+
#[AutowiredService]
28+
final class PropertyHandler implements StmtHandler
29+
{
30+
31+
public function __construct(
32+
private StatementPhpDocsHelper $statementPhpDocsHelper,
33+
private PropertyHooksHandler $propertyHooksHandler,
34+
)
35+
{
36+
}
37+
38+
public function supports(Stmt $stmt): bool
39+
{
40+
return $stmt instanceof Property;
41+
}
42+
43+
public function analyseStmt(Stmt $stmt, GeneratorScope $scope, StatementContext $context, ?callable $alternativeNodeCallback): Generator
44+
{
45+
yield new AttrGroupsAnalysisRequest($stmt, $stmt->attrGroups, $scope, $alternativeNodeCallback);
46+
47+
$nativePropertyType = $stmt->type !== null ? ParserNodeTypeToPHPStanType::resolve($stmt->type, $scope->getClassReflection()) : null;
48+
49+
[,,,,,,,,,,,,$isReadOnly, $docComment, ,,,$varTags, $isAllowedPrivateMutation] = $this->statementPhpDocsHelper->getPhpDocs($scope, $stmt);
50+
$phpDocType = null;
51+
if (isset($varTags[0]) && count($varTags) === 1) {
52+
$phpDocType = $varTags[0]->getType();
53+
}
54+
55+
foreach ($stmt->props as $prop) {
56+
yield new NodeCallbackRequest($prop, $scope, $alternativeNodeCallback);
57+
if ($prop->default !== null) {
58+
yield new ExprAnalysisRequest($stmt, $prop->default, $scope, ExpressionContext::createDeep(), $alternativeNodeCallback);
59+
}
60+
61+
if (!$scope->isInClass()) {
62+
throw new ShouldNotHappenException();
63+
}
64+
$propertyName = $prop->name->toString();
65+
66+
if ($phpDocType === null) {
67+
if (isset($varTags[$propertyName])) {
68+
$phpDocType = $varTags[$propertyName]->getType();
69+
}
70+
}
71+
72+
$propStmt = clone $stmt;
73+
$propStmt->setAttributes($prop->getAttributes());
74+
$propStmt->setAttribute('originalPropertyStmt', $stmt);
75+
yield new NodeCallbackRequest(
76+
new ClassPropertyNode(
77+
$propertyName,
78+
$stmt->flags,
79+
$nativePropertyType,
80+
$prop->default,
81+
$docComment,
82+
$phpDocType,
83+
false,
84+
false,
85+
$propStmt,
86+
$isReadOnly,
87+
$scope->isInTrait(),
88+
$scope->getClassReflection()->isReadOnly(),
89+
$isAllowedPrivateMutation,
90+
$scope->getClassReflection(),
91+
),
92+
$scope,
93+
$alternativeNodeCallback,
94+
);
95+
}
96+
97+
if (count($stmt->hooks) > 0) {
98+
if (!isset($propertyName)) {
99+
throw new ShouldNotHappenException('Property name should be known when analysing hooks.');
100+
}
101+
102+
yield from $this->propertyHooksHandler->processPropertyHooks(
103+
$stmt,
104+
$stmt->type,
105+
$phpDocType,
106+
$propertyName,
107+
$stmt->hooks,
108+
$scope,
109+
$alternativeNodeCallback,
110+
);
111+
}
112+
113+
if ($stmt->type !== null) {
114+
yield new NodeCallbackRequest($stmt->type, $scope, $alternativeNodeCallback);
115+
}
116+
117+
return new StmtAnalysisResult(
118+
$scope,
119+
hasYield: false,
120+
isAlwaysTerminating: false,
121+
exitPoints: [],
122+
throwPoints: [],
123+
impurePoints: [],
124+
);
125+
}
126+
127+
}

0 commit comments

Comments
 (0)