Skip to content

Commit f3fe245

Browse files
committed
Make MutatingScope::invalidateMethodsOnExpression() private
1 parent a96cdf2 commit f3fe245

File tree

3 files changed

+82
-3
lines changed

3 files changed

+82
-3
lines changed

src/Analyser/MutatingScope.php

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3428,14 +3428,31 @@ public function unsetExpression(Expr $expr): self
34283428
$this->parentScope,
34293429
);
34303430
} elseif ($expr instanceof Expr\ArrayDimFetch && $expr->dim !== null) {
3431-
return $this->specifyExpressionType(
3431+
$exprVarType = $this->getType($expr->var);
3432+
$dimType = $this->getType($expr->dim);
3433+
$unset = $exprVarType->unsetOffset($dimType);
3434+
$scope = $this->specifyExpressionType(
34323435
$expr->var,
3433-
$this->getType($expr->var)->unsetOffset($this->getType($expr->dim)),
3436+
$unset,
34343437
)->invalidateExpression(
34353438
new FuncCall(new FullyQualified('count'), [new Arg($expr->var)]),
34363439
)->invalidateExpression(
34373440
new FuncCall(new FullyQualified('sizeof'), [new Arg($expr->var)]),
34383441
);
3442+
3443+
if ($expr->var instanceof Expr\ArrayDimFetch && $expr->var->dim !== null) {
3444+
$varVar = $this->getType($expr->var->var);
3445+
$varDim = $this->getType($expr->var->dim);
3446+
$scope = $scope->specifyExpressionType(
3447+
$expr->var->var,
3448+
TypeCombinator::union($varVar->setOffsetValueType(
3449+
$varDim,
3450+
TypeCombinator::union($varVar->getOffsetValueType($varDim), new ConstantArrayType([], [])),
3451+
), new ConstantArrayType([], [])),
3452+
);
3453+
}
3454+
3455+
return $scope;
34393456
}
34403457

34413458
return $this;
@@ -3697,7 +3714,7 @@ private function exprStringToExpr(string $exprString): ?Expr
36973714
return $expr->expr;
36983715
}
36993716

3700-
public function invalidateMethodsOnExpression(Expr $expressionToInvalidate): self
3717+
private function invalidateMethodsOnExpression(Expr $expressionToInvalidate): self
37013718
{
37023719
$exprStringToInvalidate = $this->getNodeKey($expressionToInvalidate);
37033720
$moreSpecificTypeHolders = $this->moreSpecificTypes;

tests/PHPStan/Analyser/NodeScopeResolverTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -998,6 +998,7 @@ public function dataFileAsserts(): iterable
998998
yield from $this->gatherAssertTypes(__DIR__ . '/data/array-flip-constant.php');
999999
yield from $this->gatherAssertTypes(__DIR__ . '/data/array-filter-constant.php');
10001000
yield from $this->gatherAssertTypes(__DIR__ . '/data/array-intersect-key-constant.php');
1001+
yield from $this->gatherAssertTypes(__DIR__ . '/data/composer-array-bug.php');
10011002
}
10021003

10031004
/**
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
<?php
2+
3+
namespace ComposerArrayBug;
4+
5+
use function PHPStan\Testing\assertType;
6+
7+
class Foo
8+
{
9+
10+
/** @var mixed[] */
11+
private $config;
12+
13+
/** @var string[] */
14+
private $errors;
15+
16+
public function doFoo(): void
17+
{
18+
if (!empty($this->config['authors'])) {
19+
foreach ($this->config['authors'] as $key => $author) {
20+
if (!is_array($author)) {
21+
$this->errors[] = 'authors.'.$key.' : should be an array, '.gettype($author).' given';
22+
assertType("mixed~0|0.0|''|'0'|false|null", $this->config['authors']);
23+
unset($this->config['authors'][$key]);
24+
assertType("mixed~0|0.0|''|'0'|false|null", $this->config['authors']);
25+
continue;
26+
}
27+
assertType("mixed~0|0.0|''|'0'|false|null", $this->config['authors']);
28+
foreach (['homepage', 'email', 'name', 'role'] as $authorData) {
29+
if (isset($author[$authorData]) && !is_string($author[$authorData])) {
30+
$this->errors[] = 'authors.'.$key.'.'.$authorData.' : invalid value, must be a string';
31+
unset($this->config['authors'][$key][$authorData]);
32+
}
33+
}
34+
if (isset($author['homepage'])) {
35+
assertType("mixed~0|0.0|''|'0'|false|null", $this->config['authors']);
36+
unset($this->config['authors'][$key]['homepage']);
37+
assertType("mixed~0|0.0|''|'0'|false|null", $this->config['authors']);
38+
}
39+
if (isset($author['email']) && !filter_var($author['email'], FILTER_VALIDATE_EMAIL)) {
40+
unset($this->config['authors'][$key]['email']);
41+
}
42+
if (empty($this->config['authors'][$key])) {
43+
unset($this->config['authors'][$key]);
44+
}
45+
}
46+
47+
assertType("array&hasOffsetValue('authors', mixed~0|0.0|''|'0'|false|null)", $this->config);
48+
assertType("mixed~0|0.0|''|'0'|false|null", $this->config['authors']);
49+
50+
if (empty($this->config['authors'])) {
51+
unset($this->config['authors']);
52+
assertType("array", $this->config);
53+
} else {
54+
assertType("array&hasOffsetValue('authors', mixed~0|0.0|''|'0'|array{}|false|null)", $this->config);
55+
}
56+
57+
assertType('array', $this->config);
58+
}
59+
}
60+
61+
}

0 commit comments

Comments
 (0)