Skip to content

Commit

Permalink
Bleeding edge - private property accessed through static::
Browse files Browse the repository at this point in the history
  • Loading branch information
ondrejmirtes committed Aug 17, 2021
1 parent bad2607 commit d8e8953
Show file tree
Hide file tree
Showing 6 changed files with 150 additions and 0 deletions.
4 changes: 4 additions & 0 deletions conf/config.level2.neon
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ conditionalTags:
phpstan.rules.rule: %featureToggles.classConstants%
PHPStan\Rules\Methods\CallPrivateMethodThroughStaticRule:
phpstan.rules.rule: %featureToggles.privateStaticCall%
PHPStan\Rules\Properties\AccessPrivatePropertyThroughStaticRule:
phpstan.rules.rule: %featureToggles.privateStaticCall%

rules:
- PHPStan\Rules\Cast\EchoRule
Expand Down Expand Up @@ -60,6 +62,8 @@ services:
class: PHPStan\Rules\Methods\CallPrivateMethodThroughStaticRule
-
class: PHPStan\Rules\PhpDoc\IncompatibleClassConstantPhpDocTypeRule
-
class: PHPStan\Rules\Properties\AccessPrivatePropertyThroughStaticRule
-
class: PHPStan\Rules\Generics\InterfaceAncestorsRule
arguments:
Expand Down
63 changes: 63 additions & 0 deletions src/Rules/Properties/AccessPrivatePropertyThroughStaticRule.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Properties;

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

/**
* @implements Rule<Node\Expr\StaticPropertyFetch>
*/
class AccessPrivatePropertyThroughStaticRule implements Rule
{

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

public function processNode(Node $node, Scope $scope): array
{
if (!$node->name instanceof Node\VarLikeIdentifier) {
return [];
}
if (!$node->class instanceof Name) {
return [];
}

$propertyName = $node->name->name;
$className = $node->class;
if ($className->toLowerString() !== 'static') {
return [];
}

$classType = $scope->resolveTypeByName($className);
if (!$classType->hasProperty($propertyName)->yes()) {
return [];
}

$property = $classType->getProperty($propertyName, $scope);
if (!$property->isPrivate()) {
return [];
}
if (!$property->isStatic()) {
return [];
}

if ($scope->isInClass() && $scope->getClassReflection()->isFinal()) {
return [];
}

return [
RuleErrorBuilder::message(sprintf(
'Unsafe access to private property %s::$%s through static::.',
$property->getDeclaringClass()->getDisplayName(),
$propertyName
))->build(),
];
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Properties;

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

/** @extends RuleTestCase<AccessPrivatePropertyThroughStaticRule> */
class AccessPrivatePropertyThroughStaticRuleTest extends RuleTestCase
{

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

public function testRule(): void
{
$this->analyse([__DIR__ . '/data/access-private-property-static.php'], [
[
'Unsafe access to private property AccessPrivatePropertyThroughStatic\Foo::$foo through static::.',
13,
],
]);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,14 @@ public function testAccessStaticProperties(): void
209,
'Learn more at https://phpstan.org/user-guide/discovering-symbols',
],
[
'Static access to instance property AccessWithStatic::$bar.',
223,
],
[
'Access to an undefined static property static(AccessWithStatic)::$nonexistent.',
224,
],
]);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

namespace AccessPrivatePropertyThroughStatic;

class Foo
{

private static $foo;
private $bar;

public function doBar()
{
static::$foo;
static::$bar; // reported by different rule
static::$nonexistent; // reported by different rule
}

}

final class Bar
{

private static $foo;
private $bar;

public function doBar()
{
static::$foo;
static::$bar;
static::$nonexistent;
}

}
15 changes: 15 additions & 0 deletions tests/PHPStan/Rules/Properties/data/access-static-properties.php
Original file line number Diff line number Diff line change
Expand Up @@ -210,3 +210,18 @@ public function doBar(TraitWithStaticProperty $a): void
}

}

class AccessWithStatic
{

private static $foo;
private $bar;

public function doBar()
{
static::$foo; // reported by different rule
static::$bar;
static::$nonexistent;
}

}

0 comments on commit d8e8953

Please sign in to comment.