Skip to content

Commit f880613

Browse files
committed
Check - disallow variable variables
1 parent 83f6717 commit f880613

17 files changed

+373
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
* Types in `switch` condition and `case` value must match. PHP compares them loosely by default and that can lead to unexpected results.
1919
* Statically declared methods are called statically.
2020
* Disallow `empty()` - it's a very loose comparison (see [manual](https://php.net/empty)), it's recommended to use more strict one.
21+
* Disallow variable variables (`$$foo`, `$this->$method()` etc.)
2122
* Always true `instanceof`, type-checking `is_*` functions and strict comparisons `===`/`!==`. These checks can be turned off by setting `checkAlwaysTrueInstanceof`/`checkAlwaysTrueCheckTypeFunctionCall`/`checkAlwaysTrueStrictComparison` to false.
2223
* Require parameter and return typehints for functions and methods (either native or phpDocs)
2324
* Correct case for referenced and called function names.

rules.neon

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,11 @@ rules:
3636
- PHPStan\Rules\StrictCalls\DynamicCallOnStaticMethodsRule
3737
- PHPStan\Rules\StrictCalls\StrictFunctionCallsRule
3838
- PHPStan\Rules\SwitchConditions\MatchingTypeInSwitchCaseConditionRule
39+
- PHPStan\Rules\VariableVariables\VariableMethodCallRule
40+
- PHPStan\Rules\VariableVariables\VariableStaticMethodCallRule
41+
- PHPStan\Rules\VariableVariables\VariableStaticPropertyFetchRule
42+
- PHPStan\Rules\VariableVariables\VariablePropertyFetchRule
43+
- PHPStan\Rules\VariableVariables\VariableVariablesRule
3944

