Skip to content

Commit 455ae30

Browse files
ondrejmirtesclaude
andcommitted
Move collectOffsetSetUsage() from NodeScopeResolver to AssignHandler
AssignHandler is its only caller, so it becomes a private method there, observing through the handler's own TemplateArgumentObserver. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014hgcbwfKQnye2coQXtX5XU
1 parent 0b2855e commit 455ae30

2 files changed

Lines changed: 29 additions & 27 deletions

File tree

‎src/Analyser/ExprHandler/AssignHandler.php‎

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
use PHPStan\Analyser\ExprHandler\Helper\MethodThrowPointHelper;
3737
use PHPStan\Analyser\ExprHandler\Helper\NonNullabilityHelper;
3838
use PHPStan\Analyser\ExprHandler\Helper\VirtualExprResultHelper;
39+
use PHPStan\Analyser\Generics\TemplateArgumentConstraints;
3940
use PHPStan\Analyser\Generics\TemplateArgumentObserver;
4041
use PHPStan\Analyser\ImpurePoint;
4142
use PHPStan\Analyser\InternalThrowPoint;
@@ -1492,7 +1493,8 @@ public function applyWrite(
14921493
&& !$setVarType->isArray()->yes()
14931494
&& !(new ObjectType(ArrayAccess::class))->isSuperTypeOf($setVarType)->no()
14941495
) {
1495-
$scope = $scope->addTemplateArgumentConstraints($nodeScopeResolver->collectOffsetSetUsage(
1496+
$scope = $scope->addTemplateArgumentConstraints($this->collectOffsetSetUsage(
1497+
$nodeScopeResolver,
14961498
$scope,
14971499
$setVarType,
14981500
$offsetTypes[count($offsetTypes) - 1][0],
@@ -1813,6 +1815,32 @@ public function applyWrite(
18131815
);
18141816
}
18151817

1818+
/**
1819+
* A write through ArrayAccess (`$storage[$key] = $value`) reaches the
1820+
* object's template arguments exactly like the offsetSet() call it stands
1821+
* for, so observe both the key and the written value against that method's
1822+
* parameters resolved on the receiver.
1823+
*/
1824+
private function collectOffsetSetUsage(NodeScopeResolver $nodeScopeResolver, MutatingScope $scope, Type $receiverType, ?Type $keyType, Type $valueType): TemplateArgumentConstraints
1825+
{
1826+
$constraints = TemplateArgumentConstraints::createEmpty();
1827+
$frame = $nodeScopeResolver->observingTemplateArgumentFrame($scope);
1828+
if ($frame === null || !$receiverType->hasMethod('offsetSet')->yes()) {
1829+
return $constraints;
1830+
}
1831+
1832+
$parameters = $receiverType->getMethod('offsetSet', $scope)->getOnlyVariant()->getParameters();
1833+
if ($keyType !== null && isset($parameters[0])) {
1834+
$constraints = $constraints->merge($this->templateArgumentObserver->collectArgument($parameters[0]->getType(), $keyType));
1835+
}
1836+
if (!isset($parameters[1])) {
1837+
return $constraints;
1838+
}
1839+
1840+
$constraints = $constraints->merge($this->templateArgumentObserver->collectArgument($parameters[1]->getType(), $valueType));
1841+
return $constraints;
1842+
}
1843+
18161844
private function createArrayDimFetchConditionalExpressionHolder(
18171845
Expr\Variable $keyVar,
18181846
Expr $arrayArg,

‎src/Analyser/NodeScopeResolver.php‎

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1067,30 +1067,4 @@ public function collectReturnSend(MutatingScope $scope, ExpressionResult $return
10671067
return $this->templateArgumentObserver->collectSend($declaredReturnType, $returnedResult->getType());
10681068
}
10691069

1070-
/**
1071-
* A write through ArrayAccess (`$storage[$key] = $value`) reaches the
1072-
* object's template arguments exactly like the offsetSet() call it stands
1073-
* for, so observe both the key and the written value against that method's
1074-
* parameters resolved on the receiver.
1075-
*/
1076-
public function collectOffsetSetUsage(MutatingScope $scope, Type $receiverType, ?Type $keyType, Type $valueType): TemplateArgumentConstraints
1077-
{
1078-
$constraints = TemplateArgumentConstraints::createEmpty();
1079-
$frame = $this->observingTemplateArgumentFrame($scope);
1080-
if ($frame === null || !$receiverType->hasMethod('offsetSet')->yes()) {
1081-
return $constraints;
1082-
}
1083-
1084-
$parameters = $receiverType->getMethod('offsetSet', $scope)->getOnlyVariant()->getParameters();
1085-
if ($keyType !== null && isset($parameters[0])) {
1086-
$constraints = $constraints->merge($this->templateArgumentObserver->collectArgument($parameters[0]->getType(), $keyType));
1087-
}
1088-
if (!isset($parameters[1])) {
1089-
return $constraints;
1090-
}
1091-
1092-
$constraints = $constraints->merge($this->templateArgumentObserver->collectArgument($parameters[1]->getType(), $valueType));
1093-
return $constraints;
1094-
}
1095-
10961070
}

0 commit comments

Comments
 (0)