Skip to content

Commit

Permalink
UninitializedPropertyRule - do not report implicit array creation as …
Browse files Browse the repository at this point in the history
…premature access
  • Loading branch information
ondrejmirtes committed Jan 8, 2022
1 parent f2b59e3 commit e9ae0f8
Show file tree
Hide file tree
Showing 11 changed files with 59 additions and 25 deletions.
4 changes: 2 additions & 2 deletions src/Analyser/NodeScopeResolver.php
Expand Up @@ -3115,14 +3115,14 @@ private function processAssignVar(
}

// 1. eval root expr
if ($enterExpressionAssign && $var instanceof Variable) {
if ($enterExpressionAssign) {
$scope = $scope->enterExpressionAssign($var);
}
$result = $this->processExprNode($var, $scope, $nodeCallback, $context->enterDeep());
$hasYield = $result->hasYield();
$throwPoints = $result->getThrowPoints();
$scope = $result->getScope();
if ($enterExpressionAssign && $var instanceof Variable) {
if ($enterExpressionAssign) {
$scope = $scope->exitExpressionAssign($var);
}

Expand Down
9 changes: 5 additions & 4 deletions src/Rules/Properties/AccessPropertiesInAssignRule.php
Expand Up @@ -4,10 +4,11 @@

use PhpParser\Node;
use PHPStan\Analyser\Scope;
use PHPStan\Node\PropertyAssignNode;
use PHPStan\Rules\Rule;

/**
* @implements Rule<Node\Expr\Assign>
* @implements Rule<PropertyAssignNode>
*/
class AccessPropertiesInAssignRule implements Rule
{
Expand All @@ -18,16 +19,16 @@ public function __construct(private AccessPropertiesRule $accessPropertiesRule)

public function getNodeType(): string
{
return Node\Expr\Assign::class;
return PropertyAssignNode::class;
}

public function processNode(Node $node, Scope $scope): array
{
if (!$node->var instanceof Node\Expr\PropertyFetch) {
if (!$node->getPropertyFetch() instanceof Node\Expr\PropertyFetch) {
return [];
}

return $this->accessPropertiesRule->processNode($node->var, $scope);
return $this->accessPropertiesRule->processNode($node->getPropertyFetch(), $scope);
}

}
9 changes: 5 additions & 4 deletions src/Rules/Properties/AccessStaticPropertiesInAssignRule.php
Expand Up @@ -4,10 +4,11 @@

use PhpParser\Node;
use PHPStan\Analyser\Scope;
use PHPStan\Node\PropertyAssignNode;
use PHPStan\Rules\Rule;

/**
* @implements Rule<Node\Expr\Assign>
* @implements Rule<PropertyAssignNode>
*/
class AccessStaticPropertiesInAssignRule implements Rule
{
Expand All @@ -18,16 +19,16 @@ public function __construct(private AccessStaticPropertiesRule $accessStaticProp

public function getNodeType(): string
{
return Node\Expr\Assign::class;
return PropertyAssignNode::class;
}

public function processNode(Node $node, Scope $scope): array
{
if (!$node->var instanceof Node\Expr\StaticPropertyFetch) {
if (!$node->getPropertyFetch() instanceof Node\Expr\StaticPropertyFetch) {
return [];
}

return $this->accessStaticPropertiesRule->processNode($node->var, $scope);
return $this->accessStaticPropertiesRule->processNode($node->getPropertyFetch(), $scope);
}

}
2 changes: 1 addition & 1 deletion src/Rules/RuleErrorBuilder.php
Expand Up @@ -21,7 +21,7 @@ class RuleErrorBuilder
private int $type;

/** @var mixed[] */
private array $properties = [];
private array $properties;

private function __construct(string $message)
{
Expand Down
10 changes: 10 additions & 0 deletions tests/PHPStan/Rules/DeadCode/UnusedPrivatePropertyRuleTest.php
Expand Up @@ -131,6 +131,16 @@ public function testRule(): void
191,
$tip,
],
[
'Property UnusedPrivateProperty\WriteToCollection::$collection1 is never read, only written.',
221,
$tip,
],
[
'Property UnusedPrivateProperty\WriteToCollection::$collection2 is never read, only written.',
224,
$tip,
],
]);
$this->analyse([__DIR__ . '/data/TestExtension.php'], [
[
Expand Down
Expand Up @@ -23,6 +23,10 @@ protected function getRule(): Rule
public function testRule(): void
{
$this->analyse([__DIR__ . '/data/access-properties-assign.php'], [
[
'Access to an undefined property TestAccessPropertiesAssign\AccessPropertyWithDimFetch::$foo.',
10,
],
[
'Access to an undefined property TestAccessPropertiesAssign\AccessPropertyWithDimFetch::$foo.',
15,
Expand Down
12 changes: 0 additions & 12 deletions tests/PHPStan/Rules/Properties/AccessPropertiesRuleTest.php
Expand Up @@ -157,10 +157,6 @@ public function testAccessProperties(): void
'Access to an undefined property class@anonymous/tests/PHPStan/Rules/Properties/data/access-properties.php:294::$barProperty.',
299,
],
[
'Access to an undefined property TestAccessProperties\AccessPropertyWithDimFetch::$foo.',
364,
],
[
'Access to an undefined property TestAccessProperties\AccessInIsset::$foo.',
386,
Expand Down Expand Up @@ -295,10 +291,6 @@ public function testAccessPropertiesWithoutUnionTypes(): void
'Access to an undefined property class@anonymous/tests/PHPStan/Rules/Properties/data/access-properties.php:294::$barProperty.',
299,
],
[
'Access to an undefined property TestAccessProperties\AccessPropertyWithDimFetch::$foo.',
364,
],
[
'Access to an undefined property TestAccessProperties\AccessInIsset::$foo.',
386,
Expand All @@ -322,10 +314,6 @@ public function testAccessPropertiesOnThisOnly(): void
'Access to private property $foo of parent class TestAccessProperties\FooAccessProperties.',
24,
],
[
'Access to an undefined property TestAccessProperties\AccessPropertyWithDimFetch::$foo.',
364,
],
[
'Access to an undefined property TestAccessProperties\AccessInIsset::$foo.',
386,
Expand Down
Expand Up @@ -24,6 +24,10 @@ protected function getRule(): Rule
public function testRule(): void
{
$this->analyse([__DIR__ . '/data/access-static-properties-assign.php'], [
[
'Access to an undefined static property TestAccessStaticPropertiesAssign\AccessStaticPropertyWithDimFetch::$foo.',
10,
],
[
'Access to an undefined static property TestAccessStaticPropertiesAssign\AccessStaticPropertyWithDimFetch::$foo.',
15,
Expand Down
Expand Up @@ -7,7 +7,7 @@ class AccessPropertyWithDimFetch

public function doFoo()
{
$this->foo['foo'] = 'test'; // already reported by a separate rule
$this->foo['foo'] = 'test';
}

public function doBar()
Expand Down
Expand Up @@ -7,7 +7,7 @@ class AccessStaticPropertyWithDimFetch

public function doFoo()
{
self::$foo['foo'] = 'test'; // already reported by a separate rule
self::$foo['foo'] = 'test';
}

public function doBar()
Expand Down
26 changes: 26 additions & 0 deletions tests/PHPStan/Rules/Properties/data/uninitialized-property.php
Expand Up @@ -122,3 +122,29 @@ class TestExtension
private int $uninited;

}

class ImplicitArrayCreation
{

/** @var mixed[] */
private array $properties;

private function __construct(string $message)
{
$this->properties['message'] = $message;
}

}

class ImplicitArrayCreation2
{

/** @var mixed[] */
private array $properties;

private function __construct(string $message)
{
$this->properties['foo']['message'] = $message;
}

}

0 comments on commit e9ae0f8

Please sign in to comment.