4045
services:
4146
-
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Rules\VariableVariables;
4+
5+
use PhpParser\Node;
6+
use PHPStan\Analyser\Scope;
7+
use PHPStan\Rules\Rule;
8+
9+
class VariableMethodCallRule implements Rule
10+
{
11+
12+
public function getNodeType(): string
13+
{
14+
return Node\Expr\MethodCall::class;
15+
}
16+
17+
/**
18+
* @param \PhpParser\Node\Expr\MethodCall $node
19+
* @param \PHPStan\Analyser\Scope $scope
20+
* @return string[]
21+
*/
22+
public function processNode(Node $node, Scope $scope): array
23+
{
24+
if ($node->name instanceof Node\Identifier) {
25+
return [];
26+
}
27+
28+
return [
29+
'Variable method calls are not allowed.',
30+
];
31+
}
32+
33+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Rules\VariableVariables;
4+
5+
use PhpParser\Node;
6+
use PHPStan\Analyser\Scope;
7+
use PHPStan\Rules\Rule;
8+
9+
class VariablePropertyFetchRule implements Rule
10+
{
11+
12+
public function getNodeType(): string
13+
{
14+
return Node\Expr\PropertyFetch::class;
15+
}
16+
17+
/**
18+
* @param \PhpParser\Node\Expr\PropertyFetch $node
19+
* @param \PHPStan\Analyser\Scope $scope
20+
* @return string[]
21+
*/
22+
public function processNode(Node $node, Scope $scope): array
23+
{
24+
if ($node->name instanceof Node\Identifier) {
25+
return [];
26+
}
27+
28+
return [
29+
'Variable properties are not allowed.',
30+
];
31+
}
32+
33+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Rules\VariableVariables;
4+
5+
use PhpParser\Node;
6+
use PHPStan\Analyser\Scope;
7+
use PHPStan\Rules\Rule;
8+
9+
class VariableStaticMethodCallRule implements Rule
10+
{
11+
12+
public function getNodeType(): string
13+
{
14+
return Node\Expr\StaticCall::class;
15+
}
16+
17+
/**
18+
* @param \PhpParser\Node\Expr\StaticCall $node
19+
* @param \PHPStan\Analyser\Scope $scope
20+
* @return string[]
21+
*/
22+
public function processNode(Node $node, Scope $scope): array
23+
{
24+
if ($node->name instanceof Node\Identifier) {
25+
return [];
26+
}
27+
28+
return [
29+
'Variable static method calls are not allowed.',
30+
];
31+
}
32+
33+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Rules\VariableVariables;
4+
5+
use PhpParser\Node;
6+
use PHPStan\Analyser\Scope;
7+
use PHPStan\Rules\Rule;
8+
9+
class VariableStaticPropertyFetchRule implements Rule
10+
{
11+
12+
public function getNodeType(): string
13+
{
14+
return Node\Expr\StaticPropertyFetch::class;
15+
}
16+
17+
/**
18+
* @param \PhpParser\Node\Expr\StaticPropertyFetch $node
19+
* @param \PHPStan\Analyser\Scope $scope
20+
* @return string[]
21+
*/
22+
public function processNode(Node $node, Scope $scope): array
23+
{
24+
if ($node->name instanceof Node\VarLikeIdentifier) {
25+
return [];
26+
}
27+
28+
return [
29+
'Variable static properties are not allowed.',
30+
];
31+
}
32+
33+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Rules\VariableVariables;
4+
5+
use PhpParser\Node;
6+
use PHPStan\Analyser\Scope;
7+
use PHPStan\Rules\Rule;
8+
9+
class VariableVariablesRule implements Rule
10+
{
11+
12+
public function getNodeType(): string
13+
{
14+
return Node\Expr\Variable::class;
15+
}
16+
17+
/**
18+
* @param \PhpParser\Node\Expr\Variable $node
19+
* @param \PHPStan\Analyser\Scope $scope
20+
* @return string[]
21+
*/
22+
public function processNode(Node $node, Scope $scope): array
23+
{
24+
if (is_string($node->name)) {
25+
return [];
26+
}
27+
28+
return [
29+
'Variable variables are not allowed.',
30+
];
31+
}
32+
33+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Rules\VariableVariables;
4+
5+
use PHPStan\Rules\Rule;
6+
use PHPStan\Testing\RuleTestCase;
7+
8+
class VariableMethodCallRuleTest extends RuleTestCase
9+
{
10+
11+
protected function getRule(): Rule
12+
{
13+
return new VariableMethodCallRule();
14+
}
15+
16+
public function testRule(): void
17+
{
18+
$this->analyse([__DIR__ . '/data/methods.php'], [
19+
[
20+
'Variable method calls are not allowed.',
21+
7,
22+
],
23+
]);
24+
}
25+
26+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Rules\VariableVariables;
4+
5+
use PHPStan\Rules\Rule;
6+
use PHPStan\Testing\RuleTestCase;
7+
8+
class VariablePropertyFetchRuleTest extends RuleTestCase
9+
{
10+
11+
protected function getRule(): Rule
12+
{
13+
return new VariablePropertyFetchRule();
14+
}
15+
16+
public function testRule(): void
17+
{
18+
$this->analyse([__DIR__ . '/data/properties.php'], [
19+
[
20+
'Variable properties are not allowed.',
21+
6,
22+
],
23+
[
24+
'Variable properties are not allowed.',
25+
9,
26+
],
27+
]);
28+
}
29+
30+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Rules\VariableVariables;
4+
5+
use PHPStan\Rules\Rule;
6+
use PHPStan\Testing\RuleTestCase;
7+
8+
class VariableStaticMethodCallRuleTest extends RuleTestCase
9+
{
10+
11+
protected function getRule(): Rule
12+
{
13+
return new VariableStaticMethodCallRule();
14+
}
15+
16+
public function testRule(): void
17+
{
18+
$this->analyse([__DIR__ . '/data/staticMethods.php'], [
19+
[
20+
'Variable static method calls are not allowed.',
21+
7,
22+
],
23+
]);
24+
}
25+
26+
}

0 commit comments

Comments
 (0)