Skip to content

Commit e501091

Browse files
committed
Rework processing inline @var
1 parent 1a843eb commit e501091

File tree

5 files changed

+78
-28
lines changed

5 files changed

+78
-28
lines changed

src/Analyser/NodeScopeResolver.php

Lines changed: 46 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1168,13 +1168,20 @@ private function processStmtNode(
11681168
}
11691169
} elseif ($stmt instanceof Static_) {
11701170
$hasYield = false;
1171-
$comment = CommentHelper::getDocComment($stmt);
1171+
1172+
$vars = [];
11721173
foreach ($stmt->vars as $var) {
11731174
$scope = $this->processStmtNode($var, $scope, $nodeCallback)->getScope();
1174-
if ($comment === null || !is_string($var->var->name)) {
1175+
if (!is_string($var->var->name)) {
11751176
continue;
11761177
}
1177-
$scope = $this->processVarAnnotation($scope, $var->var->name, $comment, false);
1178+
1179+
$vars[] = $var->var->name;
1180+
}
1181+
1182+
$comment = CommentHelper::getDocComment($stmt);
1183+
if ($comment !== null) {
1184+
$scope = $this->processVarAnnotation($scope, $vars, $comment);
11781185
}
11791186
} elseif ($stmt instanceof StaticVar) {
11801187
$hasYield = false;
@@ -1523,7 +1530,7 @@ function (MutatingScope $scope) use ($expr, $nodeCallback, $context): Expression
15231530
if ($expr->var instanceof Variable && is_string($expr->var->name)) {
15241531
$comment = CommentHelper::getDocComment($expr);
15251532
if ($comment !== null) {
1526-
$scope = $this->processVarAnnotation($scope, $expr->var->name, $comment, false, $varChangedScope);
1533+
$scope = $this->processVarAnnotation($scope, [$expr->var->name], $comment, $varChangedScope);
15271534
}
15281535
}
15291536

@@ -1552,6 +1559,7 @@ function (MutatingScope $scope) use ($expr, $nodeCallback, $context): Expression
15521559
$scope = $this->lookForArrayDestructuringArray($scope, $expr->var, $scope->getType($expr->expr));
15531560
$comment = CommentHelper::getDocComment($expr);
15541561
if ($comment !== null) {
1562+
$vars = [];
15551563
foreach ($expr->var->items as $arrayItem) {
15561564
if ($arrayItem === null) {
15571565
continue;
@@ -1560,15 +1568,17 @@ function (MutatingScope $scope) use ($expr, $nodeCallback, $context): Expression
15601568
continue;
15611569
}
15621570

1571+
$vars[] = $arrayItem->value->name;
1572+
}
1573+
1574+
if (count($vars) > 0) {
15631575
$varChangedScope = false;
1564-
$scope = $this->processVarAnnotation($scope, $arrayItem->value->name, $comment, true, $varChangedScope);
1565-
if ($varChangedScope) {
1566-
continue;
1576+
$scope = $this->processVarAnnotation($scope, $vars, $comment, $varChangedScope);
1577+
if (!$varChangedScope) {
1578+
$scope = $this->processStmtVarAnnotation($scope, new Node\Stmt\Expression($expr, [
1579+
'comments' => $expr->getAttribute('comments'),
1580+
]), null);
15671581
}
1568-
1569-
$scope = $this->processStmtVarAnnotation($scope, new Node\Stmt\Expression($expr, [
1570-
'comments' => $expr->getAttribute('comments'),
1571-
]), null);
15721582
}
15731583
}
15741584
}
@@ -2820,7 +2830,14 @@ private function processStmtVarAnnotation(MutatingScope $scope, Node\Stmt $stmt,
28202830
return $scope;
28212831
}
28222832

2823-
private function processVarAnnotation(MutatingScope $scope, string $variableName, string $comment, bool $strict, bool &$changed = false): MutatingScope
2833+
/**
2834+
* @param MutatingScope $scope
2835+
* @param array<int, string> $variableNames
2836+
* @param string $comment
2837+
* @param bool $changed
2838+
* @return MutatingScope
2839+
*/
2840+
private function processVarAnnotation(MutatingScope $scope, array $variableNames, string $comment, bool &$changed = false): MutatingScope
28242841
{
28252842
$function = $scope->getFunction();
28262843
$resolvedPhpDoc = $this->fileTypeMapper->getResolvedPhpDoc(
@@ -2832,27 +2849,29 @@ private function processVarAnnotation(MutatingScope $scope, string $variableName
28322849
);
28332850
$varTags = $resolvedPhpDoc->getVarTags();
28342851

2835-
if (isset($varTags[$variableName])) {
2852+
foreach ($variableNames as $variableName) {
2853+
if (!isset($varTags[$variableName])) {
2854+
continue;
2855+
}
2856+
28362857
$variableType = $varTags[$variableName]->getType();
28372858
$changed = true;
2838-
return $scope->assignVariable($variableName, $variableType);
2839-
2859+
$scope = $scope->assignVariable($variableName, $variableType);
28402860
}
28412861

2842-
if (!$strict && count($varTags) === 1 && isset($varTags[0])) {
2862+
if (count($variableNames) === 1 && count($varTags) === 1 && isset($varTags[0])) {
28432863
$variableType = $varTags[0]->getType();
28442864
$changed = true;
2845-
return $scope->assignVariable($variableName, $variableType);
2846-
2865+
$scope = $scope->assignVariable($variableNames[0], $variableType);
28472866
}
28482867

28492868
return $scope;
28502869
}
28512870

28522871
private function enterForeach(MutatingScope $scope, Foreach_ $stmt): MutatingScope
28532872
{
2854-
$comment = CommentHelper::getDocComment($stmt);
28552873
$iterateeType = $scope->getType($stmt->expr);
2874+
$vars = [];
28562875
if ($stmt->valueVar instanceof Variable && is_string($stmt->valueVar->name)) {
28572876
$scope = $scope->enterForeach(
28582877
$stmt->expr,
@@ -2863,21 +2882,17 @@ private function enterForeach(MutatingScope $scope, Foreach_ $stmt): MutatingSco
28632882
? $stmt->keyVar->name
28642883
: null
28652884
);
2866-
if ($comment !== null) {
2867-
$scope = $this->processVarAnnotation($scope, $stmt->valueVar->name, $comment, true);
2868-
}
2885+
$vars[] = $stmt->valueVar->name;
28692886
}
28702887

28712888
if (
28722889
$stmt->keyVar instanceof Variable && is_string($stmt->keyVar->name)
28732890
) {
28742891
$scope = $scope->enterForeachKey($stmt->expr, $stmt->keyVar->name);
2875-
2876-
if ($comment !== null) {
2877-
$scope = $this->processVarAnnotation($scope, $stmt->keyVar->name, $comment, true);
2878-
}
2892+
$vars[] = $stmt->keyVar->name;
28792893
}
28802894

2895+
$comment = CommentHelper::getDocComment($stmt);
28812896
if (
28822897
$comment === null
28832898
&& $iterateeType instanceof ConstantArrayType
@@ -2902,7 +2917,6 @@ private function enterForeach(MutatingScope $scope, Foreach_ $stmt): MutatingSco
29022917
$exprType = $scope->getType($stmt->expr);
29032918
$itemType = $exprType->getIterableValueType();
29042919
$scope = $this->lookForArrayDestructuringArray($scope, $stmt->valueVar, $itemType);
2905-
$comment = CommentHelper::getDocComment($stmt);
29062920
if ($comment !== null) {
29072921
foreach ($stmt->valueVar->items as $arrayItem) {
29082922
if ($arrayItem === null) {
@@ -2912,11 +2926,15 @@ private function enterForeach(MutatingScope $scope, Foreach_ $stmt): MutatingSco
29122926
continue;
29132927
}
29142928

2915-
$scope = $this->processVarAnnotation($scope, $arrayItem->value->name, $comment, true);
2929+
$vars[] = $arrayItem->value->name;
29162930
}
29172931
}
29182932
}
29192933

2934+
if ($comment !== null) {
2935+
$scope = $this->processVarAnnotation($scope, $vars, $comment);
2936+
}
2937+
29202938
return $scope;
29212939
}
29222940

src/Rules/PhpDoc/WrongVariableNameInVarTagRule.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,9 @@ private function processForeach(?Node\Expr $keyVar, Node\Expr $valueVar, array $
138138
$errors = [];
139139
foreach (array_keys($varTags) as $name) {
140140
if (is_int($name)) {
141+
if (count($variableNames) === 1) {
142+
continue;
143+
}
141144
$errors[] = RuleErrorBuilder::message(
142145
'PHPDoc tag @var above foreach loop does not specify variable name.'
143146
)->build();

tests/PHPStan/Analyser/NodeScopeResolverTest.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4771,6 +4771,11 @@ public function dataForeachArrayType(): array
47714771
],
47724772
[
47734773
__DIR__ . '/data/foreach/type-in-comment-no-variable.php',
4774+
'bool',
4775+
'$value',
4776+
],
4777+
[
4778+
__DIR__ . '/data/foreach/type-in-comment-no-variable-2.php',
47744779
'mixed',
47754780
'$value',
47764781
],
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
3+
namespace TypeInCommentOnForeach;
4+
5+
/** @var mixed[] $values */
6+
$values = [];
7+
8+
/** @var bool */
9+
foreach ($values as $key => $value) {
10+
die;
11+
}

tests/PHPStan/Rules/PhpDoc/data/wrong-variable-name-var.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,3 +224,16 @@ class Bar
224224
const TEST = 'str';
225225

226226
}
227+
228+
class ForeachJustValueVar
229+
{
230+
231+
public function doBar(array $list)
232+
{
233+
/** @var int */
234+
foreach ($list as $val) {
235+
236+
}
237+
}
238+
239+
}

0 commit comments

Comments
 (0)