Skip to content

Commit

Permalink
Fix literal array with empty item outside of left-side assign
Browse files Browse the repository at this point in the history
  • Loading branch information
ondrejmirtes committed Oct 24, 2020
1 parent fb8d3ef commit a97477b
Show file tree
Hide file tree
Showing 8 changed files with 88 additions and 5 deletions.
1 change: 1 addition & 0 deletions conf/config.level0.neon
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ parametersSchema:

rules:
- PHPStan\Rules\Arrays\DuplicateKeysInLiteralArraysRule
- PHPStan\Rules\Arrays\EmptyArrayItemRule
- PHPStan\Rules\Arrays\OffsetAccessWithoutDimForReadingRule
- PHPStan\Rules\Classes\ClassConstantRule
- PHPStan\Rules\Classes\DuplicateDeclarationRule
Expand Down
4 changes: 2 additions & 2 deletions src/Analyser/NodeScopeResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -1755,10 +1755,10 @@ function (MutatingScope $scope) use ($expr, $nodeCallback, $context): Expression
$itemNodes = [];
$hasYield = false;
foreach ($expr->items as $arrayItem) {
$itemNodes[] = new LiteralArrayItem($scope, $arrayItem);
if ($arrayItem === null) {
throw new \PHPStan\ShouldNotHappenException();
continue;
}
$itemNodes[] = new LiteralArrayItem($scope, $arrayItem);
$result = $this->processExprNode($arrayItem, $scope, $nodeCallback, $context->enterDeep());
$hasYield = $hasYield || $result->hasYield();
$scope = $result->getScope();
Expand Down
6 changes: 3 additions & 3 deletions src/Node/LiteralArrayItem.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ class LiteralArrayItem

private Scope $scope;

private ArrayItem $arrayItem;
private ?ArrayItem $arrayItem;

public function __construct(Scope $scope, ArrayItem $arrayItem)
public function __construct(Scope $scope, ?ArrayItem $arrayItem)
{
$this->scope = $scope;
$this->arrayItem = $arrayItem;
Expand All @@ -23,7 +23,7 @@ public function getScope(): Scope
return $this->scope;
}

public function getArrayItem(): ArrayItem
public function getArrayItem(): ?ArrayItem
{
return $this->arrayItem;
}
Expand Down
3 changes: 3 additions & 0 deletions src/Rules/Arrays/DuplicateKeysInLiteralArraysRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ public function processNode(\PhpParser\Node $node, Scope $scope): array
$valueLines = [];
foreach ($node->getItemNodes() as $itemNode) {
$item = $itemNode->getArrayItem();
if ($item === null) {
continue;
}
if ($item->key === null) {
continue;
}
Expand Down
40 changes: 40 additions & 0 deletions src/Rules/Arrays/EmptyArrayItemRule.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Arrays;

use PhpParser\Node;
use PHPStan\Analyser\Scope;
use PHPStan\Node\LiteralArrayNode;
use PHPStan\Rules\Rule;
use PHPStan\Rules\RuleErrorBuilder;

/**
* @implements \PHPStan\Rules\Rule<\PHPStan\Node\LiteralArrayNode>
*/
class EmptyArrayItemRule implements Rule
{

public function getNodeType(): string
{
return LiteralArrayNode::class;
}

public function processNode(Node $node, Scope $scope): array
{
foreach ($node->getItemNodes() as $itemNode) {
$item = $itemNode->getArrayItem();
if ($item !== null) {
continue;
}

return [
RuleErrorBuilder::message('Literal array contains empty item.')
->nonIgnorable()
->build(),
];
}

return [];
}

}
3 changes: 3 additions & 0 deletions src/Rules/Arrays/UnpackIterableInArrayRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ public function processNode(Node $node, Scope $scope): array
$errors = [];
foreach ($node->getItemNodes() as $itemNode) {
$item = $itemNode->getArrayItem();
if ($item === null) {
continue;
}
if (!$item->unpack) {
continue;
}
Expand Down
29 changes: 29 additions & 0 deletions tests/PHPStan/Rules/Arrays/EmptyArrayItemRuleTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Arrays;

use PHPStan\Rules\Rule;
use PHPStan\Testing\RuleTestCase;

/**
* @extends RuleTestCase<EmptyArrayItemRule>
*/
class EmptyArrayItemRuleTest extends RuleTestCase
{

protected function getRule(): Rule
{
return new EmptyArrayItemRule();
}

public function testRule(): void
{
$this->analyse([__DIR__ . '/data/empty-array-item.php'], [
[
'Literal array contains empty item.',
5,
],
]);
}

}
7 changes: 7 additions & 0 deletions tests/PHPStan/Rules/Arrays/data/empty-array-item.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?php

namespace EmptyArrayItem;

doFoo([, 'foo']);

[, $a] = doFoo();

0 comments on commit a97477b

Please sign in to comment.